diff --git a/Documentation/DocBook/media/dvb/dvbstb.pdf b/Documentation/DocBook/media/dvb/dvbstb.pdf deleted file mode 100644 index 0fa75d90c3e..00000000000 Binary files a/Documentation/DocBook/media/dvb/dvbstb.pdf and /dev/null differ diff --git a/Documentation/DocBook/media/v4l/crop.pdf b/Documentation/DocBook/media/v4l/crop.pdf deleted file mode 100644 index c9fb81cd32f..00000000000 Binary files a/Documentation/DocBook/media/v4l/crop.pdf and /dev/null differ diff --git a/Documentation/DocBook/media/v4l/fieldseq_bt.pdf b/Documentation/DocBook/media/v4l/fieldseq_bt.pdf deleted file mode 100644 index 26598b23f80..00000000000 Binary files a/Documentation/DocBook/media/v4l/fieldseq_bt.pdf and /dev/null differ diff --git a/Documentation/DocBook/media/v4l/fieldseq_tb.pdf b/Documentation/DocBook/media/v4l/fieldseq_tb.pdf deleted file mode 100644 index 4965b22ddb3..00000000000 Binary files a/Documentation/DocBook/media/v4l/fieldseq_tb.pdf and /dev/null differ diff --git a/Documentation/DocBook/media/v4l/pipeline.pdf b/Documentation/DocBook/media/v4l/pipeline.pdf deleted file mode 100644 index ee3e37f04b6..00000000000 Binary files a/Documentation/DocBook/media/v4l/pipeline.pdf and /dev/null differ diff --git a/Documentation/DocBook/media/v4l/vbi_525.pdf b/Documentation/DocBook/media/v4l/vbi_525.pdf deleted file mode 100644 index 9e72c25b208..00000000000 Binary files a/Documentation/DocBook/media/v4l/vbi_525.pdf and /dev/null differ diff --git a/Documentation/DocBook/media/v4l/vbi_625.pdf b/Documentation/DocBook/media/v4l/vbi_625.pdf deleted file mode 100644 index 765235e33a4..00000000000 Binary files a/Documentation/DocBook/media/v4l/vbi_625.pdf and /dev/null differ diff --git a/Documentation/DocBook/media/v4l/vbi_hsync.pdf b/Documentation/DocBook/media/v4l/vbi_hsync.pdf deleted file mode 100644 index 200b668189b..00000000000 Binary files a/Documentation/DocBook/media/v4l/vbi_hsync.pdf and /dev/null differ diff --git a/Documentation/block/row-iosched.txt b/Documentation/block/row-iosched.txt new file mode 100644 index 00000000000..987bd883444 --- /dev/null +++ b/Documentation/block/row-iosched.txt @@ -0,0 +1,117 @@ +Introduction +============ + +The ROW scheduling algorithm will be used in mobile devices as default +block layer IO scheduling algorithm. ROW stands for "READ Over WRITE" +which is the main requests dispatch policy of this algorithm. + +The ROW IO scheduler was developed with the mobile devices needs in +mind. In mobile devices we favor user experience upon everything else, +thus we want to give READ IO requests as much priority as possible. +The main idea of the ROW scheduling policy is: +If there are READ requests in pipe - dispatch them but don't starve +the WRITE requests too much. + +Software description +==================== +The requests are kept in queues according to their priority. The +dispatching of requests is done in a Round Robin manner with a +different slice for each queue. The dispatch quantum for a specific +queue is defined according to the queues priority. READ queues are +given bigger dispatch quantum than the WRITE queues, within a dispatch +cycle. + +At the moment there are 6 types of queues the requests are +distributed to: +- High priority READ queue +- High priority Synchronous WRITE queue +- Regular priority READ queue +- Regular priority Synchronous WRITE queue +- Regular priority WRITE queue +- Low priority READ queue + +If in a certain dispatch cycle one of the queues was empty and didn't +use its quantum that queue will be marked as "un-served". If we're in a +middle of a dispatch cycle dispatching from queue Y and a request +arrives for queue X that was un-served in the previous cycle, if X's +priority is higher than Y's, queue X will be preempted in the favor of +queue Y. This won't mean that cycle is restarted. The "dispatched" +counter of queue X will remain unchanged. Once queue Y uses up it's quantum +(or there will be no more requests left on it) we'll switch back to queue X +and allow it to finish it's quantum. + +For READ requests queues we allow idling in within a dispatch quantum in +order to give the application a chance to insert more requests. Idling +means adding some extra time for serving a certain queue even if the +queue is empty. The idling is enabled if we identify the application is +inserting requests in a high frequency. + +For idling on READ queues we use timer mechanism. When the timer expires, +if there are requests in the scheduler we will signal the underlying driver +(for example the MMC driver) to fetch another request for dispatch. + +The ROW algorithm takes the scheduling policy one step further, making +it a bit more "user-needs oriented", by allowing the application to +hint on the urgency of its requests. For example: even among the READ +requests several requests may be more urgent for completion then others. +The former will go to the High priority READ queue, that is given the +bigger dispatch quantum than any other queue. + +ROW scheduler will support special services for block devices that +supports High Priority Requests. That is, the scheduler may inform the +device upon urgent requests using new callback make_urgent_request. +In addition it will support rescheduling of requests that were +interrupted. For example, if the device issues a long write request and +a sudden high priority read interrupt pops in, the scheduler will +inform the device about the urgent request, so the device can stop the +current write request and serve the high priority read request. In such +a case the device may also send back to the scheduler the reminder of +the interrupted write request, such that the scheduler may continue +sending high priority requests without the need to interrupt the +ongoing write again and again. The write remainder will be sent later on +according to the scheduler policy. + +Design +====== +Existing algorithms (cfq, deadline) sort the io requests according LBA. +When deciding on the next request to dispatch they choose the closest +request to the current disk head position (from handling last +dispatched request). This is done in order to reduce the disk head +movement to a minimum. +We feel that this functionality isn't really needed in mobile devices. +Usually applications that write/read large chunks of data insert the +requests in already sorted LBA order. Thus dealing with sort trees adds +unnecessary complexity. + +We're planing to try this enhancement in the future to check if the +performance is influenced by it. + +SMP/multi-core +============== +At the moment the code is acceded from 2 contexts: +- Application context (from block/elevator layer): adding the requests. +- Underlying driver context (for example the mmc driver thread): dispatching + the requests and notifying on completion. + +One lock is used to synchronize between the two. This lock is provided +by the underlying driver along with the dispatch queue. + +Config options +============== +1. hp_read_quantum: dispatch quantum for the high priority READ queue +2. rp_read_quantum: dispatch quantum for the regular priority READ queue +3. hp_swrite_quantum: dispatch quantum for the high priority Synchronous + WRITE queue +4. rp_swrite_quantum: dispatch quantum for the regular priority + Synchronous WRITE queue +5. rp_write_quantum: dispatch quantum for the regular priority WRITE + queue +6. lp_read_quantum: dispatch quantum for the low priority READ queue +7. lp_swrite_quantum: dispatch quantum for the low priority Synchronous + WRITE queue +8. read_idle: how long to idle on read queue in Msec (in case idling + is enabled on that queue). +9. read_idle_freq: frequency of inserting READ requests that will + trigger idling. This is the time in Msec between inserting two READ + requests + diff --git a/Documentation/devicetree/bindings/gpu/adreno.txt b/Documentation/devicetree/bindings/gpu/adreno.txt index 0433d98b51e..e2a4dcdd147 100644 --- a/Documentation/devicetree/bindings/gpu/adreno.txt +++ b/Documentation/devicetree/bindings/gpu/adreno.txt @@ -5,7 +5,12 @@ Qualcomm Adreno GPU Required properties: - label: A string used as a descriptive name for the device. - compatible: Must be "qcom,kgsl-3d0" and "qcom,kgsl-3d" -- reg: Specifies the base address and address size for this device. +- reg: Specifies the register base address and size. The second interval + specifies the shader memory base address and size. +- reg-names: Resource names used for the physical address of device registers + and shader memory. "kgsl_3d0_reg_memory" gives the physical address + and length of device registers while "kgsl_3d0_shader_memory" gives + physical address and length of device shader memory. - interrupts: Interrupt mapping for GPU IRQ. - interrupt-names: String property to describe the name of the interrupt. - qcom,id: An integer used as an identification number for the device. @@ -57,11 +62,26 @@ DCVS Core info Optional Properties: - qcom,initial-powerlevel: This value indicates which qcom,gpu-pwrlevel should be used at start time and when coming back out of resume +- qcom,step-pwrlevel: How many qcom,gpu-pwrlevel should be decremented at once - qcom,idle-timeout: This property represents the time in microseconds for idle timeout. -- qcom,nap-allowed: Boolean. <0> or <1> to disable/enable nap. - qcom,chipid: If it exists this property is used to replace the chip identification read from the GPU hardware. This is used to override faulty hardware readings. +- qcom,strtstp-sleepwake: Boolean. Enables use of GPU SLUMBER instead of SLEEP for power savings + +The following properties are optional as collecting data via coresight might +not be supported for every chipset. The documentation for coresight +properties can be found in: +Documentation/devicetree/bindings/coresight/coresight.txt + +- coresight-id Unique integer identifier for the bus. +- coresight-name Unique descriptive name of the bus. +- coresight-nr-inports Number of input ports on the bus. +- coresight-outports List of output port numbers on the bus. +- coresight-child-list List of phandles pointing to the children of this + component. +- coresight-child-ports List of input port numbers of the children. + Example of A330 GPU in MSM8974: @@ -69,8 +89,9 @@ Example of A330 GPU in MSM8974: qcom,kgsl-3d0@fdb00000 { label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; - reg = <0xfdb00000 0x20000>; - reg-names = "kgsl_3d0_reg_memory"; + reg = <0xfdb00000 0x10000 + 0xfdb20000 0x10000>; + reg-names = "kgsl_3d0_reg_memory", "kgsl_3d0_shader_memory"; interrupts = <0 33 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; @@ -81,7 +102,6 @@ Example of A330 GPU in MSM8974: qcom,initial-pwrlevel = <1>; qcom,idle-timeout = <83>; // - qcom,nap-allowed = <1>; qcom,clk-map = <0x00000016>; //KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE /* Bus Scale Settings */ diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index b7413cb46dc..87fb3e9ccd7 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -360,6 +360,8 @@ is not associated with a file: [stack:1001] = the stack of the thread with tid 1001 [vdso] = the "virtual dynamic shared object", the kernel system call handler + [anon:] = an anonymous mapping that has been + named by userspace or if empty, the mapping is anonymous. @@ -409,6 +411,7 @@ Swap: 0 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Locked: 374 kB +Name: name from userspace The first of these lines shows the same information as is displayed for the mapping in /proc/PID/maps. The remaining lines show the size of the mapping @@ -424,6 +427,9 @@ and a page is modified, the file page is replaced by a private anonymous copy. "Swap" shows how much would-be-anonymous memory is also used, but out on swap. +The "Name" field will only be present on a mapping that has been named by +userspace, and will show the name passed in by userspace. + This file is only present if the CONFIG_MMU kernel configuration option is enabled. diff --git a/Documentation/vm/00-INDEX b/Documentation/vm/00-INDEX index 5481c8ba341..71418760337 100644 --- a/Documentation/vm/00-INDEX +++ b/Documentation/vm/00-INDEX @@ -14,6 +14,8 @@ hwpoison.txt - explains what hwpoison is ksm.txt - how to use the Kernel Samepage Merging feature. +uksm.txt + - Introduction to Ultra KSM locking - info on how locking and synchronization is done in the Linux vm code. map_hugetlb.c diff --git a/Documentation/vm/uksm.txt b/Documentation/vm/uksm.txt new file mode 100644 index 00000000000..9b2cb51c2c4 --- /dev/null +++ b/Documentation/vm/uksm.txt @@ -0,0 +1,57 @@ +The Ultra Kernel Samepage Merging feature +---------------------------------------------- +/* + * Ultra KSM. Copyright (C) 2011-2012 Nai Xia + * + * This is an improvement upon KSM. Some basic data structures and routines + * are borrowed from ksm.c . + * + * Its new features: + * 1. Full system scan: + * It automatically scans all user processes' anonymous VMAs. Kernel-user + * interaction to submit a memory area to KSM is no longer needed. + * + * 2. Rich area detection: + * It automatically detects rich areas containing abundant duplicated + * pages based. Rich areas are given a full scan speed. Poor areas are + * sampled at a reasonable speed with very low CPU consumption. + * + * 3. Ultra Per-page scan speed improvement: + * A new hash algorithm is proposed. As a result, on a machine with + * Core(TM)2 Quad Q9300 CPU in 32-bit mode and 800MHZ DDR2 main memory, it + * can scan memory areas that does not contain duplicated pages at speed of + * 627MB/sec ~ 2445MB/sec and can merge duplicated areas at speed of + * 477MB/sec ~ 923MB/sec. + * + * 4. Thrashing area avoidance: + * Thrashing area(an VMA that has frequent Ksm page break-out) can be + * filtered out. My benchmark shows it's more efficient than KSM's per-page + * hash value based volatile page detection. + * + * + * 5. Misc changes upon KSM: + * * It has a fully x86-opitmized memcmp dedicated for 4-byte-aligned page + * comparison. It's much faster than default C version on x86. + * * rmap_item now has an struct *page member to loosely cache a + * address-->page mapping, which reduces too much time-costly + * follow_page(). + * * The VMA creation/exit procedures are hooked to let the Ultra KSM know. + * * try_to_merge_two_pages() now can revert a pte if it fails. No break_ + * ksm is needed for this case. + * + * 6. Full Zero Page consideration(contributed by Figo Zhang) + * Now uksmd consider full zero pages as special pages and merge them to an + * special unswappable uksm zero page. + */ + +ChangeLog: + +2012-05-05 The creation of this Doc +2012-05-08 UKSM 0.1.1.1 libc crash bug fix, api clean up, doc clean up. +2012-05-28 UKSM 0.1.1.2 bug fix release +2012-06-26 UKSM 0.1.2-beta1 first beta release for 0.1.2 +2012-07-2 UKSM 0.1.2-beta2 +2012-07-10 UKSM 0.1.2-beta3 +2012-07-26 UKSM 0.1.2 Fine grained speed control, more scan optimization. +2012-10-13 UKSM 0.1.2.1 Bug fixes. +2012-12-31 UKSM 0.1.2.2 Minor bug fixes diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt index 7c3a8801b7c..97ebeccf39c 100644 --- a/Documentation/x86/boot.txt +++ b/Documentation/x86/boot.txt @@ -623,9 +623,10 @@ Protocol: 2.08+ uncompressed data should be determined using the standard magic numbers. The currently supported compression formats are gzip (magic numbers 1F 8B or 1F 9E), bzip2 (magic number 42 5A), LZMA - (magic number 5D 00), and XZ (magic number FD 37). The uncompressed - payload is currently always ELF (magic number 7F 45 4C 46). - + (magic number 5D 00), XZ (magic number FD 37), and LZ4 (magic number + 02 21). The uncompressed payload is currently always ELF (magic + number 7F 45 4C 46). + Field name: payload_length Type: read Offset/size: 0x24c/4 diff --git a/Makefile b/Makefile index 75b36ae3c7d..e516a385532 100644 --- a/Makefile +++ b/Makefile @@ -245,8 +245,13 @@ CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \ HOSTCC = gcc HOSTCXX = g++ +ifdef CONFIG_CC_OPTIMIZE_ALOT +HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -Ofast -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -ftree-vectorize -fomit-frame-pointer +HOSTCXXFLAGS = -Ofast -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +else HOSTCFLAGS = -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer HOSTCXXFLAGS = -O2 +endif # Decide whether to build built-in, modular, or both. # Normally, just do built-in. @@ -351,12 +356,23 @@ CC = $(srctree)/scripts/gcc-wrapper.py $(REAL_CC) CHECKFLAGS := -D__linux__ -Dlinux -D__STDC__ -Dunix -D__unix__ \ -Wbitwise -Wno-return-void $(CF) -CFLAGS_MODULE = -AFLAGS_MODULE = -LDFLAGS_MODULE = -CFLAGS_KERNEL = -AFLAGS_KERNEL = +ifdef CONFIG_CC_OPTIMIZE_ALOT +MODFLAGS = -DMODULE -O2 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -fno-pic -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +else +MODFLAGS = -DMODULE -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -fno-pic -marm -mfpu=neon -ftree-vectorize -mvectorize-with-neon-quad +endif + +CFLAGS_MODULE = $(MODFLAGS) +AFLAGS_MODULE = $(MODFLAGS) +LDFLAGS_MODULE = -T $(srctree)/scripts/module-common.lds +ifdef CONFIG_CC_OPTIMIZE_ALOT +CFLAGS_KERNEL = -Ofast -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad -fgraphite-identity -ftree-loop-linear -floop-interchange -floop-strip-mine -floop-block +AFLAGS_KERNEL = -Ofast -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad +else +CFLAGS_KERNEL = -O2 -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -funswitch-loops -mvectorize-with-neon-quad +AFLAGS_KERNEL = CFLAGS_GCOV = -fprofile-arcs -ftest-coverage +endif # Use LINUXINCLUDE when you must reference the include/ directory. @@ -366,18 +382,33 @@ LINUXINCLUDE := -I$(srctree)/arch/$(hdr-arch)/include \ $(if $(KBUILD_SRC), -I$(srctree)/include) \ -include $(srctree)/include/linux/kconfig.h +ifdef CONFIG_CC_OPTIMIZE_ALOT +KBUILD_CPPFLAGS := -D__KERNEL__ -Ofast -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +else KBUILD_CPPFLAGS := -D__KERNEL__ +endif 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 + -Wno-format-security -Wno-unused-function -Wno-array-bounds -Wno-uninitialized \ + -fno-delete-null-pointer-checks -Wno-unused-variable -Wno-maybe-uninitialized -Wno-cpp -Wno-declaration-after-statement \ + -mcpu=cortex-a15 -mtune=cortex-a15 -mfpu=neon-vfpv4 \ + -fpredictive-commoning -fgcse-after-reload -ftree-vectorize \ + -mno-unaligned-access \ + -fipa-cp-clone -fsingle-precision-constant -pipe \ + -funswitch-loops -fmodulo-sched -fmodulo-sched-allow-regmoves \ + -fgraphite-identity -ftree-loop-linear -floop-interchange -floop-strip-mine -floop-block +ifdef CONFIG_CC_OPTIMIZE_ALOT +KBUILD_AFLAGS_KERNEL := -Ofast -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +KBUILD_CFLAGS_KERNEL := -Ofast -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad +else KBUILD_AFLAGS_KERNEL := KBUILD_CFLAGS_KERNEL := +endif KBUILD_AFLAGS := -D__ASSEMBLY__ KBUILD_AFLAGS_MODULE := -DMODULE -KBUILD_CFLAGS_MODULE := -DMODULE +KBUILD_CFLAGS_MODULE := -DMODULE -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -ffast-math -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -mfpu=neon-vfpv4 -ftree-vectorize -funswitch-loops -Wno-cpp KBUILD_LDFLAGS_MODULE := -T $(srctree)/scripts/module-common.lds # Read KERNELRELEASE from include/config/kernel.release (if it exists) @@ -564,9 +595,13 @@ all: vmlinux ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE KBUILD_CFLAGS += -Os -else +endif +ifdef CONFIG_CC_OPTIMIZE_DEFAULT KBUILD_CFLAGS += -O2 endif +ifdef CONFIG_CC_OPTIMIZE_ALOT +KBUILD_CFLAGS += -Ofast +endif include $(srctree)/arch/$(SRCARCH)/Makefile @@ -583,18 +618,18 @@ endif # Use make W=1 to enable this warning (see scripts/Makefile.build) KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable) -ifdef CONFIG_FRAME_POINTER -KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls -else +# ifdef CONFIG_FRAME_POINTER +# KBUILD_CFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls +# else # Some targets (ARM with Thumb2, for example), can't be built with frame # pointers. For those, we don't have FUNCTION_TRACER automatically # select FRAME_POINTER. However, FUNCTION_TRACER adds -pg, and this is # incompatible with -fomit-frame-pointer with current GCC, so we don't use # -fomit-frame-pointer with FUNCTION_TRACER. -ifndef CONFIG_FUNCTION_TRACER +# ifndef CONFIG_FUNCTION_TRACER KBUILD_CFLAGS += -fomit-frame-pointer -endif -endif +# endif +# endif ifdef CONFIG_DEBUG_INFO KBUILD_CFLAGS += -g diff --git a/android/configs/README b/android/configs/README new file mode 100644 index 00000000000..8798731f890 --- /dev/null +++ b/android/configs/README @@ -0,0 +1,15 @@ +The files in this directory are meant to be used as a base for an Android +kernel config. All devices should have the options in android-base.cfg enabled. +While not mandatory, the options in android-recommended.cfg enable advanced +Android features. + +Assuming you already have a minimalist defconfig for your device, a possible +way to enable these options would be: + + ARCH= scripts/kconfig/merge_config.sh /_defconfig android/configs/android-base.cfg android/configs/android-recommended.cfg + +This will generate a .config that can then be used to save a new defconfig or +compile a new kernel with Android features enabled. + +Because there is no tool to consistently generate these config fragments, +lets keep them alphabetically sorted instead of random. diff --git a/android/configs/android-base.cfg b/android/configs/android-base.cfg new file mode 100644 index 00000000000..6b67601b7f1 --- /dev/null +++ b/android/configs/android-base.cfg @@ -0,0 +1,140 @@ +# KEEP ALPHABETICALLY SORTED +# CONFIG_INET_LRO is not set +# CONFIG_MODULES is not set +# CONFIG_OABI_COMPAT is not set +CONFIG_ANDROID=y +CONFIG_ANDROID_BINDER_IPC=y +CONFIG_ANDROID_INTF_ALARM_DEV=y +CONFIG_ANDROID_LOGGER=y +CONFIG_ANDROID_LOW_MEMORY_KILLER=y +CONFIG_ASHMEM=y +CONFIG_BLK_DEV_DM=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_CGROUPS=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_DEBUG=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_SCHED=y +CONFIG_DM_CRYPT=y +CONFIG_EMBEDDED=y +CONFIG_EXPERIMENTAL=y +CONFIG_FB=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_INET6_AH=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_INET=y +CONFIG_INET_ESP=y +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_TARGET_REJECT_SKERR=y +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_NF_ARPFILTER=y +CONFIG_IP_NF_ARPTABLES=y +CONFIG_IP_NF_ARP_MANGLE=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_MATCH_AH=y +CONFIG_IP_NF_MATCH_ECN=y +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_TARGET_MASQUERADE=y +CONFIG_IP_NF_TARGET_NETMAP=y +CONFIG_IP_NF_TARGET_REDIRECT=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_REJECT_SKERR=y +CONFIG_NET=y +CONFIG_NETDEVICES=y +CONFIG_NETFILTER=y +CONFIG_NETFILTER_TPROXY=y +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=y +CONFIG_NETFILTER_XT_MATCH_HELPER=y +CONFIG_NETFILTER_XT_MATCH_IPRANGE=y +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_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +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_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=y +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y +CONFIG_NETFILTER_XT_TARGET_CONNMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +CONFIG_NETFILTER_XT_TARGET_NFLOG=y +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +CONFIG_NETFILTER_XT_TARGET_TPROXY=y +CONFIG_NETFILTER_XT_TARGET_TRACE=y +CONFIG_NET_CLS_ACT=y +CONFIG_NET_CLS_U32=y +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_KEY=y +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_HTB=y +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_FTP=y +CONFIG_NF_CONNTRACK_H323=y +CONFIG_NF_CONNTRACK_IPV4=y +CONFIG_NF_CONNTRACK_IPV6=y +CONFIG_NF_CONNTRACK_IRC=y +CONFIG_NF_CONNTRACK_NETBIOS_NS=y +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=y +CONFIG_NF_CONNTRACK_TFTP=y +CONFIG_NF_CT_NETLINK=y +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_NAT=y +CONFIG_NO_HZ=y +CONFIG_PACKET=y +CONFIG_PM_AUTOSLEEP=y +CONFIG_PM_WAKELOCKS=y +CONFIG_PPP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_MPPE=y +CONFIG_PREEMPT=y +CONFIG_RESOURCE_COUNTERS=y +CONFIG_RTC_CLASS=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_STAGING=y +CONFIG_SWITCH=y +CONFIG_SYNC=y +CONFIG_SYSVIPC=y +CONFIG_TUN=y +CONFIG_UNIX=y +CONFIG_USB_GADGET=y +CONFIG_USB_G_ANDROID=y +CONFIG_USB_OTG_WAKELOCK=y +CONFIG_XFRM_USER=y diff --git a/android/configs/android-recommended.cfg b/android/configs/android-recommended.cfg new file mode 100644 index 00000000000..9caa089c5d1 --- /dev/null +++ b/android/configs/android-recommended.cfg @@ -0,0 +1,118 @@ +# KEEP ALPHABETICALLY SORTED +# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_NF_CONNTRACK_SIP is not set +# CONFIG_PM_WAKELOCKS_GC is not set +# CONFIG_VT is not set +CONFIG_ANDROID_RAM_CONSOLE=y +CONFIG_ANDROID_TIMED_GPIO=y +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_COMPACTION=y +CONFIG_DM_UEVENT=y +CONFIG_DRAGONRISE_FF=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_FUSE_FS=y +CONFIG_GREENASIA_FF=y +CONFIG_HIDRAW=y +CONFIG_HID_A4TECH=y +CONFIG_HID_ACRUX=y +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +CONFIG_HID_ELECOM=y +CONFIG_HID_EMS_FF=y +CONFIG_HID_EZKEY=y +CONFIG_HID_GREENASIA=y +CONFIG_HID_GYRATION=y +CONFIG_HID_HOLTEK=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_KEYTOUCH=y +CONFIG_HID_KYE=y +CONFIG_HID_LCPOWER=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_LOGITECH_DJ=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_NTRIG=y +CONFIG_HID_ORTEK=y +CONFIG_HID_PANTHERLORD=y +CONFIG_HID_PETALYNX=y +CONFIG_HID_PICOLCD=y +CONFIG_HID_PRIMAX=y +CONFIG_HID_PRODIKEYS=y +CONFIG_HID_ROCCAT=y +CONFIG_HID_SAITEK=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SMARTJOYPLUS=y +CONFIG_HID_SONY=y +CONFIG_HID_SPEEDLINK=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_THRUSTMASTER=y +CONFIG_HID_TIVO=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_TWINHAN=y +CONFIG_HID_UCLOGIC=y +CONFIG_HID_WACOM=y +CONFIG_HID_WALTOP=y +CONFIG_HID_WIIMOTE=y +CONFIG_HID_ZEROPLUS=y +CONFIG_HID_ZYDACRON=y +CONFIG_INPUT_EVDEV=y +CONFIG_INPUT_GPIO=y +CONFIG_INPUT_JOYSTICK=y +CONFIG_INPUT_KEYCHORD=y +CONFIG_INPUT_KEYRESET=y +CONFIG_INPUT_MISC=y +CONFIG_INPUT_TABLET=y +CONFIG_INPUT_UINPUT=y +CONFIG_ION=y +CONFIG_JOYSTICK_XPAD=y +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_KALLSYMS_ALL=y +CONFIG_KSM=y +CONFIG_LOGIG940_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGITECH_FF=y +CONFIG_MD=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MSDOS_FS=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_PANTHERLORD_FF=y +CONFIG_PERF_EVENTS=y +CONFIG_PM_DEBUG=y +CONFIG_PM_RUNTIME=y +CONFIG_PM_WAKELOCKS_LIMIT=0 +CONFIG_POWER_SUPPLY=y +CONFIG_SCHEDSTATS=y +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_SND=y +CONFIG_SOUND=y +CONFIG_SUSPEND_TIME=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_TIMER_STATS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_UHID=y +CONFIG_UID_STAT=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_USBNET=y +CONFIG_VFAT_FS=y diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index c450e1db066..5b472ff28ad 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -12,17 +12,18 @@ config ARM select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI) select HAVE_OPROFILE if (HAVE_PERF_EVENTS) select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL - select HAVE_ARCH_KGDB + #select HAVE_ARCH_KGDB select HAVE_KPROBES if !XIP_KERNEL select HAVE_KRETPROBES if (HAVE_KPROBES) - select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) - select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) - select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) - select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) + #select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) + #select HAVE_FTRACE_MCOUNT_RECORD if (!XIP_KERNEL) + #select HAVE_DYNAMIC_FTRACE if (!XIP_KERNEL) + #select HAVE_FUNCTION_GRAPH_TRACER if (!THUMB2_KERNEL) select ARCH_BINFMT_ELF_RANDOMIZE_PIE select HAVE_GENERIC_DMA_COHERENT select HAVE_KERNEL_GZIP select HAVE_KERNEL_LZO + select HAVE_KERNEL_LZ4 select HAVE_KERNEL_LZMA select HAVE_KERNEL_XZ select HAVE_IRQ_WORK @@ -1456,6 +1457,7 @@ config KSAPI endmenu source "arch/arm/common/Kconfig" +source "arch/arm/hotplug/Kconfig" menu "Bus support" @@ -1582,6 +1584,7 @@ config ARM_CPU_TOPOLOGY config SCHED_MC bool "Multi-core scheduler support" depends on ARM_CPU_TOPOLOGY + default y help Multi-core scheduler support improves the CPU scheduler's decision making when dealing with multi-core CPU chips at a cost of slightly @@ -1590,6 +1593,7 @@ config SCHED_MC config SCHED_SMT bool "SMT scheduler support" depends on ARM_CPU_TOPOLOGY + default y help Improves the CPU scheduler's decision making when dealing with MultiThreading at a cost of slightly increased overhead in some @@ -2180,6 +2184,32 @@ config ATAGS_PROC Should the atags used to boot the kernel be exported in an "atags" file in procfs. Useful with kexec. +config KEXEC_HARDBOOT + bool "Support hard booting to a kexec kernel" + depends on KEXEC + help + Allows hard booting (i.e., with a full hardware reboot) to a kernel + previously loaded in memory by kexec. This works around the problem of + soft-booted kernel hangs due to improper device shutdown and/or + reinitialization. Support is comprised of two components: + + First, a "hardboot" flag is added to the kexec syscall to force a hard + reboot in relocate_new_kernel() (which requires machine-specific assembly + code). This also requires the kexec userspace tool to load the kexec'd + kernel in memory region left untouched by the bootloader (i.e., not + explicitly cleared and not overwritten by the boot kernel). Just prior + to reboot, the kexec kernel arguments are stashed in a machine-specific + memory page that must also be preserved. Note that this hardboot page + need not be reserved during regular kernel execution. + + Second, the zImage decompresor of the boot (bootloader-loaded) kernel is + modified to check the hardboot page for fresh kexec arguments, and if + present, attempts to jump to the kexec'd kernel preserved in memory. + + Note that hardboot support is only required in the boot kernel and any + kernel capable of performing a hardboot kexec. It is _not_ required by a + kexec'd kernel. + config CRASH_DUMP bool "Build kdump crash kernel (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug index 1c010a809da..85e5542ca8b 100644 --- a/arch/arm/Kconfig.debug +++ b/arch/arm/Kconfig.debug @@ -44,7 +44,7 @@ config ARM_UNWIND config OLD_MCOUNT bool depends on FUNCTION_TRACER && FRAME_POINTER - default y + default n config DEBUG_USER bool "Verbose user fault messages" diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 81b5dc9c829..9fd803369a1 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -17,7 +17,7 @@ endif OBJCOPYFLAGS :=-O binary -R .comment -S GZFLAGS :=-9 -#KBUILD_CFLAGS +=-pipe +KBUILD_CFLAGS +=-pipe # Explicitly specifiy 32-bit ARM ISA since toolchain default can be -mthumb: KBUILD_CFLAGS +=$(call cc-option,-marm,) @@ -33,10 +33,6 @@ ifeq ($(CONFIG_MMU),) MMUEXT := -nommu endif -ifeq ($(CONFIG_FRAME_POINTER),y) -KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog -endif - ifeq ($(CONFIG_CC_STACKPROTECTOR),y) KBUILD_CFLAGS +=-fstack-protector endif @@ -57,7 +53,7 @@ comma = , # Note that GCC does not numerically define an architecture version # macro, but instead defines a whole series of macros which makes # testing for a specific architecture or later rather impossible. -arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-march=armv7-a,-march=armv5t -Wa$(comma)-march=armv7-a) +arch-$(CONFIG_CPU_32v7) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-mcpu=cortex-a15,-march=armv7-a) arch-$(CONFIG_CPU_32v6) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6,-march=armv5t -Wa$(comma)-march=armv6) # Only override the compiler option if ARMv6. The ARMv6K extensions are # always available in ARMv7 @@ -69,6 +65,18 @@ arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3 +# Since 'cortex-a15' is a superset of the 'armv7-a' arch spec, we need to +# explicitly redefine the arch options to not include '-march=armv7-a' when +# generating code for Krait, which is compatible with the instruction set of the +# Cortex-A15, because GCC will warn us about ambiguous ISA restrictions caused +# by seemingly conflicting -march and -mcpu options. +# If $(CC) does not support the -mcpu=cortex-a15 option, fall back on passing +# -march=armv7-a to specify the ISA restriction, though this is suboptimal. To +# keep things simpler, we don't bother with a fallback option if the compiler +# doesn't even support -march=armv7-a, since in that situation we would have +# bigger problems. +arch-$(CONFIG_ARCH_MSM_KRAIT) :=-D__LINUX_ARM_ARCH__=7 $(call cc-option,-mcpu=cortex-a15,-march=armv7-a) + # This selects how we optimise for the processor. tune-$(CONFIG_CPU_ARM610) :=-mtune=arm610 tune-$(CONFIG_CPU_ARM710) :=-mtune=arm710 @@ -97,9 +105,9 @@ else CFLAGS_ABI :=$(call cc-option,-mapcs-32,-mabi=apcs-gnu) $(call cc-option,-mno-thumb-interwork,) endif -ifeq ($(CONFIG_ARM_UNWIND),y) -CFLAGS_ABI +=-funwind-tables -endif +# ifeq ($(CONFIG_ARM_UNWIND),y) +# CFLAGS_ABI +=-funwind-tables +# endif ifeq ($(CONFIG_THUMB2_KERNEL),y) AFLAGS_AUTOIT :=$(call as-option,-Wa$(comma)-mimplicit-it=always,-Wa$(comma)-mauto-it) @@ -252,6 +260,7 @@ core-$(CONFIG_VFP) += arch/arm/vfp/ core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ core-y += arch/arm/net/ core-y += $(machdirs) $(platdirs) +core-$(CONFIG_INTELLI_PLUG) += arch/arm/hotplug/ drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ core-y += arch/arm/perfmon/ diff --git a/arch/arm/boot/compressed/.gitignore b/arch/arm/boot/compressed/.gitignore index d0d441c429a..ae66f95e378 100644 --- a/arch/arm/boot/compressed/.gitignore +++ b/arch/arm/boot/compressed/.gitignore @@ -5,6 +5,7 @@ piggy.gzip piggy.lzo piggy.lzma piggy.xzkern +piggy.lz4 vmlinux vmlinux.lds diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile index bb267562e7e..e908d1a3888 100644 --- a/arch/arm/boot/compressed/Makefile +++ b/arch/arm/boot/compressed/Makefile @@ -5,27 +5,37 @@ # OBJS = +plus_sec := $(call as-instr,.arch_extension sec,+sec) # Ensure that MMCIF loader code appears early in the image # to minimise that number of bocks that have to be read in # order to load it. ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y) +ifeq ($(CONFIG_ARCH_SH7372),y) OBJS += mmcif-sh7372.o endif +endif -# Ensure that SDHI loader code appears early in the image -# to minimise that number of bocks that have to be read in -# order to load it. -ifeq ($(CONFIG_ZBOOT_ROM_SH_MOBILE_SDHI),y) -OBJS += sdhi-shmobile.o -OBJS += sdhi-sh7372.o +AFLAGS_head.o := -DTEXT_OFFSET=$(TEXT_OFFSET) +AFLAGS_head.o += -Wa,-march=armv7-a$(plus_sec) +HEAD = head.o + +AFLAGS_misc.o +=-Wa,-march=armv7-a$(plus_sec) +MISC = misc.o + +AFLAGS_decompress.o += -Wa,-march=armv7-a$(plus_sec) +ifeq ($(CONFIG_KERNEL_LZ4),y) +CFLAGS_decompress.o := -Os endif +DECOMPRESS = decompress.o -AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) -HEAD = head.o -OBJS += misc.o decompress.o FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c +#AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET) +#HEAD = head.o +#OBJS += misc.o decompress.o +#FONTC = $(srctree)/drivers/video/console/font_acorn_8x8.c + # string library code (-Os is enforced to keep it much smaller) OBJS += string.o CFLAGS_string.o := -Os @@ -93,6 +103,7 @@ suffix_$(CONFIG_KERNEL_GZIP) = gzip suffix_$(CONFIG_KERNEL_LZO) = lzo suffix_$(CONFIG_KERNEL_LZMA) = lzma suffix_$(CONFIG_KERNEL_XZ) = xzkern +suffix_$(CONFIG_KERNEL_LZ4) = lz4 # Borrowed libfdt files for the ATAG compatibility mode @@ -113,12 +124,10 @@ endif targets := vmlinux vmlinux.lds \ piggy.$(suffix_y) piggy.$(suffix_y).o \ - lib1funcs.o lib1funcs.S ashldi3.o ashldi3.S \ - font.o font.c head.o misc.o $(OBJS) + lib1funcs.o lib1funcs.S font.o font.c head.o misc.o decompress.o $(OBJS) # Make sure files are removed during clean -extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern \ - lib1funcs.S ashldi3.S $(libfdt) $(libfdt_hdrs) +extra-y += piggy.gzip piggy.lzo piggy.lzma piggy.xzkern lib1funcs.S $(libfdt) $(libfdt_hdrs) ifeq ($(CONFIG_FUNCTION_TRACER),y) ORIG_CFLAGS := $(KBUILD_CFLAGS) @@ -129,8 +138,8 @@ ccflags-y := -fpic -fno-builtin -I$(obj) asflags-y := -Wa,-march=all # Supply kernel BSS size to the decompressor via a linker symbol. -KBSS_SZ = $(shell $(CROSS_COMPILE)size $(obj)/../../../../vmlinux | \ - awk 'END{print $$3}') +SIZEBIN := $(if $(shell which $(CROSS_COMPILE)size),$(CROSS_COMPILE)size,size) +KBSS_SZ = $(shell $(SIZEBIN) $(obj)/../../../../vmlinux | awk 'END{print $$3}') LDFLAGS_vmlinux = --defsym _kernel_bss_size=$(KBSS_SZ) # Supply ZRELADDR to the decompressor via a linker symbol. ifneq ($(CONFIG_AUTO_ZRELADDR),y) @@ -139,6 +148,9 @@ endif ifeq ($(CONFIG_CPU_ENDIAN_BE8),y) LDFLAGS_vmlinux += --be8 endif +ifneq ($(PARAMS_PHYS),) +LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS) +endif # ? LDFLAGS_vmlinux += -p # Report unresolved symbol references @@ -149,17 +161,12 @@ LDFLAGS_vmlinux += -X LDFLAGS_vmlinux += -T # For __aeabi_uidivmod +AFLAGS_lib1funcs.o +=-Wa,-march=armv7-a$(plus_sec) lib1funcs = $(obj)/lib1funcs.o $(obj)/lib1funcs.S: $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.S $(call cmd,shipped) -# For __aeabi_llsl -ashldi3 = $(obj)/ashldi3.o - -$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S - $(call cmd,shipped) - # We need to prevent any GOTOFF relocs being used with references # to symbols in the .bss section since we cannot relocate them # independently from the rest at run time. This can be achieved by @@ -172,20 +179,19 @@ bad_syms=$$($(CROSS_COMPILE)nm $@ | sed -n 's/^.\{8\} [bc] \(.*\)/\1/p') && \ [ -z "$$bad_syms" ] || \ ( echo "following symbols must have non local/private scope:" >&2; \ echo "$$bad_syms" >&2; rm -f $@; false ) +# For __aeabi_llsl +AFLAGS_ashldi3.o +=-Wa,-march=armv7-a$(plus_sec) +ashldi3 = $(obj)/ashldi3.o -check_for_multiple_zreladdr = \ -if [ $(words $(ZRELADDR)) -gt 1 -a "$(CONFIG_AUTO_ZRELADDR)" = "" ]; then \ - echo 'multiple zreladdrs: $(ZRELADDR)'; \ - echo 'This needs CONFIG_AUTO_ZRELADDR to be set'; \ - false; \ -fi +$(obj)/ashldi3.S: $(srctree)/arch/$(SRCARCH)/lib/ashldi3.S FORCE + $(call cmd,shipped) -$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ - $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE - @$(check_for_multiple_zreladdr) +$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/$(MISC) $(obj)/$(DECOMPRESS) $(obj)/piggy.$(suffix_y).o \ + $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) $(ashldi3) FORCE $(call if_changed,ld) @$(check_for_bad_syms) +AFLAGS_piggy.$(suffix_y).o += -Wa,-march=armv7-a$(plus_sec) $(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE $(call if_changed,$(suffix_y)) diff --git a/arch/arm/boot/compressed/decompress.c b/arch/arm/boot/compressed/decompress.c index f41b38cafce..1d99e860ced 100644 --- a/arch/arm/boot/compressed/decompress.c +++ b/arch/arm/boot/compressed/decompress.c @@ -50,6 +50,10 @@ extern void error(char *); #include "../../../../lib/decompress_unxz.c" #endif +#ifdef CONFIG_KERNEL_LZ4 +#include "../../../../lib/decompress_unlz4.c" +#endif + int do_decompress(u8 *input, int len, u8 *output, void (*error)(char *x)) { return decompress(input, len, NULL, NULL, output, NULL, error); diff --git a/arch/arm/boot/compressed/head.S b/arch/arm/boot/compressed/head.S index 64a6d6f8d29..c7f1e6408a1 100644 --- a/arch/arm/boot/compressed/head.S +++ b/arch/arm/boot/compressed/head.S @@ -10,6 +10,11 @@ */ #include +#ifdef CONFIG_KEXEC_HARDBOOT + #include + #include +#endif + /* * Debugging stuff * @@ -135,6 +140,97 @@ start: 1: mov r7, r1 @ save architecture ID mov r8, r2 @ save atags pointer +#ifdef CONFIG_KEXEC_HARDBOOT + /* Check hardboot page for a kexec kernel. */ + ldr r3, =KEXEC_HB_PAGE_ADDR + ldr r0, [r3] + ldr r1, =KEXEC_HB_PAGE_MAGIC + teq r0, r1 + bne not_booting_other + + /* Clear hardboot page magic to avoid boot loop. */ + mov r0, #0 + str r0, [r3] + +/* Copy the kernel tagged list (atags): + * + * The kernel requires atags to be located in a direct-mapped region, + * usually below the kernel in the first 16 kB of RAM. If they're above + * (the start of) the kernel, they need to be copied to a suitable + * location, e.g., the machine-defined params_phys. + * + * The assumption is that the tags will only be "out of place" if the + * decompressor code is also, so copying is implemented only in the "won't + * overwrite" case (which should be fixed). Still need to make sure that + * the copied tags don't overwrite either the kernel or decompressor code + * (or rather, the remainder of it since everything up to here has already + * been executed). + * + * Vojtech Bocek : I've moved atags copying from guest + * kernel to the host and rewrote it from C to assembler in order to remove + * the need for guest kernel to be patched. I don't know assembler very well, + * so it doesn't look very good and I have no idea if I didn't accidentally + * break something, causing problems down the road. It's worked every time + * and I didn't notice any problems so far though. + * + * r4: zreladdr (kernel start) + * r8: kexec_boot_atags + * r2: boot_atags */ + ldr r8, [r3, #12] @ kexec_boot_atags (r2: boot_atags) + ldr r4, =zreladdr @ zreladdr + + /* No need to copy atags if they're already below kernel */ + cmp r8, r4 + blo no_atags_cpy + + /* r0: min(zreladdr, pc) */ + mov r0, pc + cmp r4, r0 + movlo r0, r4 + + /* Compute max space for atags, if max <= 0 don't copy. */ + subs r5, r0, r2 @ max = min(zreladdr, pc) - dest + bls no_atags_cpy + + /* Copy atags to params_phys. */ + /* r8 src, r2 dest, r5 max */ + + ldr r0, [r8] @ first tag size + cmp r0, #0 + moveq r4, #8 + beq catags_empty + mov r4, r8 + +catags_foreach: + lsl r0, r0, #2 @ Multiply by 4 + ldr r0, [r4, r0]! @ Load next tag size to r0 and address to r4 + cmp r0, #0 + bne catags_foreach + + rsb r4, r8, r4 @ r4 -= r8 (get only size) + add r4, r4, #8 @ add size of the last tag +catags_empty: + cmp r5, r4 @ if(max <= size) + bcc no_atags_cpy + + mov r5, #0 @ iterator +catags_cpy: + ldr r0, [r8, r5] + str r0, [r2, r5] + add r5, r5, #4 + cmp r5, r4 + blo catags_cpy + +no_atags_cpy: + /* Load boot arguments and jump to kexec kernel. */ + ldr r1, [r3, #8] @ kexec_mach_type + ldr pc, [r3, #4] @ kexec_start_address + + .ltorg + +not_booting_other: +#endif + #ifndef __ARM_ARCH_2__ /* * Booting from Angel - need to enter SVC mode and disable diff --git a/arch/arm/boot/compressed/piggy.lz4.S b/arch/arm/boot/compressed/piggy.lz4.S new file mode 100644 index 00000000000..3d9a575618a --- /dev/null +++ b/arch/arm/boot/compressed/piggy.lz4.S @@ -0,0 +1,6 @@ + .section .piggydata,#alloc + .globl input_data +input_data: + .incbin "arch/arm/boot/compressed/piggy.lz4" + .globl input_data_end +input_data_end: diff --git a/arch/arm/boot/dts/msm8974-gpu.dtsi b/arch/arm/boot/dts/msm8974-gpu.dtsi index 1ee1f4754be..48abdc5d28c 100644 --- a/arch/arm/boot/dts/msm8974-gpu.dtsi +++ b/arch/arm/boot/dts/msm8974-gpu.dtsi @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, 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 @@ -13,29 +13,33 @@ qcom,kgsl-3d0@fdb00000 { label = "kgsl-3d0"; compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d"; - reg = <0xfdb00000 0x20000>; - reg-names = "kgsl_3d0_reg_memory"; + reg = <0xfdb00000 0x10000 + 0xfdb20000 0x10000>; + reg-names = "kgsl_3d0_reg_memory" , "kgsl_3d0_shader_memory"; interrupts = <0 33 0>; interrupt-names = "kgsl_3d0_irq"; qcom,id = <0>; qcom,chipid = <0x03030000>; - qcom,initial-pwrlevel = <1>; + qcom,initial-pwrlevel = <2>; + qcom,step-pwrlevel = <2>; - qcom,idle-timeout = <83>; // - qcom,nap-allowed = <1>; + qcom,idle-timeout = <8>; // + qcom,strtstp-sleepwake; qcom,clk-map = <0x00000016>; //KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE /* Bus Scale Settings */ qcom,msm-bus,name = "grp3d"; - qcom,msm-bus,num-cases = <4>; + qcom,msm-bus,num-cases = <6>; qcom,msm-bus,active-only = <0>; qcom,msm-bus,num-paths = <2>; qcom,msm-bus,vectors-KBps = <26 512 0 0>, <89 604 0 0>, - <26 512 0 2000000>, <89 604 0 3000000>, - <26 512 0 4000000>, <89 604 0 5000000>, + <26 512 0 2200000>, <89 604 0 3000000>, + <26 512 0 4000000>, <89 604 0 3000000>, + <26 512 0 4000000>, <89 604 0 4500000>, + <26 512 0 6400000>, <89 604 0 4500000>, <26 512 0 6400000>, <89 604 0 7600000>; /* GDSC oxili regulators */ @@ -47,6 +51,14 @@ /* IOMMU Data */ iommu = <&kgsl_iommu>; + /* Trace bus */ + coresight-id = <67>; + coresight-name = "coresight-gfx"; + coresight-nr-inports = <0>; + coresight-outports = <0>; + coresight-child-list = <&funnel_mmss>; + coresight-child-ports = <7>; + qcom,gpu-pwrlevels { #address-cells = <1>; #size-cells = <0>; @@ -55,27 +67,41 @@ qcom,gpu-pwrlevel@0 { reg = <0>; - qcom,gpu-freq = <500000000>; - qcom,bus-freq = <3>; - qcom,io-fraction = <0>; + qcom,gpu-freq = <450000000>; + qcom,bus-freq = <5>; + qcom,io-fraction = <33>; }; qcom,gpu-pwrlevel@1 { reg = <1>; - qcom,gpu-freq = <333000000>; - qcom,bus-freq = <2>; - qcom,io-fraction = <33>; + qcom,gpu-freq = <320000000>; + qcom,bus-freq = <4>; + qcom,io-fraction = <66>; }; qcom,gpu-pwrlevel@2 { reg = <2>; + qcom,gpu-freq = <320000000>; + qcom,bus-freq = <3>; + qcom,io-fraction = <66>; + }; + + qcom,gpu-pwrlevel@3 { + reg = <3>; + qcom,gpu-freq = <200000000>; + qcom,bus-freq = <2>; + qcom,io-fraction = <100>; + }; + + qcom,gpu-pwrlevel@4 { + reg = <4>; qcom,gpu-freq = <200000000>; qcom,bus-freq = <1>; qcom,io-fraction = <100>; }; - qcom,gpu-pwrlevel@3 { - reg = <3>; + qcom,gpu-pwrlevel@5 { + reg = <5>; qcom,gpu-freq = <27000000>; qcom,bus-freq = <0>; qcom,io-fraction = <0>; diff --git a/arch/arm/configs/Glitch_flo_defconfig b/arch/arm/configs/Glitch_flo_defconfig new file mode 100644 index 00000000000..2769e262b2c --- /dev/null +++ b/arch/arm/configs/Glitch_flo_defconfig @@ -0,0 +1,4150 @@ +# +# Automatically generated file; DO NOT EDIT. +# Linux/arm 3.4.0 Kernel Configuration +# +CONFIG_ARM=y +CONFIG_ARM_HAS_SG_CHAIN=y +CONFIG_MIGHT_HAVE_PCI=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_ARM_TICKET_LOCKS=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 is not set +CONFIG_NEED_MACH_IO_H=y +CONFIG_NEED_MACH_MEMORY_H=y +CONFIG_PHYS_OFFSET=0x80200000 +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="-Glitch-N7-AOSP" +# 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 is not set +CONFIG_KERNEL_LZ4=y +CONFIG_DEFAULT_HOSTNAME="(none)" +# CONFIG_SWAP is not set +CONFIG_SYSVIPC=y +CONFIG_SYSVIPC_SYSCTL=y +# CONFIG_POSIX_MQUEUE is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_FHANDLE is not set +# CONFIG_TASKSTATS is not set +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y +CONFIG_AUDIT_WATCH=y +CONFIG_AUDIT_TREE=y +# 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 is not set + +# +# 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=y +CONFIG_RCU_BOOST_PRIO=1 +CONFIG_RCU_BOOST_DELAY=500 +CONFIG_IKCONFIG=y +# CONFIG_IKCONFIG_PROC is not set +CONFIG_LOG_BUF_SHIFT=17 +CONFIG_CGROUPS=y +# CONFIG_CGROUP_DEBUG is not set +CONFIG_CGROUP_FREEZER=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 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 is not set +# CONFIG_CHECKPOINT_RESTORE is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set +# CONFIG_NET_NS is not set +CONFIG_SCHED_AUTOGROUP=y +# CONFIG_SYSFS_DEPRECATED is not set +# CONFIG_RELAY is not set +CONFIG_BLK_DEV_INITRD=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_RD_GZIP=y +CONFIG_RD_BZIP2=y +CONFIG_RD_LZMA=y +# CONFIG_RD_XZ is not set +# CONFIG_RD_LZO is not set +CONFIG_RD_LZ4=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set +# CONFIG_CC_OPTIMIZE_DEFAULT is not set +CONFIG_CC_OPTIMIZE_ALOT=y +CONFIG_SYSCTL=y +CONFIG_ANON_INODES=y +CONFIG_PANIC_TIMEOUT=5 +CONFIG_EXPERT=y +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=y +CONFIG_HAVE_PERF_EVENTS=y +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_VM_EVENT_COUNTERS=y +CONFIG_PCI_QUIRKS=y +# CONFIG_SLUB_DEBUG is not set +CONFIG_COMPAT_BRK=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set +CONFIG_PROFILING=y +# CONFIG_OPROFILE is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_KPROBES is not set +# CONFIG_JUMP_LABEL is not set +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_ARCH_JUMP_LABEL=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=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MODVERSIONS=y +# CONFIG_MODULE_SRCVERSION_ALL is not set +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 + +# +# 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_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 +# +CONFIG_IOSCHED_NOOP=y +# CONFIG_IOSCHED_TEST is not set +CONFIG_IOSCHED_DEADLINE=y +CONFIG_IOSCHED_ROW=y +CONFIG_IOSCHED_CFQ=y +CONFIG_IOSCHED_FIOPS=y +CONFIG_IOSCHED_SIO=y +# CONFIG_DEFAULT_DEADLINE is not set +CONFIG_DEFAULT_ROW=y +# CONFIG_DEFAULT_CFQ is not set +# CONFIG_DEFAULT_NOOP is not set +# CONFIG_DEFAULT_SIO is not set +# CONFIG_DEFAULT_FIOPS is not set +CONFIG_DEFAULT_IOSCHED="row" +# 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_PNX4008 is not set +# CONFIG_ARCH_PXA is not set +CONFIG_ARCH_MSM=y +# 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 is not set + +# +# MSM SoC Type +# +# CONFIG_ARCH_MSM7X01A is not set +# CONFIG_ARCH_MSM7X25 is not set +# CONFIG_ARCH_MSM7X27 is not set +# CONFIG_ARCH_MSM7X30 is not set +# CONFIG_ARCH_QSD8X50 is not set +# CONFIG_ARCH_MSM8X60 is not set +CONFIG_ARCH_MSM8960=y +CONFIG_ARCH_MSM8930=y +CONFIG_ARCH_APQ8064=y +# CONFIG_ARCH_MSM8974 is not set +# CONFIG_ARCH_MPQ8092 is not set +# CONFIG_ARCH_MSM8226 is not set +# CONFIG_ARCH_FSM9XXX is not set +# CONFIG_ARCH_MSM9615 is not set +# CONFIG_ARCH_MSM8625 is not set +# CONFIG_ARCH_MSM9625 is not set +CONFIG_MSM_SOC_REV_NONE=y +# CONFIG_MSM_SOC_REV_A is not set +CONFIG_MSM_KRAIT_TBB_ABORT_HANDLER=y +CONFIG_ARCH_MSM_KRAIT=y +CONFIG_MSM_SMP=y +CONFIG_ARCH_MSM_KRAITMP=y +CONFIG_MSM_KRAIT_WFE_FIXUP=y +CONFIG_MSM_RPM=y +# CONFIG_MSM_RPM_SMD is not set +CONFIG_MSM_MPM=y +CONFIG_MSM_XO=y +CONFIG_MSM_REMOTE_SPINLOCK_SFPB=y + +# +# MSM Board Selection +# +# CONFIG_MACH_MSM8960_CDP is not set +# CONFIG_MACH_MSM8960_MTP is not set +# CONFIG_MACH_MSM8960_FLUID is not set +# CONFIG_MACH_MSM8960_LIQUID is not set +# CONFIG_MACH_MSM8930_CDP is not set +# CONFIG_MACH_MSM8930_MTP is not set +# CONFIG_MACH_MSM8930_FLUID is not set +# CONFIG_MACH_MSM8627_CDP is not set +# CONFIG_MACH_MSM8627_MTP is not set +# CONFIG_MACH_APQ8064_CDP is not set +# CONFIG_MACH_APQ8064_MTP is not set +# CONFIG_MACH_APQ8064_LIQUID is not set +# CONFIG_MACH_MPQ8064_CDP is not set +# CONFIG_MACH_MPQ8064_HRD is not set +# CONFIG_MACH_MPQ8064_DTV is not set +# CONFIG_MACH_MSM_DUMMY is not set + +# +# LGE Board Selection +# +CONFIG_BOARD_HEADER_FILE="" +# CONFIG_MACH_APQ8064_MAKO is not set +# CONFIG_MACH_LGE_DUMMY is not set + +# +# LGE Specific Patches +# +CONFIG_UPDATE_LCDC_LUT=y +# CONFIG_LGE_CRASH_HANDLER is not set +CONFIG_MACH_ASUSTEK=y + +# +# ASUSTek Board Selection +# +CONFIG_MACH_APQ8064_FLO=y +CONFIG_MACH_APQ8064_DEB=y +# CONFIG_MACH_ASUSTEK_DUMMY is not set + +# +# ASUSTek Specific Feature +# +CONFIG_ASUSTEK_PCBID=y +CONFIG_ASUSTEK_KEYPAD=y +# CONFIG_MSM_STACKED_MEMORY is not set +CONFIG_KERNEL_MSM_CONTIG_MEM_REGION=y +CONFIG_MSM_AMSS_VERSION=6225 +# CONFIG_MSM_AMSS_VERSION_6210 is not set +# CONFIG_MSM_AMSS_VERSION_6220 is not set +CONFIG_MSM_AMSS_VERSION_6225=y +CONFIG_MSM7X00A_USE_GP_TIMER=y +# CONFIG_MSM7X00A_USE_DG_TIMER is not set +CONFIG_MSM7X00A_SLEEP_MODE_POWER_COLLAPSE_SUSPEND=y +# CONFIG_MSM7X00A_SLEEP_MODE_POWER_COLLAPSE is not set +# CONFIG_MSM7X00A_SLEEP_MODE_APPS_SLEEP is not set +# CONFIG_MSM7X00A_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT is not set +# CONFIG_MSM7X00A_SLEEP_WAIT_FOR_INTERRUPT is not set +CONFIG_MSM7X00A_SLEEP_MODE=0 +# CONFIG_MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE_SUSPEND is not set +CONFIG_MSM7X00A_IDLE_SLEEP_MODE_POWER_COLLAPSE=y +# CONFIG_MSM7X00A_IDLE_SLEEP_MODE_APPS_SLEEP is not set +# CONFIG_MSM7X00A_IDLE_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT is not set +# CONFIG_MSM7X00A_IDLE_SLEEP_WAIT_FOR_INTERRUPT is not set +CONFIG_MSM7X00A_IDLE_SLEEP_MODE=1 +CONFIG_MSM7X00A_IDLE_SLEEP_MIN_TIME=20000000 +CONFIG_MSM7X00A_IDLE_SPIN_TIME=80000 +CONFIG_MSM_IDLE_STATS=y +CONFIG_MSM_IDLE_STATS_FIRST_BUCKET=62500 +CONFIG_MSM_IDLE_STATS_BUCKET_SHIFT=2 +CONFIG_MSM_IDLE_STATS_BUCKET_COUNT=10 +CONFIG_MSM_SUSPEND_STATS_FIRST_BUCKET=1000000000 +CONFIG_CPU_HAS_L2_PMU=y +# CONFIG_HTC_HEADSET is not set +# CONFIG_HTC_PWRSINK is not set +# CONFIG_MSM_FIQ_SUPPORT is not set +# CONFIG_MSM_SERIAL_DEBUGGER is not set +# CONFIG_MSM_PROC_COMM is not set +CONFIG_MSM_SMD=y +# CONFIG_MSM_SMD_PKG3 is not set +CONFIG_MSM_SMD_PKG4=y +CONFIG_MSM_PCIE=y +CONFIG_MSM_SMD_DEBUG=y +CONFIG_MSM_BAM_DMUX=y +CONFIG_MSM_N_WAY_SMD=y +CONFIG_MSM_N_WAY_SMSM=y +CONFIG_MSM_RESET_MODEM=y +CONFIG_MSM_SMD_LOGGING=y +CONFIG_MSM_IPC_LOGGING=y +CONFIG_MSM_SMD_NMEA=y +CONFIG_MSM_HSIC_TTY=y +CONFIG_MSM_SMD_TTY=y +CONFIG_MSM_SMD_QMI=y +CONFIG_MSM_SMD_PKT=y +CONFIG_MSM_DSPS=y +# CONFIG_MSM_ONCRPCROUTER is not set +CONFIG_MSM_IPC_ROUTER=y +CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y +CONFIG_MSM_IPC_ROUTER_SECURITY=y +# CONFIG_MSM_DALRPC is not set +# CONFIG_MSM_CPU_FREQ_SET_MIN_MAX is not set +CONFIG_MSM_SLEEPER=y +CONFIG_CPU_VOLTAGE_TABLE=y +CONFIG_GPU_VOLTAGE_TABLE=y +CONFIG_MSM_AVS_HW=y +# CONFIG_MSM_HW3D is not set +CONFIG_AMSS_7X25_VERSION_2009=y +# CONFIG_AMSS_7X25_VERSION_2008 is not set +CONFIG_RTAC=y +# CONFIG_MSM_VREG_SWITCH_INVERTED is not set +CONFIG_MSM_DMA_TEST=y +# CONFIG_WIFI_CONTROL_FUNC is not set +CONFIG_MSM_SLEEP_TIME_OVERRIDE=y +# CONFIG_MSM_MEMORY_LOW_POWER_MODE is not set +CONFIG_MSM_PM_TIMEOUT_HALT=y +# CONFIG_MSM_PM_TIMEOUT_RESET_MODEM is not set +# CONFIG_MSM_PM_TIMEOUT_RESET_CHIP is not set +CONFIG_MSM_IDLE_WAIT_ON_MODEM=0 +CONFIG_MSM_RPM_REGULATOR=y +CONFIG_MSM_SUBSYSTEM_RESTART=y +CONFIG_MSM_SYSMON_COMM=y +CONFIG_MSM_PIL=y +# CONFIG_MSM_PIL_MODEM is not set +# CONFIG_MSM_PIL_QDSP6V3 is not set +CONFIG_MSM_PIL_QDSP6V4=y +# CONFIG_MSM_PIL_LPASS_QDSP6V5 is not set +# CONFIG_MSM_PIL_MSS_QDSP6V5 is not set +CONFIG_MSM_PIL_RIVA=y +CONFIG_MSM_PIL_TZAPPS=y +CONFIG_MSM_PIL_DSPS=y +CONFIG_MSM_PIL_VIDC=y +# CONFIG_MSM_PIL_VENUS is not set +CONFIG_MSM_PIL_GSS=y +# CONFIG_MSM_PIL_PRONTO is not set +CONFIG_MSM_SCM=y +CONFIG_MSM_MODEM_8960=y +CONFIG_MSM_LPASS_8960=y +CONFIG_MSM_WCNSS_SSR_8960=y +CONFIG_MSM_GSS_SSR_8064=y +CONFIG_MSM_BUSPM_DEV=y +CONFIG_MSM_TZ_LOG=y +CONFIG_MSM_RPM_LOG=y +CONFIG_MSM_RPM_STATS_LOG=y +CONFIG_MSM_RPM_RBCPR_STATS_LOG=y +CONFIG_MSM_DIRECT_SCLK_ACCESS=y +CONFIG_IOMMU_API=y +CONFIG_MSM_GPIOMUX=y +CONFIG_MSM_NATIVE_RESTART=y +CONFIG_MSM_PM8X60=y +CONFIG_MSM_EVENT_TIMER=y +CONFIG_MSM_BUS_SCALING=y +CONFIG_MSM_BUS_RPM_MULTI_TIER_ENABLED=y +CONFIG_MSM_WATCHDOG=y +# CONFIG_MSM_WATCHDOG_V2 is not set +# CONFIG_MSM_MEMORY_DUMP is not set +CONFIG_MSM_DLOAD_MODE=y +# CONFIG_MSM_JTAG is not set +# CONFIG_MSM_JTAG_MM is not set +# CONFIG_MSM_SLEEP_STATS_DEVICE is not set +CONFIG_MSM_RUN_QUEUE_STATS=y +# CONFIG_MSM_STANDALONE_POWER_COLLAPSE is not set +# CONFIG_MSM_GSBI9_UART is not set +CONFIG_MSM_SHOW_RESUME_IRQ=y +# CONFIG_MSM_FAKE_BATTERY is not set +CONFIG_MSM_QDSP6_APR=y +# CONFIG_MSM_QDSP6_APRV2 is not set +CONFIG_MSM_QDSP6_CODECS=y +# CONFIG_MSM_QDSP6V2_CODECS is not set +CONFIG_MSM_AUDIO_QDSP6=y +# CONFIG_MSM_AUDIO_QDSP6V2 is not set +CONFIG_MSM_ADSP_LOADER=y +CONFIG_MSM_ULTRASOUND=y +# CONFIG_MSM_SPM_V1 is not set +CONFIG_MSM_SPM_V2=y +CONFIG_MSM_L2_SPM=y +CONFIG_MSM_MULTIMEDIA_USE_ION=y +# CONFIG_MSM_OCMEM is not set +# CONFIG_MSM_RTB is not set +# CONFIG_MSM_EBI_ERP is not set +CONFIG_MSM_CACHE_ERP=y +# CONFIG_MSM_L1_ERR_PANIC is not set +CONFIG_MSM_L1_ERR_LOG=y +# CONFIG_MSM_L2_ERP_PRINT_ACCESS_ERRORS is not set +# CONFIG_MSM_L2_ERP_1BIT_PANIC is not set +# CONFIG_MSM_L2_ERP_2BIT_PANIC is not set +CONFIG_MSM_DCVS=y +CONFIG_MSM_HOTPLUG=y +# CONFIG_MSM_CPR is not set +CONFIG_HAVE_ARCH_HAS_CURRENT_TIMER=y +# CONFIG_MSM_CACHE_DUMP is not set +# CONFIG_MSM_HSIC_SYSMON is not set +CONFIG_MSM_CPU_PWRCTL=y +CONFIG_FORCE_FAST_CHARGE=y +CONFIG_LCD_KCAL_STANDALONE=y + +# +# System MMU +# + +# +# 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_STRICT_MEMORY_RWX=y +CONFIG_ARM_NR_BANKS=8 +# CONFIG_RESERVE_FIRST_PAGE is not set +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_KSAPI is not set +CONFIG_ARM_GIC=y +# CONFIG_FIQ_DEBUGGER is not set +CONFIG_INTELLI_PLUG=y + +# +# Bus support +# +CONFIG_PCI=y +CONFIG_PCI_SYSCALL=y +CONFIG_ARCH_SUPPORTS_MSI=y +CONFIG_PCI_MSI=y +# 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 +# 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 is not set +CONFIG_ARM_CPU_TOPOLOGY=y +CONFIG_SCHED_MC=y +# CONFIG_SCHED_SMT is not set +CONFIG_HAVE_ARM_SCU=y +# CONFIG_ARM_ARCH_TIMER 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=4 +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_HAS_HOLES_MEMORYMODEL=y +CONFIG_ARCH_SPARSEMEM_ENABLE=y +CONFIG_ARCH_SPARSEMEM_DEFAULT=y +CONFIG_ARCH_SELECT_MEMORY_MODEL=y +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_SPARSEMEM_MANUAL=y +CONFIG_SPARSEMEM=y +CONFIG_HAVE_MEMORY_PRESENT=y +CONFIG_SPARSEMEM_EXTREME=y +CONFIG_HAVE_MEMBLOCK=y +CONFIG_SPLIT_PTLOCK_CPUS=4 +# CONFIG_COMPACTION is not set +CONFIG_MIGRATION=y +# CONFIG_PHYS_ADDR_T_64BIT is not set +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_BOUNCE=y +CONFIG_VIRT_TO_BUS=y +CONFIG_KSM=y +CONFIG_UKSM=y +# CONFIG_KSM_LEGACY is not set +CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 +CONFIG_CLEANCACHE=y +# CONFIG_ARCH_MEMORY_PROBE is not set +# CONFIG_ARCH_MEMORY_REMOVE is not set +# CONFIG_ENABLE_DMM is not set +# CONFIG_FIX_MOVABLE_ZONE is not set +CONFIG_DONT_MAP_HOLE_AFTER_MEMBANK0=y +# CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG is not set +# CONFIG_ARCH_ENABLE_MEMORY_HOTREMOVE is not set +CONFIG_HOLES_IN_ZONE=y +CONFIG_FORCE_MAX_ZONEORDER=11 +CONFIG_ALIGNMENT_TRAP=y +# CONFIG_UACCESS_WITH_MEMCPY is not set +# CONFIG_SECCOMP is not set +CONFIG_CC_STACKPROTECTOR=y +# CONFIG_DEPRECATED_PARAM_STRUCT is not set +# CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART is not set +CONFIG_CP_ACCESS=y + +# +# Boot options +# +# CONFIG_USE_OF is not set +CONFIG_ZBOOT_ROM_TEXT=0 +CONFIG_ZBOOT_ROM_BSS=0 +CONFIG_CMDLINE="" +# CONFIG_XIP_KERNEL is not set +CONFIG_KEXEC=y +CONFIG_ATAGS_PROC=y +CONFIG_KEXEC_HARDBOOT=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_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_DEFAULT_GOV_INTERACTIVE is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX is not set +# CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIACTIVE is not set +CONFIG_CPU_FREQ_GOV_PERFORMANCE=y +# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set +CONFIG_CPU_FREQ_GOV_USERSPACE=y +CONFIG_CPU_FREQ_GOV_ONDEMAND=y +CONFIG_CPU_FREQ_GOV_INTERACTIVE=y +CONFIG_CPU_FREQ_GOV_SMARTMAX=y +# CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA is not set +# CONFIG_CPU_FREQ_GOV_SMARTMAX_30 is not set +# CONFIG_CPU_FREQ_GOV_SMARTMAX_ENRC2B is not set +# CONFIG_CPU_FREQ_GOV_SMARTMAX_PRIMOU is not set +CONFIG_CPU_FREQ_GOV_SMARTMAX_M7=y +# CONFIG_CPU_FREQ_GOV_SMARTMAX_EPS is not set +CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y +CONFIG_CPU_FREQ_GOV_INTELLIDEMAND=y +# CONFIG_CPUFREQ_ID_PERFLOCK is not set +CONFIG_CPU_FREQ_GOV_INTELLIACTIVE=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_CPU_FREQ_MSM=y + +# +# 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 is not set +CONFIG_HAVE_AOUT=y +# CONFIG_BINFMT_AOUT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Power management options +# +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_EARLYSUSPEND=y +# CONFIG_NO_USER_SPACE_SCREEN_ACCESS_CONTROL is not set +# CONFIG_CONSOLE_EARLYSUSPEND is not set +CONFIG_FB_EARLYSUSPEND=y +CONFIG_PM_SLEEP=y +CONFIG_PM_SLEEP_SMP=y +CONFIG_PM_RUNTIME=y +CONFIG_PM=y +# CONFIG_PM_DEBUG is not set +# 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 is not set +# 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 is not set +CONFIG_IP_MULTIPLE_TABLES=y +# CONFIG_IP_ROUTE_MULTIPATH is not set +CONFIG_IP_ROUTE_VERBOSE=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_IP_MROUTE is not set +# CONFIG_ARPD is not set +# CONFIG_SYN_COOKIES is not set +# CONFIG_INET_AH is not set +CONFIG_INET_ESP=y +# 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=y +# 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=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 is not set +# 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=y +# CONFIG_DEFAULT_RENO is not set +CONFIG_DEFAULT_TCP_CONG="westwood" +# CONFIG_TCP_MD5SIG is not set +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=y +CONFIG_INET6_ESP=y +CONFIG_INET6_IPCOMP=y +CONFIG_IPV6_MIP6=y +CONFIG_INET6_XFRM_TUNNEL=y +CONFIG_INET6_TUNNEL=y +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_SIT=y +# CONFIG_IPV6_SIT_6RD is not set +CONFIG_IPV6_NDISC_NODETYPE=y +# CONFIG_IPV6_TUNNEL is not set +CONFIG_IPV6_MULTIPLE_TABLES=y +CONFIG_IPV6_SUBTREES=y +# CONFIG_IPV6_MROUTE is not set +# CONFIG_NETLABEL is not set +CONFIG_ANDROID_PARANOID_NETWORK=y +CONFIG_NET_ACTIVITY_STATS=y +CONFIG_NETWORK_SECMARK=y +# CONFIG_NETWORK_PHY_TIMESTAMPING is not set +CONFIG_NETFILTER=y +# CONFIG_NETFILTER_DEBUG is not set +CONFIG_NETFILTER_ADVANCED=y + +# +# Core Netfilter Configuration +# +CONFIG_NETFILTER_NETLINK=y +# CONFIG_NETFILTER_NETLINK_ACCT is not set +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_PROCFS=y +CONFIG_NF_CONNTRACK_EVENTS=y +# CONFIG_NF_CONNTRACK_TIMEOUT is not set +# CONFIG_NF_CONNTRACK_TIMESTAMP is not set +CONFIG_NF_CT_PROTO_DCCP=y +CONFIG_NF_CT_PROTO_GRE=y +CONFIG_NF_CT_PROTO_SCTP=y +CONFIG_NF_CT_PROTO_UDPLITE=y +CONFIG_NF_CONNTRACK_AMANDA=y +CONFIG_NF_CONNTRACK_FTP=y +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 is not set +CONFIG_NF_CONNTRACK_PPTP=y +CONFIG_NF_CONNTRACK_SANE=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_TPROXY=y +CONFIG_NETFILTER_XTABLES=y + +# +# Xtables combined modules +# +CONFIG_NETFILTER_XT_MARK=y +CONFIG_NETFILTER_XT_CONNMARK=y + +# +# Xtables targets +# +# 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 is not set +# CONFIG_NETFILTER_XT_TARGET_DSCP is not set +# CONFIG_NETFILTER_XT_TARGET_HL is not set +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y +# CONFIG_NETFILTER_XT_TARGET_LED is not set +CONFIG_NETFILTER_XT_TARGET_LOG=y +CONFIG_NETFILTER_XT_TARGET_MARK=y +# CONFIG_NETFILTER_XT_TARGET_NFLOG is not set +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y +# CONFIG_NETFILTER_XT_TARGET_NOTRACK is not set +# CONFIG_NETFILTER_XT_TARGET_RATEEST is not set +# CONFIG_NETFILTER_XT_TARGET_TEE is not set +# CONFIG_NETFILTER_XT_TARGET_TPROXY is not set +# CONFIG_NETFILTER_XT_TARGET_TRACE is not set +CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y +# CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP is not set + +# +# Xtables matches +# +# CONFIG_NETFILTER_XT_MATCH_ADDRTYPE is not set +# CONFIG_NETFILTER_XT_MATCH_CLUSTER is not set +CONFIG_NETFILTER_XT_MATCH_COMMENT=y +# CONFIG_NETFILTER_XT_MATCH_CONNBYTES is not set +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y +CONFIG_NETFILTER_XT_MATCH_CONNMARK=y +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +# 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=y +# CONFIG_NETFILTER_XT_MATCH_ESP is not set +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_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 is not set +# CONFIG_NETFILTER_XT_MATCH_OSF is not set +# CONFIG_NETFILTER_XT_MATCH_OWNER is not set +CONFIG_NETFILTER_XT_MATCH_POLICY=y +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y +CONFIG_NETFILTER_XT_MATCH_QTAGUID=y +CONFIG_NETFILTER_XT_MATCH_QUOTA=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2=y +CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y +# 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=y +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=y +CONFIG_NETFILTER_XT_MATCH_STRING=y +# CONFIG_NETFILTER_XT_MATCH_TCPMSS is not set +CONFIG_NETFILTER_XT_MATCH_TIME=y +CONFIG_NETFILTER_XT_MATCH_U32=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_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 +# CONFIG_IP_NF_MATCH_RPFILTER is not set +CONFIG_IP_NF_MATCH_TTL=y +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +# CONFIG_IP_NF_TARGET_REJECT_SKERR is not set +# CONFIG_IP_NF_TARGET_ULOG is not set +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_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 is not set +CONFIG_IP_NF_MANGLE=y +# CONFIG_IP_NF_TARGET_CLUSTERIP is not set +# CONFIG_IP_NF_TARGET_ECN is not set +# CONFIG_IP_NF_TARGET_TTL is not set +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 + +# +# IPv6: Netfilter Configuration +# +CONFIG_NF_DEFRAG_IPV6=y +CONFIG_NF_CONNTRACK_IPV6=y +# CONFIG_IP6_NF_QUEUE is not set +CONFIG_IP6_NF_IPTABLES=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 is not set +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +# CONFIG_IP6_NF_SECURITY 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=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_DECNET is not set +# 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 is not set +CONFIG_NET_SCH_HTB=y +# CONFIG_NET_SCH_HFSC is not set +CONFIG_NET_SCH_PRIO=y +# 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_INGRESS 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=y +CONFIG_NET_CLS_U32=y +# CONFIG_CLS_U32_PERF is not set +CONFIG_CLS_U32_MARK=y +# CONFIG_NET_CLS_RSVP is not set +# CONFIG_NET_CLS_RSVP6 is not set +CONFIG_NET_CLS_FLOW=y +# CONFIG_NET_CLS_CGROUP is not set +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_STACK=32 +CONFIG_NET_EMATCH_CMP=y +CONFIG_NET_EMATCH_NBYTE=y +CONFIG_NET_EMATCH_U32=y +CONFIG_NET_EMATCH_META=y +CONFIG_NET_EMATCH_TEXT=y +CONFIG_NET_CLS_ACT=y +# CONFIG_NET_ACT_POLICE is not set +# CONFIG_NET_ACT_GACT is not set +# CONFIG_NET_ACT_MIRRED is not set +# CONFIG_NET_ACT_IPT is not set +# 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 is not set +# CONFIG_NET_ACT_CSUM 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 is not set +# CONFIG_OPENVSWITCH 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 + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +# CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set +CONFIG_IRDA=y + +# +# IrDA protocols +# +# CONFIG_IRLAN is not set +# CONFIG_IRNET is not set +# CONFIG_IRCOMM is not set +# CONFIG_IRDA_ULTRA is not set + +# +# 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=y + +# +# Dongle support +# +CONFIG_DONGLE=y +# CONFIG_ESI_DONGLE is not set +# CONFIG_ACTISYS_DONGLE is not set +# CONFIG_TEKRAM_DONGLE is not set +# CONFIG_TOIM3232_DONGLE is not set +# CONFIG_LITELINK_DONGLE is not set +CONFIG_MA600_DONGLE=y +# CONFIG_GIRBIL_DONGLE is not set +# CONFIG_MCP2120_DONGLE is not set +# CONFIG_OLD_BELKIN_DONGLE is not set +# CONFIG_ACT200L_DONGLE is not set +# CONFIG_KINGSUN_DONGLE is not set +# CONFIG_KSDAZZLE_DONGLE is not set +# CONFIG_KS959_DONGLE is not set + +# +# FIR device drivers +# +CONFIG_USB_IRDA=y +# CONFIG_SIGMATEL_FIR is not set +# CONFIG_TOSHIBA_FIR is not set +# CONFIG_VLSI_FIR is not set +# CONFIG_MCS_FIR 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_HIDP=y + +# +# Bluetooth device drivers +# +CONFIG_BT_HCISMD=y +# CONFIG_BT_HCIBTUSB is not set +# CONFIG_BT_HCIBTSDIO is not set +CONFIG_BT_HCIUART=y +CONFIG_BT_HCIUART_H4=y +# CONFIG_BT_HCIUART_BCSP is not set +CONFIG_BT_HCIUART_ATH3K=y +# CONFIG_BT_HCIUART_LL is not set +CONFIG_BT_HCIUART_IBS=y +# CONFIG_BT_HCIBCM203X is not set +# CONFIG_BT_HCIBPA10X is not set +# CONFIG_BT_MSM_SLEEP is not set +# CONFIG_BT_HCIBFUSB is not set +# CONFIG_BT_HCIVHCI is not set +# CONFIG_BT_MRVL is not set +CONFIG_MSM_BT_POWER=y +# 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_CFG80211_DEVELOPER_WARNINGS is not set +CONFIG_CFG80211_REG_DEBUG=y +CONFIG_CFG80211_DEFAULT_PS=y +# CONFIG_CFG80211_DEBUGFS is not set +CONFIG_CFG80211_INTERNAL_REGDB=y +CONFIG_CFG80211_WEXT=y +# CONFIG_WIRELESS_EXT_SYSFS is not set +CONFIG_LIB80211=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 is not set +CONFIG_MAC80211_LEDS=y +# CONFIG_MAC80211_DEBUGFS is not set +# CONFIG_MAC80211_DEBUG_MENU is not set +# CONFIG_WIMAX is not set +CONFIG_RFKILL=y +CONFIG_RFKILL_PM=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_BCM2079X=y + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_UEVENT_HELPER_PATH="" +# CONFIG_DEVTMPFS is not set +CONFIG_STANDALONE=y +CONFIG_PREVENT_FIRMWARE_BUILD=y +CONFIG_FW_LOADER=y +CONFIG_FIRMWARE_IN_KERNEL=y +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_GENLOCK is not set +CONFIG_SYNC=y +CONFIG_SW_SYNC=y +# CONFIG_SW_SYNC_USER is not set +CONFIG_CMA=y +# CONFIG_CMA_DEBUG is not set + +# +# 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 +CONFIG_CMA_AREAS=7 +# CONFIG_CONNECTOR is not set +# CONFIG_MTD is not set +# CONFIG_PARPORT is not set +CONFIG_BLK_DEV=y +# CONFIG_BLK_DEV_PCIESSD_MTIP32XX is not set +# CONFIG_BLK_CPQ_DA 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 + +# +# DRBD disabled because PROC_FS, INET or CONNECTOR not selected +# +# CONFIG_BLK_DEV_NBD is not set +# CONFIG_BLK_DEV_NVME is not set +# CONFIG_BLK_DEV_SX8 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_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_ANDROID_PMEM=y +# CONFIG_ATMEL_PWM is not set +# CONFIG_PHANTOM is not set +# CONFIG_INTEL_MID_PTI 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_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_PCH_PHUB is not set +# CONFIG_USB_SWITCH_FSA9480 is not set +# CONFIG_WL127X_RFKILL is not set +# CONFIG_TSIF is not set +# CONFIG_TSPP is not set +# CONFIG_HAPTIC_ISA1200 is not set +CONFIG_PMIC8XXX_VIBRATOR=y +# CONFIG_ANDROID_VIBRATOR is not set +# CONFIG_TOUCHSENSE_VIBRATOR is not set +# CONFIG_PMIC8XXX_NFC is not set +# CONFIG_PMIC8XXX_UPL is not set +CONFIG_QSEECOM=y +# CONFIG_QFP_FUSE is not set +CONFIG_USB_HSIC_SMSC_HUB=y +# CONFIG_BU52031NVX 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=y +# CONFIG_EEPROM_93XX46 is not set +# CONFIG_CB710_CORE is not set +# CONFIG_IWMC3200TOP 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 +CONFIG_SLIMPORT_ANX7808=y +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_TGT=y +# CONFIG_SCSI_NETLINK 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=y +CONFIG_CHR_DEV_SCH=y +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +# CONFIG_SCSI_WAIT_SCAN is not set + +# +# 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_SCSI_BNX2X_FCOE 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_AIC7XXX_OLD 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_DPT_I2O is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_ARCMSR 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_UFSHCD is not set +# CONFIG_SCSI_HPTIOP is not set +# CONFIG_LIBFC is not set +# CONFIG_LIBFCOE is not set +# CONFIG_FCOE 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_QLOGIC_1280 is not set +# CONFIG_SCSI_QLA_FC is not set +# CONFIG_SCSI_QLA_ISCSI is not set +# CONFIG_SCSI_LPFC is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_NSP32 is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_PMCRAID is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_SRP is not set +# CONFIG_SCSI_BFA_FC is not set +# CONFIG_SCSI_DH is not set +# CONFIG_SCSI_OSD_INITIATOR is not set +# CONFIG_ATA is not set +CONFIG_MD=y +# CONFIG_BLK_DEV_MD is not set +CONFIG_BLK_DEV_DM=y +# CONFIG_DM_DEBUG is not set +CONFIG_DM_CRYPT=y +# CONFIG_DM_SNAPSHOT is not set +# CONFIG_DM_THIN_PROVISIONING 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_FLAKEY is not set +# CONFIG_DM_VERITY is not set +# CONFIG_TARGET_CORE is not set +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support +# +# CONFIG_FIREWIRE is not set +# CONFIG_FIREWIRE_NOSY is not set +# CONFIG_I2O is not set +CONFIG_NETDEVICES=y +CONFIG_NET_CORE=y +# CONFIG_BONDING is not set +CONFIG_DUMMY=y +# CONFIG_EQUALIZER is not set +# CONFIG_NET_FC is not set +CONFIG_MII=y +# CONFIG_IFB is not set +# CONFIG_NET_TEAM is not set +# CONFIG_MACVLAN is not set +# CONFIG_NETCONSOLE is not set +# CONFIG_NETPOLL is not set +# CONFIG_NET_POLL_CONTROLLER is not set +CONFIG_TUN=y +# CONFIG_VETH is not set +# CONFIG_ARCNET is not set + +# +# CAIF transport drivers +# +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_ALTEON=y +# CONFIG_ACENIC is not set +CONFIG_NET_VENDOR_AMD=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_PCNET32 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_NET_VENDOR_BROADCOM=y +# CONFIG_B44 is not set +# CONFIG_BNX2 is not set +# CONFIG_CNIC is not set +# CONFIG_TIGON3 is not set +# CONFIG_BNX2X is not set +CONFIG_NET_VENDOR_BROCADE=y +# CONFIG_BNA is not set +# CONFIG_NET_CALXEDA_XGMAC is not set +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_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_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_IXGBEVF is not set +CONFIG_NET_VENDOR_I825XX=y +# CONFIG_IP1000 is not set +# CONFIG_JME is not set +CONFIG_NET_VENDOR_MARVELL=y +# 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_NET_VENDOR_MICREL=y +# 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_MSM_RMNET is not set +CONFIG_MSM_RMNET_BAM=y +CONFIG_MSM_RMNET_SMUX=y +# CONFIG_QFEC 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_PCH_GBE is not set +# 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_REALTEK=y +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_R8169 is not set +CONFIG_NET_VENDOR_RDC=y +# CONFIG_R6040 is not set +CONFIG_NET_VENDOR_SEEQ=y +# CONFIG_SEEQ8005 is not set +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=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=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_TLAN is not set +CONFIG_NET_VENDOR_VIA=y +# CONFIG_VIA_RHINE is not set +# CONFIG_VIA_VELOCITY is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PHYLIB=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 is not set +# CONFIG_MDIO_BITBANG is not set +# CONFIG_MICREL_KS8995MA 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=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y +CONFIG_SLIP=y +CONFIG_SLHC=y +CONFIG_SLIP_COMPRESSED=y +# CONFIG_SLIP_SMART is not set +CONFIG_SLIP_MODE_SLIP6=y +# CONFIG_TR is not set + +# +# USB Network Adapters +# +# 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_USBNET=y +CONFIG_USB_NET_AX8817X=y +CONFIG_USB_NET_CDCETHER=y +# CONFIG_USB_NET_CDC_EEM is not set +CONFIG_USB_NET_CDC_NCM=y +# 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=y +# 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=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 is not set +# CONFIG_USB_KC2190 is not set +CONFIG_USB_NET_ZAURUS=y +# 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=y +# CONFIG_USB_VL600 is not set +CONFIG_MSM_RMNET_USB=y +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=y +CONFIG_RTL8187_LEDS=y +# CONFIG_ADM8211 is not set +# CONFIG_MAC80211_HWSIM is not set +# CONFIG_MWL8K is not set +# CONFIG_LIBRA_SDIOIF is not set +# CONFIG_ATH6K_LEGACY_EXT is not set +CONFIG_WCNSS_CORE=y +CONFIG_ATH_COMMON=y +# CONFIG_ATH_DEBUG is not set +# CONFIG_ATH5K is not set +# CONFIG_ATH5K_PCI is not set +CONFIG_ATH9K_HW=y +CONFIG_ATH9K_COMMON=y +CONFIG_ATH9K_BTCOEX_SUPPORT=y +# CONFIG_ATH9K is not set +CONFIG_ATH9K_HTC=y +# CONFIG_ATH9K_HTC_DEBUGFS is not set +# CONFIG_CARL9170 is not set +# CONFIG_ATH6KL is not set +# CONFIG_B43 is not set +# CONFIG_B43LEGACY is not set +# CONFIG_BCMDHD is not set +# CONFIG_BRCMFMAC is not set +# CONFIG_HOSTAP is not set +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set +# CONFIG_IWLWIFI is not set +# CONFIG_IWL4965 is not set +# CONFIG_IWL3945 is not set +# CONFIG_IWM 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=y +CONFIG_RT2800USB_RT33XX=y +CONFIG_RT2800USB_RT35XX=y +# CONFIG_RT2800USB_RT53XX is not set +# CONFIG_RT2800USB_UNKNOWN is not set +CONFIG_RT2800_LIB=y +CONFIG_RT2X00_LIB_USB=y +CONFIG_RT2X00_LIB=y +CONFIG_RT2X00_LIB_FIRMWARE=y +CONFIG_RT2X00_LIB_CRYPTO=y +CONFIG_RT2X00_LIB_LEDS=y +# CONFIG_RT2X00_DEBUG is not set +# CONFIG_RTL8192CE is not set +# CONFIG_RTL8192SE is not set +# CONFIG_RTL8192DE is not set +# CONFIG_RTL8192CU is not set +# CONFIG_WL1251 is not set +# CONFIG_WL12XX_MENU is not set +# CONFIG_ZD1211RW is not set +# CONFIG_MWIFIEX 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_FF_MEMLESS=y +# CONFIG_INPUT_POLLDEV is not set +# CONFIG_INPUT_SPARSEKMAP is not set + +# +# 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=y +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set +# CONFIG_INPUT_KEYRESET is not set +CONFIG_INPUT_LID=y + +# +# 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=y +# CONFIG_KEYBOARD_LM8323 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_PMIC8XXX 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_QCIKBD 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_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 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_QCITP is not set +# CONFIG_MOUSE_SYNAPTICS_USB is not set +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_AS5011 is not set +# CONFIG_JOYSTICK_JOYDUMP is not set +CONFIG_JOYSTICK_XPAD=y +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +# CONFIG_TOUCHDISC_VTD518_SHINETSU 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_ATMEL_MAXTOUCH 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_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_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_MAX11801 is not set +# CONFIG_TOUCHSCREEN_MCS5000 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_SYNAPTICS_RMI4_I2C 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 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_MSM_LEGACY is not set +# CONFIG_TOUCHSCREEN_W90X900 is not set +# CONFIG_TOUCHSCREEN_ST1232 is not set +# CONFIG_TOUCHSCREEN_TPS6507X is not set +# CONFIG_TOUCHSCREEN_CY8C_TS is not set +# CONFIG_TOUCHSCREEN_CYTTSP_I2C_QC is not set +# CONFIG_TOUCHSCREEN_FT5X06 is not set +# CONFIG_TOUCHSCREEN_LGE_COMMON is not set +# CONFIG_TOUCHSCREEN_LGE_SYNAPTICS is not set +CONFIG_TOUCHSCREEN_ELAN_TF_3K=y +CONFIG_WAKE_TIMEOUT=y +CONFIG_INPUT_MISC=y +# CONFIG_INPUT_AD714X is not set +# CONFIG_INPUT_BMA150 is not set +# CONFIG_INPUT_PM8XXX_VIBRATOR is not set +# CONFIG_INPUT_PMIC8XXX_PWRKEY is not set +# CONFIG_INPUT_MMA8450 is not set +CONFIG_INPUT_MPU3050=y +# CONFIG_INPUT_GP2A is not set +# CONFIG_INPUT_GPIO_TILT_POLLED is not set +# CONFIG_INPUT_ATI_REMOTE2 is not set +CONFIG_INPUT_KEYCHORD=y +# 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_GPIO is not set +# CONFIG_INPUT_ISA1200_FF_MEMLESS 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_CMA3000 is not set +# CONFIG_BOSCH_BMA150 is not set +CONFIG_STM_LIS3DH=y +# CONFIG_BMP18X is not set + +# +# Hardware I/O ports +# +CONFIG_SERIO=y +CONFIG_SERIO_SERPORT=y +# 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_GAMEPORT is not set + +# +# 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 is not set +CONFIG_UNIX98_PTYS=y +# CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set +# CONFIG_N_GSM is not set +CONFIG_N_SMUX=y +CONFIG_N_SMUX_LOOPBACK=y +CONFIG_SMUX_CTL=y +# CONFIG_TRACE_SINK is not set +CONFIG_DEVMEM=y +CONFIG_DEVKMEM=y +CONFIG_FRANDOM=y + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_MAX3100 is not set +# CONFIG_SERIAL_MAX3107 is not set +# CONFIG_SERIAL_MFD_HSU is not set +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_JSM is not set +# CONFIG_SERIAL_MSM is not set +CONFIG_SERIAL_MSM_HS=y +CONFIG_SERIAL_MSM_HSL=y +CONFIG_SERIAL_MSM_HSL_CONSOLE=y +# CONFIG_SERIAL_BCM_BT_LPM 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_MSM_SMD is not set +# CONFIG_SERIAL_XILINX_PS_UART is not set + +# +# Diag Support +# +CONFIG_DIAG_CHAR=y + +# +# DIAG traffic over USB +# +CONFIG_DIAG_OVER_USB=y + +# +# SDIO support for DIAG +# + +# +# HSIC/SMUX support for DIAG +# +CONFIG_DIAGFWD_BRIDGE_CODE=y +# CONFIG_TTY_PRINTK is not set +# 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_MSM=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_DCC_TTY is not set +# CONFIG_RAMOOPS is not set +CONFIG_MSM_ROTATOR=y +CONFIG_MSM_ADSPRPC=y +# CONFIG_MMC_GENERIC_CSDIO is not set +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 + +# +# 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_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_INTEL_MID is not set +# CONFIG_I2C_MSM is not set +CONFIG_I2C_QUP=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_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 is not set +# CONFIG_SPI_GPIO is not set +# CONFIG_SPI_OC_TINY is not set +# CONFIG_SPI_PXA2XX_PCI is not set +# CONFIG_SPI_TOPCLIFF_PCH is not set +# CONFIG_SPI_XILINX is not set +CONFIG_SPI_QUP=y +# 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_SLIMBUS=y +CONFIG_SLIMBUS_MSM_CTRL=y +# CONFIG_HSI is not set + +# +# PPS support +# +# CONFIG_PPS is not set + +# +# PPS generators support +# + +# +# PTP clock support +# + +# +# Enable Device Drivers -> PPS to see the PTP clock options. +# +CONFIG_ARCH_REQUIRE_GPIOLIB=y +CONFIG_GPIOLIB=y +CONFIG_DEBUG_GPIO=y +CONFIG_GPIO_SYSFS=y + +# +# Memory mapped GPIO drivers: +# +# CONFIG_GPIO_GENERIC_PLATFORM is not set +# CONFIG_GPIO_MSM_V1 is not set +CONFIG_GPIO_MSM_V2=y +# CONFIG_GPIO_MSM_V3 is not set +# CONFIG_GPIO_FSM9XXX is not set +# CONFIG_GPIO_VX855 is not set + +# +# I2C GPIO expanders: +# +# CONFIG_GPIO_MAX7300 is not set +# CONFIG_GPIO_MAX732X is not set +# CONFIG_GPIO_PCF857X is not set +CONFIG_GPIO_SX150X=y +# CONFIG_GPIO_ADP5588 is not set + +# +# PCI GPIO expanders: +# +# CONFIG_GPIO_BT8XX is not set +# CONFIG_GPIO_ML_IOH is not set +# CONFIG_GPIO_RDC321X is not set + +# +# 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_GPIO_PM8XXX=y +CONFIG_GPIO_PM8XXX_MPP=y +# CONFIG_GPIO_PM8XXX_RPC is not set +# 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_CHARGER_SMB345=y +# 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_BATTERY_MSM is not set +# CONFIG_BATTERY_MSM8X60 is not set +# CONFIG_SMB137B_CHARGER is not set +# CONFIG_SMB349_CHARGER is not set +# CONFIG_BATTERY_BQ27520 is not set +# CONFIG_BATTERY_BQ27541 is not set +# CONFIG_PM8921_CHARGER is not set +# CONFIG_PM8XXX_CCADC is not set +# CONFIG_LTC4088_CHARGER is not set +# CONFIG_PM8921_BMS is not set +# CONFIG_CHARGER_SMB347 is not set +# CONFIG_WIRELESS_CHARGER is not set +# CONFIG_BATTERY_TEMP_CONTROL is not set +CONFIG_BATTERY_ASUS_BQ27541=y +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_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_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_G760A is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_GL520SM is not set +# CONFIG_SENSORS_GPIO_FAN 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 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_LTC4151 is not set +# CONFIG_SENSORS_LTC4215 is not set +# CONFIG_SENSORS_LTC4245 is not set +# CONFIG_SENSORS_LTC4261 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_MAX6639 is not set +# CONFIG_SENSORS_MAX6642 is not set +# CONFIG_SENSORS_MAX6650 is not set +# CONFIG_SENSORS_MCP3021 is not set +# CONFIG_SENSORS_NTC_THERMISTOR is not set +CONFIG_SENSORS_PM8XXX_ADC=y +CONFIG_SENSORS_EPM_ADC=y +# 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_SIS5595 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_THMC50 is not set +# CONFIG_SENSORS_TMP102 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_SENSORS_CAP1106=y +CONFIG_CAP_SENSOR_RMNET_CTL=y +CONFIG_THERMAL=y +CONFIG_THERMAL_HWMON=y +# CONFIG_THERMAL_MSM_POPMEM is not set +# CONFIG_THERMAL_TSENS is not set +CONFIG_THERMAL_TSENS8960=y +# CONFIG_THERMAL_TSENS8974 is not set +CONFIG_THERMAL_PM8XXX=y +CONFIG_THERMAL_MONITOR=y +# CONFIG_WATCHDOG 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_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_PMIC8058 is not set +# CONFIG_PMIC8901 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_TIMBERDALE is not set +# CONFIG_LPC_SCH is not set +# CONFIG_MFD_RDC321X is not set +# CONFIG_MFD_JANZ_CMODIO is not set +# CONFIG_MFD_VX855 is not set +# CONFIG_MFD_WL1273_CORE is not set +CONFIG_MFD_PM8XXX=y +CONFIG_MFD_PM8921_CORE=y +CONFIG_MFD_PM8821_CORE=y +# CONFIG_MFD_PM8018_CORE is not set +CONFIG_MFD_PM8038_CORE=y +CONFIG_MFD_PM8XXX_IRQ=y +CONFIG_MFD_PM8821_IRQ=y +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_AAT2870_CORE is not set +CONFIG_MFD_PM8XXX_DEBUG=y +CONFIG_MFD_PM8XXX_PWM=y +CONFIG_MFD_PM8XXX_MISC=y +CONFIG_MFD_PM8XXX_SPK=y +CONFIG_MFD_PM8XXX_BATT_ALARM=y +CONFIG_WCD9304_CODEC=y +CONFIG_WCD9310_CODEC=y +# CONFIG_WCD9320_CODEC 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_REGULATOR_PM8XXX=y +CONFIG_REGULATOR_MSM_GPIO=y +# CONFIG_REGULATOR_STUB 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 is not set +CONFIG_VIDEO_MEDIA=y + +# +# Multimedia drivers +# +CONFIG_RC_CORE=y +CONFIG_LIRC=y +CONFIG_USER_RC_INPUT=y +CONFIG_RC_MAP=y +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_IR_LIRC_CODEC=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_RC_LOOPBACK is not set +CONFIG_IR_GPIO_CIR=y + +# +# Qualcomm MSM Camera And Video +# +# CONFIG_MSM_CAMERA is not set +# CONFIG_IMX111 is not set +# CONFIG_IMX111_ACT is not set +# CONFIG_SEKONIX_LENS_ACT is not set +# CONFIG_IMX119 is not set +CONFIG_MSM_CAMERA_SENSOR=y +CONFIG_MSM_ACTUATOR=y +# CONFIG_MSM_EEPROM is not set +CONFIG_MSM_GEMINI=y +# CONFIG_MSM_CPP is not set +CONFIG_MSM_CCI=y +CONFIG_MSM_CSI20_HEADER=y +# CONFIG_MSM_CSI30_HEADER is not set +CONFIG_MSM_CSIPHY=y +CONFIG_MSM_CSID=y +CONFIG_MSM_ISPIF=y +# CONFIG_S5K3L1YX is not set +# CONFIG_MSM_V4L2_VIDEO_OVERLAY_DEVICE is not set +CONFIG_OV5693=y +CONFIG_MI1040=y +CONFIG_MSMB_CAMERA=y +# CONFIG_MSMB_CAMERA_DEBUG 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_VIDEOBUF2_CORE=y +CONFIG_VIDEOBUF2_MEMOPS=y +CONFIG_VIDEOBUF2_DMA_CONTIG=y +CONFIG_VIDEOBUF2_VMALLOC=y +CONFIG_VIDEOBUF2_DMA_SG=y +CONFIG_VIDEOBUF2_MSM_MEM=y +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=y + +# +# Audio decoders, processors and mixers +# + +# +# RDS decoders +# + +# +# Video decoders +# + +# +# Video and audio decoders +# + +# +# MPEG video encoders +# + +# +# Video encoders +# + +# +# Camera sensor devices +# + +# +# Flash devices +# + +# +# Video improvement chips +# + +# +# Miscelaneous helper chips +# +CONFIG_MSM_VCAP=y +CONFIG_V4L_USB_DRIVERS=y +CONFIG_USB_VIDEO_CLASS=y +CONFIG_USB_VIDEO_CLASS_INPUT_EVDEV=y +CONFIG_USB_GSPCA=y +# 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_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_VIDEO_PVRUSB2 is not set +# CONFIG_VIDEO_HDPVR is not set +# CONFIG_VIDEO_EM28XX is not set +# CONFIG_VIDEO_CX231XX is not set +# CONFIG_VIDEO_TM6000 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_V4L_PCI_DRIVERS=y +# CONFIG_VIDEO_BT848 is not set +# CONFIG_VIDEO_CX88 is not set +# CONFIG_VIDEO_HEXIUM_GEMINI is not set +# CONFIG_VIDEO_HEXIUM_ORION is not set +# CONFIG_VIDEO_IVTV is not set +# CONFIG_VIDEO_MXB is not set +# CONFIG_VIDEO_SAA7134 is not set +CONFIG_V4L_PLATFORM_DRIVERS=y +# CONFIG_VIDEO_CAFE_CCIC is not set +# CONFIG_SOC_CAMERA is not set +# CONFIG_V4L_MEM2MEM_DRIVERS is not set +CONFIG_MSM_WFD=y +CONFIG_RADIO_ADAPTERS=y +# CONFIG_RADIO_SI470X is not set +# CONFIG_USB_MR800 is not set +# CONFIG_USB_DSBR is not set +# CONFIG_RADIO_MAXIRADIO is not set +# CONFIG_I2C_SI4713 is not set +# CONFIG_RADIO_SI4713 is not set +# CONFIG_USB_KEENE 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 is not set +CONFIG_RADIO_IRIS=y +# CONFIG_RADIO_IRIS_TRANSPORT is not set + +# +# Graphics support +# +CONFIG_VGA_ARB=y +CONFIG_VGA_ARB_MAX_GPUS=16 +# CONFIG_DRM is not set +# CONFIG_STUB_POULSBO is not set +CONFIG_ION=y +CONFIG_ION_MSM=y +CONFIG_MSM_KGSL=y +# CONFIG_MSM_KGSL_CFF_DUMP is not set +# CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL is not set +# CONFIG_MSM_KGSL_PSTMRTMDMP_NO_IB_DUMP is not set +# CONFIG_MSM_KGSL_PSTMRTMDMP_RB_HEX is not set +CONFIG_MSM_KGSL_2D=y +CONFIG_KGSL_PER_PROCESS_PAGE_TABLE=y +CONFIG_MSM_KGSL_PAGE_TABLE_SIZE=0xFFF0000 +CONFIG_MSM_KGSL_PAGE_TABLE_COUNT=24 +CONFIG_MSM_KGSL_MMU_PAGE_FAULT=y +# CONFIG_MSM_KGSL_DISABLE_SHADOW_WRITES is not set +# CONFIG_MSM_KGSL_SIMPLE_GOV is not set +# 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=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_WMT_GE_ROPS 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 is not set +# CONFIG_FB_TILEBLITTING is not set + +# +# Frame buffer hardware drivers +# +# CONFIG_FB_CIRRUS is not set +# CONFIG_FB_PM2 is not set +# CONFIG_FB_CYBER2000 is not set +# CONFIG_FB_ASILIANT is not set +# CONFIG_FB_IMSTT 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_SMSCUFX is not set +# CONFIG_FB_UDL is not set +CONFIG_FB_VIRTUAL=y +# CONFIG_FB_METRONOME is not set +# CONFIG_FB_MB862XX is not set +# CONFIG_FB_BROADSHEET is not set +CONFIG_MSM_VIDC=y +CONFIG_MSM_VIDC_1080P=y +CONFIG_MSM_VIDC_VENC=y +CONFIG_MSM_VIDC_VDEC=y +# CONFIG_MSM_VIDC_CONTENT_PROTECTION is not set +CONFIG_FB_MSM=y +# CONFIG_FB_MSM_BACKLIGHT is not set +# CONFIG_FB_MSM_LOGO is not set +CONFIG_FB_MSM_LCDC_HW=y +CONFIG_FB_MSM_TRIPLE_BUFFER=y +CONFIG_FB_MSM_MDP_HW=y +# CONFIG_FB_MSM_MDP22 is not set +# CONFIG_FB_MSM_MDP30 is not set +# CONFIG_FB_MSM_MDP31 is not set +CONFIG_FB_MSM_MDP40=y +# CONFIG_FB_MSM_MDSS is not set +# CONFIG_FB_MSM_MDP_NONE is not set +# CONFIG_FB_MSM_EBI2 is not set +# CONFIG_FB_MSM_MDDI is not set +CONFIG_FB_MSM_MIPI_DSI=y +# CONFIG_FB_MSM_LCDC is not set +# CONFIG_FB_MSM_LVDS is not set +CONFIG_FB_MSM_OVERLAY=y +CONFIG_FB_MSM_DTV=y +# CONFIG_FB_MSM_EXTMDDI is not set +# CONFIG_FB_MSM_TVOUT is not set +# CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON is not set +# CONFIG_FB_MSM_MDDI_TOSHIBA_COMMON_VGA is not set +# CONFIG_FB_MSM_MDDI_ORISE is not set +# CONFIG_FB_MSM_MDDI_QUICKVX is not set +# CONFIG_FB_MSM_MDDI_AUTO_DETECT is not set +# CONFIG_FB_MSM_LCDC_AUTO_DETECT is not set +# CONFIG_FB_MSM_LCDC_PANEL is not set +# CONFIG_FB_MSM_MIPI_DSI_TOSHIBA is not set +# CONFIG_FB_MSM_MIPI_DSI_LGIT is not set +# CONFIG_FB_MSM_MIPI_DSI_RENESAS is not set +# CONFIG_FB_MSM_MIPI_DSI_SIMULATOR is not set +CONFIG_FB_MSM_MIPI_DSI_NOVATEK=y +CONFIG_FB_MSM_MIPI_DSI_LG=y +CONFIG_FB_MSM_MIPI_DSI_JDI=y +# CONFIG_FB_MSM_MIPI_DSI_ORISE is not set +# CONFIG_FB_MSM_LCDC_ST15_WXGA is not set +# CONFIG_FB_MSM_LCDC_ST15_PANEL is not set +# CONFIG_FB_MSM_LCDC_PRISM_WVGA is not set +# CONFIG_FB_MSM_LCDC_SAMSUNG_WSVGA is not set +# CONFIG_FB_MSM_LCDC_CHIMEI_WXGA is not set +# CONFIG_FB_MSM_LCDC_GORDON_VGA is not set +# CONFIG_FB_MSM_LCDC_TOSHIBA_WVGA_PT is not set +# CONFIG_FB_MSM_LCDC_TOSHIBA_FWVGA_PT is not set +# CONFIG_FB_MSM_LCDC_SHARP_WVGA_PT is not set +# CONFIG_FB_MSM_LCDC_AUO_WVGA is not set +# CONFIG_FB_MSM_LCDC_TRULY_HVGA_IPS3P2335 is not set +# CONFIG_FB_MSM_LCDC_TRULY_HVGA_IPS3P2335_PT_PANEL is not set +# CONFIG_FB_MSM_LCDC_SAMSUNG_OLED_PT is not set +# CONFIG_FB_MSM_LCDC_NT35582_WVGA is not set +# CONFIG_FB_MSM_LCDC_WXGA is not set +# CONFIG_FB_MSM_MIPI_LGIT_VIDEO_WXGA_PT is not set +# CONFIG_FB_MSM_LVDS_CHIMEI_WXGA is not set +# CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WVGA_PT is not set +# CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WSVGA_PT is not set +# CONFIG_FB_MSM_MIPI_TOSHIBA_VIDEO_WUXGA is not set +# CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_QHD_PT is not set +# CONFIG_FB_MSM_MIPI_NOVATEK_CMD_QHD_PT is not set +CONFIG_FB_MSM_MIPI_NOVATEK_1080_HD_PT=y +CONFIG_FB_MSM_MIPI_LG_1080_HD_PT=y +CONFIG_FB_MSM_MIPI_JDI_1080_HD_PT=y +# CONFIG_FB_MSM_MIPI_ORISE_VIDEO_720P_PT is not set +# CONFIG_FB_MSM_MIPI_ORISE_CMD_720P_PT is not set +# CONFIG_FB_MSM_MIPI_RENESAS_VIDEO_FWVGA_PT is not set +# CONFIG_FB_MSM_MIPI_RENESAS_CMD_FWVGA_PT is not set +# CONFIG_FB_MSM_MIPI_NT35510_VIDEO_WVGA_PT is not set +# CONFIG_FB_MSM_MIPI_NT35510_CMD_WVGA_PT is not set +# CONFIG_FB_MSM_MIPI_NT35516_VIDEO_QHD_PT is not set +# CONFIG_FB_MSM_MIPI_NT35516_CMD_QHD_PT is not set +# CONFIG_FB_MSM_MIPI_CHIMEI_WXGA is not set +# CONFIG_FB_MSM_MIPI_CHIMEI_WUXGA is not set +# CONFIG_FB_MSM_MIPI_SIMULATOR_VIDEO is not set +CONFIG_FB_MSM_NO_MDP_PIPE_CTRL=y +CONFIG_FB_MSM_OVERLAY0_WRITEBACK=y +CONFIG_FB_MSM_OVERLAY1_WRITEBACK=y +# CONFIG_FB_MSM_WRITEBACK_MSM_PANEL is not set +CONFIG_FB_MSM_MIPI_NOVATEK_VIDEO_MODE=y +CONFIG_FB_MSM_MIPI_LG_VIDEO_MODE=y +CONFIG_FB_MSM_MIPI_JDI_CMD_MODE=y +CONFIG_FB_MSM_EXT_INTERFACE_COMMON=y +CONFIG_FB_MSM_HDMI_COMMON=y +CONFIG_FB_MSM_HDMI_3D=y +# CONFIG_FB_MSM_HDMI_ADV7520_PANEL is not set +CONFIG_FB_MSM_HDMI_MSM_PANEL=y +# CONFIG_FB_MSM_HDMI_MSM_PANEL_DVI_SUPPORT is not set +# CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT is not set +# CONFIG_FB_MSM_HDMI_MHL_9244 is not set +# CONFIG_FB_MSM_HDMI_MHL_8334 is not set +# CONFIG_FB_MSM_TVOUT_NTSC_M is not set +# CONFIG_FB_MSM_TVOUT_NTSC_J is not set +# CONFIG_FB_MSM_TVOUT_PAL_BDGHIN is not set +# CONFIG_FB_MSM_TVOUT_PAL_M is not set +# CONFIG_FB_MSM_TVOUT_PAL_N is not set +CONFIG_FB_MSM_TVOUT_NONE=y +# CONFIG_FB_MSM_DEFAULT_DEPTH_RGB565 is not set +# CONFIG_FB_MSM_DEFAULT_DEPTH_ARGB8888 is not set +CONFIG_FB_MSM_DEFAULT_DEPTH_RGBA8888=y +# CONFIG_FB_MSM_EBI2_EPSON_S1D_QVGA_PANEL is not set +# CONFIG_FB_MSM_EBI2_PANEL_DETECT is not set +# CONFIG_EXYNOS_VIDEO is not set +CONFIG_BACKLIGHT_LCD_SUPPORT=y +CONFIG_LCD_CLASS_DEVICE=y +# 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=y +# CONFIG_BACKLIGHT_ADP8860 is not set +# CONFIG_BACKLIGHT_ADP8870 is not set +# CONFIG_BACKLIGHT_LP855X is not set +# CONFIG_BACKLIGHT_LM3530 is not set +# CONFIG_BACKLIGHT_LM3533 is not set + +# +# Console display driver support +# +CONFIG_DUMMY_CONSOLE=y +# CONFIG_FRAMEBUFFER_CONSOLE is not set +# CONFIG_LOGO 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_HWDEP=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 +# CONFIG_SND_PCM_OSS is not set +# CONFIG_SND_HRTIMER is not set +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_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_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 is not set +# CONFIG_SND_CS4281 is not set +# CONFIG_SND_CS46XX is not set +# CONFIG_SND_CS5535AUDIO 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_HDA_INTEL 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_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 +CONFIG_SND_ARM=y +CONFIG_SND_SPI=y +CONFIG_SND_USB=y +CONFIG_SND_USB_AUDIO=y +# CONFIG_SND_USB_UA101 is not set +# CONFIG_SND_USB_CAIAQ is not set +# CONFIG_SND_USB_6FIRE is not set +CONFIG_SND_SOC=y + +# +# MSM SoC Audio support +# +CONFIG_SND_SOC_MSM_HOSTLESS_PCM=y +CONFIG_SND_SOC_MSM_QDSP6_HDMI_AUDIO=y +CONFIG_SND_SOC_MSM_QDSP6_INTF=y +# CONFIG_SND_SOC_MSM_QDSP6V2_INTF is not set +CONFIG_SND_SOC_VOICE=y +CONFIG_SND_SOC_QDSP6=y +# CONFIG_SND_SOC_QDSP6V2 is not set +CONFIG_SND_SOC_MSM8960=y +# CONFIG_SND_SOC_DUAL_AMIC is not set +CONFIG_ASUSTEK_HEADSET=y +CONFIG_SND_SOC_I2C_AND_SPI=y +# CONFIG_SND_SOC_ALL_CODECS is not set +CONFIG_SND_SOC_WCD9304=y +CONFIG_SND_SOC_WCD9310=y +CONFIG_SND_SOC_CS8427=y +CONFIG_SND_SOC_MSM_STUB=y +# CONFIG_SND_SOC_TPA2028D is not set +CONFIG_SOUND_CONTROL_HAX_GPL=y +CONFIG_SOUND_CONTROL_HAX_3_GPL=y +# 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=y + +# +# USB Input Devices +# +CONFIG_USB_HID=y +# CONFIG_HID_PID is not set +CONFIG_USB_HIDDEV=y + +# +# Special HID drivers +# +CONFIG_HID_A4TECH=y +CONFIG_HID_ACRUX=y +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=y +CONFIG_HID_BELKIN=y +CONFIG_HID_CHERRY=y +CONFIG_HID_CHICONY=y +CONFIG_HID_PRODIKEYS=y +CONFIG_HID_CYPRESS=y +CONFIG_HID_DRAGONRISE=y +# CONFIG_DRAGONRISE_FF is not set +CONFIG_HID_EMS_FF=y +CONFIG_HID_ELECOM=y +CONFIG_HID_EZKEY=y +CONFIG_HID_HOLTEK=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_TWINHAN=y +CONFIG_HID_KENSINGTON=y +CONFIG_HID_LCPOWER=y +CONFIG_HID_LOGITECH=y +CONFIG_HID_LOGITECH_DJ=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=y +CONFIG_HID_MICROSOFT=y +CONFIG_HID_MONTEREY=y +CONFIG_HID_MULTITOUCH=y +CONFIG_HID_NTRIG=y +CONFIG_HID_ORTEK=y +CONFIG_HID_PANTHERLORD=y +# CONFIG_PANTHERLORD_FF is not set +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_LCD is not set +# CONFIG_HID_PICOLCD_LEDS is not set +CONFIG_HID_PRIMAX=y +CONFIG_HID_ROCCAT=y +CONFIG_HID_SAITEK=y +CONFIG_HID_SAMSUNG=y +CONFIG_HID_SONY=y +CONFIG_HID_SPEEDLINK=y +CONFIG_HID_SUNPLUS=y +CONFIG_HID_GREENASIA=y +# CONFIG_GREENASIA_FF is not set +CONFIG_HID_SMARTJOYPLUS=y +# CONFIG_SMARTJOYPLUS_FF is not set +CONFIG_HID_TIVO=y +CONFIG_HID_TOPSEED=y +CONFIG_HID_THRUSTMASTER=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 is not set +CONFIG_HID_ZYDACRON=y +CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y +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=y + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +CONFIG_USB_DEVICE_CLASS=y +# CONFIG_USB_DYNAMIC_MINORS is not set +CONFIG_USB_SUSPEND=y +# CONFIG_USB_OTG is not set +# CONFIG_USB_OTG_WHITELIST is not set +# CONFIG_USB_OTG_BLACKLIST_HUB is not set +# CONFIG_USB_DWC3 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_EHSET=y +CONFIG_USB_EHCI_ROOT_HUB_TT=y +CONFIG_USB_EHCI_TT_NEWSCHED=y +CONFIG_USB_EHCI_MSM=y +CONFIG_USB_EHCI_MSM_HSIC=y +CONFIG_USB_EHCI_MSM_HOST4=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 is not set +# CONFIG_USB_EHCI_HCD_PLATFORM 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_PEHCI_HCD is not set +# CONFIG_USB_MUSB_HDRC is not set +# CONFIG_USB_RENESAS_USBHS is not set + +# +# USB Device Class drivers +# +CONFIG_USB_ACM=y +CONFIG_USB_PRINTER=y +CONFIG_USB_WDM=y +# 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=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 is not set +# CONFIG_USB_UAS is not set +# CONFIG_USB_LIBUSUAL is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK 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_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=y +# 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=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_CSVT=y +# 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=y +# CONFIG_USB_ISIGHTFW is not set +# CONFIG_USB_YUREX is not set +CONFIG_USB_QCOM_DIAG_BRIDGE=y +# CONFIG_USB_QCOM_DIAG_BRIDGE_TEST is not set +CONFIG_USB_QCOM_MDM_BRIDGE=y +CONFIG_USB_QCOM_KS_BRIDGE=y +CONFIG_USB_GADGET=y +# CONFIG_USB_GADGET_DEBUG is not set +CONFIG_USB_GADGET_DEBUG_FILES=y +# CONFIG_USB_GADGET_DEBUG_FS is not set +CONFIG_USB_GADGET_VBUS_DRAW=500 +CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 + +# +# USB Peripheral Controller +# +# 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_AMD5536UDC is not set +# CONFIG_USB_CI13XXX_PCI is not set +# CONFIG_USB_NET2272 is not set +# CONFIG_USB_NET2280 is not set +# CONFIG_USB_GOKU is not set +# CONFIG_USB_LANGWELL is not set +# CONFIG_USB_EG20T is not set +CONFIG_USB_CI13XXX_MSM=y +# CONFIG_USB_CI13XXX_MSM_HSIC is not set +# CONFIG_USB_DWC3_MSM is not set +# CONFIG_USB_MSM_72K is not set +# CONFIG_USB_DUMMY_HCD is not set +CONFIG_USB_GADGET_DUALSPEED=y +# CONFIG_USB_GADGET_SUPERSPEED is not set +# 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_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_CSW_HACK=y +# CONFIG_USB_MSC_PROFILING is not set +CONFIG_MODEM_SUPPORT=y +CONFIG_RMNET_SMD_CTL_CHANNEL="" +CONFIG_RMNET_SMD_DATA_CHANNEL="" +# CONFIG_USB_ANDROID_CDC_ECM is not set + +# +# OTG and related infrastructure +# +CONFIG_USB_OTG_UTILS=y +# CONFIG_USB_OTG_WAKELOCK is not set +# CONFIG_USB_GPIO_VBUS is not set +# CONFIG_USB_ULPI is not set +# CONFIG_USB_MSM_OTG_72K is not set +# CONFIG_NOP_USB_XCEIV is not set +CONFIG_USB_MSM_OTG=y +# CONFIG_USB_MSM_ACA is not set +# CONFIG_UWB is not set +CONFIG_MMC=y +# CONFIG_MMC_DEBUG is not set +CONFIG_MMC_PERF_PROFILING=y +CONFIG_MMC_UNSAFE_RESUME=y +CONFIG_MMC_CLKGATE=y +# CONFIG_MMC_EMBEDDED_SDIO is not set +CONFIG_MMC_PARANOID_SD_INIT=y + +# +# MMC/SD/SDIO Card Drivers +# +CONFIG_MMC_BLOCK=y +# CONFIG_MMC_SECDISCARD is not set +CONFIG_MMC_BLOCK_MINORS=32 +# CONFIG_MMC_BLOCK_BOUNCE is not set +# CONFIG_MMC_BLOCK_DEFERRED_RESUME is not set +# 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_SDHCI_PXAV3 is not set +# CONFIG_MMC_SDHCI_PXAV2 is not set +CONFIG_MMC_MSM=y +# CONFIG_MMC_TIFM_SD is not set +CONFIG_MMC_MSM_SDC1_SUPPORT=y +CONFIG_MMC_MSM_SDC1_8_BIT_SUPPORT=y +# CONFIG_MMC_MSM_SDC2_SUPPORT is not set +# CONFIG_MMC_MSM_SDC3_SUPPORT is not set +# CONFIG_MMC_MSM_SDC3_POLLING is not set +# CONFIG_MMC_MSM_SDC4_SUPPORT is not set +# CONFIG_MMC_MSM_SDC5_SUPPORT is not set +CONFIG_MMC_MSM_SPS_SUPPORT=y +# 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_MEMSTICK is not set +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y + +# +# LED drivers +# +# CONFIG_LEDS_LM3530 is not set +# CONFIG_LEDS_PCA9532 is not set +# CONFIG_LEDS_GPIO is not set +# CONFIG_LEDS_MSM_PDM is not set +# CONFIG_LEDS_PMIC_MPP is not set +# CONFIG_LEDS_MSM_TRICOLOR is not set +# CONFIG_LEDS_LP3944 is not set +# CONFIG_LEDS_CPLD is not set +# CONFIG_LEDS_LP5521 is not set +# CONFIG_LEDS_LP5523 is not set +# CONFIG_LEDS_PCA955X is not set +CONFIG_LEDS_PM8XXX=y +# 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_MSM_PMIC 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 is not set +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +# CONFIG_LEDS_TRIGGER_BACKLIGHT is not set +# CONFIG_LEDS_TRIGGER_GPIO is not set +# CONFIG_LEDS_TRIGGER_DEFAULT_ON is not set +# CONFIG_LEDS_TRIGGER_SLEEP is not set + +# +# iptables trigger is under Netfilter config (LED target) +# +CONFIG_SWITCH=y +# CONFIG_SWITCH_GPIO is not set +# CONFIG_SWITCH_FSA8008 is not set +# CONFIG_ACCESSIBILITY is not set +# CONFIG_INFINIBAND 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_ALARM=y +CONFIG_RTC_INTF_ALARM_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 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_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_MSM is not set +# CONFIG_RTC_DRV_MSM7X00A is not set +CONFIG_RTC_DRV_PM8XXX=y +# CONFIG_DMADEVICES is not set +# CONFIG_AUXDISPLAY is not set +# CONFIG_UIO is not set + +# +# Virtio drivers +# +# CONFIG_VIRTIO_PCI is not set +# CONFIG_VIRTIO_BALLOON 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_ASUS_OLED is not set +# CONFIG_R8187SE is not set +# CONFIG_RTL8192U is not set +# CONFIG_RTLLIB is not set +# CONFIG_R8712U is not set +# CONFIG_RTS_PSTOR 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_USB_SERIAL_QUATECH_USB2 is not set +# CONFIG_VT6655 is not set +# CONFIG_VT6656 is not set +# CONFIG_VME_BUS is not set +# CONFIG_DX_SEP is not set +# CONFIG_IIO is not set +CONFIG_QCACHE=y +# CONFIG_FB_SM7XX is not set +# CONFIG_CRYSTALHD 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 is not set + +# +# 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_ANDROID_TIMED_OUTPUT=y +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 is not set +# CONFIG_PHONE is not set +# CONFIG_USB_WPAN_HCD is not set + +# +# Qualcomm Atheros Prima WLAN module +# +CONFIG_PRIMA_WLAN=y +# CONFIG_PRIMA_WLAN_BTAMP is not set +CONFIG_PRIMA_WLAN_LFR=y +CONFIG_PRIMA_WLAN_OKC=y +# CONFIG_PRIMA_WLAN_11AC_HIGH_TP is not set +# CONFIG_QCOM_VOWIFI_11R is not set +CONFIG_CPUPOWER=y + +# +# Qualcomm MSM specific device drivers +# +CONFIG_MSM_SSBI=y +CONFIG_SPS=y +# CONFIG_USB_BAM is not set +CONFIG_SPS_SUPPORT_BAMDMA=y +# CONFIG_SPS_SUPPORT_NDP_BAM is not set +CONFIG_CLKDEV_LOOKUP=y +CONFIG_HAVE_CLK_PREPARE=y + +# +# Hardware Spinlock drivers +# +CONFIG_IOMMU_SUPPORT=y +CONFIG_MSM_IOMMU=y +CONFIG_MSM_IOMMU_GPU_SYNC=y +CONFIG_IOMMU_PGTABLES_L2=y + +# +# Remoteproc drivers (EXPERIMENTAL) +# + +# +# Rpmsg drivers (EXPERIMENTAL) +# +# CONFIG_VIRT_DRIVERS is not set +# CONFIG_PM_DEVFREQ is not set +# CONFIG_MOBICORE_SUPPORT is not set +# CONFIG_CORESIGHT is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +# CONFIG_EXT2_FS_POSIX_ACL is not set +# CONFIG_EXT2_FS_SECURITY is not set +# CONFIG_EXT2_FS_XIP is not set +CONFIG_EXT3_FS=y +# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set +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_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_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 is not set +# CONFIG_QUOTACTL is not set +# CONFIG_AUTOFS4_FS is not set +CONFIG_FUSE_FS=y +# CONFIG_CUSE is not set + +# +# Caches +# +# CONFIG_FSCACHE is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +# CONFIG_MSDOS_FS is not set +CONFIG_VFAT_FS=y +CONFIG_FAT_DEFAULT_CODEPAGE=437 +CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" +CONFIG_NTFS_FS=y +# CONFIG_NTFS_DEBUG is not set +CONFIG_NTFS_RW=y +CONFIG_EXFAT_FS=y +CONFIG_EXFAT_DEFAULT_CODEPAGE=437 +CONFIG_EXFAT_DEFAULT_IOCHARSET="utf8" + +# +# 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 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_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_F2FS_FS=y +# CONFIG_F2FS_STAT_FS is not set +CONFIG_F2FS_FS_XATTR=y +CONFIG_F2FS_FS_POSIX_ACL=y +CONFIG_F2FS_FS_SECURITY=y +# CONFIG_F2FS_CHECK_FS is not set +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +# CONFIG_NFS_V3_ACL is not set +CONFIG_NFS_V4=y +# CONFIG_NFS_V4_1 is not set +# CONFIG_ROOT_NFS is not set +# CONFIG_NFS_USE_LEGACY_DNS is not set +CONFIG_NFS_USE_KERNEL_DNS=y +# CONFIG_NFSD is not set +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_NFS_COMMON=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=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_DEBUG2 is not set +# CONFIG_CIFS_DFS_UPCALL is not set +# CONFIG_CIFS_ACL 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=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_DYNAMIC_FSYNC=y +CONFIG_RESTRICT_ROOTFS_SLAVE=y + +# +# Kernel hacking +# +CONFIG_PRINTK_TIME=y +CONFIG_DEFAULT_MESSAGE_LOGLEVEL=4 +CONFIG_ENABLE_WARN_DEPRECATED=y +CONFIG_ENABLE_MUST_CHECK=y +CONFIG_FRAME_WARN=2048 +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_STRIP_ASM_SYMS 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_KERNEL=y +# CONFIG_DEBUG_SHIRQ is not set +# CONFIG_LOCKUP_DETECTOR 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=y +# CONFIG_DEBUG_OBJECTS is not set +# CONFIG_SLUB_STATS is not set +# CONFIG_DEBUG_KMEMLEAK is not set +# CONFIG_DEBUG_PREEMPT is not set +# 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 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 is not set +# CONFIG_DEBUG_LIST is not set +# 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 is not set +# CONFIG_RCU_TORTURE_TEST is not set +CONFIG_RCU_CPU_STALL_TIMEOUT=60 +# CONFIG_RCU_CPU_STALL_VERBOSE is not set +# CONFIG_RCU_CPU_STALL_INFO 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 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_FAULT_INJECTION is not set +# CONFIG_DEBUG_PAGEALLOC is not set +CONFIG_HAVE_C_RECORDMCOUNT=y +CONFIG_TRACING_SUPPORT=y +# CONFIG_FTRACE is not set +# CONFIG_DYNAMIC_DEBUG is not set +# CONFIG_DMA_API_DEBUG is not set +# CONFIG_ATOMIC64_SELFTEST is not set +# CONFIG_SAMPLES is not set +# CONFIG_TEST_KSTRTOX is not set +# CONFIG_STRICT_DEVMEM is not set +CONFIG_ARM_UNWIND=y +# CONFIG_DEBUG_USER is not set +# CONFIG_DEBUG_RODATA is not set +# CONFIG_DEBUG_LL is not set +# CONFIG_PID_IN_CONTEXTIDR 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=y +# CONFIG_SECURITYFS is not set +CONFIG_SECURITY_NETWORK=y +# CONFIG_SECURITY_NETWORK_XFRM is not set +# CONFIG_SECURITY_PATH is not set +CONFIG_LSM_MMAP_MIN_ADDR=4096 +CONFIG_SECURITY_SELINUX=y +# CONFIG_SECURITY_SELINUX_BOOTPARAM is not set +# CONFIG_SECURITY_SELINUX_DISABLE is not set +CONFIG_SECURITY_SELINUX_DEVELOP=y +CONFIG_SECURITY_SELINUX_AVC_STATS=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +# CONFIG_SECURITY_SELINUX_POLICYDB_VERSION_MAX 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_SELINUX=y +# CONFIG_DEFAULT_SECURITY_DAC is not set +CONFIG_DEFAULT_SECURITY="selinux" +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 is not set +CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y +# CONFIG_CRYPTO_GF128MUL is not set +# CONFIG_CRYPTO_NULL is not set +# CONFIG_CRYPTO_PCRYPT is not set +CONFIG_CRYPTO_WORKQUEUE=y +# CONFIG_CRYPTO_CRYPTD is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_TEST is not set + +# +# Authenticated Encryption with Associated Data +# +# CONFIG_CRYPTO_CCM is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_SEQIV is not set + +# +# Block modes +# +CONFIG_CRYPTO_CBC=y +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_CTS is not set +CONFIG_CRYPTO_ECB=y +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_PCBC is not set +# CONFIG_CRYPTO_XTS is not set + +# +# Hash modes +# +CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set +# CONFIG_CRYPTO_VMAC is not set + +# +# Digest +# +CONFIG_CRYPTO_CRC32C=y +# CONFIG_CRYPTO_GHASH 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_SHA1_ARM=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_AES_ARM=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 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 is not set +CONFIG_CRYPTO_LZ4=y +CONFIG_CRYPTO_LZ4HC=y + +# +# Random Number Generation +# +CONFIG_CRYPTO_ANSI_CPRNG=y +# CONFIG_CRYPTO_USER_API_HASH is not set +# CONFIG_CRYPTO_USER_API_SKCIPHER is not set +CONFIG_CRYPTO_HW=y +# CONFIG_CRYPTO_DEV_HIFN_795X is not set +# CONFIG_CRYPTO_DEV_QCRYPTO is not set +# CONFIG_CRYPTO_DEV_QCE is not set +# CONFIG_CRYPTO_DEV_QCEDEV is not set +# CONFIG_CRYPTO_DEV_OTA_CRYPTO is not set +# CONFIG_BINARY_PRINTF is not set + +# +# Library routines +# +CONFIG_BITREVERSE=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 is not set +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_GENERIC=y +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 is not set +# CONFIG_XZ_DEC_BCJ is not set +CONFIG_DECOMPRESS_GZIP=y +CONFIG_DECOMPRESS_BZIP2=y +CONFIG_DECOMPRESS_LZMA=y +CONFIG_DECOMPRESS_LZ4=y +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 +CONFIG_TEXTSEARCH_FSM=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y +CONFIG_CPU_RMAP=y +CONFIG_DQL=y +CONFIG_NLATTR=y +CONFIG_AVERAGE=y +# CONFIG_CORDIC is not set diff --git a/arch/arm/configs/flo_defconfig b/arch/arm/configs/flo_defconfig index 15454e0ca0f..d9ef152b4a7 100644 --- a/arch/arm/configs/flo_defconfig +++ b/arch/arm/configs/flo_defconfig @@ -1,5 +1,6 @@ # CONFIG_ARM_PATCH_PHYS_VIRT is not set CONFIG_EXPERIMENTAL=y +# CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_AUDIT=y CONFIG_IKCONFIG=y @@ -24,7 +25,6 @@ CONFIG_PANIC_TIMEOUT=5 CONFIG_KALLSYMS_ALL=y CONFIG_EMBEDDED=y CONFIG_PROFILING=y -# CONFIG_OPROFILE is not set CONFIG_PARTITION_ADVANCED=y CONFIG_EFI_PARTITION=y CONFIG_ARCH_MSM=y @@ -108,13 +108,15 @@ CONFIG_PM_DEBUG=y CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y +CONFIG_NET_KEY=y CONFIG_INET=y +CONFIG_IP_MULTICAST=y CONFIG_IP_ADVANCED_ROUTER=y CONFIG_IP_MULTIPLE_TABLES=y CONFIG_IP_ROUTE_VERBOSE=y CONFIG_IP_PNP=y CONFIG_IP_PNP_DHCP=y -CONFIG_IP_MULTICAST=y +CONFIG_INET_ESP=y # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_LRO is not set CONFIG_IPV6_PRIVACY=y @@ -142,17 +144,18 @@ CONFIG_NF_CONNTRACK_IRC=y CONFIG_NF_CONNTRACK_NETBIOS_NS=y CONFIG_NF_CONNTRACK_PPTP=y CONFIG_NF_CONNTRACK_SANE=y -# CONFIG_NF_CONNTRACK_SIP is not set CONFIG_NF_CONNTRACK_TFTP=y CONFIG_NF_CT_NETLINK=y CONFIG_NETFILTER_TPROXY=y CONFIG_NETFILTER_XT_TARGET_CLASSIFY=y CONFIG_NETFILTER_XT_TARGET_CONNMARK=y CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=y +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=y CONFIG_NETFILTER_XT_TARGET_LOG=y CONFIG_NETFILTER_XT_TARGET_MARK=y CONFIG_NETFILTER_XT_TARGET_NFQUEUE=y CONFIG_NETFILTER_XT_TARGET_SECMARK=y +CONFIG_NETFILTER_XT_TARGET_TCPMSS=y CONFIG_NETFILTER_XT_MATCH_COMMENT=y CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y CONFIG_NETFILTER_XT_MATCH_CONNMARK=y @@ -200,6 +203,7 @@ CONFIG_IP6_NF_FILTER=y CONFIG_IP6_NF_TARGET_REJECT=y CONFIG_IP6_NF_MANGLE=y CONFIG_IP6_NF_RAW=y +CONFIG_L2TP=y CONFIG_NET_SCHED=y CONFIG_NET_SCH_HTB=y CONFIG_NET_SCH_PRIO=y @@ -227,6 +231,7 @@ CONFIG_BT_HCIUART_H4=y CONFIG_BT_HCIUART_ATH3K=y CONFIG_BT_HCIUART_IBS=y CONFIG_CFG80211=y +CONFIG_CFG80211_INTERNAL_REGDB=y # CONFIG_CFG80211_WEXT is not set CONFIG_RFKILL=y CONFIG_BCM2079X=y @@ -261,6 +266,18 @@ CONFIG_MSM_RMNET_SMUX=y CONFIG_SMC91X=y CONFIG_SMC911X=y CONFIG_SMSC911X=y +CONFIG_PPP=y +CONFIG_PPP_BSDCOMP=y +CONFIG_PPP_DEFLATE=y +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=y +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOE=y +CONFIG_PPPOL2TP=y +CONFIG_PPPOLAC=y +CONFIG_PPPOPNS=y +CONFIG_PPP_ASYNC=y +CONFIG_PPP_SYNC_TTY=y CONFIG_SLIP=y CONFIG_SLIP_COMPRESSED=y CONFIG_SLIP_MODE_SLIP6=y @@ -330,6 +347,7 @@ CONFIG_IR_GPIO_CIR=y # CONFIG_MSM_CAMERA is not set CONFIG_MSM_CAMERA_SENSOR=y CONFIG_MSM_ACTUATOR=y +CONFIG_MSM_GEMINI=y CONFIG_MSM_CCI=y CONFIG_MSM_CSI20_HEADER=y CONFIG_MSM_CSIPHY=y @@ -338,7 +356,6 @@ CONFIG_MSM_ISPIF=y CONFIG_OV5693=y CONFIG_MI1040=y CONFIG_MSMB_CAMERA=y -CONFIG_MSM_GEMINI=y # CONFIG_MEDIA_TUNER_CUSTOMISE is not set CONFIG_VIDEOBUF2_MSM_MEM=y CONFIG_VIDEO_HELPER_CHIPS_AUTO=y @@ -511,29 +528,9 @@ CONFIG_DEBUG_INFO=y CONFIG_DEBUG_MEMORY_INIT=y CONFIG_ENABLE_DEFAULT_TRACERS=y CONFIG_DYNAMIC_DEBUG=y -# CONFIG_DEBUG_USER is not set CONFIG_PID_IN_CONTEXTIDR=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_LSM_MMAP_MIN_ADDR=4096 CONFIG_SECURITY_SELINUX=y CONFIG_CRYPTO_TWOFISH=y -CONFIG_NET_KEY=y -CONFIG_INET_ESP=y -CONFIG_INET_XFRM_MODE_TRANSPORT=y -CONFIG_INET_XFRM_MODE_TUNNEL=y -CONFIG_PPP=y -CONFIG_PPP_DEFLATE=y -CONFIG_PPP_BSDCOMP=y -CONFIG_PPP_FILTER=y -CONFIG_PPP_MPPE=y -CONFIG_PPP_MULTILINK=y -CONFIG_PPPOE=y -CONFIG_L2TP=y -CONFIG_PPPOL2TP=y -CONFIG_PPPOLAC=y -CONFIG_PPPOPNS=y -CONFIG_PPP_ASYNC=y -CONFIG_PPP_SYNC_TTY=y -CONFIG_CFG80211_INTERNAL_REGDB=y -CONFIG_SWAP=n diff --git a/arch/arm/crypto/Makefile b/arch/arm/crypto/Makefile new file mode 100644 index 00000000000..82955273d5e --- /dev/null +++ b/arch/arm/crypto/Makefile @@ -0,0 +1,10 @@ +# +# Arch-specific CryptoAPI modules. +# + +obj-$(CONFIG_CRYPTO_AES_ARM) += aes-arm.o +obj-$(CONFIG_CRYPTO_SHA1_ARM) += sha1-arm.o + +aes-arm-y := aes-armv4.o aes_glue.o +sha1-arm-y := sha1-armv4-large.o sha1_glue.o + diff --git a/arch/arm/crypto/aes-armv4.S b/arch/arm/crypto/aes-armv4.S new file mode 100644 index 00000000000..e59b1d505d6 --- /dev/null +++ b/arch/arm/crypto/aes-armv4.S @@ -0,0 +1,1112 @@ +#define __ARM_ARCH__ __LINUX_ARM_ARCH__ +@ ==================================================================== +@ Written by Andy Polyakov for the OpenSSL +@ project. The module is, however, dual licensed under OpenSSL and +@ CRYPTOGAMS licenses depending on where you obtain it. For further +@ details see http://www.openssl.org/~appro/cryptogams/. +@ ==================================================================== + +@ AES for ARMv4 + +@ January 2007. +@ +@ Code uses single 1K S-box and is >2 times faster than code generated +@ by gcc-3.4.1. This is thanks to unique feature of ARMv4 ISA, which +@ allows to merge logical or arithmetic operation with shift or rotate +@ in one instruction and emit combined result every cycle. The module +@ is endian-neutral. The performance is ~42 cycles/byte for 128-bit +@ key [on single-issue Xscale PXA250 core]. + +@ May 2007. +@ +@ AES_set_[en|de]crypt_key is added. + +@ July 2010. +@ +@ Rescheduling for dual-issue pipeline resulted in 12% improvement on +@ Cortex A8 core and ~25 cycles per byte processed with 128-bit key. + +@ February 2011. +@ +@ Profiler-assisted and platform-specific optimization resulted in 16% +@ improvement on Cortex A8 core and ~21.5 cycles per byte. + +@ A little glue here to select the correct code below for the ARM CPU +@ that is being targetted. + +.text +.code 32 + +.type AES_Te,%object +.align 5 +AES_Te: +.word 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d +.word 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554 +.word 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d +.word 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a +.word 0x8fcaca45, 0x1f82829d, 0x89c9c940, 0xfa7d7d87 +.word 0xeffafa15, 0xb25959eb, 0x8e4747c9, 0xfbf0f00b +.word 0x41adadec, 0xb3d4d467, 0x5fa2a2fd, 0x45afafea +.word 0x239c9cbf, 0x53a4a4f7, 0xe4727296, 0x9bc0c05b +.word 0x75b7b7c2, 0xe1fdfd1c, 0x3d9393ae, 0x4c26266a +.word 0x6c36365a, 0x7e3f3f41, 0xf5f7f702, 0x83cccc4f +.word 0x6834345c, 0x51a5a5f4, 0xd1e5e534, 0xf9f1f108 +.word 0xe2717193, 0xabd8d873, 0x62313153, 0x2a15153f +.word 0x0804040c, 0x95c7c752, 0x46232365, 0x9dc3c35e +.word 0x30181828, 0x379696a1, 0x0a05050f, 0x2f9a9ab5 +.word 0x0e070709, 0x24121236, 0x1b80809b, 0xdfe2e23d +.word 0xcdebeb26, 0x4e272769, 0x7fb2b2cd, 0xea75759f +.word 0x1209091b, 0x1d83839e, 0x582c2c74, 0x341a1a2e +.word 0x361b1b2d, 0xdc6e6eb2, 0xb45a5aee, 0x5ba0a0fb +.word 0xa45252f6, 0x763b3b4d, 0xb7d6d661, 0x7db3b3ce +.word 0x5229297b, 0xdde3e33e, 0x5e2f2f71, 0x13848497 +.word 0xa65353f5, 0xb9d1d168, 0x00000000, 0xc1eded2c +.word 0x40202060, 0xe3fcfc1f, 0x79b1b1c8, 0xb65b5bed +.word 0xd46a6abe, 0x8dcbcb46, 0x67bebed9, 0x7239394b +.word 0x944a4ade, 0x984c4cd4, 0xb05858e8, 0x85cfcf4a +.word 0xbbd0d06b, 0xc5efef2a, 0x4faaaae5, 0xedfbfb16 +.word 0x864343c5, 0x9a4d4dd7, 0x66333355, 0x11858594 +.word 0x8a4545cf, 0xe9f9f910, 0x04020206, 0xfe7f7f81 +.word 0xa05050f0, 0x783c3c44, 0x259f9fba, 0x4ba8a8e3 +.word 0xa25151f3, 0x5da3a3fe, 0x804040c0, 0x058f8f8a +.word 0x3f9292ad, 0x219d9dbc, 0x70383848, 0xf1f5f504 +.word 0x63bcbcdf, 0x77b6b6c1, 0xafdada75, 0x42212163 +.word 0x20101030, 0xe5ffff1a, 0xfdf3f30e, 0xbfd2d26d +.word 0x81cdcd4c, 0x180c0c14, 0x26131335, 0xc3ecec2f +.word 0xbe5f5fe1, 0x359797a2, 0x884444cc, 0x2e171739 +.word 0x93c4c457, 0x55a7a7f2, 0xfc7e7e82, 0x7a3d3d47 +.word 0xc86464ac, 0xba5d5de7, 0x3219192b, 0xe6737395 +.word 0xc06060a0, 0x19818198, 0x9e4f4fd1, 0xa3dcdc7f +.word 0x44222266, 0x542a2a7e, 0x3b9090ab, 0x0b888883 +.word 0x8c4646ca, 0xc7eeee29, 0x6bb8b8d3, 0x2814143c +.word 0xa7dede79, 0xbc5e5ee2, 0x160b0b1d, 0xaddbdb76 +.word 0xdbe0e03b, 0x64323256, 0x743a3a4e, 0x140a0a1e +.word 0x924949db, 0x0c06060a, 0x4824246c, 0xb85c5ce4 +.word 0x9fc2c25d, 0xbdd3d36e, 0x43acacef, 0xc46262a6 +.word 0x399191a8, 0x319595a4, 0xd3e4e437, 0xf279798b +.word 0xd5e7e732, 0x8bc8c843, 0x6e373759, 0xda6d6db7 +.word 0x018d8d8c, 0xb1d5d564, 0x9c4e4ed2, 0x49a9a9e0 +.word 0xd86c6cb4, 0xac5656fa, 0xf3f4f407, 0xcfeaea25 +.word 0xca6565af, 0xf47a7a8e, 0x47aeaee9, 0x10080818 +.word 0x6fbabad5, 0xf0787888, 0x4a25256f, 0x5c2e2e72 +.word 0x381c1c24, 0x57a6a6f1, 0x73b4b4c7, 0x97c6c651 +.word 0xcbe8e823, 0xa1dddd7c, 0xe874749c, 0x3e1f1f21 +.word 0x964b4bdd, 0x61bdbddc, 0x0d8b8b86, 0x0f8a8a85 +.word 0xe0707090, 0x7c3e3e42, 0x71b5b5c4, 0xcc6666aa +.word 0x904848d8, 0x06030305, 0xf7f6f601, 0x1c0e0e12 +.word 0xc26161a3, 0x6a35355f, 0xae5757f9, 0x69b9b9d0 +.word 0x17868691, 0x99c1c158, 0x3a1d1d27, 0x279e9eb9 +.word 0xd9e1e138, 0xebf8f813, 0x2b9898b3, 0x22111133 +.word 0xd26969bb, 0xa9d9d970, 0x078e8e89, 0x339494a7 +.word 0x2d9b9bb6, 0x3c1e1e22, 0x15878792, 0xc9e9e920 +.word 0x87cece49, 0xaa5555ff, 0x50282878, 0xa5dfdf7a +.word 0x038c8c8f, 0x59a1a1f8, 0x09898980, 0x1a0d0d17 +.word 0x65bfbfda, 0xd7e6e631, 0x844242c6, 0xd06868b8 +.word 0x824141c3, 0x299999b0, 0x5a2d2d77, 0x1e0f0f11 +.word 0x7bb0b0cb, 0xa85454fc, 0x6dbbbbd6, 0x2c16163a +@ Te4[256] +.byte 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5 +.byte 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76 +.byte 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0 +.byte 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0 +.byte 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc +.byte 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15 +.byte 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a +.byte 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75 +.byte 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0 +.byte 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84 +.byte 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b +.byte 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf +.byte 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85 +.byte 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8 +.byte 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5 +.byte 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2 +.byte 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17 +.byte 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73 +.byte 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88 +.byte 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb +.byte 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c +.byte 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79 +.byte 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9 +.byte 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08 +.byte 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6 +.byte 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a +.byte 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e +.byte 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e +.byte 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94 +.byte 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf +.byte 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68 +.byte 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16 +@ rcon[] +.word 0x01000000, 0x02000000, 0x04000000, 0x08000000 +.word 0x10000000, 0x20000000, 0x40000000, 0x80000000 +.word 0x1B000000, 0x36000000, 0, 0, 0, 0, 0, 0 +.size AES_Te,.-AES_Te + +@ void AES_encrypt(const unsigned char *in, unsigned char *out, +@ const AES_KEY *key) { +.global AES_encrypt +.type AES_encrypt,%function +.align 5 +AES_encrypt: + sub r3,pc,#8 @ AES_encrypt + stmdb sp!,{r1,r4-r12,lr} + mov r12,r0 @ inp + mov r11,r2 + sub r10,r3,#AES_encrypt-AES_Te @ Te +#if __ARM_ARCH__<7 + ldrb r0,[r12,#3] @ load input data in endian-neutral + ldrb r4,[r12,#2] @ manner... + ldrb r5,[r12,#1] + ldrb r6,[r12,#0] + orr r0,r0,r4,lsl#8 + ldrb r1,[r12,#7] + orr r0,r0,r5,lsl#16 + ldrb r4,[r12,#6] + orr r0,r0,r6,lsl#24 + ldrb r5,[r12,#5] + ldrb r6,[r12,#4] + orr r1,r1,r4,lsl#8 + ldrb r2,[r12,#11] + orr r1,r1,r5,lsl#16 + ldrb r4,[r12,#10] + orr r1,r1,r6,lsl#24 + ldrb r5,[r12,#9] + ldrb r6,[r12,#8] + orr r2,r2,r4,lsl#8 + ldrb r3,[r12,#15] + orr r2,r2,r5,lsl#16 + ldrb r4,[r12,#14] + orr r2,r2,r6,lsl#24 + ldrb r5,[r12,#13] + ldrb r6,[r12,#12] + orr r3,r3,r4,lsl#8 + orr r3,r3,r5,lsl#16 + orr r3,r3,r6,lsl#24 +#else + ldr r0,[r12,#0] + ldr r1,[r12,#4] + ldr r2,[r12,#8] + ldr r3,[r12,#12] +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif +#endif + bl _armv4_AES_encrypt + + ldr r12,[sp],#4 @ pop out +#if __ARM_ARCH__>=7 +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif + str r0,[r12,#0] + str r1,[r12,#4] + str r2,[r12,#8] + str r3,[r12,#12] +#else + mov r4,r0,lsr#24 @ write output in endian-neutral + mov r5,r0,lsr#16 @ manner... + mov r6,r0,lsr#8 + strb r4,[r12,#0] + strb r5,[r12,#1] + mov r4,r1,lsr#24 + strb r6,[r12,#2] + mov r5,r1,lsr#16 + strb r0,[r12,#3] + mov r6,r1,lsr#8 + strb r4,[r12,#4] + strb r5,[r12,#5] + mov r4,r2,lsr#24 + strb r6,[r12,#6] + mov r5,r2,lsr#16 + strb r1,[r12,#7] + mov r6,r2,lsr#8 + strb r4,[r12,#8] + strb r5,[r12,#9] + mov r4,r3,lsr#24 + strb r6,[r12,#10] + mov r5,r3,lsr#16 + strb r2,[r12,#11] + mov r6,r3,lsr#8 + strb r4,[r12,#12] + strb r5,[r12,#13] + strb r6,[r12,#14] + strb r3,[r12,#15] +#endif +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif +.size AES_encrypt,.-AES_encrypt + +.type _armv4_AES_encrypt,%function +.align 2 +_armv4_AES_encrypt: + str lr,[sp,#-4]! @ push lr + ldmia r11!,{r4-r7} + eor r0,r0,r4 + ldr r12,[r11,#240-16] + eor r1,r1,r5 + eor r2,r2,r6 + eor r3,r3,r7 + sub r12,r12,#1 + mov lr,#255 + + and r7,lr,r0 + and r8,lr,r0,lsr#8 + and r9,lr,r0,lsr#16 + mov r0,r0,lsr#24 +.Lenc_loop: + ldr r4,[r10,r7,lsl#2] @ Te3[s0>>0] + and r7,lr,r1,lsr#16 @ i0 + ldr r5,[r10,r8,lsl#2] @ Te2[s0>>8] + and r8,lr,r1 + ldr r6,[r10,r9,lsl#2] @ Te1[s0>>16] + and r9,lr,r1,lsr#8 + ldr r0,[r10,r0,lsl#2] @ Te0[s0>>24] + mov r1,r1,lsr#24 + + ldr r7,[r10,r7,lsl#2] @ Te1[s1>>16] + ldr r8,[r10,r8,lsl#2] @ Te3[s1>>0] + ldr r9,[r10,r9,lsl#2] @ Te2[s1>>8] + eor r0,r0,r7,ror#8 + ldr r1,[r10,r1,lsl#2] @ Te0[s1>>24] + and r7,lr,r2,lsr#8 @ i0 + eor r5,r5,r8,ror#8 + and r8,lr,r2,lsr#16 @ i1 + eor r6,r6,r9,ror#8 + and r9,lr,r2 + ldr r7,[r10,r7,lsl#2] @ Te2[s2>>8] + eor r1,r1,r4,ror#24 + ldr r8,[r10,r8,lsl#2] @ Te1[s2>>16] + mov r2,r2,lsr#24 + + ldr r9,[r10,r9,lsl#2] @ Te3[s2>>0] + eor r0,r0,r7,ror#16 + ldr r2,[r10,r2,lsl#2] @ Te0[s2>>24] + and r7,lr,r3 @ i0 + eor r1,r1,r8,ror#8 + and r8,lr,r3,lsr#8 @ i1 + eor r6,r6,r9,ror#16 + and r9,lr,r3,lsr#16 @ i2 + ldr r7,[r10,r7,lsl#2] @ Te3[s3>>0] + eor r2,r2,r5,ror#16 + ldr r8,[r10,r8,lsl#2] @ Te2[s3>>8] + mov r3,r3,lsr#24 + + ldr r9,[r10,r9,lsl#2] @ Te1[s3>>16] + eor r0,r0,r7,ror#24 + ldr r7,[r11],#16 + eor r1,r1,r8,ror#16 + ldr r3,[r10,r3,lsl#2] @ Te0[s3>>24] + eor r2,r2,r9,ror#8 + ldr r4,[r11,#-12] + eor r3,r3,r6,ror#8 + + ldr r5,[r11,#-8] + eor r0,r0,r7 + ldr r6,[r11,#-4] + and r7,lr,r0 + eor r1,r1,r4 + and r8,lr,r0,lsr#8 + eor r2,r2,r5 + and r9,lr,r0,lsr#16 + eor r3,r3,r6 + mov r0,r0,lsr#24 + + subs r12,r12,#1 + bne .Lenc_loop + + add r10,r10,#2 + + ldrb r4,[r10,r7,lsl#2] @ Te4[s0>>0] + and r7,lr,r1,lsr#16 @ i0 + ldrb r5,[r10,r8,lsl#2] @ Te4[s0>>8] + and r8,lr,r1 + ldrb r6,[r10,r9,lsl#2] @ Te4[s0>>16] + and r9,lr,r1,lsr#8 + ldrb r0,[r10,r0,lsl#2] @ Te4[s0>>24] + mov r1,r1,lsr#24 + + ldrb r7,[r10,r7,lsl#2] @ Te4[s1>>16] + ldrb r8,[r10,r8,lsl#2] @ Te4[s1>>0] + ldrb r9,[r10,r9,lsl#2] @ Te4[s1>>8] + eor r0,r7,r0,lsl#8 + ldrb r1,[r10,r1,lsl#2] @ Te4[s1>>24] + and r7,lr,r2,lsr#8 @ i0 + eor r5,r8,r5,lsl#8 + and r8,lr,r2,lsr#16 @ i1 + eor r6,r9,r6,lsl#8 + and r9,lr,r2 + ldrb r7,[r10,r7,lsl#2] @ Te4[s2>>8] + eor r1,r4,r1,lsl#24 + ldrb r8,[r10,r8,lsl#2] @ Te4[s2>>16] + mov r2,r2,lsr#24 + + ldrb r9,[r10,r9,lsl#2] @ Te4[s2>>0] + eor r0,r7,r0,lsl#8 + ldrb r2,[r10,r2,lsl#2] @ Te4[s2>>24] + and r7,lr,r3 @ i0 + eor r1,r1,r8,lsl#16 + and r8,lr,r3,lsr#8 @ i1 + eor r6,r9,r6,lsl#8 + and r9,lr,r3,lsr#16 @ i2 + ldrb r7,[r10,r7,lsl#2] @ Te4[s3>>0] + eor r2,r5,r2,lsl#24 + ldrb r8,[r10,r8,lsl#2] @ Te4[s3>>8] + mov r3,r3,lsr#24 + + ldrb r9,[r10,r9,lsl#2] @ Te4[s3>>16] + eor r0,r7,r0,lsl#8 + ldr r7,[r11,#0] + ldrb r3,[r10,r3,lsl#2] @ Te4[s3>>24] + eor r1,r1,r8,lsl#8 + ldr r4,[r11,#4] + eor r2,r2,r9,lsl#16 + ldr r5,[r11,#8] + eor r3,r6,r3,lsl#24 + ldr r6,[r11,#12] + + eor r0,r0,r7 + eor r1,r1,r4 + eor r2,r2,r5 + eor r3,r3,r6 + + sub r10,r10,#2 + ldr pc,[sp],#4 @ pop and return +.size _armv4_AES_encrypt,.-_armv4_AES_encrypt + +.global private_AES_set_encrypt_key +.type private_AES_set_encrypt_key,%function +.align 5 +private_AES_set_encrypt_key: +_armv4_AES_set_encrypt_key: + sub r3,pc,#8 @ AES_set_encrypt_key + teq r0,#0 + moveq r0,#-1 + beq .Labrt + teq r2,#0 + moveq r0,#-1 + beq .Labrt + + teq r1,#128 + beq .Lok + teq r1,#192 + beq .Lok + teq r1,#256 + movne r0,#-1 + bne .Labrt + +.Lok: stmdb sp!,{r4-r12,lr} + sub r10,r3,#_armv4_AES_set_encrypt_key-AES_Te-1024 @ Te4 + + mov r12,r0 @ inp + mov lr,r1 @ bits + mov r11,r2 @ key + +#if __ARM_ARCH__<7 + ldrb r0,[r12,#3] @ load input data in endian-neutral + ldrb r4,[r12,#2] @ manner... + ldrb r5,[r12,#1] + ldrb r6,[r12,#0] + orr r0,r0,r4,lsl#8 + ldrb r1,[r12,#7] + orr r0,r0,r5,lsl#16 + ldrb r4,[r12,#6] + orr r0,r0,r6,lsl#24 + ldrb r5,[r12,#5] + ldrb r6,[r12,#4] + orr r1,r1,r4,lsl#8 + ldrb r2,[r12,#11] + orr r1,r1,r5,lsl#16 + ldrb r4,[r12,#10] + orr r1,r1,r6,lsl#24 + ldrb r5,[r12,#9] + ldrb r6,[r12,#8] + orr r2,r2,r4,lsl#8 + ldrb r3,[r12,#15] + orr r2,r2,r5,lsl#16 + ldrb r4,[r12,#14] + orr r2,r2,r6,lsl#24 + ldrb r5,[r12,#13] + ldrb r6,[r12,#12] + orr r3,r3,r4,lsl#8 + str r0,[r11],#16 + orr r3,r3,r5,lsl#16 + str r1,[r11,#-12] + orr r3,r3,r6,lsl#24 + str r2,[r11,#-8] + str r3,[r11,#-4] +#else + ldr r0,[r12,#0] + ldr r1,[r12,#4] + ldr r2,[r12,#8] + ldr r3,[r12,#12] +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif + str r0,[r11],#16 + str r1,[r11,#-12] + str r2,[r11,#-8] + str r3,[r11,#-4] +#endif + + teq lr,#128 + bne .Lnot128 + mov r12,#10 + str r12,[r11,#240-16] + add r6,r10,#256 @ rcon + mov lr,#255 + +.L128_loop: + and r5,lr,r3,lsr#24 + and r7,lr,r3,lsr#16 + ldrb r5,[r10,r5] + and r8,lr,r3,lsr#8 + ldrb r7,[r10,r7] + and r9,lr,r3 + ldrb r8,[r10,r8] + orr r5,r5,r7,lsl#24 + ldrb r9,[r10,r9] + orr r5,r5,r8,lsl#16 + ldr r4,[r6],#4 @ rcon[i++] + orr r5,r5,r9,lsl#8 + eor r5,r5,r4 + eor r0,r0,r5 @ rk[4]=rk[0]^... + eor r1,r1,r0 @ rk[5]=rk[1]^rk[4] + str r0,[r11],#16 + eor r2,r2,r1 @ rk[6]=rk[2]^rk[5] + str r1,[r11,#-12] + eor r3,r3,r2 @ rk[7]=rk[3]^rk[6] + str r2,[r11,#-8] + subs r12,r12,#1 + str r3,[r11,#-4] + bne .L128_loop + sub r2,r11,#176 + b .Ldone + +.Lnot128: +#if __ARM_ARCH__<7 + ldrb r8,[r12,#19] + ldrb r4,[r12,#18] + ldrb r5,[r12,#17] + ldrb r6,[r12,#16] + orr r8,r8,r4,lsl#8 + ldrb r9,[r12,#23] + orr r8,r8,r5,lsl#16 + ldrb r4,[r12,#22] + orr r8,r8,r6,lsl#24 + ldrb r5,[r12,#21] + ldrb r6,[r12,#20] + orr r9,r9,r4,lsl#8 + orr r9,r9,r5,lsl#16 + str r8,[r11],#8 + orr r9,r9,r6,lsl#24 + str r9,[r11,#-4] +#else + ldr r8,[r12,#16] + ldr r9,[r12,#20] +#ifdef __ARMEL__ + rev r8,r8 + rev r9,r9 +#endif + str r8,[r11],#8 + str r9,[r11,#-4] +#endif + + teq lr,#192 + bne .Lnot192 + mov r12,#12 + str r12,[r11,#240-24] + add r6,r10,#256 @ rcon + mov lr,#255 + mov r12,#8 + +.L192_loop: + and r5,lr,r9,lsr#24 + and r7,lr,r9,lsr#16 + ldrb r5,[r10,r5] + and r8,lr,r9,lsr#8 + ldrb r7,[r10,r7] + and r9,lr,r9 + ldrb r8,[r10,r8] + orr r5,r5,r7,lsl#24 + ldrb r9,[r10,r9] + orr r5,r5,r8,lsl#16 + ldr r4,[r6],#4 @ rcon[i++] + orr r5,r5,r9,lsl#8 + eor r9,r5,r4 + eor r0,r0,r9 @ rk[6]=rk[0]^... + eor r1,r1,r0 @ rk[7]=rk[1]^rk[6] + str r0,[r11],#24 + eor r2,r2,r1 @ rk[8]=rk[2]^rk[7] + str r1,[r11,#-20] + eor r3,r3,r2 @ rk[9]=rk[3]^rk[8] + str r2,[r11,#-16] + subs r12,r12,#1 + str r3,[r11,#-12] + subeq r2,r11,#216 + beq .Ldone + + ldr r7,[r11,#-32] + ldr r8,[r11,#-28] + eor r7,r7,r3 @ rk[10]=rk[4]^rk[9] + eor r9,r8,r7 @ rk[11]=rk[5]^rk[10] + str r7,[r11,#-8] + str r9,[r11,#-4] + b .L192_loop + +.Lnot192: +#if __ARM_ARCH__<7 + ldrb r8,[r12,#27] + ldrb r4,[r12,#26] + ldrb r5,[r12,#25] + ldrb r6,[r12,#24] + orr r8,r8,r4,lsl#8 + ldrb r9,[r12,#31] + orr r8,r8,r5,lsl#16 + ldrb r4,[r12,#30] + orr r8,r8,r6,lsl#24 + ldrb r5,[r12,#29] + ldrb r6,[r12,#28] + orr r9,r9,r4,lsl#8 + orr r9,r9,r5,lsl#16 + str r8,[r11],#8 + orr r9,r9,r6,lsl#24 + str r9,[r11,#-4] +#else + ldr r8,[r12,#24] + ldr r9,[r12,#28] +#ifdef __ARMEL__ + rev r8,r8 + rev r9,r9 +#endif + str r8,[r11],#8 + str r9,[r11,#-4] +#endif + + mov r12,#14 + str r12,[r11,#240-32] + add r6,r10,#256 @ rcon + mov lr,#255 + mov r12,#7 + +.L256_loop: + and r5,lr,r9,lsr#24 + and r7,lr,r9,lsr#16 + ldrb r5,[r10,r5] + and r8,lr,r9,lsr#8 + ldrb r7,[r10,r7] + and r9,lr,r9 + ldrb r8,[r10,r8] + orr r5,r5,r7,lsl#24 + ldrb r9,[r10,r9] + orr r5,r5,r8,lsl#16 + ldr r4,[r6],#4 @ rcon[i++] + orr r5,r5,r9,lsl#8 + eor r9,r5,r4 + eor r0,r0,r9 @ rk[8]=rk[0]^... + eor r1,r1,r0 @ rk[9]=rk[1]^rk[8] + str r0,[r11],#32 + eor r2,r2,r1 @ rk[10]=rk[2]^rk[9] + str r1,[r11,#-28] + eor r3,r3,r2 @ rk[11]=rk[3]^rk[10] + str r2,[r11,#-24] + subs r12,r12,#1 + str r3,[r11,#-20] + subeq r2,r11,#256 + beq .Ldone + + and r5,lr,r3 + and r7,lr,r3,lsr#8 + ldrb r5,[r10,r5] + and r8,lr,r3,lsr#16 + ldrb r7,[r10,r7] + and r9,lr,r3,lsr#24 + ldrb r8,[r10,r8] + orr r5,r5,r7,lsl#8 + ldrb r9,[r10,r9] + orr r5,r5,r8,lsl#16 + ldr r4,[r11,#-48] + orr r5,r5,r9,lsl#24 + + ldr r7,[r11,#-44] + ldr r8,[r11,#-40] + eor r4,r4,r5 @ rk[12]=rk[4]^... + ldr r9,[r11,#-36] + eor r7,r7,r4 @ rk[13]=rk[5]^rk[12] + str r4,[r11,#-16] + eor r8,r8,r7 @ rk[14]=rk[6]^rk[13] + str r7,[r11,#-12] + eor r9,r9,r8 @ rk[15]=rk[7]^rk[14] + str r8,[r11,#-8] + str r9,[r11,#-4] + b .L256_loop + +.Ldone: mov r0,#0 + ldmia sp!,{r4-r12,lr} +.Labrt: tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +.size private_AES_set_encrypt_key,.-private_AES_set_encrypt_key + +.global private_AES_set_decrypt_key +.type private_AES_set_decrypt_key,%function +.align 5 +private_AES_set_decrypt_key: + str lr,[sp,#-4]! @ push lr +#if 0 + @ kernel does both of these in setkey so optimise this bit out by + @ expecting the key to already have the enc_key work done (see aes_glue.c) + bl _armv4_AES_set_encrypt_key +#else + mov r0,#0 +#endif + teq r0,#0 + ldrne lr,[sp],#4 @ pop lr + bne .Labrt + + stmdb sp!,{r4-r12} + + ldr r12,[r2,#240] @ AES_set_encrypt_key preserves r2, + mov r11,r2 @ which is AES_KEY *key + mov r7,r2 + add r8,r2,r12,lsl#4 + +.Linv: ldr r0,[r7] + ldr r1,[r7,#4] + ldr r2,[r7,#8] + ldr r3,[r7,#12] + ldr r4,[r8] + ldr r5,[r8,#4] + ldr r6,[r8,#8] + ldr r9,[r8,#12] + str r0,[r8],#-16 + str r1,[r8,#16+4] + str r2,[r8,#16+8] + str r3,[r8,#16+12] + str r4,[r7],#16 + str r5,[r7,#-12] + str r6,[r7,#-8] + str r9,[r7,#-4] + teq r7,r8 + bne .Linv + ldr r0,[r11,#16]! @ prefetch tp1 + mov r7,#0x80 + mov r8,#0x1b + orr r7,r7,#0x8000 + orr r8,r8,#0x1b00 + orr r7,r7,r7,lsl#16 + orr r8,r8,r8,lsl#16 + sub r12,r12,#1 + mvn r9,r7 + mov r12,r12,lsl#2 @ (rounds-1)*4 + +.Lmix: and r4,r0,r7 + and r1,r0,r9 + sub r4,r4,r4,lsr#7 + and r4,r4,r8 + eor r1,r4,r1,lsl#1 @ tp2 + + and r4,r1,r7 + and r2,r1,r9 + sub r4,r4,r4,lsr#7 + and r4,r4,r8 + eor r2,r4,r2,lsl#1 @ tp4 + + and r4,r2,r7 + and r3,r2,r9 + sub r4,r4,r4,lsr#7 + and r4,r4,r8 + eor r3,r4,r3,lsl#1 @ tp8 + + eor r4,r1,r2 + eor r5,r0,r3 @ tp9 + eor r4,r4,r3 @ tpe + eor r4,r4,r1,ror#24 + eor r4,r4,r5,ror#24 @ ^= ROTATE(tpb=tp9^tp2,8) + eor r4,r4,r2,ror#16 + eor r4,r4,r5,ror#16 @ ^= ROTATE(tpd=tp9^tp4,16) + eor r4,r4,r5,ror#8 @ ^= ROTATE(tp9,24) + + ldr r0,[r11,#4] @ prefetch tp1 + str r4,[r11],#4 + subs r12,r12,#1 + bne .Lmix + + mov r0,#0 +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif +.size private_AES_set_decrypt_key,.-private_AES_set_decrypt_key + +.type AES_Td,%object +.align 5 +AES_Td: +.word 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96 +.word 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393 +.word 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25 +.word 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f +.word 0xdeb15a49, 0x25ba1b67, 0x45ea0e98, 0x5dfec0e1 +.word 0xc32f7502, 0x814cf012, 0x8d4697a3, 0x6bd3f9c6 +.word 0x038f5fe7, 0x15929c95, 0xbf6d7aeb, 0x955259da +.word 0xd4be832d, 0x587421d3, 0x49e06929, 0x8ec9c844 +.word 0x75c2896a, 0xf48e7978, 0x99583e6b, 0x27b971dd +.word 0xbee14fb6, 0xf088ad17, 0xc920ac66, 0x7dce3ab4 +.word 0x63df4a18, 0xe51a3182, 0x97513360, 0x62537f45 +.word 0xb16477e0, 0xbb6bae84, 0xfe81a01c, 0xf9082b94 +.word 0x70486858, 0x8f45fd19, 0x94de6c87, 0x527bf8b7 +.word 0xab73d323, 0x724b02e2, 0xe31f8f57, 0x6655ab2a +.word 0xb2eb2807, 0x2fb5c203, 0x86c57b9a, 0xd33708a5 +.word 0x302887f2, 0x23bfa5b2, 0x02036aba, 0xed16825c +.word 0x8acf1c2b, 0xa779b492, 0xf307f2f0, 0x4e69e2a1 +.word 0x65daf4cd, 0x0605bed5, 0xd134621f, 0xc4a6fe8a +.word 0x342e539d, 0xa2f355a0, 0x058ae132, 0xa4f6eb75 +.word 0x0b83ec39, 0x4060efaa, 0x5e719f06, 0xbd6e1051 +.word 0x3e218af9, 0x96dd063d, 0xdd3e05ae, 0x4de6bd46 +.word 0x91548db5, 0x71c45d05, 0x0406d46f, 0x605015ff +.word 0x1998fb24, 0xd6bde997, 0x894043cc, 0x67d99e77 +.word 0xb0e842bd, 0x07898b88, 0xe7195b38, 0x79c8eedb +.word 0xa17c0a47, 0x7c420fe9, 0xf8841ec9, 0x00000000 +.word 0x09808683, 0x322bed48, 0x1e1170ac, 0x6c5a724e +.word 0xfd0efffb, 0x0f853856, 0x3daed51e, 0x362d3927 +.word 0x0a0fd964, 0x685ca621, 0x9b5b54d1, 0x24362e3a +.word 0x0c0a67b1, 0x9357e70f, 0xb4ee96d2, 0x1b9b919e +.word 0x80c0c54f, 0x61dc20a2, 0x5a774b69, 0x1c121a16 +.word 0xe293ba0a, 0xc0a02ae5, 0x3c22e043, 0x121b171d +.word 0x0e090d0b, 0xf28bc7ad, 0x2db6a8b9, 0x141ea9c8 +.word 0x57f11985, 0xaf75074c, 0xee99ddbb, 0xa37f60fd +.word 0xf701269f, 0x5c72f5bc, 0x44663bc5, 0x5bfb7e34 +.word 0x8b432976, 0xcb23c6dc, 0xb6edfc68, 0xb8e4f163 +.word 0xd731dcca, 0x42638510, 0x13972240, 0x84c61120 +.word 0x854a247d, 0xd2bb3df8, 0xaef93211, 0xc729a16d +.word 0x1d9e2f4b, 0xdcb230f3, 0x0d8652ec, 0x77c1e3d0 +.word 0x2bb3166c, 0xa970b999, 0x119448fa, 0x47e96422 +.word 0xa8fc8cc4, 0xa0f03f1a, 0x567d2cd8, 0x223390ef +.word 0x87494ec7, 0xd938d1c1, 0x8ccaa2fe, 0x98d40b36 +.word 0xa6f581cf, 0xa57ade28, 0xdab78e26, 0x3fadbfa4 +.word 0x2c3a9de4, 0x5078920d, 0x6a5fcc9b, 0x547e4662 +.word 0xf68d13c2, 0x90d8b8e8, 0x2e39f75e, 0x82c3aff5 +.word 0x9f5d80be, 0x69d0937c, 0x6fd52da9, 0xcf2512b3 +.word 0xc8ac993b, 0x10187da7, 0xe89c636e, 0xdb3bbb7b +.word 0xcd267809, 0x6e5918f4, 0xec9ab701, 0x834f9aa8 +.word 0xe6956e65, 0xaaffe67e, 0x21bccf08, 0xef15e8e6 +.word 0xbae79bd9, 0x4a6f36ce, 0xea9f09d4, 0x29b07cd6 +.word 0x31a4b2af, 0x2a3f2331, 0xc6a59430, 0x35a266c0 +.word 0x744ebc37, 0xfc82caa6, 0xe090d0b0, 0x33a7d815 +.word 0xf104984a, 0x41ecdaf7, 0x7fcd500e, 0x1791f62f +.word 0x764dd68d, 0x43efb04d, 0xccaa4d54, 0xe49604df +.word 0x9ed1b5e3, 0x4c6a881b, 0xc12c1fb8, 0x4665517f +.word 0x9d5eea04, 0x018c355d, 0xfa877473, 0xfb0b412e +.word 0xb3671d5a, 0x92dbd252, 0xe9105633, 0x6dd64713 +.word 0x9ad7618c, 0x37a10c7a, 0x59f8148e, 0xeb133c89 +.word 0xcea927ee, 0xb761c935, 0xe11ce5ed, 0x7a47b13c +.word 0x9cd2df59, 0x55f2733f, 0x1814ce79, 0x73c737bf +.word 0x53f7cdea, 0x5ffdaa5b, 0xdf3d6f14, 0x7844db86 +.word 0xcaaff381, 0xb968c43e, 0x3824342c, 0xc2a3405f +.word 0x161dc372, 0xbce2250c, 0x283c498b, 0xff0d9541 +.word 0x39a80171, 0x080cb3de, 0xd8b4e49c, 0x6456c190 +.word 0x7bcb8461, 0xd532b670, 0x486c5c74, 0xd0b85742 +@ Td4[256] +.byte 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38 +.byte 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb +.byte 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87 +.byte 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb +.byte 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d +.byte 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e +.byte 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2 +.byte 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25 +.byte 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16 +.byte 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92 +.byte 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda +.byte 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84 +.byte 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a +.byte 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06 +.byte 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02 +.byte 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b +.byte 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea +.byte 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73 +.byte 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85 +.byte 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e +.byte 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89 +.byte 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b +.byte 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20 +.byte 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4 +.byte 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31 +.byte 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f +.byte 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d +.byte 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef +.byte 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0 +.byte 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61 +.byte 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26 +.byte 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d +.size AES_Td,.-AES_Td + +@ void AES_decrypt(const unsigned char *in, unsigned char *out, +@ const AES_KEY *key) { +.global AES_decrypt +.type AES_decrypt,%function +.align 5 +AES_decrypt: + sub r3,pc,#8 @ AES_decrypt + stmdb sp!,{r1,r4-r12,lr} + mov r12,r0 @ inp + mov r11,r2 + sub r10,r3,#AES_decrypt-AES_Td @ Td +#if __ARM_ARCH__<7 + ldrb r0,[r12,#3] @ load input data in endian-neutral + ldrb r4,[r12,#2] @ manner... + ldrb r5,[r12,#1] + ldrb r6,[r12,#0] + orr r0,r0,r4,lsl#8 + ldrb r1,[r12,#7] + orr r0,r0,r5,lsl#16 + ldrb r4,[r12,#6] + orr r0,r0,r6,lsl#24 + ldrb r5,[r12,#5] + ldrb r6,[r12,#4] + orr r1,r1,r4,lsl#8 + ldrb r2,[r12,#11] + orr r1,r1,r5,lsl#16 + ldrb r4,[r12,#10] + orr r1,r1,r6,lsl#24 + ldrb r5,[r12,#9] + ldrb r6,[r12,#8] + orr r2,r2,r4,lsl#8 + ldrb r3,[r12,#15] + orr r2,r2,r5,lsl#16 + ldrb r4,[r12,#14] + orr r2,r2,r6,lsl#24 + ldrb r5,[r12,#13] + ldrb r6,[r12,#12] + orr r3,r3,r4,lsl#8 + orr r3,r3,r5,lsl#16 + orr r3,r3,r6,lsl#24 +#else + ldr r0,[r12,#0] + ldr r1,[r12,#4] + ldr r2,[r12,#8] + ldr r3,[r12,#12] +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif +#endif + bl _armv4_AES_decrypt + + ldr r12,[sp],#4 @ pop out +#if __ARM_ARCH__>=7 +#ifdef __ARMEL__ + rev r0,r0 + rev r1,r1 + rev r2,r2 + rev r3,r3 +#endif + str r0,[r12,#0] + str r1,[r12,#4] + str r2,[r12,#8] + str r3,[r12,#12] +#else + mov r4,r0,lsr#24 @ write output in endian-neutral + mov r5,r0,lsr#16 @ manner... + mov r6,r0,lsr#8 + strb r4,[r12,#0] + strb r5,[r12,#1] + mov r4,r1,lsr#24 + strb r6,[r12,#2] + mov r5,r1,lsr#16 + strb r0,[r12,#3] + mov r6,r1,lsr#8 + strb r4,[r12,#4] + strb r5,[r12,#5] + mov r4,r2,lsr#24 + strb r6,[r12,#6] + mov r5,r2,lsr#16 + strb r1,[r12,#7] + mov r6,r2,lsr#8 + strb r4,[r12,#8] + strb r5,[r12,#9] + mov r4,r3,lsr#24 + strb r6,[r12,#10] + mov r5,r3,lsr#16 + strb r2,[r12,#11] + mov r6,r3,lsr#8 + strb r4,[r12,#12] + strb r5,[r12,#13] + strb r6,[r12,#14] + strb r3,[r12,#15] +#endif +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif +.size AES_decrypt,.-AES_decrypt + +.type _armv4_AES_decrypt,%function +.align 2 +_armv4_AES_decrypt: + str lr,[sp,#-4]! @ push lr + ldmia r11!,{r4-r7} + eor r0,r0,r4 + ldr r12,[r11,#240-16] + eor r1,r1,r5 + eor r2,r2,r6 + eor r3,r3,r7 + sub r12,r12,#1 + mov lr,#255 + + and r7,lr,r0,lsr#16 + and r8,lr,r0,lsr#8 + and r9,lr,r0 + mov r0,r0,lsr#24 +.Ldec_loop: + ldr r4,[r10,r7,lsl#2] @ Td1[s0>>16] + and r7,lr,r1 @ i0 + ldr r5,[r10,r8,lsl#2] @ Td2[s0>>8] + and r8,lr,r1,lsr#16 + ldr r6,[r10,r9,lsl#2] @ Td3[s0>>0] + and r9,lr,r1,lsr#8 + ldr r0,[r10,r0,lsl#2] @ Td0[s0>>24] + mov r1,r1,lsr#24 + + ldr r7,[r10,r7,lsl#2] @ Td3[s1>>0] + ldr r8,[r10,r8,lsl#2] @ Td1[s1>>16] + ldr r9,[r10,r9,lsl#2] @ Td2[s1>>8] + eor r0,r0,r7,ror#24 + ldr r1,[r10,r1,lsl#2] @ Td0[s1>>24] + and r7,lr,r2,lsr#8 @ i0 + eor r5,r8,r5,ror#8 + and r8,lr,r2 @ i1 + eor r6,r9,r6,ror#8 + and r9,lr,r2,lsr#16 + ldr r7,[r10,r7,lsl#2] @ Td2[s2>>8] + eor r1,r1,r4,ror#8 + ldr r8,[r10,r8,lsl#2] @ Td3[s2>>0] + mov r2,r2,lsr#24 + + ldr r9,[r10,r9,lsl#2] @ Td1[s2>>16] + eor r0,r0,r7,ror#16 + ldr r2,[r10,r2,lsl#2] @ Td0[s2>>24] + and r7,lr,r3,lsr#16 @ i0 + eor r1,r1,r8,ror#24 + and r8,lr,r3,lsr#8 @ i1 + eor r6,r9,r6,ror#8 + and r9,lr,r3 @ i2 + ldr r7,[r10,r7,lsl#2] @ Td1[s3>>16] + eor r2,r2,r5,ror#8 + ldr r8,[r10,r8,lsl#2] @ Td2[s3>>8] + mov r3,r3,lsr#24 + + ldr r9,[r10,r9,lsl#2] @ Td3[s3>>0] + eor r0,r0,r7,ror#8 + ldr r7,[r11],#16 + eor r1,r1,r8,ror#16 + ldr r3,[r10,r3,lsl#2] @ Td0[s3>>24] + eor r2,r2,r9,ror#24 + + ldr r4,[r11,#-12] + eor r0,r0,r7 + ldr r5,[r11,#-8] + eor r3,r3,r6,ror#8 + ldr r6,[r11,#-4] + and r7,lr,r0,lsr#16 + eor r1,r1,r4 + and r8,lr,r0,lsr#8 + eor r2,r2,r5 + and r9,lr,r0 + eor r3,r3,r6 + mov r0,r0,lsr#24 + + subs r12,r12,#1 + bne .Ldec_loop + + add r10,r10,#1024 + + ldr r5,[r10,#0] @ prefetch Td4 + ldr r6,[r10,#32] + ldr r4,[r10,#64] + ldr r5,[r10,#96] + ldr r6,[r10,#128] + ldr r4,[r10,#160] + ldr r5,[r10,#192] + ldr r6,[r10,#224] + + ldrb r0,[r10,r0] @ Td4[s0>>24] + ldrb r4,[r10,r7] @ Td4[s0>>16] + and r7,lr,r1 @ i0 + ldrb r5,[r10,r8] @ Td4[s0>>8] + and r8,lr,r1,lsr#16 + ldrb r6,[r10,r9] @ Td4[s0>>0] + and r9,lr,r1,lsr#8 + + ldrb r7,[r10,r7] @ Td4[s1>>0] + ldrb r1,[r10,r1,lsr#24] @ Td4[s1>>24] + ldrb r8,[r10,r8] @ Td4[s1>>16] + eor r0,r7,r0,lsl#24 + ldrb r9,[r10,r9] @ Td4[s1>>8] + eor r1,r4,r1,lsl#8 + and r7,lr,r2,lsr#8 @ i0 + eor r5,r5,r8,lsl#8 + and r8,lr,r2 @ i1 + ldrb r7,[r10,r7] @ Td4[s2>>8] + eor r6,r6,r9,lsl#8 + ldrb r8,[r10,r8] @ Td4[s2>>0] + and r9,lr,r2,lsr#16 + + ldrb r2,[r10,r2,lsr#24] @ Td4[s2>>24] + eor r0,r0,r7,lsl#8 + ldrb r9,[r10,r9] @ Td4[s2>>16] + eor r1,r8,r1,lsl#16 + and r7,lr,r3,lsr#16 @ i0 + eor r2,r5,r2,lsl#16 + and r8,lr,r3,lsr#8 @ i1 + ldrb r7,[r10,r7] @ Td4[s3>>16] + eor r6,r6,r9,lsl#16 + ldrb r8,[r10,r8] @ Td4[s3>>8] + and r9,lr,r3 @ i2 + + ldrb r9,[r10,r9] @ Td4[s3>>0] + ldrb r3,[r10,r3,lsr#24] @ Td4[s3>>24] + eor r0,r0,r7,lsl#16 + ldr r7,[r11,#0] + eor r1,r1,r8,lsl#8 + ldr r4,[r11,#4] + eor r2,r9,r2,lsl#8 + ldr r5,[r11,#8] + eor r3,r6,r3,lsl#24 + ldr r6,[r11,#12] + + eor r0,r0,r7 + eor r1,r1,r4 + eor r2,r2,r5 + eor r3,r3,r6 + + sub r10,r10,#1024 + ldr pc,[sp],#4 @ pop and return +.size _armv4_AES_decrypt,.-_armv4_AES_decrypt +.asciz "AES for ARMv4, CRYPTOGAMS by " +.align 2 diff --git a/arch/arm/crypto/aes_glue.c b/arch/arm/crypto/aes_glue.c new file mode 100644 index 00000000000..59f7877ead6 --- /dev/null +++ b/arch/arm/crypto/aes_glue.c @@ -0,0 +1,108 @@ +/* + * Glue Code for the asm optimized version of the AES Cipher Algorithm + */ + +#include +#include +#include + +#define AES_MAXNR 14 + +typedef struct { + unsigned int rd_key[4 *(AES_MAXNR + 1)]; + int rounds; +} AES_KEY; + +struct AES_CTX { + AES_KEY enc_key; + AES_KEY dec_key; +}; + +asmlinkage void AES_encrypt(const u8 *in, u8 *out, AES_KEY *ctx); +asmlinkage void AES_decrypt(const u8 *in, u8 *out, AES_KEY *ctx); +asmlinkage int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); +asmlinkage int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key); + +static void aes_encrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ + struct AES_CTX *ctx = crypto_tfm_ctx(tfm); + AES_encrypt(src, dst, &ctx->enc_key); +} + +static void aes_decrypt(struct crypto_tfm *tfm, u8 *dst, const u8 *src) +{ + struct AES_CTX *ctx = crypto_tfm_ctx(tfm); + AES_decrypt(src, dst, &ctx->dec_key); +} + +static int aes_set_key(struct crypto_tfm *tfm, const u8 *in_key, + unsigned int key_len) +{ + struct AES_CTX *ctx = crypto_tfm_ctx(tfm); + + switch (key_len) { + case AES_KEYSIZE_128: + key_len = 128; + break; + case AES_KEYSIZE_192: + key_len = 192; + break; + case AES_KEYSIZE_256: + key_len = 256; + break; + default: + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + + if (private_AES_set_encrypt_key(in_key, key_len, &ctx->enc_key) == -1) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + /* private_AES_set_decrypt_key expects an encryption key as input */ + ctx->dec_key = ctx->enc_key; + if (private_AES_set_decrypt_key(in_key, key_len, &ctx->dec_key) == -1) { + tfm->crt_flags |= CRYPTO_TFM_RES_BAD_KEY_LEN; + return -EINVAL; + } + return 0; +} + +static struct crypto_alg aes_alg = { + .cra_name = "aes", + .cra_driver_name = "aes-asm", + .cra_priority = 200, + .cra_flags = CRYPTO_ALG_TYPE_CIPHER, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct AES_CTX), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(aes_alg.cra_list), + .cra_u = { + .cipher = { + .cia_min_keysize = AES_MIN_KEY_SIZE, + .cia_max_keysize = AES_MAX_KEY_SIZE, + .cia_setkey = aes_set_key, + .cia_encrypt = aes_encrypt, + .cia_decrypt = aes_decrypt + } + } +}; + +static int __init aes_init(void) +{ + return crypto_register_alg(&aes_alg); +} + +static void __exit aes_fini(void) +{ + crypto_unregister_alg(&aes_alg); +} + +module_init(aes_init); +module_exit(aes_fini); + +MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm (ASM)"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("aes"); +MODULE_ALIAS("aes-asm"); +MODULE_AUTHOR("David McCullough "); diff --git a/arch/arm/crypto/sha1-armv4-large.S b/arch/arm/crypto/sha1-armv4-large.S new file mode 100644 index 00000000000..7050ab133b9 --- /dev/null +++ b/arch/arm/crypto/sha1-armv4-large.S @@ -0,0 +1,503 @@ +#define __ARM_ARCH__ __LINUX_ARM_ARCH__ +@ ==================================================================== +@ Written by Andy Polyakov for the OpenSSL +@ project. The module is, however, dual licensed under OpenSSL and +@ CRYPTOGAMS licenses depending on where you obtain it. For further +@ details see http://www.openssl.org/~appro/cryptogams/. +@ ==================================================================== + +@ sha1_block procedure for ARMv4. +@ +@ January 2007. + +@ Size/performance trade-off +@ ==================================================================== +@ impl size in bytes comp cycles[*] measured performance +@ ==================================================================== +@ thumb 304 3212 4420 +@ armv4-small 392/+29% 1958/+64% 2250/+96% +@ armv4-compact 740/+89% 1552/+26% 1840/+22% +@ armv4-large 1420/+92% 1307/+19% 1370/+34%[***] +@ full unroll ~5100/+260% ~1260/+4% ~1300/+5% +@ ==================================================================== +@ thumb = same as 'small' but in Thumb instructions[**] and +@ with recurring code in two private functions; +@ small = detached Xload/update, loops are folded; +@ compact = detached Xload/update, 5x unroll; +@ large = interleaved Xload/update, 5x unroll; +@ full unroll = interleaved Xload/update, full unroll, estimated[!]; +@ +@ [*] Manually counted instructions in "grand" loop body. Measured +@ performance is affected by prologue and epilogue overhead, +@ i-cache availability, branch penalties, etc. +@ [**] While each Thumb instruction is twice smaller, they are not as +@ diverse as ARM ones: e.g., there are only two arithmetic +@ instructions with 3 arguments, no [fixed] rotate, addressing +@ modes are limited. As result it takes more instructions to do +@ the same job in Thumb, therefore the code is never twice as +@ small and always slower. +@ [***] which is also ~35% better than compiler generated code. Dual- +@ issue Cortex A8 core was measured to process input block in +@ ~990 cycles. + +@ August 2010. +@ +@ Rescheduling for dual-issue pipeline resulted in 13% improvement on +@ Cortex A8 core and in absolute terms ~870 cycles per input block +@ [or 13.6 cycles per byte]. + +@ February 2011. +@ +@ Profiler-assisted and platform-specific optimization resulted in 10% +@ improvement on Cortex A8 core and 12.2 cycles per byte. + +.text + +.global sha1_block_data_order +.type sha1_block_data_order,%function + +.align 2 +sha1_block_data_order: + stmdb sp!,{r4-r12,lr} + add r2,r1,r2,lsl#6 @ r2 to point at the end of r1 + ldmia r0,{r3,r4,r5,r6,r7} +.Lloop: + ldr r8,.LK_00_19 + mov r14,sp + sub sp,sp,#15*4 + mov r5,r5,ror#30 + mov r6,r6,ror#30 + mov r7,r7,ror#30 @ [6] +.L_00_15: +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r7,r8,r7,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r5,r6 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r7,r7,r3,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r7,r8,r7,ror#2 @ E+=K_00_19 + eor r10,r5,r6 @ F_xx_xx + add r7,r7,r3,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r4,r10,ror#2 + add r7,r7,r9 @ E+=X[i] + eor r10,r10,r6,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r7,r7,r10 @ E+=F_00_19(B,C,D) +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r6,r8,r6,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r4,r5 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r6,r6,r7,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r6,r8,r6,ror#2 @ E+=K_00_19 + eor r10,r4,r5 @ F_xx_xx + add r6,r6,r7,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r3,r10,ror#2 + add r6,r6,r9 @ E+=X[i] + eor r10,r10,r5,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r6,r6,r10 @ E+=F_00_19(B,C,D) +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r5,r8,r5,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r3,r4 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r5,r5,r6,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r5,r8,r5,ror#2 @ E+=K_00_19 + eor r10,r3,r4 @ F_xx_xx + add r5,r5,r6,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r7,r10,ror#2 + add r5,r5,r9 @ E+=X[i] + eor r10,r10,r4,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r5,r5,r10 @ E+=F_00_19(B,C,D) +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r4,r8,r4,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r7,r3 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r4,r4,r5,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r4,r8,r4,ror#2 @ E+=K_00_19 + eor r10,r7,r3 @ F_xx_xx + add r4,r4,r5,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r6,r10,ror#2 + add r4,r4,r9 @ E+=X[i] + eor r10,r10,r3,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r4,r4,r10 @ E+=F_00_19(B,C,D) +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r3,r8,r3,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r6,r7 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r3,r3,r4,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r3,r8,r3,ror#2 @ E+=K_00_19 + eor r10,r6,r7 @ F_xx_xx + add r3,r3,r4,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r5,r10,ror#2 + add r3,r3,r9 @ E+=X[i] + eor r10,r10,r7,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r3,r3,r10 @ E+=F_00_19(B,C,D) + teq r14,sp + bne .L_00_15 @ [((11+4)*5+2)*3] +#if __ARM_ARCH__<7 + ldrb r10,[r1,#2] + ldrb r9,[r1,#3] + ldrb r11,[r1,#1] + add r7,r8,r7,ror#2 @ E+=K_00_19 + ldrb r12,[r1],#4 + orr r9,r9,r10,lsl#8 + eor r10,r5,r6 @ F_xx_xx + orr r9,r9,r11,lsl#16 + add r7,r7,r3,ror#27 @ E+=ROR(A,27) + orr r9,r9,r12,lsl#24 +#else + ldr r9,[r1],#4 @ handles unaligned + add r7,r8,r7,ror#2 @ E+=K_00_19 + eor r10,r5,r6 @ F_xx_xx + add r7,r7,r3,ror#27 @ E+=ROR(A,27) +#ifdef __ARMEL__ + rev r9,r9 @ byte swap +#endif +#endif + and r10,r4,r10,ror#2 + add r7,r7,r9 @ E+=X[i] + eor r10,r10,r6,ror#2 @ F_00_19(B,C,D) + str r9,[r14,#-4]! + add r7,r7,r10 @ E+=F_00_19(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r6,r8,r6,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r4,r5 @ F_xx_xx + mov r9,r9,ror#31 + add r6,r6,r7,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r3,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r6,r6,r9 @ E+=X[i] + eor r10,r10,r5,ror#2 @ F_00_19(B,C,D) + add r6,r6,r10 @ E+=F_00_19(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r5,r8,r5,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r3,r4 @ F_xx_xx + mov r9,r9,ror#31 + add r5,r5,r6,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r7,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r5,r5,r9 @ E+=X[i] + eor r10,r10,r4,ror#2 @ F_00_19(B,C,D) + add r5,r5,r10 @ E+=F_00_19(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r4,r8,r4,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r7,r3 @ F_xx_xx + mov r9,r9,ror#31 + add r4,r4,r5,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r6,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r4,r4,r9 @ E+=X[i] + eor r10,r10,r3,ror#2 @ F_00_19(B,C,D) + add r4,r4,r10 @ E+=F_00_19(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r3,r8,r3,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r6,r7 @ F_xx_xx + mov r9,r9,ror#31 + add r3,r3,r4,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r5,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r3,r3,r9 @ E+=X[i] + eor r10,r10,r7,ror#2 @ F_00_19(B,C,D) + add r3,r3,r10 @ E+=F_00_19(B,C,D) + + ldr r8,.LK_20_39 @ [+15+16*4] + sub sp,sp,#25*4 + cmn sp,#0 @ [+3], clear carry to denote 20_39 +.L_20_39_or_60_79: + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r7,r8,r7,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r5,r6 @ F_xx_xx + mov r9,r9,ror#31 + add r7,r7,r3,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r4,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r7,r7,r9 @ E+=X[i] + add r7,r7,r10 @ E+=F_20_39(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r6,r8,r6,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r4,r5 @ F_xx_xx + mov r9,r9,ror#31 + add r6,r6,r7,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r3,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r6,r6,r9 @ E+=X[i] + add r6,r6,r10 @ E+=F_20_39(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r5,r8,r5,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r3,r4 @ F_xx_xx + mov r9,r9,ror#31 + add r5,r5,r6,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r7,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r5,r5,r9 @ E+=X[i] + add r5,r5,r10 @ E+=F_20_39(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r4,r8,r4,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r7,r3 @ F_xx_xx + mov r9,r9,ror#31 + add r4,r4,r5,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r6,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r4,r4,r9 @ E+=X[i] + add r4,r4,r10 @ E+=F_20_39(B,C,D) + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r3,r8,r3,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r6,r7 @ F_xx_xx + mov r9,r9,ror#31 + add r3,r3,r4,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + eor r10,r5,r10,ror#2 @ F_xx_xx + @ F_xx_xx + add r3,r3,r9 @ E+=X[i] + add r3,r3,r10 @ E+=F_20_39(B,C,D) + teq r14,sp @ preserve carry + bne .L_20_39_or_60_79 @ [+((12+3)*5+2)*4] + bcs .L_done @ [+((12+3)*5+2)*4], spare 300 bytes + + ldr r8,.LK_40_59 + sub sp,sp,#20*4 @ [+2] +.L_40_59: + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r7,r8,r7,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r5,r6 @ F_xx_xx + mov r9,r9,ror#31 + add r7,r7,r3,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r4,r10,ror#2 @ F_xx_xx + and r11,r5,r6 @ F_xx_xx + add r7,r7,r9 @ E+=X[i] + add r7,r7,r10 @ E+=F_40_59(B,C,D) + add r7,r7,r11,ror#2 + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r6,r8,r6,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r4,r5 @ F_xx_xx + mov r9,r9,ror#31 + add r6,r6,r7,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r3,r10,ror#2 @ F_xx_xx + and r11,r4,r5 @ F_xx_xx + add r6,r6,r9 @ E+=X[i] + add r6,r6,r10 @ E+=F_40_59(B,C,D) + add r6,r6,r11,ror#2 + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r5,r8,r5,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r3,r4 @ F_xx_xx + mov r9,r9,ror#31 + add r5,r5,r6,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r7,r10,ror#2 @ F_xx_xx + and r11,r3,r4 @ F_xx_xx + add r5,r5,r9 @ E+=X[i] + add r5,r5,r10 @ E+=F_40_59(B,C,D) + add r5,r5,r11,ror#2 + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r4,r8,r4,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r7,r3 @ F_xx_xx + mov r9,r9,ror#31 + add r4,r4,r5,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r6,r10,ror#2 @ F_xx_xx + and r11,r7,r3 @ F_xx_xx + add r4,r4,r9 @ E+=X[i] + add r4,r4,r10 @ E+=F_40_59(B,C,D) + add r4,r4,r11,ror#2 + ldr r9,[r14,#15*4] + ldr r10,[r14,#13*4] + ldr r11,[r14,#7*4] + add r3,r8,r3,ror#2 @ E+=K_xx_xx + ldr r12,[r14,#2*4] + eor r9,r9,r10 + eor r11,r11,r12 @ 1 cycle stall + eor r10,r6,r7 @ F_xx_xx + mov r9,r9,ror#31 + add r3,r3,r4,ror#27 @ E+=ROR(A,27) + eor r9,r9,r11,ror#31 + str r9,[r14,#-4]! + and r10,r5,r10,ror#2 @ F_xx_xx + and r11,r6,r7 @ F_xx_xx + add r3,r3,r9 @ E+=X[i] + add r3,r3,r10 @ E+=F_40_59(B,C,D) + add r3,r3,r11,ror#2 + teq r14,sp + bne .L_40_59 @ [+((12+5)*5+2)*4] + + ldr r8,.LK_60_79 + sub sp,sp,#20*4 + cmp sp,#0 @ set carry to denote 60_79 + b .L_20_39_or_60_79 @ [+4], spare 300 bytes +.L_done: + add sp,sp,#80*4 @ "deallocate" stack frame + ldmia r0,{r8,r9,r10,r11,r12} + add r3,r8,r3 + add r4,r9,r4 + add r5,r10,r5,ror#2 + add r6,r11,r6,ror#2 + add r7,r12,r7,ror#2 + stmia r0,{r3,r4,r5,r6,r7} + teq r1,r2 + bne .Lloop @ [+18], total 1307 + +#if __ARM_ARCH__>=5 + ldmia sp!,{r4-r12,pc} +#else + ldmia sp!,{r4-r12,lr} + tst lr,#1 + moveq pc,lr @ be binary compatible with V4, yet + .word 0xe12fff1e @ interoperable with Thumb ISA:-) +#endif +.align 2 +.LK_00_19: .word 0x5a827999 +.LK_20_39: .word 0x6ed9eba1 +.LK_40_59: .word 0x8f1bbcdc +.LK_60_79: .word 0xca62c1d6 +.size sha1_block_data_order,.-sha1_block_data_order +.asciz "SHA1 block transform for ARMv4, CRYPTOGAMS by " +.align 2 diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c new file mode 100644 index 00000000000..76cd976230b --- /dev/null +++ b/arch/arm/crypto/sha1_glue.c @@ -0,0 +1,179 @@ +/* + * Cryptographic API. + * Glue code for the SHA1 Secure Hash Algorithm assembler implementation + * + * This file is based on sha1_generic.c and sha1_ssse3_glue.c + * + * Copyright (c) Alan Smithee. + * Copyright (c) Andrew McDonald + * Copyright (c) Jean-Francois Dive + * Copyright (c) Mathias Krause + * + * 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 + +struct SHA1_CTX { + uint32_t h0,h1,h2,h3,h4; + u64 count; + u8 data[SHA1_BLOCK_SIZE]; +}; + +asmlinkage void sha1_block_data_order(struct SHA1_CTX *digest, + const unsigned char *data, unsigned int rounds); + + +static int sha1_init(struct shash_desc *desc) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + memset(sctx, 0, sizeof(*sctx)); + sctx->h0 = SHA1_H0; + sctx->h1 = SHA1_H1; + sctx->h2 = SHA1_H2; + sctx->h3 = SHA1_H3; + sctx->h4 = SHA1_H4; + return 0; +} + + +static int __sha1_update(struct SHA1_CTX *sctx, const u8 *data, + unsigned int len, unsigned int partial) +{ + unsigned int done = 0; + + sctx->count += len; + + if (partial) { + done = SHA1_BLOCK_SIZE - partial; + memcpy(sctx->data + partial, data, done); + sha1_block_data_order(sctx, sctx->data, 1); + } + + if (len - done >= SHA1_BLOCK_SIZE) { + const unsigned int rounds = (len - done) / SHA1_BLOCK_SIZE; + sha1_block_data_order(sctx, data + done, rounds); + done += rounds * SHA1_BLOCK_SIZE; + } + + memcpy(sctx->data, data + done, len - done); + return 0; +} + + +static int sha1_update(struct shash_desc *desc, const u8 *data, + unsigned int len) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + unsigned int partial = sctx->count % SHA1_BLOCK_SIZE; + int res; + + /* Handle the fast case right here */ + if (partial + len < SHA1_BLOCK_SIZE) { + sctx->count += len; + memcpy(sctx->data + partial, data, len); + return 0; + } + res = __sha1_update(sctx, data, len, partial); + return res; +} + + +/* Add padding and return the message digest. */ +static int sha1_final(struct shash_desc *desc, u8 *out) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + unsigned int i, index, padlen; + __be32 *dst = (__be32 *)out; + __be64 bits; + static const u8 padding[SHA1_BLOCK_SIZE] = { 0x80, }; + + bits = cpu_to_be64(sctx->count << 3); + + /* Pad out to 56 mod 64 and append length */ + index = sctx->count % SHA1_BLOCK_SIZE; + padlen = (index < 56) ? (56 - index) : ((SHA1_BLOCK_SIZE+56) - index); + /* We need to fill a whole block for __sha1_update() */ + if (padlen <= 56) { + sctx->count += padlen; + memcpy(sctx->data + index, padding, padlen); + } else { + __sha1_update(sctx, padding, padlen, index); + } + __sha1_update(sctx, (const u8 *)&bits, sizeof(bits), 56); + + /* Store state in digest */ + for (i = 0; i < 5; i++) + dst[i] = cpu_to_be32(((u32 *)sctx)[i]); + + /* Wipe context */ + memset(sctx, 0, sizeof(*sctx)); + return 0; +} + + +static int sha1_export(struct shash_desc *desc, void *out) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + memcpy(out, sctx, sizeof(*sctx)); + return 0; +} + + +static int sha1_import(struct shash_desc *desc, const void *in) +{ + struct SHA1_CTX *sctx = shash_desc_ctx(desc); + memcpy(sctx, in, sizeof(*sctx)); + return 0; +} + + +static struct shash_alg alg = { + .digestsize = SHA1_DIGEST_SIZE, + .init = sha1_init, + .update = sha1_update, + .final = sha1_final, + .export = sha1_export, + .import = sha1_import, + .descsize = sizeof(struct SHA1_CTX), + .statesize = sizeof(struct SHA1_CTX), + .base = { + .cra_name = "sha1", + .cra_driver_name= "sha1-asm", + .cra_priority = 150, + .cra_flags = CRYPTO_ALG_TYPE_SHASH, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_module = THIS_MODULE, + } +}; + + +static int __init sha1_mod_init(void) +{ + return crypto_register_shash(&alg); +} + + +static void __exit sha1_mod_fini(void) +{ + crypto_unregister_shash(&alg); +} + + +module_init(sha1_mod_init); +module_exit(sha1_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("SHA1 Secure Hash Algorithm (ARM)"); +MODULE_ALIAS("sha1"); +MODULE_AUTHOR("David McCullough "); diff --git a/arch/arm/hotplug/Kconfig b/arch/arm/hotplug/Kconfig new file mode 100644 index 00000000000..e1ac913eddf --- /dev/null +++ b/arch/arm/hotplug/Kconfig @@ -0,0 +1,5 @@ +config INTELLI_PLUG + bool "Enable intelli-plug cpu hotplug driver" + default n + help + Generic Intelli-plug cpu hotplug driver for ARM SOCs diff --git a/arch/arm/hotplug/Makefile b/arch/arm/hotplug/Makefile new file mode 100644 index 00000000000..795b58d1fc3 --- /dev/null +++ b/arch/arm/hotplug/Makefile @@ -0,0 +1 @@ +obj-y := intelli_plug.o diff --git a/arch/arm/hotplug/intelli_plug.c b/arch/arm/hotplug/intelli_plug.c new file mode 100644 index 00000000000..11b09daac3a --- /dev/null +++ b/arch/arm/hotplug/intelli_plug.c @@ -0,0 +1,585 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * Copyright 2012~2014 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 +#include +#include + +#ifdef CONFIG_POWERSUSPEND +#include +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +#endif + +//#define DEBUG_INTELLI_PLUG +#undef DEBUG_INTELLI_PLUG + +#define INTELLI_PLUG_MAJOR_VERSION 3 +#define INTELLI_PLUG_MINOR_VERSION 8 + +#define DEF_SAMPLING_MS (268) + +#define DUAL_PERSISTENCE (2500 / DEF_SAMPLING_MS) +#define TRI_PERSISTENCE (1700 / DEF_SAMPLING_MS) +#define QUAD_PERSISTENCE (1000 / DEF_SAMPLING_MS) + +#define BUSY_PERSISTENCE (3500 / DEF_SAMPLING_MS) + +static DEFINE_MUTEX(intelli_plug_mutex); + +static struct delayed_work intelli_plug_work; +static struct delayed_work intelli_plug_boost; + +static struct workqueue_struct *intelliplug_wq; +static struct workqueue_struct *intelliplug_boost_wq; + +static unsigned int intelli_plug_active = 0; +module_param(intelli_plug_active, uint, 0644); + +static unsigned int touch_boost_active = 1; +module_param(touch_boost_active, uint, 0644); + +static unsigned int nr_run_profile_sel = 0; +module_param(nr_run_profile_sel, uint, 0644); + +//default to something sane rather than zero +static unsigned int sampling_time = DEF_SAMPLING_MS; + +static int persist_count = 0; + +static bool suspended = false; + +struct ip_cpu_info { + unsigned int sys_max; + unsigned int cur_max; + unsigned long cpu_nr_running; +}; + +static DEFINE_PER_CPU(struct ip_cpu_info, ip_info); + +static unsigned int screen_off_max = UINT_MAX; +module_param(screen_off_max, uint, 0644); + +#define CAPACITY_RESERVE 50 + +#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \ +defined(CONFIG_ARCH_MSM8974) +#define THREAD_CAPACITY (339 - CAPACITY_RESERVE) +#elif defined(CONFIG_ARCH_MSM8226) || defined (CONFIG_ARCH_MSM8926) || \ +defined (CONFIG_ARCH_MSM8610) || defined (CONFIG_ARCH_MSM8228) +#define THREAD_CAPACITY (190 - CAPACITY_RESERVE) +#else +#define THREAD_CAPACITY (250 - CAPACITY_RESERVE) +#endif + +#define MULT_FACTOR 4 +#define DIV_FACTOR 100000 +#define NR_FSHIFT 3 + +static unsigned int nr_fshift = NR_FSHIFT; + +static unsigned int nr_run_thresholds_balance[] = { + (THREAD_CAPACITY * 625 * MULT_FACTOR) / DIV_FACTOR, + (THREAD_CAPACITY * 875 * MULT_FACTOR) / DIV_FACTOR, + (THREAD_CAPACITY * 1125 * MULT_FACTOR) / DIV_FACTOR, + UINT_MAX +}; + +static unsigned int nr_run_thresholds_performance[] = { + (THREAD_CAPACITY * 380 * MULT_FACTOR) / DIV_FACTOR, + (THREAD_CAPACITY * 625 * MULT_FACTOR) / DIV_FACTOR, + (THREAD_CAPACITY * 875 * MULT_FACTOR) / DIV_FACTOR, + UINT_MAX +}; + +static unsigned int nr_run_thresholds_conservative[] = { + (THREAD_CAPACITY * 875 * MULT_FACTOR) / DIV_FACTOR, + (THREAD_CAPACITY * 1625 * MULT_FACTOR) / DIV_FACTOR, + (THREAD_CAPACITY * 2125 * MULT_FACTOR) / DIV_FACTOR, + UINT_MAX +}; + +static unsigned int nr_run_thresholds_eco[] = { + (THREAD_CAPACITY * 380 * MULT_FACTOR) / DIV_FACTOR, + UINT_MAX +}; + +static unsigned int nr_run_thresholds_eco_extreme[] = { + (THREAD_CAPACITY * 750 * MULT_FACTOR) / DIV_FACTOR, + UINT_MAX +}; + +static unsigned int nr_run_thresholds_disable[] = { + 0, 0, 0, UINT_MAX +}; + +static unsigned int *nr_run_profiles[] = { + nr_run_thresholds_balance, + nr_run_thresholds_performance, + nr_run_thresholds_conservative, + nr_run_thresholds_eco, + nr_run_thresholds_eco_extreme, + nr_run_thresholds_disable, +}; + +#define NR_RUN_ECO_MODE_PROFILE 3 +#define NR_RUN_HYSTERESIS_QUAD 8 +#define NR_RUN_HYSTERESIS_DUAL 4 + +#define CPU_NR_THRESHOLD ((THREAD_CAPACITY << 1) + (THREAD_CAPACITY / 2)) + +static unsigned int nr_possible_cores; +module_param(nr_possible_cores, uint, 0444); + +static unsigned int cpu_nr_run_threshold = CPU_NR_THRESHOLD; +module_param(cpu_nr_run_threshold, uint, 0644); + +static unsigned int nr_run_hysteresis = NR_RUN_HYSTERESIS_QUAD; +module_param(nr_run_hysteresis, uint, 0644); + +static unsigned int nr_run_last; + +extern unsigned long avg_nr_running(void); +extern unsigned long avg_cpu_nr_running(unsigned int cpu); + +static unsigned int calculate_thread_stats(void) +{ + unsigned int avg_nr_run = avg_nr_running(); + unsigned int nr_run; + unsigned int threshold_size; + unsigned int *current_profile; + + current_profile = nr_run_profiles[nr_run_profile_sel]; + if (num_possible_cpus() > 2) { + if (nr_run_profile_sel >= NR_RUN_ECO_MODE_PROFILE) + threshold_size = + ARRAY_SIZE(nr_run_thresholds_eco); + else + threshold_size = + ARRAY_SIZE(nr_run_thresholds_balance); + } else + threshold_size = + ARRAY_SIZE(nr_run_thresholds_eco); + + if (nr_run_profile_sel >= NR_RUN_ECO_MODE_PROFILE) + nr_fshift = 1; + else + nr_fshift = num_possible_cpus() - 1; + + for (nr_run = 1; nr_run < threshold_size; nr_run++) { + unsigned int nr_threshold; + nr_threshold = current_profile[nr_run - 1]; + + if (nr_run_last <= nr_run) + nr_threshold += nr_run_hysteresis; + if (avg_nr_run <= (nr_threshold << (FSHIFT - nr_fshift))) + break; + } + nr_run_last = nr_run; + + return nr_run; +} + +static void __cpuinit intelli_plug_boost_fn(struct work_struct *work) +{ + + int nr_cpus = num_online_cpus(); + + if (intelli_plug_active) + if (touch_boost_active) + if (nr_cpus < 2) + cpu_up(1); +} + +/* +static int cmp_nr_running(const void *a, const void *b) +{ + return *(unsigned long *)a - *(unsigned long *)b; +} +*/ + +static void update_per_cpu_stat(void) +{ + unsigned int cpu; + struct ip_cpu_info *l_ip_info; + + for_each_online_cpu(cpu) { + l_ip_info = &per_cpu(ip_info, cpu); + l_ip_info->cpu_nr_running = avg_cpu_nr_running(cpu); +#ifdef DEBUG_INTELLI_PLUG + pr_info("cpu %u nr_running => %lu\n", cpu, + l_ip_info->cpu_nr_running); +#endif + } +} + +static void unplug_cpu(int min_active_cpu) +{ + unsigned int cpu; + struct ip_cpu_info *l_ip_info; + int l_nr_threshold; + + for_each_online_cpu(cpu) { + l_nr_threshold = + cpu_nr_run_threshold << 1 / (num_online_cpus()); + if (cpu == 0) + continue; + l_ip_info = &per_cpu(ip_info, cpu); + if (cpu > min_active_cpu) + if (l_ip_info->cpu_nr_running < l_nr_threshold) + cpu_down(cpu); + } +} + +static void __cpuinit intelli_plug_work_fn(struct work_struct *work) +{ + unsigned int nr_run_stat; + unsigned int cpu_count = 0; + unsigned int nr_cpus = 0; + + int i; + + if (intelli_plug_active) { + nr_run_stat = calculate_thread_stats(); + update_per_cpu_stat(); +#ifdef DEBUG_INTELLI_PLUG + pr_info("nr_run_stat: %u\n", nr_run_stat); +#endif + cpu_count = nr_run_stat; + nr_cpus = num_online_cpus(); + + if (!suspended) { + + if (persist_count > 0) + persist_count--; + + switch (cpu_count) { + case 1: + if (persist_count == 0) { + //take down everyone + unplug_cpu(0); + } +#ifdef DEBUG_INTELLI_PLUG + pr_info("case 1: %u\n", persist_count); +#endif + break; + case 2: + if (persist_count == 0) + persist_count = DUAL_PERSISTENCE; + if (nr_cpus < 2) { + for (i = 1; i < cpu_count; i++) + cpu_up(i); + } else { + unplug_cpu(1); + } +#ifdef DEBUG_INTELLI_PLUG + pr_info("case 2: %u\n", persist_count); +#endif + break; + case 3: + if (persist_count == 0) + persist_count = TRI_PERSISTENCE; + if (nr_cpus < 3) { + for (i = 1; i < cpu_count; i++) + cpu_up(i); + } else { + unplug_cpu(2); + } +#ifdef DEBUG_INTELLI_PLUG + pr_info("case 3: %u\n", persist_count); +#endif + break; + case 4: + if (persist_count == 0) + persist_count = QUAD_PERSISTENCE; + if (nr_cpus < 4) + for (i = 1; i < cpu_count; i++) + cpu_up(i); +#ifdef DEBUG_INTELLI_PLUG + pr_info("case 4: %u\n", persist_count); +#endif + break; + default: + pr_err("Run Stat Error: Bad value %u\n", nr_run_stat); + break; + } + } +#ifdef DEBUG_INTELLI_PLUG + else + pr_info("intelli_plug is suspened!\n"); +#endif + } + queue_delayed_work_on(0, intelliplug_wq, &intelli_plug_work, + msecs_to_jiffies(sampling_time)); +} + +#if defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) +static void screen_off_limit(bool on) +{ + unsigned int cpu; + struct cpufreq_policy *policy; + struct ip_cpu_info *l_ip_info; + + /* not active, so exit */ + if (screen_off_max == UINT_MAX) + return; + + for_each_online_cpu(cpu) { + l_ip_info = &per_cpu(ip_info, cpu); + policy = cpufreq_cpu_get(0); + + if (on) { + /* save current instance */ + l_ip_info->cur_max = policy->max; + policy->max = screen_off_max; + policy->cpuinfo.max_freq = screen_off_max; +#ifdef DEBUG_INTELLI_PLUG + pr_info("cpuinfo max is (on): %u %u\n", + policy->cpuinfo.max_freq, l_ip_info->sys_max); +#endif + } else { + /* restore */ + if (cpu != 0) { + l_ip_info = &per_cpu(ip_info, 0); + } + policy->cpuinfo.max_freq = l_ip_info->sys_max; + policy->max = l_ip_info->cur_max; +#ifdef DEBUG_INTELLI_PLUG + pr_info("cpuinfo max is (off): %u %u\n", + policy->cpuinfo.max_freq, l_ip_info->sys_max); +#endif + } + cpufreq_update_policy(cpu); + } +} + +#ifdef CONFIG_POWERSUSPEND +static void intelli_plug_suspend(struct power_suspend *handler) +#else +static void intelli_plug_suspend(struct early_suspend *handler) +#endif +{ + if (intelli_plug_active) { + int cpu; + + flush_workqueue(intelliplug_wq); + + mutex_lock(&intelli_plug_mutex); + suspended = true; + screen_off_limit(true); + mutex_unlock(&intelli_plug_mutex); + + // put rest of the cores to sleep unconditionally! + for_each_online_cpu(cpu) { + if (cpu != 0) + cpu_down(cpu); + } + } +} + +static void wakeup_boost(void) +{ + unsigned int cpu; + struct cpufreq_policy *policy; + struct ip_cpu_info *l_ip_info; + + for_each_online_cpu(cpu) { + policy = cpufreq_cpu_get(0); + l_ip_info = &per_cpu(ip_info, 0); + policy->cur = l_ip_info->cur_max; + cpufreq_update_policy(cpu); + } +} + +#ifdef CONFIG_POWERSUSPEND +static void __cpuinit intelli_plug_resume(struct power_suspend *handler) +#else +static void __cpuinit intelli_plug_resume(struct early_suspend *handler) +#endif +{ + + if (intelli_plug_active) { + int cpu; + + mutex_lock(&intelli_plug_mutex); + /* keep cores awake long enough for faster wake up */ + persist_count = BUSY_PERSISTENCE; + suspended = false; + mutex_unlock(&intelli_plug_mutex); + + for_each_possible_cpu(cpu) { + if (cpu == 0) + continue; + cpu_up(cpu); + } + + wakeup_boost(); + screen_off_limit(false); + } + queue_delayed_work_on(0, intelliplug_wq, &intelli_plug_work, + msecs_to_jiffies(10)); +} +#endif + +#ifdef CONFIG_POWERSUSPEND +static struct power_suspend intelli_plug_power_suspend_driver = { + .suspend = intelli_plug_suspend, + .resume = intelli_plug_resume, +}; +#endif /* CONFIG_POWERSUSPEND */ + +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct early_suspend intelli_plug_early_suspend_driver = { + .level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 10, + .suspend = intelli_plug_suspend, + .resume = intelli_plug_resume, +}; +#endif /* CONFIG_HAS_EARLYSUSPEND */ + +static void intelli_plug_input_event(struct input_handle *handle, + unsigned int type, unsigned int code, int value) +{ +#ifdef DEBUG_INTELLI_PLUG + pr_info("intelli_plug touched!\n"); +#endif + queue_delayed_work_on(0, intelliplug_wq, &intelli_plug_boost, + msecs_to_jiffies(10)); +} + +static int intelli_plug_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "intelliplug"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + pr_info("%s found and connected!\n", dev->name); + return 0; +err1: + input_unregister_handle(handle); +err2: + kfree(handle); + return error; +} + +static void intelli_plug_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id intelli_plug_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, /* multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, + }, /* touchpad */ + { }, +}; + +static struct input_handler intelli_plug_input_handler = { + .event = intelli_plug_input_event, + .connect = intelli_plug_input_connect, + .disconnect = intelli_plug_input_disconnect, + .name = "intelliplug_handler", + .id_table = intelli_plug_ids, +}; + +int __init intelli_plug_init(void) +{ + int rc; +#if defined (CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + struct cpufreq_policy *policy; + struct ip_cpu_info *l_ip_info; +#endif + + nr_possible_cores = num_possible_cpus(); + + pr_info("intelli_plug: version %d.%d by faux123\n", + INTELLI_PLUG_MAJOR_VERSION, + INTELLI_PLUG_MINOR_VERSION); + + if (nr_possible_cores > 2) { + nr_run_hysteresis = NR_RUN_HYSTERESIS_QUAD; + nr_run_profile_sel = 0; + } else { + nr_run_hysteresis = NR_RUN_HYSTERESIS_DUAL; + nr_run_profile_sel = NR_RUN_ECO_MODE_PROFILE; + } + +#if defined (CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + l_ip_info = &per_cpu(ip_info, 0); + policy = cpufreq_cpu_get(0); + l_ip_info->sys_max = policy->cpuinfo.max_freq; + l_ip_info->cur_max = policy->max; +#endif + + rc = input_register_handler(&intelli_plug_input_handler); +#ifdef CONFIG_POWERSUSPEND + register_power_suspend(&intelli_plug_power_suspend_driver); +#endif +#ifdef CONFIG_HAS_EARLYSUSPEND + register_early_suspend(&intelli_plug_early_suspend_driver); +#endif + intelliplug_wq = alloc_workqueue("intelliplug", + WQ_HIGHPRI | WQ_UNBOUND, 1); + intelliplug_boost_wq = alloc_workqueue("iplug_boost", + WQ_HIGHPRI | WQ_UNBOUND, 1); + INIT_DELAYED_WORK(&intelli_plug_work, intelli_plug_work_fn); + INIT_DELAYED_WORK(&intelli_plug_boost, intelli_plug_boost_fn); + queue_delayed_work_on(0, intelliplug_wq, &intelli_plug_work, + msecs_to_jiffies(10)); + + return 0; +} + +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("'intell_plug' - An intelligent cpu hotplug driver for " + "Low Latency Frequency Transition capable processors"); +MODULE_LICENSE("GPL"); + +late_initcall(intelli_plug_init); diff --git a/arch/arm/include/asm/assembler.h b/arch/arm/include/asm/assembler.h index 03fb93621d0..5c8b3bf4d82 100644 --- a/arch/arm/include/asm/assembler.h +++ b/arch/arm/include/asm/assembler.h @@ -320,4 +320,12 @@ .size \name , . - \name .endm + .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req +#ifndef CONFIG_CPU_USE_DOMAINS + adds \tmp, \addr, #\size - 1 + sbcccs \tmp, \tmp, \limit + bcs \bad +#endif + .endm + #endif /* __ASM_ASSEMBLER_H__ */ diff --git a/arch/arm/include/asm/cacheflush.h b/arch/arm/include/asm/cacheflush.h index d021905cfd1..895eb978a07 100644 --- a/arch/arm/include/asm/cacheflush.h +++ b/arch/arm/include/asm/cacheflush.h @@ -50,6 +50,13 @@ * * Unconditionally clean and invalidate the entire cache. * + * flush_kern_louis() + * + * Flush data cache levels up to the level of unification + * inner shareable and invalidate the I-cache. + * Only needed from v7 onwards, falls back to flush_cache_all() + * for all other processor versions. + * * flush_user_all() * * Clean and invalidate all user space cache entries @@ -113,6 +120,7 @@ struct cpu_cache_fns { void (*flush_icache_all)(void); void (*flush_kern_all)(void); + void (*flush_kern_louis)(void); void (*flush_user_all)(void); void (*flush_user_range)(unsigned long, unsigned long, unsigned int); @@ -137,6 +145,7 @@ extern struct cpu_cache_fns cpu_cache; #define __cpuc_flush_icache_all cpu_cache.flush_icache_all #define __cpuc_flush_kern_all cpu_cache.flush_kern_all +#define __cpuc_flush_kern_louis cpu_cache.flush_kern_louis #define __cpuc_flush_user_all cpu_cache.flush_user_all #define __cpuc_flush_user_range cpu_cache.flush_user_range #define __cpuc_coherent_kern_range cpu_cache.coherent_kern_range @@ -159,6 +168,7 @@ extern struct cpu_cache_fns cpu_cache; extern void __cpuc_flush_icache_all(void); extern void __cpuc_flush_kern_all(void); +extern void __cpuc_flush_kern_louis(void); extern void __cpuc_flush_user_all(void); extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int); extern void __cpuc_coherent_kern_range(unsigned long, unsigned long); @@ -226,6 +236,11 @@ static inline void __flush_icache_all(void) __flush_icache_preferred(); } +/* + * Flush caches up to Level of Unification Inner Shareable + */ +#define flush_cache_louis() __cpuc_flush_kern_louis() + #define flush_cache_all() __cpuc_flush_kern_all() static inline void vivt_flush_cache_mm(struct mm_struct *mm) diff --git a/arch/arm/include/asm/glue-cache.h b/arch/arm/include/asm/glue-cache.h index 7e30874377e..2d6a7de87a8 100644 --- a/arch/arm/include/asm/glue-cache.h +++ b/arch/arm/include/asm/glue-cache.h @@ -132,6 +132,7 @@ #ifndef MULTI_CACHE #define __cpuc_flush_icache_all __glue(_CACHE,_flush_icache_all) #define __cpuc_flush_kern_all __glue(_CACHE,_flush_kern_cache_all) +#define __cpuc_flush_kern_louis __glue(_CACHE,_flush_kern_cache_louis) #define __cpuc_flush_user_all __glue(_CACHE,_flush_user_cache_all) #define __cpuc_flush_user_range __glue(_CACHE,_flush_user_cache_range) #define __cpuc_coherent_kern_range __glue(_CACHE,_coherent_kern_range) diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index 42fef7cca6f..c1295c43453 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -68,15 +68,18 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); #define __raw_writeb_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v)) #define __raw_writew_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)) #define __raw_writel_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v)) +#define __raw_writell_no_log(v, a) (__chk_io_ptr(a), *(volatile unsigned long long __force *)(a) = (v)) #define __raw_writeb(v, a) __raw_write_logged((v), (a), b) #define __raw_writew(v, a) __raw_write_logged((v), (a), w) #define __raw_writel(v, a) __raw_write_logged((v), (a), l) +#define __raw_writell(v, a) __raw_write_logged((v), (a), ll) #define __raw_readb_no_log(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a)) #define __raw_readw_no_log(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) #define __raw_readl_no_log(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a)) +#define __raw_readll_no_log(a) (__chk_io_ptr(a), *(volatile unsigned long long __force *)(a)) #define __raw_read_logged(a, _l, _t) ({ \ unsigned _t __a; \ @@ -94,6 +97,7 @@ extern void __raw_readsl(const void __iomem *addr, void *data, int longlen); #define __raw_readb(a) __raw_read_logged((a), b, char) #define __raw_readw(a) __raw_read_logged((a), w, short) #define __raw_readl(a) __raw_read_logged((a), l, int) +#define __raw_readll(a) __raw_read_logged((a), ll, long long) /* * Architecture ioremap implementation. @@ -268,20 +272,35 @@ extern void _memset_io(volatile void __iomem *, int, size_t); __raw_readw(c)); __r; }) #define readl_relaxed(c) ({ u32 __r = le32_to_cpu((__force __le32) \ __raw_readl(c)); __r; }) +#define readll_relaxed(c) ({ u64 __r = le64_to_cpu((__force __le64) \ + __raw_readll(c)); __r; }) +#define readl_relaxed_no_log(c) ({ u32 __r = le32_to_cpu((__force __le32) \ + __raw_readl_no_log(c)); __r; }) +#define readll_relaxed_no_log(c) ({ u64 __r = le64_to_cpu((__force __le64) \ + __raw_readll_no_log(c)); __r; }) + #define writeb_relaxed(v,c) ((void)__raw_writeb(v,c)) #define writew_relaxed(v,c) ((void)__raw_writew((__force u16) \ cpu_to_le16(v),c)) #define writel_relaxed(v,c) ((void)__raw_writel((__force u32) \ cpu_to_le32(v),c)) +#define writell_relaxed(v, c) ((void)__raw_writell((__force u64) \ + cpu_to_le64(v), c)) +#define writel_relaxed_no_log(v, c) ((void)__raw_writel_no_log((__force u32) \ + cpu_to_le32(v), c)) +#define writell_relaxed_no_log(v, c) ((void)__raw_writell_no_log((__force u64) \ + cpu_to_le64(v), c)) #define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; }) #define readw(c) ({ u16 __v = readw_relaxed(c); __iormb(); __v; }) #define readl(c) ({ u32 __v = readl_relaxed(c); __iormb(); __v; }) +#define readll(c) ({ u64 __v = readll_relaxed(c); __iormb(); __v; }) #define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); }) #define writew(v,c) ({ __iowmb(); writew_relaxed(v,c); }) #define writel(v,c) ({ __iowmb(); writel_relaxed(v,c); }) +#define writell(v, c) ({ __iowmb(); writell_relaxed(v, c); }) #define readsb(p,d,l) __raw_readsb(p,d,l) #define readsw(p,d,l) __raw_readsw(p,d,l) @@ -311,22 +330,26 @@ extern void _memset_io(volatile void __iomem *, int, size_t); #define iounmap __arm_iounmap /* - * io{read,write}{8,16,32} macros + * io{read,write}{8,16,32,64} macros */ #ifndef ioread8 #define ioread8(p) ({ unsigned int __v = __raw_readb(p); __iormb(); __v; }) #define ioread16(p) ({ unsigned int __v = le16_to_cpu((__force __le16)__raw_readw(p)); __iormb(); __v; }) #define ioread32(p) ({ unsigned int __v = le32_to_cpu((__force __le32)__raw_readl(p)); __iormb(); __v; }) +#define ioread64(p) ({ unsigned int __v = le64_to_cpu((__force __le64)__raw_readll(p)); __iormb(); __v; }) #define ioread16be(p) ({ unsigned int __v = be16_to_cpu((__force __be16)__raw_readw(p)); __iormb(); __v; }) #define ioread32be(p) ({ unsigned int __v = be32_to_cpu((__force __be32)__raw_readl(p)); __iormb(); __v; }) +#define ioread64be(p) ({ unsigned int __v = be64_to_cpu((__force __be64)__raw_readll(p)); __iormb(); __v; }) #define iowrite8(v,p) ({ __iowmb(); (void)__raw_writeb(v, p); }) #define iowrite16(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_le16(v), p); }) #define iowrite32(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_le32(v), p); }) +#define iowrite64(v, p) ({ __iowmb(); (void)__raw_writell((__force __u64)cpu_to_le64(v), p); }) #define iowrite16be(v,p) ({ __iowmb(); (void)__raw_writew((__force __u16)cpu_to_be16(v), p); }) #define iowrite32be(v,p) ({ __iowmb(); (void)__raw_writel((__force __u32)cpu_to_be32(v), p); }) +#define iowrite64be(v, p) ({ __iowmb(); (void)__raw_writell((__force __u64)cpu_to_be64(v), p); }) #define ioread8_rep(p,d,c) __raw_readsb(p,d,c) #define ioread16_rep(p,d,c) __raw_readsw(p,d,c) diff --git a/arch/arm/include/asm/kexec.h b/arch/arm/include/asm/kexec.h index c2b9b4bdec0..564c55b394e 100644 --- a/arch/arm/include/asm/kexec.h +++ b/arch/arm/include/asm/kexec.h @@ -17,6 +17,10 @@ #define KEXEC_ARM_ATAGS_OFFSET 0x1000 #define KEXEC_ARM_ZIMAGE_OFFSET 0x8000 +#ifdef CONFIG_KEXEC_HARDBOOT + #define KEXEC_HB_PAGE_MAGIC 0x4a5db007 +#endif + #ifndef __ASSEMBLY__ /** @@ -53,6 +57,10 @@ static inline void crash_setup_regs(struct pt_regs *newregs, /* Function pointer to optional machine-specific reinitialization */ extern void (*kexec_reinit)(void); +#ifdef CONFIG_KEXEC_HARDBOOT +extern void (*kexec_hardboot_hook)(void); +#endif + #endif /* __ASSEMBLY__ */ #endif /* CONFIG_KEXEC */ diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index 7b6f42a4b0b..2512e1b7145 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h @@ -101,7 +101,7 @@ extern pgprot_t pgprot_kernel; __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_BUFFERABLE) #define pgprot_stronglyordered(prot) \ - __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED) + __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_UNCACHED | L_PTE_XN) #define pgprot_device(prot) \ __pgprot_modify(prot, L_PTE_MT_MASK, L_PTE_MT_DEV_NONSHARED) diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index 58b8b84adcd..8aae906c118 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -6,6 +6,7 @@ #include struct cputopo_arm { + int id; int thread_id; int core_id; int socket_id; @@ -27,11 +28,55 @@ void init_cpu_topology(void); void store_cpu_topology(unsigned int cpuid); const struct cpumask *cpu_coregroup_mask(int cpu); +void set_power_scale(unsigned int cpu, unsigned int power); +int topology_register_notifier(struct notifier_block *nb); +int topology_unregister_notifier(struct notifier_block *nb); + #else static inline void init_cpu_topology(void) { } static inline void store_cpu_topology(unsigned int cpuid) { } +static inline void set_power_scale(unsigned int cpu, unsigned int power) { } +static inline int topology_register_notifier(struct notifier_block *nb) { } +static inline int topology_unregister_notifier(struct notifier_block *nb) { } + +#endif + +/* Topology notifier event */ +#define TOPOLOGY_POSTCHANGE 0 + +/* Common values for CPUs */ +#ifndef SD_CPU_INIT +#define SD_CPU_INIT (struct sched_domain) { \ + .min_interval = 1, \ + .max_interval = 4, \ + .busy_factor = 64, \ + .imbalance_pct = 125, \ + .cache_nice_tries = 1, \ + .busy_idx = 2, \ + .idle_idx = 1, \ + .newidle_idx = 0, \ + .wake_idx = 0, \ + .forkexec_idx = 0, \ + \ + .flags = 1*SD_LOAD_BALANCE \ + | 1*SD_BALANCE_NEWIDLE \ + | 1*SD_BALANCE_EXEC \ + | 1*SD_BALANCE_FORK \ + | 0*SD_BALANCE_WAKE \ + | 1*SD_WAKE_AFFINE \ + | 0*SD_PREFER_LOCAL \ + | 0*SD_SHARE_CPUPOWER \ + | 0*SD_SHARE_PKG_RESOURCES \ + | 0*SD_SERIALIZE \ + | arch_sd_sibling_asym_packing() \ + | sd_balance_for_package_power() \ + | sd_power_saving_flags() \ + , \ + .last_balance = jiffies, \ + .balance_interval = 1, \ +} #endif #include diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index 71f6536d17a..0a070e98625 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -101,28 +101,39 @@ extern int __get_user_1(void *); extern int __get_user_2(void *); extern int __get_user_4(void *); -#define __get_user_x(__r2,__p,__e,__s,__i...) \ +#define __GUP_CLOBBER_1 "lr", "cc" +#ifdef CONFIG_CPU_USE_DOMAINS +#define __GUP_CLOBBER_2 "ip", "lr", "cc" +#else +#define __GUP_CLOBBER_2 "lr", "cc" +#endif +#define __GUP_CLOBBER_4 "lr", "cc" + +#define __get_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%1", "r2") \ + __asmeq("%3", "r1") \ "bl __get_user_" #__s \ : "=&r" (__e), "=r" (__r2) \ - : "0" (__p) \ - : __i, "cc") + : "0" (__p), "r" (__l) \ + : __GUP_CLOBBER_##__s) #define get_user(x,p) \ ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ register unsigned long __r2 asm("r2"); \ + register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __get_user_x(__r2, __p, __e, 1, "lr"); \ - break; \ + __get_user_x(__r2, __p, __e, __l, 1); \ + break; \ case 2: \ - __get_user_x(__r2, __p, __e, 2, "r3", "lr"); \ + __get_user_x(__r2, __p, __e, __l, 2); \ break; \ case 4: \ - __get_user_x(__r2, __p, __e, 4, "lr"); \ + __get_user_x(__r2, __p, __e, __l, 4); \ break; \ default: __e = __get_user_bad(); break; \ } \ @@ -135,31 +146,34 @@ extern int __put_user_2(void *, unsigned int); extern int __put_user_4(void *, unsigned int); extern int __put_user_8(void *, unsigned long long); -#define __put_user_x(__r2,__p,__e,__s) \ +#define __put_user_x(__r2,__p,__e,__l,__s) \ __asm__ __volatile__ ( \ __asmeq("%0", "r0") __asmeq("%2", "r2") \ + __asmeq("%3", "r1") \ "bl __put_user_" #__s \ : "=&r" (__e) \ - : "0" (__p), "r" (__r2) \ + : "0" (__p), "r" (__r2), "r" (__l) \ : "ip", "lr", "cc") #define put_user(x,p) \ ({ \ + unsigned long __limit = current_thread_info()->addr_limit - 1; \ register const typeof(*(p)) __r2 asm("r2") = (x); \ register const typeof(*(p)) __user *__p asm("r0") = (p);\ + register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ switch (sizeof(*(__p))) { \ case 1: \ - __put_user_x(__r2, __p, __e, 1); \ + __put_user_x(__r2, __p, __e, __l, 1); \ break; \ case 2: \ - __put_user_x(__r2, __p, __e, 2); \ + __put_user_x(__r2, __p, __e, __l, 2); \ break; \ case 4: \ - __put_user_x(__r2, __p, __e, 4); \ + __put_user_x(__r2, __p, __e, __l, 4); \ break; \ case 8: \ - __put_user_x(__r2, __p, __e, 8); \ + __put_user_x(__r2, __p, __e, __l, 8); \ break; \ default: __e = __put_user_bad(); break; \ } \ diff --git a/arch/arm/kernel/atags.c b/arch/arm/kernel/atags.c index 42a1a1415fa..0cfd7e48038 100644 --- a/arch/arm/kernel/atags.c +++ b/arch/arm/kernel/atags.c @@ -4,29 +4,45 @@ #include #include +/* + * [PATCH] Backport arch/arm/kernel/atags.c from 3.10 + * + * There is a bug in older kernels, causing kexec-tools binary to + * only read first 1024 bytes from /proc/atags. I guess the bug is + * somewhere in /fs/proc/, since I don't think the callback in atags.c + * does something wrong. It might affect all procfs files using that + * old read callback instead of fops. Doesn't matter though, since it + * was accidentally fixed when 3.10 removed it. + * + * This might have no particular effect on real devices, because the + * atags _might_ be organized "just right", but it might be very hard + * to track down on a device where it causes problems. + * + */ + struct buffer { size_t size; char data[]; }; -static int -read_buffer(char* page, char** start, off_t off, int count, - int* eof, void* data) -{ - struct buffer *buffer = (struct buffer *)data; - - if (off >= buffer->size) { - *eof = 1; - return 0; - } - - count = min((int) (buffer->size - off), count); +static struct buffer* atags_buffer = NULL; - memcpy(page, &buffer->data[off], count); - - return count; +static ssize_t atags_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + // These are introduced in kernel 3.10. I don't want to backport + // the whole chunk, and other things (ram_console) use static + // variable to keep data too, so I guess it's okay. + //struct buffer *b = PDE_DATA(file_inode(file)); + struct buffer *b = atags_buffer; + return simple_read_from_buffer(buf, count, ppos, b->data, b->size); } +static const struct file_operations atags_fops = { + .read = atags_read, + .llseek = default_llseek, +}; + #define BOOT_PARAMS_SIZE 1536 static char __initdata atags_copy[BOOT_PARAMS_SIZE]; @@ -66,12 +82,13 @@ static int __init init_atags_procfs(void) b->size = size; memcpy(b->data, atags_copy, size); - tags_entry = create_proc_read_entry("atags", 0400, - NULL, read_buffer, b); + tags_entry = proc_create_data("atags", 0400, NULL, &atags_fops, b); if (!tags_entry) goto nomem; + atags_buffer = b; + return 0; nomem: diff --git a/arch/arm/kernel/machine_kexec.c b/arch/arm/kernel/machine_kexec.c index c355aebdf2d..449394d81fb 100644 --- a/arch/arm/kernel/machine_kexec.c +++ b/arch/arm/kernel/machine_kexec.c @@ -14,6 +14,7 @@ #include #include #include +#include extern const unsigned char relocate_new_kernel[]; extern const unsigned int relocate_new_kernel_size; @@ -22,6 +23,10 @@ extern unsigned long kexec_start_address; extern unsigned long kexec_indirection_page; extern unsigned long kexec_mach_type; extern unsigned long kexec_boot_atags; +#ifdef CONFIG_KEXEC_HARDBOOT +extern unsigned long kexec_hardboot; +void (*kexec_hardboot_hook)(void); +#endif static atomic_t waiting_for_crash_ipi; @@ -120,10 +125,13 @@ void machine_kexec(struct kimage *image) reboot_code_buffer = page_address(image->control_code_page); /* Prepare parameters for reboot_code_buffer*/ - kexec_start_address = image->start; - kexec_indirection_page = page_list; - kexec_mach_type = machine_arch_type; - kexec_boot_atags = image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET; + mem_text_write_kernel_word(&kexec_start_address, image->start); + mem_text_write_kernel_word(&kexec_indirection_page, page_list); + mem_text_write_kernel_word(&kexec_mach_type, machine_arch_type); + mem_text_write_kernel_word(&kexec_boot_atags, image->start - KEXEC_ARM_ZIMAGE_OFFSET + KEXEC_ARM_ATAGS_OFFSET); +#ifdef CONFIG_KEXEC_HARDBOOT + mem_text_write_kernel_word(&kexec_hardboot, image->hardboot); +#endif /* copy our kernel relocation code to the control code page */ memcpy(reboot_code_buffer, @@ -137,5 +145,11 @@ void machine_kexec(struct kimage *image) if (kexec_reinit) kexec_reinit(); +#ifdef CONFIG_KEXEC_HARDBOOT + /* Run any final machine-specific shutdown code. */ + if (image->hardboot && kexec_hardboot_hook) + kexec_hardboot_hook(); +#endif + soft_restart(reboot_code_buffer_phys); } diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c index 8fb93d07de0..aed4443011a 100644 --- a/arch/arm/kernel/perf_event.c +++ b/arch/arm/kernel/perf_event.c @@ -338,6 +338,9 @@ validate_event(struct pmu_hw_events *hw_events, struct hw_perf_event fake_event = event->hw; struct pmu *leader_pmu = event->group_leader->pmu; + if (is_software_event(event)) + return 1; + if (event->pmu != leader_pmu || event->state <= PERF_EVENT_STATE_OFF) return 1; diff --git a/arch/arm/kernel/relocate_kernel.S b/arch/arm/kernel/relocate_kernel.S index d0cdedf4864..f5342939d95 100644 --- a/arch/arm/kernel/relocate_kernel.S +++ b/arch/arm/kernel/relocate_kernel.S @@ -4,6 +4,15 @@ #include +#ifdef CONFIG_KEXEC_HARDBOOT +#include +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) + #include +#elif defined(CONFIG_ARCH_APQ8064) + #include +#endif +#endif + .globl relocate_new_kernel relocate_new_kernel: @@ -52,6 +61,12 @@ relocate_new_kernel: b 0b 2: +#ifdef CONFIG_KEXEC_HARDBOOT + ldr r0, kexec_hardboot + teq r0, #0 + bne hardboot +#endif + /* Jump to relocated kernel */ mov lr,r1 mov r0,#0 @@ -60,6 +75,40 @@ relocate_new_kernel: ARM( mov pc, lr ) THUMB( bx lr ) +#ifdef CONFIG_KEXEC_HARDBOOT +hardboot: + /* Stash boot arguments in hardboot page: + * 0: KEXEC_HB_PAGE_MAGIC + * 4: kexec_start_address + * 8: kexec_mach_type + * 12: kexec_boot_atags */ + ldr r0, =KEXEC_HB_PAGE_ADDR + str r1, [r0, #4] + ldr r1, kexec_mach_type + str r1, [r0, #8] + ldr r1, kexec_boot_atags + str r1, [r0, #12] + ldr r1, =KEXEC_HB_PAGE_MAGIC + str r1, [r0] + +#if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) + ldr r0, =TEGRA_PMC_BASE + ldr r1, [r0] + orr r1, r1, #0x10 + str r1, [r0] +loop: b loop +#elif defined(CONFIG_ARCH_APQ8064) + /* Restart using the PMIC chip, see mach-msm/restart.c */ + ldr r0, =APQ8064_TLMM_PHYS + mov r1, #0 + str r1, [r0, #0x820] @ PSHOLD_CTL_SU +loop: b loop +#else +#error "No reboot method defined for hardboot." +#endif + + .ltorg +#endif .align .globl kexec_start_address @@ -79,6 +128,12 @@ kexec_mach_type: kexec_boot_atags: .long 0x0 +#ifdef CONFIG_KEXEC_HARDBOOT + .globl kexec_hardboot +kexec_hardboot: + .long 0x0 +#endif + relocate_new_kernel_end: .globl relocate_new_kernel_size diff --git a/arch/arm/kernel/signal.c b/arch/arm/kernel/signal.c index d68d1b69468..eb3a2912cb9 100644 --- a/arch/arm/kernel/signal.c +++ b/arch/arm/kernel/signal.c @@ -642,7 +642,7 @@ static void do_signal(struct pt_regs *regs, int syscall) } } - if (try_to_freeze()) + if (try_to_freeze_nowarn()) goto no_signal; /* diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c index e46fd92b451..a5f7e61bb3e 100644 --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,7 @@ #include #include #include + #include #include #include @@ -158,8 +160,11 @@ int __cpu_disable(void) /* * Flush user cache and TLB mappings, and then remove this CPU * from the vm mask set of all processes. + * + * Caches are flushed to the Level of Unification Inner Shareable + * to write-back dirty lines to unified caches shared by all CPUs. */ - flush_cache_all(); + flush_cache_louis(); local_flush_tlb_all(); read_lock(&tasklist_lock); @@ -656,9 +661,9 @@ void smp_send_stop(void) smp_cross_call(&mask, IPI_CPU_STOP); /* Wait up to one second for other CPUs to stop */ - timeout = USEC_PER_SEC; + timeout = MSEC_PER_SEC; while (num_active_cpus() > 1 && timeout--) - udelay(1); + mdelay(1); if (num_active_cpus() > 1) pr_warning("SMP: failed to stop secondary CPUs\n"); @@ -673,3 +678,57 @@ int setup_profiling_timer(unsigned int multiplier) { return -EINVAL; } + +#ifdef CONFIG_CPU_FREQ + +static DEFINE_PER_CPU(unsigned long, l_p_j_ref); +static DEFINE_PER_CPU(unsigned long, l_p_j_ref_freq); +static unsigned long global_l_p_j_ref; +static unsigned long global_l_p_j_ref_freq; + +static int cpufreq_callback(struct notifier_block *nb, + unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + int cpu = freq->cpu; + + if (freq->flags & CPUFREQ_CONST_LOOPS) + return NOTIFY_OK; + + if (!per_cpu(l_p_j_ref, cpu)) { + per_cpu(l_p_j_ref, cpu) = + per_cpu(cpu_data, cpu).loops_per_jiffy; + per_cpu(l_p_j_ref_freq, cpu) = freq->old; + if (!global_l_p_j_ref) { + global_l_p_j_ref = loops_per_jiffy; + global_l_p_j_ref_freq = freq->old; + } + } + + if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || + (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) || + (val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) { + loops_per_jiffy = cpufreq_scale(global_l_p_j_ref, + global_l_p_j_ref_freq, + freq->new); + per_cpu(cpu_data, cpu).loops_per_jiffy = + cpufreq_scale(per_cpu(l_p_j_ref, cpu), + per_cpu(l_p_j_ref_freq, cpu), + freq->new); + } + return NOTIFY_OK; +} + +static struct notifier_block cpufreq_notifier = { + .notifier_call = cpufreq_callback, +}; + +static int __init register_cpufreq_notifier(void) +{ + return cpufreq_register_notifier(&cpufreq_notifier, + CPUFREQ_TRANSITION_NOTIFIER); +} +core_initcall(register_cpufreq_notifier); + +#endif + diff --git a/arch/arm/kernel/suspend.c b/arch/arm/kernel/suspend.c index 1794cc3b0f1..358bca3a995 100644 --- a/arch/arm/kernel/suspend.c +++ b/arch/arm/kernel/suspend.c @@ -17,6 +17,8 @@ extern void cpu_resume_mmu(void); */ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) { + u32 *ctx = ptr; + *save_ptr = virt_to_phys(ptr); /* This must correspond to the LDM in cpu_resume() assembly */ @@ -26,7 +28,20 @@ void __cpu_suspend_save(u32 *ptr, u32 ptrsz, u32 sp, u32 *save_ptr) cpu_do_suspend(ptr); - flush_cache_all(); + flush_cache_louis(); + + /* + * flush_cache_louis does not guarantee that + * save_ptr and ptr are cleaned to main memory, + * just up to the Level of Unification Inner Shareable. + * Since the context pointer and context itself + * are to be retrieved with the MMU off that + * data must be cleaned from all cache levels + * to main memory using "area" cache primitives. + */ + __cpuc_flush_dcache_area(ctx, ptrsz); + __cpuc_flush_dcache_area(save_ptr, sizeof(*save_ptr)); + outer_clean_range(*save_ptr, *save_ptr + ptrsz); outer_clean_range(virt_to_phys(save_ptr), virt_to_phys(save_ptr) + sizeof(*save_ptr)); diff --git a/arch/arm/kernel/topology.c b/arch/arm/kernel/topology.c index 8200deaa14f..ab85d949393 100644 --- a/arch/arm/kernel/topology.c +++ b/arch/arm/kernel/topology.c @@ -18,10 +18,20 @@ #include #include #include +#include +#include +#include + +#ifdef CONFIG_DEBUG_FS +#include +#include /* for copy_from_user */ +#endif #include #include +#define ARM_FAMILY_MASK 0xFF0FFFF0 + #define MPIDR_SMP_BITMASK (0x3 << 30) #define MPIDR_SMP_VALUE (0x2 << 30) @@ -43,11 +53,202 @@ struct cputopo_arm cpu_topology[NR_CPUS]; + +/* + * cpu power scale management + * a per cpu data structure should be better because each cpu is mainly + * using its own cpu_power even it's not always true because of + * nohz_idle_balance + */ + +static DEFINE_PER_CPU(unsigned int, cpu_scale); + +/* + * cpu topology mask update management + */ + +static unsigned int prev_sched_mc_power_savings = 0; +static unsigned int prev_sched_smt_power_savings = 0; + +ATOMIC_NOTIFIER_HEAD(topology_update_notifier_list); + +/* + * Update the cpu power of the scheduler + */ +unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu) +{ + return per_cpu(cpu_scale, cpu); +} + +void set_power_scale(unsigned int cpu, unsigned int power) +{ + per_cpu(cpu_scale, cpu) = power; +} + +int topology_register_notifier(struct notifier_block *nb) +{ + + return atomic_notifier_chain_register( + &topology_update_notifier_list, nb); +} + +int topology_unregister_notifier(struct notifier_block *nb) +{ + + return atomic_notifier_chain_unregister( + &topology_update_notifier_list, nb); +} + +/* + * sched_domain flag configuration + */ +/* TODO add a config flag for this function */ +int arch_sd_sibling_asym_packing(void) +{ + if (sched_smt_power_savings || sched_mc_power_savings) + return SD_ASYM_PACKING; + return 0; +} + +/* + * default topology function + */ const struct cpumask *cpu_coregroup_mask(int cpu) { return &cpu_topology[cpu].core_sibling; } +/* + * clear cpu topology masks + */ +static void clear_cpu_topology_mask(void) +{ + unsigned int cpuid; + for_each_possible_cpu(cpuid) { + struct cputopo_arm *cpuid_topo = &(cpu_topology[cpuid]); + cpumask_clear(&cpuid_topo->core_sibling); + cpumask_clear(&cpuid_topo->thread_sibling); + } + smp_wmb(); +} + +/* + * default_cpu_topology_mask set the core and thread mask as described in the + * ARM ARM + */ +static void default_cpu_topology_mask(unsigned int cpuid) +{ + struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; + unsigned int cpu; + + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + + if (cpuid_topo->socket_id == cpu_topo->socket_id) { + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->core_sibling); + + if (cpuid_topo->core_id == cpu_topo->core_id) { + cpumask_set_cpu(cpuid, + &cpu_topo->thread_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->thread_sibling); + } + } + } + smp_wmb(); +} + +static void normal_cpu_topology_mask(void) +{ + unsigned int cpuid; + + for_each_possible_cpu(cpuid) { + default_cpu_topology_mask(cpuid); + } + smp_wmb(); +} + +/* + * For Cortex-A9 MPcore, we emulate a multi-package topology in power mode. + * The goal is to gathers tasks on 1 virtual package + */ +static void power_cpu_topology_mask_CA9(unsigned int cpuid) +{ + struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; + unsigned int cpu; + + for_each_possible_cpu(cpu) { + struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + + if ((cpuid_topo->socket_id == cpu_topo->socket_id) + && ((cpuid & 0x1) == (cpu & 0x1))) { + cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->core_sibling); + + if (cpuid_topo->core_id == cpu_topo->core_id) { + cpumask_set_cpu(cpuid, + &cpu_topo->thread_sibling); + if (cpu != cpuid) + cpumask_set_cpu(cpu, + &cpuid_topo->thread_sibling); + } + } + } + smp_wmb(); +} + +static int need_topology_update(void) +{ + int update; + + update = ((prev_sched_mc_power_savings ^ sched_mc_power_savings) + || (prev_sched_smt_power_savings ^ sched_smt_power_savings)); + + prev_sched_mc_power_savings = sched_mc_power_savings; + prev_sched_smt_power_savings = sched_smt_power_savings; + + return update; +} + +#define ARM_CORTEX_A9_FAMILY 0x410FC090 + +/* update_cpu_topology_policy select a cpu topology policy according to the + * available cores. + * TODO: The current version assumes that all cores are exactly the same which + * might not be true. We need to update it to take into account various + * configuration among which system with different kind of core. + */ +static int update_cpu_topology_mask(void) +{ + unsigned long cpuid; + + if (sched_mc_power_savings == POWERSAVINGS_BALANCE_NONE) { + normal_cpu_topology_mask(); + return 0; + } + + for_each_possible_cpu(cpuid) { + struct cputopo_arm *cpuid_topo = &(cpu_topology[cpuid]); + + switch (cpuid_topo->id) { + case ARM_CORTEX_A9_FAMILY: + power_cpu_topology_mask_CA9(cpuid); + break; + default: + default_cpu_topology_mask(cpuid); + break; + } + } + + return 0; +} + /* * store_cpu_topology is called at boot when only one cpu is running * and with the mutex cpu_hotplug.lock locked, when several cpus have booted, @@ -57,7 +258,6 @@ void store_cpu_topology(unsigned int cpuid) { struct cputopo_arm *cpuid_topo = &cpu_topology[cpuid]; unsigned int mpidr; - unsigned int cpu; /* If the cpu topology has been already set, just return */ if (cpuid_topo->core_id != -1) @@ -88,6 +288,9 @@ void store_cpu_topology(unsigned int cpuid) cpuid_topo->socket_id = (mpidr >> MPIDR_LEVEL1_SHIFT) & MPIDR_LEVEL1_MASK; } + + cpuid_topo->id = read_cpuid_id() & ARM_FAMILY_MASK; + } else { /* * This is an uniprocessor system @@ -99,26 +302,12 @@ void store_cpu_topology(unsigned int cpuid) cpuid_topo->socket_id = -1; } - /* update core and thread sibling masks */ - for_each_possible_cpu(cpu) { - struct cputopo_arm *cpu_topo = &cpu_topology[cpu]; + /* + * The core and thread sibling masks can also be updated during the + * call of arch_update_cpu_topology + */ + default_cpu_topology_mask(cpuid); - if (cpuid_topo->socket_id == cpu_topo->socket_id) { - cpumask_set_cpu(cpuid, &cpu_topo->core_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, - &cpuid_topo->core_sibling); - - if (cpuid_topo->core_id == cpu_topo->core_id) { - cpumask_set_cpu(cpuid, - &cpu_topo->thread_sibling); - if (cpu != cpuid) - cpumask_set_cpu(cpu, - &cpuid_topo->thread_sibling); - } - } - } - smp_wmb(); printk(KERN_INFO "CPU%u: thread %d, cpu %d, socket %d, mpidr %x\n", cpuid, cpu_topology[cpuid].thread_id, @@ -126,6 +315,28 @@ void store_cpu_topology(unsigned int cpuid) cpu_topology[cpuid].socket_id, mpidr); } +/* + * arch_update_cpu_topology is called by the scheduler before building + * a new sched_domain hierarchy. + */ +int arch_update_cpu_topology(void) +{ + if (!need_topology_update()) + return 0; + + /* clear core threads mask */ + clear_cpu_topology_mask(); + + /* set topology mask */ + update_cpu_topology_mask(); + + /* notify the topology update */ + atomic_notifier_call_chain(&topology_update_notifier_list, + TOPOLOGY_POSTCHANGE, (void *)sched_mc_power_savings); + + return 1; +} + /* * init_cpu_topology is called at boot when only one cpu is running * which prevent simultaneous write access to cpu_topology array @@ -138,11 +349,105 @@ void init_cpu_topology(void) for_each_possible_cpu(cpu) { struct cputopo_arm *cpu_topo = &(cpu_topology[cpu]); + cpu_topo->id = -1; cpu_topo->thread_id = -1; cpu_topo->core_id = -1; cpu_topo->socket_id = -1; cpumask_clear(&cpu_topo->core_sibling); cpumask_clear(&cpu_topo->thread_sibling); + + per_cpu(cpu_scale, cpu) = SCHED_POWER_SCALE; } smp_wmb(); } + +/* + * debugfs interface for scaling cpu power + */ + +#ifdef CONFIG_DEBUG_FS +static struct dentry *topo_debugfs_root; + +static ssize_t dbg_write(struct file *file, const char __user *buf, + size_t size, loff_t *off) +{ + unsigned int *value = file->f_dentry->d_inode->i_private; + char cdata[128]; + unsigned long tmp; + + if (size < (sizeof(cdata)-1)) { + if (copy_from_user(cdata, buf, size)) + return -EFAULT; + cdata[size] = 0; + if (!strict_strtoul(cdata, 10, &tmp)) { + *value = tmp; + } + return size; + } + return -EINVAL; +} + +static ssize_t dbg_read(struct file *file, char __user *buf, + size_t size, loff_t *off) +{ + unsigned int *value = file->f_dentry->d_inode->i_private; + char cdata[128]; + unsigned int len; + + len = sprintf(cdata, "%u\n", *value); + return simple_read_from_buffer(buf, size, off, cdata, len); +} + +static const struct file_operations debugfs_fops = { + .read = dbg_read, + .write = dbg_write, +}; + +static struct dentry *topo_debugfs_register(unsigned int cpu, + struct dentry *parent) +{ + struct dentry *cpu_d, *d; + char cpu_name[16]; + + sprintf(cpu_name, "cpu%u", cpu); + + cpu_d = debugfs_create_dir(cpu_name, parent); + if (!cpu_d) + return NULL; + + d = debugfs_create_file("cpu_power", S_IRUGO | S_IWUGO, + cpu_d, &per_cpu(cpu_scale, cpu), &debugfs_fops); + if (!d) + goto err_out; + + return cpu_d; + +err_out: + debugfs_remove_recursive(cpu_d); + return NULL; +} + +static int __init topo_debugfs_init(void) +{ + struct dentry *d; + unsigned int cpu; + + d = debugfs_create_dir("cpu_topo", NULL); + if (!d) + return -ENOMEM; + topo_debugfs_root = d; + + for_each_possible_cpu(cpu) { + d = topo_debugfs_register(cpu, topo_debugfs_root); + if (d == NULL) + goto err_out; + } + return 0; + +err_out: + debugfs_remove_recursive(topo_debugfs_root); + return -ENOMEM; +} + +late_initcall(topo_debugfs_init); +#endif diff --git a/arch/arm/lib/getuser.S b/arch/arm/lib/getuser.S index 11093a7c3e3..9b06bb41fca 100644 --- a/arch/arm/lib/getuser.S +++ b/arch/arm/lib/getuser.S @@ -16,8 +16,9 @@ * __get_user_X * * Inputs: r0 contains the address + * r1 contains the address limit, which must be preserved * Outputs: r0 is the error code - * r2, r3 contains the zero-extended value + * r2 contains the zero-extended value * lr corrupted * * No other registers must be altered. (see @@ -27,33 +28,39 @@ * Note also that it is intended that __get_user_bad is not global. */ #include +#include #include #include ENTRY(__get_user_1) + check_uaccess r0, 1, r1, r2, __get_user_bad 1: TUSER(ldrb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__get_user_1) ENTRY(__get_user_2) -#ifdef CONFIG_THUMB2_KERNEL -2: TUSER(ldrb) r2, [r0] -3: TUSER(ldrb) r3, [r0, #1] + check_uaccess r0, 2, r1, r2, __get_user_bad +#ifdef CONFIG_CPU_USE_DOMAINS +rb .req ip +2: ldrbt r2, [r0], #1 +3: ldrbt rb, [r0], #0 #else -2: TUSER(ldrb) r2, [r0], #1 -3: TUSER(ldrb) r3, [r0] +rb .req r0 +2: ldrb r2, [r0] +3: ldrb rb, [r0, #1] #endif #ifndef __ARMEB__ - orr r2, r2, r3, lsl #8 + orr r2, r2, rb, lsl #8 #else - orr r2, r3, r2, lsl #8 + orr r2, rb, r2, lsl #8 #endif mov r0, #0 mov pc, lr ENDPROC(__get_user_2) ENTRY(__get_user_4) + check_uaccess r0, 4, r1, r2, __get_user_bad 4: TUSER(ldr) r2, [r0] mov r0, #0 mov pc, lr diff --git a/arch/arm/lib/memset.S b/arch/arm/lib/memset.S index 650d5923ab8..94b0650ea98 100644 --- a/arch/arm/lib/memset.S +++ b/arch/arm/lib/memset.S @@ -14,27 +14,15 @@ .text .align 5 - .word 0 - -1: subs r2, r2, #4 @ 1 do we have enough - blt 5f @ 1 bytes to align with? - cmp r3, #2 @ 1 - strltb r1, [r0], #1 @ 1 - strleb r1, [r0], #1 @ 1 - strb r1, [r0], #1 @ 1 - add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) -/* - * The pointer is now aligned and the length is adjusted. Try doing the - * memset again. - */ ENTRY(memset) ands r3, r0, #3 @ 1 unaligned? - bne 1b @ 1 + mov ip, r0 @ preserve r0 as return value + bne 6f @ 1 /* - * we know that the pointer in r0 is aligned to a word boundary. + * we know that the pointer in ip is aligned to a word boundary. */ - orr r1, r1, r1, lsl #8 +1: orr r1, r1, r1, lsl #8 orr r1, r1, r1, lsl #16 mov r3, r1 cmp r2, #16 @@ -43,29 +31,28 @@ ENTRY(memset) #if ! CALGN(1)+0 /* - * We need an extra register for this loop - save the return address and - * use the LR + * We need 2 extra registers for this loop - use r8 and the LR */ - str lr, [sp, #-4]! - mov ip, r1 + stmfd sp!, {r8, lr} + mov r8, r1 mov lr, r1 2: subs r2, r2, #64 - stmgeia r0!, {r1, r3, ip, lr} @ 64 bytes at a time. - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} - stmgeia r0!, {r1, r3, ip, lr} + stmgeia ip!, {r1, r3, r8, lr} @ 64 bytes at a time. + stmgeia ip!, {r1, r3, r8, lr} + stmgeia ip!, {r1, r3, r8, lr} + stmgeia ip!, {r1, r3, r8, lr} bgt 2b - ldmeqfd sp!, {pc} @ Now <64 bytes to go. + ldmeqfd sp!, {r8, pc} @ Now <64 bytes to go. /* * No need to correct the count; we're only testing bits from now on */ tst r2, #32 - stmneia r0!, {r1, r3, ip, lr} - stmneia r0!, {r1, r3, ip, lr} + stmneia ip!, {r1, r3, r8, lr} + stmneia ip!, {r1, r3, r8, lr} tst r2, #16 - stmneia r0!, {r1, r3, ip, lr} - ldr lr, [sp], #4 + stmneia ip!, {r1, r3, r8, lr} + ldmfd sp!, {r8, lr} #else @@ -74,54 +61,63 @@ ENTRY(memset) * whole cache lines at once. */ - stmfd sp!, {r4-r7, lr} + stmfd sp!, {r4-r8, lr} mov r4, r1 mov r5, r1 mov r6, r1 mov r7, r1 - mov ip, r1 + mov r8, r1 mov lr, r1 cmp r2, #96 - tstgt r0, #31 + tstgt ip, #31 ble 3f - and ip, r0, #31 - rsb ip, ip, #32 - sub r2, r2, ip - movs ip, ip, lsl #(32 - 4) - stmcsia r0!, {r4, r5, r6, r7} - stmmiia r0!, {r4, r5} - tst ip, #(1 << 30) - mov ip, r1 - strne r1, [r0], #4 + and r8, ip, #31 + rsb r8, r8, #32 + sub r2, r2, r8 + movs r8, r8, lsl #(32 - 4) + stmcsia ip!, {r4, r5, r6, r7} + stmmiia ip!, {r4, r5} + tst r8, #(1 << 30) + mov r8, r1 + strne r1, [ip], #4 3: subs r2, r2, #64 - stmgeia r0!, {r1, r3-r7, ip, lr} - stmgeia r0!, {r1, r3-r7, ip, lr} + stmgeia ip!, {r1, r3-r8, lr} + stmgeia ip!, {r1, r3-r8, lr} bgt 3b - ldmeqfd sp!, {r4-r7, pc} + ldmeqfd sp!, {r4-r8, pc} tst r2, #32 - stmneia r0!, {r1, r3-r7, ip, lr} + stmneia ip!, {r1, r3-r8, lr} tst r2, #16 - stmneia r0!, {r4-r7} - ldmfd sp!, {r4-r7, lr} + stmneia ip!, {r4-r7} + ldmfd sp!, {r4-r8, lr} #endif 4: tst r2, #8 - stmneia r0!, {r1, r3} + stmneia ip!, {r1, r3} tst r2, #4 - strne r1, [r0], #4 + strne r1, [ip], #4 /* * When we get here, we've got less than 4 bytes to zero. We * may have an unaligned pointer as well. */ 5: tst r2, #2 - strneb r1, [r0], #1 - strneb r1, [r0], #1 + strneb r1, [ip], #1 + strneb r1, [ip], #1 tst r2, #1 - strneb r1, [r0], #1 + strneb r1, [ip], #1 mov pc, lr + +6: subs r2, r2, #4 @ 1 do we have enough + blt 5b @ 1 bytes to align with? + cmp r3, #2 @ 1 + strltb r1, [ip], #1 @ 1 + strleb r1, [ip], #1 @ 1 + strb r1, [ip], #1 @ 1 + add r2, r2, r3 @ 1 (r2 = r2 - (4 - r3)) + b 1b ENDPROC(memset) diff --git a/arch/arm/lib/putuser.S b/arch/arm/lib/putuser.S index 7db25990c58..3d73dcb959b 100644 --- a/arch/arm/lib/putuser.S +++ b/arch/arm/lib/putuser.S @@ -16,6 +16,7 @@ * __put_user_X * * Inputs: r0 contains the address + * r1 contains the address limit, which must be preserved * r2, r3 contains the value * Outputs: r0 is the error code * lr corrupted @@ -27,16 +28,19 @@ * Note also that it is intended that __put_user_bad is not global. */ #include +#include #include #include ENTRY(__put_user_1) + check_uaccess r0, 1, r1, ip, __put_user_bad 1: TUSER(strb) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_1) ENTRY(__put_user_2) + check_uaccess r0, 2, r1, ip, __put_user_bad mov ip, r2, lsr #8 #ifdef CONFIG_THUMB2_KERNEL #ifndef __ARMEB__ @@ -60,12 +64,14 @@ ENTRY(__put_user_2) ENDPROC(__put_user_2) ENTRY(__put_user_4) + check_uaccess r0, 4, r1, ip, __put_user_bad 4: TUSER(str) r2, [r0] mov r0, #0 mov pc, lr ENDPROC(__put_user_4) ENTRY(__put_user_8) + check_uaccess r0, 8, r1, ip, __put_user_bad #ifdef CONFIG_THUMB2_KERNEL 5: TUSER(str) r2, [r0] 6: TUSER(str) r3, [r0, #4] diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig index 10efe055e01..fa3d466bce5 100644 --- a/arch/arm/mach-msm/Kconfig +++ b/arch/arm/mach-msm/Kconfig @@ -34,7 +34,6 @@ config ARCH_MSM7X27 select MULTI_IRQ_HANDLER select MSM_PROC_COMM_REGULATOR select CLEANCACHE - select QCACHE select MSM_PM2 if PM select MSM_RUN_QUEUE_STATS if MSM_SOC_REV_A select DONT_MAP_HOLE_AFTER_MEMBANK0 @@ -168,7 +167,6 @@ config ARCH_MSM8960 select ARCH_SPARSEMEM_ENABLE select ARCH_HAS_HOLES_MEMORYMODEL select CLEANCACHE - select QCACHE select MSM_MULTIMEDIA_USE_ION select MULTI_IRQ_HANDLER select MSM_PM8X60 if PM @@ -234,7 +232,6 @@ config ARCH_APQ8064 select CPU_HAS_L2_PMU select HOLES_IN_ZONE if SPARSEMEM select CLEANCACHE - select QCACHE select MIGHT_HAVE_PCI select ARCH_SUPPORTS_MSI select ARM_HAS_SG_CHAIN @@ -414,7 +411,6 @@ config ARCH_MSM_KRAITMP select HAVE_ARCH_HAS_CURRENT_TIMER select MSM_JTAG if CORESIGHT_ETM bool - select HAVE_HW_BRKPT_RESERVED_RW_ACCESS config ARCH_MSM_CORTEXMP select MSM_SMP @@ -425,7 +421,6 @@ config MSM_KRAIT_WFE_FIXUP config ARCH_MSM_CORTEX_A5 bool - select HAVE_HW_BRKPT_RESERVED_RW_ACCESS config ARCH_MSM7X27A bool @@ -1620,15 +1615,34 @@ config MSM_CPU_FREQ_SET_MIN_MAX config MSM_CPU_FREQ_MAX int "Max CPU Frequency" depends on MSM_CPU_FREQ_SET_MIN_MAX - default 384000 + default 2322000 config MSM_CPU_FREQ_MIN int "Min CPU Frequency" depends on MSM_CPU_FREQ_SET_MIN_MAX - default 245760 + default 384000 endif # CPU_FREQ_MSM +config MSM_SLEEPER + bool "Limit max frequency while screen is off" + default y + help + Limit max frequency while screen is off + +config CPU_VOLTAGE_TABLE + bool "Enable CPU Voltage Table via sysfs for adjustements" + default n + help + Krait User Voltage Control + +config GPU_VOLTAGE_TABLE + bool "Enable GPU Voltage Table via sysfs for adjustements" + depends on CPU_VOLTAGE_TABLE + default n + help + Adreno GPU User Voltage Control + config MSM_AVS_HW bool "Enable Adaptive Voltage Scaling (AVS)" default n @@ -2562,6 +2576,14 @@ config MSM_DCVS algorithm and the algorithm returns a frequency for the core which is passed to the frequency change driver. +config MSM_HOTPLUG + bool "MSM hotplug driver" + depends on HOTPLUG_CPU + default y + help + The MSM hotplug driver controls on-/offlining of additional cores based + on current cpu load. + config MSM_CPR tristate "Use MSM CPR in S/W mode" help @@ -2618,4 +2640,23 @@ config MSM_CPU_PWRCTL stand alone power collapse operation. Selecting this option ensures that they are always off. +config FORCE_FAST_CHARGE + bool "Force AC charge mode at will" + default y + help + A simple sysfs interface to force adapters that + are detected as USB to charge as AC. + +config UPDATE_LCDC_LUT + bool "Set initial Qualcomm LCDC lut" + default n + help + Set initial Qualcomm LCDC Look Up Table. + +config LCD_KCAL_STANDALONE + tristate "MSM generic LCDC Calibration" + default n + help + Enable MSM generic LCDC temperature Calibration. + endif diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile index 63e99f5ddff..ef3e6643767 100644 --- a/arch/arm/mach-msm/Makefile +++ b/arch/arm/mach-msm/Makefile @@ -30,7 +30,6 @@ obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o obj-$(CONFIG_ARCH_MSM_KRAIT) += msm-krait-l2-accessors.o pmu.o perf_event_msm_krait_l2.o obj-$(CONFIG_ARCH_MSM_KRAIT) += krait-scm.o obj-$(CONFIG_ARCH_MSM7X27A) += pmu.o -obj-$(CONFIG_DEBUG_FS) += perf_debug.o ifndef CONFIG_MSM_SMP obj-$(CONFIG_ARCH_MSM_SCORPION) += msm_fault_handlers.o @@ -319,6 +318,9 @@ obj-$(CONFIG_HTC_HEADSET) += htc_headset.o obj-$(CONFIG_MSM_RMT_STORAGE_CLIENT) += rmt_storage_client.o obj-$(CONFIG_MSM_SDIO_SMEM) += sdio_smem.o obj-$(CONFIG_MSM_RPM) += rpm.o + +obj-$(CONFIG_LCD_KCAL) += msm_kcal_ctrl.o + ifdef CONFIG_MSM_RPM obj-$(CONFIG_ARCH_APQ8064) += rpm_resources.o obj-$(CONFIG_ARCH_MSM8960) += rpm_resources.o @@ -360,6 +362,7 @@ obj-$(CONFIG_ARCH_MSM9625) += gpiomux-v2.o gpiomux.o obj-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += idle_stats_device.o obj-$(CONFIG_MSM_DCVS) += msm_dcvs_scm.o msm_dcvs.o msm_mpdecision.o +obj-$(CONFIG_MSM_HOTPLUG) += msm_hotplug.o obj-$(CONFIG_MSM_RUN_QUEUE_STATS) += msm_rq_stats.o obj-$(CONFIG_MSM_SHOW_RESUME_IRQ) += msm_show_resume_irq.o obj-$(CONFIG_BT_MSM_PINTEST) += btpintest.o @@ -388,8 +391,12 @@ obj-$(CONFIG_MSM_HSIC_SYSMON_TEST) += hsic_sysmon_test.o obj-$(CONFIG_MSM_RPM_SMD) += rpm-smd.o obj-$(CONFIG_MSM_CPR) += msm_cpr.o obj-$(CONFIG_MSM_VP_REGULATOR) += msm_vp.o +obj-$(CONFIG_FORCE_FAST_CHARGE) += fastchg.o +obj-$(CONFIG_MSM_SLEEPER) += msm-sleeper.o ifdef CONFIG_MSM_CPR obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o endif obj-$(CONFIG_MSM_CPU_PWRCTL) += msm_cpu_pwrctl.o + +obj-$(CONFIG_LCD_KCAL_STANDALONE) += msm_kcal_ctrl.o diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c index 0fe1793d5df..4d0d8ff09eb 100644 --- a/arch/arm/mach-msm/acpuclock-8064.c +++ b/arch/arm/mach-msm/acpuclock-8064.c @@ -21,6 +21,9 @@ #include "mach/socinfo.h" #include "acpuclock.h" #include "acpuclock-krait.h" +#include "vdd_limits_8064.h" + +int opt_bin = 1; static struct hfpll_data hfpll_data __initdata = { .mode_offset = 0x00, @@ -37,7 +40,7 @@ static struct hfpll_data hfpll_data __initdata = { .vdd[HFPLL_VDD_NONE] = 0, .vdd[HFPLL_VDD_LOW] = 945000, .vdd[HFPLL_VDD_NOM] = 1050000, - .vdd[HFPLL_VDD_HIGH] = 1150000, + .vdd[HFPLL_VDD_HIGH] = MEM_DIG_MAX_VDD, }; static struct scalable scalable[] __initdata = { @@ -47,9 +50,9 @@ static struct scalable scalable[] __initdata = { .aux_clk_sel = 3, .sec_clk_sel = 2, .l2cpmr_iaddr = 0x4501, - .vreg[VREG_CORE] = { "krait0", 1300000 }, - .vreg[VREG_MEM] = { "krait0_mem", 1150000 }, - .vreg[VREG_DIG] = { "krait0_dig", 1150000 }, + .vreg[VREG_CORE] = { "krait0", SC_MAX_VDD }, + .vreg[VREG_MEM] = { "krait0_mem", MEM_DIG_MAX_VDD }, + .vreg[VREG_DIG] = { "krait0_dig", MEM_DIG_MAX_VDD }, .vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 }, }, [CPU1] = { @@ -58,9 +61,9 @@ static struct scalable scalable[] __initdata = { .aux_clk_sel = 3, .sec_clk_sel = 2, .l2cpmr_iaddr = 0x5501, - .vreg[VREG_CORE] = { "krait1", 1300000 }, - .vreg[VREG_MEM] = { "krait1_mem", 1150000 }, - .vreg[VREG_DIG] = { "krait1_dig", 1150000 }, + .vreg[VREG_CORE] = { "krait1", SC_MAX_VDD }, + .vreg[VREG_MEM] = { "krait1_mem", MEM_DIG_MAX_VDD }, + .vreg[VREG_DIG] = { "krait1_dig", MEM_DIG_MAX_VDD }, .vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 }, }, [CPU2] = { @@ -69,9 +72,9 @@ static struct scalable scalable[] __initdata = { .aux_clk_sel = 3, .sec_clk_sel = 2, .l2cpmr_iaddr = 0x6501, - .vreg[VREG_CORE] = { "krait2", 1300000 }, - .vreg[VREG_MEM] = { "krait2_mem", 1150000 }, - .vreg[VREG_DIG] = { "krait2_dig", 1150000 }, + .vreg[VREG_CORE] = { "krait2", SC_MAX_VDD }, + .vreg[VREG_MEM] = { "krait2_mem", MEM_DIG_MAX_VDD }, + .vreg[VREG_DIG] = { "krait2_dig", MEM_DIG_MAX_VDD }, .vreg[VREG_HFPLL_A] = { "krait2_hfpll", 1800000 }, }, [CPU3] = { @@ -80,9 +83,9 @@ static struct scalable scalable[] __initdata = { .aux_clk_sel = 3, .sec_clk_sel = 2, .l2cpmr_iaddr = 0x7501, - .vreg[VREG_CORE] = { "krait3", 1300000 }, - .vreg[VREG_MEM] = { "krait3_mem", 1150000 }, - .vreg[VREG_DIG] = { "krait3_dig", 1150000 }, + .vreg[VREG_CORE] = { "krait3", SC_MAX_VDD }, + .vreg[VREG_MEM] = { "krait3_mem", MEM_DIG_MAX_VDD }, + .vreg[VREG_DIG] = { "krait3_dig", MEM_DIG_MAX_VDD }, .vreg[VREG_HFPLL_A] = { "krait3_hfpll", 1800000 }, }, [L2] = { @@ -106,6 +109,8 @@ static struct msm_bus_paths bw_level_tbl[] __initdata = { [3] = BW_MBPS(2128), /* At least 266 MHz on bus. */ [4] = BW_MBPS(3200), /* At least 400 MHz on bus. */ [5] = BW_MBPS(4264), /* At least 533 MHz on bus. */ + [6] = BW_MBPS(4660), /* At least 583 MHz on bus. */ + [7] = BW_MBPS(4800), /* At least 600 MHz on bus. */ }; static struct msm_bus_scale_pdata bus_scale_data __initdata = { @@ -134,6 +139,101 @@ static struct l2_level l2_freq_tbl[] __initdata = { { } }; +static struct l2_level l2_freq_tbl_oc1[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 5 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 5 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 5 }, + [13] = { { 1080000, HFPLL, 1, 0x28 }, 1150000, 1150000, 5 }, + [14] = { { 1188000, HFPLL, 1, 0x2C }, 1150000, 1150000, 5 }, + { } +}; + +static struct l2_level l2_freq_tbl_oc2[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 6 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 6 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 6 }, + [13] = { { 1080000, HFPLL, 1, 0x28 }, 1150000, 1150000, 6 }, + [14] = { { 1215000, HFPLL, 1, 0x2D }, 1175000, 1175000, 6 }, + { } +}; + +static struct l2_level l2_freq_tbl_oc3[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 6 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 6 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 6 }, + [13] = { { 1134000, HFPLL, 1, 0x2A }, 1150000, 1150000, 6 }, + [14] = { { 1350000, HFPLL, 1, 0x32 }, 1200000, 1200000, 6 }, + { } +}; + +static struct l2_level l2_freq_tbl_oc4[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 7 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 7 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 7 }, + [13] = { { 1188000, HFPLL, 1, 0x2C }, 1175000, 1175000, 7 }, + [14] = { { 1431000, HFPLL, 1, 0x35 }, 1225000, 1225000, 7 }, + { } +}; + +static struct l2_level l2_freq_tbl_oc5[] __initdata = { + [0] = { { 384000, PLL_8, 0, 0x00 }, 950000, 1050000, 1 }, + [1] = { { 432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 }, + [2] = { { 486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 }, + [3] = { { 540000, HFPLL, 2, 0x28 }, 1050000, 1050000, 2 }, + [4] = { { 594000, HFPLL, 1, 0x16 }, 1050000, 1050000, 2 }, + [5] = { { 648000, HFPLL, 1, 0x18 }, 1050000, 1050000, 4 }, + [6] = { { 702000, HFPLL, 1, 0x1A }, 1150000, 1150000, 4 }, + [7] = { { 756000, HFPLL, 1, 0x1C }, 1150000, 1150000, 4 }, + [8] = { { 810000, HFPLL, 1, 0x1E }, 1150000, 1150000, 4 }, + [9] = { { 864000, HFPLL, 1, 0x20 }, 1150000, 1150000, 4 }, + [10] = { { 918000, HFPLL, 1, 0x22 }, 1150000, 1150000, 7 }, + [11] = { { 972000, HFPLL, 1, 0x24 }, 1150000, 1150000, 7 }, + [12] = { { 1026000, HFPLL, 1, 0x26 }, 1150000, 1150000, 7 }, + [13] = { { 1215000, HFPLL, 1, 0x2D }, 1175000, 1175000, 7 }, + [14] = { { 1485000, HFPLL, 1, 0x37 }, MEM_DIG_MAX_VDD, MEM_DIG_MAX_VDD, 7 }, + { } +}; + static struct acpu_level tbl_slow[] __initdata = { { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 }, { 0, { 432000, HFPLL, 2, 0x20 }, L2(5), 975000 }, @@ -239,114 +339,219 @@ static struct acpu_level tbl_faster[] __initdata = { }; static struct acpu_level tbl_PVS0_1512MHz[] __initdata = { + { 1, { 81000, HFPLL, 2, 0x06 }, L2(0), 850000 }, + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 950000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 950000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 950000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 962500 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 1000000 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1025000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1037500 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 1075000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 1087500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 1125000 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1150000 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 962500 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 1000000 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 1025000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 1037500 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 1075000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 1087500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 1125000 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1150000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1162500 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1187500 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1212500 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1237500 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1250000 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1275000 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1300000 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1312500 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1325000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1337500 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1350000 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1375000 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1400000 }, { 0, { 0 } } }; static struct acpu_level tbl_PVS1_1512MHz[] __initdata = { + { 1, { 81000, HFPLL, 2, 0x06 }, L2(0), 850000 }, + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 950000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 950000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 950000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 950000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 950000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 950000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 962500 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 975000 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 1000000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 1012500 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 1037500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 1050000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 1087500 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1112500 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 962500 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 975000 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 1000000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 1012500 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 1037500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 1050000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 1087500 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1112500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1125000 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1150000 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1175000 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1200000 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1212500 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1225000 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1250000 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1275000 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1300000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1325000 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1337500 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1350000 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1375000 }, { 0, { 0 } } }; static struct acpu_level tbl_PVS2_1512MHz[] __initdata = { + { 1, { 81000, HFPLL, 2, 0x06 }, L2(0), 850000 }, + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 925000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 925000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 925000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 925000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 925000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 925000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 925000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 937500 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 950000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 975000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 1000000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 1012500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 1037500 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1075000 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 925000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 937500 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 950000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 975000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 1000000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 1012500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 1037500 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1075000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1087500 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1112500 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1137500 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1162500 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1175000 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1187500 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1212500 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1237500 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1262500 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1287500 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1312500 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1337500 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1362500 }, { 0, { 0 } } }; static struct acpu_level tbl_PVS3_1512MHz[] __initdata = { + { 1, { 81000, HFPLL, 2, 0x06 }, L2(0), 825000 }, + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 900000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 900000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 900000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 900000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 900000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 900000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 900000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 900000 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 925000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 950000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 975000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 987500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 1000000 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1037500 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 900000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 900000 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 925000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 950000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 975000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 987500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 1000000 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1037500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1050000 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1075000 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1100000 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1125000 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1137500 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1150000 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1175000 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1200000 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1225000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1250000 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1275000 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1312500 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1350000 }, { 0, { 0 } } }; static struct acpu_level tbl_PVS4_1512MHz[] __initdata = { + { 1, { 81000, HFPLL, 2, 0x06 }, L2(0), 800000 }, + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 950000 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 962500 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 975000 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 1000000 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 887500 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 900000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 925000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 950000 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 962500 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 975000 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 1000000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1012500 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1037500 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1062500 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1087500 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1100000 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1112500 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1137500 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1175000 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1200000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1225000 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1250000 }, + { 1, { 2268000, HFPLL, 1, 0x52 }, L2(14), 1275000 }, + { 1, { 2322000, HFPLL, 1, 0x54 }, L2(14), 1300000 }, { 0, { 0 } } }; static struct acpu_level tbl_PVS5_1512MHz[] __initdata = { + { 1, { 81000, HFPLL, 2, 0x06 }, L2(0), 800000 }, + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 937500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 950000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 962500 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 987500 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 887500 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 900000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 925000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 937500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 950000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 962500 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 987500 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 1000000 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1025000 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1050000 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1075000 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1087500 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1100000 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1137500 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1162500 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1187500 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1212500 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1237500 }, + { 1, { 2268000, HFPLL, 1, 0x54 }, L2(14), 1250000 }, + { 1, { 2322000, HFPLL, 1, 0x56 }, L2(14), 1275000 }, { 0, { 0 } } }; static struct acpu_level tbl_PVS6_1512MHz[] __initdata = { + { 1, { 81000, HFPLL, 2, 0x06 }, L2(0), 800000 }, + { 1, { 162000, HFPLL, 2, 0x0C }, L2(0), 875000 }, + { 1, { 270000, HFPLL, 2, 0x14 }, L2(0), 875000 }, { 1, { 384000, PLL_8, 0, 0x00 }, L2(0), 875000 }, - { 1, { 486000, HFPLL, 2, 0x24 }, L2(5), 875000 }, + { 1, { 486000, HFPLL, 2, 0x24 }, L2(4), 875000 }, { 1, { 594000, HFPLL, 1, 0x16 }, L2(5), 875000 }, - { 1, { 702000, HFPLL, 1, 0x1A }, L2(5), 875000 }, - { 1, { 810000, HFPLL, 1, 0x1E }, L2(5), 887500 }, - { 1, { 918000, HFPLL, 1, 0x22 }, L2(5), 900000 }, - { 1, { 1026000, HFPLL, 1, 0x26 }, L2(5), 925000 }, - { 1, { 1134000, HFPLL, 1, 0x2A }, L2(14), 937500 }, - { 1, { 1242000, HFPLL, 1, 0x2E }, L2(14), 950000 }, - { 1, { 1350000, HFPLL, 1, 0x32 }, L2(14), 962500 }, - { 1, { 1458000, HFPLL, 1, 0x36 }, L2(14), 975000 }, + { 1, { 702000, HFPLL, 1, 0x1A }, L2(6), 875000 }, + { 1, { 810000, HFPLL, 1, 0x1E }, L2(7), 887500 }, + { 1, { 918000, HFPLL, 1, 0x22 }, L2(8), 900000 }, + { 1, { 1026000, HFPLL, 1, 0x26 }, L2(9), 925000 }, + { 1, { 1134000, HFPLL, 1, 0x2A }, L2(10), 937500 }, + { 1, { 1242000, HFPLL, 1, 0x2E }, L2(11), 950000 }, + { 1, { 1350000, HFPLL, 1, 0x32 }, L2(12), 962500 }, + { 1, { 1458000, HFPLL, 1, 0x36 }, L2(13), 975000 }, { 1, { 1512000, HFPLL, 1, 0x38 }, L2(14), 987500 }, + { 1, { 1620000, HFPLL, 1, 0x3C }, L2(14), 1012500 }, + { 1, { 1728000, HFPLL, 1, 0x40 }, L2(14), 1037500 }, + { 1, { 1836000, HFPLL, 1, 0x44 }, L2(14), 1062500 }, + { 1, { 1890000, HFPLL, 1, 0x46 }, L2(14), 1075000 }, + { 1, { 1944000, HFPLL, 1, 0x48 }, L2(14), 1087500 }, + { 1, { 1998000, HFPLL, 1, 0x4A }, L2(14), 1125000 }, + { 1, { 2052000, HFPLL, 1, 0x4C }, L2(14), 1150000 }, + { 1, { 2106000, HFPLL, 1, 0x4E }, L2(14), 1175000 }, + { 1, { 2160000, HFPLL, 1, 0x4F }, L2(14), 1200000 }, + { 1, { 2214000, HFPLL, 1, 0x50 }, L2(14), 1225000 }, + { 1, { 2268000, HFPLL, 1, 0x54 }, L2(14), 1250000 }, + { 1, { 2322000, HFPLL, 1, 0x56 }, L2(14), 1275000 }, { 0, { 0 } } }; @@ -652,6 +857,28 @@ static struct acpuclk_krait_params acpuclk_8064_params __initdata = { .stby_khz = 384000, }; +static int __init get_opt_level(char *l2_opt) +{ + if (strcmp(l2_opt, "0") == 0) { + opt_bin = 0; + } else if (strcmp(l2_opt, "1") == 0) { + opt_bin = 1; + } else if (strcmp(l2_opt, "2") == 0) { + opt_bin = 2; + } else if (strcmp(l2_opt, "3") == 0) { + opt_bin = 3; + } else if (strcmp(l2_opt, "4") == 0) { + opt_bin = 4; + } else if (strcmp(l2_opt, "5") == 0) { + opt_bin = 5; + } else { + opt_bin = 0; + } + return 0; +} + +__setup("l2_opt=", get_opt_level); + static int __init acpuclk_8064_probe(struct platform_device *pdev) { if (cpu_is_apq8064ab() || @@ -659,6 +886,30 @@ static int __init acpuclk_8064_probe(struct platform_device *pdev) acpuclk_8064_params.hfpll_data->low_vdd_l_max = 37; acpuclk_8064_params.hfpll_data->nom_vdd_l_max = 74; } + if (opt_bin == 1) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc1; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc1); + } + + if (opt_bin == 2) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc2; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc2); + } + + if (opt_bin == 3) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc3; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc3); + } + + if (opt_bin == 4) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc4; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc4); + } + + if (opt_bin == 5) { + acpuclk_8064_params.l2_freq_tbl = l2_freq_tbl_oc5; + acpuclk_8064_params.l2_freq_tbl_size = sizeof(l2_freq_tbl_oc5); + } return acpuclk_krait_init(&pdev->dev, &acpuclk_8064_params); } diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c index 64b162e3e1d..416dba5fe90 100644 --- a/arch/arm/mach-msm/acpuclock-krait.c +++ b/arch/arm/mach-msm/acpuclock-krait.c @@ -38,6 +38,7 @@ #include "acpuclock.h" #include "acpuclock-krait.h" #include "avs.h" +#include "vdd_limits_8064.h" /* MUX source selects. */ #define PRI_SRC_SEL_SEC_SRC 0 @@ -46,6 +47,131 @@ #define SECCLKAGD BIT(4) +#define FREQ_TABLE_SIZE 47 + +/** elementalx defs **/ + +int uv_bin = 0; +uint32_t arg_max_oc0 = 1512000; +uint32_t arg_max_oc1 = 1512000; +uint32_t arg_max_oc2 = 1512000; +uint32_t arg_max_oc3 = 1512000; +uint32_t arg_min_clock = 384000; + +/* boot arg max_oc */ +static int __init cpufreq_read_arg_max_oc0(char *max_oc0) +{ + unsigned long ui_khz; + int err; + err = strict_strtoul(max_oc0, 0, &ui_khz); + if (err) { + arg_max_oc0 = 1512000; + printk(KERN_INFO "[glitch]: max_oc0='%i'\n", arg_max_oc0); + return 1; + } + + arg_max_oc0 = ui_khz; + + return 0; +} +__setup("max_oc0=", cpufreq_read_arg_max_oc0); + +static int __init cpufreq_read_arg_max_oc1(char *max_oc1) +{ + unsigned long ui_khz; + int err; + err = strict_strtoul(max_oc1, 0, &ui_khz); + if (err) { + arg_max_oc1 = 1512000; + printk(KERN_INFO "[glitch]: max_oc1='%i'\n", arg_max_oc1); + return 1; + } + + arg_max_oc1 = ui_khz; + + return 0; +} +__setup("max_oc1=", cpufreq_read_arg_max_oc1); + +static int __init cpufreq_read_arg_max_oc2(char *max_oc2) +{ + unsigned long ui_khz; + int err; + err = strict_strtoul(max_oc2, 0, &ui_khz); + if (err) { + arg_max_oc2 = 1512000; + printk(KERN_INFO "[glitch]: max_oc2='%i'\n", arg_max_oc2); + return 1; + } + + arg_max_oc2 = ui_khz; + + return 0; +} +__setup("max_oc2=", cpufreq_read_arg_max_oc2); + +static int __init cpufreq_read_arg_max_oc3(char *max_oc3) +{ + unsigned long ui_khz; + int err; + err = strict_strtoul(max_oc3, 0, &ui_khz); + if (err) { + arg_max_oc3 = 1512000; + printk(KERN_INFO "[glitch]: max_oc3='%i'\n", arg_max_oc3); + return 1; + } + + arg_max_oc3 = ui_khz; + + return 0; +} +__setup("max_oc3=", cpufreq_read_arg_max_oc3); + +/* boot arg min_clock */ +static int __init cpufreq_read_arg_min_clock(char *min_clock) +{ + unsigned long idle_khz; + int err; + err = strict_strtoul(min_clock, 0, &idle_khz); + if (err) { + arg_min_clock = 384000; + printk(KERN_INFO "[glitch]: min_clock='%i'\n", arg_min_clock); + return 1; + } + + arg_min_clock = idle_khz; + + return 0; +} +__setup("min_clock=", cpufreq_read_arg_min_clock); + +static int __init get_uv_level(char *vdd_uv) +{ + if (strcmp(vdd_uv, "0") == 0) { + uv_bin = 0; + } else if (strcmp(vdd_uv, "1") == 0) { + uv_bin = 1; + } else if (strcmp(vdd_uv, "2") == 0) { + uv_bin = 2; + } else if (strcmp(vdd_uv, "3") == 0) { + uv_bin = 3; + } else if (strcmp(vdd_uv, "4") == 0) { + uv_bin = 4; + } else if (strcmp(vdd_uv, "5") == 0) { + uv_bin = 5; + } else if (strcmp(vdd_uv, "6") == 0) { + uv_bin = 6; + } else { + uv_bin = 0; + } + return 0; +} + +__setup("vdd_uv=", get_uv_level); + +/** end elementalx defs **/ + + static DEFINE_MUTEX(driver_lock); static DEFINE_SPINLOCK(l2_lock); @@ -80,7 +206,7 @@ static void set_pri_clk_src(struct scalable *sc, u32 pri_src_sel) } /* Select a source on the secondary MUX. */ -static void __cpuinit set_sec_clk_src(struct scalable *sc, u32 sec_src_sel) +static void set_sec_clk_src(struct scalable *sc, u32 sec_src_sel) { u32 regval; @@ -607,7 +733,7 @@ static struct acpuclk_data acpuclk_krait_data = { }; /* Initialize a HFPLL at a given rate and enable it. */ -static void __cpuinit hfpll_init(struct scalable *sc, +static void hfpll_init(struct scalable *sc, const struct core_speed *tgt_s) { dev_dbg(drv.dev, "Initializing HFPLL%d\n", sc - drv.scalable); @@ -634,7 +760,7 @@ static void __cpuinit hfpll_init(struct scalable *sc, hfpll_enable(sc, false); } -static int __cpuinit rpm_regulator_init(struct scalable *sc, enum vregs vreg, +static int rpm_regulator_init(struct scalable *sc, enum vregs vreg, int vdd, bool enable) { int ret; @@ -674,7 +800,7 @@ static int __cpuinit rpm_regulator_init(struct scalable *sc, enum vregs vreg, return ret; } -static void __cpuinit rpm_regulator_cleanup(struct scalable *sc, +static void rpm_regulator_cleanup(struct scalable *sc, enum vregs vreg) { if (!sc->vreg[vreg].rpm_reg) @@ -685,7 +811,7 @@ static void __cpuinit rpm_regulator_cleanup(struct scalable *sc, } /* Voltage regulator initialization. */ -static int __cpuinit regulator_init(struct scalable *sc, +static int regulator_init(struct scalable *sc, const struct acpu_level *acpu_level) { int ret, vdd_mem, vdd_dig, vdd_core; @@ -766,7 +892,7 @@ static int __cpuinit regulator_init(struct scalable *sc, return ret; } -static void __cpuinit regulator_cleanup(struct scalable *sc) +static void regulator_cleanup(struct scalable *sc) { regulator_disable(sc->vreg[VREG_CORE].reg); regulator_put(sc->vreg[VREG_CORE].reg); @@ -777,7 +903,7 @@ static void __cpuinit regulator_cleanup(struct scalable *sc) } /* Set initial rate for a given core. */ -static int __cpuinit init_clock_sources(struct scalable *sc, +static int init_clock_sources(struct scalable *sc, const struct core_speed *tgt_s) { u32 regval; @@ -809,21 +935,21 @@ static int __cpuinit init_clock_sources(struct scalable *sc, return 0; } -static void __cpuinit fill_cur_core_speed(struct core_speed *s, +static void fill_cur_core_speed(struct core_speed *s, struct scalable *sc) { s->pri_src_sel = get_l2_indirect_reg(sc->l2cpmr_iaddr) & 0x3; s->pll_l_val = readl_relaxed(sc->hfpll_base + drv.hfpll_data->l_offset); } -static bool __cpuinit speed_equal(const struct core_speed *s1, +static bool speed_equal(const struct core_speed *s1, const struct core_speed *s2) { return (s1->pri_src_sel == s2->pri_src_sel && s1->pll_l_val == s2->pll_l_val); } -static const struct acpu_level __cpuinit *find_cur_acpu_level(int cpu) +static const struct acpu_level *find_cur_acpu_level(int cpu) { struct scalable *sc = &drv.scalable[cpu]; const struct acpu_level *l; @@ -849,7 +975,7 @@ static const struct l2_level __init *find_cur_l2_level(void) return NULL; } -static const struct acpu_level __cpuinit *find_min_acpu_level(void) +static const struct acpu_level *find_min_acpu_level(void) { struct acpu_level *l; @@ -860,7 +986,7 @@ static const struct acpu_level __cpuinit *find_min_acpu_level(void) return NULL; } -static int __cpuinit per_cpu_init(int cpu) +static int per_cpu_init(int cpu) { struct scalable *sc = &drv.scalable[cpu]; const struct acpu_level *acpu_level; @@ -925,19 +1051,68 @@ static void __init bus_init(const struct l2_level *l2_level) dev_err(drv.dev, "initial bandwidth req failed (%d)\n", ret); } +#ifdef CONFIG_CPU_VOLTAGE_TABLE + +ssize_t acpuclk_get_vdd_levels_str(char *buf) { + + int i, len = 0; + + if (buf) { + mutex_lock(&driver_lock); + + for (i = 0; drv.acpu_freq_tbl[i].speed.khz; i++) { + /* updated to use uv required by 8x60 architecture - faux123 */ + len += sprintf(buf + len, "%8lu: %8d\n", drv.acpu_freq_tbl[i].speed.khz, + drv.acpu_freq_tbl[i].vdd_core ); + } + + mutex_unlock(&driver_lock); + } + return len; +} + +/* updated to use uv required by 8x60 architecture - faux123 */ +void acpuclk_set_vdd(unsigned int khz, int vdd_uv) { + + int i; + unsigned int new_vdd_uv; + + mutex_lock(&driver_lock); + + for (i = 0; drv.acpu_freq_tbl[i].speed.khz; i++) { + if (khz == 0) + new_vdd_uv = min(max((unsigned int)(drv.acpu_freq_tbl[i].vdd_core + vdd_uv), + (unsigned int)SC_MIN_VDD), (unsigned int)SC_MAX_VDD); + else if ( drv.acpu_freq_tbl[i].speed.khz == khz) + new_vdd_uv = min(max((unsigned int)vdd_uv, + (unsigned int)SC_MIN_VDD), (unsigned int)SC_MAX_VDD); + else + continue; + + drv.acpu_freq_tbl[i].vdd_core = new_vdd_uv; + } + pr_warn("faux123: user voltage table modified!\n"); + mutex_unlock(&driver_lock); +} +#endif /* CONFIG_CPU_VOTALGE_TABLE */ + #ifdef CONFIG_CPU_FREQ_MSM -static struct cpufreq_frequency_table freq_table[NR_CPUS][35]; +static struct cpufreq_frequency_table freq_table[NR_CPUS][FREQ_TABLE_SIZE]; static void __init cpufreq_table_init(void) { int cpu; + uint32_t limit_max_oc[4] = {arg_max_oc0, arg_max_oc1, arg_max_oc2, arg_max_oc3}; + uint32_t limit_min_clock = arg_min_clock; + for_each_possible_cpu(cpu) { int i, freq_cnt = 0; /* Construct the freq_table tables from acpu_freq_tbl. */ for (i = 0; drv.acpu_freq_tbl[i].speed.khz != 0 && freq_cnt < ARRAY_SIZE(*freq_table); i++) { - if (drv.acpu_freq_tbl[i].use_for_scaling) { + if (drv.acpu_freq_tbl[i].speed.khz <= limit_max_oc[cpu] + && drv.acpu_freq_tbl[i].speed.khz >= limit_min_clock) { freq_table[cpu][freq_cnt].index = freq_cnt; freq_table[cpu][freq_cnt].frequency = drv.acpu_freq_tbl[i].speed.khz; @@ -972,7 +1147,7 @@ static void __init dcvs_freq_init(void) drv.acpu_freq_tbl[i].vdd_core / 1000); } -static int __cpuinit acpuclk_cpu_callback(struct notifier_block *nfb, +static int acpuclk_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { static int prev_khz[NR_CPUS]; @@ -1010,7 +1185,7 @@ static int __cpuinit acpuclk_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block __cpuinitdata acpuclk_cpu_notifier = { +static struct notifier_block acpuclk_cpu_notifier = { .notifier_call = acpuclk_cpu_callback, }; @@ -1035,6 +1210,44 @@ static void krait_apply_vmin(struct acpu_level *tbl) } } +static void apply_undervolting(void) +{ + int i; + + for (i = 0; drv.acpu_freq_tbl[i].speed.khz <= arg_min_clock; i++) { + + if (uv_bin == 6) { + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 175000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); + } + + if (uv_bin == 5) { + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 150000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); + } + + if (uv_bin == 4) { + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 125000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); + } + + if (uv_bin == 3) { + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 100000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); + } + + if (uv_bin == 2) { + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 75000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core ); + } + + if (uv_bin == 1) { + drv.acpu_freq_tbl[i].vdd_core = (drv.acpu_freq_tbl[i].vdd_core - 50000); + printk(KERN_INFO "[glitch]: min_voltage='%i'\n", drv.acpu_freq_tbl[i].vdd_core); + } + } +} + static int __init get_speed_bin(u32 pte_efuse) { uint32_t speed_bin; @@ -1139,6 +1352,9 @@ static void __init hw_init(void) if (krait_needs_vmin()) krait_apply_vmin(drv.acpu_freq_tbl); + if (uv_bin) + apply_undervolting(); + l2->hfpll_base = ioremap(l2->hfpll_phys_base, SZ_32); BUG_ON(!l2->hfpll_base); diff --git a/arch/arm/mach-msm/asustek/devices_asustek.c b/arch/arm/mach-msm/asustek/devices_asustek.c index 85ed946db17..43ab567d503 100644 --- a/arch/arm/mach-msm/asustek/devices_asustek.c +++ b/arch/arm/mach-msm/asustek/devices_asustek.c @@ -17,6 +17,10 @@ #include #include +#ifdef CONFIG_KEXEC_HARDBOOT +#include +#endif + #include #include #include @@ -56,6 +60,17 @@ void __init asustek_add_persistent_ram(void) void __init asustek_reserve(void) { +#ifdef CONFIG_KEXEC_HARDBOOT + // Reserve space for hardboot page, just before the ram_console + struct membank* bank = &meminfo.bank[0]; + phys_addr_t start = bank->start + bank->size - SZ_1M - ASUSTEK_PERSISTENT_RAM_SIZE; + int ret = memblock_remove(start, SZ_1M); + if(!ret) + pr_info("Hardboot page reserved at 0x%X\n", start); + else + pr_err("Failed to reserve space for hardboot page at 0x%X!\n", start); +#endif + asustek_add_persistent_ram(); } diff --git a/arch/arm/mach-msm/asustek/flo/board-flo-display.c b/arch/arm/mach-msm/asustek/flo/board-flo-display.c index 26450db8568..cf9a33d8d12 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo-display.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo-display.c @@ -152,8 +152,18 @@ static int msm_fb_detect_panel(const char *name) return -ENODEV; } +#ifdef CONFIG_UPDATE_LCDC_LUT +int update_preset_lcdc_lut(void) +{ + return 0; +} +#endif + static struct msm_fb_platform_data msm_fb_pdata = { .detect_client = msm_fb_detect_panel, +#ifdef CONFIG_UPDATE_LCDC_LUT + .update_lcdc_lut = update_preset_lcdc_lut, +#endif }; static struct platform_device msm_fb_device = { diff --git a/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c b/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c index ecafb4b5a39..b297ca3dfab 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo-gpu.c @@ -93,13 +93,13 @@ static struct msm_bus_vectors grp3d_low_vectors[] = { .src = MSM_BUS_MASTER_GRAPHICS_3D, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, - .ib = KGSL_CONVERT_TO_MBPS(1000), + .ib = KGSL_CONVERT_TO_MBPS(1200), }, { .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, - .ib = KGSL_CONVERT_TO_MBPS(1000), + .ib = KGSL_CONVERT_TO_MBPS(1200), }, }; @@ -138,13 +138,13 @@ static struct msm_bus_vectors grp3d_max_vectors[] = { .src = MSM_BUS_MASTER_GRAPHICS_3D, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, - .ib = KGSL_CONVERT_TO_MBPS(4264), + .ib = KGSL_CONVERT_TO_MBPS(4800), }, { .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1, .dst = MSM_BUS_SLAVE_EBI_CH0, .ab = 0, - .ib = KGSL_CONVERT_TO_MBPS(4264), + .ib = KGSL_CONVERT_TO_MBPS(4800), }, }; @@ -182,6 +182,12 @@ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, /* Shader Mem Address */ .end = 0x0431ffff, .flags = IORESOURCE_MEM, }, @@ -221,7 +227,7 @@ static struct kgsl_device_iommu_data kgsl_3d0_iommu_data[] = { static struct kgsl_device_platform_data kgsl_3d0_pdata = { .pwrlevel = { { - .gpu_freq = 400000000, + .gpu_freq = 450000000, .bus_freq = 4, .io_fraction = 0, }, @@ -249,7 +255,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 5, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .strtstp_sleepwake = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING @@ -272,6 +277,11 @@ struct platform_device device_kgsl_3d0 = { }, }; +void SetMAXGPUFreq(unsigned long freq) +{ + kgsl_3d0_pdata.pwrlevel[0].gpu_freq = freq; +} + void __init apq8064_init_gpu(void) { unsigned int version = socinfo_get_version(); diff --git a/arch/arm/mach-msm/asustek/flo/board-flo-regulator.c b/arch/arm/mach-msm/asustek/flo/board-flo-regulator.c index 05de2e5c5d8..8e74db7ec19 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo-regulator.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo-regulator.c @@ -14,6 +14,7 @@ #include #include "board-flo.h" +#include "../../vdd_limits_8064.h" #define VREG_CONSUMERS(_id) \ static struct regulator_consumer_supply vreg_consumers_##_id[] @@ -567,15 +568,15 @@ mpq8064_gpio_regulator_pdata[] __devinitdata = { /* SAW regulator constraints */ struct regulator_init_data msm8064_saw_regulator_pdata_8921_s5 = /* ID vreg_name min_uV max_uV */ - SAW_VREG_INIT(S5, "8921_s5", 850000, 1300000); + SAW_VREG_INIT(S5, "8921_s5", SC_MIN_VDD, SC_MAX_VDD); struct regulator_init_data msm8064_saw_regulator_pdata_8921_s6 = - SAW_VREG_INIT(S6, "8921_s6", 850000, 1300000); + SAW_VREG_INIT(S6, "8921_s6", SC_MIN_VDD, SC_MAX_VDD); struct regulator_init_data msm8064_saw_regulator_pdata_8821_s0 = /* ID vreg_name min_uV max_uV */ - SAW_VREG_INIT(8821_S0, "8821_s0", 850000, 1300000); + SAW_VREG_INIT(8821_S0, "8821_s0", SC_MIN_VDD, SC_MAX_VDD); struct regulator_init_data msm8064_saw_regulator_pdata_8821_s1 = - SAW_VREG_INIT(8821_S1, "8821_s1", 850000, 1300000); + SAW_VREG_INIT(8821_S1, "8821_s1", SC_MIN_VDD, SC_MAX_VDD); /* PM8921 regulator constraints */ struct pm8xxx_regulator_platform_data @@ -623,7 +624,7 @@ apq8064_rpm_regulator_init_data[] __devinitdata = { /* ID a_on pd ss min_uV max_uV supply sys_uA freq fm ss_fm */ RPM_SMPS(S1, 1, 1, 0, 1225000, 1225000, NULL, 100000, 3p20, NONE, NONE), RPM_SMPS(S2, 0, 1, 0, 1300000, 1300000, NULL, 0, 1p60, NONE, NONE), - RPM_SMPS(S3, 0, 1, 1, 500000, 1150000, NULL, 100000, 4p80, NONE, NONE), + RPM_SMPS(S3, 0, 1, 1, 500000, MEM_DIG_MAX_VDD, NULL, 100000, 4p80, NONE, NONE), RPM_SMPS(S4, 1, 1, 0, 1800000, 1800000, NULL, 100000, 1p60, AUTO, AUTO), RPM_SMPS(S7, 0, 0, 0, 1300000, 1300000, NULL, 100000, 3p20, NONE, NONE), RPM_SMPS(S8, 0, 1, 0, 2200000, 2200000, NULL, 0, 1p60, NONE, NONE), @@ -650,7 +651,7 @@ apq8064_rpm_regulator_init_data[] __devinitdata = { RPM_LDO(L21, 0, 1, 0, 1050000, 1050000, NULL, 0, 0), RPM_LDO(L22, 0, 1, 0, 2600000, 2600000, NULL, 0, 0), RPM_LDO(L23, 0, 1, 0, 1800000, 1800000, NULL, 0, 0), - RPM_LDO(L24, 0, 1, 1, 750000, 1150000, "8921_s1", 10000, 10000), + RPM_LDO(L24, 0, 1, 1, 750000, MEM_DIG_MAX_VDD, "8921_s1", 10000, 10000), RPM_LDO(L25, 1, 1, 0, 1250000, 1250000, "8921_s1", 10000, 10000), RPM_LDO(L27, 0, 0, 0, 1100000, 1100000, "8921_s7", 0, 0), RPM_LDO(L28, 0, 1, 0, 1050000, 1050000, "8921_s7", 0, 0), diff --git a/arch/arm/mach-msm/asustek/flo/board-flo.c b/arch/arm/mach-msm/asustek/flo/board-flo.c index f4c5c10a1e5..78fb1b1f54b 100644 --- a/arch/arm/mach-msm/asustek/flo/board-flo.c +++ b/arch/arm/mach-msm/asustek/flo/board-flo.c @@ -247,7 +247,7 @@ static void enable_cap1106_regulator(void) { #define HOLE_SIZE 0x20000 #define MSM_CONTIG_MEM_SIZE 0x65000 #ifdef CONFIG_MSM_IOMMU -#define MSM_ION_MM_SIZE 0x4C00000 +#define MSM_ION_MM_SIZE 0x5C00000 #define MSM_ION_SF_SIZE 0 #define MSM_ION_QSECOM_SIZE 0x780000 /* (7.5MB) */ #define MSM_ION_HEAP_NUM 7 @@ -2085,10 +2085,10 @@ static struct platform_device msm_tsens_device = { static struct msm_thermal_data msm_thermal_pdata = { .sensor_id = 7, - .poll_ms = 250, +/* .poll_ms = 250, .limit_temp_degC = 60, .temp_hysteresis_degC = 10, - .freq_step = 2, + .freq_step = 2,*/ }; #define MSM_SHARED_RAM_PHYS 0x80000000 @@ -2222,13 +2222,13 @@ static struct msm_rpmrs_platform_data msm_rpmrs_data __initdata = { [MSM_RPMRS_VDD_MEM_RET_LOW] = 750000, [MSM_RPMRS_VDD_MEM_RET_HIGH] = 750000, [MSM_RPMRS_VDD_MEM_ACTIVE] = 1050000, - [MSM_RPMRS_VDD_MEM_MAX] = 1150000, + [MSM_RPMRS_VDD_MEM_MAX] = 1250000, }, .vdd_dig_levels = { [MSM_RPMRS_VDD_DIG_RET_LOW] = 500000, [MSM_RPMRS_VDD_DIG_RET_HIGH] = 750000, [MSM_RPMRS_VDD_DIG_ACTIVE] = 950000, - [MSM_RPMRS_VDD_DIG_MAX] = 1150000, + [MSM_RPMRS_VDD_DIG_MAX] = 1250000, }, .vdd_mask = 0x7FFFFF, .rpmrs_target_id = { @@ -3277,10 +3277,10 @@ static struct i2c_registry i2c_anx7808_devices __initdata = { static void __init add_i2c_anx7808_device(void) { if (machine_is_apq8064_flo()) { - anx7808_pdata.phy_reg2 = 0x39; - anx7808_pdata.phy_reg12 = 0x09; + anx7808_pdata.phy_reg2 = 0x3f; + anx7808_pdata.phy_reg12 = 0x10; anx7808_pdata.phy_reg6 = 0x3f; - anx7808_pdata.phy_reg16 = 0x1d; + anx7808_pdata.phy_reg16 = 0x1f; } else if (machine_is_apq8064_deb()) { anx7808_pdata.phy_reg2 = 0x3a; anx7808_pdata.phy_reg12 = 0x09; diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c index ad87e0a7748..4b6a5b95730 100644 --- a/arch/arm/mach-msm/board-8064-gpu.c +++ b/arch/arm/mach-msm/board-8064-gpu.c @@ -182,6 +182,12 @@ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, /* Shader Mem Address */ .end = 0x0431ffff, .flags = IORESOURCE_MEM, }, @@ -249,7 +255,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 5, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .strtstp_sleepwake = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c index cbf6803e023..12a6ab129a0 100644 --- a/arch/arm/mach-msm/board-8930-gpu.c +++ b/arch/arm/mach-msm/board-8930-gpu.c @@ -88,6 +88,12 @@ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, .end = 0x0431ffff, .flags = IORESOURCE_MEM, }, @@ -139,7 +145,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 4, .set_grp_async = NULL, .idle_timeout = HZ/12, - .nap_allowed = true, .strtstp_sleepwake = false, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c index 4b4d653d23b..77f172a0dd7 100644 --- a/arch/arm/mach-msm/board-8960.c +++ b/arch/arm/mach-msm/board-8960.c @@ -3032,8 +3032,18 @@ static void __init msm8960_gfx_init(void) kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0); /* 8960PRO nominal clock rate is 320Mhz */ kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 320000000; + + /* + * If this an A320 GPU device (MSM8960AB), then + * switch the resource table to 8960AB, to reflect the + * separate register and shader memory mapping used in A320. + */ + + msm_kgsl_3d0.num_resources = kgsl_num_resources_8960ab; + msm_kgsl_3d0.resource = kgsl_3d0_resources_8960ab; } else { kgsl_3d0_pdata->iommu_count = 1; + if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) { kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000; kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000; diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c index 3c66d3ab884..b3648959f4e 100644 --- a/arch/arm/mach-msm/clock-8960.c +++ b/arch/arm/mach-msm/clock-8960.c @@ -380,16 +380,57 @@ enum vdd_dig_levels { VDD_DIG_NUM }; +#ifdef CONFIG_GPU_VOLTAGE_TABLE +static int vdd_uv[] = { + [VDD_DIG_NONE] = 0, + [VDD_DIG_LOW] = 945000, + [VDD_DIG_NOMINAL] = 1050000, + [VDD_DIG_HIGH] = 1150000 +}; + +ssize_t get_gpu_vdd_levels_str(char *buf) +{ + int i, len = 0; + + if (buf) + { + for (i = 1; i <= 3; i++) + { + len += sprintf(buf + len, "%d\n", vdd_uv[i]); + } + } + return len; +} + +void set_gpu_vdd_levels(int uv_tbl[]) +{ + int i; + for (i = 1; i <= 3; i++) + { + vdd_uv[i] = uv_tbl[i - 1]; + } +} + +#endif + static int set_vdd_dig_8960(struct clk_vdd_class *vdd_class, int level) { - static const int vdd_uv[] = { - [VDD_DIG_NONE] = 0, - [VDD_DIG_LOW] = 945000, - [VDD_DIG_NOMINAL] = 1050000, - [VDD_DIG_HIGH] = 1150000 - }; - return rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S3, RPM_VREG_VOTER3, - vdd_uv[level], 1150000, 1); +#ifdef CONFIG_GPU_VOLTAGE_TABLE + int ret; + ret = rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S3, RPM_VREG_VOTER3, + vdd_uv[level], vdd_uv[VDD_DIG_HIGH], 1); + //pr_alert("GPU VOLTAGE - %d - %d", vdd_uv[level], ret); + return ret; +#else +static const int vdd_uv[] = { + [VDD_DIG_NONE] = 0, + [VDD_DIG_LOW] = 945000, + [VDD_DIG_NOMINAL] = 1050000, + [VDD_DIG_HIGH] = 1150000 +}; +return rpm_vreg_set_voltage(RPM_VREG_ID_PM8921_S3, RPM_VREG_VOTER3, + vdd_uv[level], 1150000, 1); +#endif } static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig_8960, VDD_DIG_NUM); @@ -3586,7 +3627,7 @@ static unsigned long fmax_gfx3d_8064ab[VDD_DIG_NUM] = { static unsigned long fmax_gfx3d_8064[VDD_DIG_NUM] = { [VDD_DIG_LOW] = 128000000, [VDD_DIG_NOMINAL] = 325000000, - [VDD_DIG_HIGH] = 400000000 + [VDD_DIG_HIGH] = 450000000 }; static unsigned long fmax_gfx3d_8930[VDD_DIG_NUM] = { @@ -6335,7 +6376,7 @@ static struct pll_config pll4_config_393 __initdata = { .main_output_mask = BIT(23), }; -static struct pll_config_regs pll15_regs __initdata = { +static struct pll_config_regs pll15_regs = { .l_reg = MM_PLL3_L_VAL_REG, .m_reg = MM_PLL3_M_VAL_REG, .n_reg = MM_PLL3_N_VAL_REG, @@ -6343,7 +6384,7 @@ static struct pll_config_regs pll15_regs __initdata = { .mode_reg = MM_PLL3_MODE_REG, }; -static struct pll_config pll15_config __initdata = { +static struct pll_config pll15_config = { .l = (0x24 | BVAL(31, 7, 0x620)), .m = 0x1, .n = 0x9, @@ -6600,6 +6641,21 @@ static void __init reg_init(void) } } +extern void configure_pllOC(struct pll_config *config, + struct pll_config_regs *regs, u32 ena_fsm_mode); + +void __ref SetGPUpll_config(u32 loc, unsigned long freq) +{ + /* Program PLL15 to 900MHZ */ + pll15_config.l = loc | BVAL(31, 7, 0x620); + pll15_config.m = 0x1; + pll15_config.n = 0x3; + configure_pllOC(&pll15_config, &pll15_regs, 0); + //fmax_gfx3d_8064ab[VDD_DIG_HIGH] = freq; + //gfx3d_clk.c.fmax = fmax_gfx3d_8064ab; + //gfx3d_clk.freq_tbl[ARRAY_SIZE(clk_tbl_gfx3d)-1].freq_hz = freq; + pr_alert("SET GPU OC-%d-%ld", loc, freq / 1000000); +} struct clock_init_data msm8960_clock_init_data __initdata; static void __init msm8960_clock_pre_init(void) { diff --git a/arch/arm/mach-msm/clock-pll.c b/arch/arm/mach-msm/clock-pll.c index aeb1c5ed0c7..0df064a56d1 100644 --- a/arch/arm/mach-msm/clock-pll.c +++ b/arch/arm/mach-msm/clock-pll.c @@ -501,6 +501,41 @@ void __init __configure_pll(struct pll_config *config, writel_relaxed(regval, PLL_CONFIG_REG(regs)); } +void configure_pllOC(struct pll_config *config, + struct pll_config_regs *regs, u32 ena_fsm_mode) +{ + u32 regval; + + writel_relaxed(config->l, PLL_L_REG(regs)); + writel_relaxed(config->m, PLL_M_REG(regs)); + writel_relaxed(config->n, PLL_N_REG(regs)); + + regval = readl_relaxed(PLL_CONFIG_REG(regs)); + + /* Enable the MN accumulator */ + if (config->mn_ena_mask) { + regval &= ~config->mn_ena_mask; + regval |= config->mn_ena_val; + } + + /* Enable the main output */ + if (config->main_output_mask) { + regval &= ~config->main_output_mask; + regval |= config->main_output_val; + } + + /* Set pre-divider and post-divider values */ + regval &= ~config->pre_div_mask; + regval |= config->pre_div_val; + regval &= ~config->post_div_mask; + regval |= config->post_div_val; + + /* Select VCO setting */ + regval &= ~config->vco_mask; + regval |= config->vco_val; + writel_relaxed(regval, PLL_CONFIG_REG(regs)); +} + void __init configure_sr_pll(struct pll_config *config, struct pll_config_regs *regs, u32 ena_fsm_mode) { diff --git a/arch/arm/mach-msm/cpufreq.c b/arch/arm/mach-msm/cpufreq.c index 9d9ea5cb3c9..2f23f563714 100644 --- a/arch/arm/mach-msm/cpufreq.c +++ b/arch/arm/mach-msm/cpufreq.c @@ -32,6 +32,13 @@ #include "acpuclock.h" +/* maxscroff */ +uint32_t maxscroff_freq = 1026000; +uint32_t maxscroff = 1; + +/* ex max freq */ +uint32_t ex_max_freq; + struct cpufreq_suspend_t { struct mutex suspend_mutex; int device_suspended; @@ -49,12 +56,35 @@ struct cpu_freq { static DEFINE_PER_CPU(struct cpu_freq, cpu_freq_info); +/**maxscroff**/ +static int __init cpufreq_read_arg_maxscroff(char *max_so) +{ + if (strcmp(max_so, "0") == 0) { + maxscroff = 0; + } else if (strcmp(max_so, "1") == 0) { + maxscroff = 1; + } else { + maxscroff = 0; + } + return 1; +} + +__setup("max_so=", cpufreq_read_arg_maxscroff); +/**end maxscroff**/ + static int set_cpu_freq(struct cpufreq_policy *policy, unsigned int new_freq) { int ret = 0; struct cpufreq_freqs freqs; struct cpu_freq *limit = &per_cpu(cpu_freq_info, policy->cpu); +#ifdef CONFIG_TURBO_BOOST + if (num_online_cpus() > 2) { + if (new_freq > STOCK_CPU_MAX_SPEED) + new_freq = STOCK_CPU_MAX_SPEED; + } +#endif + if (limit->limits_init) { if (new_freq > limit->allowed_max) { new_freq = limit->allowed_max; @@ -192,7 +222,7 @@ int msm_cpufreq_set_freq_limits(uint32_t cpu, uint32_t min, uint32_t max) } EXPORT_SYMBOL(msm_cpufreq_set_freq_limits); -static int __cpuinit msm_cpufreq_init(struct cpufreq_policy *policy) +static int msm_cpufreq_init(struct cpufreq_policy *policy) { int cur_freq; int index; @@ -249,7 +279,7 @@ static int __cpuinit msm_cpufreq_init(struct cpufreq_policy *policy) return 0; } -static int __cpuinit msm_cpufreq_cpu_callback(struct notifier_block *nfb, +static int msm_cpufreq_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -306,8 +336,139 @@ static int msm_cpufreq_resume(struct cpufreq_policy *policy) return 0; } +/** max freq interface **/ + +static ssize_t show_ex_max_freq(struct cpufreq_policy *policy, char *buf) +{ + if (!ex_max_freq) + ex_max_freq = policy->max; + + return sprintf(buf, "%u\n", ex_max_freq); +} + +static ssize_t store_ex_max_freq(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + unsigned int freq = 0; + int ret, cpu; + int index; + struct cpufreq_frequency_table *freq_table = cpufreq_frequency_get_table(policy->cpu); + + if (!freq_table) + return -EINVAL; + + ret = sscanf(buf, "%u", &freq); + if (ret != 1) + return -EINVAL; + + mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex); + + ret = cpufreq_frequency_table_target(policy, freq_table, freq, + CPUFREQ_RELATION_H, &index); + if (ret) + goto out; + + ex_max_freq = freq_table[index].frequency; + + for_each_possible_cpu(cpu) { + msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, ex_max_freq); + } + cpufreq_update_policy(cpu); + + ret = count; + +out: + mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex); + return ret; +} + +struct freq_attr msm_cpufreq_attr_ex_max_freq = { + .attr = { .name = "ex_max_freq", + .mode = 0666, + }, + .show = show_ex_max_freq, + .store = store_ex_max_freq, +}; +/** end max freq interface **/ + +/** maxscreen off sysfs interface **/ + +static ssize_t show_max_screen_off_khz(struct cpufreq_policy *policy, char *buf) +{ + return sprintf(buf, "%u\n", maxscroff_freq); +} + +static ssize_t store_max_screen_off_khz(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + unsigned int freq = 0; + int ret; + int index; + struct cpufreq_frequency_table *freq_table = cpufreq_frequency_get_table(policy->cpu); + + if (!freq_table) + return -EINVAL; + + ret = sscanf(buf, "%u", &freq); + if (ret != 1) + return -EINVAL; + + mutex_lock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex); + + ret = cpufreq_frequency_table_target(policy, freq_table, freq, + CPUFREQ_RELATION_H, &index); + if (ret) + goto out; + + maxscroff_freq = freq_table[index].frequency; + + ret = count; + +out: + mutex_unlock(&per_cpu(cpufreq_suspend, policy->cpu).suspend_mutex); + return ret; +} + +struct freq_attr msm_cpufreq_attr_max_screen_off_khz = { + .attr = { .name = "screen_off_max_freq", + .mode = 0666, + }, + .show = show_max_screen_off_khz, + .store = store_max_screen_off_khz, +}; + +static ssize_t show_max_screen_off(struct cpufreq_policy *policy, char *buf) +{ + return sprintf(buf, "%u\n", maxscroff); +} + +static ssize_t store_max_screen_off(struct cpufreq_policy *policy, + const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (maxscroff != buf[0] - '0') + maxscroff = buf[0] - '0'; + + return count; +} + +struct freq_attr msm_cpufreq_attr_max_screen_off = { + .attr = { .name = "screen_off_max", + .mode = 0666, + }, + .show = show_max_screen_off, + .store = store_max_screen_off, +}; + +/** end maxscreen off sysfs interface **/ + + static struct freq_attr *msm_freq_attr[] = { &cpufreq_freq_attr_scaling_available_freqs, +/** maxscreen off sysfs interface **/ + &msm_cpufreq_attr_max_screen_off_khz, + &msm_cpufreq_attr_max_screen_off, + &msm_cpufreq_attr_ex_max_freq, NULL, }; diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c index 862437a3bbe..a17621f21c6 100644 --- a/arch/arm/mach-msm/devices-8064.c +++ b/arch/arm/mach-msm/devices-8064.c @@ -1451,11 +1451,7 @@ struct msm_vidc_platform_data apq8064_vidc_platform_data = { #endif .disable_dmx = 0, .disable_fullhd = 0, -#if (CONFIG_MACH_APQ8064_FLO || CONFIG_MACH_APQ8064_DEB) - .cont_mode_dpb_count = 14, -#else .cont_mode_dpb_count = 18, -#endif .fw_addr = 0x9fe00000, .enable_sec_metadata = 1, }; diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c index 3a949ff98e5..f5d4c5b84d8 100644 --- a/arch/arm/mach-msm/devices-8960.c +++ b/arch/arm/mach-msm/devices-8960.c @@ -3227,7 +3227,30 @@ struct msm_bus_scale_pdata grp2d1_bus_scale_pdata = { }; #endif -static struct resource kgsl_3d0_resources[] = { +struct resource kgsl_3d0_resources_8960ab[] = { + { + .name = KGSL_3D0_REG_MEMORY, + .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, /* Shader Mem Address (8960AB) */ + .end = 0x0431ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_IRQ, + .start = GFX3D_IRQ, + .end = GFX3D_IRQ, + .flags = IORESOURCE_IRQ, + }, +}; + +int kgsl_num_resources_8960ab = ARRAY_SIZE(kgsl_3d0_resources_8960ab); + +static struct resource kgsl_3d0_resources_8960[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ @@ -3298,7 +3321,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = ARRAY_SIZE(grp3d_freq) + 1, .set_grp_async = NULL, .idle_timeout = HZ/12, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp3d_bus_scale_pdata, @@ -3311,8 +3333,8 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { struct platform_device msm_kgsl_3d0 = { .name = "kgsl-3d0", .id = 0, - .num_resources = ARRAY_SIZE(kgsl_3d0_resources), - .resource = kgsl_3d0_resources, + .num_resources = ARRAY_SIZE(kgsl_3d0_resources_8960), + .resource = kgsl_3d0_resources_8960, .dev = { .platform_data = &kgsl_3d0_pdata, }, @@ -3365,7 +3387,6 @@ static struct kgsl_device_platform_data kgsl_2d0_pdata = { .num_levels = ARRAY_SIZE(grp2d_freq) + 1, .set_grp_async = NULL, .idle_timeout = HZ/5, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp2d0_bus_scale_pdata, @@ -3432,7 +3453,6 @@ static struct kgsl_device_platform_data kgsl_2d1_pdata = { .num_levels = ARRAY_SIZE(grp2d_freq) + 1, .set_grp_async = NULL, .idle_timeout = HZ/5, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp2d1_bus_scale_pdata, diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c index c08de763bf3..6c86743c33f 100644 --- a/arch/arm/mach-msm/devices-msm7x27a.c +++ b/arch/arm/mach-msm/devices-msm7x27a.c @@ -889,7 +889,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .set_grp_async = set_grp_xbar_async, .idle_timeout = HZ, .strtstp_sleepwake = true, - .nap_allowed = false, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM, }; diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c index fd4e56d8ef9..0a6a6793eb1 100644 --- a/arch/arm/mach-msm/devices-msm7x30.c +++ b/arch/arm/mach-msm/devices-msm7x30.c @@ -1295,7 +1295,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 3, .set_grp_async = set_grp3d_async, .idle_timeout = HZ/20, - .nap_allowed = true, .idle_needed = true, .clk_map = KGSL_CLK_SRC | KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM, @@ -1338,7 +1337,6 @@ static struct kgsl_device_platform_data kgsl_2d0_pdata = { /* HW workaround, run Z180 SYNC @ 192 MHZ */ .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .idle_needed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, }; diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c index c71ecb9cce0..39b2e8d5b32 100644 --- a/arch/arm/mach-msm/devices-msm8x60.c +++ b/arch/arm/mach-msm/devices-msm8x60.c @@ -738,7 +738,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 5, .set_grp_async = NULL, .idle_timeout = HZ/5, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp3d_bus_scale_pdata, @@ -785,7 +784,6 @@ static struct kgsl_device_platform_data kgsl_2d0_pdata = { .num_levels = 2, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp2d0_bus_scale_pdata, @@ -832,7 +830,6 @@ static struct kgsl_device_platform_data kgsl_2d1_pdata = { .num_levels = 2, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE, #ifdef CONFIG_MSM_BUS_SCALING .bus_scale_table = &grp2d1_bus_scale_pdata, diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h index 5f3aa3a43f6..5e067eab7cc 100644 --- a/arch/arm/mach-msm/devices.h +++ b/arch/arm/mach-msm/devices.h @@ -319,6 +319,9 @@ extern struct platform_device msm_kgsl_3d0; extern struct platform_device msm_kgsl_2d0; extern struct platform_device msm_kgsl_2d1; +extern struct resource kgsl_3d0_resources_8960ab[]; +extern int kgsl_num_resources_8960ab; + extern struct platform_device msm_mipi_dsi1_device; extern struct platform_device mipi_dsi_device; extern struct platform_device msm_lvds_device; diff --git a/arch/arm/mach-msm/fastchg.c b/arch/arm/mach-msm/fastchg.c new file mode 100644 index 00000000000..228acee5525 --- /dev/null +++ b/arch/arm/mach-msm/fastchg.c @@ -0,0 +1,104 @@ +/* + * Author: Chad Froebel + * + * Simple port to Nexus 4 : motley + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +/* + * Possible values for "force_fast_charge" are : + * + * 0 - disabled (default) + * 1 - substitute AC to USB unconditional +*/ + +#include +#include +#include +#include + +int force_fast_charge = 0; +static int __init get_fastcharge_opt(char *ffc) +{ + if (strcmp(ffc, "0") == 0) { + force_fast_charge = 0; + } else if (strcmp(ffc, "1") == 0) { + force_fast_charge = 1; + } else { + force_fast_charge = 0; + } + return 1; +} + +__setup("ffc=", get_fastcharge_opt); + +static ssize_t force_fast_charge_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", force_fast_charge); + return count; +} + +static ssize_t force_fast_charge_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (force_fast_charge != buf[0] - '0') + force_fast_charge = buf[0] - '0'; + + return count; +} + +static struct kobj_attribute force_fast_charge_attribute = +__ATTR(force_fast_charge, 0666, force_fast_charge_show, force_fast_charge_store); + +static struct attribute *force_fast_charge_attrs[] = { +&force_fast_charge_attribute.attr, +NULL, +}; + +static struct attribute_group force_fast_charge_attr_group = { +.attrs = force_fast_charge_attrs, +}; + +/* Initialize fast charge sysfs folder */ +static struct kobject *force_fast_charge_kobj; + +int force_fast_charge_init(void) +{ + int force_fast_charge_retval; + +// force_fast_charge = FAST_CHARGE_DISABLED; /* Forced fast charge disabled by default */ + + force_fast_charge_kobj = kobject_create_and_add("fast_charge", kernel_kobj); + if (!force_fast_charge_kobj) { + return -ENOMEM; + } + + force_fast_charge_retval = sysfs_create_group(force_fast_charge_kobj, &force_fast_charge_attr_group); + + if (force_fast_charge_retval) + kobject_put(force_fast_charge_kobj); + + if (force_fast_charge_retval) + kobject_put(force_fast_charge_kobj); + + return (force_fast_charge_retval); +} + +void force_fast_charge_exit(void) +{ + kobject_put(force_fast_charge_kobj); +} + +module_init(force_fast_charge_init); +module_exit(force_fast_charge_exit); + diff --git a/arch/arm/mach-msm/idle-v7.S b/arch/arm/mach-msm/idle-v7.S index 9e823c39568..6ec38f328be 100644 --- a/arch/arm/mach-msm/idle-v7.S +++ b/arch/arm/mach-msm/idle-v7.S @@ -110,6 +110,7 @@ ENTRY(msm_pm_collapse) mov r2, #1 and r1, r2, r1, ASR #30 /* Check if the cache is write back */ orr r1, r0, r1 + and r1, r1, #1 cmp r1, #1 bne skip bl v7_flush_dcache_all diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h index 31510a87149..d6f13b12609 100644 --- a/arch/arm/mach-msm/include/mach/board.h +++ b/arch/arm/mach-msm/include/mach/board.h @@ -499,7 +499,9 @@ struct msm_fb_platform_data { int (*allow_set_offset)(void); char prim_panel_name[PANEL_NAME_MAX_LEN]; char ext_panel_name[PANEL_NAME_MAX_LEN]; +#ifdef CONFIG_UPDATE_LCDC_LUT int (*update_lcdc_lut)(void); +#endif }; struct msm_hdmi_platform_data { diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h index 59d430f7bd0..7e98a0bfe60 100644 --- a/arch/arm/mach-msm/include/mach/iommu_domains.h +++ b/arch/arm/mach-msm/include/mach/iommu_domains.h @@ -114,6 +114,7 @@ extern void msm_iommu_unmap_contig_buffer(unsigned long iova, unsigned long size); extern int msm_register_domain(struct msm_iova_layout *layout); +extern int msm_unregister_domain(struct iommu_domain *domain); #else static inline struct iommu_domain @@ -177,6 +178,11 @@ static inline int msm_register_domain(struct msm_iova_layout *layout) { return -ENODEV; } + +static inline int msm_unregister_domain(struct iommu_domain *domain) +{ + return -ENODEV; +} #endif #endif diff --git a/arch/arm/mach-msm/include/mach/kgsl.h b/arch/arm/mach-msm/include/mach/kgsl.h index a22b628bb19..2d7e8df5d56 100644 --- a/arch/arm/mach-msm/include/mach/kgsl.h +++ b/arch/arm/mach-msm/include/mach/kgsl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, 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 @@ -20,13 +20,15 @@ #define KGSL_CLK_MEM 0x00000008 #define KGSL_CLK_MEM_IFACE 0x00000010 #define KGSL_CLK_AXI 0x00000020 +#define KGSL_CLK_ALT_MEM_IFACE 0x00000040 -#define KGSL_MAX_PWRLEVELS 5 +#define KGSL_MAX_PWRLEVELS 10 #define KGSL_CONVERT_TO_MBPS(val) \ (val*1000*1000U) #define KGSL_3D0_REG_MEMORY "kgsl_3d0_reg_memory" +#define KGSL_3D0_SHADER_MEMORY "kgsl_3d0_shader_memory" #define KGSL_3D0_IRQ "kgsl_3d0_irq" #define KGSL_2D0_REG_MEMORY "kgsl_2d0_reg_memory" #define KGSL_2D0_IRQ "kgsl_2d0_irq" @@ -49,9 +51,19 @@ struct kgsl_iommu_ctx { enum kgsl_iommu_context_id ctx_id; }; +/* + * struct kgsl_device_iommu_data - Struct holding iommu context data obtained + * from dtsi file + * @iommu_ctxs: Pointer to array of struct hoding context name and id + * @iommu_ctx_count: Number of contexts defined in the dtsi file + * @iommu_halt_enable: Indicated if smmu halt h/w feature is supported + * @physstart: Start of iommu registers physical address + * @physend: End of iommu registers physical address + */ struct kgsl_device_iommu_data { const struct kgsl_iommu_ctx *iommu_ctxs; int iommu_ctx_count; + int iommu_halt_enable; unsigned int physstart; unsigned int physend; }; @@ -69,13 +81,15 @@ struct kgsl_device_platform_data { int (*set_grp_async)(void); unsigned int idle_timeout; bool strtstp_sleepwake; - unsigned int nap_allowed; unsigned int clk_map; unsigned int idle_needed; + unsigned int step_mul; struct msm_bus_scale_pdata *bus_scale_table; struct kgsl_device_iommu_data *iommu_data; int iommu_count; struct msm_dcvs_core_info *core_info; + struct coresight_device *csdev; + struct coresight_platform_data *coresight_pdata; unsigned int chipid; }; diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h index 83296117c70..43b0e063a99 100644 --- a/arch/arm/mach-msm/include/mach/memory.h +++ b/arch/arm/mach-msm/include/mach/memory.h @@ -20,6 +20,14 @@ /* physical offset of RAM */ #define PLAT_PHYS_OFFSET UL(CONFIG_PHYS_OFFSET) +#if defined(CONFIG_KEXEC_HARDBOOT) +#if defined(CONFIG_MACH_APQ8064_FLO) +#define KEXEC_HB_PAGE_ADDR UL(0x88C00000) +#else +#error "Adress for kexec hardboot page not defined" +#endif +#endif + #define MAX_PHYSMEM_BITS 32 #define SECTION_SIZE_BITS 28 diff --git a/arch/arm/mach-msm/include/mach/scm.h b/arch/arm/mach-msm/include/mach/scm.h index 8a06fe3b8ac..56f2146a18a 100644 --- a/arch/arm/mach-msm/include/mach/scm.h +++ b/arch/arm/mach-msm/include/mach/scm.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, 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 @@ -31,6 +31,7 @@ extern int scm_call(u32 svc_id, u32 cmd_id, const void *cmd_buf, size_t cmd_len, extern s32 scm_call_atomic1(u32 svc, u32 cmd, u32 arg1); extern s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2); +extern s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3); extern s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 *ret1, u32 *ret2); @@ -58,6 +59,12 @@ static inline s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) return 0; } +static inline s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, + u32 arg3) +{ + return 0; +} + static inline s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 *ret1, u32 *ret2) { diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c index 6053be31a7c..d87b4b4646d 100644 --- a/arch/arm/mach-msm/iommu_domains.c +++ b/arch/arm/mach-msm/iommu_domains.c @@ -17,6 +17,8 @@ #include #include #include +#include +#include #include #include #include @@ -35,9 +37,14 @@ struct msm_iova_data { int domain_num; }; +struct msm_iommu_data_entry { + struct list_head list; + void *data; +}; + static struct rb_root domain_root; DEFINE_MUTEX(domain_mutex); -static atomic_t domain_nums = ATOMIC_INIT(-1); +static DEFINE_IDA(domain_nums); int msm_use_iommu() { @@ -254,6 +261,27 @@ static int add_domain(struct msm_iova_data *node) return 0; } +static int remove_domain(struct iommu_domain *domain) +{ + struct rb_root *root = &domain_root; + struct rb_node *n; + struct msm_iova_data *node; + int ret = -EINVAL; + + mutex_lock(&domain_mutex); + + for (n = rb_first(root); n; n = rb_next(n)) { + node = rb_entry(n, struct msm_iova_data, node); + if (node->domain == domain) { + rb_erase(&node->node, &domain_root); + ret = 0; + break; + } + } + mutex_unlock(&domain_mutex); + return ret; +} + struct iommu_domain *msm_get_iommu_domain(int domain_num) { struct msm_iova_data *data; @@ -266,6 +294,27 @@ struct iommu_domain *msm_get_iommu_domain(int domain_num) return NULL; } +static struct msm_iova_data *msm_domain_to_iova_data(struct iommu_domain + const *domain) +{ + struct rb_root *root = &domain_root; + struct rb_node *n; + struct msm_iova_data *node; + struct msm_iova_data *iova_data = ERR_PTR(-EINVAL); + + mutex_lock(&domain_mutex); + + for (n = rb_first(root); n; n = rb_next(n)) { + node = rb_entry(n, struct msm_iova_data, node); + if (node->domain == domain) { + iova_data = node; + break; + } + } + mutex_unlock(&domain_mutex); + return iova_data; +} + int msm_allocate_iova_address(unsigned int iommu_domain, unsigned int partition_no, unsigned long size, @@ -351,11 +400,11 @@ int msm_register_domain(struct msm_iova_layout *layout) if (!data) return -ENOMEM; - pools = kmalloc(sizeof(struct mem_pool) * layout->npartitions, + pools = kzalloc(sizeof(struct mem_pool) * layout->npartitions, GFP_KERNEL); if (!pools) - goto out; + goto free_data; for (i = 0; i < layout->npartitions; i++) { if (layout->partitions[i].size == 0) @@ -389,22 +438,64 @@ int msm_register_domain(struct msm_iova_layout *layout) data->pools = pools; data->npools = layout->npartitions; - data->domain_num = atomic_inc_return(&domain_nums); + data->domain_num = ida_simple_get(&domain_nums, 0, 0, GFP_KERNEL); + if (data->domain_num < 0) + goto free_pools; + data->domain = iommu_domain_alloc(&platform_bus_type, layout->domain_flags); + if (!data->domain) + goto free_domain_num; add_domain(data); return data->domain_num; -out: +free_domain_num: + ida_simple_remove(&domain_nums, data->domain_num); + +free_pools: + for (i = 0; i < layout->npartitions; i++) { + if (pools[i].gpool) + gen_pool_destroy(pools[i].gpool); + } + kfree(pools); +free_data: kfree(data); return -EINVAL; } EXPORT_SYMBOL(msm_register_domain); -static int __init iommu_domain_probe(struct platform_device *pdev) +int msm_unregister_domain(struct iommu_domain *domain) +{ + unsigned int i; + struct msm_iova_data *data = msm_domain_to_iova_data(domain); + + if (IS_ERR_OR_NULL(data)) { + pr_err("%s: Could not find iova_data\n", __func__); + return -EINVAL; + } + + if (remove_domain(data->domain)) { + pr_err("%s: Domain not found. Failed to remove domain\n", + __func__); + } + + iommu_domain_free(domain); + + ida_simple_remove(&domain_nums, data->domain_num); + + for (i = 0; i < data->npools; ++i) + gen_pool_destroy(data->pools[i].gpool); + + kfree(data->pools); + kfree(data); + return 0; +} +EXPORT_SYMBOL(msm_unregister_domain); + +static int iommu_domain_probe(struct platform_device *pdev) { struct iommu_domains_pdata *p = pdev->dev.platform_data; int i, j; diff --git a/arch/arm/mach-msm/lge/Kconfig b/arch/arm/mach-msm/lge/Kconfig index 8916d9ac0d9..2c5c1fdd3fa 100644 --- a/arch/arm/mach-msm/lge/Kconfig +++ b/arch/arm/mach-msm/lge/Kconfig @@ -22,13 +22,6 @@ config UPDATE_LCDC_LUT help Set initial Qualcomm LCDC Look Up Table. -config LCD_KCAL - bool "Interface to calibrate LCD color temperature" - default n - depends on MACH_LGE && UPDATE_LCDC_LUT - help - Interface to calibrate LCD color temperature - config EARJACK_DEBUGGER bool "Earjack UART debugger support" depends on MACH_APQ8064_MAKO diff --git a/arch/arm/mach-msm/lge/mako/board-mako-gpu.c b/arch/arm/mach-msm/lge/mako/board-mako-gpu.c index 28c9515afe8..a2d6ac04781 100644 --- a/arch/arm/mach-msm/lge/mako/board-mako-gpu.c +++ b/arch/arm/mach-msm/lge/mako/board-mako-gpu.c @@ -183,6 +183,12 @@ static struct resource kgsl_3d0_resources[] = { { .name = KGSL_3D0_REG_MEMORY, .start = 0x04300000, /* GFX3D address */ + .end = 0x0430ffff, + .flags = IORESOURCE_MEM, + }, + { + .name = KGSL_3D0_SHADER_MEMORY, + .start = 0x04310000, .end = 0x0431ffff, .flags = IORESOURCE_MEM, }, @@ -250,7 +256,6 @@ static struct kgsl_device_platform_data kgsl_3d0_pdata = { .num_levels = 5, .set_grp_async = NULL, .idle_timeout = HZ/10, - .nap_allowed = true, .strtstp_sleepwake = true, .clk_map = KGSL_CLK_CORE | KGSL_CLK_IFACE | KGSL_CLK_MEM_IFACE, #ifdef CONFIG_MSM_BUS_SCALING diff --git a/arch/arm/mach-msm/mdm_common.c b/arch/arm/mach-msm/mdm_common.c index 1c10427d878..2d3ee630587 100644 --- a/arch/arm/mach-msm/mdm_common.c +++ b/arch/arm/mach-msm/mdm_common.c @@ -111,6 +111,7 @@ static DEFINE_SPINLOCK(ssr_lock); static unsigned int mdm_debug_mask; int vddmin_gpios_sent; static struct mdm_ops *mdm_ops; +static struct mutex restart_lock; static void mdm_device_list_add(struct mdm_device *mdev) { @@ -361,6 +362,32 @@ static void mdm_update_gpio_configs(struct mdm_device *mdev, } } +static int reset_mdm(struct mdm_modem_drv *mdm_drv) +{ + int value; + + pr_info("%s++\n", __func__); + + if (!mutex_trylock(&restart_lock)) + return -EINVAL; + + value = gpio_get_value(mdm_drv->mdm2ap_status_gpio); + if (value == 0 || atomic_read(&mdm_drv->mdm_ready) == 0) { + pr_err("%s: mdm_status = %d, mdm_ready = %d, return\n", + __func__, value, atomic_read(&mdm_drv->mdm_ready)); + mutex_unlock(&restart_lock); + return -EINVAL; + } + + atomic_set(&mdm_drv->mdm_ready, 0); + mutex_unlock(&restart_lock); + + subsystem_restart(EXTERNAL_MODEM); + + pr_info("%s--\n", __func__); + return 0; +} + static long mdm_modem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) { @@ -383,6 +410,10 @@ static long mdm_modem_ioctl(struct file *filp, unsigned int cmd, __func__, mdev->mdm_data.device_id); mdm_ops->power_on_mdm_cb(mdm_drv); break; + case RESET_CHARM: + pr_info("RESET_CHARM"); + ret = reset_mdm(mdm_drv); + break; case CHECK_FOR_BOOT: if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0) put_user(1, (unsigned long __user *) arg); @@ -1089,6 +1120,8 @@ static int __devinit mdm_modem_probe(struct platform_device *pdev) mdm_ops->power_on_mdm_cb(&mdev->mdm_data); } + mutex_init(&restart_lock); + return ret; init_err: @@ -1107,6 +1140,8 @@ static int __devexit mdm_modem_remove(struct platform_device *pdev) ret = misc_deregister(&mdev->misc_device); mdm_device_list_remove(mdev); kfree(mdev); + mutex_destroy(&restart_lock); + return ret; } diff --git a/arch/arm/mach-msm/msm-sleeper.c b/arch/arm/mach-msm/msm-sleeper.c new file mode 100644 index 00000000000..3b4c064d2b2 --- /dev/null +++ b/arch/arm/mach-msm/msm-sleeper.c @@ -0,0 +1,85 @@ +/* + * ElementalX msm-sleeper by flar2 + * + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 + +#define MSM_SLEEPER_MAJOR_VERSION 1 +#define MSM_SLEEPER_MINOR_VERSION 2 + +extern uint32_t maxscroff; +extern uint32_t maxscroff_freq; +extern uint32_t ex_max_freq; +static int limit_set = 0; + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void msm_sleeper_early_suspend(struct early_suspend *h) +{ + int cpu; + + if (maxscroff) { + for_each_possible_cpu(cpu) { + msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, maxscroff_freq); + pr_info("msm-sleeper: limit max frequency to: %d\n", maxscroff_freq); + } + limit_set = 1; + } + return; +} + +static void msm_sleeper_late_resume(struct early_suspend *h) +{ + int cpu; + + if (!limit_set) + return; + + for_each_possible_cpu(cpu) { + msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, ex_max_freq); + pr_info("msm-sleeper: restore max frequency.\n"); + } + limit_set = 0; + return; +} + +static struct early_suspend msm_sleeper_early_suspend_driver = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 10, + .suspend = msm_sleeper_early_suspend, + .resume = msm_sleeper_late_resume, +}; +#endif + +static int __init msm_sleeper_init(void) +{ + pr_info("msm-sleeper version %d.%d\n", + MSM_SLEEPER_MAJOR_VERSION, + MSM_SLEEPER_MINOR_VERSION); + +#ifdef CONFIG_HAS_EARLYSUSPEND + register_early_suspend(&msm_sleeper_early_suspend_driver); +#endif + return 0; +} + +MODULE_AUTHOR("flar2 "); +MODULE_DESCRIPTION("'msm-sleeper' - Limit max frequency while screen is off"); +MODULE_LICENSE("GPL"); + +late_initcall(msm_sleeper_init); + diff --git a/arch/arm/mach-msm/msm_dcvs.c b/arch/arm/mach-msm/msm_dcvs.c index 9e0be639597..ece2384c38a 100644 --- a/arch/arm/mach-msm/msm_dcvs.c +++ b/arch/arm/mach-msm/msm_dcvs.c @@ -146,7 +146,7 @@ static struct dcvs_core core_list[CORES_MAX]; static struct kobject *cores_kobj; -#define DCVS_MAX_NUM_FREQS 15 +#define DCVS_MAX_NUM_FREQS 27 static struct msm_dcvs_freq_entry cpu_freq_tbl[DCVS_MAX_NUM_FREQS]; static unsigned num_cpu_freqs; static struct msm_dcvs_platform_data *dcvs_pdata; diff --git a/arch/arm/mach-msm/msm_hotplug.c b/arch/arm/mach-msm/msm_hotplug.c new file mode 100644 index 00000000000..0ccaeb61941 --- /dev/null +++ b/arch/arm/mach-msm/msm_hotplug.c @@ -0,0 +1,1431 @@ +/* + * MSM Hotplug Driver + * + * Copyright (c) 2013-2014, Fluxi + * Copyright (c) 2010-2014, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_LCD_NOTIFY +#include +#elif defined(CONFIG_POWERSUSPEND) +#include +#elif defined(CONFIG_HAS_EARLYSUSPEND) +#include +#endif +#include +#include +#include +#include +#include + +#define MSM_HOTPLUG "msm_hotplug" +#define HOTPLUG_ENABLED 1 +#define DEFAULT_UPDATE_RATE HZ / 10 +#define START_DELAY HZ * 20 +#define MIN_INPUT_INTERVAL 150 * 1000L +#define DEFAULT_HISTORY_SIZE 10 +#define DEFAULT_DOWN_LOCK_DUR 500 +#define DEFAULT_BOOST_LOCK_DUR 2500 * 1000L +#define DEFAULT_NR_CPUS_BOOSTED 2 +#define DEFAULT_MIN_CPUS_ONLINE 1 +#define DEFAULT_MAX_CPUS_ONLINE NR_CPUS +#define DEFAULT_FAST_LANE_LOAD 400 +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) +#define DEFAULT_SUSPEND_DEFER_TIME 10 +#define DEFAULT_MAX_CPUS_ONLINE_SUSP NR_CPUS / 2 +#endif + +static unsigned int debug = 0; +module_param_named(debug_mask, debug, uint, 0644); + +#define dprintk(msg...) \ +do { \ + if (debug) \ + pr_info(msg); \ +} while (0) + +static struct cpu_hotplug { + unsigned int msm_enabled; +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + unsigned int suspended; + unsigned int suspend_defer_time; + unsigned int min_cpus_online_res; + unsigned int max_cpus_online_res; + unsigned int max_cpus_online_susp; +#endif + unsigned int target_cpus; + unsigned int min_cpus_online; + unsigned int max_cpus_online; + unsigned int cpus_boosted; + unsigned int offline_load; + unsigned int down_lock_dur; + u64 boost_lock_dur; + u64 last_input; + unsigned int fast_lane_load; + struct work_struct up_work; + struct work_struct down_work; +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + struct delayed_work suspend_work; + struct work_struct resume_work; + struct mutex msm_hotplug_mutex; +#ifdef CONFIG_LCD_NOTIFY + struct notifier_block notif; +#endif +#endif +} hotplug = { + .msm_enabled = HOTPLUG_ENABLED, + .min_cpus_online = DEFAULT_MIN_CPUS_ONLINE, + .max_cpus_online = DEFAULT_MAX_CPUS_ONLINE, +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + .suspended = 0, + .suspend_defer_time = DEFAULT_SUSPEND_DEFER_TIME, + .min_cpus_online_res = DEFAULT_MIN_CPUS_ONLINE, + .max_cpus_online_res = DEFAULT_MAX_CPUS_ONLINE, + .max_cpus_online_susp = DEFAULT_MAX_CPUS_ONLINE_SUSP, +#endif + .cpus_boosted = DEFAULT_NR_CPUS_BOOSTED, + .down_lock_dur = DEFAULT_DOWN_LOCK_DUR, + .boost_lock_dur = DEFAULT_BOOST_LOCK_DUR, + .fast_lane_load = DEFAULT_FAST_LANE_LOAD +}; + +static struct workqueue_struct *hotplug_wq; +static struct delayed_work hotplug_work; + +static u64 last_boost_time; +static unsigned int default_update_rates[] = { DEFAULT_UPDATE_RATE }; + +static struct cpu_stats { + unsigned int *update_rates; + int nupdate_rates; + spinlock_t update_rates_lock; + unsigned int *load_hist; + unsigned int hist_size; + unsigned int hist_cnt; + unsigned int min_cpus; + unsigned int total_cpus; + unsigned int online_cpus; + unsigned int cur_avg_load; + unsigned int cur_max_load; + struct mutex stats_mutex; +} stats = { + .update_rates = default_update_rates, + .nupdate_rates = ARRAY_SIZE(default_update_rates), + .hist_size = DEFAULT_HISTORY_SIZE, + .min_cpus = 1, + .total_cpus = NR_CPUS +}; + +struct down_lock { + unsigned int locked; + struct delayed_work lock_rem; +}; + +static DEFINE_PER_CPU(struct down_lock, lock_info); + +struct cpu_load_data { + u64 prev_cpu_idle; + u64 prev_cpu_wall; + unsigned int avg_load_maxfreq; + unsigned int cur_load_maxfreq; + unsigned int samples; + unsigned int window_size; + cpumask_var_t related_cpus; +}; + +static DEFINE_PER_CPU(struct cpu_load_data, cpuload); + +static bool io_is_busy; + +static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) +{ + u64 idle_time; + u64 cur_wall_time; + u64 busy_time; + + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + + busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; + + idle_time = cur_wall_time - busy_time; + if (wall) + *wall = jiffies_to_usecs(cur_wall_time); + + return jiffies_to_usecs(idle_time); +} + +static inline u64 get_cpu_idle_time(unsigned int cpu, + u64 *wall) +{ + u64 idle_time = get_cpu_idle_time_us(cpu, io_is_busy ? wall : NULL); + + if (idle_time == -1ULL) + return get_cpu_idle_time_jiffy(cpu, wall); + else if (!io_is_busy) + idle_time += get_cpu_iowait_time_us(cpu, wall); + + return idle_time; +} + +static int update_average_load(unsigned int cpu) +{ + int ret; + unsigned int idle_time, wall_time; + unsigned int cur_load, load_max_freq; + u64 cur_wall_time, cur_idle_time; + struct cpu_load_data *pcpu = &per_cpu(cpuload, cpu); + struct cpufreq_policy policy; + + ret = cpufreq_get_policy(&policy, cpu); + if (ret) + return -EINVAL; + + cur_idle_time = get_cpu_idle_time(cpu, &cur_wall_time); + + wall_time = (unsigned int) (cur_wall_time - pcpu->prev_cpu_wall); + pcpu->prev_cpu_wall = cur_wall_time; + + idle_time = (unsigned int) (cur_idle_time - pcpu->prev_cpu_idle); + pcpu->prev_cpu_idle = cur_idle_time; + + if (unlikely(!wall_time || wall_time < idle_time)) + return 0; + + cur_load = 100 * (wall_time - idle_time) / wall_time; + + /* Calculate the scaled load across cpu */ + load_max_freq = (cur_load * policy.cur) / policy.max; + + if (!pcpu->avg_load_maxfreq) { + /* This is the first sample in this window */ + pcpu->avg_load_maxfreq = load_max_freq; + pcpu->window_size = wall_time; + } else { + /* + * The is already a sample available in this window. + * Compute weighted average with prev entry, so that + * we get the precise weighted load. + */ + pcpu->avg_load_maxfreq = + ((pcpu->avg_load_maxfreq * pcpu->window_size) + + (load_max_freq * wall_time)) / + (wall_time + pcpu->window_size); + + pcpu->window_size += wall_time; + } + + return 0; +} + +static unsigned int load_at_max_freq(void) +{ + int cpu; + unsigned int total_load = 0, max_load = 0; + struct cpu_load_data *pcpu; + + for_each_online_cpu(cpu) { + pcpu = &per_cpu(cpuload, cpu); + update_average_load(cpu); + total_load += pcpu->avg_load_maxfreq; + pcpu->cur_load_maxfreq = pcpu->avg_load_maxfreq; + max_load = max(max_load, pcpu->avg_load_maxfreq); + pcpu->avg_load_maxfreq = 0; + } + stats.cur_max_load = max_load; + + return total_load; +} +static void update_load_stats(void) +{ + unsigned int i, j; + unsigned int load = 0; + + mutex_lock(&stats.stats_mutex); + stats.online_cpus = num_online_cpus(); + + if (stats.hist_size > 1) { + stats.load_hist[stats.hist_cnt] = load_at_max_freq(); + } else { + stats.cur_avg_load = load_at_max_freq(); + mutex_unlock(&stats.stats_mutex); + return; + } + + for (i = 0, j = stats.hist_cnt; i < stats.hist_size; i++, j--) { + load += stats.load_hist[j]; + + if (j == 0) + j = stats.hist_size; + } + + if (++stats.hist_cnt == stats.hist_size) + stats.hist_cnt = 0; + + stats.cur_avg_load = load / stats.hist_size; + mutex_unlock(&stats.stats_mutex); +} + +struct loads_tbl { + unsigned int up_threshold; + unsigned int down_threshold; +}; + +#define LOAD_SCALE(u, d) \ +{ \ + .up_threshold = u, \ + .down_threshold = d, \ +} + +static struct loads_tbl loads[] = { + LOAD_SCALE(400, 0), + LOAD_SCALE(75, 0), + LOAD_SCALE(120, 60), + LOAD_SCALE(180, 100), + LOAD_SCALE(410, 160), + LOAD_SCALE(0, 0), +}; + +static void apply_down_lock(unsigned int cpu) +{ + struct down_lock *dl = &per_cpu(lock_info, cpu); + + dl->locked = 1; + queue_delayed_work_on(0, hotplug_wq, &dl->lock_rem, + msecs_to_jiffies(hotplug.down_lock_dur)); +} + +static void remove_down_lock(struct work_struct *work) +{ + struct down_lock *dl = container_of(work, struct down_lock, + lock_rem.work); + dl->locked = 0; +} + +static int check_down_lock(unsigned int cpu) +{ + struct down_lock *dl = &per_cpu(lock_info, cpu); + + return dl->locked; +} + +static int get_lowest_load_cpu(void) +{ + int cpu, lowest_cpu = 0; + unsigned int lowest_load = UINT_MAX; + unsigned int cpu_load[stats.total_cpus]; + unsigned int proj_load; + struct cpu_load_data *pcpu; + + for_each_online_cpu(cpu) { + if (cpu == 0) + continue; + pcpu = &per_cpu(cpuload, cpu); + cpu_load[cpu] = pcpu->cur_load_maxfreq; + if (cpu_load[cpu] < lowest_load) { + lowest_load = cpu_load[cpu]; + lowest_cpu = cpu; + } + } + + proj_load = stats.cur_avg_load - lowest_load; + if (proj_load > loads[stats.online_cpus - 1].up_threshold) + return -EPERM; + + if (hotplug.offline_load && lowest_load >= hotplug.offline_load) + return -EPERM; + + return lowest_cpu; +} + +static void __ref cpu_up_work(struct work_struct *work) +{ + int cpu; + unsigned int target; + + target = hotplug.target_cpus; + + for_each_cpu_not(cpu, cpu_online_mask) { + if (target <= num_online_cpus()) + break; + if (cpu == 0) + continue; + cpu_up(cpu); + apply_down_lock(cpu); + } +} + +static void cpu_down_work(struct work_struct *work) +{ + int cpu, lowest_cpu; + unsigned int target; + + target = hotplug.target_cpus; + + for_each_online_cpu(cpu) { + if (cpu == 0) + continue; + lowest_cpu = get_lowest_load_cpu(); + if (lowest_cpu > 0 && lowest_cpu <= stats.total_cpus) { + if (check_down_lock(lowest_cpu)) + break; + cpu_down(lowest_cpu); + } + if (target >= num_online_cpus()) + break; + } +} + +static void online_cpu(unsigned int target) +{ + unsigned int online_cpus; + + if (!hotplug.msm_enabled) + return; + + online_cpus = num_online_cpus(); + + /* + * Do not online more CPUs if max_cpus_online reached + * and cancel online task if target already achieved. + */ + if (target <= online_cpus || + online_cpus >= hotplug.max_cpus_online) + return; + + hotplug.target_cpus = target; + queue_work_on(0, hotplug_wq, &hotplug.up_work); +} + +static void offline_cpu(unsigned int target) +{ + unsigned int online_cpus; + u64 now; + + if (!hotplug.msm_enabled) + return; + + online_cpus = num_online_cpus(); + + /* + * Do not offline more CPUs if min_cpus_online reached + * and cancel offline task if target already achieved. + */ + if (target >= online_cpus || + online_cpus <= hotplug.min_cpus_online) + return; + + now = ktime_to_us(ktime_get()); + if (online_cpus <= hotplug.cpus_boosted && + (now - hotplug.last_input < hotplug.boost_lock_dur)) + return; + + hotplug.target_cpus = target; + queue_work_on(0, hotplug_wq, &hotplug.down_work); +} + +static unsigned int load_to_update_rate(unsigned int load) +{ + int i, ret; + unsigned long flags; + + spin_lock_irqsave(&stats.update_rates_lock, flags); + + for (i = 0; i < stats.nupdate_rates - 1 && + load >= stats.update_rates[i+1]; i += 2) + ; + + ret = stats.update_rates[i]; + spin_unlock_irqrestore(&stats.update_rates_lock, flags); + return ret; +} + +static void reschedule_hotplug_work(void) +{ + int delay = load_to_update_rate(stats.cur_avg_load); + queue_delayed_work_on(0, hotplug_wq, &hotplug_work, + msecs_to_jiffies(delay)); +} + +static void msm_hotplug_work(struct work_struct *work) +{ + unsigned int i, target = 0; + +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + if (hotplug.suspended && hotplug.max_cpus_online_susp <= 1) { + dprintk("%s: suspended.\n", MSM_HOTPLUG); + return; + } +#endif + + update_load_stats(); + + if (stats.cur_max_load >= hotplug.fast_lane_load) { + /* Enter the fast lane */ + online_cpu(hotplug.max_cpus_online); + goto reschedule; + } + + /* If number of cpus locked, break out early */ + if (hotplug.min_cpus_online == stats.total_cpus) { + if (stats.online_cpus != hotplug.min_cpus_online) + online_cpu(hotplug.min_cpus_online); + goto reschedule; + } else if (hotplug.max_cpus_online == stats.min_cpus) { + if (stats.online_cpus != hotplug.max_cpus_online) + offline_cpu(hotplug.max_cpus_online); + goto reschedule; + } + + for (i = stats.min_cpus; loads[i].up_threshold; i++) { + if (stats.cur_avg_load <= loads[i].up_threshold + && stats.cur_avg_load > loads[i].down_threshold) { + target = i; + break; + } + } + + if (target > hotplug.max_cpus_online) + target = hotplug.max_cpus_online; + else if (target < hotplug.min_cpus_online) + target = hotplug.min_cpus_online; + + if (stats.online_cpus != target) { + if (target > stats.online_cpus) + online_cpu(target); + else if (target < stats.online_cpus) + offline_cpu(target); + } + +reschedule: + dprintk("%s: cur_avg_load: %3u online_cpus: %u target: %u\n", MSM_HOTPLUG, + stats.cur_avg_load, stats.online_cpus, target); + reschedule_hotplug_work(); +} + +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) +static void msm_hotplug_suspend(struct work_struct *work) +{ + int cpu; + + if (!hotplug.msm_enabled) + return; + + mutex_lock(&hotplug.msm_hotplug_mutex); + hotplug.suspended = 1; + hotplug.min_cpus_online_res = hotplug.min_cpus_online; + hotplug.min_cpus_online = 1; + hotplug.max_cpus_online_res = hotplug.max_cpus_online; + hotplug.max_cpus_online = hotplug.max_cpus_online_susp; + mutex_unlock(&hotplug.msm_hotplug_mutex); + + /* Do not cancel hotplug work unless max_cpus_online_susp is 1 */ + if (hotplug.max_cpus_online_susp > 1) + return; + + /* Flush hotplug workqueue */ + flush_workqueue(hotplug_wq); + cancel_delayed_work_sync(&hotplug_work); + + /* Put all sibling cores to sleep */ + for_each_online_cpu(cpu) { + if (cpu == 0) + continue; + cpu_down(cpu); + } +} + +static void __ref msm_hotplug_resume(struct work_struct *work) +{ + int cpu, required_reschedule = 0; + + if (!hotplug.msm_enabled) + return; + + if (hotplug.suspended) { + mutex_lock(&hotplug.msm_hotplug_mutex); + hotplug.suspended = 0; + hotplug.min_cpus_online = hotplug.min_cpus_online_res; + hotplug.max_cpus_online = hotplug.max_cpus_online_res; + mutex_unlock(&hotplug.msm_hotplug_mutex); + /* Initiate hotplug work if it was cancelled */ + if (hotplug.max_cpus_online_susp <= 1) { + required_reschedule = 1; + INIT_DELAYED_WORK(&hotplug_work, msm_hotplug_work); + } + } + + /* Fire up all CPUs */ + for_each_cpu_not(cpu, cpu_online_mask) { + if (cpu == 0) + continue; + cpu_up(cpu); + apply_down_lock(cpu); + } + + /* Resume hotplug workqueue if required */ + if (required_reschedule) + reschedule_hotplug_work(); +} + +#ifdef CONFIG_LCD_NOTIFY +static void __msm_hotplug_suspend(void) +#elif defined(CONFIG_POWERSUSPEND) +static void __msm_hotplug_suspend(struct power_suspend *handler) +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void __msm_hotplug_suspend(struct early_suspend *handler) +#endif +{ + INIT_DELAYED_WORK(&hotplug.suspend_work, msm_hotplug_suspend); + schedule_delayed_work_on(0, &hotplug.suspend_work, + msecs_to_jiffies(hotplug.suspend_defer_time * 1000)); +} + +#ifdef CONFIG_LCD_NOTIFY +static void __msm_hotplug_resume(void) +#elif defined(CONFIG_POWERSUSPEND) +static void __msm_hotplug_resume(struct power_suspend *handler) +#elif defined(CONFIG_HAS_EARLYSUSPEND) +static void __msm_hotplug_resume(struct early_suspend *handler) +#endif +{ + cancel_delayed_work_sync(&hotplug.suspend_work); + schedule_work_on(0, &hotplug.resume_work); +} + +#ifdef CONFIG_LCD_NOTIFY +static int lcd_notifier_callback(struct notifier_block *this, + unsigned long event, void *data) +{ + switch (event) { + case LCD_EVENT_ON_END: + case LCD_EVENT_OFF_START: + break; + case LCD_EVENT_ON_START: + __msm_hotplug_resume(); + break; + case LCD_EVENT_OFF_END: + __msm_hotplug_suspend(); + break; + default: + break; + } + + return NOTIFY_OK; +} +#elif defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) +#ifdef CONFIG_POWERSUSPEND +static struct power_suspend msm_hotplug_power_suspend_driver = { +#else +static struct early_suspend msm_hotplug_early_suspend_driver = { + .level = EARLY_SUSPEND_LEVEL_DISABLE_FB + 10, +#endif + .suspend = __msm_hotplug_suspend, + .resume = __msm_hotplug_resume, +}; +#endif +#endif + +static void hotplug_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) +{ + u64 now; + +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + if (hotplug.suspended) { + dprintk("%s: suspended.\n", MSM_HOTPLUG); + return; + } +#endif + + now = ktime_to_us(ktime_get()); + hotplug.last_input = now; + if (now - last_boost_time < MIN_INPUT_INTERVAL) + return; + + if (num_online_cpus() >= hotplug.cpus_boosted || + hotplug.cpus_boosted <= hotplug.min_cpus_online) + return; + + dprintk("%s: online_cpus: %u boosted\n", MSM_HOTPLUG, + stats.online_cpus); + + online_cpu(hotplug.cpus_boosted); + last_boost_time = ktime_to_us(ktime_get()); +} + +static int hotplug_input_connect(struct input_handler *handler, + struct input_dev *dev, + const struct input_device_id *id) +{ + struct input_handle *handle; + int err; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = handler->name; + + err = input_register_handle(handle); + if (err) + goto err_register; + + err = input_open_device(handle); + if (err) + goto err_open; + + return 0; +err_open: + input_unregister_handle(handle); +err_register: + kfree(handle); + return err; +} + +static void hotplug_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id hotplug_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, /* multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, + }, /* touchpad */ + { }, +}; + +static struct input_handler hotplug_input_handler = { + .event = hotplug_input_event, + .connect = hotplug_input_connect, + .disconnect = hotplug_input_disconnect, + .name = MSM_HOTPLUG, + .id_table = hotplug_ids, +}; + +static int __ref msm_hotplug_start(void) +{ + int cpu, ret = 0; + struct down_lock *dl; + + hotplug_wq = + alloc_workqueue("msm_hotplug_wq", WQ_HIGHPRI | WQ_FREEZABLE, 0); + if (!hotplug_wq) { + pr_err("%s: Failed to allocate hotplug workqueue\n", + MSM_HOTPLUG); + ret = -ENOMEM; + goto err_out; + } + +#ifdef CONFIG_LCD_NOTIFY + hotplug.notif.notifier_call = lcd_notifier_callback; + if (lcd_register_client(&hotplug.notif) != 0) { + pr_err("%s: Failed to register LCD notifier callback\n", + MSM_HOTPLUG); + goto err_dev; + } +#elif defined(CONFIG_POWERSUSPEND) + register_power_suspend(&msm_hotplug_power_suspend_driver); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + register_early_suspend(&msm_hotplug_early_suspend_driver); +#endif + ret = input_register_handler(&hotplug_input_handler); + if (ret) { + pr_err("%s: Failed to register input handler: %d\n", + MSM_HOTPLUG, ret); + goto err_dev; + } + + stats.load_hist = kmalloc(sizeof(stats.hist_size), GFP_KERNEL); + if (!stats.load_hist) { + pr_err("%s: Failed to allocate memory\n", MSM_HOTPLUG); + ret = -ENOMEM; + goto err_dev; + } + + mutex_init(&stats.stats_mutex); +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + mutex_init(&hotplug.msm_hotplug_mutex); +#endif + + INIT_DELAYED_WORK(&hotplug_work, msm_hotplug_work); + INIT_WORK(&hotplug.up_work, cpu_up_work); + INIT_WORK(&hotplug.down_work, cpu_down_work); +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + INIT_DELAYED_WORK(&hotplug.suspend_work, msm_hotplug_suspend); + INIT_WORK(&hotplug.resume_work, msm_hotplug_resume); +#endif + + for_each_possible_cpu(cpu) { + dl = &per_cpu(lock_info, cpu); + INIT_DELAYED_WORK(&dl->lock_rem, remove_down_lock); + } + + /* Fire up all CPUs */ + for_each_cpu_not(cpu, cpu_online_mask) { + if (cpu == 0) + continue; + cpu_up(cpu); + apply_down_lock(cpu); + } + + queue_delayed_work_on(0, hotplug_wq, &hotplug_work, + START_DELAY); + + return ret; +err_dev: + destroy_workqueue(hotplug_wq); +err_out: + hotplug.msm_enabled = 0; + return ret; +} + +static void msm_hotplug_stop(void) +{ + int cpu; + struct down_lock *dl; + + for_each_possible_cpu(cpu) { + dl = &per_cpu(lock_info, cpu); + cancel_delayed_work_sync(&dl->lock_rem); + } +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + cancel_work_sync(&hotplug.resume_work); + cancel_delayed_work_sync(&hotplug.suspend_work); +#endif + cancel_work_sync(&hotplug.down_work); + cancel_work_sync(&hotplug.up_work); + + flush_workqueue(hotplug_wq); + cancel_delayed_work_sync(&hotplug_work); + +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + mutex_destroy(&hotplug.msm_hotplug_mutex); +#endif + mutex_destroy(&stats.stats_mutex); + kfree(stats.load_hist); + +#ifdef CONFIG_LCD_NOTIFY + lcd_unregister_client(&hotplug.notif); + hotplug.notif.notifier_call = NULL; +#elif defined(CONFIG_POWERSUSPEND) + unregister_power_suspend(&msm_hotplug_power_suspend_driver); +#elif defined(CONFIG_HAS_EARLYSUSPEND) + unregister_early_suspend(&msm_hotplug_early_suspend_driver); +#endif + input_unregister_handler(&hotplug_input_handler); + + destroy_workqueue(hotplug_wq); + + /* Put all sibling cores to sleep */ + for_each_online_cpu(cpu) { + if (cpu == 0) + continue; + cpu_down(cpu); + } +} + +static unsigned int *get_tokenized_data(const char *buf, int *num_tokens) +{ + const char *cp; + int i; + int ntokens = 1; + int *tokenized_data; + int err = -EINVAL; + + cp = buf; + while ((cp = strpbrk(cp + 1, " :"))) + ntokens++; + + if (!(ntokens & 0x1)) + goto err; + + tokenized_data = kmalloc(ntokens * sizeof(int), GFP_KERNEL); + if (!tokenized_data) { + err = -ENOMEM; + goto err; + } + + cp = buf; + i = 0; + while (i < ntokens) { + if (sscanf(cp, "%d", &tokenized_data[i++]) != 1) + goto err_kfree; + + cp = strpbrk(cp, " :"); + if (!cp) + break; + cp++; + } + + if (i != ntokens) + goto err_kfree; + + *num_tokens = ntokens; + return tokenized_data; + +err_kfree: + kfree(tokenized_data); +err: + return ERR_PTR(err); +} + +/************************** sysfs interface ************************/ + +static ssize_t show_enable_hotplug(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", hotplug.msm_enabled); +} + +static ssize_t store_enable_hotplug(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1 || val < 0 || val > 1) + return -EINVAL; + + if (val == hotplug.msm_enabled) + return count; + + hotplug.msm_enabled = val; + + if (hotplug.msm_enabled) + ret = msm_hotplug_start(); + else + msm_hotplug_stop(); + + return count; +} + +static ssize_t show_down_lock_duration(struct device *dev, + struct device_attribute + *msm_hotplug_attrs, char *buf) +{ + return sprintf(buf, "%u\n", hotplug.down_lock_dur); +} + +static ssize_t store_down_lock_duration(struct device *dev, + struct device_attribute + *msm_hotplug_attrs, const char *buf, + size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1) + return -EINVAL; + + hotplug.down_lock_dur = val; + + return count; +} + +static ssize_t show_boost_lock_duration(struct device *dev, + struct device_attribute + *msm_hotplug_attrs, char *buf) +{ + return sprintf(buf, "%llu\n", div_u64(hotplug.boost_lock_dur, 1000)); +} + +static ssize_t store_boost_lock_duration(struct device *dev, + struct device_attribute + *msm_hotplug_attrs, const char *buf, + size_t count) +{ + int ret; + u64 val; + + ret = sscanf(buf, "%llu", &val); + if (ret != 1) + return -EINVAL; + + hotplug.boost_lock_dur = val * 1000; + + return count; +} + +static ssize_t show_update_rates(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + int i; + ssize_t ret = 0; + unsigned long flags; + + spin_lock_irqsave(&stats.update_rates_lock, flags); + + for (i = 0; i < stats.nupdate_rates; i++) + ret += sprintf(buf + ret, "%u%s", stats.update_rates[i], + i & 0x1 ? ":" : " "); + + sprintf(buf + ret - 1, "\n"); + spin_unlock_irqrestore(&stats.update_rates_lock, flags); + return ret; +} + +static ssize_t store_update_rates(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ntokens; + unsigned int *new_update_rates = NULL; + unsigned long flags; + + new_update_rates = get_tokenized_data(buf, &ntokens); + if (IS_ERR(new_update_rates)) + return PTR_RET(new_update_rates); + + spin_lock_irqsave(&stats.update_rates_lock, flags); + if (stats.update_rates != default_update_rates) + kfree(stats.update_rates); + stats.update_rates = new_update_rates; + stats.nupdate_rates = ntokens; + spin_unlock_irqrestore(&stats.update_rates_lock, flags); + return count; +} + +static ssize_t show_load_levels(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + int i, len = 0; + + if (!buf) + return -EINVAL; + + for (i = 0; loads[i].up_threshold; i++) { + len += sprintf(buf + len, "%u ", i); + len += sprintf(buf + len, "%u ", loads[i].up_threshold); + len += sprintf(buf + len, "%u\n", loads[i].down_threshold); + } + + return len; +} + +static ssize_t store_load_levels(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val[3]; + + ret = sscanf(buf, "%u %u %u", &val[0], &val[1], &val[2]); + if (ret != ARRAY_SIZE(val) || val[2] > val[1]) + return -EINVAL; + + loads[val[0]].up_threshold = val[1]; + loads[val[0]].down_threshold = val[2]; + + return count; +} + +static ssize_t show_history_size(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", stats.hist_size); +} + +static ssize_t store_history_size(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1 || val < 1 || val > 20) + return -EINVAL; + + if (hotplug.msm_enabled) { + flush_workqueue(hotplug_wq); + cancel_delayed_work_sync(&hotplug_work); + memset(stats.load_hist, 0, sizeof(stats.load_hist)); + } + + stats.hist_size = val; + + if (hotplug.msm_enabled) + reschedule_hotplug_work(); + + return count; +} + +static ssize_t show_min_cpus_online(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", hotplug.min_cpus_online); +} + +static ssize_t store_min_cpus_online(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1 || val < 1 || val > stats.total_cpus) + return -EINVAL; + + if (hotplug.max_cpus_online < val) + hotplug.max_cpus_online = val; + + hotplug.min_cpus_online = val; + + return count; +} + +static ssize_t show_max_cpus_online(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n",hotplug.max_cpus_online); +} + +static ssize_t store_max_cpus_online(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1 || val < 1 || val > stats.total_cpus) + return -EINVAL; + + if (hotplug.min_cpus_online > val) + hotplug.min_cpus_online = val; + + hotplug.max_cpus_online = val; + + return count; +} + +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) +static ssize_t store_suspend_defer_time(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1) + return -EINVAL; + + hotplug.suspend_defer_time = val; + + return count; +} + +static ssize_t show_suspend_defer_time(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", hotplug.suspend_defer_time); +} + +static ssize_t show_max_cpus_online_susp(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n",hotplug.max_cpus_online_susp); +} + +static ssize_t store_max_cpus_online_susp(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1 || val < 1 || val > stats.total_cpus) + return -EINVAL; + + hotplug.max_cpus_online_susp = val; + + return count; +} + +#endif + +static ssize_t show_cpus_boosted(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", hotplug.cpus_boosted); +} + +static ssize_t store_cpus_boosted(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1 || val < 1 || val > stats.total_cpus) + return -EINVAL; + + hotplug.cpus_boosted = val; + + return count; +} + +static ssize_t show_offline_load(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", hotplug.offline_load); +} + +static ssize_t store_offline_load(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1) + return -EINVAL; + + hotplug.offline_load = val; + + return count; +} + +static ssize_t show_fast_lane_load(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", hotplug.fast_lane_load); +} + +static ssize_t store_fast_lane_load(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1) + return -EINVAL; + + hotplug.fast_lane_load = val; + + return count; +} + +static ssize_t show_io_is_busy(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", io_is_busy); +} + +static ssize_t store_io_is_busy(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + const char *buf, size_t count) +{ + int ret; + unsigned int val; + + ret = sscanf(buf, "%u", &val); + if (ret != 1 || val < 0 || val > 1) + return -EINVAL; + + io_is_busy = val ? true : false; + + return count; +} + +static ssize_t show_current_load(struct device *dev, + struct device_attribute *msm_hotplug_attrs, + char *buf) +{ + return sprintf(buf, "%u\n", stats.cur_avg_load); +} + +static DEVICE_ATTR(msm_enabled, 644, show_enable_hotplug, store_enable_hotplug); +static DEVICE_ATTR(down_lock_duration, 644, show_down_lock_duration, + store_down_lock_duration); +static DEVICE_ATTR(boost_lock_duration, 644, show_boost_lock_duration, + store_boost_lock_duration); +static DEVICE_ATTR(update_rates, 644, show_update_rates, store_update_rates); +static DEVICE_ATTR(load_levels, 644, show_load_levels, store_load_levels); +static DEVICE_ATTR(history_size, 644, show_history_size, store_history_size); +static DEVICE_ATTR(min_cpus_online, 644, show_min_cpus_online, + store_min_cpus_online); +static DEVICE_ATTR(max_cpus_online, 644, show_max_cpus_online, + store_max_cpus_online); +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) +static DEVICE_ATTR(suspend_defer_time, 644, show_suspend_defer_time, + store_suspend_defer_time); +static DEVICE_ATTR(max_cpus_online_susp, 644, show_max_cpus_online_susp, + store_max_cpus_online_susp); +#endif +static DEVICE_ATTR(cpus_boosted, 644, show_cpus_boosted, store_cpus_boosted); +static DEVICE_ATTR(offline_load, 644, show_offline_load, store_offline_load); +static DEVICE_ATTR(fast_lane_load, 644, show_fast_lane_load, + store_fast_lane_load); +static DEVICE_ATTR(io_is_busy, 644, show_io_is_busy, store_io_is_busy); +static DEVICE_ATTR(current_load, 444, show_current_load, NULL); + +static struct attribute *msm_hotplug_attrs[] = { + &dev_attr_msm_enabled.attr, + &dev_attr_down_lock_duration.attr, + &dev_attr_boost_lock_duration.attr, + &dev_attr_update_rates.attr, + &dev_attr_load_levels.attr, + &dev_attr_history_size.attr, + &dev_attr_min_cpus_online.attr, + &dev_attr_max_cpus_online.attr, +#if defined(CONFIG_LCD_NOTIFY) || defined(CONFIG_POWERSUSPEND) || defined(CONFIG_HAS_EARLYSUSPEND) + &dev_attr_suspend_defer_time.attr, + &dev_attr_max_cpus_online_susp.attr, +#endif + &dev_attr_cpus_boosted.attr, + &dev_attr_offline_load.attr, + &dev_attr_fast_lane_load.attr, + &dev_attr_io_is_busy.attr, + &dev_attr_current_load.attr, + NULL, +}; + +static struct attribute_group attr_group = { + .attrs = msm_hotplug_attrs, +}; + +/************************** sysfs end ************************/ + +static int __devinit msm_hotplug_probe(struct platform_device *pdev) +{ + int ret = 0; + struct kobject *module_kobj; + + module_kobj = kset_find_obj(module_kset, MSM_HOTPLUG); + if (!module_kobj) { + pr_err("%s: Cannot find kobject for module\n", MSM_HOTPLUG); + goto err_dev; + } + + ret = sysfs_create_group(module_kobj, &attr_group); + if (ret) { + pr_err("%s: Failed to create sysfs: %d\n", MSM_HOTPLUG, ret); + goto err_dev; + } + + if (hotplug.msm_enabled) { + ret = msm_hotplug_start(); + if (ret != 0) + goto err_dev; + } + + return ret; +err_dev: + module_kobj = NULL; + return ret; +} + +static struct platform_device msm_hotplug_device = { + .name = MSM_HOTPLUG, + .id = -1, +}; + +static int msm_hotplug_remove(struct platform_device *pdev) +{ + if (hotplug.msm_enabled) + msm_hotplug_stop(); + + return 0; +} + +static struct platform_driver msm_hotplug_driver = { + .probe = msm_hotplug_probe, + .remove = msm_hotplug_remove, + .driver = { + .name = MSM_HOTPLUG, + .owner = THIS_MODULE, + }, +}; + +static int __init msm_hotplug_init(void) +{ + int ret; + + ret = platform_driver_register(&msm_hotplug_driver); + if (ret) { + pr_err("%s: Driver register failed: %d\n", MSM_HOTPLUG, ret); + return ret; + } + + ret = platform_device_register(&msm_hotplug_device); + if (ret) { + pr_err("%s: Device register failed: %d\n", MSM_HOTPLUG, ret); + return ret; + } + + pr_info("%s: Device init\n", MSM_HOTPLUG); + + return ret; +} + +static void __exit msm_hotplug_exit(void) +{ + platform_device_unregister(&msm_hotplug_device); + platform_driver_unregister(&msm_hotplug_driver); +} + +late_initcall(msm_hotplug_init); +module_exit(msm_hotplug_exit); + +MODULE_AUTHOR("Fluxi "); +MODULE_DESCRIPTION("MSM Hotplug Driver"); +MODULE_LICENSE("GPLv2"); diff --git a/arch/arm/mach-msm/msm_kcal_ctrl.c b/arch/arm/mach-msm/msm_kcal_ctrl.c new file mode 100644 index 00000000000..fbcd77d9b46 --- /dev/null +++ b/arch/arm/mach-msm/msm_kcal_ctrl.c @@ -0,0 +1,593 @@ +/* arch/arm/mach-msm/msm_kcal_ctrl.c + * + * Interface to calibrate display color temperature. + * + * Copyright (C) 2012 LGE + * Copyright (C) 2013 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 +#include + +#include "../../../drivers/video/msm/mdp.h" + +#define KCAL_CTRL_MAJOR_VERSION 1 +#define KCAL_CTRL_MINOR_VERSION 0 +#define KCAL_PLATFORM_NAME "DIAG0" + +struct kcal_data { + int red; + int green; + int blue; +}; + +struct kcal_platform_data { + int (*set_values) (int r, int g, int b); + int (*get_values) (int *r, int *g, int *b); + int (*refresh_display) (void); +}; + +static bool lut_updated = false; +static struct kcal_platform_data *kcal_ctrl_pdata; +static int last_status_kcal_ctrl; + +/* pixel order : RBG */ +static unsigned int lcd_rgb_linear_lut[256] = { + /* default linear qlut */ + 0x00000000, 0x00010101, 0x00020202, 0x00030303, + 0x00040404, 0x00050505, 0x00060606, 0x00070707, + 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, + 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, + 0x00101010, 0x00111111, 0x00121212, 0x00131313, + 0x00141414, 0x00151515, 0x00161616, 0x00171717, + 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, + 0x001c1c1c, 0x001d1d1d, 0x001e1e1e, 0x001f1f1f, + 0x00202020, 0x00212121, 0x00222222, 0x00232323, + 0x00242424, 0x00252525, 0x00262626, 0x00272727, + 0x00282828, 0x00292929, 0x002a2a2a, 0x002b2b2b, + 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, + 0x00303030, 0x00313131, 0x00323232, 0x00333333, + 0x00343434, 0x00353535, 0x00363636, 0x00373737, + 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, + 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, + 0x00404040, 0x00414141, 0x00424242, 0x00434343, + 0x00444444, 0x00454545, 0x00464646, 0x00474747, + 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, + 0x004c4c4c, 0x004d4d4d, 0x004e4e4e, 0x004f4f4f, + 0x00505050, 0x00515151, 0x00525252, 0x00535353, + 0x00545454, 0x00555555, 0x00565656, 0x00575757, + 0x00585858, 0x00595959, 0x005a5a5a, 0x005b5b5b, + 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, + 0x00606060, 0x00616161, 0x00626262, 0x00636363, + 0x00646464, 0x00656565, 0x00666666, 0x00676767, + 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, + 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, + 0x00707070, 0x00717171, 0x00727272, 0x00737373, + 0x00747474, 0x00757575, 0x00767676, 0x00777777, + 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, + 0x007c7c7c, 0x007d7d7d, 0x007e7e7e, 0x007f7f7f, + 0x00808080, 0x00818181, 0x00828282, 0x00838383, + 0x00848484, 0x00858585, 0x00868686, 0x00878787, + 0x00888888, 0x00898989, 0x008a8a8a, 0x008b8b8b, + 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, + 0x00909090, 0x00919191, 0x00929292, 0x00939393, + 0x00949494, 0x00959595, 0x00969696, 0x00979797, + 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, + 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, + 0x00a0a0a0, 0x00a1a1a1, 0x00a2a2a2, 0x00a3a3a3, + 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, + 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, + 0x00acacac, 0x00adadad, 0x00aeaeae, 0x00afafaf, + 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, + 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, + 0x00b8b8b8, 0x00b9b9b9, 0x00bababa, 0x00bbbbbb, + 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, + 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, + 0x00c4c4c4, 0x00c5c5c5, 0x00c6c6c6, 0x00c7c7c7, + 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, + 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, + 0x00d0d0d0, 0x00d1d1d1, 0x00d2d2d2, 0x00d3d3d3, + 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, + 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, + 0x00dcdcdc, 0x00dddddd, 0x00dedede, 0x00dfdfdf, + 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, + 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, + 0x00e8e8e8, 0x00e9e9e9, 0x00eaeaea, 0x00ebebeb, + 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, + 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, + 0x00f4f4f4, 0x00f5f5f5, 0x00f6f6f6, 0x00f7f7f7, + 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, + 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff +}; + +/* pixel order : RBG */ +static unsigned int lcd_rgb_working_lut[256] = { + /* default linear qlut */ + 0x00000000, 0x00010101, 0x00020202, 0x00030303, + 0x00040404, 0x00050505, 0x00060606, 0x00070707, + 0x00080808, 0x00090909, 0x000a0a0a, 0x000b0b0b, + 0x000c0c0c, 0x000d0d0d, 0x000e0e0e, 0x000f0f0f, + 0x00101010, 0x00111111, 0x00121212, 0x00131313, + 0x00141414, 0x00151515, 0x00161616, 0x00171717, + 0x00181818, 0x00191919, 0x001a1a1a, 0x001b1b1b, + 0x001c1c1c, 0x001d1d1d, 0x001e1e1e, 0x001f1f1f, + 0x00202020, 0x00212121, 0x00222222, 0x00232323, + 0x00242424, 0x00252525, 0x00262626, 0x00272727, + 0x00282828, 0x00292929, 0x002a2a2a, 0x002b2b2b, + 0x002c2c2c, 0x002d2d2d, 0x002e2e2e, 0x002f2f2f, + 0x00303030, 0x00313131, 0x00323232, 0x00333333, + 0x00343434, 0x00353535, 0x00363636, 0x00373737, + 0x00383838, 0x00393939, 0x003a3a3a, 0x003b3b3b, + 0x003c3c3c, 0x003d3d3d, 0x003e3e3e, 0x003f3f3f, + 0x00404040, 0x00414141, 0x00424242, 0x00434343, + 0x00444444, 0x00454545, 0x00464646, 0x00474747, + 0x00484848, 0x00494949, 0x004a4a4a, 0x004b4b4b, + 0x004c4c4c, 0x004d4d4d, 0x004e4e4e, 0x004f4f4f, + 0x00505050, 0x00515151, 0x00525252, 0x00535353, + 0x00545454, 0x00555555, 0x00565656, 0x00575757, + 0x00585858, 0x00595959, 0x005a5a5a, 0x005b5b5b, + 0x005c5c5c, 0x005d5d5d, 0x005e5e5e, 0x005f5f5f, + 0x00606060, 0x00616161, 0x00626262, 0x00636363, + 0x00646464, 0x00656565, 0x00666666, 0x00676767, + 0x00686868, 0x00696969, 0x006a6a6a, 0x006b6b6b, + 0x006c6c6c, 0x006d6d6d, 0x006e6e6e, 0x006f6f6f, + 0x00707070, 0x00717171, 0x00727272, 0x00737373, + 0x00747474, 0x00757575, 0x00767676, 0x00777777, + 0x00787878, 0x00797979, 0x007a7a7a, 0x007b7b7b, + 0x007c7c7c, 0x007d7d7d, 0x007e7e7e, 0x007f7f7f, + 0x00808080, 0x00818181, 0x00828282, 0x00838383, + 0x00848484, 0x00858585, 0x00868686, 0x00878787, + 0x00888888, 0x00898989, 0x008a8a8a, 0x008b8b8b, + 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, 0x008f8f8f, + 0x00909090, 0x00919191, 0x00929292, 0x00939393, + 0x00949494, 0x00959595, 0x00969696, 0x00979797, + 0x00989898, 0x00999999, 0x009a9a9a, 0x009b9b9b, + 0x009c9c9c, 0x009d9d9d, 0x009e9e9e, 0x009f9f9f, + 0x00a0a0a0, 0x00a1a1a1, 0x00a2a2a2, 0x00a3a3a3, + 0x00a4a4a4, 0x00a5a5a5, 0x00a6a6a6, 0x00a7a7a7, + 0x00a8a8a8, 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, + 0x00acacac, 0x00adadad, 0x00aeaeae, 0x00afafaf, + 0x00b0b0b0, 0x00b1b1b1, 0x00b2b2b2, 0x00b3b3b3, + 0x00b4b4b4, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, + 0x00b8b8b8, 0x00b9b9b9, 0x00bababa, 0x00bbbbbb, + 0x00bcbcbc, 0x00bdbdbd, 0x00bebebe, 0x00bfbfbf, + 0x00c0c0c0, 0x00c1c1c1, 0x00c2c2c2, 0x00c3c3c3, + 0x00c4c4c4, 0x00c5c5c5, 0x00c6c6c6, 0x00c7c7c7, + 0x00c8c8c8, 0x00c9c9c9, 0x00cacaca, 0x00cbcbcb, + 0x00cccccc, 0x00cdcdcd, 0x00cecece, 0x00cfcfcf, + 0x00d0d0d0, 0x00d1d1d1, 0x00d2d2d2, 0x00d3d3d3, + 0x00d4d4d4, 0x00d5d5d5, 0x00d6d6d6, 0x00d7d7d7, + 0x00d8d8d8, 0x00d9d9d9, 0x00dadada, 0x00dbdbdb, + 0x00dcdcdc, 0x00dddddd, 0x00dedede, 0x00dfdfdf, + 0x00e0e0e0, 0x00e1e1e1, 0x00e2e2e2, 0x00e3e3e3, + 0x00e4e4e4, 0x00e5e5e5, 0x00e6e6e6, 0x00e7e7e7, + 0x00e8e8e8, 0x00e9e9e9, 0x00eaeaea, 0x00ebebeb, + 0x00ececec, 0x00ededed, 0x00eeeeee, 0x00efefef, + 0x00f0f0f0, 0x00f1f1f1, 0x00f2f2f2, 0x00f3f3f3, + 0x00f4f4f4, 0x00f5f5f5, 0x00f6f6f6, 0x00f7f7f7, + 0x00f8f8f8, 0x00f9f9f9, 0x00fafafa, 0x00fbfbfb, + 0x00fcfcfc, 0x00fdfdfd, 0x00fefefe, 0x00ffffff +}; + +/* pixel order : sRBG */ +//static unsigned int lcd_srgb_preset_lut[256] = { + /* default linear qlut */ +/* + 0x00000000, 0x00141414, 0x001c1c1c, 0x00212121, + 0x00262626, 0x002a2a2a, 0x002e2e2e, 0x00313131, + 0x00343434, 0x00373737, 0x003a3a3a, 0x003d3d3d, + 0x003f3f3f, 0x00414141, 0x00444444, 0x00464646, + 0x00484848, 0x004a4a4a, 0x004c4c4c, 0x004e4e4e, + 0x00505050, 0x00515151, 0x00535353, 0x00555555, + 0x00575757, 0x00585858, 0x005a5a5a, 0x005b5b5b, + 0x005d5d5d, 0x005e5e5e, 0x00606060, 0x00616161, + 0x00636363, 0x00646464, 0x00666666, 0x00676767, + 0x00686868, 0x006a6a6a, 0x006b6b6b, 0x006c6c6c, + 0x006d6d6d, 0x006f6f6f, 0x00707070, 0x00717171, + 0x00727272, 0x00737373, 0x00757575, 0x00767676, + 0x00777777, 0x00787878, 0x00797979, 0x007a7a7a, + 0x007b7b7b, 0x007c7c7c, 0x007d7d7d, 0x007e7e7e, + 0x00808080, 0x00818181, 0x00828282, 0x00838383, + 0x00848484, 0x00858585, 0x00868686, 0x00878787, + 0x00888888, 0x00888888, 0x00898989, 0x008a8a8a, + 0x008b8b8b, 0x008c8c8c, 0x008d8d8d, 0x008e8e8e, + 0x008f8f8f, 0x00909090, 0x00919191, 0x00929292, + 0x00939393, 0x00939393, 0x00949494, 0x00959595, + 0x00969696, 0x00979797, 0x00989898, 0x00999999, + 0x00999999, 0x009a9a9a, 0x009b9b9b, 0x009c9c9c, + 0x009d9d9d, 0x009e9e9e, 0x009e9e9e, 0x009f9f9f, + 0x00a0a0a0, 0x00a1a1a1, 0x00a2a2a2, 0x00a2a2a2, + 0x00a3a3a3, 0x00a4a4a4, 0x00a5a5a5, 0x00a5a5a5, + 0x00a6a6a6, 0x00a7a7a7, 0x00a8a8a8, 0x00a8a8a8, + 0x00a9a9a9, 0x00aaaaaa, 0x00ababab, 0x00ababab, + 0x00acacac, 0x00adadad, 0x00aeaeae, 0x00aeaeae, + 0x00afafaf, 0x00b0b0b0, 0x00b0b0b0, 0x00b1b1b1, + 0x00b2b2b2, 0x00b2b2b2, 0x00b3b3b3, 0x00b4b4b4, + 0x00b5b5b5, 0x00b5b5b5, 0x00b6b6b6, 0x00b7b7b7, + 0x00b7b7b7, 0x00b8b8b8, 0x00b9b9b9, 0x00b9b9b9, + 0x00bababa, 0x00bbbbbb, 0x00bbbbbb, 0x00bcbcbc, + 0x00bdbdbd, 0x00bdbdbd, 0x00bebebe, 0x00bebebe, + 0x00bfbfbf, 0x00c0c0c0, 0x00c0c0c0, 0x00c1c1c1, + 0x00c2c2c2, 0x00c2c2c2, 0x00c3c3c3, 0x00c4c4c4, + 0x00c4c4c4, 0x00c5c5c5, 0x00c5c5c5, 0x00c6c6c6, + 0x00c7c7c7, 0x00c7c7c7, 0x00c8c8c8, 0x00c8c8c8, + 0x00c9c9c9, 0x00cacaca, 0x00cacaca, 0x00cbcbcb, + 0x00cbcbcb, 0x00cccccc, 0x00cdcdcd, 0x00cdcdcd, + 0x00cecece, 0x00cecece, 0x00cfcfcf, 0x00d0d0d0, + 0x00d0d0d0, 0x00d1d1d1, 0x00d1d1d1, 0x00d2d2d2, + 0x00d2d2d2, 0x00d3d3d3, 0x00d4d4d4, 0x00d4d4d4, + 0x00d5d5d5, 0x00d5d5d5, 0x00d6d6d6, 0x00d6d6d6, + 0x00d7d7d7, 0x00d8d8d8, 0x00d8d8d8, 0x00d9d9d9, + 0x00d9d9d9, 0x00dadada, 0x00dadada, 0x00dbdbdb, + 0x00dbdbdb, 0x00dcdcdc, 0x00dcdcdc, 0x00dddddd, + 0x00dedede, 0x00dedede, 0x00dfdfdf, 0x00dfdfdf, + 0x00e0e0e0, 0x00e0e0e0, 0x00e1e1e1, 0x00e1e1e1, + 0x00e2e2e2, 0x00e2e2e2, 0x00e3e3e3, 0x00e3e3e3, + 0x00e4e4e4, 0x00e4e4e4, 0x00e5e5e5, 0x00e5e5e5, + 0x00e6e6e6, 0x00e6e6e6, 0x00e7e7e7, 0x00e7e7e7, + 0x00e8e8e8, 0x00e8e8e8, 0x00e9e9e9, 0x00e9e9e9, + 0x00eaeaea, 0x00eaeaea, 0x00ebebeb, 0x00ebebeb, + 0x00ececec, 0x00ececec, 0x00ededed, 0x00ededed, + 0x00eeeeee, 0x00eeeeee, 0x00efefef, 0x00efefef, + 0x00f0f0f0, 0x00f0f0f0, 0x00f1f1f1, 0x00f1f1f1, + 0x00f2f2f2, 0x00f2f2f2, 0x00f3f3f3, 0x00f3f3f3, + 0x00f4f4f4, 0x00f4f4f4, 0x00f5f5f5, 0x00f5f5f5, + 0x00f6f6f6, 0x00f6f6f6, 0x00f7f7f7, 0x00f7f7f7, + 0x00f8f8f8, 0x00f8f8f8, 0x00f9f9f9, 0x00f9f9f9, + 0x00f9f9f9, 0x00fafafa, 0x00fafafa, 0x00fbfbfb, + 0x00fbfbfb, 0x00fcfcfc, 0x00fcfcfc, 0x00fdfdfd, + 0x00fdfdfd, 0x00fefefe, 0x00fefefe, 0x00ffffff +}; +*/ + +void static resetWorkingLut(void) +{ + memcpy((void *)lcd_rgb_working_lut, (void *)lcd_rgb_linear_lut, + sizeof(lcd_rgb_linear_lut)); +} + +void static updateLUT(unsigned int lut_val, unsigned int color, + unsigned int posn) +{ + int offset, mask; + + if (lut_val > 0xff) + return; + + if (color == 0) { + offset = 16; + mask = 0x0000ffff; + } else if (color == 1) { + offset = 8; + mask = 0x00ff00ff; + } else if (color == 2) { + offset = 0; + mask = 0x00ffff00; + } else + // bad color select! + return; + + lcd_rgb_working_lut[posn] = (lcd_rgb_working_lut[posn] & mask) | + (lut_val << offset); +} + +static ssize_t kgamma_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int lut, color, posn, key, tmp; + + if (!count) + return -EINVAL; + + sscanf(buf, "%u %u %u %u", &lut, &color, &posn, &key); + + if (lut > 0xff) + return count; + + if (posn > 0xff) + return count; + + if (color > 2) + return count; + + tmp = (lut + color + posn) & 0xff; + if (key == tmp) { + updateLUT(lut, color, posn); + lut_updated = true; + } + return count; +} + +static ssize_t kgamma_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int res = 0; + + if (lut_updated) { + res = sprintf(buf, "OK\n"); + lut_updated = false; + } else + res = sprintf(buf, "NG\n"); + + return res; + +} + +static ssize_t kgamma_reset_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + int reset; + + if (!count) + return -EINVAL; + + sscanf(buf, "%u", &reset); + + if (reset) + resetWorkingLut(); + + return count; +} + +static ssize_t kgamma_reset_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return 0; +} + +static struct kcal_data kcal_value = {255, 255, 255}; + +static int update_lcdc_lut(void) +{ + struct fb_cmap cmap; + int ret = 0; + + cmap.start = 0; + cmap.len = 256; + cmap.transp = NULL; + + cmap.red = (uint16_t *)&(kcal_value.red); + cmap.green = (uint16_t *)&(kcal_value.green); + cmap.blue = (uint16_t *)&(kcal_value.blue); + + ret = mdp_preset_lut_update_lcdc(&cmap, lcd_rgb_working_lut); + + //if (ret) + // pr_err("%s: failed to set lut! %d\n", __func__, ret); + + return ret; +} + +static int kcal_set_values(int kcal_r, int kcal_g, int kcal_b) +{ + kcal_value.red = kcal_r; + kcal_value.green = kcal_g; + kcal_value.blue = kcal_b; + return 0; +} + +static int kcal_get_values(int *kcal_r, int *kcal_g, int *kcal_b) +{ + *kcal_r = kcal_value.red; + *kcal_g = kcal_value.green; + *kcal_b = kcal_value.blue; + return 0; +} + +static int kcal_refresh_values(void) +{ + return update_lcdc_lut(); +} + +static bool calc_checksum(unsigned int a, unsigned int b, + unsigned int c, unsigned int d) +{ + unsigned char chksum = 0; + + chksum = ~((a & 0xff) + (b & 0xff) + (c & 0xff)); + + if (chksum == (d & 0xff)) { + return true; + } else { + return true; + } +} + +static ssize_t kcal_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + int kcal_r = 0; + int kcal_g = 0; + int kcal_b = 0; + int chksum = 0; + + if (!count) + return -EINVAL; + + sscanf(buf, "%d %d %d %d", &kcal_r, &kcal_g, &kcal_b, &chksum); + chksum = (chksum & 0x0000ff00) >> 8; + + if (calc_checksum(kcal_r, kcal_g, kcal_b, chksum)) + kcal_ctrl_pdata->set_values(kcal_r, kcal_g, kcal_b); + return count; +} + +static ssize_t kcal_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + int kcal_r = 0; + int kcal_g = 0; + int kcal_b = 0; + + kcal_ctrl_pdata->get_values(&kcal_r, &kcal_g, &kcal_b); + + return sprintf(buf, "%d %d %d\n", kcal_r, kcal_g, kcal_b); +} + +static ssize_t kcal_ctrl_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int cmd = 0; + if (!count) + return last_status_kcal_ctrl = -EINVAL; + + sscanf(buf, "%d", &cmd); + + if(cmd != 1) + return last_status_kcal_ctrl = -EINVAL; + + last_status_kcal_ctrl = kcal_ctrl_pdata->refresh_display(); + + if(last_status_kcal_ctrl) + return -EINVAL; + else + return count; +} + +static ssize_t kcal_ctrl_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + if(last_status_kcal_ctrl) + return sprintf(buf, "NG\n"); + else + return sprintf(buf, "OK\n"); +} + +static ssize_t kcal_version_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d.%d\n", + KCAL_CTRL_MAJOR_VERSION, + KCAL_CTRL_MINOR_VERSION); +} + +static DEVICE_ATTR(power_reset, 0644, kgamma_reset_show, kgamma_reset_store); +static DEVICE_ATTR(power_line, 0644, kgamma_show, kgamma_store); +static DEVICE_ATTR(power_rail, 0644, kcal_show, kcal_store); +static DEVICE_ATTR(power_rail_ctrl, 0644, kcal_ctrl_show, kcal_ctrl_store); +static DEVICE_ATTR(power_rail_version, 0444, kcal_version_show, NULL); + +static int kcal_ctrl_probe(struct platform_device *pdev) +{ + int rc = 0; + kcal_ctrl_pdata = pdev->dev.platform_data; + + if(!kcal_ctrl_pdata->set_values || !kcal_ctrl_pdata->get_values || + !kcal_ctrl_pdata->refresh_display) { + //pr_err("kcal function not registered\n"); + return -1; + } + + rc = device_create_file(&pdev->dev, &dev_attr_power_reset); + if(rc !=0) + return -1; + rc = device_create_file(&pdev->dev, &dev_attr_power_line); + if(rc !=0) + return -1; + rc = device_create_file(&pdev->dev, &dev_attr_power_rail); + if(rc !=0) + return -1; + rc = device_create_file(&pdev->dev, &dev_attr_power_rail_ctrl); + if(rc !=0) + return -1; + rc = device_create_file(&pdev->dev, &dev_attr_power_rail_version); + if(rc !=0) + return -1; + + return 0; +} + +static struct kcal_platform_data kcal_pdata = { + .set_values = kcal_set_values, + .get_values = kcal_get_values, + .refresh_display = kcal_refresh_values +}; + +static struct platform_device kcal_platform_device = { + .name = KCAL_PLATFORM_NAME, + .dev = { + .platform_data = &kcal_pdata, + } +}; + +static struct platform_device *msm_panel_devices[] __initdata = { + &kcal_platform_device, +}; + +static struct platform_driver this_driver = { + .probe = kcal_ctrl_probe, + .driver = { + .name = KCAL_PLATFORM_NAME, + }, +}; + +typedef int (*funcPtr)(void); + +static void msm_kcal_early_suspend(struct early_suspend *handler) +{ + +} + +static void msm_kcal_late_resume(struct early_suspend *handler) +{ + kcal_ctrl_pdata->refresh_display(); + pr_info("msm kcal late resume update!\n"); +} + +static struct early_suspend msm_kcal_early_suspend_struct_driver = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN - 20, + .suspend = msm_kcal_early_suspend, + .resume = msm_kcal_late_resume, +}; + +int __init kcal_ctrl_init(void) +{ +#if 0 + struct kcal_platform_data *kcalPtr; + + addr = kallsyms_lookup_name("klcd_pdata"); + kcalPtr = (struct kcal_platform_data *)addr; + kcalPtr->set_values = kcal_set_values; + kcalPtr->get_values = kcal_get_values; + kcalPtr->refresh_display = kcal_refresh_values; + +#endif + unsigned int addr; + + addr = kallsyms_lookup_name("update_preset_lcdc_lut"); + *(funcPtr *)addr = (funcPtr)update_lcdc_lut; + + platform_add_devices(msm_panel_devices, + ARRAY_SIZE(msm_panel_devices)); + + register_early_suspend(&msm_kcal_early_suspend_struct_driver); + + //pr_info("generic kcal ctrl initialized\n"); + //pr_info("generic kcal ctrl version %d.%d\n", + // KCAL_CTRL_MAJOR_VERSION, + // KCAL_CTRL_MINOR_VERSION); + return platform_driver_register(&this_driver); +} + +device_initcall(kcal_ctrl_init); + +//MODULE_DESCRIPTION("Generic MSM KCAL driver"); +MODULE_LICENSE("GPL and additional rights"); + diff --git a/arch/arm/mach-msm/msm_mpdecision.c b/arch/arm/mach-msm/msm_mpdecision.c index 52b9ec316a9..04437527276 100644 --- a/arch/arm/mach-msm/msm_mpdecision.c +++ b/arch/arm/mach-msm/msm_mpdecision.c @@ -116,7 +116,7 @@ enum { HPUPDATE_IN_PROGRESS = 2, /* we are in the process of hotplugging */ }; -static int msm_mpd_enabled = 1; +static int msm_mpd_enabled = 0; module_param_named(enabled, msm_mpd_enabled, int, S_IRUGO | S_IWUSR | S_IWGRP); static struct dentry *debugfs_base; @@ -362,6 +362,7 @@ static int __cpuinit msm_mpd_do_hotplug(void *data) int cpu; while (1) { + msm_dcvs_update_algo_params(); wait_event(msm_mpd.wait_hpq, *event || kthread_should_stop()); if (kthread_should_stop()) break; @@ -394,7 +395,6 @@ static int __cpuinit msm_mpd_do_hotplug(void *data) } msm_mpd.hpupdate = HPUPDATE_WAITING; msm_dcvs_apply_gpu_floor(0); - msm_dcvs_update_algo_params(); } return 0; diff --git a/arch/arm/mach-msm/msm_rq_stats.c b/arch/arm/mach-msm/msm_rq_stats.c index aa440eae8f6..8a76b7d977d 100644 --- a/arch/arm/mach-msm/msm_rq_stats.c +++ b/arch/arm/mach-msm/msm_rq_stats.c @@ -45,6 +45,7 @@ struct cpu_load_data { cputime64_t prev_cpu_wall; cputime64_t prev_cpu_iowait; unsigned int avg_load_maxfreq; + unsigned int cur_load_maxfreq; unsigned int samples; unsigned int window_size; unsigned int cur_freq; @@ -152,7 +153,7 @@ static int update_average_load(unsigned int freq, unsigned int cpu) return 0; } -static unsigned int report_load_at_max_freq(void) +unsigned int report_load_at_max_freq(void) { int cpu; struct cpu_load_data *pcpu; @@ -163,12 +164,21 @@ static unsigned int report_load_at_max_freq(void) mutex_lock(&pcpu->cpu_load_mutex); update_average_load(pcpu->cur_freq, cpu); total_load += pcpu->avg_load_maxfreq; + pcpu->cur_load_maxfreq = pcpu->avg_load_maxfreq; pcpu->avg_load_maxfreq = 0; mutex_unlock(&pcpu->cpu_load_mutex); } return total_load; } + +unsigned int report_avg_load_cpu(unsigned int cpu) +{ + struct cpu_load_data *pcpu= &per_cpu(cpuload, cpu); + + return pcpu->cur_load_maxfreq; +} + static int cpufreq_transition_handler(struct notifier_block *nb, unsigned long val, void *data) { diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c index 369f70dceb8..bc497218574 100644 --- a/arch/arm/mach-msm/restart.c +++ b/arch/arm/mach-msm/restart.c @@ -35,6 +35,10 @@ #include "msm_watchdog.h" #include "timer.h" +#ifdef CONFIG_KEXEC_HARDBOOT +#include +#endif + extern unsigned get_cable_status(void); #define WDT0_RST 0x38 @@ -337,6 +341,14 @@ static int __init msm_pmic_restart_init(void) late_initcall(msm_pmic_restart_init); +#ifdef CONFIG_KEXEC_HARDBOOT +static void msm_kexec_hardboot_hook(void) +{ + // Set PMIC to restart-on-poweroff + pm8xxx_reset_pwr_off(1); +} +#endif + static int __init msm_restart_init(void) { #ifdef CONFIG_MSM_DLOAD_MODE @@ -352,6 +364,10 @@ static int __init msm_restart_init(void) restart_reason = MSM_IMEM_BASE + RESTART_REASON_ADDR; pm_power_off = msm_power_off; +#ifdef CONFIG_KEXEC_HARDBOOT + kexec_hardboot_hook = msm_kexec_hardboot_hook; +#endif + return 0; } early_initcall(msm_restart_init); diff --git a/arch/arm/mach-msm/scm-pas.c b/arch/arm/mach-msm/scm-pas.c index 9eb04e03338..6dcb78c1786 100644 --- a/arch/arm/mach-msm/scm-pas.c +++ b/arch/arm/mach-msm/scm-pas.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -36,18 +37,28 @@ int pas_init_image(enum pas_id id, const u8 *metadata, size_t size) u32 image_addr; } request; u32 scm_ret = 0; - /* Make memory physically contiguous */ - void *mdata_buf = kmemdup(metadata, size, GFP_KERNEL); + void *mdata_buf; + dma_addr_t mdata_phys; + DEFINE_DMA_ATTRS(attrs); - if (!mdata_buf) + dma_set_attr(DMA_ATTR_STRONGLY_ORDERED, &attrs); + mdata_buf = dma_alloc_attrs(NULL, size, &mdata_phys, GFP_KERNEL, + &attrs); + + if (!mdata_buf) { + pr_err("Allocation for metadata failed.\n"); return -ENOMEM; + } + + memcpy(mdata_buf, metadata, size); request.proc = id; - request.image_addr = virt_to_phys(mdata_buf); + request.image_addr = mdata_phys; ret = scm_call(SCM_SVC_PIL, PAS_INIT_IMAGE_CMD, &request, sizeof(request), &scm_ret, sizeof(scm_ret)); - kfree(mdata_buf); + + dma_free_attrs(NULL, size, mdata_buf, mdata_phys, &attrs); if (ret) return ret; diff --git a/arch/arm/mach-msm/scm.c b/arch/arm/mach-msm/scm.c index 468939ba75f..26320d2e090 100644 --- a/arch/arm/mach-msm/scm.c +++ b/arch/arm/mach-msm/scm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, 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 @@ -342,6 +342,43 @@ s32 scm_call_atomic2(u32 svc, u32 cmd, u32 arg1, u32 arg2) } EXPORT_SYMBOL(scm_call_atomic2); +/** + * scm_call_atomic3() - Send an atomic SCM command with three arguments + * @svc_id: service identifier + * @cmd_id: command identifier + * @arg1: first argument + * @arg2: second argument + * @arg3: third argument + * + * This shall only be used with commands that are guaranteed to be + * uninterruptable, atomic and SMP safe. + */ +s32 scm_call_atomic3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3) +{ + int context_id; + register u32 r0 asm("r0") = SCM_ATOMIC(svc, cmd, 3); + register u32 r1 asm("r1") = (u32)&context_id; + register u32 r2 asm("r2") = arg1; + register u32 r3 asm("r3") = arg2; + register u32 r4 asm("r4") = arg3; + + asm volatile( + __asmeq("%0", "r0") + __asmeq("%1", "r0") + __asmeq("%2", "r1") + __asmeq("%3", "r2") + __asmeq("%4", "r3") + __asmeq("%5", "r4") +#ifdef REQUIRES_SEC + ".arch_extension sec\n" +#endif + "smc #0 @ switch to secure world\n" + : "=r" (r0) + : "r" (r0), "r" (r1), "r" (r2), "r" (r3), "r" (r4)); + return r0; +} +EXPORT_SYMBOL(scm_call_atomic3); + s32 scm_call_atomic4_3(u32 svc, u32 cmd, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 *ret1, u32 *ret2) { diff --git a/arch/arm/mach-msm/vdd_limits_8064.h b/arch/arm/mach-msm/vdd_limits_8064.h new file mode 100644 index 00000000000..01546925754 --- /dev/null +++ b/arch/arm/mach-msm/vdd_limits_8064.h @@ -0,0 +1,3 @@ +#define SC_MAX_VDD 1400000 +#define SC_MIN_VDD 500000 +#define MEM_DIG_MAX_VDD 1250000 diff --git a/arch/arm/mm/cache-fa.S b/arch/arm/mm/cache-fa.S index 07201637109..e505befe51b 100644 --- a/arch/arm/mm/cache-fa.S +++ b/arch/arm/mm/cache-fa.S @@ -240,6 +240,9 @@ ENTRY(fa_dma_unmap_area) mov pc, lr ENDPROC(fa_dma_unmap_area) + .globl fa_flush_kern_cache_louis + .equ fa_flush_kern_cache_louis, fa_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v3.S b/arch/arm/mm/cache-v3.S index c2301f22610..d99c00c54ee 100644 --- a/arch/arm/mm/cache-v3.S +++ b/arch/arm/mm/cache-v3.S @@ -127,6 +127,9 @@ ENTRY(v3_dma_map_area) ENDPROC(v3_dma_unmap_area) ENDPROC(v3_dma_map_area) + .globl v3_flush_kern_cache_louis + .equ v3_flush_kern_cache_louis, v3_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4.S b/arch/arm/mm/cache-v4.S index fd9bb7addc8..548b892a79a 100644 --- a/arch/arm/mm/cache-v4.S +++ b/arch/arm/mm/cache-v4.S @@ -139,6 +139,9 @@ ENTRY(v4_dma_map_area) ENDPROC(v4_dma_unmap_area) ENDPROC(v4_dma_map_area) + .globl v4_flush_kern_cache_louis + .equ v4_flush_kern_cache_louis, v4_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4wb.S b/arch/arm/mm/cache-v4wb.S index 4f2c14151cc..63b7e4952fd 100644 --- a/arch/arm/mm/cache-v4wb.S +++ b/arch/arm/mm/cache-v4wb.S @@ -251,6 +251,9 @@ ENTRY(v4wb_dma_unmap_area) mov pc, lr ENDPROC(v4wb_dma_unmap_area) + .globl v4wb_flush_kern_cache_louis + .equ v4wb_flush_kern_cache_louis, v4wb_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v4wt.S b/arch/arm/mm/cache-v4wt.S index 4d7b467631c..198d424b320 100644 --- a/arch/arm/mm/cache-v4wt.S +++ b/arch/arm/mm/cache-v4wt.S @@ -195,6 +195,9 @@ ENTRY(v4wt_dma_map_area) ENDPROC(v4wt_dma_unmap_area) ENDPROC(v4wt_dma_map_area) + .globl v4wt_flush_kern_cache_louis + .equ v4wt_flush_kern_cache_louis, v4wt_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v6.S b/arch/arm/mm/cache-v6.S index 2edb6f67f69..6a5674d3021 100644 --- a/arch/arm/mm/cache-v6.S +++ b/arch/arm/mm/cache-v6.S @@ -345,6 +345,9 @@ ENTRY(v6_dma_unmap_area) mov pc, lr ENDPROC(v6_dma_unmap_area) + .globl v6_flush_kern_cache_louis + .equ v6_flush_kern_cache_louis, v6_flush_kern_cache_all + __INITDATA @ define struct cpu_cache_fns (see and proc-macros.S) diff --git a/arch/arm/mm/cache-v7.S b/arch/arm/mm/cache-v7.S index a655d3da386..98bdfe89770 100644 --- a/arch/arm/mm/cache-v7.S +++ b/arch/arm/mm/cache-v7.S @@ -32,6 +32,24 @@ ENTRY(v7_flush_icache_all) mov pc, lr ENDPROC(v7_flush_icache_all) + /* + * v7_flush_dcache_louis() + * + * Flush the D-cache up to the Level of Unification Inner Shareable + * + * Corrupted registers: r0-r7, r9-r11 (r6 only in Thumb mode) + */ + +ENTRY(v7_flush_dcache_louis) + dmb @ ensure ordering with previous memory accesses + mrc p15, 1, r0, c0, c0, 1 @ read clidr, r0 = clidr + ands r3, r0, #0xe00000 @ extract LoUIS from clidr + mov r3, r3, lsr #20 @ r3 = LoUIS * 2 + moveq pc, lr @ return if level == 0 + mov r10, #0 @ r10 (starting level) = 0 + b flush_levels @ start flushing cache levels +ENDPROC(v7_flush_dcache_louis) + /* * v7_flush_dcache_all() * @@ -48,7 +66,7 @@ ENTRY(v7_flush_dcache_all) mov r3, r3, lsr #23 @ left align loc bit field beq finished @ if loc is 0, then no need to clean mov r10, #0 @ start clean at cache level 0 -loop1: +flush_levels: add r2, r10, r10, lsr #1 @ work out 3x current cache level mov r1, r0, lsr r2 @ extract cache type bits from clidr and r1, r1, #7 @ mask of the bits for current cache only @@ -70,9 +88,9 @@ loop1: clz r5, r4 @ find bit position of way size increment ldr r7, =0x7fff ands r7, r7, r1, lsr #13 @ extract max number of the index size -loop2: +loop1: mov r9, r4 @ create working copy of max way size -loop3: +loop2: ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11 THUMB( lsl r6, r9, r5 ) THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11 @@ -81,13 +99,13 @@ loop3: THUMB( orr r11, r11, r6 ) @ factor index number into r11 mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way subs r9, r9, #1 @ decrement the way - bge loop3 - subs r7, r7, #1 @ decrement the index bge loop2 + subs r7, r7, #1 @ decrement the index + bge loop1 skip: add r10, r10, #2 @ increment cache number cmp r3, r10 - bgt loop1 + bgt flush_levels finished: mov r10, #0 @ swith back to cache level 0 mcr p15, 2, r10, c0, c0, 0 @ select current cache level in cssr @@ -119,6 +137,24 @@ ENTRY(v7_flush_kern_cache_all) mov pc, lr ENDPROC(v7_flush_kern_cache_all) + /* + * v7_flush_kern_cache_louis(void) + * + * Flush the data cache up to Level of Unification Inner Shareable. + * Invalidate the I-cache to the point of unification. + */ +ENTRY(v7_flush_kern_cache_louis) + ARM( stmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( stmfd sp!, {r4-r7, r9-r11, lr} ) + bl v7_flush_dcache_louis + mov r0, #0 + ALT_SMP(mcr p15, 0, r0, c7, c1, 0) @ invalidate I-cache inner shareable + ALT_UP(mcr p15, 0, r0, c7, c5, 0) @ I+BTB cache invalidate + ARM( ldmfd sp!, {r4-r5, r7, r9-r11, lr} ) + THUMB( ldmfd sp!, {r4-r7, r9-r11, lr} ) + mov pc, lr +ENDPROC(v7_flush_kern_cache_louis) + /* * v7_flush_cache_all() * diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index ab88ed4f8e0..99db769307e 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c @@ -92,6 +92,9 @@ static int __init init_static_idmap(void) (long long)idmap_start, (long long)idmap_end); identity_mapping_add(idmap_pgd, idmap_start, idmap_end); + /* Flush L1 for the hardware to see this page table content */ + flush_cache_louis(); + return 0; } early_initcall(init_static_idmap); @@ -103,12 +106,15 @@ early_initcall(init_static_idmap); */ void setup_mm_for_reboot(void) { - /* Clean and invalidate L1. */ - flush_cache_all(); - /* Switch to the identity mapping. */ cpu_switch_mm(idmap_pgd, &init_mm); - /* Flush the TLB. */ +#ifdef CONFIG_CPU_HAS_ASID + /* + * We don't have a clean ASID for the identity mapping, which + * may clash with virtual addresses of the previous page tables + * and therefore potentially in the TLB. + */ local_flush_tlb_all(); +#endif } diff --git a/arch/arm/mm/proc-arm1020.S b/arch/arm/mm/proc-arm1020.S index 234951345eb..c11e32ef056 100644 --- a/arch/arm/mm/proc-arm1020.S +++ b/arch/arm/mm/proc-arm1020.S @@ -367,6 +367,9 @@ ENTRY(arm1020_dma_unmap_area) mov pc, lr ENDPROC(arm1020_dma_unmap_area) + .globl arm1020_flush_kern_cache_louis + .equ arm1020_flush_kern_cache_louis, arm1020_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm1020 diff --git a/arch/arm/mm/proc-arm1020e.S b/arch/arm/mm/proc-arm1020e.S index c244b06caac..9624a35cd42 100644 --- a/arch/arm/mm/proc-arm1020e.S +++ b/arch/arm/mm/proc-arm1020e.S @@ -353,6 +353,9 @@ ENTRY(arm1020e_dma_unmap_area) mov pc, lr ENDPROC(arm1020e_dma_unmap_area) + .globl arm1020e_flush_kern_cache_louis + .equ arm1020e_flush_kern_cache_louis, arm1020e_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm1020e diff --git a/arch/arm/mm/proc-arm1022.S b/arch/arm/mm/proc-arm1022.S index 38fe22efd18..f2b45ee05fc 100644 --- a/arch/arm/mm/proc-arm1022.S +++ b/arch/arm/mm/proc-arm1022.S @@ -342,6 +342,9 @@ ENTRY(arm1022_dma_unmap_area) mov pc, lr ENDPROC(arm1022_dma_unmap_area) + .globl arm1022_flush_kern_cache_louis + .equ arm1022_flush_kern_cache_louis, arm1022_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm1022 diff --git a/arch/arm/mm/proc-arm1026.S b/arch/arm/mm/proc-arm1026.S index 3eb9c3c26c7..95934d2e0cf 100644 --- a/arch/arm/mm/proc-arm1026.S +++ b/arch/arm/mm/proc-arm1026.S @@ -336,6 +336,9 @@ ENTRY(arm1026_dma_unmap_area) mov pc, lr ENDPROC(arm1026_dma_unmap_area) + .globl arm1026_flush_kern_cache_louis + .equ arm1026_flush_kern_cache_louis, arm1026_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm1026 diff --git a/arch/arm/mm/proc-arm920.S b/arch/arm/mm/proc-arm920.S index cb941ae95f6..ed3acd442b6 100644 --- a/arch/arm/mm/proc-arm920.S +++ b/arch/arm/mm/proc-arm920.S @@ -318,6 +318,9 @@ ENTRY(arm920_dma_unmap_area) mov pc, lr ENDPROC(arm920_dma_unmap_area) + .globl arm920_flush_kern_cache_louis + .equ arm920_flush_kern_cache_louis, arm920_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm920 #endif diff --git a/arch/arm/mm/proc-arm922.S b/arch/arm/mm/proc-arm922.S index 4ec0e074dd5..142bace0a17 100644 --- a/arch/arm/mm/proc-arm922.S +++ b/arch/arm/mm/proc-arm922.S @@ -320,6 +320,9 @@ ENTRY(arm922_dma_unmap_area) mov pc, lr ENDPROC(arm922_dma_unmap_area) + .globl arm922_flush_kern_cache_louis + .equ arm922_flush_kern_cache_louis, arm922_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm922 #endif diff --git a/arch/arm/mm/proc-arm925.S b/arch/arm/mm/proc-arm925.S index 9dccd9a365b..3028390aea5 100644 --- a/arch/arm/mm/proc-arm925.S +++ b/arch/arm/mm/proc-arm925.S @@ -375,6 +375,9 @@ ENTRY(arm925_dma_unmap_area) mov pc, lr ENDPROC(arm925_dma_unmap_area) + .globl arm925_flush_kern_cache_louis + .equ arm925_flush_kern_cache_louis, arm925_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm925 diff --git a/arch/arm/mm/proc-arm926.S b/arch/arm/mm/proc-arm926.S index 820259b81a1..1f99b469cba 100644 --- a/arch/arm/mm/proc-arm926.S +++ b/arch/arm/mm/proc-arm926.S @@ -338,6 +338,9 @@ ENTRY(arm926_dma_unmap_area) mov pc, lr ENDPROC(arm926_dma_unmap_area) + .globl arm926_flush_kern_cache_louis + .equ arm926_flush_kern_cache_louis, arm926_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm926 diff --git a/arch/arm/mm/proc-arm940.S b/arch/arm/mm/proc-arm940.S index 9fdc0a17097..e5af9598ad3 100644 --- a/arch/arm/mm/proc-arm940.S +++ b/arch/arm/mm/proc-arm940.S @@ -267,6 +267,9 @@ ENTRY(arm940_dma_unmap_area) mov pc, lr ENDPROC(arm940_dma_unmap_area) + .globl arm940_flush_kern_cache_louis + .equ arm940_flush_kern_cache_louis, arm940_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm940 diff --git a/arch/arm/mm/proc-arm946.S b/arch/arm/mm/proc-arm946.S index f684cfedcca..3599b379853 100644 --- a/arch/arm/mm/proc-arm946.S +++ b/arch/arm/mm/proc-arm946.S @@ -309,6 +309,9 @@ ENTRY(arm946_dma_unmap_area) mov pc, lr ENDPROC(arm946_dma_unmap_area) + .globl arm946_flush_kern_cache_louis + .equ arm946_flush_kern_cache_louis, arm946_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions arm946 diff --git a/arch/arm/mm/proc-feroceon.S b/arch/arm/mm/proc-feroceon.S index ba3c500584a..26a998423dc 100644 --- a/arch/arm/mm/proc-feroceon.S +++ b/arch/arm/mm/proc-feroceon.S @@ -414,6 +414,9 @@ ENTRY(feroceon_dma_unmap_area) mov pc, lr ENDPROC(feroceon_dma_unmap_area) + .globl feroceon_flush_kern_cache_louis + .equ feroceon_flush_kern_cache_louis, feroceon_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions feroceon diff --git a/arch/arm/mm/proc-macros.S b/arch/arm/mm/proc-macros.S index 5829bb379b2..2ea177ac399 100644 --- a/arch/arm/mm/proc-macros.S +++ b/arch/arm/mm/proc-macros.S @@ -299,6 +299,7 @@ ENTRY(\name\()_processor_functions) ENTRY(\name\()_cache_fns) .long \name\()_flush_icache_all .long \name\()_flush_kern_cache_all + .long \name\()_flush_kern_cache_louis .long \name\()_flush_user_cache_all .long \name\()_flush_user_cache_range .long \name\()_coherent_kern_range diff --git a/arch/arm/mm/proc-mohawk.S b/arch/arm/mm/proc-mohawk.S index cdfedc5b8ad..224d0f5471a 100644 --- a/arch/arm/mm/proc-mohawk.S +++ b/arch/arm/mm/proc-mohawk.S @@ -302,6 +302,9 @@ ENTRY(mohawk_dma_unmap_area) mov pc, lr ENDPROC(mohawk_dma_unmap_area) + .globl mohawk_flush_kern_cache_louis + .equ mohawk_flush_kern_cache_louis, mohawk_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions mohawk diff --git a/arch/arm/mm/proc-v7.S b/arch/arm/mm/proc-v7.S index 47dab27f62f..ce4743ead6c 100644 --- a/arch/arm/mm/proc-v7.S +++ b/arch/arm/mm/proc-v7.S @@ -175,7 +175,7 @@ __v7_ca15mp_setup: __v7_setup: adr r12, __v7_setup_stack @ the local stack stmia r12, {r0-r5, r7, r9, r11, lr} - bl v7_flush_dcache_all + bl v7_flush_dcache_louis ldmia r12, {r0-r5, r7, r9, r11, lr} mrc p15, 0, r0, c0, c0, 0 @ read main ID register diff --git a/arch/arm/mm/proc-xsc3.S b/arch/arm/mm/proc-xsc3.S index b0d57869da2..eb93d6487f3 100644 --- a/arch/arm/mm/proc-xsc3.S +++ b/arch/arm/mm/proc-xsc3.S @@ -337,6 +337,9 @@ ENTRY(xsc3_dma_unmap_area) mov pc, lr ENDPROC(xsc3_dma_unmap_area) + .globl xsc3_flush_kern_cache_louis + .equ xsc3_flush_kern_cache_louis, xsc3_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions xsc3 diff --git a/arch/arm/mm/proc-xscale.S b/arch/arm/mm/proc-xscale.S index 4ffebaa595e..b5ea31d6daa 100644 --- a/arch/arm/mm/proc-xscale.S +++ b/arch/arm/mm/proc-xscale.S @@ -410,6 +410,9 @@ ENTRY(xscale_dma_unmap_area) mov pc, lr ENDPROC(xscale_dma_unmap_area) + .globl xscale_flush_kern_cache_louis + .equ xscale_flush_kern_cache_louis, xscale_flush_kern_cache_all + @ define struct cpu_cache_fns (see and proc-macros.S) define_cache_functions xscale diff --git a/arch/arm/vfp/Makefile b/arch/arm/vfp/Makefile index a81404c09d5..3202e6e6881 100644 --- a/arch/arm/vfp/Makefile +++ b/arch/arm/vfp/Makefile @@ -7,7 +7,7 @@ # ccflags-y := -DDEBUG # asflags-y := -DDEBUG -KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp -mfloat-abi=soft) +KBUILD_AFLAGS :=$(KBUILD_AFLAGS:-mhard-float=-Wa,-mfpu=neon-vfpv4 -ffast-math -mfloat-abi=hard) LDFLAGS +=--no-warn-mismatch obj-y += vfp.o diff --git a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c index 5c3e0888265..1034884b77d 100644 --- a/arch/ia64/kernel/irq_ia64.c +++ b/arch/ia64/kernel/irq_ia64.c @@ -23,7 +23,6 @@ #include #include #include -#include /* for rand_initialize_irq() */ #include #include #include diff --git a/arch/sh/boot/compressed/vmlinux.scr b/arch/sh/boot/compressed/vmlinux.scr deleted file mode 100644 index 862d7480823..00000000000 --- a/arch/sh/boot/compressed/vmlinux.scr +++ /dev/null @@ -1,10 +0,0 @@ -SECTIONS -{ - .rodata..compressed : { - input_len = .; - LONG(input_data_end - input_data) input_data = .; - *(.data) - output_len = . - 4; - input_data_end = .; - } -} diff --git a/arch/sh/boot/romimage/vmlinux.scr b/arch/sh/boot/romimage/vmlinux.scr deleted file mode 100644 index 590394e2f5f..00000000000 --- a/arch/sh/boot/romimage/vmlinux.scr +++ /dev/null @@ -1,8 +0,0 @@ -SECTIONS -{ - .text : { - zero_page_pos = .; - *(.data) - end_data = .; - } -} diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 7cbdfdac3c7..c7ef52665c8 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -56,6 +56,7 @@ config X86 select HAVE_KERNEL_LZMA select HAVE_KERNEL_XZ select HAVE_KERNEL_LZO + select HAVE_KERNEL_LZ4 select HAVE_HW_BREAKPOINT select HAVE_MIXED_BREAKPOINTS_REGS select PERF_EVENTS diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 7116dcba0c9..99c33dc2635 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -147,6 +147,10 @@ static int lines, cols; #include "../../../../lib/decompress_unlzo.c" #endif +#ifdef CONFIG_KERNEL_LZ4 +#include "../../../../lib/decompress_unlz4.c" +#endif + static void scroll(void) { int i; diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched index 4142d919b75..45deec89147 100644 --- a/block/Kconfig.iosched +++ b/block/Kconfig.iosched @@ -32,6 +32,17 @@ config IOSCHED_DEADLINE a new point in the service tree and doing a batch of IO from there in case of expiry. +config IOSCHED_ROW + tristate "ROW I/O scheduler" + default y + ---help--- + The ROW I/O scheduler gives priority to READ requests over the + WRITE requests when dispatching, without starving WRITE requests. + Requests are kept in priority queues. Dispatching is done in a RR + manner when the dispatch quantum for each queue is calculated + according to queue priority. + Most suitable for mobile devices. + config IOSCHED_CFQ tristate "CFQ I/O scheduler" # If BLK_CGROUP is a module, CFQ has to be built as module. @@ -47,6 +58,24 @@ config IOSCHED_CFQ Note: If BLK_CGROUP=m, then CFQ can be built only as module. +config IOSCHED_FIOPS + tristate "IOPS based I/O scheduler" + default y + ---help--- + This is an IOPS based I/O scheduler. It will try to distribute + IOPS equally among all processes in the system. It's mainly for + Flash based storage. + +config IOSCHED_SIO + tristate "Simple I/O scheduler" + default y + ---help--- + The Simple I/O scheduler is an extremely simple scheduler, + based on noop and deadline, that relies on deadlines to + ensure fairness. The algorithm does not do any sorting but + basic merging, trying to keep a minimum overhead. It is aimed + mainly for aleatory access devices (eg: flash devices). + config CFQ_GROUP_IOSCHED bool "CFQ Group Scheduling support" depends on IOSCHED_CFQ && BLK_CGROUP @@ -64,19 +93,38 @@ choice config DEFAULT_DEADLINE bool "Deadline" if IOSCHED_DEADLINE=y + config DEFAULT_ROW + bool "ROW" if IOSCHED_ROW=y + help + The ROW I/O scheduler gives priority to READ requests + over the WRITE requests when dispatching, without starving + WRITE requests. Requests are kept in priority queues. + Dispatching is done in a RR manner when the dispatch quantum + for each queue is defined according to queue priority. + Most suitable for mobile devices. + config DEFAULT_CFQ bool "CFQ" if IOSCHED_CFQ=y config DEFAULT_NOOP bool "No-op" + config DEFAULT_SIO + bool "SIO" if IOSCHED_SIO=y + + config DEFAULT_FIOPS + bool "FIOPS" if IOSCHED_FIOPS=y + endchoice config DEFAULT_IOSCHED string default "deadline" if DEFAULT_DEADLINE + default "row" if DEFAULT_ROW default "cfq" if DEFAULT_CFQ default "noop" if DEFAULT_NOOP + default "fiops" if DEFAULT_FIOPS + default "sio" if DEFAULT_SIO endmenu diff --git a/block/Makefile b/block/Makefile index 436b220cecc..ee9195ccbff 100644 --- a/block/Makefile +++ b/block/Makefile @@ -14,8 +14,11 @@ obj-$(CONFIG_BLK_CGROUP) += blk-cgroup.o obj-$(CONFIG_BLK_DEV_THROTTLING) += blk-throttle.o obj-$(CONFIG_IOSCHED_NOOP) += noop-iosched.o obj-$(CONFIG_IOSCHED_DEADLINE) += deadline-iosched.o +obj-$(CONFIG_IOSCHED_ROW) += row-iosched.o obj-$(CONFIG_IOSCHED_CFQ) += cfq-iosched.o obj-$(CONFIG_IOSCHED_TEST) += test-iosched.o +obj-$(CONFIG_IOSCHED_FIOPS) += fiops-iosched.o +obj-$(CONFIG_IOSCHED_SIO) += sio-iosched.o obj-$(CONFIG_BLOCK_COMPAT) += compat_ioctl.o obj-$(CONFIG_BLK_DEV_INTEGRITY) += blk-integrity.o diff --git a/block/blk-core.c b/block/blk-core.c index 68d7158aeb6..514c2c0d38c 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -297,13 +297,26 @@ EXPORT_SYMBOL(blk_sync_queue); * Description: * See @blk_run_queue. This variant must be called with the queue lock * held and interrupts disabled. + * Device driver will be notified of an urgent request + * pending under the following conditions: + * 1. The driver and the current scheduler support urgent reques handling + * 2. There is an urgent request pending in the scheduler + * 3. There isn't already an urgent request in flight, meaning previously + * notified urgent request completed (!q->notified_urgent) */ void __blk_run_queue(struct request_queue *q) { if (unlikely(blk_queue_stopped(q))) return; - q->request_fn(q); + if (!q->notified_urgent && + q->elevator->type->ops.elevator_is_urgent_fn && + q->urgent_request_fn && + q->elevator->type->ops.elevator_is_urgent_fn(q)) { + q->notified_urgent = true; + q->urgent_request_fn(q); + } else + q->request_fn(q); } EXPORT_SYMBOL(__blk_run_queue); @@ -1066,10 +1079,74 @@ void blk_requeue_request(struct request_queue *q, struct request *rq) BUG_ON(blk_queued_rq(rq)); + if (rq->cmd_flags & REQ_URGENT) { + /* + * It's not compliant with the design to re-insert + * urgent requests. We want to be able to track this + * down. + */ + pr_debug("%s(): requeueing an URGENT request", __func__); + WARN_ON(!q->dispatched_urgent); + q->dispatched_urgent = false; + } elv_requeue_request(q, rq); } EXPORT_SYMBOL(blk_requeue_request); +/** + * blk_reinsert_request() - Insert a request back to the scheduler + * @q: request queue + * @rq: request to be inserted + * + * This function inserts the request back to the scheduler as if + * it was never dispatched. + * + * Return: 0 on success, error code on fail + */ +int blk_reinsert_request(struct request_queue *q, struct request *rq) +{ + if (unlikely(!rq) || unlikely(!q)) + return -EIO; + + blk_delete_timer(rq); + blk_clear_rq_complete(rq); + trace_block_rq_requeue(q, rq); + + if (blk_rq_tagged(rq)) + blk_queue_end_tag(q, rq); + + BUG_ON(blk_queued_rq(rq)); + if (rq->cmd_flags & REQ_URGENT) { + /* + * It's not compliant with the design to re-insert + * urgent requests. We want to be able to track this + * down. + */ + pr_debug("%s(): reinserting an URGENT request", __func__); + WARN_ON(!q->dispatched_urgent); + q->dispatched_urgent = false; + } + + return elv_reinsert_request(q, rq); +} +EXPORT_SYMBOL(blk_reinsert_request); + +/** + * blk_reinsert_req_sup() - check whether the scheduler supports + * reinsertion of requests + * @q: request queue + * + * Returns true if the current scheduler supports reinserting + * request. False otherwise + */ +bool blk_reinsert_req_sup(struct request_queue *q) +{ + if (unlikely(!q)) + return false; + return q->elevator->type->ops.elevator_reinsert_req_fn ? true : false; +} +EXPORT_SYMBOL(blk_reinsert_req_sup); + static void add_acct_request(struct request_queue *q, struct request *rq, int where) { @@ -1940,6 +2017,8 @@ struct request *blk_peek_request(struct request_queue *q) * not be passed by new incoming requests */ rq->cmd_flags |= REQ_STARTED; + if (rq->cmd_flags & REQ_URGENT) + q->dispatched_urgent = true; trace_block_rq_issue(q, rq); } diff --git a/block/blk-exec.c b/block/blk-exec.c index fb2cbd55162..b49f7c91b0e 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -109,9 +109,9 @@ int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, /* Prevent hang_check timer from firing at us during very long I/O */ hang_check = sysctl_hung_task_timeout_secs; if (hang_check) - while (!wait_for_completion_timeout(&wait, hang_check * (HZ/2))); + while (!wait_for_completion_io_timeout(&wait, hang_check * (HZ/2))); else - wait_for_completion(&wait); + wait_for_completion_io(&wait); if (rq->errors) err = -EIO; diff --git a/block/blk-flush.c b/block/blk-flush.c index 720ad607ff9..db8f1b50785 100644 --- a/block/blk-flush.c +++ b/block/blk-flush.c @@ -436,7 +436,7 @@ int blkdev_issue_flush(struct block_device *bdev, gfp_t gfp_mask, bio_get(bio); submit_bio(WRITE_FLUSH, bio); - wait_for_completion(&wait); + wait_for_completion_io(&wait); /* * The driver must store the error location in ->bi_sector, if diff --git a/block/blk-lib.c b/block/blk-lib.c index 280d63e6c30..d185765bcec 100644 --- a/block/blk-lib.c +++ b/block/blk-lib.c @@ -105,7 +105,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector, /* Wait for bios in-flight */ if (!atomic_dec_and_test(&bb.done)) - wait_for_completion(&wait); + wait_for_completion_io(&wait); if (!test_bit(BIO_UPTODATE, &bb.flags)) ret = -EIO; @@ -156,7 +156,7 @@ int blkdev_issue_sanitize(struct block_device *bdev, gfp_t gfp_mask) /* Wait for bios in-flight */ if (!atomic_dec_and_test(&bb.done)) - wait_for_completion(&wait); + wait_for_completion_io(&wait); if (!test_bit(BIO_UPTODATE, &bb.flags)) ret = -EIO; @@ -218,7 +218,7 @@ int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector, /* Wait for bios in-flight */ if (!atomic_dec_and_test(&bb.done)) - wait_for_completion(&wait); + wait_for_completion_io(&wait); if (!test_bit(BIO_UPTODATE, &bb.flags)) /* One of bios in the batch was completed with error.*/ diff --git a/block/blk-settings.c b/block/blk-settings.c index d3234fc494a..579328cff6d 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -99,6 +99,18 @@ void blk_queue_lld_busy(struct request_queue *q, lld_busy_fn *fn) } EXPORT_SYMBOL_GPL(blk_queue_lld_busy); +/** + * blk_urgent_request() - Set an urgent_request handler function for queue + * @q: queue + * @fn: handler for urgent requests + * + */ +void blk_urgent_request(struct request_queue *q, request_fn_proc *fn) +{ + q->urgent_request_fn = fn; +} +EXPORT_SYMBOL(blk_urgent_request); + /** * blk_set_default_limits - reset limits to default values * @lim: the queue_limits structure to reset diff --git a/block/blk-tag.c b/block/blk-tag.c index 4af6f5cc116..bc25b6e2d06 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -350,9 +350,16 @@ int blk_queue_start_tag(struct request_queue *q, struct request *rq) */ max_depth = bqt->max_depth; if (!rq_is_sync(rq) && max_depth > 1) { - max_depth -= 2; - if (!max_depth) + switch (max_depth) { + case 2: max_depth = 1; + break; + case 3: + max_depth = 2; + break; + default: + max_depth -= 2; + } if (q->in_flight[BLK_RW_ASYNC] > max_depth) return 1; } diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 3c38536bd52..830fe67fa9d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -239,6 +239,9 @@ struct cfq_data { unsigned long workload_expires; struct cfq_group *serving_group; + unsigned int nr_urgent_pending; + unsigned int nr_urgent_in_flight; + /* * Each priority tree is sorted by next_request position. These * trees are used when determining if two or more queues are @@ -2091,6 +2094,14 @@ static void cfq_dispatch_insert(struct request_queue *q, struct request *rq) (RQ_CFQG(rq))->dispatched++; elv_dispatch_sort(q, rq); + if (rq->cmd_flags & REQ_URGENT) { + if (!cfqd->nr_urgent_pending) + WARN_ON(1); + else + cfqd->nr_urgent_pending--; + cfqd->nr_urgent_in_flight++; + } + cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]++; cfqq->nr_sectors += blk_rq_sectors(rq); cfq_blkiocg_update_dispatch_stats(&cfqq->cfqg->blkg, blk_rq_bytes(rq), @@ -3191,6 +3202,69 @@ cfq_rq_enqueued(struct cfq_data *cfqd, struct cfq_queue *cfqq, } } +/* + * Called when a request (rq) is reinserted (to cfqq). Check if there's + * something we should do about it + */ +static void +cfq_rq_requeued(struct cfq_data *cfqd, struct cfq_queue *cfqq, + struct request *rq) +{ + struct cfq_io_cq *cic = RQ_CIC(rq); + + cfqd->rq_queued++; + if (rq->cmd_flags & REQ_PRIO) + cfqq->prio_pending++; + + cfqq->dispatched--; + (RQ_CFQG(rq))->dispatched--; + + cfqd->rq_in_flight[cfq_cfqq_sync(cfqq)]--; + + cfq_update_io_thinktime(cfqd, cfqq, cic); + cfq_update_io_seektime(cfqd, cfqq, rq); + cfq_update_idle_window(cfqd, cfqq, cic); + + cfqq->last_request_pos = blk_rq_pos(rq) + blk_rq_sectors(rq); + + if (cfqq == cfqd->active_queue) { + if (cfq_cfqq_wait_request(cfqq)) { + if (blk_rq_bytes(rq) > PAGE_CACHE_SIZE || + cfqd->busy_queues > 1) { + cfq_del_timer(cfqd, cfqq); + cfq_clear_cfqq_wait_request(cfqq); + } else { + cfq_blkiocg_update_idle_time_stats( + &cfqq->cfqg->blkg); + cfq_mark_cfqq_must_dispatch(cfqq); + } + } + } else if (cfq_should_preempt(cfqd, cfqq, rq)) { + cfq_preempt_queue(cfqd, cfqq); + } +} + +static int cfq_reinsert_request(struct request_queue *q, struct request *rq) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + struct cfq_queue *cfqq = RQ_CFQQ(rq); + + if (!cfqq || cfqq->cfqd != cfqd) + return -EIO; + + cfq_log_cfqq(cfqd, cfqq, "re-insert_request"); + list_add(&rq->queuelist, &cfqq->fifo); + cfq_add_rq_rb(rq); + + cfq_rq_requeued(cfqd, cfqq, rq); + if (rq->cmd_flags & REQ_URGENT) { + if (cfqd->nr_urgent_in_flight) + cfqd->nr_urgent_in_flight--; + cfqd->nr_urgent_pending++; + } + return 0; +} + static void cfq_insert_request(struct request_queue *q, struct request *rq) { struct cfq_data *cfqd = q->elevator->elevator_data; @@ -3205,7 +3279,45 @@ static void cfq_insert_request(struct request_queue *q, struct request *rq) cfq_blkiocg_update_io_add_stats(&(RQ_CFQG(rq))->blkg, &cfqd->serving_group->blkg, rq_data_dir(rq), rq_is_sync(rq)); + cfq_rq_enqueued(cfqd, cfqq, rq); + + if (rq->cmd_flags & REQ_URGENT) { + WARN_ON(1); + blk_dump_rq_flags(rq, ""); + rq->cmd_flags &= ~REQ_URGENT; + } + + /* Request is considered URGENT if: + * 1. The queue being served is of a lower IO priority then the new + * request + * OR: + * 2. The workload being performed is ASYNC + * Only READ requests may be considered as URGENT + */ + if ((cfqd->active_queue && + cfqq->ioprio_class < cfqd->active_queue->ioprio_class) || + (cfqd->serving_type == ASYNC_WORKLOAD && + rq_data_dir(rq) == READ)) { + rq->cmd_flags |= REQ_URGENT; + cfqd->nr_urgent_pending++; + } +} + + +/** + * cfq_urgent_pending() - Return TRUE if there is an urgent + * request on scheduler + * @q: requests queue + */ +static bool cfq_urgent_pending(struct request_queue *q) +{ + struct cfq_data *cfqd = q->elevator->elevator_data; + + if (cfqd->nr_urgent_pending && !cfqd->nr_urgent_in_flight) + return true; + + return false; } /* @@ -3289,6 +3401,14 @@ static void cfq_completed_request(struct request_queue *q, struct request *rq) const int sync = rq_is_sync(rq); unsigned long now; + if (rq->cmd_flags & REQ_URGENT) { + if (!cfqd->nr_urgent_in_flight) + WARN_ON(1); + else + cfqd->nr_urgent_in_flight--; + rq->cmd_flags &= ~REQ_URGENT; + } + now = jiffies; cfq_log_cfqq(cfqd, cfqq, "complete rqnoidle %d", !!(rq->cmd_flags & REQ_NOIDLE)); @@ -3856,6 +3976,8 @@ static struct elevator_type iosched_cfq = { .elevator_bio_merged_fn = cfq_bio_merged, .elevator_dispatch_fn = cfq_dispatch_requests, .elevator_add_req_fn = cfq_insert_request, + .elevator_reinsert_req_fn = cfq_reinsert_request, + .elevator_is_urgent_fn = cfq_urgent_pending, .elevator_activate_req_fn = cfq_activate_request, .elevator_deactivate_req_fn = cfq_deactivate_request, .elevator_completed_req_fn = cfq_completed_request, diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c index 7bf12d793fc..6d42716a9fa 100644 --- a/block/deadline-iosched.c +++ b/block/deadline-iosched.c @@ -20,7 +20,7 @@ static const int read_expire = HZ / 2; /* max time before a read is submitted. */ static const int write_expire = 5 * HZ; /* ditto for writes, these limits are SOFT! */ static const int writes_starved = 2; /* max times reads can starve a write */ -static const int fifo_batch = 16; /* # of sequential requests treated as one +static const int fifo_batch = 1; /* # of sequential requests treated as one by the above parameters. For throughput. */ struct deadline_data { @@ -230,7 +230,7 @@ static inline int deadline_check_fifo(struct deadline_data *dd, int ddir) /* * rq is expired! */ - if (time_after(jiffies, rq_fifo_time(rq))) + if (time_after_eq(jiffies, rq_fifo_time(rq))) return 1; return 0; diff --git a/block/elevator.c b/block/elevator.c index 74fd51b154f..4368180a8df 100644 --- a/block/elevator.c +++ b/block/elevator.c @@ -585,6 +585,41 @@ void elv_requeue_request(struct request_queue *q, struct request *rq) __elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE); } +/** + * elv_reinsert_request() - Insert a request back to the scheduler + * @q: request queue where request should be inserted + * @rq: request to be inserted + * + * This function returns the request back to the scheduler to be + * inserted as if it was never dispatched + * + * Return: 0 on success, error code on failure + */ +int elv_reinsert_request(struct request_queue *q, struct request *rq) +{ + int res; + + if (!q->elevator->type->ops.elevator_reinsert_req_fn) + return -EPERM; + + res = q->elevator->type->ops.elevator_reinsert_req_fn(q, rq); + if (!res) { + /* + * it already went through dequeue, we need to decrement the + * in_flight count again + */ + if (blk_account_rq(rq)) { + q->in_flight[rq_is_sync(rq)]--; + if (rq->cmd_flags & REQ_SORTED) + elv_deactivate_rq(q, rq); + } + rq->cmd_flags &= ~REQ_STARTED; + q->nr_sorted++; + } + + return res; +} + void elv_drain_elevator(struct request_queue *q) { static int printed; @@ -779,6 +814,10 @@ void elv_completed_request(struct request_queue *q, struct request *rq) { struct elevator_queue *e = q->elevator; + if (rq->cmd_flags & REQ_URGENT) { + q->notified_urgent = false; + q->dispatched_urgent = false; + } /* * request is released from the driver, io must be done */ diff --git a/block/fiops-iosched.c b/block/fiops-iosched.c new file mode 100644 index 00000000000..52ae15ee1a7 --- /dev/null +++ b/block/fiops-iosched.c @@ -0,0 +1,754 @@ +/* + * IOPS based IO scheduler. Based on CFQ. + * Copyright (C) 2003 Jens Axboe + * Shaohua Li + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "blk.h" + +#define VIOS_SCALE_SHIFT 10 +#define VIOS_SCALE (1 << VIOS_SCALE_SHIFT) + +#define VIOS_READ_SCALE (1) +#define VIOS_WRITE_SCALE (1) +#define VIOS_SYNC_SCALE (2) +#define VIOS_ASYNC_SCALE (5) + +#define VIOS_PRIO_SCALE (5) + +struct fiops_rb_root { + struct rb_root rb; + struct rb_node *left; + unsigned count; + + u64 min_vios; +}; +#define FIOPS_RB_ROOT (struct fiops_rb_root) { .rb = RB_ROOT} + +enum wl_prio_t { + IDLE_WORKLOAD = 0, + BE_WORKLOAD = 1, + RT_WORKLOAD = 2, + FIOPS_PRIO_NR, +}; + +struct fiops_data { + struct request_queue *queue; + + struct fiops_rb_root service_tree[FIOPS_PRIO_NR]; + + unsigned int busy_queues; + unsigned int in_flight[2]; + + struct work_struct unplug_work; + + unsigned int read_scale; + unsigned int write_scale; + unsigned int sync_scale; + unsigned int async_scale; +}; + +struct fiops_ioc { + struct io_cq icq; + + unsigned int flags; + struct fiops_data *fiopsd; + struct rb_node rb_node; + u64 vios; /* key in service_tree */ + struct fiops_rb_root *service_tree; + + unsigned int in_flight; + + struct rb_root sort_list; + struct list_head fifo; + + pid_t pid; + unsigned short ioprio; + enum wl_prio_t wl_type; +}; + +#define ioc_service_tree(ioc) (&((ioc)->fiopsd->service_tree[(ioc)->wl_type])) +#define RQ_CIC(rq) icq_to_cic((rq)->elv.icq) + +enum ioc_state_flags { + FIOPS_IOC_FLAG_on_rr = 0, /* on round-robin busy list */ + FIOPS_IOC_FLAG_prio_changed, /* task priority has changed */ +}; + +#define FIOPS_IOC_FNS(name) \ +static inline void fiops_mark_ioc_##name(struct fiops_ioc *ioc) \ +{ \ + ioc->flags |= (1 << FIOPS_IOC_FLAG_##name); \ +} \ +static inline void fiops_clear_ioc_##name(struct fiops_ioc *ioc) \ +{ \ + ioc->flags &= ~(1 << FIOPS_IOC_FLAG_##name); \ +} \ +static inline int fiops_ioc_##name(const struct fiops_ioc *ioc) \ +{ \ + return ((ioc)->flags & (1 << FIOPS_IOC_FLAG_##name)) != 0; \ +} + +FIOPS_IOC_FNS(on_rr); +FIOPS_IOC_FNS(prio_changed); +#undef FIOPS_IOC_FNS + +#define fiops_log_ioc(fiopsd, ioc, fmt, args...) \ + blk_add_trace_msg((fiopsd)->queue, "ioc%d " fmt, (ioc)->pid, ##args) +#define fiops_log(fiopsd, fmt, args...) \ + blk_add_trace_msg((fiopsd)->queue, "fiops " fmt, ##args) + +enum wl_prio_t fiops_wl_type(short prio_class) +{ + if (prio_class == IOPRIO_CLASS_RT) + return RT_WORKLOAD; + if (prio_class == IOPRIO_CLASS_BE) + return BE_WORKLOAD; + return IDLE_WORKLOAD; +} + +static inline struct fiops_ioc *icq_to_cic(struct io_cq *icq) +{ + /* cic->icq is the first member, %NULL will convert to %NULL */ + return container_of(icq, struct fiops_ioc, icq); +} + +static inline struct fiops_ioc *fiops_cic_lookup(struct fiops_data *fiopsd, + struct io_context *ioc) +{ + if (ioc) + return icq_to_cic(ioc_lookup_icq(ioc, fiopsd->queue)); + return NULL; +} + +/* + * The below is leftmost cache rbtree addon + */ +static struct fiops_ioc *fiops_rb_first(struct fiops_rb_root *root) +{ + /* Service tree is empty */ + if (!root->count) + return NULL; + + if (!root->left) + root->left = rb_first(&root->rb); + + if (root->left) + return rb_entry(root->left, struct fiops_ioc, rb_node); + + return NULL; +} + +static void rb_erase_init(struct rb_node *n, struct rb_root *root) +{ + rb_erase(n, root); + RB_CLEAR_NODE(n); +} + +static void fiops_rb_erase(struct rb_node *n, struct fiops_rb_root *root) +{ + if (root->left == n) + root->left = NULL; + rb_erase_init(n, &root->rb); + --root->count; +} + +static inline u64 max_vios(u64 min_vios, u64 vios) +{ + s64 delta = (s64)(vios - min_vios); + if (delta > 0) + min_vios = vios; + + return min_vios; +} + +static void fiops_update_min_vios(struct fiops_rb_root *service_tree) +{ + struct fiops_ioc *ioc; + + ioc = fiops_rb_first(service_tree); + if (!ioc) + return; + service_tree->min_vios = max_vios(service_tree->min_vios, ioc->vios); +} + +/* + * The fiopsd->service_trees holds all pending fiops_ioc's that have + * requests waiting to be processed. It is sorted in the order that + * we will service the queues. + */ +static void fiops_service_tree_add(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + struct rb_node **p, *parent; + struct fiops_ioc *__ioc; + struct fiops_rb_root *service_tree = ioc_service_tree(ioc); + u64 vios; + int left; + + /* New added IOC */ + if (RB_EMPTY_NODE(&ioc->rb_node)) { + if (ioc->in_flight > 0) + vios = ioc->vios; + else + vios = max_vios(service_tree->min_vios, ioc->vios); + } else { + vios = ioc->vios; + /* ioc->service_tree might not equal to service_tree */ + fiops_rb_erase(&ioc->rb_node, ioc->service_tree); + ioc->service_tree = NULL; + } + + fiops_log_ioc(fiopsd, ioc, "service tree add, vios %lld", vios); + + left = 1; + parent = NULL; + ioc->service_tree = service_tree; + p = &service_tree->rb.rb_node; + while (*p) { + struct rb_node **n; + + parent = *p; + __ioc = rb_entry(parent, struct fiops_ioc, rb_node); + + /* + * sort by key, that represents service time. + */ + if (vios < __ioc->vios) + n = &(*p)->rb_left; + else { + n = &(*p)->rb_right; + left = 0; + } + + p = n; + } + + if (left) + service_tree->left = &ioc->rb_node; + + ioc->vios = vios; + rb_link_node(&ioc->rb_node, parent, p); + rb_insert_color(&ioc->rb_node, &service_tree->rb); + service_tree->count++; + + fiops_update_min_vios(service_tree); +} + +/* + * Update ioc's position in the service tree. + */ +static void fiops_resort_rr_list(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + /* + * Resorting requires the ioc to be on the RR list already. + */ + if (fiops_ioc_on_rr(ioc)) + fiops_service_tree_add(fiopsd, ioc); +} + +/* + * add to busy list of queues for service, trying to be fair in ordering + * the pending list according to last request service + */ +static void fiops_add_ioc_rr(struct fiops_data *fiopsd, struct fiops_ioc *ioc) +{ + BUG_ON(fiops_ioc_on_rr(ioc)); + fiops_mark_ioc_on_rr(ioc); + + fiopsd->busy_queues++; + + fiops_resort_rr_list(fiopsd, ioc); +} + +/* + * Called when the ioc no longer has requests pending, remove it from + * the service tree. + */ +static void fiops_del_ioc_rr(struct fiops_data *fiopsd, struct fiops_ioc *ioc) +{ + BUG_ON(!fiops_ioc_on_rr(ioc)); + fiops_clear_ioc_on_rr(ioc); + + if (!RB_EMPTY_NODE(&ioc->rb_node)) { + fiops_rb_erase(&ioc->rb_node, ioc->service_tree); + ioc->service_tree = NULL; + } + + BUG_ON(!fiopsd->busy_queues); + fiopsd->busy_queues--; +} + +/* + * rb tree support functions + */ +static void fiops_del_rq_rb(struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + + elv_rb_del(&ioc->sort_list, rq); +} + +static void fiops_add_rq_rb(struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + struct fiops_data *fiopsd = ioc->fiopsd; + + elv_rb_add(&ioc->sort_list, rq); + + if (!fiops_ioc_on_rr(ioc)) + fiops_add_ioc_rr(fiopsd, ioc); +} + +static void fiops_reposition_rq_rb(struct fiops_ioc *ioc, struct request *rq) +{ + elv_rb_del(&ioc->sort_list, rq); + fiops_add_rq_rb(rq); +} + +static void fiops_remove_request(struct request *rq) +{ + list_del_init(&rq->queuelist); + fiops_del_rq_rb(rq); +} + +static u64 fiops_scaled_vios(struct fiops_data *fiopsd, + struct fiops_ioc *ioc, struct request *rq) +{ + int vios = VIOS_SCALE; + + if (rq_data_dir(rq) == WRITE) + vios = vios * fiopsd->write_scale / fiopsd->read_scale; + + if (!rq_is_sync(rq)) + vios = vios * fiopsd->async_scale / fiopsd->sync_scale; + + vios += vios * (ioc->ioprio - IOPRIO_NORM) / VIOS_PRIO_SCALE; + + return vios; +} + +/* return vios dispatched */ +static u64 fiops_dispatch_request(struct fiops_data *fiopsd, + struct fiops_ioc *ioc) +{ + struct request *rq; + struct request_queue *q = fiopsd->queue; + + rq = rq_entry_fifo(ioc->fifo.next); + + fiops_remove_request(rq); + elv_dispatch_add_tail(q, rq); + + fiopsd->in_flight[rq_is_sync(rq)]++; + ioc->in_flight++; + + return fiops_scaled_vios(fiopsd, ioc, rq); +} + +static int fiops_forced_dispatch(struct fiops_data *fiopsd) +{ + struct fiops_ioc *ioc; + int dispatched = 0; + int i; + + for (i = RT_WORKLOAD; i >= IDLE_WORKLOAD; i--) { + while (!RB_EMPTY_ROOT(&fiopsd->service_tree[i].rb)) { + ioc = fiops_rb_first(&fiopsd->service_tree[i]); + + while (!list_empty(&ioc->fifo)) { + fiops_dispatch_request(fiopsd, ioc); + dispatched++; + } + if (fiops_ioc_on_rr(ioc)) + fiops_del_ioc_rr(fiopsd, ioc); + } + } + return dispatched; +} + +static struct fiops_ioc *fiops_select_ioc(struct fiops_data *fiopsd) +{ + struct fiops_ioc *ioc; + struct fiops_rb_root *service_tree = NULL; + int i; + struct request *rq; + + for (i = RT_WORKLOAD; i >= IDLE_WORKLOAD; i--) { + if (!RB_EMPTY_ROOT(&fiopsd->service_tree[i].rb)) { + service_tree = &fiopsd->service_tree[i]; + break; + } + } + + if (!service_tree) + return NULL; + + ioc = fiops_rb_first(service_tree); + + rq = rq_entry_fifo(ioc->fifo.next); + /* + * we are the only async task and sync requests are in flight, delay a + * moment. If there are other tasks coming, sync tasks have no chance + * to be starved, don't delay + */ + if (!rq_is_sync(rq) && fiopsd->in_flight[1] != 0 && + service_tree->count == 1) { + fiops_log_ioc(fiopsd, ioc, + "postpone async, in_flight async %d sync %d", + fiopsd->in_flight[0], fiopsd->in_flight[1]); + return NULL; + } + + return ioc; +} + +static void fiops_charge_vios(struct fiops_data *fiopsd, + struct fiops_ioc *ioc, u64 vios) +{ + struct fiops_rb_root *service_tree = ioc->service_tree; + ioc->vios += vios; + + fiops_log_ioc(fiopsd, ioc, "charge vios %lld, new vios %lld", vios, ioc->vios); + + if (RB_EMPTY_ROOT(&ioc->sort_list)) + fiops_del_ioc_rr(fiopsd, ioc); + else + fiops_resort_rr_list(fiopsd, ioc); + + fiops_update_min_vios(service_tree); +} + +static int fiops_dispatch_requests(struct request_queue *q, int force) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *ioc; + u64 vios; + + if (unlikely(force)) + return fiops_forced_dispatch(fiopsd); + + ioc = fiops_select_ioc(fiopsd); + if (!ioc) + return 0; + + vios = fiops_dispatch_request(fiopsd, ioc); + + fiops_charge_vios(fiopsd, ioc, vios); + return 1; +} + +static void fiops_init_prio_data(struct fiops_ioc *cic) +{ + struct task_struct *tsk = current; + struct io_context *ioc = cic->icq.ioc; + int ioprio_class; + + if (!fiops_ioc_prio_changed(cic)) + return; + + ioprio_class = IOPRIO_PRIO_CLASS(ioc->ioprio); + switch (ioprio_class) { + default: + printk(KERN_ERR "fiops: bad prio %x\n", ioprio_class); + case IOPRIO_CLASS_NONE: + /* + * no prio set, inherit CPU scheduling settings + */ + cic->ioprio = task_nice_ioprio(tsk); + cic->wl_type = fiops_wl_type(task_nice_ioclass(tsk)); + break; + case IOPRIO_CLASS_RT: + cic->ioprio = task_ioprio(ioc); + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_RT); + break; + case IOPRIO_CLASS_BE: + cic->ioprio = task_ioprio(ioc); + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_BE); + break; + case IOPRIO_CLASS_IDLE: + cic->wl_type = fiops_wl_type(IOPRIO_CLASS_IDLE); + cic->ioprio = 7; + break; + } + + fiops_clear_ioc_prio_changed(cic); +} + +static void fiops_insert_request(struct request_queue *q, struct request *rq) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + + fiops_init_prio_data(ioc); + + list_add_tail(&rq->queuelist, &ioc->fifo); + + fiops_add_rq_rb(rq); +} + +/* + * scheduler run of queue, if there are requests pending and no one in the + * driver that will restart queueing + */ +static inline void fiops_schedule_dispatch(struct fiops_data *fiopsd) +{ + if (fiopsd->busy_queues) + kblockd_schedule_work(fiopsd->queue, &fiopsd->unplug_work); +} + +static void fiops_completed_request(struct request_queue *q, struct request *rq) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *ioc = RQ_CIC(rq); + + fiopsd->in_flight[rq_is_sync(rq)]--; + ioc->in_flight--; + + fiops_log_ioc(fiopsd, ioc, "in_flight %d, busy queues %d", + ioc->in_flight, fiopsd->busy_queues); + + if (fiopsd->in_flight[0] + fiopsd->in_flight[1] == 0) + fiops_schedule_dispatch(fiopsd); +} + +static struct request * +fiops_find_rq_fmerge(struct fiops_data *fiopsd, struct bio *bio) +{ + struct task_struct *tsk = current; + struct fiops_ioc *cic; + + cic = fiops_cic_lookup(fiopsd, tsk->io_context); + + if (cic) { + sector_t sector = bio->bi_sector + bio_sectors(bio); + + return elv_rb_find(&cic->sort_list, sector); + } + + return NULL; +} + +static int fiops_merge(struct request_queue *q, struct request **req, + struct bio *bio) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct request *__rq; + + __rq = fiops_find_rq_fmerge(fiopsd, bio); + if (__rq && elv_rq_merge_ok(__rq, bio)) { + *req = __rq; + return ELEVATOR_FRONT_MERGE; + } + + return ELEVATOR_NO_MERGE; +} + +static void fiops_merged_request(struct request_queue *q, struct request *req, + int type) +{ + if (type == ELEVATOR_FRONT_MERGE) { + struct fiops_ioc *ioc = RQ_CIC(req); + + fiops_reposition_rq_rb(ioc, req); + } +} + +static void +fiops_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + struct fiops_ioc *ioc = RQ_CIC(rq); + struct fiops_data *fiopsd = q->elevator->elevator_data; + + fiops_remove_request(next); + + ioc = RQ_CIC(next); + /* + * all requests of this task are merged to other tasks, delete it + * from the service tree. + */ + if (fiops_ioc_on_rr(ioc) && RB_EMPTY_ROOT(&ioc->sort_list)) + fiops_del_ioc_rr(fiopsd, ioc); +} + +static int fiops_allow_merge(struct request_queue *q, struct request *rq, + struct bio *bio) +{ + struct fiops_data *fiopsd = q->elevator->elevator_data; + struct fiops_ioc *cic; + + /* + * Lookup the ioc that this bio will be queued with. Allow + * merge only if rq is queued there. + */ + cic = fiops_cic_lookup(fiopsd, current->io_context); + + return cic == RQ_CIC(rq); +} + +static void fiops_exit_queue(struct elevator_queue *e) +{ + struct fiops_data *fiopsd = e->elevator_data; + + cancel_work_sync(&fiopsd->unplug_work); + + kfree(fiopsd); +} + +static void fiops_kick_queue(struct work_struct *work) +{ + struct fiops_data *fiopsd = + container_of(work, struct fiops_data, unplug_work); + struct request_queue *q = fiopsd->queue; + + spin_lock_irq(q->queue_lock); + __blk_run_queue(q); + spin_unlock_irq(q->queue_lock); +} + +static void *fiops_init_queue(struct request_queue *q) +{ + struct fiops_data *fiopsd; + int i; + + fiopsd = kzalloc_node(sizeof(*fiopsd), GFP_KERNEL, q->node); + if (!fiopsd) + return NULL; + + fiopsd->queue = q; + + for (i = IDLE_WORKLOAD; i <= RT_WORKLOAD; i++) + fiopsd->service_tree[i] = FIOPS_RB_ROOT; + + INIT_WORK(&fiopsd->unplug_work, fiops_kick_queue); + + fiopsd->read_scale = VIOS_READ_SCALE; + fiopsd->write_scale = VIOS_WRITE_SCALE; + fiopsd->sync_scale = VIOS_SYNC_SCALE; + fiopsd->async_scale = VIOS_ASYNC_SCALE; + + return fiopsd; +} + +static void fiops_init_icq(struct io_cq *icq) +{ + struct fiops_data *fiopsd = icq->q->elevator->elevator_data; + struct fiops_ioc *ioc = icq_to_cic(icq); + + RB_CLEAR_NODE(&ioc->rb_node); + INIT_LIST_HEAD(&ioc->fifo); + ioc->sort_list = RB_ROOT; + + ioc->fiopsd = fiopsd; + + ioc->pid = current->pid; + fiops_mark_ioc_prio_changed(ioc); +} + +/* + * sysfs parts below --> + */ +static ssize_t +fiops_var_show(unsigned int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +fiops_var_store(unsigned int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtoul(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct fiops_data *fiopsd = e->elevator_data; \ + return fiops_var_show(__VAR, (page)); \ +} +SHOW_FUNCTION(fiops_read_scale_show, fiopsd->read_scale); +SHOW_FUNCTION(fiops_write_scale_show, fiopsd->write_scale); +SHOW_FUNCTION(fiops_sync_scale_show, fiopsd->sync_scale); +SHOW_FUNCTION(fiops_async_scale_show, fiopsd->async_scale); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct fiops_data *fiopsd = e->elevator_data; \ + unsigned int __data; \ + int ret = fiops_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(fiops_read_scale_store, &fiopsd->read_scale, 1, 100); +STORE_FUNCTION(fiops_write_scale_store, &fiopsd->write_scale, 1, 100); +STORE_FUNCTION(fiops_sync_scale_store, &fiopsd->sync_scale, 1, 100); +STORE_FUNCTION(fiops_async_scale_store, &fiopsd->async_scale, 1, 100); +#undef STORE_FUNCTION + +#define FIOPS_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, fiops_##name##_show, fiops_##name##_store) + +static struct elv_fs_entry fiops_attrs[] = { + FIOPS_ATTR(read_scale), + FIOPS_ATTR(write_scale), + FIOPS_ATTR(sync_scale), + FIOPS_ATTR(async_scale), + __ATTR_NULL +}; + +static struct elevator_type iosched_fiops = { + .ops = { + .elevator_merge_fn = fiops_merge, + .elevator_merged_fn = fiops_merged_request, + .elevator_merge_req_fn = fiops_merged_requests, + .elevator_allow_merge_fn = fiops_allow_merge, + .elevator_dispatch_fn = fiops_dispatch_requests, + .elevator_add_req_fn = fiops_insert_request, + .elevator_completed_req_fn = fiops_completed_request, + .elevator_former_req_fn = elv_rb_former_request, + .elevator_latter_req_fn = elv_rb_latter_request, + .elevator_init_icq_fn = fiops_init_icq, + .elevator_init_fn = fiops_init_queue, + .elevator_exit_fn = fiops_exit_queue, + }, + .icq_size = sizeof(struct fiops_ioc), + .icq_align = __alignof__(struct fiops_ioc), + .elevator_attrs = fiops_attrs, + .elevator_name = "fiops", + .elevator_owner = THIS_MODULE, +}; + +static int __init fiops_init(void) +{ + return elv_register(&iosched_fiops); +} + +static void __exit fiops_exit(void) +{ + elv_unregister(&iosched_fiops); +} + +module_init(fiops_init); +module_exit(fiops_exit); + +MODULE_AUTHOR("Jens Axboe, Shaohua Li "); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("IOPS based IO scheduler"); + diff --git a/block/row-iosched.c b/block/row-iosched.c new file mode 100644 index 00000000000..dfb46b42712 --- /dev/null +++ b/block/row-iosched.c @@ -0,0 +1,1097 @@ +/* + * ROW (Read Over Write) I/O scheduler. + * + * Copyright (c) 2012-2013, 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. + */ + +/* See Documentation/block/row-iosched.txt */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * enum row_queue_prio - Priorities of the ROW queues + * + * This enum defines the priorities (and the number of queues) + * the requests will be distributed to. The higher priority - + * the bigger is the "bus time" (or the dispatch quantum) given + * to that queue. + * ROWQ_PRIO_HIGH_READ - is the higher priority queue. + * + */ +enum row_queue_prio { + ROWQ_PRIO_HIGH_READ = 0, + ROWQ_PRIO_HIGH_SWRITE, + ROWQ_PRIO_REG_READ, + ROWQ_PRIO_REG_SWRITE, + ROWQ_PRIO_REG_WRITE, + ROWQ_PRIO_LOW_READ, + ROWQ_PRIO_LOW_SWRITE, + ROWQ_MAX_PRIO, +}; + +/* + * The following indexes define the distribution of ROW queues according to + * priorities. Each index defines the first queue in that priority group. + */ +#define ROWQ_HIGH_PRIO_IDX ROWQ_PRIO_HIGH_READ +#define ROWQ_REG_PRIO_IDX ROWQ_PRIO_REG_READ +#define ROWQ_LOW_PRIO_IDX ROWQ_PRIO_LOW_READ + +/** + * struct row_queue_params - ROW queue parameters + * @idling_enabled: Flag indicating whether idling is enable on + * the queue + * @quantum: Number of requests to be dispatched from this queue + * in a dispatch cycle + * @is_urgent: Flags indicating whether the queue can notify on + * urgent requests + * + */ +struct row_queue_params { + bool idling_enabled; + int quantum; + bool is_urgent; +}; + +/* + * This array holds the default values of the different configurables + * for each ROW queue. Each row of the array holds the following values: + * {idling_enabled, quantum, is_urgent} + * Each row corresponds to a queue with the same index (according to + * enum row_queue_prio) + * Note: The quantums are valid inside their priority type. For example: + * For every 10 high priority read requests, 1 high priority sync + * write will be dispatched. + * For every 100 regular read requests 1 regular write request will + * be dispatched. + */ +static const struct row_queue_params row_queues_def[] = { +/* idling_enabled, quantum, is_urgent */ + {true, 10, true}, /* ROWQ_PRIO_HIGH_READ */ + {false, 1, false}, /* ROWQ_PRIO_HIGH_SWRITE */ + {true, 100, true}, /* ROWQ_PRIO_REG_READ */ + {false, 1, false}, /* ROWQ_PRIO_REG_SWRITE */ + {false, 1, false}, /* ROWQ_PRIO_REG_WRITE */ + {false, 1, false}, /* ROWQ_PRIO_LOW_READ */ + {false, 1, false} /* ROWQ_PRIO_LOW_SWRITE */ +}; + +/* Default values for idling on read queues (in msec) */ +#define ROW_IDLE_TIME_MSEC 5 +#define ROW_READ_FREQ_MSEC 5 + +/** + * struct rowq_idling_data - parameters for idling on the queue + * @last_insert_time: time the last request was inserted + * to the queue + * @begin_idling: flag indicating wether we should idle + * + */ +struct rowq_idling_data { + ktime_t last_insert_time; + bool begin_idling; +}; + +/** + * struct row_queue - requests grouping structure + * @rdata: parent row_data structure + * @fifo: fifo of requests + * @prio: queue priority (enum row_queue_prio) + * @nr_dispatched: number of requests already dispatched in + * the current dispatch cycle + * @nr_req: number of requests in queue + * @dispatch quantum: number of requests this queue may + * dispatch in a dispatch cycle + * @idle_data: data for idling on queues + * + */ +struct row_queue { + struct row_data *rdata; + struct list_head fifo; + enum row_queue_prio prio; + + unsigned int nr_dispatched; + + unsigned int nr_req; + int disp_quantum; + + /* used only for READ queues */ + struct rowq_idling_data idle_data; +}; + +/** + * struct idling_data - data for idling on empty rqueue + * @idle_time_ms: idling duration (msec) + * @freq_ms: min time between two requests that + * triger idling (msec) + * @hr_timer: idling timer + * @idle_work: the work to be scheduled when idling timer expires + * @idling_queue_idx: index of the queues we're idling on + * + */ +struct idling_data { + s64 idle_time_ms; + s64 freq_ms; + + struct hrtimer hr_timer; + struct work_struct idle_work; + enum row_queue_prio idling_queue_idx; +}; + +/** + * struct starvation_data - data for starvation management + * @starvation_limit: number of times this priority class + * can tolerate being starved + * @starvation_counter: number of requests from higher + * priority classes that were dispatched while this + * priority request were pending + * + */ +struct starvation_data { + int starvation_limit; + int starvation_counter; +}; + +/** + * struct row_queue - Per block device rqueue structure + * @dispatch_queue: dispatch rqueue + * @row_queues: array of priority request queues + * @rd_idle_data: data for idling after READ request + * @nr_reqs: nr_reqs[0] holds the number of all READ requests in + * scheduler, nr_reqs[1] holds the number of all WRITE + * requests in scheduler + * @urgent_in_flight: flag indicating that there is an urgent + * request that was dispatched to driver and is yet to + * complete. + * @pending_urgent_rq: pointer to the pending urgent request + * @last_served_ioprio_class: I/O priority class that was last dispatched from + * @reg_prio_starvation: starvation data for REGULAR priority queues + * @low_prio_starvation: starvation data for LOW priority queues + * @cycle_flags: used for marking unserved queueus + * + */ +struct row_data { + struct request_queue *dispatch_queue; + + struct row_queue row_queues[ROWQ_MAX_PRIO]; + + struct idling_data rd_idle_data; + unsigned int nr_reqs[2]; + bool urgent_in_flight; + struct request *pending_urgent_rq; + int last_served_ioprio_class; + +#define ROW_REG_STARVATION_TOLLERANCE 5000 + struct starvation_data reg_prio_starvation; +#define ROW_LOW_STARVATION_TOLLERANCE 10000 + struct starvation_data low_prio_starvation; + + unsigned int cycle_flags; +}; + +#define RQ_ROWQ(rq) ((struct row_queue *) ((rq)->elv.priv[0])) + +#define row_log(q, fmt, args...) \ + blk_add_trace_msg(q, "%s():" fmt , __func__, ##args) +#define row_log_rowq(rdata, rowq_id, fmt, args...) \ + blk_add_trace_msg(rdata->dispatch_queue, "rowq%d " fmt, \ + rowq_id, ##args) + +static inline void row_mark_rowq_unserved(struct row_data *rd, + enum row_queue_prio qnum) +{ + rd->cycle_flags |= (1 << qnum); +} + +static inline void row_clear_rowq_unserved(struct row_data *rd, + enum row_queue_prio qnum) +{ + rd->cycle_flags &= ~(1 << qnum); +} + +static inline int row_rowq_unserved(struct row_data *rd, + enum row_queue_prio qnum) +{ + return rd->cycle_flags & (1 << qnum); +} + +static inline void __maybe_unused row_dump_queues_stat(struct row_data *rd) +{ + int i; + + row_log(rd->dispatch_queue, " Queues status:"); + for (i = 0; i < ROWQ_MAX_PRIO; i++) + row_log(rd->dispatch_queue, + "queue%d: dispatched= %d, nr_req=%d", i, + rd->row_queues[i].nr_dispatched, + rd->row_queues[i].nr_req); +} + +/******************** Static helper functions ***********************/ +static void kick_queue(struct work_struct *work) +{ + struct idling_data *read_data = + container_of(work, struct idling_data, idle_work); + struct row_data *rd = + container_of(read_data, struct row_data, rd_idle_data); + + blk_run_queue(rd->dispatch_queue); +} + + +static enum hrtimer_restart row_idle_hrtimer_fn(struct hrtimer *hr_timer) +{ + struct idling_data *read_data = + container_of(hr_timer, struct idling_data, hr_timer); + struct row_data *rd = + container_of(read_data, struct row_data, rd_idle_data); + + row_log_rowq(rd, rd->rd_idle_data.idling_queue_idx, + "Performing delayed work"); + /* Mark idling process as done */ + rd->row_queues[rd->rd_idle_data.idling_queue_idx]. + idle_data.begin_idling = false; + rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + + if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE]) + row_log(rd->dispatch_queue, "No requests in scheduler"); + else + kblockd_schedule_work(rd->dispatch_queue, + &read_data->idle_work); + return HRTIMER_NORESTART; +} + +/* + * row_regular_req_pending() - Check if there are REGULAR priority requests + * Pending in scheduler + * @rd: pointer to struct row_data + * + * Returns True if there are REGULAR priority requests in scheduler queues. + * False, otherwise. + */ +static inline bool row_regular_req_pending(struct row_data *rd) +{ + int i; + + for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++) + if (!list_empty(&rd->row_queues[i].fifo)) + return true; + return false; +} + +/* + * row_low_req_pending() - Check if there are LOW priority requests + * Pending in scheduler + * @rd: pointer to struct row_data + * + * Returns True if there are LOW priority requests in scheduler queues. + * False, otherwise. + */ +static inline bool row_low_req_pending(struct row_data *rd) +{ + int i; + + for (i = ROWQ_LOW_PRIO_IDX; i < ROWQ_MAX_PRIO; i++) + if (!list_empty(&rd->row_queues[i].fifo)) + return true; + return false; +} + +/******************* Elevator callback functions *********************/ + +/* + * row_add_request() - Add request to the scheduler + * @q: requests queue + * @rq: request to add + * + */ +static void row_add_request(struct request_queue *q, + struct request *rq) +{ + struct row_data *rd = (struct row_data *)q->elevator->elevator_data; + struct row_queue *rqueue = RQ_ROWQ(rq); + s64 diff_ms; + bool queue_was_empty = list_empty(&rqueue->fifo); + unsigned long bv_page_flags = 0; + + if (rq->bio && rq->bio->bi_io_vec && rq->bio->bi_io_vec->bv_page) + bv_page_flags = rq->bio->bi_io_vec->bv_page->flags; + + list_add_tail(&rq->queuelist, &rqueue->fifo); + rd->nr_reqs[rq_data_dir(rq)]++; + rqueue->nr_req++; + rq_set_fifo_time(rq, jiffies); /* for statistics*/ + + if (rq->cmd_flags & REQ_URGENT) { + WARN_ON(1); + blk_dump_rq_flags(rq, ""); + rq->cmd_flags &= ~REQ_URGENT; + } + + if (row_queues_def[rqueue->prio].idling_enabled) { + if (rd->rd_idle_data.idling_queue_idx == rqueue->prio && + hrtimer_active(&rd->rd_idle_data.hr_timer)) { + if (hrtimer_try_to_cancel( + &rd->rd_idle_data.hr_timer) >= 0) { + row_log_rowq(rd, rqueue->prio, + "Canceled delayed work on %d", + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = + ROWQ_MAX_PRIO; + } + } + diff_ms = ktime_to_ms(ktime_sub(ktime_get(), + rqueue->idle_data.last_insert_time)); + if (unlikely(diff_ms < 0)) { + pr_err("%s(): time delta error: diff_ms < 0", + __func__); + rqueue->idle_data.begin_idling = false; + return; + } + + if ((bv_page_flags & (1L << PG_readahead)) || + (diff_ms < rd->rd_idle_data.freq_ms)) { + rqueue->idle_data.begin_idling = true; + row_log_rowq(rd, rqueue->prio, "Enable idling"); + } else { + rqueue->idle_data.begin_idling = false; + row_log_rowq(rd, rqueue->prio, "Disable idling (%ldms)", + (long)diff_ms); + } + + rqueue->idle_data.last_insert_time = ktime_get(); + } + if (row_queues_def[rqueue->prio].is_urgent && + !rd->pending_urgent_rq && !rd->urgent_in_flight) { + /* Handle High Priority queues */ + if (rqueue->prio < ROWQ_REG_PRIO_IDX && + rd->last_served_ioprio_class != IOPRIO_CLASS_RT && + queue_was_empty) { + row_log_rowq(rd, rqueue->prio, + "added (high prio) urgent request"); + rq->cmd_flags |= REQ_URGENT; + rd->pending_urgent_rq = rq; + } else if (row_rowq_unserved(rd, rqueue->prio)) { + /* Handle Regular priotity queues */ + row_log_rowq(rd, rqueue->prio, + "added urgent request (total on queue=%d)", + rqueue->nr_req); + rq->cmd_flags |= REQ_URGENT; + rd->pending_urgent_rq = rq; + } + } else + row_log_rowq(rd, rqueue->prio, + "added request (total on queue=%d)", rqueue->nr_req); +} + +/** + * row_reinsert_req() - Reinsert request back to the scheduler + * @q: requests queue + * @rq: request to add + * + * Reinsert the given request back to the queue it was + * dispatched from as if it was never dispatched. + * + * Returns 0 on success, error code otherwise + */ +static int row_reinsert_req(struct request_queue *q, + struct request *rq) +{ + struct row_data *rd = q->elevator->elevator_data; + struct row_queue *rqueue = RQ_ROWQ(rq); + + if (!rqueue || rqueue->prio >= ROWQ_MAX_PRIO) + return -EIO; + + list_add(&rq->queuelist, &rqueue->fifo); + rd->nr_reqs[rq_data_dir(rq)]++; + rqueue->nr_req++; + + row_log_rowq(rd, rqueue->prio, + "%s request reinserted (total on queue=%d)", + (rq_data_dir(rq) == READ ? "READ" : "write"), rqueue->nr_req); + + if (rq->cmd_flags & REQ_URGENT) { + /* + * It's not compliant with the design to re-insert + * urgent requests. We want to be able to track this + * down. + */ + WARN_ON(1); + if (!rd->urgent_in_flight) { + pr_err("%s(): no urgent in flight", __func__); + } else { + rd->urgent_in_flight = false; + pr_err("%s(): reinserting URGENT %s req", + __func__, + (rq_data_dir(rq) == READ ? "READ" : "WRITE")); + if (rd->pending_urgent_rq) { + pr_err("%s(): urgent rq is pending", + __func__); + rd->pending_urgent_rq->cmd_flags &= ~REQ_URGENT; + } + rd->pending_urgent_rq = rq; + } + } + return 0; +} + +static void row_completed_req(struct request_queue *q, struct request *rq) +{ + struct row_data *rd = q->elevator->elevator_data; + + if (rq->cmd_flags & REQ_URGENT) { + if (!rd->urgent_in_flight) { + WARN_ON(1); + pr_err("%s(): URGENT req but urgent_in_flight = F", + __func__); + } + rd->urgent_in_flight = false; + rq->cmd_flags &= ~REQ_URGENT; + } + row_log(q, "completed %s %s req.", + (rq->cmd_flags & REQ_URGENT ? "URGENT" : "regular"), + (rq_data_dir(rq) == READ ? "READ" : "WRITE")); +} + +/** + * row_urgent_pending() - Return TRUE if there is an urgent + * request on scheduler + * @q: requests queue + */ +static bool row_urgent_pending(struct request_queue *q) +{ + struct row_data *rd = q->elevator->elevator_data; + + if (rd->urgent_in_flight) { + row_log(rd->dispatch_queue, "%d urgent requests in flight", + rd->urgent_in_flight); + return false; + } + + if (rd->pending_urgent_rq) { + row_log(rd->dispatch_queue, "Urgent request pending"); + return true; + } + + row_log(rd->dispatch_queue, "no urgent request pending/in flight"); + return false; +} + +/** + * row_remove_request() - Remove given request from scheduler + * @q: requests queue + * @rq: request to remove + * + */ +static void row_remove_request(struct row_data *rd, + struct request *rq) +{ + struct row_queue *rqueue = RQ_ROWQ(rq); + + list_del_init(&(rq)->queuelist); + if (rd->pending_urgent_rq == rq) + rd->pending_urgent_rq = NULL; + else + BUG_ON(rq->cmd_flags & REQ_URGENT); + rqueue->nr_req--; + rd->nr_reqs[rq_data_dir(rq)]--; +} + +/* + * row_dispatch_insert() - move request to dispatch queue + * @rd: pointer to struct row_data + * @rq: the request to dispatch + * + * This function moves the given request to the dispatch queue + * + */ +static void row_dispatch_insert(struct row_data *rd, struct request *rq) +{ + struct row_queue *rqueue = RQ_ROWQ(rq); + + row_remove_request(rd, rq); + elv_dispatch_sort(rd->dispatch_queue, rq); + if (rq->cmd_flags & REQ_URGENT) { + WARN_ON(rd->urgent_in_flight); + rd->urgent_in_flight = true; + } + rqueue->nr_dispatched++; + row_clear_rowq_unserved(rd, rqueue->prio); + row_log_rowq(rd, rqueue->prio, + " Dispatched request %p nr_disp = %d", rq, + rqueue->nr_dispatched); + if (rqueue->prio < ROWQ_REG_PRIO_IDX) { + rd->last_served_ioprio_class = IOPRIO_CLASS_RT; + if (row_regular_req_pending(rd)) + rd->reg_prio_starvation.starvation_counter++; + if (row_low_req_pending(rd)) + rd->low_prio_starvation.starvation_counter++; + } else if (rqueue->prio < ROWQ_LOW_PRIO_IDX) { + rd->last_served_ioprio_class = IOPRIO_CLASS_BE; + rd->reg_prio_starvation.starvation_counter = 0; + if (row_low_req_pending(rd)) + rd->low_prio_starvation.starvation_counter++; + } else { + rd->last_served_ioprio_class = IOPRIO_CLASS_IDLE; + rd->low_prio_starvation.starvation_counter = 0; + } +} + +/* + * row_get_ioprio_class_to_serve() - Return the next I/O priority + * class to dispatch requests from + * @rd: pointer to struct row_data + * @force: flag indicating if forced dispatch + * + * This function returns the next I/O priority class to serve + * {IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE}. + * If there are no more requests in scheduler or if we're idling on some queue + * IOPRIO_CLASS_NONE will be returned. + * If idling is scheduled on a lower priority queue than the one that needs + * to be served, it will be canceled. + * + */ +static int row_get_ioprio_class_to_serve(struct row_data *rd, int force) +{ + int i; + int ret = IOPRIO_CLASS_NONE; + + if (!rd->nr_reqs[READ] && !rd->nr_reqs[WRITE]) { + row_log(rd->dispatch_queue, "No more requests in scheduler"); + goto check_idling; + } + + /* First, go over the high priority queues */ + for (i = 0; i < ROWQ_REG_PRIO_IDX; i++) { + if (!list_empty(&rd->row_queues[i].fifo)) { + if (hrtimer_active(&rd->rd_idle_data.hr_timer)) { + if (hrtimer_try_to_cancel( + &rd->rd_idle_data.hr_timer) >= 0) { + row_log(rd->dispatch_queue, + "Canceling delayed work on %d. RT pending", + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = + ROWQ_MAX_PRIO; + } + } + + if (row_regular_req_pending(rd) && + (rd->reg_prio_starvation.starvation_counter >= + rd->reg_prio_starvation.starvation_limit)) + ret = IOPRIO_CLASS_BE; + else if (row_low_req_pending(rd) && + (rd->low_prio_starvation.starvation_counter >= + rd->low_prio_starvation.starvation_limit)) + ret = IOPRIO_CLASS_IDLE; + else + ret = IOPRIO_CLASS_RT; + + goto done; + } + } + + /* + * At the moment idling is implemented only for READ queues. + * If enabled on WRITE, this needs updating + */ + if (hrtimer_active(&rd->rd_idle_data.hr_timer)) { + row_log(rd->dispatch_queue, "Delayed work pending. Exiting"); + goto done; + } +check_idling: + /* Check for (high priority) idling and enable if needed */ + for (i = 0; i < ROWQ_REG_PRIO_IDX && !force; i++) { + if (rd->row_queues[i].idle_data.begin_idling && + row_queues_def[i].idling_enabled) + goto initiate_idling; + } + + /* Regular priority queues */ + for (i = ROWQ_REG_PRIO_IDX; i < ROWQ_LOW_PRIO_IDX; i++) { + if (list_empty(&rd->row_queues[i].fifo)) { + /* We can idle only if this is not a forced dispatch */ + if (rd->row_queues[i].idle_data.begin_idling && + !force && row_queues_def[i].idling_enabled) + goto initiate_idling; + } else { + if (row_low_req_pending(rd) && + (rd->low_prio_starvation.starvation_counter >= + rd->low_prio_starvation.starvation_limit)) + ret = IOPRIO_CLASS_IDLE; + else + ret = IOPRIO_CLASS_BE; + goto done; + } + } + + if (rd->nr_reqs[READ] || rd->nr_reqs[WRITE]) + ret = IOPRIO_CLASS_IDLE; + goto done; + +initiate_idling: + hrtimer_start(&rd->rd_idle_data.hr_timer, + ktime_set(0, rd->rd_idle_data.idle_time_ms * NSEC_PER_MSEC), + HRTIMER_MODE_REL); + + rd->rd_idle_data.idling_queue_idx = i; + row_log_rowq(rd, i, "Scheduled delayed work on %d. exiting", i); + +done: + return ret; +} + +static void row_restart_cycle(struct row_data *rd, + int start_idx, int end_idx) +{ + int i; + + row_dump_queues_stat(rd); + for (i = start_idx; i < end_idx; i++) { + if (rd->row_queues[i].nr_dispatched < + rd->row_queues[i].disp_quantum) + row_mark_rowq_unserved(rd, i); + rd->row_queues[i].nr_dispatched = 0; + } + row_log(rd->dispatch_queue, "Restarting cycle for class @ %d-%d", + start_idx, end_idx); +} + +/* + * row_get_next_queue() - selects the next queue to dispatch from + * @q: requests queue + * @rd: pointer to struct row_data + * @start_idx/end_idx: indexes in the row_queues array to select a queue + * from. + * + * Return index of the queues to dispatch from. Error code if fails. + * + */ +static int row_get_next_queue(struct request_queue *q, struct row_data *rd, + int start_idx, int end_idx) +{ + int i = start_idx; + bool restart = true; + int ret = -EIO; + + do { + if (list_empty(&rd->row_queues[i].fifo) || + rd->row_queues[i].nr_dispatched >= + rd->row_queues[i].disp_quantum) { + i++; + if (i == end_idx && restart) { + /* Restart cycle for this priority class */ + row_restart_cycle(rd, start_idx, end_idx); + i = start_idx; + restart = false; + } + } else { + ret = i; + break; + } + } while (i < end_idx); + + return ret; +} + +/* + * row_dispatch_requests() - selects the next request to dispatch + * @q: requests queue + * @force: flag indicating if forced dispatch + * + * Return 0 if no requests were moved to the dispatch queue. + * 1 otherwise + * + */ +static int row_dispatch_requests(struct request_queue *q, int force) +{ + struct row_data *rd = (struct row_data *)q->elevator->elevator_data; + int ret = 0, currq, ioprio_class_to_serve, start_idx, end_idx; + + if (force && hrtimer_active(&rd->rd_idle_data.hr_timer)) { + if (hrtimer_try_to_cancel(&rd->rd_idle_data.hr_timer) >= 0) { + row_log(rd->dispatch_queue, + "Canceled delayed work on %d - forced dispatch", + rd->rd_idle_data.idling_queue_idx); + rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + } + } + + if (rd->pending_urgent_rq) { + row_log(rd->dispatch_queue, "dispatching urgent request"); + row_dispatch_insert(rd, rd->pending_urgent_rq); + ret = 1; + goto done; + } + + ioprio_class_to_serve = row_get_ioprio_class_to_serve(rd, force); + row_log(rd->dispatch_queue, "Dispatching from %d priority class", + ioprio_class_to_serve); + + switch (ioprio_class_to_serve) { + case IOPRIO_CLASS_NONE: + rd->last_served_ioprio_class = IOPRIO_CLASS_NONE; + goto done; + case IOPRIO_CLASS_RT: + start_idx = ROWQ_HIGH_PRIO_IDX; + end_idx = ROWQ_REG_PRIO_IDX; + break; + case IOPRIO_CLASS_BE: + start_idx = ROWQ_REG_PRIO_IDX; + end_idx = ROWQ_LOW_PRIO_IDX; + break; + case IOPRIO_CLASS_IDLE: + start_idx = ROWQ_LOW_PRIO_IDX; + end_idx = ROWQ_MAX_PRIO; + break; + default: + pr_err("%s(): Invalid I/O priority class", __func__); + goto done; + } + + currq = row_get_next_queue(q, rd, start_idx, end_idx); + + /* Dispatch */ + if (currq >= 0) { + row_dispatch_insert(rd, + rq_entry_fifo(rd->row_queues[currq].fifo.next)); + ret = 1; + } +done: + return ret; +} + +/* + * row_init_queue() - Init scheduler data structures + * @q: requests queue + * + * Return pointer to struct row_data to be saved in elevator for + * this dispatch queue + * + */ +static void *row_init_queue(struct request_queue *q) +{ + + struct row_data *rdata; + int i; + + rdata = kmalloc_node(sizeof(*rdata), + GFP_KERNEL | __GFP_ZERO, q->node); + if (!rdata) + return NULL; + + memset(rdata, 0, sizeof(*rdata)); + for (i = 0; i < ROWQ_MAX_PRIO; i++) { + INIT_LIST_HEAD(&rdata->row_queues[i].fifo); + rdata->row_queues[i].disp_quantum = row_queues_def[i].quantum; + rdata->row_queues[i].rdata = rdata; + rdata->row_queues[i].prio = i; + rdata->row_queues[i].idle_data.begin_idling = false; + rdata->row_queues[i].idle_data.last_insert_time = + ktime_set(0, 0); + } + + rdata->reg_prio_starvation.starvation_limit = + ROW_REG_STARVATION_TOLLERANCE; + rdata->low_prio_starvation.starvation_limit = + ROW_LOW_STARVATION_TOLLERANCE; + /* + * Currently idling is enabled only for READ queues. If we want to + * enable it for write queues also, note that idling frequency will + * be the same in both cases + */ + rdata->rd_idle_data.idle_time_ms = ROW_IDLE_TIME_MSEC; + rdata->rd_idle_data.freq_ms = ROW_READ_FREQ_MSEC; + hrtimer_init(&rdata->rd_idle_data.hr_timer, + CLOCK_MONOTONIC, HRTIMER_MODE_REL); + rdata->rd_idle_data.hr_timer.function = &row_idle_hrtimer_fn; + + INIT_WORK(&rdata->rd_idle_data.idle_work, kick_queue); + rdata->last_served_ioprio_class = IOPRIO_CLASS_NONE; + rdata->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + rdata->dispatch_queue = q; + + return rdata; +} + +/* + * row_exit_queue() - called on unloading the RAW scheduler + * @e: poiner to struct elevator_queue + * + */ +static void row_exit_queue(struct elevator_queue *e) +{ + struct row_data *rd = (struct row_data *)e->elevator_data; + int i; + + for (i = 0; i < ROWQ_MAX_PRIO; i++) + BUG_ON(!list_empty(&rd->row_queues[i].fifo)); + if (hrtimer_cancel(&rd->rd_idle_data.hr_timer)) + pr_err("%s(): idle timer was active!", __func__); + rd->rd_idle_data.idling_queue_idx = ROWQ_MAX_PRIO; + kfree(rd); +} + +/* + * row_merged_requests() - Called when 2 requests are merged + * @q: requests queue + * @rq: request the two requests were merged into + * @next: request that was merged + */ +static void row_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + struct row_queue *rqueue = RQ_ROWQ(next); + + list_del_init(&next->queuelist); + rqueue->nr_req--; + if (rqueue->rdata->pending_urgent_rq == next) { + pr_err("\n\nROW_WARNING: merging pending urgent!"); + rqueue->rdata->pending_urgent_rq = rq; + rq->cmd_flags |= REQ_URGENT; + WARN_ON(!(next->cmd_flags & REQ_URGENT)); + next->cmd_flags &= ~REQ_URGENT; + } + rqueue->rdata->nr_reqs[rq_data_dir(rq)]--; +} + +/* + * row_get_queue_prio() - Get queue priority for a given request + * + * This is a helping function which purpose is to determine what + * ROW queue the given request should be added to (and + * dispatched from later on) + * + */ +static enum row_queue_prio row_get_queue_prio(struct request *rq, + struct row_data *rd) +{ + const int data_dir = rq_data_dir(rq); + const bool is_sync = rq_is_sync(rq); + enum row_queue_prio q_type = ROWQ_MAX_PRIO; + int ioprio_class = IOPRIO_PRIO_CLASS(rq->elv.icq->ioc->ioprio); + + switch (ioprio_class) { + case IOPRIO_CLASS_RT: + if (data_dir == READ) + q_type = ROWQ_PRIO_HIGH_READ; + else if (is_sync) + q_type = ROWQ_PRIO_HIGH_SWRITE; + else { + pr_err("%s:%s(): got a simple write from RT_CLASS. How???", + rq->rq_disk->disk_name, __func__); + q_type = ROWQ_PRIO_REG_WRITE; + } + break; + case IOPRIO_CLASS_IDLE: + if (data_dir == READ) + q_type = ROWQ_PRIO_LOW_READ; + else if (is_sync) + q_type = ROWQ_PRIO_LOW_SWRITE; + else { + pr_err("%s:%s(): got a simple write from IDLE_CLASS. How???", + rq->rq_disk->disk_name, __func__); + q_type = ROWQ_PRIO_REG_WRITE; + } + break; + case IOPRIO_CLASS_NONE: + case IOPRIO_CLASS_BE: + default: + if (data_dir == READ) + q_type = ROWQ_PRIO_REG_READ; + else if (is_sync) + q_type = ROWQ_PRIO_REG_SWRITE; + else + q_type = ROWQ_PRIO_REG_WRITE; + break; + } + + return q_type; +} + +/* + * row_set_request() - Set ROW data structures associated with this request. + * @q: requests queue + * @rq: pointer to the request + * @gfp_mask: ignored + * + */ +static int +row_set_request(struct request_queue *q, struct request *rq, gfp_t gfp_mask) +{ + struct row_data *rd = (struct row_data *)q->elevator->elevator_data; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + rq->elv.priv[0] = + (void *)(&rd->row_queues[row_get_queue_prio(rq, rd)]); + spin_unlock_irqrestore(q->queue_lock, flags); + + return 0; +} + +/********** Helping sysfs functions/defenitions for ROW attributes ******/ +static ssize_t row_var_show(int var, char *page) +{ + return snprintf(page, 100, "%d\n", var); +} + +static ssize_t row_var_store(int *var, const char *page, size_t count) +{ + int err; + err = kstrtoul(page, 10, (unsigned long *)var); + + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct row_data *rowd = e->elevator_data; \ + int __data = __VAR; \ + return row_var_show(__data, (page)); \ +} +SHOW_FUNCTION(row_hp_read_quantum_show, + rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum); +SHOW_FUNCTION(row_rp_read_quantum_show, + rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum); +SHOW_FUNCTION(row_hp_swrite_quantum_show, + rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum); +SHOW_FUNCTION(row_rp_swrite_quantum_show, + rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum); +SHOW_FUNCTION(row_rp_write_quantum_show, + rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum); +SHOW_FUNCTION(row_lp_read_quantum_show, + rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum); +SHOW_FUNCTION(row_lp_swrite_quantum_show, + rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum); +SHOW_FUNCTION(row_rd_idle_data_show, rowd->rd_idle_data.idle_time_ms); +SHOW_FUNCTION(row_rd_idle_data_freq_show, rowd->rd_idle_data.freq_ms); +SHOW_FUNCTION(row_reg_starv_limit_show, + rowd->reg_prio_starvation.starvation_limit); +SHOW_FUNCTION(row_low_starv_limit_show, + rowd->low_prio_starvation.starvation_limit); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX) \ +static ssize_t __FUNC(struct elevator_queue *e, \ + const char *page, size_t count) \ +{ \ + struct row_data *rowd = e->elevator_data; \ + int __data; \ + int ret = row_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(row_hp_read_quantum_store, +&rowd->row_queues[ROWQ_PRIO_HIGH_READ].disp_quantum, 1, INT_MAX); +STORE_FUNCTION(row_rp_read_quantum_store, + &rowd->row_queues[ROWQ_PRIO_REG_READ].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_hp_swrite_quantum_store, + &rowd->row_queues[ROWQ_PRIO_HIGH_SWRITE].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_rp_swrite_quantum_store, + &rowd->row_queues[ROWQ_PRIO_REG_SWRITE].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_rp_write_quantum_store, + &rowd->row_queues[ROWQ_PRIO_REG_WRITE].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_lp_read_quantum_store, + &rowd->row_queues[ROWQ_PRIO_LOW_READ].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_lp_swrite_quantum_store, + &rowd->row_queues[ROWQ_PRIO_LOW_SWRITE].disp_quantum, + 1, INT_MAX); +STORE_FUNCTION(row_rd_idle_data_store, &rowd->rd_idle_data.idle_time_ms, + 1, INT_MAX); +STORE_FUNCTION(row_rd_idle_data_freq_store, &rowd->rd_idle_data.freq_ms, + 1, INT_MAX); +STORE_FUNCTION(row_reg_starv_limit_store, + &rowd->reg_prio_starvation.starvation_limit, + 1, INT_MAX); +STORE_FUNCTION(row_low_starv_limit_store, + &rowd->low_prio_starvation.starvation_limit, + 1, INT_MAX); + +#undef STORE_FUNCTION + +#define ROW_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, row_##name##_show, \ + row_##name##_store) + +static struct elv_fs_entry row_attrs[] = { + ROW_ATTR(hp_read_quantum), + ROW_ATTR(rp_read_quantum), + ROW_ATTR(hp_swrite_quantum), + ROW_ATTR(rp_swrite_quantum), + ROW_ATTR(rp_write_quantum), + ROW_ATTR(lp_read_quantum), + ROW_ATTR(lp_swrite_quantum), + ROW_ATTR(rd_idle_data), + ROW_ATTR(rd_idle_data_freq), + ROW_ATTR(reg_starv_limit), + ROW_ATTR(low_starv_limit), + __ATTR_NULL +}; + +static struct elevator_type iosched_row = { + .ops = { + .elevator_merge_req_fn = row_merged_requests, + .elevator_dispatch_fn = row_dispatch_requests, + .elevator_add_req_fn = row_add_request, + .elevator_reinsert_req_fn = row_reinsert_req, + .elevator_is_urgent_fn = row_urgent_pending, + .elevator_completed_req_fn = row_completed_req, + .elevator_former_req_fn = elv_rb_former_request, + .elevator_latter_req_fn = elv_rb_latter_request, + .elevator_set_req_fn = row_set_request, + .elevator_init_fn = row_init_queue, + .elevator_exit_fn = row_exit_queue, + }, + .icq_size = sizeof(struct io_cq), + .icq_align = __alignof__(struct io_cq), + .elevator_attrs = row_attrs, + .elevator_name = "row", + .elevator_owner = THIS_MODULE, +}; + +static int __init row_init(void) +{ + elv_register(&iosched_row); + return 0; +} + +static void __exit row_exit(void) +{ + elv_unregister(&iosched_row); +} + +module_init(row_init); +module_exit(row_exit); + +MODULE_LICENSE("GPLv2"); +MODULE_DESCRIPTION("Read Over Write IO scheduler"); diff --git a/block/sio-iosched.c b/block/sio-iosched.c new file mode 100644 index 00000000000..f774cbd94d3 --- /dev/null +++ b/block/sio-iosched.c @@ -0,0 +1,401 @@ +/* + * Simple IO scheduler + * Based on Noop, Deadline and V(R) IO schedulers. + * + * Copyright (C) 2012 Miguel Boton + * + * + * This algorithm does not do any kind of sorting, as it is aimed for + * aleatory access devices, but it does some basic merging. We try to + * keep minimum overhead to achieve low latency. + * + * Asynchronous and synchronous requests are not treated separately, but + * we relay on deadlines to ensure fairness. + * + */ +#include +#include +#include +#include +#include +#include +#include + +enum { ASYNC, SYNC }; + +/* Tunables */ +static const int sync_read_expire = HZ / 2; /* max time before a sync read is submitted. */ +static const int sync_write_expire = 2 * HZ; /* max time before a sync write is submitted. */ + +static const int async_read_expire = 4 * HZ; /* ditto for async, these limits are SOFT! */ +static const int async_write_expire = 16 * HZ; /* ditto for async, these limits are SOFT! */ + +static const int writes_starved = 2; /* max times reads can starve a write */ +static const int fifo_batch = 8; /* # of sequential requests treated as one + by the above parameters. For throughput. */ + +/* Elevator data */ +struct sio_data { + /* Request queues */ + struct list_head fifo_list[2][2]; + + /* Attributes */ + unsigned int batched; + unsigned int starved; + + /* Settings */ + int fifo_expire[2][2]; + int fifo_batch; + int writes_starved; +}; + +static void +sio_merged_requests(struct request_queue *q, struct request *rq, + struct request *next) +{ + /* + * If next expires before rq, assign its expire time to rq + * and move into next position (next will be deleted) in fifo. + */ + if (!list_empty(&rq->queuelist) && !list_empty(&next->queuelist)) { + if (time_before(rq_fifo_time(next), rq_fifo_time(rq))) { + list_move(&rq->queuelist, &next->queuelist); + rq_set_fifo_time(rq, rq_fifo_time(next)); + } + } + + /* Delete next request */ + rq_fifo_clear(next); +} + +static void +sio_add_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + /* + * Add request to the proper fifo list and set its + * expire time. + */ + rq_set_fifo_time(rq, jiffies + sd->fifo_expire[sync][data_dir]); + list_add_tail(&rq->queuelist, &sd->fifo_list[sync][data_dir]); +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38) +static int +sio_queue_empty(struct request_queue *q) +{ + struct sio_data *sd = q->elevator->elevator_data; + + /* Check if fifo lists are empty */ + return list_empty(&sd->fifo_list[SYNC][READ]) && list_empty(&sd->fifo_list[SYNC][WRITE]) && + list_empty(&sd->fifo_list[ASYNC][READ]) && list_empty(&sd->fifo_list[ASYNC][WRITE]); +} +#endif + +static struct request * +sio_expired_request(struct sio_data *sd, int sync, int data_dir) +{ + struct list_head *list = &sd->fifo_list[sync][data_dir]; + struct request *rq; + + if (list_empty(list)) + return NULL; + + /* Retrieve request */ + rq = rq_entry_fifo(list->next); + + /* Request has expired */ + if (time_after(jiffies, rq_fifo_time(rq))) + return rq; + + return NULL; +} + +static struct request * +sio_choose_expired_request(struct sio_data *sd) +{ + struct request *rq; + + /* + * Check expired requests. + * Asynchronous requests have priority over synchronous. + * Write requests have priority over read. + */ + rq = sio_expired_request(sd, ASYNC, WRITE); + if (rq) + return rq; + rq = sio_expired_request(sd, ASYNC, READ); + if (rq) + return rq; + + rq = sio_expired_request(sd, SYNC, WRITE); + if (rq) + return rq; + rq = sio_expired_request(sd, SYNC, READ); + if (rq) + return rq; + + return NULL; +} + +static struct request * +sio_choose_request(struct sio_data *sd, int data_dir) +{ + struct list_head *sync = sd->fifo_list[SYNC]; + struct list_head *async = sd->fifo_list[ASYNC]; + + /* + * Retrieve request from available fifo list. + * Synchronous requests have priority over asynchronous. + * Read requests have priority over write. + */ + if (!list_empty(&sync[data_dir])) + return rq_entry_fifo(sync[data_dir].next); + if (!list_empty(&async[data_dir])) + return rq_entry_fifo(async[data_dir].next); + + if (!list_empty(&sync[!data_dir])) + return rq_entry_fifo(sync[!data_dir].next); + if (!list_empty(&async[!data_dir])) + return rq_entry_fifo(async[!data_dir].next); + + return NULL; +} + +static inline void +sio_dispatch_request(struct sio_data *sd, struct request *rq) +{ + /* + * Remove the request from the fifo list + * and dispatch it. + */ + rq_fifo_clear(rq); + elv_dispatch_add_tail(rq->q, rq); + + sd->batched++; + + if (rq_data_dir(rq)) + sd->starved = 0; + else + sd->starved++; +} + +static int +sio_dispatch_requests(struct request_queue *q, int force) +{ + struct sio_data *sd = q->elevator->elevator_data; + struct request *rq = NULL; + int data_dir = READ; + + /* + * Retrieve any expired request after a batch of + * sequential requests. + */ + if (sd->batched > sd->fifo_batch) { + sd->batched = 0; + rq = sio_choose_expired_request(sd); + } + + /* Retrieve request */ + if (!rq) { + if (sd->starved > sd->writes_starved) + data_dir = WRITE; + + rq = sio_choose_request(sd, data_dir); + if (!rq) + return 0; + } + + /* Dispatch request */ + sio_dispatch_request(sd, rq); + + return 1; +} + +static struct request * +sio_former_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + if (rq->queuelist.prev == &sd->fifo_list[sync][data_dir]) + return NULL; + + /* Return former request */ + return list_entry(rq->queuelist.prev, struct request, queuelist); +} + +static struct request * +sio_latter_request(struct request_queue *q, struct request *rq) +{ + struct sio_data *sd = q->elevator->elevator_data; + const int sync = rq_is_sync(rq); + const int data_dir = rq_data_dir(rq); + + if (rq->queuelist.next == &sd->fifo_list[sync][data_dir]) + return NULL; + + /* Return latter request */ + return list_entry(rq->queuelist.next, struct request, queuelist); +} + +static void * +sio_init_queue(struct request_queue *q) +{ + struct sio_data *sd; + + /* Allocate structure */ + sd = kmalloc_node(sizeof(*sd), GFP_KERNEL, q->node); + if (!sd) + return NULL; + + /* Initialize fifo lists */ + INIT_LIST_HEAD(&sd->fifo_list[SYNC][READ]); + INIT_LIST_HEAD(&sd->fifo_list[SYNC][WRITE]); + INIT_LIST_HEAD(&sd->fifo_list[ASYNC][READ]); + INIT_LIST_HEAD(&sd->fifo_list[ASYNC][WRITE]); + + /* Initialize data */ + sd->batched = 0; + sd->fifo_expire[SYNC][READ] = sync_read_expire; + sd->fifo_expire[SYNC][WRITE] = sync_write_expire; + sd->fifo_expire[ASYNC][READ] = async_read_expire; + sd->fifo_expire[ASYNC][WRITE] = async_write_expire; + sd->fifo_batch = fifo_batch; + + return sd; +} + +static void +sio_exit_queue(struct elevator_queue *e) +{ + struct sio_data *sd = e->elevator_data; + + BUG_ON(!list_empty(&sd->fifo_list[SYNC][READ])); + BUG_ON(!list_empty(&sd->fifo_list[SYNC][WRITE])); + BUG_ON(!list_empty(&sd->fifo_list[ASYNC][READ])); + BUG_ON(!list_empty(&sd->fifo_list[ASYNC][WRITE])); + + /* Free structure */ + kfree(sd); +} + +/* + * sysfs code + */ + +static ssize_t +sio_var_show(int var, char *page) +{ + return sprintf(page, "%d\n", var); +} + +static ssize_t +sio_var_store(int *var, const char *page, size_t count) +{ + char *p = (char *) page; + + *var = simple_strtol(p, &p, 10); + return count; +} + +#define SHOW_FUNCTION(__FUNC, __VAR, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, char *page) \ +{ \ + struct sio_data *sd = e->elevator_data; \ + int __data = __VAR; \ + if (__CONV) \ + __data = jiffies_to_msecs(__data); \ + return sio_var_show(__data, (page)); \ +} +SHOW_FUNCTION(sio_sync_read_expire_show, sd->fifo_expire[SYNC][READ], 1); +SHOW_FUNCTION(sio_sync_write_expire_show, sd->fifo_expire[SYNC][WRITE], 1); +SHOW_FUNCTION(sio_async_read_expire_show, sd->fifo_expire[ASYNC][READ], 1); +SHOW_FUNCTION(sio_async_write_expire_show, sd->fifo_expire[ASYNC][WRITE], 1); +SHOW_FUNCTION(sio_fifo_batch_show, sd->fifo_batch, 0); +SHOW_FUNCTION(sio_writes_starved_show, sd->writes_starved, 0); +#undef SHOW_FUNCTION + +#define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV) \ +static ssize_t __FUNC(struct elevator_queue *e, const char *page, size_t count) \ +{ \ + struct sio_data *sd = e->elevator_data; \ + int __data; \ + int ret = sio_var_store(&__data, (page), count); \ + if (__data < (MIN)) \ + __data = (MIN); \ + else if (__data > (MAX)) \ + __data = (MAX); \ + if (__CONV) \ + *(__PTR) = msecs_to_jiffies(__data); \ + else \ + *(__PTR) = __data; \ + return ret; \ +} +STORE_FUNCTION(sio_sync_read_expire_store, &sd->fifo_expire[SYNC][READ], 0, INT_MAX, 1); +STORE_FUNCTION(sio_sync_write_expire_store, &sd->fifo_expire[SYNC][WRITE], 0, INT_MAX, 1); +STORE_FUNCTION(sio_async_read_expire_store, &sd->fifo_expire[ASYNC][READ], 0, INT_MAX, 1); +STORE_FUNCTION(sio_async_write_expire_store, &sd->fifo_expire[ASYNC][WRITE], 0, INT_MAX, 1); +STORE_FUNCTION(sio_fifo_batch_store, &sd->fifo_batch, 0, INT_MAX, 0); +STORE_FUNCTION(sio_writes_starved_store, &sd->writes_starved, 0, INT_MAX, 0); +#undef STORE_FUNCTION + +#define DD_ATTR(name) \ + __ATTR(name, S_IRUGO|S_IWUSR, sio_##name##_show, \ + sio_##name##_store) + +static struct elv_fs_entry sio_attrs[] = { + DD_ATTR(sync_read_expire), + DD_ATTR(sync_write_expire), + DD_ATTR(async_read_expire), + DD_ATTR(async_write_expire), + DD_ATTR(fifo_batch), + DD_ATTR(writes_starved), + __ATTR_NULL +}; + +static struct elevator_type iosched_sio = { + .ops = { + .elevator_merge_req_fn = sio_merged_requests, + .elevator_dispatch_fn = sio_dispatch_requests, + .elevator_add_req_fn = sio_add_request, +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,38) + .elevator_queue_empty_fn = sio_queue_empty, +#endif + .elevator_former_req_fn = sio_former_request, + .elevator_latter_req_fn = sio_latter_request, + .elevator_init_fn = sio_init_queue, + .elevator_exit_fn = sio_exit_queue, + }, + + .elevator_attrs = sio_attrs, + .elevator_name = "sio", + .elevator_owner = THIS_MODULE, +}; + +static int __init sio_init(void) +{ + /* Register elevator */ + elv_register(&iosched_sio); + + return 0; +} + +static void __exit sio_exit(void) +{ + /* Unregister elevator */ + elv_unregister(&iosched_sio); +} + +module_init(sio_init); +module_exit(sio_exit); + +MODULE_AUTHOR("Miguel Boton"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Simple IO scheduler"); +MODULE_VERSION("0.2"); + diff --git a/crypto/Kconfig b/crypto/Kconfig index 8e84225c096..da3c05976c2 100644 --- a/crypto/Kconfig +++ b/crypto/Kconfig @@ -423,6 +423,15 @@ config CRYPTO_SHA1_SSSE3 using Supplemental SSE3 (SSSE3) instructions or Advanced Vector Extensions (AVX), when available. +config CRYPTO_SHA1_ARM + tristate "SHA1 digest algorithm (ARM-asm)" + depends on ARM + select CRYPTO_SHA1 + select CRYPTO_HASH + help + SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2) implemented + using optimized ARM assembler. + config CRYPTO_SHA256 tristate "SHA224 and SHA256 digest algorithm" select CRYPTO_HASH @@ -577,6 +586,30 @@ config CRYPTO_AES_NI_INTEL ECB, CBC, LRW, PCBC, XTS. The 64 bit version has additional acceleration for CTR. +config CRYPTO_AES_ARM + tristate "AES cipher algorithms (ARM-asm)" + depends on ARM + select CRYPTO_ALGAPI + select CRYPTO_AES + help + Use optimized AES assembler routines for ARM platforms. + + AES cipher algorithms (FIPS-197). AES uses the Rijndael + algorithm. + + Rijndael appears to be consistently a very good performer in + both hardware and software across a wide range of computing + environments regardless of its use in feedback or non-feedback + modes. Its key setup time is excellent, and its key agility is + good. Rijndael's very low memory requirements make it very well + suited for restricted-space environments, in which it also + demonstrates excellent performance. Rijndael's operations are + among the easiest to defend against power and timing attacks. + + The AES specifies three key sizes: 128, 192 and 256 bits + + See for more information. + config CRYPTO_ANUBIS tristate "Anubis cipher algorithm" select CRYPTO_ALGAPI @@ -943,6 +976,31 @@ config CRYPTO_LZO help This is the LZO algorithm. +config CRYPTO_842 + tristate "842 compression algorithm" + depends on CRYPTO_DEV_NX_COMPRESS + # 842 uses lzo if the hardware becomes unavailable + select LZO_COMPRESS + select LZO_DECOMPRESS + help + This is the 842 algorithm. + +config CRYPTO_LZ4 + tristate "LZ4 compression algorithm" + select CRYPTO_ALGAPI + select LZ4_COMPRESS + select LZ4_DECOMPRESS + help + This is the LZ4 algorithm. + +config CRYPTO_LZ4HC + tristate "LZ4HC compression algorithm" + select CRYPTO_ALGAPI + select LZ4HC_COMPRESS + select LZ4_DECOMPRESS + help + This is the LZ4 high compression mode algorithm. + comment "Random Number Generation" config CRYPTO_ANSI_CPRNG diff --git a/crypto/Makefile b/crypto/Makefile index 30f33d67533..7d567d02086 100644 --- a/crypto/Makefile +++ b/crypto/Makefile @@ -82,6 +82,9 @@ obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o obj-$(CONFIG_CRYPTO_LZO) += lzo.o +obj-$(CONFIG_CRYPTO_LZ4) += lz4.o +obj-$(CONFIG_CRYPTO_LZ4HC) += lz4hc.o +obj-$(CONFIG_CRYPTO_842) += 842.o obj-$(CONFIG_CRYPTO_RNG2) += rng.o obj-$(CONFIG_CRYPTO_RNG2) += krng.o obj-$(CONFIG_CRYPTO_ANSI_CPRNG) += ansi_cprng.o diff --git a/crypto/lz4.c b/crypto/lz4.c new file mode 100644 index 00000000000..4586dd15b0d --- /dev/null +++ b/crypto/lz4.c @@ -0,0 +1,106 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2013 Chanho Min + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include +#include +#include +#include +#include + +struct lz4_ctx { + void *lz4_comp_mem; +}; + +static int lz4_init(struct crypto_tfm *tfm) +{ + struct lz4_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->lz4_comp_mem = vmalloc(LZ4_MEM_COMPRESS); + if (!ctx->lz4_comp_mem) + return -ENOMEM; + + return 0; +} + +static void lz4_exit(struct crypto_tfm *tfm) +{ + struct lz4_ctx *ctx = crypto_tfm_ctx(tfm); + vfree(ctx->lz4_comp_mem); +} + +static int lz4_compress_crypto(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) +{ + struct lz4_ctx *ctx = crypto_tfm_ctx(tfm); + size_t tmp_len = *dlen; + int err; + + err = lz4_compress(src, slen, dst, &tmp_len, ctx->lz4_comp_mem); + + if (err < 0) + return -EINVAL; + + *dlen = tmp_len; + return 0; +} + +static int lz4_decompress_crypto(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) +{ + int err; + size_t tmp_len = *dlen; + size_t __slen = slen; + + err = lz4_decompress(src, &__slen, dst, tmp_len); + if (err < 0) + return -EINVAL; + + *dlen = tmp_len; + return err; +} + +static struct crypto_alg alg_lz4 = { + .cra_name = "lz4", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_ctxsize = sizeof(struct lz4_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg_lz4.cra_list), + .cra_init = lz4_init, + .cra_exit = lz4_exit, + .cra_u = { .compress = { + .coa_compress = lz4_compress_crypto, + .coa_decompress = lz4_decompress_crypto } } +}; + +static int __init lz4_mod_init(void) +{ + return crypto_register_alg(&alg_lz4); +} + +static void __exit lz4_mod_fini(void) +{ + crypto_unregister_alg(&alg_lz4); +} + +module_init(lz4_mod_init); +module_exit(lz4_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LZ4 Compression Algorithm"); diff --git a/crypto/lz4hc.c b/crypto/lz4hc.c new file mode 100644 index 00000000000..151ba31d34e --- /dev/null +++ b/crypto/lz4hc.c @@ -0,0 +1,106 @@ +/* + * Cryptographic API. + * + * Copyright (c) 2013 Chanho Min + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include +#include +#include +#include +#include + +struct lz4hc_ctx { + void *lz4hc_comp_mem; +}; + +static int lz4hc_init(struct crypto_tfm *tfm) +{ + struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->lz4hc_comp_mem = vmalloc(LZ4HC_MEM_COMPRESS); + if (!ctx->lz4hc_comp_mem) + return -ENOMEM; + + return 0; +} + +static void lz4hc_exit(struct crypto_tfm *tfm) +{ + struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm); + + vfree(ctx->lz4hc_comp_mem); +} + +static int lz4hc_compress_crypto(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) +{ + struct lz4hc_ctx *ctx = crypto_tfm_ctx(tfm); + size_t tmp_len = *dlen; + int err; + + err = lz4hc_compress(src, slen, dst, &tmp_len, ctx->lz4hc_comp_mem); + + if (err < 0) + return -EINVAL; + + *dlen = tmp_len; + return 0; +} + +static int lz4hc_decompress_crypto(struct crypto_tfm *tfm, const u8 *src, + unsigned int slen, u8 *dst, unsigned int *dlen) +{ + int err; + size_t tmp_len = *dlen; + size_t __slen = slen; + + err = lz4_decompress(src, &__slen, dst, tmp_len); + if (err < 0) + return -EINVAL; + + *dlen = tmp_len; + return err; +} + +static struct crypto_alg alg_lz4hc = { + .cra_name = "lz4hc", + .cra_flags = CRYPTO_ALG_TYPE_COMPRESS, + .cra_ctxsize = sizeof(struct lz4hc_ctx), + .cra_module = THIS_MODULE, + .cra_list = LIST_HEAD_INIT(alg_lz4hc.cra_list), + .cra_init = lz4hc_init, + .cra_exit = lz4hc_exit, + .cra_u = { .compress = { + .coa_compress = lz4hc_compress_crypto, + .coa_decompress = lz4hc_decompress_crypto } } +}; + +static int __init lz4hc_mod_init(void) +{ + return crypto_register_alg(&alg_lz4hc); +} + +static void __exit lz4hc_mod_fini(void) +{ + crypto_unregister_alg(&alg_lz4hc); +} + +module_init(lz4hc_mod_init); +module_exit(lz4hc_mod_fini); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("LZ4HC Compression Algorithm"); diff --git a/drivers/base/sync.c b/drivers/base/sync.c index 2e359968919..95819987fbe 100644 --- a/drivers/base/sync.c +++ b/drivers/base/sync.c @@ -79,27 +79,27 @@ static void sync_timeline_free(struct kref *kref) container_of(kref, struct sync_timeline, kref); unsigned long flags; - if (obj->ops->release_obj) - obj->ops->release_obj(obj); - spin_lock_irqsave(&sync_timeline_list_lock, flags); list_del(&obj->sync_timeline_list); spin_unlock_irqrestore(&sync_timeline_list_lock, flags); + if (obj->ops->release_obj) + obj->ops->release_obj(obj); + kfree(obj); } void sync_timeline_destroy(struct sync_timeline *obj) { obj->destroyed = true; + smp_wmb(); /* - * If this is not the last reference, signal any children - * that their parent is going away. + * signal any children that their parent is going away. */ + sync_timeline_signal(obj); - if (!kref_put(&obj->kref, sync_timeline_free)) - sync_timeline_signal(obj); + kref_put(&obj->kref, sync_timeline_free); } EXPORT_SYMBOL(sync_timeline_destroy); diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 0b3ffef43cb..0118bb99d93 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -28,6 +28,15 @@ config DEVKMEM kind of kernel debugging operations. When in doubt, say "N". +config FRANDOM + bool "/dev/frandom device support" + default y + help + Say Y here if you want to support the /dev/frandom device. Frandom + is a Linux kernel random number generator, which is 10-50 times faster + than what you get from Linux' built-in /dev/urandom. + When in doubt, say "N" + config STALDRV bool "Stallion multiport serial support" depends on SERIAL_NONSTANDARD diff --git a/drivers/char/frandom.c b/drivers/char/frandom.c new file mode 100644 index 00000000000..d108cccb7c1 --- /dev/null +++ b/drivers/char/frandom.c @@ -0,0 +1,421 @@ +/* +** frandom.c +** Fast pseudo-random generator +** +** (c) Copyright 2003-2011 Eli Billauer +** http://www.billauer.co.il +** +** 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 +#include +#include +#include + +#define INTERNAL_SEED 0 +#define EXTERNAL_SEED 1 + +#define FRANDOM_MAJOR 235 +#define FRANDOM_MINOR 11 +#define ERANDOM_MINOR 12 + +static struct file_operations frandom_fops; /* Values assigned below */ + +static int erandom_seeded = 0; /* Internal flag */ + +static int frandom_major = FRANDOM_MAJOR; +static int frandom_minor = FRANDOM_MINOR; +static int erandom_minor = ERANDOM_MINOR; +static int frandom_bufsize = 256; +static int frandom_chunklimit = 0; /* =0 means unlimited */ + +static struct cdev frandom_cdev; +static struct cdev erandom_cdev; +static struct class *frandom_class; +struct device *frandom_device; +struct device *erandom_device; + +MODULE_DESCRIPTION("Fast pseudo-random number generator"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Eli Billauer"); +module_param(frandom_major, int, 0); +module_param(frandom_minor, int, 0); +module_param(erandom_minor, int, 0); +module_param(frandom_bufsize, int, 0); +module_param(frandom_chunklimit, int, 0); + +MODULE_PARM_DESC(frandom_major,"Major number of /dev/frandom and /dev/erandom"); +MODULE_PARM_DESC(frandom_minor,"Minor number of /dev/frandom"); +MODULE_PARM_DESC(erandom_minor,"Minor number of /dev/erandom"); +MODULE_PARM_DESC(frandom_bufsize,"Internal buffer size in bytes. Default is 256. Must be >= 256"); +MODULE_PARM_DESC(frandom_chunklimit,"Limit for read() blocks size. 0 (default) is unlimited, otherwise must be >= 256"); + +struct frandom_state +{ + struct semaphore sem; /* Semaphore on the state structure */ + + u8 S[256]; /* The state array */ + u8 i; + u8 j; + + char *buf; +}; + +static struct frandom_state *erandom_state; + +static inline void swap_byte(u8 *a, u8 *b) +{ + u8 swapByte; + + swapByte = *a; + *a = *b; + *b = swapByte; +} + +static void init_rand_state(struct frandom_state *state, int seedflag); + +void erandom_get_random_bytes(char *buf, size_t count) +{ + struct frandom_state *state = erandom_state; + int k; + + unsigned int i; + unsigned int j; + u8 *S; + + /* If we fail to get the semaphore, we revert to external random data. + Since semaphore blocking is expected to be very rare, and interrupts + during these rare and very short periods of time even less frequent, + we take the better-safe-than-sorry approach, and fill the buffer + some expensive random data, in case the caller wasn't aware of this + possibility, and expects random data anyhow. + */ + + if (down_interruptible(&state->sem)) { + get_random_bytes(buf, count); + return; + } + + /* We seed erandom as late as possible, hoping that the kernel's main + RNG is already restored in the boot sequence (not critical, but + better. + */ + + if (!erandom_seeded) { + erandom_seeded = 1; + init_rand_state(state, EXTERNAL_SEED); + printk(KERN_INFO "frandom: Seeded global generator now (used by erandom)\n"); + } + + i = state->i; + j = state->j; + S = state->S; + + for (k=0; ki = i; + state->j = j; + + up(&state->sem); +} + +static void init_rand_state(struct frandom_state *state, int seedflag) +{ + unsigned int i, j, k; + u8 *S; + u8 *seed = state->buf; + + if (seedflag == INTERNAL_SEED) + erandom_get_random_bytes(seed, 256); + else + get_random_bytes(seed, 256); + + S = state->S; + for (i=0; i<256; i++) + *S++=i; + + j=0; + S = state->S; + + for (i=0; i<256; i++) { + j = (j + S[i] + *seed++) & 0xff; + swap_byte(&S[i], &S[j]); + } + + /* It's considered good practice to discard the first 256 bytes + generated. So we do it: + */ + + i=0; j=0; + for (k=0; k<256; k++) { + i = (i + 1) & 0xff; + j = (j + S[i]) & 0xff; + swap_byte(&S[i], &S[j]); + } + + state->i = i; /* Save state */ + state->j = j; +} + +static int frandom_open(struct inode *inode, struct file *filp) +{ + + struct frandom_state *state; + + int num = iminor(inode); + + /* This should never happen, now when the minors are regsitered + * explicitly + */ + if ((num != frandom_minor) && (num != erandom_minor)) return -ENODEV; + + state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); + if (!state) + return -ENOMEM; + + state->buf = kmalloc(frandom_bufsize, GFP_KERNEL); + if (!state->buf) { + kfree(state); + return -ENOMEM; + } + + sema_init(&state->sem, 1); /* Init semaphore as a mutex */ + + if (num == frandom_minor) + init_rand_state(state, EXTERNAL_SEED); + else + init_rand_state(state, INTERNAL_SEED); + + filp->private_data = state; + + return 0; /* Success */ +} + +static int frandom_release(struct inode *inode, struct file *filp) +{ + + struct frandom_state *state = filp->private_data; + + kfree(state->buf); + kfree(state); + + return 0; +} + +static ssize_t frandom_read(struct file *filp, char *buf, size_t count, + loff_t *f_pos) +{ + struct frandom_state *state = filp->private_data; + ssize_t ret; + int dobytes, k; + char *localbuf; + + unsigned int i; + unsigned int j; + u8 *S; + + if (down_interruptible(&state->sem)) + return -ERESTARTSYS; + + if ((frandom_chunklimit > 0) && (count > frandom_chunklimit)) + count = frandom_chunklimit; + + ret = count; /* It's either everything or an error... */ + + i = state->i; + j = state->j; + S = state->S; + + while (count) { + if (count > frandom_bufsize) + dobytes = frandom_bufsize; + else + dobytes = count; + + localbuf = state->buf; + + for (k=0; kbuf, dobytes)) { + ret = -EFAULT; + goto out; + } + + buf += dobytes; + count -= dobytes; + } + + out: + state->i = i; + state->j = j; + + up(&state->sem); + return ret; +} + +static struct file_operations frandom_fops = { + read: frandom_read, + open: frandom_open, + release: frandom_release, +}; + +static void frandom_cleanup_module(void) { + unregister_chrdev_region(MKDEV(frandom_major, erandom_minor), 1); + cdev_del(&erandom_cdev); + device_destroy(frandom_class, MKDEV(frandom_major, erandom_minor)); + + unregister_chrdev_region(MKDEV(frandom_major, frandom_minor), 1); + cdev_del(&frandom_cdev); + device_destroy(frandom_class, MKDEV(frandom_major, frandom_minor)); + class_destroy(frandom_class); + + kfree(erandom_state->buf); + kfree(erandom_state); +} + + +static int frandom_init_module(void) +{ + int result; + + /* The buffer size MUST be at least 256 bytes, because we assume that + minimal length in init_rand_state(). + */ + if (frandom_bufsize < 256) { + printk(KERN_ERR "frandom: Refused to load because frandom_bufsize=%d < 256\n",frandom_bufsize); + return -EINVAL; + } + if ((frandom_chunklimit != 0) && (frandom_chunklimit < 256)) { + printk(KERN_ERR "frandom: Refused to load because frandom_chunklimit=%d < 256 and != 0\n",frandom_chunklimit); + return -EINVAL; + } + + erandom_state = kmalloc(sizeof(struct frandom_state), GFP_KERNEL); + if (!erandom_state) + return -ENOMEM; + + /* This specific buffer is only used for seeding, so we need + 256 bytes exactly */ + erandom_state->buf = kmalloc(256, GFP_KERNEL); + if (!erandom_state->buf) { + kfree(erandom_state); + return -ENOMEM; + } + + sema_init(&erandom_state->sem, 1); /* Init semaphore as a mutex */ + + erandom_seeded = 0; + + frandom_class = class_create(THIS_MODULE, "fastrng"); + if (IS_ERR(frandom_class)) { + result = PTR_ERR(frandom_class); + printk(KERN_WARNING "frandom: Failed to register class fastrng\n"); + goto error0; + } + + /* + * Register your major, and accept a dynamic number. This is the + * first thing to do, in order to avoid releasing other module's + * fops in frandom_cleanup_module() + */ + + cdev_init(&frandom_cdev, &frandom_fops); + frandom_cdev.owner = THIS_MODULE; + result = cdev_add(&frandom_cdev, MKDEV(frandom_major, frandom_minor), 1); + if (result) { + printk(KERN_WARNING "frandom: Failed to add cdev for /dev/frandom\n"); + goto error1; + } + + result = register_chrdev_region(MKDEV(frandom_major, frandom_minor), 1, "/dev/frandom"); + if (result < 0) { + printk(KERN_WARNING "frandom: can't get major/minor %d/%d\n", frandom_major, frandom_minor); + goto error2; + } + + frandom_device = device_create(frandom_class, NULL, MKDEV(frandom_major, frandom_minor), NULL, "frandom"); + + if (IS_ERR(frandom_device)) { + printk(KERN_WARNING "frandom: Failed to create frandom device\n"); + goto error3; + } + + cdev_init(&erandom_cdev, &frandom_fops); + erandom_cdev.owner = THIS_MODULE; + result = cdev_add(&erandom_cdev, MKDEV(frandom_major, erandom_minor), 1); + if (result) { + printk(KERN_WARNING "frandom: Failed to add cdev for /dev/erandom\n"); + goto error4; + } + + result = register_chrdev_region(MKDEV(frandom_major, erandom_minor), 1, "/dev/erandom"); + if (result < 0) { + printk(KERN_WARNING "frandom: can't get major/minor %d/%d\n", frandom_major, erandom_minor); + goto error5; + } + + erandom_device = device_create(frandom_class, NULL, MKDEV(frandom_major, erandom_minor), NULL, "erandom"); + + if (IS_ERR(erandom_device)) { + printk(KERN_WARNING "frandom: Failed to create erandom device\n"); + goto error6; + } + return 0; /* succeed */ + + error6: + unregister_chrdev_region(MKDEV(frandom_major, erandom_minor), 1); + error5: + cdev_del(&erandom_cdev); + error4: + device_destroy(frandom_class, MKDEV(frandom_major, frandom_minor)); + error3: + unregister_chrdev_region(MKDEV(frandom_major, frandom_minor), 1); + error2: + cdev_del(&frandom_cdev); + error1: + class_destroy(frandom_class); + error0: + kfree(erandom_state->buf); + kfree(erandom_state); + + return result; +} + +module_init(frandom_init_module); +module_exit(frandom_cleanup_module); + +EXPORT_SYMBOL(erandom_get_random_bytes); + +MODULE_AUTHOR("Eli Billauer "); +MODULE_DESCRIPTION("'char_random_frandom' - A fast random generator for " +"general usage"); +MODULE_LICENSE("GPL"); + diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c index 20e716efb21..684d283c707 100644 --- a/drivers/char/msm_rotator.c +++ b/drivers/char/msm_rotator.c @@ -1508,6 +1508,7 @@ static int msm_rotator_rotate_prepare( fput_light(srcp0_file, ps0_need); else put_img(srcp0_file, srcp0_ihdl, ROTATOR_SRC_DOMAIN, 0); + msm_rotator_signal_timeline_done(s); dev_dbg(msm_rotator_dev->device, "%s() returning rc = %d\n", __func__, rc); mutex_unlock(&msm_rotator_dev->rotator_lock); diff --git a/drivers/char/random.c b/drivers/char/random.c index 4ec04a75473..4d8458f1319 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -125,21 +125,26 @@ * The current exported interfaces for gathering environmental noise * from the devices are: * + * void add_device_randomness(const void *buf, unsigned int size); * void add_input_randomness(unsigned int type, unsigned int code, * unsigned int value); - * void add_interrupt_randomness(int irq); + * void add_interrupt_randomness(int irq, int irq_flags); * void add_disk_randomness(struct gendisk *disk); * + * add_device_randomness() is for adding data to the random pool that + * is likely to differ between two devices (or possibly even per boot). + * This would be things like MAC addresses or serial numbers, or the + * read-out of the RTC. This does *not* add any actual entropy to the + * pool, but it initializes the pool to different values for devices + * that might otherwise be identical and have very little entropy + * available to them (particularly common in the embedded world). + * * add_input_randomness() uses the input layer interrupt timing, as well as * the event type information from the hardware. * - * add_interrupt_randomness() uses the inter-interrupt timing as random - * inputs to the entropy pool. Note that not all interrupts are good - * sources of randomness! For example, the timer interrupts is not a - * good choice, because the periodicity of the interrupts is too - * regular, and hence predictable to an attacker. Network Interface - * Controller interrupts are a better measure, since the timing of the - * NIC interrupts are more unpredictable. + * add_interrupt_randomness() uses the interrupt timing as random + * inputs to the entropy pool. Using the cycle counters and the irq source + * as inputs, it feeds the randomness roughly once a second. * * add_disk_randomness() uses what amounts to the seek time of block * layer request events, on a per-disk_devt basis, as input to the @@ -248,6 +253,8 @@ #include #include #include +#include +#include #ifdef CONFIG_GENERIC_HARDIRQS # include @@ -256,6 +263,7 @@ #include #include #include +#include #include /* @@ -420,8 +428,10 @@ struct entropy_store { /* read-write data: */ spinlock_t lock; unsigned add_ptr; + unsigned input_rotate; int entropy_count; - int input_rotate; + int entropy_total; + unsigned int initialized:1; __u8 last_data[EXTRACT_SIZE]; }; @@ -454,6 +464,10 @@ static struct entropy_store nonblocking_pool = { .pool = nonblocking_pool_data }; +static __u32 const twist_table[8] = { + 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, + 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; + /* * This function adds bytes into the entropy "pool". It does not * update the entropy estimate. The caller should call @@ -464,29 +478,24 @@ static struct entropy_store nonblocking_pool = { * it's cheap to do so and helps slightly in the expected case where * the entropy is concentrated in the low-order bits. */ -static void mix_pool_bytes_extract(struct entropy_store *r, const void *in, - int nbytes, __u8 out[64]) +static void __mix_pool_bytes(struct entropy_store *r, const void *in, + int nbytes, __u8 out[64]) { - static __u32 const twist_table[8] = { - 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, - 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; unsigned long i, j, tap1, tap2, tap3, tap4, tap5; int input_rotate; int wordmask = r->poolinfo->poolwords - 1; const char *bytes = in; __u32 w; - unsigned long flags; - /* Taps are constant, so we can load them without holding r->lock. */ tap1 = r->poolinfo->tap1; tap2 = r->poolinfo->tap2; tap3 = r->poolinfo->tap3; tap4 = r->poolinfo->tap4; tap5 = r->poolinfo->tap5; - spin_lock_irqsave(&r->lock, flags); - input_rotate = r->input_rotate; - i = r->add_ptr; + smp_rmb(); + input_rotate = ACCESS_ONCE(r->input_rotate); + i = ACCESS_ONCE(r->add_ptr); /* mix one byte at a time to simplify size handling and churn faster */ while (nbytes--) { @@ -513,19 +522,53 @@ static void mix_pool_bytes_extract(struct entropy_store *r, const void *in, input_rotate += i ? 7 : 14; } - r->input_rotate = input_rotate; - r->add_ptr = i; + ACCESS_ONCE(r->input_rotate) = input_rotate; + ACCESS_ONCE(r->add_ptr) = i; + smp_wmb(); if (out) for (j = 0; j < 16; j++) ((__u32 *)out)[j] = r->pool[(i - j) & wordmask]; +} +static void mix_pool_bytes(struct entropy_store *r, const void *in, + int nbytes, __u8 out[64]) +{ + unsigned long flags; + + spin_lock_irqsave(&r->lock, flags); + __mix_pool_bytes(r, in, nbytes, out); spin_unlock_irqrestore(&r->lock, flags); } -static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) +struct fast_pool { + __u32 pool[4]; + unsigned long last; + unsigned short count; + unsigned char rotate; + unsigned char last_timer_intr; +}; + +/* + * This is a fast mixing routine used by the interrupt randomness + * collector. It's hardcoded for an 128 bit pool and assumes that any + * locks that might be needed are taken by the caller. + */ +static void fast_mix(struct fast_pool *f, const void *in, int nbytes) { - mix_pool_bytes_extract(r, in, bytes, NULL); + const char *bytes = in; + __u32 w; + unsigned i = f->count; + unsigned input_rotate = f->rotate; + + while (nbytes--) { + w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^ + f->pool[(i + 1) & 3]; + f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7]; + input_rotate += (i++ & 3) ? 7 : 14; + } + f->count = i; + f->rotate = input_rotate; } /* @@ -533,30 +576,34 @@ static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) */ static void credit_entropy_bits(struct entropy_store *r, int nbits) { - unsigned long flags; - int entropy_count; + int entropy_count, orig; if (!nbits) return; - spin_lock_irqsave(&r->lock, flags); - DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name); - entropy_count = r->entropy_count; +retry: + entropy_count = orig = ACCESS_ONCE(r->entropy_count); entropy_count += nbits; if (entropy_count < 0) { DEBUG_ENT("negative entropy/overflow\n"); entropy_count = 0; } else if (entropy_count > r->poolinfo->POOLBITS) entropy_count = r->poolinfo->POOLBITS; - r->entropy_count = entropy_count; + if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) + goto retry; + + if (!r->initialized && nbits > 0) { + r->entropy_total += nbits; + if (r->entropy_total > 128) + r->initialized = 1; + } /* should we wake readers? */ if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) { wake_up_interruptible(&random_read_wait); kill_fasync(&fasync, SIGIO, POLL_IN); } - spin_unlock_irqrestore(&r->lock, flags); } /********************************************************************* @@ -572,42 +619,24 @@ struct timer_rand_state { unsigned dont_count_entropy:1; }; -#ifndef CONFIG_GENERIC_HARDIRQS - -static struct timer_rand_state *irq_timer_state[NR_IRQS]; - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - return irq_timer_state[irq]; -} - -static void set_timer_rand_state(unsigned int irq, - struct timer_rand_state *state) -{ - irq_timer_state[irq] = state; -} - -#else - -static struct timer_rand_state *get_timer_rand_state(unsigned int irq) -{ - struct irq_desc *desc; - - desc = irq_to_desc(irq); - - return desc->timer_rand_state; -} - -static void set_timer_rand_state(unsigned int irq, - struct timer_rand_state *state) +/* + * Add device- or boot-specific data to the input and nonblocking + * pools to help initialize them to unique values. + * + * None of this adds any entropy, it is meant to avoid the + * problem of the nonblocking pool having similar initial state + * across largely identical devices. + */ +void add_device_randomness(const void *buf, unsigned int size) { - struct irq_desc *desc; + unsigned long time = get_cycles() ^ jiffies; - desc = irq_to_desc(irq); - - desc->timer_rand_state = state; + mix_pool_bytes(&input_pool, buf, size, NULL); + mix_pool_bytes(&input_pool, &time, sizeof(time), NULL); + mix_pool_bytes(&nonblocking_pool, buf, size, NULL); + mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL); } -#endif +EXPORT_SYMBOL(add_device_randomness); static struct timer_rand_state input_timer_state; @@ -637,13 +666,9 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) goto out; sample.jiffies = jiffies; - - /* Use arch random value, fall back to cycles */ - if (!arch_get_random_int(&sample.cycles)) - sample.cycles = get_cycles(); - + sample.cycles = get_cycles(); sample.num = num; - mix_pool_bytes(&input_pool, &sample, sizeof(sample)); + mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL); /* * Calculate number of bits of randomness we probably added. @@ -700,17 +725,48 @@ void add_input_randomness(unsigned int type, unsigned int code, } EXPORT_SYMBOL_GPL(add_input_randomness); -void add_interrupt_randomness(int irq) +static DEFINE_PER_CPU(struct fast_pool, irq_randomness); + +void add_interrupt_randomness(int irq, int irq_flags) { - struct timer_rand_state *state; + struct entropy_store *r; + struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness); + struct pt_regs *regs = get_irq_regs(); + unsigned long now = jiffies; + __u32 input[4], cycles = get_cycles(); + + input[0] = cycles ^ jiffies; + input[1] = irq; + if (regs) { + __u64 ip = instruction_pointer(regs); + input[2] = ip; + input[3] = ip >> 32; + } - state = get_timer_rand_state(irq); + fast_mix(fast_pool, input, sizeof(input)); - if (state == NULL) + if ((fast_pool->count & 1023) && + !time_after(now, fast_pool->last + HZ)) return; - DEBUG_ENT("irq event %d\n", irq); - add_timer_randomness(state, 0x100 + irq); + fast_pool->last = now; + + r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; + __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL); + /* + * If we don't have a valid cycle counter, and we see + * back-to-back timer interrupts, then skip giving credit for + * any entropy. + */ + if (cycles == 0) { + if (irq_flags & __IRQF_TIMER) { + if (fast_pool->last_timer_intr) + return; + fast_pool->last_timer_intr = 1; + } else + fast_pool->last_timer_intr = 0; + } + credit_entropy_bits(r, 1); } #ifdef CONFIG_BLOCK @@ -742,7 +798,11 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, */ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) { - __u32 tmp[OUTPUT_POOL_WORDS]; + union { + __u32 tmp[OUTPUT_POOL_WORDS]; + long hwrand[4]; + } u; + int i; if (r->pull && r->entropy_count < nbytes * 8 && r->entropy_count < r->poolinfo->POOLBITS) { @@ -753,17 +813,23 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) /* pull at least as many as BYTES as wakeup BITS */ bytes = max_t(int, bytes, random_read_wakeup_thresh / 8); /* but never more than the buffer size */ - bytes = min_t(int, bytes, sizeof(tmp)); + bytes = min_t(int, bytes, sizeof(u.tmp)); DEBUG_ENT("going to reseed %s with %d bits " "(%d of %d requested)\n", r->name, bytes * 8, nbytes * 8, r->entropy_count); - bytes = extract_entropy(r->pull, tmp, bytes, + bytes = extract_entropy(r->pull, u.tmp, bytes, random_read_wakeup_thresh / 8, rsvd); - mix_pool_bytes(r, tmp, bytes); + mix_pool_bytes(r, u.tmp, bytes, NULL); credit_entropy_bits(r, bytes*8); } + kmemcheck_mark_initialized(&u.hwrand, sizeof(u.hwrand)); + for (i = 0; i < 4; i++) + if (arch_get_random_long(&u.hwrand[i])) + break; + if (i) + mix_pool_bytes(r, &u.hwrand, sizeof(u.hwrand), 0); } /* @@ -822,9 +888,11 @@ static void extract_buf(struct entropy_store *r, __u8 *out) int i; __u32 hash[5], workspace[SHA_WORKSPACE_WORDS]; __u8 extract[64]; + unsigned long flags; /* Generate a hash across the pool, 16 words (512 bits) at a time */ sha_init(hash); + spin_lock_irqsave(&r->lock, flags); for (i = 0; i < r->poolinfo->poolwords; i += 16) sha_transform(hash, (__u8 *)(r->pool + i), workspace); @@ -837,7 +905,8 @@ static void extract_buf(struct entropy_store *r, __u8 *out) * brute-forcing the feedback as hard as brute-forcing the * hash. */ - mix_pool_bytes_extract(r, hash, sizeof(hash), extract); + __mix_pool_bytes(r, hash, sizeof(hash), extract); + spin_unlock_irqrestore(&r->lock, flags); /* * To avoid duplicates, we atomically extract a portion of the @@ -860,11 +929,10 @@ static void extract_buf(struct entropy_store *r, __u8 *out) } static ssize_t extract_entropy(struct entropy_store *r, void *buf, - size_t nbytes, int min, int reserved) + size_t nbytes, int min, int reserved) { ssize_t ret = 0, i; __u8 tmp[EXTRACT_SIZE]; - unsigned long flags; xfer_secondary_pool(r, nbytes); nbytes = account(r, nbytes, min, reserved); @@ -873,6 +941,8 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, extract_buf(r, tmp); if (fips_enabled) { + unsigned long flags; + spin_lock_irqsave(&r->lock, flags); if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) panic("Hardware RNG duplicated output!\n"); @@ -931,17 +1001,34 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, /* * This function is the exported kernel interface. It returns some - * number of good random numbers, suitable for seeding TCP sequence - * numbers, etc. + * number of good random numbers, suitable for key generation, seeding + * TCP sequence numbers, etc. It does not use the hw random number + * generator, if available; use get_random_bytes_arch() for that. */ void get_random_bytes(void *buf, int nbytes) +{ + extract_entropy(&nonblocking_pool, buf, nbytes, 0, 0); +} +EXPORT_SYMBOL(get_random_bytes); + +/* + * This function will use the architecture-specific hardware random + * number generator if it is available. The arch-specific hw RNG will + * almost certainly be faster than what we can do in software, but it + * is impossible to verify that it is implemented securely (as + * opposed, to, say, the AES encryption of a sequence number using a + * key known by the NSA). So it's useful if we need the speed, but + * only if we're willing to trust the hardware manufacturer not to + * have put in a back door. + */ +void get_random_bytes_arch(void *buf, int nbytes) { char *p = buf; while (nbytes) { unsigned long v; int chunk = min(nbytes, (int)sizeof(unsigned long)); - + if (!arch_get_random_long(&v)) break; @@ -950,9 +1037,11 @@ void get_random_bytes(void *buf, int nbytes) nbytes -= chunk; } - extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); + if (nbytes) + extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); } -EXPORT_SYMBOL(get_random_bytes); +EXPORT_SYMBOL(get_random_bytes_arch); + /* * init_std_data - initialize pool with system data @@ -966,21 +1055,18 @@ EXPORT_SYMBOL(get_random_bytes); static void init_std_data(struct entropy_store *r) { int i; - ktime_t now; - unsigned long flags; + ktime_t now = ktime_get_real(); + unsigned long rv; - spin_lock_irqsave(&r->lock, flags); r->entropy_count = 0; - spin_unlock_irqrestore(&r->lock, flags); - - now = ktime_get_real(); - mix_pool_bytes(r, &now, sizeof(now)); - for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof flags) { - if (!arch_get_random_long(&flags)) + r->entropy_total = 0; + mix_pool_bytes(r, &now, sizeof(now), NULL); + for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { + if (!arch_get_random_long(&rv)) break; - mix_pool_bytes(r, &flags, sizeof(flags)); + mix_pool_bytes(r, &rv, sizeof(rv), NULL); } - mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); + mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL); } static int rand_initialize(void) @@ -992,24 +1078,6 @@ static int rand_initialize(void) } module_init(rand_initialize); -void rand_initialize_irq(int irq) -{ - struct timer_rand_state *state; - - state = get_timer_rand_state(irq); - - if (state) - return; - - /* - * If kzalloc returns null, we just won't use that entropy - * source. - */ - state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL); - if (state) - set_timer_rand_state(irq, state); -} - #ifdef CONFIG_BLOCK void rand_initialize_disk(struct gendisk *disk) { @@ -1117,7 +1185,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count) count -= bytes; p += bytes; - mix_pool_bytes(r, buf, bytes); + mix_pool_bytes(r, buf, bytes, NULL); cond_resched(); } diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 57f96ebbce4..dd9e9561135 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -109,6 +109,28 @@ config CPU_FREQ_DEFAULT_GOV_INTERACTIVE loading your cpufreq low-level hardware driver, using the 'interactive' governor for latency-sensitive workloads. +config CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND + + bool "intellidemand" + select CPU_FREQ_GOV_INTELLIDEMAND + help + Use the CPUFreq governor 'intellidemand' as default. + +config CPU_FREQ_DEFAULT_GOV_SMARTMAX + bool "smartmax" + select CPU_FREQ_GOV_SMARTMAX + help + Use the CPUFreq governor 'smartmax' as default. + +config CPU_FREQ_DEFAULT_GOV_INTELLIACTIVE + bool "intelliactive" + select CPU_FREQ_GOV_INTELLIACTIVE + help + Use the CPUFreq governor 'intelliactive' as default. This allows + you to get a full dynamic cpu frequency capable system by simply + loading your cpufreq low-level hardware driver, using the + 'interactive' governor for latency-sensitive workloads. + endchoice config CPU_FREQ_GOV_PERFORMANCE @@ -183,6 +205,38 @@ config CPU_FREQ_GOV_INTERACTIVE If in doubt, say N. +config CPU_FREQ_GOV_SMARTMAX + tristate "'smartmax' cpufreq policy governor" + select CPU_FREQ_TABLE + help + 'smartmax' combined ondemand and smartass2 + +config CPU_FREQ_GOV_SMARTMAX_TEGRA + bool "'smartmax' for tegra" + depends on CPU_FREQ_GOV_SMARTMAX || CPU_FREQ_GOV_SMARTMAX_EPS + +config CPU_FREQ_GOV_SMARTMAX_30 + bool "'smartmax' for 3.0 and 3.1 kernels" + depends on CPU_FREQ_GOV_SMARTMAX || CPU_FREQ_GOV_SMARTMAX_EPS + +config CPU_FREQ_GOV_SMARTMAX_ENRC2B + bool "'smartmax' defaults for enrc2b" + depends on CPU_FREQ_GOV_SMARTMAX || CPU_FREQ_GOV_SMARTMAX_EPS + +config CPU_FREQ_GOV_SMARTMAX_PRIMOU + bool "'smartmax' defaults for primou" + depends on CPU_FREQ_GOV_SMARTMAX || CPU_FREQ_GOV_SMARTMAX_EPS + +config CPU_FREQ_GOV_SMARTMAX_M7 + bool "'smartmax' defaults for m7" + depends on CPU_FREQ_GOV_SMARTMAX || CPU_FREQ_GOV_SMARTMAX_EPS + +config CPU_FREQ_GOV_SMARTMAX_EPS + tristate "'smartmax EPS' cpufreq policy governor" + select CPU_FREQ_TABLE + help + 'smartmax EPS' is the extreme powersaving version of smartmax + config CPU_FREQ_GOV_CONSERVATIVE tristate "'conservative' cpufreq governor" depends on CPU_FREQ @@ -206,6 +260,34 @@ config CPU_FREQ_GOV_CONSERVATIVE If in doubt, say N. +config CPU_FREQ_GOV_INTELLIDEMAND + tristate "'intellidemand' cpufreq governor" + depends on CPU_FREQ + +config CPUFREQ_ID_PERFLOCK + bool "Intellidemand Performance Lock" + depends on CPU_FREQ_GOV_INTELLIDEMAND + default n + help + Minimum CPU performance lock for Intellidemand governor + +config CPU_FREQ_GOV_INTELLIACTIVE + tristate "'intelliactive' cpufreq policy governor" + help + 'intelliactive' - This driver adds a dynamic cpufreq policy governor + designed for latency-sensitive workloads. + + This governor attempts to reduce the latency of clock + increases so that the system is more responsive to + interactive workloads. + + To compile this driver as a module, choose M here: the + module will be called cpufreq_interactive. + + For details, take a look at linux/Documentation/cpu-freq. + + If in doubt, say N. + menu "x86 CPU frequency scaling drivers" depends on X86 source "drivers/cpufreq/Kconfig.x86" diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 46756c51847..0f75b6f9fff 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -10,6 +10,9 @@ obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o obj-$(CONFIG_CPU_FREQ_GOV_INTERACTIVE) += cpufreq_interactive.o +obj-$(CONFIG_CPU_FREQ_GOV_INTELLIDEMAND) += cpufreq_intellidemand.o +obj-$(CONFIG_CPU_FREQ_GOV_SMARTMAX) += cpufreq_smartmax.o cpufreq_smartmax_eps.o +obj-$(CONFIG_CPU_FREQ_GOV_INTELLIACTIVE)+= cpufreq_intelliactive.o # CPUfreq cross-arch helpers obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 5df0a7de6bf..7ac0900978f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -644,6 +644,90 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); } +#ifdef CONFIG_CPU_VOLTAGE_TABLE + +extern ssize_t acpuclk_get_vdd_levels_str(char *buf); +extern void acpuclk_set_vdd(unsigned acpu_khz, int vdd); + +static ssize_t show_vdd_levels(struct kobject *a, struct attribute *b, char *buf) { + return acpuclk_get_vdd_levels_str(buf); +} + +static ssize_t store_vdd_levels(struct kobject *a, struct attribute *b, const char *buf, size_t count) { + + int i = 0, j; + int pair[2] = { 0, 0 }; + int sign = 0; + + if (count < 1) + return 0; + + if (buf[0] == '-') { + sign = -1; + i++; + } + else if (buf[0] == '+') { + sign = 1; + i++; + } + + for (j = 0; i < count; i++) { + + char c = buf[i]; + + if ((c >= '0') && (c <= '9')) { + pair[j] *= 10; + pair[j] += (c - '0'); + } + else if ((c == ' ') || (c == '\t')) { + if (pair[j] != 0) { + j++; + + if ((sign != 0) || (j > 1)) + break; + } + } + else + break; + } + + if (sign != 0) { + if (pair[0] > 0) + acpuclk_set_vdd(0, sign * pair[0]); + } + else { + if ((pair[0] > 0) && (pair[1] > 0)) + acpuclk_set_vdd((unsigned)pair[0], pair[1]); + else + return -EINVAL; + } + return count; +} + +#endif /* CONFIG_CPU_VOLTAGE_TABLE */ + +#ifdef CONFIG_GPU_VOLTAGE_TABLE + +extern ssize_t get_gpu_vdd_levels_str(char *buf); +extern void set_gpu_vdd_levels(int uv_tbl[]); + +ssize_t show_vdd_levels_GPU(struct kobject *a, struct attribute *b, char *buf) +{ + int modu = 0; + return get_gpu_vdd_levels_str(buf); +} + +ssize_t store_vdd_levels_GPU(struct kobject *a, struct attribute *b, const char *buf, size_t count) +{ + unsigned int ret = -EINVAL; + unsigned int u[3]; + ret = sscanf(buf, "%d %d %d", &u[0], &u[1], &u[2]); + set_gpu_vdd_levels(u); + return count; +} + +#endif + cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); cpufreq_freq_attr_ro(cpuinfo_min_freq); cpufreq_freq_attr_ro(cpuinfo_max_freq); @@ -660,6 +744,12 @@ cpufreq_freq_attr_rw(scaling_max_freq); cpufreq_freq_attr_rw(scaling_governor); cpufreq_freq_attr_rw(scaling_setspeed); cpufreq_freq_attr_rw(dvfs_test); +#ifdef CONFIG_CPU_VOLTAGE_TABLE +define_one_global_rw(vdd_levels); +#endif +#ifdef CONFIG_GPU_VOLTAGE_TABLE +define_one_global_rw(vdd_levels_GPU); +#endif static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, @@ -678,6 +768,21 @@ static struct attribute *default_attrs[] = { NULL }; +#ifdef CONFIG_CPU_VOLTAGE_TABLE +static struct attribute *vddtbl_attrs[] = { + &vdd_levels.attr, +#ifdef CONFIG_GPU_VOLTAGE_TABLE + &vdd_levels_GPU.attr, +#endif + NULL +}; + +static struct attribute_group vddtbl_attr_group = { + .attrs = vddtbl_attrs, + .name = "vdd_table", +}; +#endif /* CONFIG_CPU_VOLTAGE_TABLE */ + struct kobject *cpufreq_global_kobject; EXPORT_SYMBOL(cpufreq_global_kobject); @@ -765,6 +870,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu, #ifdef CONFIG_SMP unsigned long flags; unsigned int j; +/* #ifdef CONFIG_HOTPLUG_CPU struct cpufreq_governor *gov; @@ -785,7 +891,7 @@ static int cpufreq_add_dev_policy(unsigned int cpu, pr_debug("Restoring CPU%d min %d and max %d\n", cpu, policy->min, policy->max); #endif - +*/ for_each_cpu(j, policy->cpus) { struct cpufreq_policy *managed_policy; @@ -814,6 +920,8 @@ static int cpufreq_add_dev_policy(unsigned int cpu, spin_lock_irqsave(&cpufreq_driver_lock, flags); cpumask_copy(managed_policy->cpus, policy->cpus); + cpumask_and(managed_policy->cpus, + managed_policy->cpus, cpu_online_mask); per_cpu(cpufreq_cpu_data, cpu) = managed_policy; spin_unlock_irqrestore(&cpufreq_driver_lock, flags); @@ -1013,10 +1121,15 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) #ifdef CONFIG_HOTPLUG_CPU for_each_online_cpu(sibling) { struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); - if (cp && cp->governor && - (cpumask_test_cpu(cpu, cp->related_cpus))) { + if (cp && cp->governor) { policy->governor = cp->governor; + policy->min = cp->min; + policy->max = cp->max; + policy->user_policy.min = cp->user_policy.min; + policy->user_policy.max = cp->user_policy.max; + found = 1; + //pr_info("sibling: found sibling!\n"); break; } } @@ -1031,6 +1144,13 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) pr_debug("initialization failed\n"); goto err_unlock_policy; } + + /* + * affected cpus must always be the one, which are online. We aren't + * managing offline cpus here. + */ + cpumask_and(policy->cpus, policy->cpus, cpu_online_mask); + policy->user_policy.min = policy->min; policy->user_policy.max = policy->max; @@ -1135,10 +1255,10 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif #ifdef CONFIG_HOTPLUG_CPU strncpy(per_cpu(cpufreq_policy_save, cpu).gov, data->governor->name, CPUFREQ_NAME_LEN); - per_cpu(cpufreq_policy_save, cpu).min = data->min; - per_cpu(cpufreq_policy_save, cpu).max = data->max; - pr_debug("Saving CPU%d policy min %d and max %d\n", - cpu, data->min, data->max); + per_cpu(cpufreq_policy_save, cpu).min = data->user_policy.min; + per_cpu(cpufreq_policy_save, cpu).max = data->user_policy.max; + pr_debug("Saving CPU%d user policy min %d and max %d\n", + cpu, data->user_policy.min, data->user_policy.max); #endif /* if we have other CPUs still registered, we need to unlink them, @@ -1164,9 +1284,11 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif #ifdef CONFIG_HOTPLUG_CPU strncpy(per_cpu(cpufreq_policy_save, j).gov, data->governor->name, CPUFREQ_NAME_LEN); - per_cpu(cpufreq_policy_save, j).min = data->min; - per_cpu(cpufreq_policy_save, j).max = data->max; - pr_debug("Saving CPU%d policy min %d and max %d\n", + per_cpu(cpufreq_policy_save, j).min + = data->user_policy.min; + per_cpu(cpufreq_policy_save, j).max + = data->user_policy.max; + pr_debug("Saving CPU%d user policy min %d and max %d\n", j, data->min, data->max); #endif cpu_dev = get_cpu_device(j); @@ -1745,7 +1867,8 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, memcpy(&policy->cpuinfo, &data->cpuinfo, sizeof(struct cpufreq_cpuinfo)); - if (policy->min > data->max || policy->max < data->min) { + if (policy->min > data->user_policy.max + || policy->max < data->user_policy.min) { ret = -EINVAL; goto error_out; } @@ -1873,7 +1996,7 @@ int cpufreq_update_policy(unsigned int cpu) } EXPORT_SYMBOL(cpufreq_update_policy); -static int __cpuinit cpufreq_cpu_callback(struct notifier_block *nfb, +static int cpufreq_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int cpu = (unsigned long)hcpu; @@ -2014,6 +2137,9 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_driver); static int __init cpufreq_core_init(void) { int cpu; +#ifdef CONFIG_CPU_VOLTAGE_TABLE + int rc; +#endif /* CONFIG_CPU_VOLTAGE_TABLE */ if (cpufreq_disabled()) return -ENODEV; @@ -2026,6 +2152,9 @@ static int __init cpufreq_core_init(void) cpufreq_global_kobject = kobject_create_and_add("cpufreq", &cpu_subsys.dev_root->kobj); BUG_ON(!cpufreq_global_kobject); register_syscore_ops(&cpufreq_syscore_ops); +#ifdef CONFIG_CPU_VOLTAGE_TABLE + rc = sysfs_create_group(cpufreq_global_kobject, &vddtbl_attr_group); +#endif /* CONFIG_CPU_VOLTAGE_TABLE */ return 0; } diff --git a/drivers/cpufreq/cpufreq_intelliactive.c b/drivers/cpufreq/cpufreq_intelliactive.c new file mode 100644 index 00000000000..50110f37f82 --- /dev/null +++ b/drivers/cpufreq/cpufreq_intelliactive.c @@ -0,0 +1,1552 @@ +/* + * drivers/cpufreq/cpufreq_intelliactive.c + * + * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2014 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + * Author: Mike Chan (mike@android.com) + * Author: Paul Reioux (reioux@gmail.com) Modified for intelliactive + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int active_count; + +struct cpufreq_interactive_cpuinfo { + struct timer_list cpu_timer; + struct timer_list cpu_slack_timer; + spinlock_t load_lock; /* protects the next 4 fields */ + u64 time_in_idle; + u64 time_in_idle_timestamp; + u64 cputime_speedadj; + u64 cputime_speedadj_timestamp; + struct cpufreq_policy *policy; + struct cpufreq_frequency_table *freq_table; + unsigned int target_freq; + unsigned int floor_freq; + u64 floor_validate_time; + u64 hispeed_validate_time; + struct rw_semaphore enable_sem; + int governor_enabled; + int prev_load; + unsigned int two_phase_freq; +}; + +static DEFINE_PER_CPU(struct cpufreq_interactive_cpuinfo, cpuinfo); + +/* realtime thread handles frequency scaling */ +static struct task_struct *speedchange_task; +static cpumask_t speedchange_cpumask; +static spinlock_t speedchange_cpumask_lock; +static struct mutex gov_lock; + +/* Hi speed to bump to from lo speed when load burst (default max) */ +static unsigned int hispeed_freq; + +/* Go to hi speed when CPU load at or above this value. */ +#define DEFAULT_GO_HISPEED_LOAD 99 +static unsigned long go_hispeed_load = DEFAULT_GO_HISPEED_LOAD; + +/* Sampling down factor to be applied to min_sample_time at max freq */ +static unsigned int sampling_down_factor; + +/* Target load. Lower values result in higher CPU speeds. */ +#define DEFAULT_TARGET_LOAD 90 +static unsigned int default_target_loads[] = {DEFAULT_TARGET_LOAD}; +static spinlock_t target_loads_lock; +static unsigned int *target_loads = default_target_loads; +static int ntarget_loads = ARRAY_SIZE(default_target_loads); + +/* + * The minimum amount of time to spend at a frequency before we can ramp down. + */ +#define DEFAULT_MIN_SAMPLE_TIME (80 * USEC_PER_MSEC) +static unsigned long min_sample_time = DEFAULT_MIN_SAMPLE_TIME; + +/* + * The sample rate of the timer used to increase frequency + */ +#define DEFAULT_TIMER_RATE (20 * USEC_PER_MSEC) +static unsigned long timer_rate = DEFAULT_TIMER_RATE; + +/* Busy SDF parameters*/ +#define MIN_BUSY_TIME (100 * USEC_PER_MSEC) + +/* + * Wait this long before raising speed above hispeed, by default a single + * timer interval. + */ +#define DEFAULT_ABOVE_HISPEED_DELAY DEFAULT_TIMER_RATE +static unsigned int default_above_hispeed_delay[] = { + DEFAULT_ABOVE_HISPEED_DELAY }; +static spinlock_t above_hispeed_delay_lock; +static unsigned int *above_hispeed_delay = default_above_hispeed_delay; +static int nabove_hispeed_delay = ARRAY_SIZE(default_above_hispeed_delay); + +/* Non-zero means indefinite speed boost active */ +static int boost_val; +/* Duration of a boot pulse in usecs */ +static int boostpulse_duration_val = DEFAULT_MIN_SAMPLE_TIME; +/* End time of boost pulse in ktime converted to usecs */ +static u64 boostpulse_endtime; + +/* + * Max additional time to wait in idle, beyond timer_rate, at speeds above + * minimum before wakeup to reduce speed, or -1 if unnecessary. + */ +#define DEFAULT_TIMER_SLACK (4 * DEFAULT_TIMER_RATE) +static int timer_slack_val = DEFAULT_TIMER_SLACK; + +static bool io_is_busy = 1; + +/* + * If the max load among other CPUs is higher than up_threshold_any_cpu_load + * and if the highest frequency among the other CPUs is higher than + * up_threshold_any_cpu_freq then do not let the frequency to drop below + * sync_freq + */ +static unsigned int up_threshold_any_cpu_load = 95; +static unsigned int sync_freq = 702000; +static unsigned int up_threshold_any_cpu_freq = 1026000; + +static int two_phase_freq_array[NR_CPUS] = {[0 ... NR_CPUS-1] = 1350000} ; + +static int cpufreq_governor_intelliactive(struct cpufreq_policy *policy, + unsigned int event); + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIACTIVE +static +#endif +struct cpufreq_governor cpufreq_gov_intelliactive = { + .name = "intelliactive", + .governor = cpufreq_governor_intelliactive, + .max_transition_latency = 10000000, + .owner = THIS_MODULE, +}; + +static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu, + cputime64_t *wall) +{ + u64 idle_time; + u64 cur_wall_time; + u64 busy_time; + + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + + busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; + + idle_time = cur_wall_time - busy_time; + if (wall) + *wall = jiffies_to_usecs(cur_wall_time); + + return jiffies_to_usecs(idle_time); +} + +static inline cputime64_t get_cpu_idle_time(unsigned int cpu, + cputime64_t *wall) +{ + u64 idle_time = get_cpu_idle_time_us(cpu, wall); + + if (idle_time == -1ULL) + idle_time = get_cpu_idle_time_jiffy(cpu, wall); + else if (!io_is_busy) + idle_time += get_cpu_iowait_time_us(cpu, wall); + + return idle_time; +} + +static void cpufreq_interactive_timer_resched( + struct cpufreq_interactive_cpuinfo *pcpu) +{ + unsigned long expires; + unsigned long flags; + + spin_lock_irqsave(&pcpu->load_lock, flags); + pcpu->time_in_idle = + get_cpu_idle_time(smp_processor_id(), + &pcpu->time_in_idle_timestamp); + pcpu->cputime_speedadj = 0; + pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; + expires = jiffies + usecs_to_jiffies(timer_rate); + mod_timer_pinned(&pcpu->cpu_timer, expires); + + if (timer_slack_val >= 0 && pcpu->target_freq > pcpu->policy->min) { + expires += usecs_to_jiffies(timer_slack_val); + mod_timer_pinned(&pcpu->cpu_slack_timer, expires); + } + + spin_unlock_irqrestore(&pcpu->load_lock, flags); +} + +/* The caller shall take enable_sem write semaphore to avoid any timer race. + * The cpu_timer and cpu_slack_timer must be deactivated when calling this + * function. + */ +static void cpufreq_interactive_timer_start(int cpu) +{ + struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); + unsigned long expires = jiffies + usecs_to_jiffies(timer_rate); + unsigned long flags; + + pcpu->cpu_timer.expires = expires; + if (cpu_online(cpu)) { + add_timer_on(&pcpu->cpu_timer, cpu); + if (timer_slack_val >= 0 && pcpu->target_freq > + pcpu->policy->min) { + expires += usecs_to_jiffies(timer_slack_val); + pcpu->cpu_slack_timer.expires = expires; + add_timer_on(&pcpu->cpu_slack_timer, cpu); + } + } + + spin_lock_irqsave(&pcpu->load_lock, flags); + pcpu->time_in_idle = + get_cpu_idle_time(cpu, &pcpu->time_in_idle_timestamp); + pcpu->cputime_speedadj = 0; + pcpu->cputime_speedadj_timestamp = pcpu->time_in_idle_timestamp; + spin_unlock_irqrestore(&pcpu->load_lock, flags); +} + +static unsigned int freq_to_above_hispeed_delay(unsigned int freq) +{ + int i; + unsigned int ret; + unsigned long flags; + + spin_lock_irqsave(&above_hispeed_delay_lock, flags); + + for (i = 0; i < nabove_hispeed_delay - 1 && + freq >= above_hispeed_delay[i+1]; i += 2) + ; + + ret = above_hispeed_delay[i]; + ret = (ret > (1 * USEC_PER_MSEC)) ? (ret - (1 * USEC_PER_MSEC)) : ret; + + spin_unlock_irqrestore(&above_hispeed_delay_lock, flags); + return ret; +} + +static unsigned int freq_to_targetload(unsigned int freq) +{ + int i; + unsigned int ret; + unsigned long flags; + + spin_lock_irqsave(&target_loads_lock, flags); + + for (i = 0; i < ntarget_loads - 1 && freq >= target_loads[i+1]; i += 2) + ; + + ret = target_loads[i]; + spin_unlock_irqrestore(&target_loads_lock, flags); + return ret; +} + +/* + * If increasing frequencies never map to a lower target load then + * choose_freq() will find the minimum frequency that does not exceed its + * target load given the current load. + */ + +static unsigned int choose_freq( + struct cpufreq_interactive_cpuinfo *pcpu, unsigned int loadadjfreq) +{ + unsigned int freq = pcpu->policy->cur; + unsigned int prevfreq, freqmin, freqmax; + unsigned int tl; + int index; + + freqmin = 0; + freqmax = UINT_MAX; + + do { + prevfreq = freq; + tl = freq_to_targetload(freq); + + /* + * Find the lowest frequency where the computed load is less + * than or equal to the target load. + */ + + if (cpufreq_frequency_table_target( + pcpu->policy, pcpu->freq_table, loadadjfreq / tl, + CPUFREQ_RELATION_L, &index)) + break; + freq = pcpu->freq_table[index].frequency; + + if (freq > prevfreq) { + /* The previous frequency is too low. */ + freqmin = prevfreq; + + if (freq >= freqmax) { + /* + * Find the highest frequency that is less + * than freqmax. + */ + if (cpufreq_frequency_table_target( + pcpu->policy, pcpu->freq_table, + freqmax - 1, CPUFREQ_RELATION_H, + &index)) + break; + freq = pcpu->freq_table[index].frequency; + + if (freq == freqmin) { + /* + * The first frequency below freqmax + * has already been found to be too + * low. freqmax is the lowest speed + * we found that is fast enough. + */ + freq = freqmax; + break; + } + } + } else if (freq < prevfreq) { + /* The previous frequency is high enough. */ + freqmax = prevfreq; + + if (freq <= freqmin) { + /* + * Find the lowest frequency that is higher + * than freqmin. + */ + if (cpufreq_frequency_table_target( + pcpu->policy, pcpu->freq_table, + freqmin + 1, CPUFREQ_RELATION_L, + &index)) + break; + freq = pcpu->freq_table[index].frequency; + + /* + * If freqmax is the first frequency above + * freqmin then we have already found that + * this speed is fast enough. + */ + if (freq == freqmax) + break; + } + } + + /* If same frequency chosen as previous then done. */ + } while (freq != prevfreq); + + return freq; +} + +static u64 update_load(int cpu) +{ + struct cpufreq_interactive_cpuinfo *pcpu = &per_cpu(cpuinfo, cpu); + u64 now; + u64 now_idle; + unsigned int delta_idle; + unsigned int delta_time; + u64 active_time; + + now_idle = get_cpu_idle_time(cpu, &now); + delta_idle = (unsigned int)(now_idle - pcpu->time_in_idle); + delta_time = (unsigned int)(now - pcpu->time_in_idle_timestamp); + + if (delta_time <= delta_idle) + active_time = 0; + else + active_time = delta_time - delta_idle; + + pcpu->cputime_speedadj += active_time * pcpu->policy->cur; + + pcpu->time_in_idle = now_idle; + pcpu->time_in_idle_timestamp = now; + return now; +} + +static void cpufreq_interactive_timer(unsigned long data) +{ + u64 now; + unsigned int delta_time; + u64 cputime_speedadj; + int cpu_load; + struct cpufreq_interactive_cpuinfo *pcpu = + &per_cpu(cpuinfo, data); + unsigned int new_freq; + unsigned int loadadjfreq; + unsigned int index; + unsigned long flags; + bool boosted; + unsigned long mod_min_sample_time; + int i, max_load; + unsigned int max_freq; + struct cpufreq_interactive_cpuinfo *picpu; + static unsigned int phase = 0; + static unsigned int counter = 0; + unsigned int nr_cpus; + + if (!down_read_trylock(&pcpu->enable_sem)) + return; + if (!pcpu->governor_enabled) + goto exit; + + if (cpu_is_offline(data)) + goto exit; + + spin_lock_irqsave(&pcpu->load_lock, flags); + now = update_load(data); + delta_time = (unsigned int)(now - pcpu->cputime_speedadj_timestamp); + cputime_speedadj = pcpu->cputime_speedadj; + spin_unlock_irqrestore(&pcpu->load_lock, flags); + + if (WARN_ON_ONCE(!delta_time)) + goto rearm; + + do_div(cputime_speedadj, delta_time); + loadadjfreq = (unsigned int)cputime_speedadj * 100; + cpu_load = loadadjfreq / pcpu->target_freq; + pcpu->prev_load = cpu_load; + boosted = boost_val || now < boostpulse_endtime; + + // HACK HACK HACK BEGIN + if (counter < 5) { + counter++; + if (counter > 2) { + phase = 1; + } + } + + if (cpu_load >= go_hispeed_load || boosted) { + if (pcpu->target_freq < hispeed_freq) { + nr_cpus = num_online_cpus(); + + pcpu->two_phase_freq = two_phase_freq_array[nr_cpus-1]; + if (pcpu->two_phase_freq < pcpu->policy->cur) + phase = 1; + if (pcpu->two_phase_freq != 0 && phase == 0) { + new_freq = pcpu->two_phase_freq; + } else + new_freq = hispeed_freq; + } else { + new_freq = choose_freq(pcpu, loadadjfreq); + + if (new_freq < hispeed_freq) + new_freq = hispeed_freq; + } + } else { + new_freq = choose_freq(pcpu, loadadjfreq); + + if (sync_freq && new_freq < sync_freq) { + + max_load = 0; + max_freq = 0; + + for_each_online_cpu(i) { + picpu = &per_cpu(cpuinfo, i); + + if (i == data || picpu->prev_load < + up_threshold_any_cpu_load) + continue; + + max_load = max(max_load, picpu->prev_load); + max_freq = max(max_freq, picpu->target_freq); + } + + if (max_freq > up_threshold_any_cpu_freq && + max_load >= up_threshold_any_cpu_load) + new_freq = sync_freq; + } + } + + if (counter > 0) { + counter--; + if (counter == 0) { + phase = 0; + } + } + + if (pcpu->target_freq >= hispeed_freq && + new_freq > pcpu->target_freq && + now - pcpu->hispeed_validate_time < + freq_to_above_hispeed_delay(pcpu->target_freq)) { + goto rearm; + } + + pcpu->hispeed_validate_time = now; + + if (cpufreq_frequency_table_target(pcpu->policy, pcpu->freq_table, + new_freq, CPUFREQ_RELATION_L, + &index)) + goto rearm; + + new_freq = pcpu->freq_table[index].frequency; + + /* + * Do not scale below floor_freq unless we have been at or above the + * floor frequency for the minimum sample time since last validated. + */ + if (sampling_down_factor && pcpu->policy->cur == pcpu->policy->max) + mod_min_sample_time = sampling_down_factor; + else + mod_min_sample_time = min_sample_time; + + if (new_freq < pcpu->floor_freq) { + if (now - pcpu->floor_validate_time < mod_min_sample_time) { + goto rearm; + } + } + + /* + * Update the timestamp for checking whether speed has been held at + * or above the selected frequency for a minimum of min_sample_time, + * if not boosted to hispeed_freq. If boosted to hispeed_freq then we + * allow the speed to drop as soon as the boostpulse duration expires + * (or the indefinite boost is turned off). + */ + + if (!boosted || new_freq > hispeed_freq) { + pcpu->floor_freq = new_freq; + pcpu->floor_validate_time = now; + } + + if (pcpu->target_freq == new_freq) { + goto rearm_if_notmax; + } + + pcpu->target_freq = new_freq; + spin_lock_irqsave(&speedchange_cpumask_lock, flags); + cpumask_set_cpu(data, &speedchange_cpumask); + spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); + wake_up_process(speedchange_task); + +rearm_if_notmax: + /* + * Already set max speed and don't see a need to change that, + * wait until next idle to re-evaluate, don't need timer. + */ + if (pcpu->target_freq == pcpu->policy->max) + goto exit; + +rearm: + if (!timer_pending(&pcpu->cpu_timer)) + cpufreq_interactive_timer_resched(pcpu); + +exit: + up_read(&pcpu->enable_sem); + return; +} + +static void cpufreq_interactive_idle_start(void) +{ + int cpu = smp_processor_id(); + struct cpufreq_interactive_cpuinfo *pcpu = + &per_cpu(cpuinfo, smp_processor_id()); + int pending; + u64 now; + + if (!down_read_trylock(&pcpu->enable_sem)) + return; + if (!pcpu->governor_enabled) + goto exit; + + /* Cancel the timer if cpu is offline */ + if (cpu_is_offline(cpu)) { + del_timer(&pcpu->cpu_timer); + del_timer(&pcpu->cpu_slack_timer); + goto exit; + } + + pending = timer_pending(&pcpu->cpu_timer); + + if (pcpu->target_freq != pcpu->policy->min) { + /* + * Entering idle while not at lowest speed. On some + * platforms this can hold the other CPU(s) at that speed + * even though the CPU is idle. Set a timer to re-evaluate + * speed so this idle CPU doesn't hold the other CPUs above + * min indefinitely. This should probably be a quirk of + * the CPUFreq driver. + */ + if (!pending) { + cpufreq_interactive_timer_resched(pcpu); + + now = ktime_to_us(ktime_get()); + if ((pcpu->policy->cur == pcpu->policy->max) && + (now - pcpu->hispeed_validate_time) > + MIN_BUSY_TIME) { + pcpu->floor_validate_time = now; + } + + } + } +exit: + up_read(&pcpu->enable_sem); +} + +static void cpufreq_interactive_idle_end(void) +{ + struct cpufreq_interactive_cpuinfo *pcpu = + &per_cpu(cpuinfo, smp_processor_id()); + + if (!down_read_trylock(&pcpu->enable_sem)) + return; + if (!pcpu->governor_enabled) { + up_read(&pcpu->enable_sem); + return; + } + + /* Arm the timer for 1-2 ticks later if not already. */ + if (!timer_pending(&pcpu->cpu_timer)) { + cpufreq_interactive_timer_resched(pcpu); + } else if (time_after_eq(jiffies, pcpu->cpu_timer.expires)) { + del_timer(&pcpu->cpu_timer); + del_timer(&pcpu->cpu_slack_timer); + cpufreq_interactive_timer(smp_processor_id()); + } + + up_read(&pcpu->enable_sem); +} + +static int cpufreq_interactive_speedchange_task(void *data) +{ + unsigned int cpu; + cpumask_t tmp_mask; + unsigned long flags; + struct cpufreq_interactive_cpuinfo *pcpu; + + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + spin_lock_irqsave(&speedchange_cpumask_lock, flags); + + if (cpumask_empty(&speedchange_cpumask)) { + spin_unlock_irqrestore(&speedchange_cpumask_lock, + flags); + schedule(); + + if (kthread_should_stop()) + break; + + spin_lock_irqsave(&speedchange_cpumask_lock, flags); + } + + set_current_state(TASK_RUNNING); + tmp_mask = speedchange_cpumask; + cpumask_clear(&speedchange_cpumask); + spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); + + for_each_cpu(cpu, &tmp_mask) { + unsigned int j; + unsigned int max_freq = 0; + + pcpu = &per_cpu(cpuinfo, cpu); + if (!down_read_trylock(&pcpu->enable_sem)) + continue; + if (!pcpu->governor_enabled) { + up_read(&pcpu->enable_sem); + continue; + } + + for_each_cpu(j, pcpu->policy->cpus) { + struct cpufreq_interactive_cpuinfo *pjcpu = + &per_cpu(cpuinfo, j); + + if (pjcpu->target_freq > max_freq) + max_freq = pjcpu->target_freq; + } + + if (max_freq != pcpu->policy->cur) + __cpufreq_driver_target(pcpu->policy, + max_freq, + CPUFREQ_RELATION_H); + + up_read(&pcpu->enable_sem); + } + } + + return 0; +} + +static void cpufreq_interactive_boost(void) +{ + int i; + int anyboost = 0; + unsigned long flags; + struct cpufreq_interactive_cpuinfo *pcpu; + + spin_lock_irqsave(&speedchange_cpumask_lock, flags); + + for_each_online_cpu(i) { + pcpu = &per_cpu(cpuinfo, i); + + if (pcpu->target_freq < hispeed_freq) { + pcpu->target_freq = hispeed_freq; + cpumask_set_cpu(i, &speedchange_cpumask); + pcpu->hispeed_validate_time = + ktime_to_us(ktime_get()); + anyboost = 1; + } + + /* + * Set floor freq and (re)start timer for when last + * validated. + */ + + pcpu->floor_freq = hispeed_freq; + pcpu->floor_validate_time = ktime_to_us(ktime_get()); + } + + spin_unlock_irqrestore(&speedchange_cpumask_lock, flags); + + if (anyboost) + wake_up_process(speedchange_task); +} + +static int cpufreq_interactive_notifier( + struct notifier_block *nb, unsigned long val, void *data) +{ + struct cpufreq_freqs *freq = data; + struct cpufreq_interactive_cpuinfo *pcpu; + int cpu; + unsigned long flags; + + if (val == CPUFREQ_POSTCHANGE) { + pcpu = &per_cpu(cpuinfo, freq->cpu); + if (!down_read_trylock(&pcpu->enable_sem)) + return 0; + if (!pcpu->governor_enabled) { + up_read(&pcpu->enable_sem); + return 0; + } + + for_each_cpu(cpu, pcpu->policy->cpus) { + struct cpufreq_interactive_cpuinfo *pjcpu = + &per_cpu(cpuinfo, cpu); + if (cpu != freq->cpu) { + if (!down_read_trylock(&pjcpu->enable_sem)) + continue; + if (!pjcpu->governor_enabled) { + up_read(&pjcpu->enable_sem); + continue; + } + } + spin_lock_irqsave(&pjcpu->load_lock, flags); + update_load(cpu); + spin_unlock_irqrestore(&pjcpu->load_lock, flags); + if (cpu != freq->cpu) + up_read(&pjcpu->enable_sem); + } + + up_read(&pcpu->enable_sem); + } + return 0; +} + +static struct notifier_block cpufreq_notifier_block = { + .notifier_call = cpufreq_interactive_notifier, +}; + +static unsigned int *get_tokenized_data(const char *buf, int *num_tokens) +{ + const char *cp; + int i; + int ntokens = 1; + unsigned int *tokenized_data; + int err = -EINVAL; + + cp = buf; + while ((cp = strpbrk(cp + 1, " :"))) + ntokens++; + + if (!(ntokens & 0x1)) + goto err; + + tokenized_data = kmalloc(ntokens * sizeof(unsigned int), GFP_KERNEL); + if (!tokenized_data) { + err = -ENOMEM; + goto err; + } + + cp = buf; + i = 0; + while (i < ntokens) { + if (sscanf(cp, "%u", &tokenized_data[i++]) != 1) + goto err_kfree; + + cp = strpbrk(cp, " :"); + if (!cp) + break; + cp++; + } + + if (i != ntokens) + goto err_kfree; + + *num_tokens = ntokens; + return tokenized_data; + +err_kfree: + kfree(tokenized_data); +err: + return ERR_PTR(err); +} + +static ssize_t show_two_phase_freq +(struct kobject *kobj, struct attribute *attr, char *buf) +{ + int i = 0 ; + int shift = 0 ; + char *buf_pos = buf; + for ( i = 0 ; i < NR_CPUS; i++) { + shift = sprintf(buf_pos,"%d,",two_phase_freq_array[i]); + buf_pos += shift; + } + *(buf_pos-1) = '\0'; + return strlen(buf); +} + +static ssize_t store_two_phase_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + + int ret = 0; + if (NR_CPUS == 1) + ret = sscanf(buf,"%u",&two_phase_freq_array[0]); + else if (NR_CPUS == 2) + ret = sscanf(buf,"%u,%u",&two_phase_freq_array[0], + &two_phase_freq_array[1]); + else if (NR_CPUS == 4) + ret = sscanf(buf, "%u,%u,%u,%u", &two_phase_freq_array[0], + &two_phase_freq_array[1], + &two_phase_freq_array[2], + &two_phase_freq_array[3]); + if (ret < NR_CPUS) + return -EINVAL; + + return count; +} + +static struct global_attr two_phase_freq_attr = + __ATTR(two_phase_freq, S_IRUGO | S_IWUSR, + show_two_phase_freq, store_two_phase_freq); + +static ssize_t show_target_loads( + struct kobject *kobj, struct attribute *attr, char *buf) +{ + int i; + ssize_t ret = 0; + unsigned long flags; + + spin_lock_irqsave(&target_loads_lock, flags); + + for (i = 0; i < ntarget_loads; i++) + ret += sprintf(buf + ret, "%u%s", target_loads[i], + i & 0x1 ? ":" : " "); + + --ret; + ret += sprintf(buf + ret, "\n"); + spin_unlock_irqrestore(&target_loads_lock, flags); + return ret; +} + +static ssize_t store_target_loads( + struct kobject *kobj, struct attribute *attr, const char *buf, + size_t count) +{ + int ntokens; + unsigned int *new_target_loads = NULL; + unsigned long flags; + + new_target_loads = get_tokenized_data(buf, &ntokens); + if (IS_ERR(new_target_loads)) + return PTR_RET(new_target_loads); + + spin_lock_irqsave(&target_loads_lock, flags); + if (target_loads != default_target_loads) + kfree(target_loads); + target_loads = new_target_loads; + ntarget_loads = ntokens; + spin_unlock_irqrestore(&target_loads_lock, flags); + return count; +} + +static struct global_attr target_loads_attr = + __ATTR(target_loads, S_IRUGO | S_IWUSR, + show_target_loads, store_target_loads); + +static ssize_t show_above_hispeed_delay( + struct kobject *kobj, struct attribute *attr, char *buf) +{ + int i; + ssize_t ret = 0; + unsigned long flags; + + spin_lock_irqsave(&above_hispeed_delay_lock, flags); + + for (i = 0; i < nabove_hispeed_delay; i++) + ret += sprintf(buf + ret, "%u%s", above_hispeed_delay[i], + i & 0x1 ? ":" : " "); + + --ret; + ret += sprintf(buf + ret, "\n"); + spin_unlock_irqrestore(&above_hispeed_delay_lock, flags); + return ret; +} + +static ssize_t store_above_hispeed_delay( + struct kobject *kobj, struct attribute *attr, const char *buf, + size_t count) +{ + int ntokens; + unsigned int *new_above_hispeed_delay = NULL; + unsigned long flags; + + new_above_hispeed_delay = get_tokenized_data(buf, &ntokens); + if (IS_ERR(new_above_hispeed_delay)) + return PTR_RET(new_above_hispeed_delay); + + spin_lock_irqsave(&above_hispeed_delay_lock, flags); + if (above_hispeed_delay != default_above_hispeed_delay) + kfree(above_hispeed_delay); + above_hispeed_delay = new_above_hispeed_delay; + nabove_hispeed_delay = ntokens; + spin_unlock_irqrestore(&above_hispeed_delay_lock, flags); + return count; + +} + +static struct global_attr above_hispeed_delay_attr = + __ATTR(above_hispeed_delay, S_IRUGO | S_IWUSR, + show_above_hispeed_delay, store_above_hispeed_delay); + +static ssize_t show_hispeed_freq(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", hispeed_freq); +} + +static ssize_t store_hispeed_freq(struct kobject *kobj, + struct attribute *attr, const char *buf, + size_t count) +{ + int ret; + long unsigned int val; + + ret = strict_strtoul(buf, 0, &val); + if (ret < 0) + return ret; + hispeed_freq = val; + return count; +} + +static struct global_attr hispeed_freq_attr = __ATTR(hispeed_freq, 0644, + show_hispeed_freq, store_hispeed_freq); + +static ssize_t show_sampling_down_factor(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", sampling_down_factor); +} + +static ssize_t store_sampling_down_factor(struct kobject *kobj, + struct attribute *attr, const char *buf, + size_t count) +{ + int ret; + long unsigned int val; + + ret = strict_strtoul(buf, 0, &val); + if (ret < 0) + return ret; + sampling_down_factor = val; + return count; +} + +static struct global_attr sampling_down_factor_attr = + __ATTR(sampling_down_factor, 0644, + show_sampling_down_factor, store_sampling_down_factor); + +static ssize_t show_go_hispeed_load(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", go_hispeed_load); +} + +static ssize_t store_go_hispeed_load(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = strict_strtoul(buf, 0, &val); + if (ret < 0) + return ret; + go_hispeed_load = val; + return count; +} + +static struct global_attr go_hispeed_load_attr = __ATTR(go_hispeed_load, 0644, + show_go_hispeed_load, store_go_hispeed_load); + +static ssize_t show_min_sample_time(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", min_sample_time); +} + +static ssize_t store_min_sample_time(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = strict_strtoul(buf, 0, &val); + if (ret < 0) + return ret; + min_sample_time = val; + return count; +} + +static struct global_attr min_sample_time_attr = __ATTR(min_sample_time, 0644, + show_min_sample_time, store_min_sample_time); + +static ssize_t show_timer_rate(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", timer_rate); +} + +static ssize_t store_timer_rate(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = strict_strtoul(buf, 0, &val); + if (ret < 0) + return ret; + timer_rate = val; + return count; +} + +static struct global_attr timer_rate_attr = __ATTR(timer_rate, 0644, + show_timer_rate, store_timer_rate); + +static ssize_t show_timer_slack( + struct kobject *kobj, struct attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", timer_slack_val); +} + +static ssize_t store_timer_slack( + struct kobject *kobj, struct attribute *attr, const char *buf, + size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtol(buf, 10, &val); + if (ret < 0) + return ret; + + timer_slack_val = val; + return count; +} + +define_one_global_rw(timer_slack); + +static ssize_t show_boost(struct kobject *kobj, struct attribute *attr, + char *buf) +{ + return sprintf(buf, "%d\n", boost_val); +} + +static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + + boost_val = val; + + if (boost_val) { + cpufreq_interactive_boost(); + } + + return count; +} + +define_one_global_rw(boost); + +static ssize_t store_boostpulse(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + + boostpulse_endtime = ktime_to_us(ktime_get()) + boostpulse_duration_val; + cpufreq_interactive_boost(); + return count; +} + +static struct global_attr boostpulse = + __ATTR(boostpulse, 0200, NULL, store_boostpulse); + +static ssize_t show_boostpulse_duration( + struct kobject *kobj, struct attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", boostpulse_duration_val); +} + +static ssize_t store_boostpulse_duration( + struct kobject *kobj, struct attribute *attr, const char *buf, + size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + + boostpulse_duration_val = val; + return count; +} + +define_one_global_rw(boostpulse_duration); + +static ssize_t show_io_is_busy(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", io_is_busy); +} + +static ssize_t store_io_is_busy(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + io_is_busy = val; + return count; +} + +static struct global_attr io_is_busy_attr = __ATTR(io_is_busy, 0644, + show_io_is_busy, store_io_is_busy); + +static ssize_t show_sync_freq(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", sync_freq); +} + +static ssize_t store_sync_freq(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + sync_freq = val; + return count; +} + +static struct global_attr sync_freq_attr = __ATTR(sync_freq, 0644, + show_sync_freq, store_sync_freq); + +static ssize_t show_up_threshold_any_cpu_load(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", up_threshold_any_cpu_load); +} + +static ssize_t store_up_threshold_any_cpu_load(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + up_threshold_any_cpu_load = val; + return count; +} + +static struct global_attr up_threshold_any_cpu_load_attr = + __ATTR(up_threshold_any_cpu_load, 0644, + show_up_threshold_any_cpu_load, + store_up_threshold_any_cpu_load); + +static ssize_t show_up_threshold_any_cpu_freq(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%u\n", up_threshold_any_cpu_freq); +} + +static ssize_t store_up_threshold_any_cpu_freq(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) +{ + int ret; + unsigned long val; + + ret = kstrtoul(buf, 0, &val); + if (ret < 0) + return ret; + up_threshold_any_cpu_freq = val; + return count; +} + +static struct global_attr up_threshold_any_cpu_freq_attr = + __ATTR(up_threshold_any_cpu_freq, 0644, + show_up_threshold_any_cpu_freq, + store_up_threshold_any_cpu_freq); + +static struct attribute *interactive_attributes[] = { + &target_loads_attr.attr, + &above_hispeed_delay_attr.attr, + &hispeed_freq_attr.attr, + &go_hispeed_load_attr.attr, + &min_sample_time_attr.attr, + &timer_rate_attr.attr, + &timer_slack.attr, + &boost.attr, + &boostpulse.attr, + &boostpulse_duration.attr, + &io_is_busy_attr.attr, + &sampling_down_factor_attr.attr, + &sync_freq_attr.attr, + &up_threshold_any_cpu_load_attr.attr, + &up_threshold_any_cpu_freq_attr.attr, + &two_phase_freq_attr.attr, + NULL, +}; + +static void interactive_input_event(struct input_handle *handle, + unsigned int type, + unsigned int code, int value) +{ + if (type == EV_SYN && code == SYN_REPORT) { + boostpulse_endtime = ktime_to_us(ktime_get()) + + boostpulse_duration_val; + cpufreq_interactive_boost(); + } +} + +static int interactive_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) +{ + struct input_handle *handle; + int error; + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "cpufreq"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + + return 0; +err1: + input_unregister_handle(handle); +err2: + kfree(handle); + return error; +} + +static void interactive_input_disconnect(struct input_handle *handle) +{ + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id interactive_ids[] = { + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, /* multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, + }, /* touchpad */ +}; + +static struct input_handler interactive_input_handler = { + .event = interactive_input_event, + .connect = interactive_input_connect, + .disconnect = interactive_input_disconnect, + .name = "intelliactive", + .id_table = interactive_ids, +}; + +static struct attribute_group interactive_attr_group = { + .attrs = interactive_attributes, + .name = "intelliactive", +}; + +static int cpufreq_interactive_idle_notifier(struct notifier_block *nb, + unsigned long val, + void *data) +{ + switch (val) { + case IDLE_START: + cpufreq_interactive_idle_start(); + break; + case IDLE_END: + cpufreq_interactive_idle_end(); + break; + } + + return 0; +} + +static struct notifier_block cpufreq_interactive_idle_nb = { + .notifier_call = cpufreq_interactive_idle_notifier, +}; + +static int cpufreq_governor_intelliactive(struct cpufreq_policy *policy, + unsigned int event) +{ + int rc; + unsigned int j; + struct cpufreq_interactive_cpuinfo *pcpu; + struct cpufreq_frequency_table *freq_table; + + switch (event) { + case CPUFREQ_GOV_START: + if (!cpu_online(policy->cpu)) + return -EINVAL; + + mutex_lock(&gov_lock); + + freq_table = + cpufreq_frequency_get_table(policy->cpu); + if (!hispeed_freq) + hispeed_freq = policy->max; + + for_each_cpu(j, policy->cpus) { + pcpu = &per_cpu(cpuinfo, j); + pcpu->policy = policy; + pcpu->target_freq = policy->cur; + pcpu->freq_table = freq_table; + pcpu->floor_freq = pcpu->target_freq; + pcpu->floor_validate_time = + ktime_to_us(ktime_get()); + pcpu->hispeed_validate_time = + pcpu->floor_validate_time; + down_write(&pcpu->enable_sem); + del_timer_sync(&pcpu->cpu_timer); + del_timer_sync(&pcpu->cpu_slack_timer); + cpufreq_interactive_timer_start(j); + pcpu->governor_enabled = 1; + up_write(&pcpu->enable_sem); + } + + /* + * Do not register the idle hook and create sysfs + * entries if we have already done so. + */ + if (++active_count > 1) { + mutex_unlock(&gov_lock); + return 0; + } + + rc = sysfs_create_group(cpufreq_global_kobject, + &interactive_attr_group); + if (rc) { + mutex_unlock(&gov_lock); + return rc; + } + + idle_notifier_register(&cpufreq_interactive_idle_nb); + cpufreq_register_notifier( + &cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); + mutex_unlock(&gov_lock); + break; + + case CPUFREQ_GOV_STOP: + mutex_lock(&gov_lock); + for_each_cpu(j, policy->cpus) { + pcpu = &per_cpu(cpuinfo, j); + down_write(&pcpu->enable_sem); + pcpu->governor_enabled = 0; + pcpu->target_freq = 0; + del_timer_sync(&pcpu->cpu_timer); + del_timer_sync(&pcpu->cpu_slack_timer); + up_write(&pcpu->enable_sem); + } + + if (--active_count > 0) { + mutex_unlock(&gov_lock); + return 0; + } + + cpufreq_unregister_notifier( + &cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); + idle_notifier_unregister(&cpufreq_interactive_idle_nb); + sysfs_remove_group(cpufreq_global_kobject, + &interactive_attr_group); + mutex_unlock(&gov_lock); + + break; + + case CPUFREQ_GOV_LIMITS: + if (policy->max < policy->cur) + __cpufreq_driver_target(policy, + policy->max, CPUFREQ_RELATION_H); + else if (policy->min > policy->cur) + __cpufreq_driver_target(policy, + policy->min, CPUFREQ_RELATION_L); + for_each_cpu(j, policy->cpus) { + pcpu = &per_cpu(cpuinfo, j); + + /* hold write semaphore to avoid race */ + down_write(&pcpu->enable_sem); + if (pcpu->governor_enabled == 0) { + up_write(&pcpu->enable_sem); + continue; + } + + /* update target_freq firstly */ + if (policy->max < pcpu->target_freq) + pcpu->target_freq = policy->max; + else if (policy->min > pcpu->target_freq) + pcpu->target_freq = policy->min; + + /* Reschedule timer. + * Delete the timers, else the timer callback may + * return without re-arm the timer when failed + * acquire the semaphore. This race may cause timer + * stopped unexpectedly. + */ + del_timer_sync(&pcpu->cpu_timer); + del_timer_sync(&pcpu->cpu_slack_timer); + cpufreq_interactive_timer_start(j); + up_write(&pcpu->enable_sem); + } + break; + } + return 0; +} + +static void cpufreq_interactive_nop_timer(unsigned long data) +{ +} + +static int __init cpufreq_intelliactive_init(void) +{ + unsigned int i, rc; + struct cpufreq_interactive_cpuinfo *pcpu; + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + + /* Initalize per-cpu timers */ + for_each_possible_cpu(i) { + pcpu = &per_cpu(cpuinfo, i); + init_timer_deferrable(&pcpu->cpu_timer); + pcpu->cpu_timer.function = cpufreq_interactive_timer; + pcpu->cpu_timer.data = i; + init_timer(&pcpu->cpu_slack_timer); + pcpu->cpu_slack_timer.function = cpufreq_interactive_nop_timer; + spin_lock_init(&pcpu->load_lock); + init_rwsem(&pcpu->enable_sem); + if (!i) + rc = input_register_handler(&interactive_input_handler); + } + + spin_lock_init(&target_loads_lock); + spin_lock_init(&speedchange_cpumask_lock); + spin_lock_init(&above_hispeed_delay_lock); + mutex_init(&gov_lock); + speedchange_task = + kthread_create(cpufreq_interactive_speedchange_task, NULL, + "cfintelliactive"); + if (IS_ERR(speedchange_task)) + return PTR_ERR(speedchange_task); + + sched_setscheduler_nocheck(speedchange_task, SCHED_FIFO, ¶m); + get_task_struct(speedchange_task); + + /* NB: wake up so the thread does not look hung to the freezer */ + wake_up_process(speedchange_task); + + return cpufreq_register_governor(&cpufreq_gov_intelliactive); +} + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIACTIVE +fs_initcall(cpufreq_intelliactive_init); +#else +module_init(cpufreq_intelliactive_init); +#endif + +static void __exit cpufreq_interactive_exit(void) +{ + unsigned int cpu; + + cpufreq_unregister_governor(&cpufreq_gov_intelliactive); + for_each_possible_cpu(cpu) { + if(!cpu) + input_unregister_handler(&interactive_input_handler); + } + kthread_stop(speedchange_task); + put_task_struct(speedchange_task); +} + +module_exit(cpufreq_interactive_exit); + +MODULE_AUTHOR("Mike Chan "); +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("'cpufreq_intelliactive' - A cpufreq governor for " + "Latency sensitive workloads based on Google's Interactive"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/cpufreq_intellidemand.c b/drivers/cpufreq/cpufreq_intellidemand.c new file mode 100644 index 00000000000..f0a5630ebcb --- /dev/null +++ b/drivers/cpufreq/cpufreq_intellidemand.c @@ -0,0 +1,890 @@ +/* + * drivers/cpufreq/cpufreq_intellidemand.c + * + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _LIMIT_LCD_OFF_CPU_MAX_FREQ_ + +/* + * dbs is used in this file as a shortform for demandbased switching + * It helps to keep variable names smaller, simpler + */ + +#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) +#define DEF_FREQUENCY_UP_THRESHOLD (90) +#define DEF_SAMPLING_DOWN_FACTOR (15) +#define MAX_SAMPLING_DOWN_FACTOR (100000) +#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) +#define MICRO_FREQUENCY_UP_THRESHOLD (85) +#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) +#define MIN_FREQUENCY_UP_THRESHOLD (11) +#define MAX_FREQUENCY_UP_THRESHOLD (100) +#define MIN_FREQUENCY_DOWN_DIFFERENTIAL (1) + +/* + * The polling frequency of this governor depends on the capability of + * the processor. Default polling frequency is 1000 times the transition + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling + * rate. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. + * All times here are in uS. + */ +#define MIN_SAMPLING_RATE_RATIO (2) + +static unsigned int min_sampling_rate; + +#define LATENCY_MULTIPLIER (1000) +#define MIN_LATENCY_MULTIPLIER (100) +#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) + +static void do_dbs_timer(struct work_struct *work); +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event); + +#ifdef _LIMIT_LCD_OFF_CPU_MAX_FREQ_ +#ifdef CONFIG_HAS_EARLYSUSPEND +static struct early_suspend cpufreq_gov_early_suspend; +static unsigned int cpufreq_gov_lcd_status; +#endif +#endif + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND +static +#endif +struct cpufreq_governor cpufreq_gov_intellidemand = { + .name = "intellidemand", + .governor = cpufreq_governor_dbs, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, +}; + +/* Sampling types */ +enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; + +struct cpu_dbs_info_s { + cputime64_t prev_cpu_idle; + cputime64_t prev_cpu_iowait; + cputime64_t prev_cpu_wall; + cputime64_t prev_cpu_nice; + struct cpufreq_policy *cur_policy; + struct delayed_work work; + struct cpufreq_frequency_table *freq_table; + unsigned int freq_lo; + unsigned int freq_lo_jiffies; + unsigned int freq_hi_jiffies; + unsigned int rate_mult; + int cpu; + unsigned int sample_type:1; + /* + * percpu mutex that serializes governor limit change with + * do_dbs_timer invocation. We do not want do_dbs_timer to run + * when user is changing the governor or limits. + */ + struct mutex timer_mutex; +}; +static DEFINE_PER_CPU(struct cpu_dbs_info_s, od_cpu_dbs_info); + +static unsigned int dbs_enable; /* number of CPUs using this policy */ + +/* + * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on + * different CPUs. It protects dbs_enable in governor start/stop. + */ +static DEFINE_MUTEX(dbs_mutex); + +static struct workqueue_struct *kintellidemand_wq; + +static struct dbs_tuners { + unsigned int sampling_rate; + unsigned int up_threshold; + unsigned int down_differential; + unsigned int ignore_nice; + unsigned int sampling_down_factor; + unsigned int powersave_bias; + unsigned int io_is_busy; +} dbs_tuners_ins = { + .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, + .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, + .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, + .ignore_nice = 0, + .powersave_bias = 0, +}; + +static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu, + cputime64_t *wall) +{ + u64 idle_time; + u64 cur_wall_time; + u64 busy_time; + + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + + busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; + + idle_time = cur_wall_time - busy_time; + if (wall) + *wall = jiffies_to_usecs(cur_wall_time); + + return jiffies_to_usecs(idle_time); +} + +static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) +{ + u64 idle_time = get_cpu_idle_time_us(cpu, wall); + + if (idle_time == -1ULL) + return get_cpu_idle_time_jiffy(cpu, wall); + + return idle_time; +} + +static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall) +{ + u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); + + if (iowait_time == -1ULL) + return 0; + + return iowait_time; +} + +/* + * Find right freq to be set now with powersave_bias on. + * Returns the freq_hi to be used right now and will set freq_hi_jiffies, + * freq_lo, and freq_lo_jiffies in percpu area for averaging freqs. + */ +static unsigned int powersave_bias_target(struct cpufreq_policy *policy, + unsigned int freq_next, + unsigned int relation) +{ + unsigned int freq_req, freq_reduc, freq_avg; + unsigned int freq_hi, freq_lo; + unsigned int index = 0; + unsigned int jiffies_total, jiffies_hi, jiffies_lo; + struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, + policy->cpu); + + if (!dbs_info->freq_table) { + dbs_info->freq_lo = 0; + dbs_info->freq_lo_jiffies = 0; + return freq_next; + } + + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_next, + relation, &index); + freq_req = dbs_info->freq_table[index].frequency; + freq_reduc = freq_req * dbs_tuners_ins.powersave_bias / 1000; + freq_avg = freq_req - freq_reduc; + + /* Find freq bounds for freq_avg in freq_table */ + index = 0; + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, + CPUFREQ_RELATION_H, &index); + freq_lo = dbs_info->freq_table[index].frequency; + index = 0; + cpufreq_frequency_table_target(policy, dbs_info->freq_table, freq_avg, + CPUFREQ_RELATION_L, &index); + freq_hi = dbs_info->freq_table[index].frequency; + + /* Find out how long we have to be in hi and lo freqs */ + if (freq_hi == freq_lo) { + dbs_info->freq_lo = 0; + dbs_info->freq_lo_jiffies = 0; + return freq_lo; + } + jiffies_total = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + jiffies_hi = (freq_avg - freq_lo) * jiffies_total; + jiffies_hi += ((freq_hi - freq_lo) / 2); + jiffies_hi /= (freq_hi - freq_lo); + jiffies_lo = jiffies_total - jiffies_hi; + dbs_info->freq_lo = freq_lo; + dbs_info->freq_lo_jiffies = jiffies_lo; + dbs_info->freq_hi_jiffies = jiffies_hi; + return freq_hi; +} + +static void intellidemand_powersave_bias_init_cpu(int cpu) +{ + struct cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); + dbs_info->freq_table = cpufreq_frequency_get_table(cpu); + dbs_info->freq_lo = 0; +} + +static void intellidemand_powersave_bias_init(void) +{ + int i; + for_each_online_cpu(i) { + intellidemand_powersave_bias_init_cpu(i); + } +} + +/************************** sysfs interface ************************/ + +static ssize_t show_sampling_rate_max(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + printk_once(KERN_INFO "CPUFREQ: intellidemand sampling_rate_max " + "sysfs file is deprecated - used by: %s\n", current->comm); + return sprintf(buf, "%u\n", -1U); +} + +static ssize_t show_sampling_rate_min(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", min_sampling_rate); +} + +define_one_global_ro(sampling_rate_max); +define_one_global_ro(sampling_rate_min); + +/* cpufreq_intellidemand Governor Tunables */ +#define show_one(file_name, object) \ +static ssize_t show_##file_name \ +(struct kobject *kobj, struct attribute *attr, char *buf) \ +{ \ + return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ +} +show_one(sampling_rate, sampling_rate); +show_one(io_is_busy, io_is_busy); +show_one(up_threshold, up_threshold); +show_one(down_differential, down_differential); +show_one(sampling_down_factor, sampling_down_factor); +show_one(ignore_nice_load, ignore_nice); +show_one(powersave_bias, powersave_bias); + +static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + mutex_lock(&dbs_mutex); + dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate); + mutex_unlock(&dbs_mutex); + + return count; +} + +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + mutex_lock(&dbs_mutex); + dbs_tuners_ins.io_is_busy = !!input; + mutex_unlock(&dbs_mutex); + + return count; +} + +static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_FREQUENCY_UP_THRESHOLD || + input < MIN_FREQUENCY_UP_THRESHOLD) { + return -EINVAL; + } + + mutex_lock(&dbs_mutex); + dbs_tuners_ins.up_threshold = input; + mutex_unlock(&dbs_mutex); + + return count; +} +static ssize_t store_sampling_down_factor(struct kobject *a, + struct attribute *b, const char *buf, size_t count) +{ + unsigned int input, j; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) + return -EINVAL; + mutex_lock(&dbs_mutex); + dbs_tuners_ins.sampling_down_factor = input; + + /* Reset down sampling multiplier in case it was active */ + for_each_online_cpu(j) { + struct cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(od_cpu_dbs_info, j); + dbs_info->rate_mult = 1; + } + mutex_unlock(&dbs_mutex); + + return count; +} + +static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + + unsigned int j; + + ret = sscanf(buf, "%u", &input); + if (ret != 1) + return -EINVAL; + + if (input > 1) + input = 1; + + if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */ + return count; + } + dbs_tuners_ins.ignore_nice = input; + + /* we need to re-evaluate prev_cpu_idle */ + for_each_online_cpu(j) { + struct cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(od_cpu_dbs_info, j); + dbs_info->prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->prev_cpu_wall); + if (dbs_tuners_ins.ignore_nice) + dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + + } + return count; +} + +static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + if (ret != 1) + return -EINVAL; + + if (input > 1000) + input = 1000; + + mutex_lock(&dbs_mutex); + dbs_tuners_ins.powersave_bias = input; + intellidemand_powersave_bias_init(); + mutex_unlock(&dbs_mutex); + + return count; +} + +static ssize_t store_down_differential(struct kobject *a, struct attribute *b, + const char *buf, size_t count) +{ + unsigned int input; + int ret; + ret = sscanf(buf, "%u", &input); + + mutex_lock(&dbs_mutex); + if (ret != 1 || input >= dbs_tuners_ins.up_threshold || + input < MIN_FREQUENCY_DOWN_DIFFERENTIAL) { + mutex_unlock(&dbs_mutex); + return -EINVAL; + } + + dbs_tuners_ins.down_differential = input; + mutex_unlock(&dbs_mutex); + + return count; +} +define_one_global_rw(sampling_rate); +define_one_global_rw(io_is_busy); +define_one_global_rw(up_threshold); +define_one_global_rw(down_differential); +define_one_global_rw(sampling_down_factor); +define_one_global_rw(ignore_nice_load); +define_one_global_rw(powersave_bias); +#ifdef CONFIG_SEC_LIMIT_MAX_FREQ // limit max freq +define_one_global_rw(lmf_temp); +define_one_global_rw(lmf_browser); +define_one_global_rw(lmf_active_load); +define_one_global_rw(lmf_inactive_load); +#endif +static struct attribute *dbs_attributes[] = { + &sampling_rate_max.attr, + &sampling_rate_min.attr, + &sampling_rate.attr, + &up_threshold.attr, + &down_differential.attr, + &sampling_down_factor.attr, + &ignore_nice_load.attr, + &powersave_bias.attr, + &io_is_busy.attr, +#ifdef CONFIG_SEC_LIMIT_MAX_FREQ // limit max freq + &lmf_temp.attr, + &lmf_browser.attr, + &lmf_active_load.attr, + &lmf_inactive_load.attr, +#endif + NULL +}; + +static struct attribute_group dbs_attr_group = { + .attrs = dbs_attributes, + .name = "intellidemand", +}; + +/************************** sysfs end ************************/ + +static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) +{ + if (dbs_tuners_ins.powersave_bias) + freq = powersave_bias_target(p, freq, CPUFREQ_RELATION_H); + else if (p->cur == p->max) + return; + + __cpufreq_driver_target(p, freq, dbs_tuners_ins.powersave_bias ? + CPUFREQ_RELATION_L : CPUFREQ_RELATION_H); +} + +static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) +{ + unsigned int max_load_freq; + + struct cpufreq_policy *policy; + unsigned int j; + + this_dbs_info->freq_lo = 0; + policy = this_dbs_info->cur_policy; + + /* + * Every sampling_rate, we check, if current idle time is less + * than 20% (default), then we try to increase frequency + * Every sampling_rate, we look for a the lowest + * frequency which can sustain the load while keeping idle time over + * 30%. If such a frequency exist, we try to decrease to this frequency. + * + * Any frequency increase takes it to the maximum frequency. + * Frequency reduction happens at minimum steps of + * 5% (default) of current frequency + */ + + /* Get Absolute Load - in terms of freq */ + max_load_freq = 0; + + for_each_cpu(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; + unsigned int idle_time, wall_time, iowait_time; + unsigned int load, load_freq; + int freq_avg; + + j_dbs_info = &per_cpu(od_cpu_dbs_info, j); + + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); + cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); + + wall_time = (unsigned int) + (cur_wall_time - j_dbs_info->prev_cpu_wall); + j_dbs_info->prev_cpu_wall = cur_wall_time; + + idle_time = (unsigned int) + (cur_idle_time - j_dbs_info->prev_cpu_idle); + j_dbs_info->prev_cpu_idle = cur_idle_time; + + iowait_time = (unsigned int) + (cur_iowait_time - j_dbs_info->prev_cpu_iowait); + j_dbs_info->prev_cpu_iowait = cur_iowait_time; + + if (dbs_tuners_ins.ignore_nice) { + u64 cur_nice; + unsigned long cur_nice_jiffies; + + cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] - + j_dbs_info->prev_cpu_nice; + /* + * Assumption: nice time between sampling periods will + * be less than 2^32 jiffies for 32 bit sys + */ + cur_nice_jiffies = (unsigned long) + cputime64_to_jiffies64(cur_nice); + + j_dbs_info->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + idle_time += jiffies_to_usecs(cur_nice_jiffies); + } + /* + * For the purpose of ondemand, waiting for disk IO is an + * indication that you're performance critical, and not that + * the system is actually idle. So subtract the iowait time + * from the cpu idle time. + */ + + if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time) + idle_time -= iowait_time; + + if (unlikely(!wall_time || wall_time < idle_time)) + continue; + + load = 100 * (wall_time - idle_time) / wall_time; + + freq_avg = __cpufreq_driver_getavg(policy, j); + if (freq_avg <= 0) + freq_avg = policy->cur; + + load_freq = load * freq_avg; + if (load_freq > max_load_freq) + max_load_freq = load_freq; + } + + /* Check for frequency increase */ + if (max_load_freq > dbs_tuners_ins.up_threshold * policy->cur) { + +/* In case of increase to max freq., freq. scales by 2 step for reducing the current consumption*/ +#ifdef _LIMIT_LCD_OFF_CPU_MAX_FREQ_ + if(!cpufreq_gov_lcd_status) { + if (policy->cur < policy->max) { + if (policy->cur < 400000) dbs_freq_increase(policy, 800000); + else if (policy->cur < 800000) dbs_freq_increase(policy, 1000000); + else { + this_dbs_info->rate_mult = dbs_tuners_ins.sampling_down_factor; + dbs_freq_increase(policy, policy->max); + } + } + return; + } else +#endif + /* If switching to max speed, apply sampling_down_factor */ + if (policy->cur < policy->max) + this_dbs_info->rate_mult = + dbs_tuners_ins.sampling_down_factor; + dbs_freq_increase(policy, policy->max); + return; + } + + /* Check for frequency decrease */ + /* if we cannot reduce the frequency anymore, break out early */ + if (policy->cur == policy->min) + return; + + /* + * The optimal frequency is the frequency that is the lowest that + * can support the current CPU usage without triggering the up + * policy. To be safe, we focus 10 points under the threshold. + */ + if (max_load_freq < + (dbs_tuners_ins.up_threshold - dbs_tuners_ins.down_differential) * + policy->cur) { + unsigned int freq_next; + freq_next = max_load_freq / + (dbs_tuners_ins.up_threshold - + dbs_tuners_ins.down_differential); + + /* No longer fully busy, reset rate_mult */ + this_dbs_info->rate_mult = 1; + + if (freq_next < policy->min) + freq_next = policy->min; + + if (!dbs_tuners_ins.powersave_bias) { + __cpufreq_driver_target(policy, freq_next, + CPUFREQ_RELATION_L); + } else { + int freq = powersave_bias_target(policy, freq_next, + CPUFREQ_RELATION_L); + __cpufreq_driver_target(policy, freq, + CPUFREQ_RELATION_L); + } + } +} + +static void do_dbs_timer(struct work_struct *work) +{ + struct cpu_dbs_info_s *dbs_info = + container_of(work, struct cpu_dbs_info_s, work.work); + unsigned int cpu = dbs_info->cpu; + int sample_type = dbs_info->sample_type; + + /* We want all CPUs to do sampling nearly on same jiffy */ + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate + * dbs_info->rate_mult); + +#if 0 + /* Don't care too much about synchronizing the workqueue in both cpus */ + if (num_online_cpus() > 1) + delay -= jiffies % delay; +#endif + + mutex_lock(&dbs_info->timer_mutex); + + /* Common NORMAL_SAMPLE setup */ + dbs_info->sample_type = DBS_NORMAL_SAMPLE; + if (!dbs_tuners_ins.powersave_bias || + sample_type == DBS_NORMAL_SAMPLE) { + dbs_check_cpu(dbs_info); + if (dbs_info->freq_lo) { + /* Setup timer for SUB_SAMPLE */ + dbs_info->sample_type = DBS_SUB_SAMPLE; + delay = dbs_info->freq_hi_jiffies; + } + } else { + __cpufreq_driver_target(dbs_info->cur_policy, + dbs_info->freq_lo, CPUFREQ_RELATION_H); + } + queue_delayed_work_on(cpu, kintellidemand_wq, &dbs_info->work, delay); + mutex_unlock(&dbs_info->timer_mutex); +} + +static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) +{ + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + + dbs_info->sample_type = DBS_NORMAL_SAMPLE; + INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); + queue_delayed_work_on(dbs_info->cpu, kintellidemand_wq, &dbs_info->work, + delay); +} + +static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) +{ + cancel_delayed_work_sync(&dbs_info->work); +} + +/* + * Not all CPUs want IO time to be accounted as busy; this dependson how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (androidlcom) calis this is also not true for ARM. + * Because of this, whitelist specific known (series) of CPUs by default, and + * leave all others up to the user. + */ +static int should_io_be_busy(void) +{ +#if defined(CONFIG_X86) + /* + * For Intel, Core 2 (model 15) andl later have an efficient idle. + */ + if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && + boot_cpu_data.x86 == 6 && + boot_cpu_data.x86_model >= 15) + return 1; +#endif +#if defined(CONFIG_ARM) + return 1; +#endif + return 0; +} + +static int cpufreq_governor_dbs(struct cpufreq_policy *policy, + unsigned int event) +{ + unsigned int cpu = policy->cpu; + struct cpu_dbs_info_s *this_dbs_info; + unsigned int j; + int rc; + + this_dbs_info = &per_cpu(od_cpu_dbs_info, cpu); + + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || (!policy->cur)) + return -EINVAL; + //per_cpu(cpu_load, cpu) = 0; + mutex_lock(&dbs_mutex); + + dbs_enable++; + for_each_cpu(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + j_dbs_info = &per_cpu(od_cpu_dbs_info, j); + j_dbs_info->cur_policy = policy; + + j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j, + &j_dbs_info->prev_cpu_wall); + if (dbs_tuners_ins.ignore_nice) + j_dbs_info->prev_cpu_nice = + kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + } + this_dbs_info->cpu = cpu; + this_dbs_info->rate_mult = 1; + intellidemand_powersave_bias_init_cpu(cpu); + /* + * Start the timerschedule work, when this governor + * is used for first time + */ + if (dbs_enable == 1) { + unsigned int latency; + + rc = sysfs_create_group(cpufreq_global_kobject, + &dbs_attr_group); + if (rc) { + mutex_unlock(&dbs_mutex); + return rc; + } + + /* policy latency is in nS. Convert it to uS first */ + latency = policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; + /* Bring kernel and HW constraints together */ + min_sampling_rate = max(min_sampling_rate, + MIN_LATENCY_MULTIPLIER * latency); + dbs_tuners_ins.sampling_rate = + max(min_sampling_rate, + latency * LATENCY_MULTIPLIER); + dbs_tuners_ins.io_is_busy = should_io_be_busy(); + } + mutex_unlock(&dbs_mutex); + + mutex_init(&this_dbs_info->timer_mutex); + dbs_timer_init(this_dbs_info); + break; + + case CPUFREQ_GOV_STOP: + dbs_timer_exit(this_dbs_info); + + mutex_lock(&dbs_mutex); + mutex_destroy(&this_dbs_info->timer_mutex); + dbs_enable--; + mutex_unlock(&dbs_mutex); + if (!dbs_enable) + sysfs_remove_group(cpufreq_global_kobject, + &dbs_attr_group); + + break; + + case CPUFREQ_GOV_LIMITS: + mutex_lock(&this_dbs_info->timer_mutex); + if (policy->max < this_dbs_info->cur_policy->cur) + __cpufreq_driver_target(this_dbs_info->cur_policy, + policy->max, CPUFREQ_RELATION_H); + else if (policy->min > this_dbs_info->cur_policy->cur) + __cpufreq_driver_target(this_dbs_info->cur_policy, + policy->min, CPUFREQ_RELATION_L); + mutex_unlock(&this_dbs_info->timer_mutex); + break; + } + return 0; +} + +#ifdef _LIMIT_LCD_OFF_CPU_MAX_FREQ_ +#ifdef CONFIG_HAS_EARLYSUSPEND +static void cpufreq_gov_suspend(struct early_suspend *h) +{ + cpufreq_gov_lcd_status = 0; + + pr_info("%s : cpufreq_gov_lcd_status %d\n", __func__, cpufreq_gov_lcd_status); +} + +static void cpufreq_gov_resume(struct early_suspend *h) +{ + cpufreq_gov_lcd_status = 1; + + pr_info("%s : cpufreq_gov_lcd_status %d\n", __func__, cpufreq_gov_lcd_status); +} +#endif +#endif + +static int __init cpufreq_gov_dbs_init(void) +{ + int err; + cputime64_t wall; + u64 idle_time; + int cpu = get_cpu(); + + idle_time = get_cpu_idle_time_us(cpu, &wall); + put_cpu(); + if (idle_time != -1ULL) { + /* Idle micro accounting is supported. Use finer thresholds */ + dbs_tuners_ins.up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; + dbs_tuners_ins.down_differential = + MICRO_FREQUENCY_DOWN_DIFFERENTIAL; + /* + * In no_hz/micro accounting case we set the minimum frequency + * not depending on HZ, but fixed (very low). The deferred + * timer might skip some samples if idle/sleeping as needed. + */ + min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; + } else { + /* For correct statistics, we need 10 ticks for each measure */ + min_sampling_rate = + MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(1); + } + + kintellidemand_wq = create_workqueue("kintellidemand"); + if (!kintellidemand_wq) { + printk(KERN_ERR "Creation of kintellidemand failed\n"); + return -EFAULT; + } + err = cpufreq_register_governor(&cpufreq_gov_intellidemand); + if (err) + destroy_workqueue(kintellidemand_wq); + +#ifdef _LIMIT_LCD_OFF_CPU_MAX_FREQ_ +#ifdef CONFIG_HAS_EARLYSUSPEND + cpufreq_gov_lcd_status = 1; + + cpufreq_gov_early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1; + + cpufreq_gov_early_suspend.suspend = cpufreq_gov_suspend; + cpufreq_gov_early_suspend.resume = cpufreq_gov_resume; + register_early_suspend(&cpufreq_gov_early_suspend); +#endif +#endif + + return err; +} + +static void __exit cpufreq_gov_dbs_exit(void) +{ + cpufreq_unregister_governor(&cpufreq_gov_intellidemand); + destroy_workqueue(kintellidemand_wq); +} + + +MODULE_AUTHOR("Venkatesh Pallipadi "); +MODULE_AUTHOR("Alexey Starikovskiy "); +MODULE_DESCRIPTION("'cpufreq_intellidemand' - A dynamic cpufreq governor for " + "Low Latency Frequency Transition capable processors"); +MODULE_LICENSE("GPL"); + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND +fs_initcall(cpufreq_gov_dbs_init); +#else +module_init(cpufreq_gov_dbs_init); +#endif +module_exit(cpufreq_gov_dbs_exit); + + diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 0bf6aa3d546..1dcdf81350f 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -27,6 +27,7 @@ #include #include #include +#include /* * dbs is used in this file as a shortform for demandbased switching @@ -1131,6 +1132,9 @@ static void dbs_input_event(struct input_handle *handle, unsigned int type, /* nothing to do */ return; } + + if (throttled_bin > 0) + return; for_each_online_cpu(i) queue_work_on(i, dbs_wq, &per_cpu(dbs_refresh_work, i)); @@ -1174,7 +1178,28 @@ static void dbs_input_disconnect(struct input_handle *handle) } static const struct input_device_id dbs_ids[] = { - { .driver_info = 1 }, + /* multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, + /* touchpad */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, + }, + /* Keypad */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT, + .evbit = { BIT_MASK(EV_KEY) }, + }, { }, }; diff --git a/drivers/cpufreq/cpufreq_smartmax.c b/drivers/cpufreq/cpufreq_smartmax.c new file mode 100644 index 00000000000..e13aae05695 --- /dev/null +++ b/drivers/cpufreq/cpufreq_smartmax.c @@ -0,0 +1,1478 @@ +/* + * drivers/cpufreq/cpufreq_smartmax.c + * + * Copyright (C) 2013 maxwen + * + * 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. + * + * Author: maxwen + * + * Based on the ondemand and smartassV2 governor + * + * ondemand: + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * + * smartassV2: + * Author: Erasmux + * + * For a general overview of CPU governors see the relavent part in + * Documentation/cpu-freq/governors.txt + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA +extern int tegra_input_boost (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); +#endif + +/******************** Tunable parameters: ********************/ + +/* + * The "ideal" frequency to use. The governor will ramp up faster + * towards the ideal frequency and slower after it has passed it. Similarly, + * lowering the frequency towards the ideal frequency is faster than below it. + */ + + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_ENRC2B +#define DEFAULT_SUSPEND_IDEAL_FREQ 475000 +#define DEFAULT_AWAKE_IDEAL_FREQ 475000 +#define DEFAULT_RAMP_UP_STEP 300000 +#define DEFAULT_RAMP_DOWN_STEP 150000 +#define DEFAULT_MAX_CPU_LOAD 80 +#define DEFAULT_MIN_CPU_LOAD 50 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +// default to 3 * sampling_rate +#define DEFAULT_INPUT_BOOST_DURATION 90000 +#define DEFAULT_TOUCH_POKE_FREQ 910000 +#define DEFAULT_BOOST_FREQ 910000 +/* + * from cpufreq_wheatley.c + * Not all CPUs want IO time to be accounted as busy; this dependson how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (androidlcom) calis this is also not true for ARM. + */ +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_PRIMOU +#define DEFAULT_SUSPEND_IDEAL_FREQ 368000 +#define DEFAULT_AWAKE_IDEAL_FREQ 806000 +#define DEFAULT_RAMP_UP_STEP 200000 +#define DEFAULT_RAMP_DOWN_STEP 200000 +#define DEFAULT_MAX_CPU_LOAD 60 +#define DEFAULT_MIN_CPU_LOAD 30 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +#define DEFAULT_INPUT_BOOST_DURATION 90000 +#define DEFAULT_TOUCH_POKE_FREQ 1200000 +#define DEFAULT_BOOST_FREQ 1200000 +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_M7 +#define DEFAULT_SUSPEND_IDEAL_FREQ 594000 +#define DEFAULT_AWAKE_IDEAL_FREQ 1026000 +#define DEFAULT_RAMP_UP_STEP 200000 +#define DEFAULT_RAMP_DOWN_STEP 200000 +#define DEFAULT_MAX_CPU_LOAD 55 +#define DEFAULT_MIN_CPU_LOAD 5 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +#define DEFAULT_INPUT_BOOST_DURATION 150000 +#define DEFAULT_TOUCH_POKE_FREQ 1512000 +#define DEFAULT_BOOST_FREQ 1512000 +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_FIND5 +#define DEFAULT_SUSPEND_IDEAL_FREQ 384000 +#define DEFAULT_AWAKE_IDEAL_FREQ 702000 +#define DEFAULT_RAMP_UP_STEP 300000 +#define DEFAULT_RAMP_DOWN_STEP 200000 +#define DEFAULT_MAX_CPU_LOAD 70 +#define DEFAULT_MIN_CPU_LOAD 40 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +#define DEFAULT_INPUT_BOOST_DURATION 1200000 +#define DEFAULT_TOUCH_POKE_FREQ 1350000 +#define DEFAULT_BOOST_FREQ 1350000 +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +static unsigned int suspend_ideal_freq; +static unsigned int awake_ideal_freq; +/* + * Freqeuncy delta when ramping up above the ideal freqeuncy. + * Zero disables and causes to always jump straight to max frequency. + * When below the ideal freqeuncy we always ramp up to the ideal freq. + */ +static unsigned int ramp_up_step; + +/* + * Freqeuncy delta when ramping down below the ideal freqeuncy. + * Zero disables and will calculate ramp down according to load heuristic. + * When above the ideal freqeuncy we always ramp down to the ideal freq. + */ +static unsigned int ramp_down_step; + +/* + * CPU freq will be increased if measured load > max_cpu_load; + */ +static unsigned int max_cpu_load; + +/* + * CPU freq will be decreased if measured load < min_cpu_load; + */ +static unsigned int min_cpu_load; + +/* + * The minimum amount of time in usecs to spend at a frequency before we can ramp up. + * Notice we ignore this when we are below the ideal frequency. + */ +static unsigned int up_rate; + +/* + * The minimum amount of time in usecs to spend at a frequency before we can ramp down. + * Notice we ignore this when we are above the ideal frequency. + */ +static unsigned int down_rate; + +/* in usecs */ +static unsigned int sampling_rate; + +/* in usecs */ +static unsigned int input_boost_duration; + +static unsigned int touch_poke_freq; +static bool touch_poke = true; + +/* + * should ramp_up steps during boost be possible + */ +static bool ramp_up_during_boost = true; + +/* + * external boost interface - boost if duration is written + * to sysfs for boost_duration + */ +static unsigned int boost_freq; +static bool boost = true; + +/* in usecs */ +static unsigned int boost_duration = 0; + +/* Consider IO as busy */ +static unsigned int io_is_busy; + +static unsigned int ignore_nice; + +/*************** End of tunables ***************/ + +static unsigned int dbs_enable; /* number of CPUs using this policy */ + +static void do_dbs_timer(struct work_struct *work); + +struct smartmax_info_s { + struct cpufreq_policy *cur_policy; + struct cpufreq_frequency_table *freq_table; + struct delayed_work work; + u64 prev_cpu_idle; + u64 prev_cpu_iowait; + u64 prev_cpu_wall; + u64 prev_cpu_nice; + u64 freq_change_time; + unsigned int cur_cpu_load; + unsigned int old_freq; + int ramp_dir; + unsigned int ideal_speed; + unsigned int cpu; + struct mutex timer_mutex; +}; +static DEFINE_PER_CPU(struct smartmax_info_s, smartmax_info); + +#define dprintk(flag,msg...) do { \ + if (debug_mask & flag) pr_info("[smartmax]" ":" msg); \ + } while (0) + +enum { + SMARTMAX_DEBUG_JUMPS = 1, + SMARTMAX_DEBUG_LOAD = 2, + SMARTMAX_DEBUG_ALG = 4, + SMARTMAX_DEBUG_BOOST = 8, + SMARTMAX_DEBUG_INPUT = 16, + SMARTMAX_DEBUG_SUSPEND = 32 +}; + +/* + * Combination of the above debug flags. + */ +//static unsigned long debug_mask = SMARTMAX_DEBUG_LOAD|SMARTMAX_DEBUG_JUMPS|SMARTMAX_DEBUG_ALG|SMARTMAX_DEBUG_BOOST|SMARTMAX_DEBUG_INPUT|SMARTMAX_DEBUG_SUSPEND; +static unsigned long debug_mask; + +#define SMARTMAX_STAT 0 +#if SMARTMAX_STAT +static u64 timer_stat[4] = {0, 0, 0, 0}; +#endif + +/* + * dbs_mutex protects dbs_enable in governor start/stop. + */ +static DEFINE_MUTEX(dbs_mutex); +static struct workqueue_struct *smartmax_wq; + +static bool boost_task_alive = false; +static struct task_struct *boost_task; +static u64 boost_end_time = 0ULL; +static unsigned int cur_boost_freq = 0; +static unsigned int cur_boost_duration = 0; +static bool boost_running = false; +static unsigned int ideal_freq; +static bool is_suspended = false; +static unsigned int min_sampling_rate; + +#define LATENCY_MULTIPLIER (1000) +#define MIN_LATENCY_MULTIPLIER (100) +#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) + +/* + * The polling frequency of this governor depends on the capability of + * the processor. Default polling frequency is 1000 times the transition + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling + * rate. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. + * All times here are in uS. + */ +#define MIN_SAMPLING_RATE_RATIO (2) +#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) + +static int cpufreq_governor_smartmax(struct cpufreq_policy *policy, + unsigned int event); + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX +static +#endif +struct cpufreq_governor cpufreq_gov_smartmax = { + .name = "smartmax", + .governor = cpufreq_governor_smartmax, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, + }; + +static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) { + + u64 idle_time; + u64 cur_wall_time; + u64 busy_time; + + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + busy_time = kstat_cpu(cpu).cpustat.user; + busy_time += kstat_cpu(cpu).cpustat.system; + busy_time += kstat_cpu(cpu).cpustat.irq; + busy_time += kstat_cpu(cpu).cpustat.softirq; + busy_time += kstat_cpu(cpu).cpustat.steal; + busy_time += kstat_cpu(cpu).cpustat.nice; +#else + busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; +#endif + + idle_time = cur_wall_time - busy_time; + if (wall) + *wall = jiffies_to_usecs(cur_wall_time); + + return jiffies_to_usecs(idle_time); +} + +static inline u64 get_cpu_idle_time(unsigned int cpu, u64 *wall) +{ + u64 idle_time = get_cpu_idle_time_us(cpu, NULL); + + if (idle_time == -1ULL) + return get_cpu_idle_time_jiffy(cpu, wall); + else + idle_time += get_cpu_iowait_time_us(cpu, wall); + + return idle_time; +} + +static inline u64 get_cpu_iowait_time(unsigned int cpu, u64 *wall) { + u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); + + if (iowait_time == -1ULL) + return 0; + + return iowait_time; +} + +inline static void smartmax_update_min_max( + struct smartmax_info_s *this_smartmax, struct cpufreq_policy *policy) { + this_smartmax->ideal_speed = // ideal_freq; but make sure it obeys the policy min/max + policy->min < ideal_freq ? + (ideal_freq < policy->max ? ideal_freq : policy->max) : + policy->min; + +} + +inline static void smartmax_update_min_max_allcpus(void) { + unsigned int cpu; + + for_each_online_cpu(cpu) + { + struct smartmax_info_s *this_smartmax = &per_cpu(smartmax_info, cpu); + if (this_smartmax->cur_policy){ + if (lock_policy_rwsem_write(cpu) < 0) + continue; + + smartmax_update_min_max(this_smartmax, this_smartmax->cur_policy); + + unlock_policy_rwsem_write(cpu); + } + } +} + +inline static unsigned int validate_freq(struct cpufreq_policy *policy, + int freq) { + if (freq > (int) policy->max) + return policy->max; + if (freq < (int) policy->min) + return policy->min; + return freq; +} + +/* We want all CPUs to do sampling nearly on same jiffy */ +static inline unsigned int get_timer_delay(void) { + unsigned int delay = usecs_to_jiffies(sampling_rate); + + if (num_online_cpus() > 1) + delay -= jiffies % delay; + return delay; +} + +static inline void dbs_timer_init(struct smartmax_info_s *this_smartmax) { + int delay = get_timer_delay(); + + INIT_DELAYED_WORK_DEFERRABLE(&this_smartmax->work, do_dbs_timer); + schedule_delayed_work_on(this_smartmax->cpu, &this_smartmax->work, delay); +} + +static inline void dbs_timer_exit(struct smartmax_info_s *this_smartmax) { + cancel_delayed_work_sync(&this_smartmax->work); +} + +inline static void target_freq(struct cpufreq_policy *policy, + struct smartmax_info_s *this_smartmax, int new_freq, int old_freq, + int prefered_relation) { + int index, target; + struct cpufreq_frequency_table *table = this_smartmax->freq_table; + unsigned int cpu = this_smartmax->cpu; + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s\n", old_freq, __func__); + + // apply policy limits - just to be sure + new_freq = validate_freq(policy, new_freq); + + if (!cpufreq_frequency_table_target(policy, table, new_freq, + prefered_relation, &index)) { + target = table[index].frequency; + if (target == old_freq) { + // if for example we are ramping up to *at most* current + ramp_up_step + // but there is no such frequency higher than the current, try also + // to ramp up to *at least* current + ramp_up_step. + if (new_freq > old_freq && prefered_relation == CPUFREQ_RELATION_H + && !cpufreq_frequency_table_target(policy, table, new_freq, + CPUFREQ_RELATION_L, &index)) + target = table[index].frequency; + // simlarly for ramping down: + else if (new_freq < old_freq + && prefered_relation == CPUFREQ_RELATION_L + && !cpufreq_frequency_table_target(policy, table, new_freq, + CPUFREQ_RELATION_H, &index)) + target = table[index].frequency; + } + + // no change + if (target == old_freq) + return; + } else { + dprintk(SMARTMAX_DEBUG_ALG, "frequency change failed\n"); + return; + } + + dprintk(SMARTMAX_DEBUG_JUMPS, "%d: jumping to %d (%d) cpu %d\n", old_freq, new_freq, target, cpu); + + __cpufreq_driver_target(policy, target, prefered_relation); + + // remember last time we changed frequency + this_smartmax->freq_change_time = ktime_to_us(ktime_get()); +} + +/* We use the same work function to sale up and down */ +static void cpufreq_smartmax_freq_change(struct smartmax_info_s *this_smartmax) { + unsigned int cpu; + unsigned int new_freq = 0; + unsigned int old_freq; + int ramp_dir; + struct cpufreq_policy *policy; + unsigned int relation = CPUFREQ_RELATION_L; + + ramp_dir = this_smartmax->ramp_dir; + old_freq = this_smartmax->old_freq; + policy = this_smartmax->cur_policy; + cpu = this_smartmax->cpu; + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s\n", old_freq, __func__); + + if (old_freq != policy->cur) { + // frequency was changed by someone else? + dprintk(SMARTMAX_DEBUG_ALG, "%d: frequency changed by 3rd party to %d\n", + old_freq, policy->cur); + new_freq = old_freq; + } else if (ramp_dir > 0 && nr_running() > 1) { + // ramp up logic: + if (old_freq < this_smartmax->ideal_speed) + new_freq = this_smartmax->ideal_speed; + else if (ramp_up_step) { + new_freq = old_freq + ramp_up_step; + relation = CPUFREQ_RELATION_H; + } else { + new_freq = policy->max; + relation = CPUFREQ_RELATION_H; + } + } else if (ramp_dir < 0) { + // ramp down logic: + if (old_freq > this_smartmax->ideal_speed) { + new_freq = this_smartmax->ideal_speed; + relation = CPUFREQ_RELATION_H; + } else if (ramp_down_step) + new_freq = old_freq - ramp_down_step; + else { + // Load heuristics: Adjust new_freq such that, assuming a linear + // scaling of load vs. frequency, the load in the new frequency + // will be max_cpu_load: + new_freq = old_freq * this_smartmax->cur_cpu_load / max_cpu_load; + if (new_freq > old_freq) // min_cpu_load > max_cpu_load ?! + new_freq = old_freq - 1; + } + } + + if (new_freq!=0){ + target_freq(policy, this_smartmax, new_freq, old_freq, relation); + } + + this_smartmax->ramp_dir = 0; +} + +static inline void cpufreq_smartmax_get_ramp_direction(struct smartmax_info_s *this_smartmax, u64 now) +{ + unsigned int cur_load = this_smartmax->cur_cpu_load; + unsigned int cur = this_smartmax->old_freq; + struct cpufreq_policy *policy = this_smartmax->cur_policy; + + // Scale up if load is above max or if there where no idle cycles since coming out of idle, + // additionally, if we are at or above the ideal_speed, verify we have been at this frequency + // for at least up_rate: + if (cur_load > max_cpu_load && cur < policy->max + && (cur < this_smartmax->ideal_speed + || (now - this_smartmax->freq_change_time) >= up_rate)) { + dprintk(SMARTMAX_DEBUG_ALG, + "%d: ramp up: load %d\n", cur, cur_load); + this_smartmax->ramp_dir = 1; + } + // Similarly for scale down: load should be below min and if we are at or below ideal + // frequency we require that we have been at this frequency for at least down_rate: + else if (cur_load < min_cpu_load && cur > policy->min + && (cur > this_smartmax->ideal_speed + || (now - this_smartmax->freq_change_time) >= down_rate)) { + dprintk(SMARTMAX_DEBUG_ALG, + "%d: ramp down: load %d\n", cur, cur_load); + this_smartmax->ramp_dir = -1; + } +} + +static void cpufreq_smartmax_timer(struct smartmax_info_s *this_smartmax) { + unsigned int cur; + struct cpufreq_policy *policy = this_smartmax->cur_policy; + u64 now = ktime_to_us(ktime_get()); + /* Extrapolated load of this CPU */ + unsigned int load_at_max_freq = 0; + unsigned int j = 0; + unsigned int cpu = this_smartmax->cpu; + +#if SMARTMAX_STAT + u64 diff = 0; + + if (timer_stat[cpu]) + diff = now - timer_stat[cpu]; + + timer_stat[cpu] = now; + printk(KERN_DEBUG "[smartmax]:cpu %d %lld\n", cpu, diff); +#endif + + cur = policy->cur; + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s cpu %d %lld\n", cur, __func__, cpu, now); + + for_each_cpu(j, policy->cpus) + { + struct smartmax_info_s *j_this_smartmax; + u64 cur_wall_time, cur_idle_time, cur_iowait_time; + unsigned int idle_time, wall_time, iowait_time; + unsigned int cur_load; + + j_this_smartmax = &per_cpu(smartmax_info, j); + + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); + cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); + + wall_time = cur_wall_time - j_this_smartmax->prev_cpu_wall; + j_this_smartmax->prev_cpu_wall = cur_wall_time; + + idle_time = cur_idle_time - j_this_smartmax->prev_cpu_idle; + j_this_smartmax->prev_cpu_idle = cur_idle_time; + + iowait_time = cur_iowait_time - j_this_smartmax->prev_cpu_iowait; + j_this_smartmax->prev_cpu_iowait = cur_iowait_time; + + if (ignore_nice) { + u64 cur_nice; + unsigned long cur_nice_jiffies; + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + cur_nice = kstat_cpu(j).cpustat.nice - j_this_smartmax->prev_cpu_nice; + cur_nice_jiffies = (unsigned long) cputime64_to_jiffies64(cur_nice); + + j_this_smartmax->prev_cpu_nice = kstat_cpu(j).cpustat.nice; +#else + cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] - j_this_smartmax->prev_cpu_nice; + cur_nice_jiffies = (unsigned long) cputime64_to_jiffies64(cur_nice); + + j_this_smartmax->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + +#endif + + idle_time += jiffies_to_usecs(cur_nice_jiffies); + } + + /* + * For the purpose of ondemand, waiting for disk IO is an + * indication that you're performance critical, and not that + * the system is actually idle. So subtract the iowait time + * from the cpu idle time. + */ + if (io_is_busy && idle_time >= iowait_time) + idle_time -= iowait_time; + + if (unlikely(!wall_time || wall_time < idle_time)) + continue; + + cur_load = 100 * (wall_time - idle_time) / wall_time; + j_this_smartmax->cur_cpu_load = cur_load; + } + + /* calculate the scaled load across CPU */ + load_at_max_freq = (this_smartmax->cur_cpu_load * policy->cur)/policy->cpuinfo.max_freq; + + cpufreq_notify_utilization(policy, load_at_max_freq); + + dprintk(SMARTMAX_DEBUG_LOAD, "%d: load %d\n", cpu, this_smartmax->cur_cpu_load); + + this_smartmax->old_freq = cur; + this_smartmax->ramp_dir = 0; + + cpufreq_smartmax_get_ramp_direction(this_smartmax, now); + + // no changes + if (this_smartmax->ramp_dir == 0) + return; + + // boost - but not block ramp up steps based on load if requested + if (boost_running){ + if (now < boost_end_time) { + dprintk(SMARTMAX_DEBUG_BOOST, "%d: cpu %d boost running %llu %llu\n", cur, cpu, now, boost_end_time); + + if (this_smartmax->ramp_dir == -1) + return; + else { + if (ramp_up_during_boost) + dprintk(SMARTMAX_DEBUG_BOOST, "%d: cpu %d boost running but ramp_up above boost freq requested\n", cur, cpu); + else + return; + } + } else + boost_running = false; + } + + cpufreq_smartmax_freq_change(this_smartmax); +} + +static void do_dbs_timer(struct work_struct *work) { + struct smartmax_info_s *this_smartmax = + container_of(work, struct smartmax_info_s, work.work); + unsigned int cpu = this_smartmax->cpu; + int delay = get_timer_delay(); + + mutex_lock(&this_smartmax->timer_mutex); + + cpufreq_smartmax_timer(this_smartmax); + + queue_delayed_work_on(cpu, smartmax_wq, &this_smartmax->work, delay); + mutex_unlock(&this_smartmax->timer_mutex); +} + +static void update_idle_time(bool online) { + int j = 0; + + for_each_possible_cpu(j) + { + struct smartmax_info_s *j_this_smartmax; + + if (online && !cpu_online(j)) { + continue; + } + j_this_smartmax = &per_cpu(smartmax_info, j); + + j_this_smartmax->prev_cpu_idle = get_cpu_idle_time(j, + &j_this_smartmax->prev_cpu_wall); + + if (ignore_nice) +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + j_this_smartmax->prev_cpu_nice = kstat_cpu(j) .cpustat.nice; +#else + j_this_smartmax->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; +#endif + } +} + +static ssize_t show_debug_mask(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%lu\n", debug_mask); +} + +static ssize_t store_debug_mask(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) + debug_mask = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_up_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", up_rate); +} + +static ssize_t store_up_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0 && input <= 100000000) + up_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_down_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", down_rate); +} + +static ssize_t store_down_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0 && input <= 100000000) + down_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_awake_ideal_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", awake_ideal_freq); +} + +static ssize_t store_awake_ideal_freq(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) { + awake_ideal_freq = input; + if (!is_suspended){ + ideal_freq = awake_ideal_freq; + smartmax_update_min_max_allcpus(); + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_suspend_ideal_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", suspend_ideal_freq); +} + +static ssize_t store_suspend_ideal_freq(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) { + suspend_ideal_freq = input; + if (is_suspended){ + ideal_freq = suspend_ideal_freq; + smartmax_update_min_max_allcpus(); + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_up_step(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", ramp_up_step); +} + +static ssize_t store_ramp_up_step(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) + ramp_up_step = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_down_step(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", ramp_down_step); +} + +static ssize_t store_ramp_down_step(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) + ramp_down_step = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_max_cpu_load(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", max_cpu_load); +} + +static ssize_t store_max_cpu_load(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 0 && input <= 100) + max_cpu_load = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_min_cpu_load(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", min_cpu_load); +} + +static ssize_t store_min_cpu_load(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 0 && input < 100) + min_cpu_load = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_sampling_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", sampling_rate); +} + +static ssize_t store_sampling_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= min_sampling_rate) + sampling_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_touch_poke_freq(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%u\n", touch_poke_freq); +} + +static ssize_t store_touch_poke_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0){ + touch_poke_freq = input; + + if (touch_poke_freq == 0) + touch_poke = false; + else + touch_poke = true; + } else + return -EINVAL; + return count; +} + +static ssize_t show_input_boost_duration(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%u\n", input_boost_duration); +} + +static ssize_t store_input_boost_duration(struct kobject *a, + struct attribute *b, const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 10000) + input_boost_duration = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_up_during_boost(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%d\n", ramp_up_during_boost); +} + +static ssize_t store_ramp_up_during_boost(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input == 0) + ramp_up_during_boost = false; + else if (input == 1) + ramp_up_during_boost = true; + else + return -EINVAL; + } else + return -EINVAL; + return count; +} + +static ssize_t show_boost_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", boost_freq); +} + +static ssize_t store_boost_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + boost_freq = input; + if (boost_freq == 0) + boost = false; + else + boost = true; + } else + return -EINVAL; + return count; +} + +static ssize_t show_boost_duration(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", boost_running); +} + +static ssize_t store_boost_duration(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 10000){ + boost_duration = input; + if (boost) { + // no need to bother if currently a boost is running anyway + if (boost_task_alive && boost_running) + return count; + + if (boost_task_alive) { + cur_boost_freq = boost_freq; + cur_boost_duration = boost_duration; + wake_up_process(boost_task); + } + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_io_is_busy(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", io_is_busy); +} + +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input > 1) + input = 1; + if (input == io_is_busy) { /* nothing to do */ + return count; + } + io_is_busy = input; + } else + return -EINVAL; + return count; +} + +static ssize_t show_ignore_nice(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", ignore_nice); +} + +static ssize_t store_ignore_nice(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input > 1) + input = 1; + if (input == ignore_nice) { /* nothing to do */ + return count; + } + ignore_nice = input; + /* we need to re-evaluate prev_cpu_idle */ + update_idle_time(true); + } else + return -EINVAL; + return count; +} + +static ssize_t show_min_sampling_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", min_sampling_rate); +} + +static ssize_t store_min_sampling_rate(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + return -EINVAL; +} + +#define define_global_rw_attr(_name) \ +static struct global_attr _name##_attr = \ + __ATTR(_name, 0644, show_##_name, store_##_name) + +#define define_global_ro_attr(_name) \ +static struct global_attr _name##_attr = \ + __ATTR(_name, 0444, show_##_name, store_##_name) + +define_global_rw_attr(debug_mask); +define_global_rw_attr(up_rate); +define_global_rw_attr(down_rate); +define_global_rw_attr(ramp_up_step); +define_global_rw_attr(ramp_down_step); +define_global_rw_attr(max_cpu_load); +define_global_rw_attr(min_cpu_load); +define_global_rw_attr(sampling_rate); +define_global_rw_attr(touch_poke_freq); +define_global_rw_attr(input_boost_duration); +define_global_rw_attr(boost_freq); +define_global_rw_attr(boost_duration); +define_global_rw_attr(io_is_busy); +define_global_rw_attr(ignore_nice); +define_global_rw_attr(ramp_up_during_boost); +define_global_rw_attr(awake_ideal_freq); +define_global_rw_attr(suspend_ideal_freq); +define_global_ro_attr(min_sampling_rate); + +static struct attribute * smartmax_attributes[] = { + &debug_mask_attr.attr, + &up_rate_attr.attr, + &down_rate_attr.attr, + &ramp_up_step_attr.attr, + &ramp_down_step_attr.attr, + &max_cpu_load_attr.attr, + &min_cpu_load_attr.attr, + &sampling_rate_attr.attr, + &touch_poke_freq_attr.attr, + &input_boost_duration_attr.attr, + &boost_freq_attr.attr, + &boost_duration_attr.attr, + &io_is_busy_attr.attr, + &ignore_nice_attr.attr, + &ramp_up_during_boost_attr.attr, + &awake_ideal_freq_attr.attr, + &suspend_ideal_freq_attr.attr, + &min_sampling_rate_attr.attr, + NULL , }; + +static struct attribute_group smartmax_attr_group = { + .attrs = smartmax_attributes, + .name = "smartmax", + }; + +static int cpufreq_smartmax_boost_task(void *data) { + struct smartmax_info_s *this_smartmax; + u64 now; + struct cpufreq_policy *policy; +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + unsigned int cpu; + bool start_boost = false; +#endif + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + + if (kthread_should_stop()) + break; + + set_current_state(TASK_RUNNING); + + if (boost_running) + continue; + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + /* on tegra there is only one cpu clock so we only need to boost cpu 0 + all others will run at the same speed */ + this_smartmax = &per_cpu(smartmax_info, 0); + if (!this_smartmax) + continue; + + policy = this_smartmax->cur_policy; + if (!policy) + continue; + + if (lock_policy_rwsem_write(0) < 0) + continue; + + tegra_input_boost(policy, cur_boost_freq, CPUFREQ_RELATION_H); + + this_smartmax->prev_cpu_idle = get_cpu_idle_time(0, + &this_smartmax->prev_cpu_wall); + + unlock_policy_rwsem_write(0); +#else + for_each_online_cpu(cpu){ + this_smartmax = &per_cpu(smartmax_info, cpu); + if (!this_smartmax) + continue; + + if (lock_policy_rwsem_write(cpu) < 0) + continue; + + policy = this_smartmax->cur_policy; + if (!policy){ + unlock_policy_rwsem_write(cpu); + continue; + } + + mutex_lock(&this_smartmax->timer_mutex); + + if (policy->cur < cur_boost_freq) { + start_boost = true; + dprintk(SMARTMAX_DEBUG_BOOST, "input boost cpu %d to %d\n", cpu, cur_boost_freq); + target_freq(policy, this_smartmax, cur_boost_freq, this_smartmax->old_freq, CPUFREQ_RELATION_H); + this_smartmax->prev_cpu_idle = get_cpu_idle_time(cpu, &this_smartmax->prev_cpu_wall); + } + mutex_unlock(&this_smartmax->timer_mutex); + + unlock_policy_rwsem_write(cpu); + } +#endif + +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + if (start_boost) { +#endif + + boost_running = true; + now = ktime_to_us(ktime_get()); + boost_end_time = now + (cur_boost_duration * num_online_cpus()); + dprintk(SMARTMAX_DEBUG_BOOST, "%s %llu %llu\n", __func__, now, boost_end_time); + +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + } +#endif + } + + pr_info("[smartmax]:" "%s boost_thread stopped\n", __func__); + return 0; +} + +#ifdef CONFIG_INPUT_MEDIATOR + +static void smartmax_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) { + if (touch_poke && type == EV_SYN && code == SYN_REPORT) { + // no need to bother if currently a boost is running anyway + if (boost_task_alive && boost_running) + return; + + if (boost_task_alive) { + cur_boost_freq = touch_poke_freq; + cur_boost_duration = input_boost_duration; + wake_up_process(boost_task); + } + } +} + +static struct input_mediator_handler smartmax_input_mediator_handler = { + .event = smartmax_input_event, + }; + +#else + +static void dbs_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) { + if (touch_poke && type == EV_SYN && code == SYN_REPORT) { + // no need to bother if currently a boost is running anyway + if (boost_task_alive && boost_running) + return; + + if (boost_task_alive) { + cur_boost_freq = touch_poke_freq; + cur_boost_duration = input_boost_duration; + wake_up_process(boost_task); + } + } +} + +static int dbs_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) { + struct input_handle *handle; + int error; + + pr_info("[smartmax]:" "%s input connect to %s\n", __func__, dev->name); + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "cpufreq"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + + return 0; + err1: input_unregister_handle(handle); + err2: kfree(handle); + pr_err("[smartmax]:" "%s faild to connect input handler %d\n", __func__, error); + return error; +} + +static void dbs_input_disconnect(struct input_handle *handle) { + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id dbs_ids[] = { +{ + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, /* multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, + }, /* touchpad */ + { }, +}; + +static struct input_handler dbs_input_handler = { + .event = dbs_input_event, + .connect = dbs_input_connect, + .disconnect = dbs_input_disconnect, + .name = "cpufreq_smartmax", + .id_table = dbs_ids, + }; +#endif + +static int cpufreq_governor_smartmax(struct cpufreq_policy *new_policy, + unsigned int event) { + unsigned int cpu = new_policy->cpu; + int rc; + struct smartmax_info_s *this_smartmax = &per_cpu(smartmax_info, cpu); + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + unsigned int latency; + + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || (!new_policy->cur)) + return -EINVAL; + + mutex_lock(&dbs_mutex); + + this_smartmax->cur_policy = new_policy; + this_smartmax->cpu = cpu; + + smartmax_update_min_max(this_smartmax,new_policy); + + this_smartmax->freq_table = cpufreq_frequency_get_table(cpu); + if (!this_smartmax->freq_table){ + mutex_unlock(&dbs_mutex); + return -EINVAL; + } + + update_idle_time(false); + + dbs_enable++; + + if (dbs_enable == 1) { + if (!boost_task_alive) { + boost_task = kthread_create ( + cpufreq_smartmax_boost_task, + NULL, + "smartmax_input_boost_task" + ); + + if (IS_ERR(boost_task)) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return PTR_ERR(boost_task); + } + + pr_info("[smartmax]:" "%s input boost task created\n", __func__); + sched_setscheduler_nocheck(boost_task, SCHED_FIFO, ¶m); + get_task_struct(boost_task); + boost_task_alive = true; + } +#ifdef CONFIG_INPUT_MEDIATOR + input_register_mediator_secondary(&smartmax_input_mediator_handler); +#else + rc = input_register_handler(&dbs_input_handler); + if (rc) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return rc; + } +#endif + rc = sysfs_create_group(cpufreq_global_kobject, + &smartmax_attr_group); + if (rc) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return rc; + } + /* policy latency is in nS. Convert it to uS first */ + latency = new_policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; + + /* Bring kernel and HW constraints together */ + min_sampling_rate = max(min_sampling_rate, MIN_LATENCY_MULTIPLIER * latency); + sampling_rate = max(min_sampling_rate, sampling_rate); + } + + mutex_unlock(&dbs_mutex); + dbs_timer_init(this_smartmax); + + break; + case CPUFREQ_GOV_LIMITS: + mutex_lock(&this_smartmax->timer_mutex); + smartmax_update_min_max(this_smartmax,new_policy); + + if (this_smartmax->cur_policy->cur > new_policy->max) { + dprintk(SMARTMAX_DEBUG_JUMPS,"CPUFREQ_GOV_LIMITS jumping to new max freq: %d\n",new_policy->max); + __cpufreq_driver_target(this_smartmax->cur_policy, + new_policy->max, CPUFREQ_RELATION_H); + } + else if (this_smartmax->cur_policy->cur < new_policy->min) { + dprintk(SMARTMAX_DEBUG_JUMPS,"CPUFREQ_GOV_LIMITS jumping to new min freq: %d\n",new_policy->min); + __cpufreq_driver_target(this_smartmax->cur_policy, + new_policy->min, CPUFREQ_RELATION_L); + } + mutex_unlock(&this_smartmax->timer_mutex); + break; + + case CPUFREQ_GOV_STOP: + dbs_timer_exit(this_smartmax); + + mutex_lock(&dbs_mutex); + this_smartmax->cur_policy = NULL; + dbs_enable--; + + if (!dbs_enable){ + if (boost_task_alive) + kthread_stop(boost_task); + + sysfs_remove_group(cpufreq_global_kobject, &smartmax_attr_group); +#ifdef CONFIG_INPUT_MEDIATOR + input_unregister_mediator_secondary(&smartmax_input_mediator_handler); +#else + input_unregister_handler(&dbs_input_handler); +#endif + } + + mutex_unlock(&dbs_mutex); + break; + } + + return 0; +} + +static int __init cpufreq_smartmax_init(void) { + unsigned int i; + struct smartmax_info_s *this_smartmax; + u64 wall; + u64 idle_time; + int cpu = get_cpu(); + + idle_time = get_cpu_idle_time_us(cpu, &wall); + put_cpu(); + if (idle_time != -1ULL) { + /* + * In no_hz/micro accounting case we set the minimum frequency + * not depending on HZ, but fixed (very low). The deferred + * timer might skip some samples if idle/sleeping as needed. + */ + min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; + } else { + /* For correct statistics, we need 10 ticks for each measure */ + min_sampling_rate = MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10); + } + + smartmax_wq = alloc_workqueue("smartmax_wq", WQ_HIGHPRI, 0); + if (!smartmax_wq) { + printk(KERN_ERR "Failed to create smartmax_wq workqueue\n"); + return -EFAULT; + } + + up_rate = DEFAULT_UP_RATE; + down_rate = DEFAULT_DOWN_RATE; + suspend_ideal_freq = DEFAULT_SUSPEND_IDEAL_FREQ; + awake_ideal_freq = DEFAULT_AWAKE_IDEAL_FREQ; + ideal_freq = awake_ideal_freq; + ramp_up_step = DEFAULT_RAMP_UP_STEP; + ramp_down_step = DEFAULT_RAMP_DOWN_STEP; + max_cpu_load = DEFAULT_MAX_CPU_LOAD; + min_cpu_load = DEFAULT_MIN_CPU_LOAD; + sampling_rate = DEFAULT_SAMPLING_RATE; + input_boost_duration = DEFAULT_INPUT_BOOST_DURATION; + io_is_busy = DEFAULT_IO_IS_BUSY; + ignore_nice = DEFAULT_IGNORE_NICE; + touch_poke_freq = DEFAULT_TOUCH_POKE_FREQ; + boost_freq = DEFAULT_BOOST_FREQ; + + /* Initalize per-cpu data: */ + for_each_possible_cpu(i) + { + this_smartmax = &per_cpu(smartmax_info, i); + this_smartmax->cur_policy = NULL; + this_smartmax->ramp_dir = 0; + this_smartmax->freq_change_time = 0; + this_smartmax->cur_cpu_load = 0; + mutex_init(&this_smartmax->timer_mutex); + } + + return cpufreq_register_governor(&cpufreq_gov_smartmax); +} + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX +fs_initcall(cpufreq_smartmax_init); +#else +module_init(cpufreq_smartmax_init); +#endif + +static void __exit cpufreq_smartmax_exit(void) { + unsigned int i; + struct smartmax_info_s *this_smartmax; + + cpufreq_unregister_governor(&cpufreq_gov_smartmax); + + for_each_possible_cpu(i) + { + this_smartmax = &per_cpu(smartmax_info, i); + mutex_destroy(&this_smartmax->timer_mutex); + } + destroy_workqueue(smartmax_wq); +} + +module_exit(cpufreq_smartmax_exit); + +MODULE_AUTHOR("maxwen"); +MODULE_DESCRIPTION("'cpufreq_smartmax' - A smart cpufreq governor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/cpufreq_smartmax_eps.c b/drivers/cpufreq/cpufreq_smartmax_eps.c new file mode 100644 index 00000000000..b8b6492a626 --- /dev/null +++ b/drivers/cpufreq/cpufreq_smartmax_eps.c @@ -0,0 +1,1464 @@ +/* + * drivers/cpufreq/cpufreq_smartmax.c + * + * Copyright (C) 2013 maxwen + * + * 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. + * + * Author: maxwen + * + * Based on the ondemand and smartassV2 governor + * + * ondemand: + * Copyright (C) 2001 Russell King + * (C) 2003 Venkatesh Pallipadi . + * Jun Nakajima + * + * smartassV2: + * Author: Erasmux + * + * For a general overview of CPU governors see the relavent part in + * Documentation/cpu-freq/governors.txt + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA +extern int tegra_input_boost (struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); +#endif + +/******************** Tunable parameters: ********************/ + +/* + * The "ideal" frequency to use. The governor will ramp up faster + * towards the ideal frequency and slower after it has passed it. Similarly, + * lowering the frequency towards the ideal frequency is faster than below it. + */ + + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_ENRC2B +#define DEFAULT_SUSPEND_IDEAL_FREQ 475000 +#define DEFAULT_AWAKE_IDEAL_FREQ 475000 +#define DEFAULT_RAMP_UP_STEP 300000 +#define DEFAULT_RAMP_DOWN_STEP 150000 +#define DEFAULT_MAX_CPU_LOAD 80 +#define DEFAULT_MIN_CPU_LOAD 50 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +// default to 3 * sampling_rate +#define DEFAULT_INPUT_BOOST_DURATION 90000 +#define DEFAULT_TOUCH_POKE_FREQ 910000 +#define DEFAULT_BOOST_FREQ 910000 +/* + * from cpufreq_wheatley.c + * Not all CPUs want IO time to be accounted as busy; this dependson how + * efficient idling at a higher frequency/voltage is. + * Pavel Machek says this is not so for various generations of AMD and old + * Intel systems. + * Mike Chan (androidlcom) calis this is also not true for ARM. + */ +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_PRIMOU +#define DEFAULT_SUSPEND_IDEAL_FREQ 368000 +#define DEFAULT_AWAKE_IDEAL_FREQ 806000 +#define DEFAULT_RAMP_UP_STEP 200000 +#define DEFAULT_RAMP_DOWN_STEP 200000 +#define DEFAULT_MAX_CPU_LOAD 60 +#define DEFAULT_MIN_CPU_LOAD 30 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +#define DEFAULT_INPUT_BOOST_DURATION 90000 +#define DEFAULT_TOUCH_POKE_FREQ 1200000 +#define DEFAULT_BOOST_FREQ 1200000 +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_M7 +#define DEFAULT_SUSPEND_IDEAL_FREQ 384000 +#define DEFAULT_AWAKE_IDEAL_FREQ 594000 +#define DEFAULT_RAMP_UP_STEP 200000 +#define DEFAULT_RAMP_DOWN_STEP 200000 +#define DEFAULT_MAX_CPU_LOAD 70 +#define DEFAULT_MIN_CPU_LOAD 40 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +#define DEFAULT_INPUT_BOOST_DURATION 90000 +#define DEFAULT_TOUCH_POKE_FREQ 1134000 +#define DEFAULT_BOOST_FREQ 1134000 +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_FIND5 +#define DEFAULT_SUSPEND_IDEAL_FREQ 384000 +#define DEFAULT_AWAKE_IDEAL_FREQ 594000 +#define DEFAULT_RAMP_UP_STEP 200000 +#define DEFAULT_RAMP_DOWN_STEP 200000 +#define DEFAULT_MAX_CPU_LOAD 90 +#define DEFAULT_MIN_CPU_LOAD 60 +#define DEFAULT_UP_RATE 30000 +#define DEFAULT_DOWN_RATE 60000 +#define DEFAULT_SAMPLING_RATE 30000 +#define DEFAULT_INPUT_BOOST_DURATION 900000 +#define DEFAULT_TOUCH_POKE_FREQ 1134000 +#define DEFAULT_BOOST_FREQ 1134000 +#define DEFAULT_IO_IS_BUSY 0 +#define DEFAULT_IGNORE_NICE 1 +#endif + +static unsigned int suspend_ideal_freq; +static unsigned int awake_ideal_freq; +/* + * Freqeuncy delta when ramping up above the ideal freqeuncy. + * Zero disables and causes to always jump straight to max frequency. + * When below the ideal freqeuncy we always ramp up to the ideal freq. + */ +static unsigned int ramp_up_step; + +/* + * Freqeuncy delta when ramping down below the ideal freqeuncy. + * Zero disables and will calculate ramp down according to load heuristic. + * When above the ideal freqeuncy we always ramp down to the ideal freq. + */ +static unsigned int ramp_down_step; + +/* + * CPU freq will be increased if measured load > max_cpu_load; + */ +static unsigned int max_cpu_load; + +/* + * CPU freq will be decreased if measured load < min_cpu_load; + */ +static unsigned int min_cpu_load; + +/* + * The minimum amount of time in usecs to spend at a frequency before we can ramp up. + * Notice we ignore this when we are below the ideal frequency. + */ +static unsigned int up_rate; + +/* + * The minimum amount of time in usecs to spend at a frequency before we can ramp down. + * Notice we ignore this when we are above the ideal frequency. + */ +static unsigned int down_rate; + +/* in usecs */ +static unsigned int sampling_rate; + +/* in usecs */ +static unsigned int input_boost_duration; + +static unsigned int touch_poke_freq; +static bool touch_poke = true; + +/* + * should ramp_up steps during boost be possible + */ +static bool ramp_up_during_boost = true; + +/* + * external boost interface - boost if duration is written + * to sysfs for boost_duration + */ +static unsigned int boost_freq; +static bool boost = true; + +/* in usecs */ +static unsigned int boost_duration = 0; + +/* Consider IO as busy */ +static unsigned int io_is_busy; + +static unsigned int ignore_nice; + +/*************** End of tunables ***************/ + +static unsigned int dbs_enable; /* number of CPUs using this policy */ + +static void do_dbs_timer(struct work_struct *work); + +struct smartmax_info_s { + struct cpufreq_policy *cur_policy; + struct cpufreq_frequency_table *freq_table; + struct delayed_work work; + u64 prev_cpu_idle; + u64 prev_cpu_iowait; + u64 prev_cpu_wall; + u64 prev_cpu_nice; + u64 freq_change_time; + unsigned int cur_cpu_load; + unsigned int old_freq; + int ramp_dir; + unsigned int ideal_speed; + unsigned int cpu; + struct mutex timer_mutex; +}; +static DEFINE_PER_CPU(struct smartmax_info_s, smartmax_info); + +#define dprintk(flag,msg...) do { \ + if (debug_mask & flag) pr_info("[smartmax]" ":" msg); \ + } while (0) + +enum { + SMARTMAX_DEBUG_JUMPS = 1, + SMARTMAX_DEBUG_LOAD = 2, + SMARTMAX_DEBUG_ALG = 4, + SMARTMAX_DEBUG_BOOST = 8, + SMARTMAX_DEBUG_INPUT = 16, + SMARTMAX_DEBUG_SUSPEND = 32 +}; + +/* + * Combination of the above debug flags. + */ +//static unsigned long debug_mask = SMARTMAX_DEBUG_LOAD|SMARTMAX_DEBUG_JUMPS|SMARTMAX_DEBUG_ALG|SMARTMAX_DEBUG_BOOST|SMARTMAX_DEBUG_INPUT|SMARTMAX_DEBUG_SUSPEND; +static unsigned long debug_mask; + +#define SMARTMAX_STAT 0 +#if SMARTMAX_STAT +static u64 timer_stat[4] = {0, 0, 0, 0}; +#endif + +/* + * dbs_mutex protects dbs_enable in governor start/stop. + */ +static DEFINE_MUTEX(dbs_mutex); +static struct workqueue_struct *smartmax_wq; + +static bool boost_task_alive = false; +static struct task_struct *boost_task; +static u64 boost_end_time = 0ULL; +static unsigned int cur_boost_freq = 0; +static unsigned int cur_boost_duration = 0; +static bool boost_running = false; +static unsigned int ideal_freq; +static bool is_suspended = false; +static unsigned int min_sampling_rate; + +#define LATENCY_MULTIPLIER (1000) +#define MIN_LATENCY_MULTIPLIER (100) +#define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) + +/* + * The polling frequency of this governor depends on the capability of + * the processor. Default polling frequency is 1000 times the transition + * latency of the processor. The governor will work on any processor with + * transition latency <= 10mS, using appropriate sampling + * rate. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. + * All times here are in uS. + */ +#define MIN_SAMPLING_RATE_RATIO (2) +#define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) + +static int cpufreq_governor_smartmax_eps(struct cpufreq_policy *policy, + unsigned int event); + +#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX_EPS +static +#endif +struct cpufreq_governor cpufreq_gov_smartmax_eps = { + .name = "smartmax_eps", + .governor = cpufreq_governor_smartmax_eps, + .max_transition_latency = TRANSITION_LATENCY_LIMIT, + .owner = THIS_MODULE, + }; + +static inline u64 get_cpu_idle_time_jiffy(unsigned int cpu, u64 *wall) { + + u64 idle_time; + u64 cur_wall_time; + u64 busy_time; + + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + busy_time = kstat_cpu(cpu).cpustat.user; + busy_time += kstat_cpu(cpu).cpustat.system; + busy_time += kstat_cpu(cpu).cpustat.irq; + busy_time += kstat_cpu(cpu).cpustat.softirq; + busy_time += kstat_cpu(cpu).cpustat.steal; + busy_time += kstat_cpu(cpu).cpustat.nice; +#else + busy_time = kcpustat_cpu(cpu).cpustat[CPUTIME_USER]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SYSTEM]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_IRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_SOFTIRQ]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_STEAL]; + busy_time += kcpustat_cpu(cpu).cpustat[CPUTIME_NICE]; +#endif + + idle_time = cur_wall_time - busy_time; + if (wall) + *wall = jiffies_to_usecs(cur_wall_time); + + return jiffies_to_usecs(idle_time); +} + +static inline u64 get_cpu_idle_time(unsigned int cpu, u64 *wall) +{ + u64 idle_time = get_cpu_idle_time_us(cpu, NULL); + + if (idle_time == -1ULL) + return get_cpu_idle_time_jiffy(cpu, wall); + else + idle_time += get_cpu_iowait_time_us(cpu, wall); + + return idle_time; +} + +static inline u64 get_cpu_iowait_time(unsigned int cpu, u64 *wall) { + u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); + + if (iowait_time == -1ULL) + return 0; + + return iowait_time; +} + +inline static void smartmax_update_min_max( + struct smartmax_info_s *this_smartmax, struct cpufreq_policy *policy) { + this_smartmax->ideal_speed = // ideal_freq; but make sure it obeys the policy min/max + policy->min < ideal_freq ? + (ideal_freq < policy->max ? ideal_freq : policy->max) : + policy->min; + +} + +inline static void smartmax_update_min_max_allcpus(void) { + unsigned int cpu; + + for_each_online_cpu(cpu) + { + struct smartmax_info_s *this_smartmax = &per_cpu(smartmax_info, cpu); + if (this_smartmax->cur_policy){ + if (lock_policy_rwsem_write(cpu) < 0) + continue; + + smartmax_update_min_max(this_smartmax, this_smartmax->cur_policy); + + unlock_policy_rwsem_write(cpu); + } + } +} + +inline static unsigned int validate_freq(struct cpufreq_policy *policy, + int freq) { + if (freq > (int) policy->max) + return policy->max; + if (freq < (int) policy->min) + return policy->min; + return freq; +} + +/* We want all CPUs to do sampling nearly on same jiffy */ +static inline unsigned int get_timer_delay(void) { + unsigned int delay = usecs_to_jiffies(sampling_rate); + + if (num_online_cpus() > 1) + delay -= jiffies % delay; + return delay; +} + +static inline void dbs_timer_init(struct smartmax_info_s *this_smartmax) { + int delay = get_timer_delay(); + + INIT_DELAYED_WORK_DEFERRABLE(&this_smartmax->work, do_dbs_timer); + schedule_delayed_work_on(this_smartmax->cpu, &this_smartmax->work, delay); +} + +static inline void dbs_timer_exit(struct smartmax_info_s *this_smartmax) { + cancel_delayed_work_sync(&this_smartmax->work); +} + +inline static void target_freq(struct cpufreq_policy *policy, + struct smartmax_info_s *this_smartmax, int new_freq, int old_freq, + int prefered_relation) { + int index, target; + struct cpufreq_frequency_table *table = this_smartmax->freq_table; + unsigned int cpu = this_smartmax->cpu; + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s\n", old_freq, __func__); + + // apply policy limits - just to be sure + new_freq = validate_freq(policy, new_freq); + + if (!cpufreq_frequency_table_target(policy, table, new_freq, + prefered_relation, &index)) { + target = table[index].frequency; + if (target == old_freq) { + // if for example we are ramping up to *at most* current + ramp_up_step + // but there is no such frequency higher than the current, try also + // to ramp up to *at least* current + ramp_up_step. + if (new_freq > old_freq && prefered_relation == CPUFREQ_RELATION_H + && !cpufreq_frequency_table_target(policy, table, new_freq, + CPUFREQ_RELATION_L, &index)) + target = table[index].frequency; + // simlarly for ramping down: + else if (new_freq < old_freq + && prefered_relation == CPUFREQ_RELATION_L + && !cpufreq_frequency_table_target(policy, table, new_freq, + CPUFREQ_RELATION_H, &index)) + target = table[index].frequency; + } + + // no change + if (target == old_freq) + return; + } else { + dprintk(SMARTMAX_DEBUG_ALG, "frequency change failed\n"); + return; + } + + dprintk(SMARTMAX_DEBUG_JUMPS, "%d: jumping to %d (%d) cpu %d\n", old_freq, new_freq, target, cpu); + + __cpufreq_driver_target(policy, target, prefered_relation); + + // remember last time we changed frequency + this_smartmax->freq_change_time = ktime_to_us(ktime_get()); +} + +/* We use the same work function to sale up and down */ +static void cpufreq_smartmax_freq_change(struct smartmax_info_s *this_smartmax) { + unsigned int cpu; + unsigned int new_freq = 0; + unsigned int old_freq; + int ramp_dir; + struct cpufreq_policy *policy; + unsigned int relation = CPUFREQ_RELATION_L; + + ramp_dir = this_smartmax->ramp_dir; + old_freq = this_smartmax->old_freq; + policy = this_smartmax->cur_policy; + cpu = this_smartmax->cpu; + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s\n", old_freq, __func__); + + if (old_freq != policy->cur) { + // frequency was changed by someone else? + dprintk(SMARTMAX_DEBUG_ALG, "%d: frequency changed by 3rd party to %d\n", + old_freq, policy->cur); + new_freq = old_freq; + } else if (ramp_dir > 0 && nr_running() > 1) { + // ramp up logic: + if (old_freq < this_smartmax->ideal_speed) + new_freq = this_smartmax->ideal_speed; + else if (ramp_up_step) { + new_freq = old_freq + ramp_up_step; + relation = CPUFREQ_RELATION_H; + } else { + new_freq = policy->max; + relation = CPUFREQ_RELATION_H; + } + } else if (ramp_dir < 0) { + // ramp down logic: + if (old_freq > this_smartmax->ideal_speed) { + new_freq = this_smartmax->ideal_speed; + relation = CPUFREQ_RELATION_H; + } else if (ramp_down_step) + new_freq = old_freq - ramp_down_step; + else { + // Load heuristics: Adjust new_freq such that, assuming a linear + // scaling of load vs. frequency, the load in the new frequency + // will be max_cpu_load: + new_freq = old_freq * this_smartmax->cur_cpu_load / max_cpu_load; + if (new_freq > old_freq) // min_cpu_load > max_cpu_load ?! + new_freq = old_freq - 1; + } + } + + if (new_freq!=0){ + target_freq(policy, this_smartmax, new_freq, old_freq, relation); + } + + this_smartmax->ramp_dir = 0; +} + +static inline void cpufreq_smartmax_get_ramp_direction(struct smartmax_info_s *this_smartmax, u64 now) +{ + unsigned int cur_load = this_smartmax->cur_cpu_load; + unsigned int cur = this_smartmax->old_freq; + struct cpufreq_policy *policy = this_smartmax->cur_policy; + + // Scale up if load is above max or if there where no idle cycles since coming out of idle, + // additionally, if we are at or above the ideal_speed, verify we have been at this frequency + // for at least up_rate: + if (cur_load > max_cpu_load && cur < policy->max + && (cur < this_smartmax->ideal_speed + || (now - this_smartmax->freq_change_time) >= up_rate)) { + dprintk(SMARTMAX_DEBUG_ALG, + "%d: ramp up: load %d\n", cur, cur_load); + this_smartmax->ramp_dir = 1; + } + // Similarly for scale down: load should be below min and if we are at or below ideal + // frequency we require that we have been at this frequency for at least down_rate: + else if (cur_load < min_cpu_load && cur > policy->min + && (cur > this_smartmax->ideal_speed + || (now - this_smartmax->freq_change_time) >= down_rate)) { + dprintk(SMARTMAX_DEBUG_ALG, + "%d: ramp down: load %d\n", cur, cur_load); + this_smartmax->ramp_dir = -1; + } +} + +static void inline cpufreq_smartmax_calc_load(int j) +{ + struct smartmax_info_s *j_this_smartmax; + u64 cur_wall_time, cur_idle_time, cur_iowait_time; + unsigned int idle_time, wall_time, iowait_time; + unsigned int cur_load; + + j_this_smartmax = &per_cpu(smartmax_info, j); + + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); + cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); + + wall_time = cur_wall_time - j_this_smartmax->prev_cpu_wall; + j_this_smartmax->prev_cpu_wall = cur_wall_time; + + idle_time = cur_idle_time - j_this_smartmax->prev_cpu_idle; + j_this_smartmax->prev_cpu_idle = cur_idle_time; + + iowait_time = cur_iowait_time - j_this_smartmax->prev_cpu_iowait; + j_this_smartmax->prev_cpu_iowait = cur_iowait_time; + + if (ignore_nice) { + u64 cur_nice; + unsigned long cur_nice_jiffies; + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + cur_nice = kstat_cpu(j).cpustat.nice - j_this_smartmax->prev_cpu_nice; + cur_nice_jiffies = (unsigned long) cputime64_to_jiffies64(cur_nice); + + j_this_smartmax->prev_cpu_nice = kstat_cpu(j).cpustat.nice; +#else + cur_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE] - j_this_smartmax->prev_cpu_nice; + cur_nice_jiffies = (unsigned long) cputime64_to_jiffies64(cur_nice); + + j_this_smartmax->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; + +#endif + + idle_time += jiffies_to_usecs(cur_nice_jiffies); + } + + /* + * For the purpose of ondemand, waiting for disk IO is an + * indication that you're performance critical, and not that + * the system is actually idle. So subtract the iowait time + * from the cpu idle time. + */ + if (io_is_busy && idle_time >= iowait_time) + idle_time -= iowait_time; + + if (unlikely(!wall_time || wall_time < idle_time)) + return; + + cur_load = 100 * (wall_time - idle_time) / wall_time; + j_this_smartmax->cur_cpu_load = cur_load; +} + +static void cpufreq_smartmax_timer(struct smartmax_info_s *this_smartmax) { + unsigned int cur; + struct cpufreq_policy *policy = this_smartmax->cur_policy; + u64 now = ktime_to_us(ktime_get()); + /* Extrapolated load of this CPU */ + //unsigned int load_at_max_freq = 0; + unsigned int cpu = this_smartmax->cpu; + +#if SMARTMAX_STAT + u64 diff = 0; + + if (timer_stat[cpu]) + diff = now - timer_stat[cpu]; + + timer_stat[cpu] = now; + printk(KERN_DEBUG "[smartmax]:cpu %d %lld\n", cpu, diff); +#endif + + cur = policy->cur; + + dprintk(SMARTMAX_DEBUG_ALG, "%d: %s cpu %d %lld\n", cur, __func__, cpu, now); + + cpufreq_smartmax_calc_load(cpu); + + /* calculate the scaled load across CPU */ + //load_at_max_freq = (this_smartmax->cur_cpu_load * policy->cur)/policy->cpuinfo.max_freq; + + //cpufreq_notify_utilization(policy, load_at_max_freq); + + dprintk(SMARTMAX_DEBUG_LOAD, "%d: load %d\n", cpu, this_smartmax->cur_cpu_load); + + this_smartmax->old_freq = cur; + this_smartmax->ramp_dir = 0; + + cpufreq_smartmax_get_ramp_direction(this_smartmax, now); + + // no changes + if (this_smartmax->ramp_dir == 0) + return; + + // boost - but not block ramp up steps based on load if requested + if (boost_running){ + if (now < boost_end_time) { + dprintk(SMARTMAX_DEBUG_BOOST, "%d: cpu %d boost running %llu %llu\n", cur, cpu, now, boost_end_time); + + if (this_smartmax->ramp_dir == -1) + return; + else { + if (ramp_up_during_boost) + dprintk(SMARTMAX_DEBUG_BOOST, "%d: cpu %d boost running but ramp_up above boost freq requested\n", cur, cpu); + else + return; + } + } else + boost_running = false; + } + + cpufreq_smartmax_freq_change(this_smartmax); +} + +static void do_dbs_timer(struct work_struct *work) { + struct smartmax_info_s *this_smartmax = + container_of(work, struct smartmax_info_s, work.work); + unsigned int cpu = this_smartmax->cpu; + int delay = get_timer_delay(); + + mutex_lock(&this_smartmax->timer_mutex); + + cpufreq_smartmax_timer(this_smartmax); + + queue_delayed_work_on(cpu, smartmax_wq, &this_smartmax->work, delay); + mutex_unlock(&this_smartmax->timer_mutex); +} + +static void update_idle_time(bool online) { + int j = 0; + + for_each_possible_cpu(j) + { + struct smartmax_info_s *j_this_smartmax; + + if (online && !cpu_online(j)) { + continue; + } + j_this_smartmax = &per_cpu(smartmax_info, j); + + j_this_smartmax->prev_cpu_idle = get_cpu_idle_time(j, + &j_this_smartmax->prev_cpu_wall); + + if (ignore_nice) +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_30 + j_this_smartmax->prev_cpu_nice = kstat_cpu(j) .cpustat.nice; +#else + j_this_smartmax->prev_cpu_nice = kcpustat_cpu(j).cpustat[CPUTIME_NICE]; +#endif + } +} + +static ssize_t show_debug_mask(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%lu\n", debug_mask); +} + +static ssize_t store_debug_mask(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) + debug_mask = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_up_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", up_rate); +} + +static ssize_t store_up_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0 && input <= 100000000) + up_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_down_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", down_rate); +} + +static ssize_t store_down_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0 && input <= 100000000) + down_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_awake_ideal_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", awake_ideal_freq); +} + +static ssize_t store_awake_ideal_freq(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) { + awake_ideal_freq = input; + if (!is_suspended){ + ideal_freq = awake_ideal_freq; + smartmax_update_min_max_allcpus(); + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_suspend_ideal_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", suspend_ideal_freq); +} + +static ssize_t store_suspend_ideal_freq(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) { + suspend_ideal_freq = input; + if (is_suspended){ + ideal_freq = suspend_ideal_freq; + smartmax_update_min_max_allcpus(); + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_up_step(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", ramp_up_step); +} + +static ssize_t store_ramp_up_step(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) + ramp_up_step = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_down_step(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", ramp_down_step); +} + +static ssize_t store_ramp_down_step(struct kobject *kobj, + struct attribute *attr, const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= 0) + ramp_down_step = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_max_cpu_load(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", max_cpu_load); +} + +static ssize_t store_max_cpu_load(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 0 && input <= 100) + max_cpu_load = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_min_cpu_load(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", min_cpu_load); +} + +static ssize_t store_min_cpu_load(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 0 && input < 100) + min_cpu_load = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_sampling_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", sampling_rate); +} + +static ssize_t store_sampling_rate(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input >= min_sampling_rate) + sampling_rate = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_touch_poke_freq(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%u\n", touch_poke_freq); +} + +static ssize_t store_touch_poke_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0){ + touch_poke_freq = input; + + if (touch_poke_freq == 0) + touch_poke = false; + else + touch_poke = true; + } else + return -EINVAL; + return count; +} + +static ssize_t show_input_boost_duration(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%u\n", input_boost_duration); +} + +static ssize_t store_input_boost_duration(struct kobject *a, + struct attribute *b, const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 10000) + input_boost_duration = input; + else + return -EINVAL; + return count; +} + +static ssize_t show_ramp_up_during_boost(struct kobject *kobj, + struct attribute *attr, char *buf) { + return sprintf(buf, "%d\n", ramp_up_during_boost); +} + +static ssize_t store_ramp_up_during_boost(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input == 0) + ramp_up_during_boost = false; + else if (input == 1) + ramp_up_during_boost = true; + else + return -EINVAL; + } else + return -EINVAL; + return count; +} + +static ssize_t show_boost_freq(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%u\n", boost_freq); +} + +static ssize_t store_boost_freq(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + boost_freq = input; + if (boost_freq == 0) + boost = false; + else + boost = true; + } else + return -EINVAL; + return count; +} + +static ssize_t show_boost_duration(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", boost_running); +} + +static ssize_t store_boost_duration(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + res = strict_strtoul(buf, 0, &input); + if (res >= 0 && input > 10000){ + boost_duration = input; + if (boost) { + // no need to bother if currently a boost is running anyway + if (boost_task_alive && boost_running) + return count; + + if (boost_task_alive) { + cur_boost_freq = boost_freq; + cur_boost_duration = boost_duration; + wake_up_process(boost_task); + } + } + } else + return -EINVAL; + return count; +} + +static ssize_t show_io_is_busy(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", io_is_busy); +} + +static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input > 1) + input = 1; + if (input == io_is_busy) { /* nothing to do */ + return count; + } + io_is_busy = input; + } else + return -EINVAL; + return count; +} + +static ssize_t show_ignore_nice(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", ignore_nice); +} + +static ssize_t store_ignore_nice(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + ssize_t res; + unsigned long input; + + res = strict_strtoul(buf, 0, &input); + if (res >= 0) { + if (input > 1) + input = 1; + if (input == ignore_nice) { /* nothing to do */ + return count; + } + ignore_nice = input; + /* we need to re-evaluate prev_cpu_idle */ + update_idle_time(true); + } else + return -EINVAL; + return count; +} + +static ssize_t show_min_sampling_rate(struct kobject *kobj, struct attribute *attr, + char *buf) { + return sprintf(buf, "%d\n", min_sampling_rate); +} + +static ssize_t store_min_sampling_rate(struct kobject *a, struct attribute *b, + const char *buf, size_t count) { + return -EINVAL; +} + +#define define_global_rw_attr(_name) \ +static struct global_attr _name##_attr = \ + __ATTR(_name, 0644, show_##_name, store_##_name) + +#define define_global_ro_attr(_name) \ +static struct global_attr _name##_attr = \ + __ATTR(_name, 0444, show_##_name, store_##_name) + +define_global_rw_attr(debug_mask); +define_global_rw_attr(up_rate); +define_global_rw_attr(down_rate); +define_global_rw_attr(ramp_up_step); +define_global_rw_attr(ramp_down_step); +define_global_rw_attr(max_cpu_load); +define_global_rw_attr(min_cpu_load); +define_global_rw_attr(sampling_rate); +define_global_rw_attr(touch_poke_freq); +define_global_rw_attr(input_boost_duration); +define_global_rw_attr(boost_freq); +define_global_rw_attr(boost_duration); +define_global_rw_attr(io_is_busy); +define_global_rw_attr(ignore_nice); +define_global_rw_attr(ramp_up_during_boost); +define_global_rw_attr(awake_ideal_freq); +define_global_rw_attr(suspend_ideal_freq); +define_global_ro_attr(min_sampling_rate); + +static struct attribute * smartmax_attributes[] = { + &debug_mask_attr.attr, + &up_rate_attr.attr, + &down_rate_attr.attr, + &ramp_up_step_attr.attr, + &ramp_down_step_attr.attr, + &max_cpu_load_attr.attr, + &min_cpu_load_attr.attr, + &sampling_rate_attr.attr, + &touch_poke_freq_attr.attr, + &input_boost_duration_attr.attr, + &boost_freq_attr.attr, + &boost_duration_attr.attr, + &io_is_busy_attr.attr, + &ignore_nice_attr.attr, + &ramp_up_during_boost_attr.attr, + &awake_ideal_freq_attr.attr, + &suspend_ideal_freq_attr.attr, + &min_sampling_rate_attr.attr, + NULL , }; + +static struct attribute_group smartmax_attr_group = { + .attrs = smartmax_attributes, + .name = "smartmax_eps", + }; + +static int cpufreq_smartmax_boost_task(void *data) { + struct smartmax_info_s *this_smartmax; + u64 now; + struct cpufreq_policy *policy; +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + unsigned int cpu; + bool start_boost = false; +#endif + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + schedule(); + + if (kthread_should_stop()) + break; + + set_current_state(TASK_RUNNING); + + if (boost_running) + continue; + +#ifdef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + /* on tegra there is only one cpu clock so we only need to boost cpu 0 + all others will run at the same speed */ + this_smartmax = &per_cpu(smartmax_info, 0); + if (!this_smartmax) + continue; + + policy = this_smartmax->cur_policy; + if (!policy) + continue; + + if (lock_policy_rwsem_write(0) < 0) + continue; + + tegra_input_boost(policy, cur_boost_freq, CPUFREQ_RELATION_H); + + this_smartmax->prev_cpu_idle = get_cpu_idle_time(0, + &this_smartmax->prev_cpu_wall); + + unlock_policy_rwsem_write(0); +#else + for_each_online_cpu(cpu){ + this_smartmax = &per_cpu(smartmax_info, cpu); + if (!this_smartmax) + continue; + + if (lock_policy_rwsem_write(cpu) < 0) + continue; + + policy = this_smartmax->cur_policy; + if (!policy){ + unlock_policy_rwsem_write(cpu); + continue; + } + + mutex_lock(&this_smartmax->timer_mutex); + + if (policy->cur < cur_boost_freq) { + start_boost = true; + dprintk(SMARTMAX_DEBUG_BOOST, "input boost cpu %d to %d\n", cpu, cur_boost_freq); + target_freq(policy, this_smartmax, cur_boost_freq, this_smartmax->old_freq, CPUFREQ_RELATION_H); + this_smartmax->prev_cpu_idle = get_cpu_idle_time(cpu, &this_smartmax->prev_cpu_wall); + } + mutex_unlock(&this_smartmax->timer_mutex); + + unlock_policy_rwsem_write(cpu); + } +#endif + +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + if (start_boost) { +#endif + + boost_running = true; + now = ktime_to_us(ktime_get()); + boost_end_time = now + (cur_boost_duration * num_online_cpus()); + dprintk(SMARTMAX_DEBUG_BOOST, "%s %llu %llu\n", __func__, now, boost_end_time); + +#ifndef CONFIG_CPU_FREQ_GOV_SMARTMAX_TEGRA + } +#endif + } + + pr_info("[smartmax]:" "%s boost_thread stopped\n", __func__); + return 0; +} + +static void smartmax_input_event(struct input_handle *handle, unsigned int type, + unsigned int code, int value) { + if (!is_suspended && touch_poke && type == EV_SYN && code == SYN_REPORT) { + // no need to bother if currently a boost is running anyway + if (boost_task_alive && boost_running) + return; + + if (boost_task_alive) { + cur_boost_freq = touch_poke_freq; + cur_boost_duration = input_boost_duration; + wake_up_process(boost_task); + } + } +} + +#ifdef CONFIG_INPUT_MEDIATOR + +static struct input_mediator_handler smartmax_input_mediator_handler = { + .event = smartmax_input_event, + }; + +#else + +static int dbs_input_connect(struct input_handler *handler, + struct input_dev *dev, const struct input_device_id *id) { + struct input_handle *handle; + int error; + + pr_info("[smartmax]:" "%s input connect to %s\n", __func__, dev->name); + + handle = kzalloc(sizeof(struct input_handle), GFP_KERNEL); + if (!handle) + return -ENOMEM; + + handle->dev = dev; + handle->handler = handler; + handle->name = "cpufreq"; + + error = input_register_handle(handle); + if (error) + goto err2; + + error = input_open_device(handle); + if (error) + goto err1; + + return 0; + err1: input_unregister_handle(handle); + err2: kfree(handle); + pr_err("[smartmax]:" "%s faild to connect input handler %d\n", __func__, error); + return error; +} + +static void dbs_input_disconnect(struct input_handle *handle) { + input_close_device(handle); + input_unregister_handle(handle); + kfree(handle); +} + +static const struct input_device_id dbs_ids[] = { +{ + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .evbit = { BIT_MASK(EV_ABS) }, + .absbit = { [BIT_WORD(ABS_MT_POSITION_X)] = + BIT_MASK(ABS_MT_POSITION_X) | + BIT_MASK(ABS_MT_POSITION_Y) }, + }, /* multi-touch touchscreen */ + { + .flags = INPUT_DEVICE_ID_MATCH_KEYBIT | + INPUT_DEVICE_ID_MATCH_ABSBIT, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + .absbit = { [BIT_WORD(ABS_X)] = + BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) }, + }, /* touchpad */ + { }, +}; + +static struct input_handler dbs_input_handler = { + .event = smartmax_input_event, + .connect = dbs_input_connect, + .disconnect = dbs_input_disconnect, + .name = "cpufreq_smartmax_eps", + .id_table = dbs_ids, + }; +#endif + +static int cpufreq_governor_smartmax_eps(struct cpufreq_policy *new_policy, + unsigned int event) { + unsigned int cpu = new_policy->cpu; + int rc; + struct smartmax_info_s *this_smartmax = &per_cpu(smartmax_info, cpu); + struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; + unsigned int latency; + + switch (event) { + case CPUFREQ_GOV_START: + if ((!cpu_online(cpu)) || (!new_policy->cur)) + return -EINVAL; + + mutex_lock(&dbs_mutex); + + this_smartmax->cur_policy = new_policy; + this_smartmax->cpu = cpu; + + smartmax_update_min_max(this_smartmax,new_policy); + + this_smartmax->freq_table = cpufreq_frequency_get_table(cpu); + if (!this_smartmax->freq_table){ + mutex_unlock(&dbs_mutex); + return -EINVAL; + } + + update_idle_time(false); + + dbs_enable++; + + if (dbs_enable == 1) { + if (!boost_task_alive) { + boost_task = kthread_create ( + cpufreq_smartmax_boost_task, + NULL, + "smartmax_input_boost_task" + ); + + if (IS_ERR(boost_task)) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return PTR_ERR(boost_task); + } + + pr_info("[smartmax]:" "%s input boost task created\n", __func__); + sched_setscheduler_nocheck(boost_task, SCHED_FIFO, ¶m); + get_task_struct(boost_task); + boost_task_alive = true; + } +#ifdef CONFIG_INPUT_MEDIATOR + input_register_mediator_secondary(&smartmax_input_mediator_handler); +#else + rc = input_register_handler(&dbs_input_handler); + if (rc) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return rc; + } +#endif + rc = sysfs_create_group(cpufreq_global_kobject, + &smartmax_attr_group); + if (rc) { + dbs_enable--; + mutex_unlock(&dbs_mutex); + return rc; + } + /* policy latency is in nS. Convert it to uS first */ + latency = new_policy->cpuinfo.transition_latency / 1000; + if (latency == 0) + latency = 1; + + /* Bring kernel and HW constraints together */ + min_sampling_rate = max(min_sampling_rate, MIN_LATENCY_MULTIPLIER * latency); + sampling_rate = max(min_sampling_rate, sampling_rate); + } + + mutex_unlock(&dbs_mutex); + dbs_timer_init(this_smartmax); + + break; + case CPUFREQ_GOV_LIMITS: + mutex_lock(&this_smartmax->timer_mutex); + smartmax_update_min_max(this_smartmax,new_policy); + + if (this_smartmax->cur_policy->cur > new_policy->max) { + dprintk(SMARTMAX_DEBUG_JUMPS,"CPUFREQ_GOV_LIMITS jumping to new max freq: %d\n",new_policy->max); + __cpufreq_driver_target(this_smartmax->cur_policy, + new_policy->max, CPUFREQ_RELATION_H); + } + else if (this_smartmax->cur_policy->cur < new_policy->min) { + dprintk(SMARTMAX_DEBUG_JUMPS,"CPUFREQ_GOV_LIMITS jumping to new min freq: %d\n",new_policy->min); + __cpufreq_driver_target(this_smartmax->cur_policy, + new_policy->min, CPUFREQ_RELATION_L); + } + mutex_unlock(&this_smartmax->timer_mutex); + break; + + case CPUFREQ_GOV_STOP: + dbs_timer_exit(this_smartmax); + + mutex_lock(&dbs_mutex); + this_smartmax->cur_policy = NULL; + dbs_enable--; + + if (!dbs_enable){ + if (boost_task_alive) + kthread_stop(boost_task); + + sysfs_remove_group(cpufreq_global_kobject, &smartmax_attr_group); +#ifdef CONFIG_INPUT_MEDIATOR + input_unregister_mediator_secondary(&smartmax_input_mediator_handler); +#else + input_unregister_handler(&dbs_input_handler); +#endif + } + + mutex_unlock(&dbs_mutex); + break; + } + + return 0; +} + +static int __init cpufreq_smartmax_init(void) { + unsigned int i; + struct smartmax_info_s *this_smartmax; + u64 wall; + u64 idle_time; + int cpu = get_cpu(); + + idle_time = get_cpu_idle_time_us(cpu, &wall); + put_cpu(); + if (idle_time != -1ULL) { + /* + * In no_hz/micro accounting case we set the minimum frequency + * not depending on HZ, but fixed (very low). The deferred + * timer might skip some samples if idle/sleeping as needed. + */ + min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; + } else { + /* For correct statistics, we need 10 ticks for each measure */ + min_sampling_rate = MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10); + } + + smartmax_wq = alloc_workqueue("smartmax_wq", WQ_HIGHPRI, 0); + if (!smartmax_wq) { + printk(KERN_ERR "Failed to create smartmax_wq workqueue\n"); + return -EFAULT; + } + + up_rate = DEFAULT_UP_RATE; + down_rate = DEFAULT_DOWN_RATE; + suspend_ideal_freq = DEFAULT_SUSPEND_IDEAL_FREQ; + awake_ideal_freq = DEFAULT_AWAKE_IDEAL_FREQ; + ideal_freq = awake_ideal_freq; + ramp_up_step = DEFAULT_RAMP_UP_STEP; + ramp_down_step = DEFAULT_RAMP_DOWN_STEP; + max_cpu_load = DEFAULT_MAX_CPU_LOAD; + min_cpu_load = DEFAULT_MIN_CPU_LOAD; + sampling_rate = DEFAULT_SAMPLING_RATE; + input_boost_duration = DEFAULT_INPUT_BOOST_DURATION; + io_is_busy = DEFAULT_IO_IS_BUSY; + ignore_nice = DEFAULT_IGNORE_NICE; + touch_poke_freq = DEFAULT_TOUCH_POKE_FREQ; + boost_freq = DEFAULT_BOOST_FREQ; + + /* Initalize per-cpu data: */ + for_each_possible_cpu(i) + { + this_smartmax = &per_cpu(smartmax_info, i); + this_smartmax->cur_policy = NULL; + this_smartmax->ramp_dir = 0; + this_smartmax->freq_change_time = 0; + this_smartmax->cur_cpu_load = 0; + mutex_init(&this_smartmax->timer_mutex); + } + + return cpufreq_register_governor(&cpufreq_gov_smartmax_eps); +} + +#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_SMARTMAX_EPS +fs_initcall(cpufreq_smartmax_init); +#else +module_init(cpufreq_smartmax_init); +#endif + +static void __exit cpufreq_smartmax_exit(void) { + unsigned int i; + struct smartmax_info_s *this_smartmax; + + cpufreq_unregister_governor(&cpufreq_gov_smartmax_eps); + + for_each_possible_cpu(i) + { + this_smartmax = &per_cpu(smartmax_info, i); + mutex_destroy(&this_smartmax->timer_mutex); + } + destroy_workqueue(smartmax_wq); +} + +module_exit(cpufreq_smartmax_exit); + +MODULE_AUTHOR("maxwen"); +MODULE_DESCRIPTION("'cpufreq_smartmax' - A smart cpufreq governor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index 2f0083a51a9..2a6b0df7ae7 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c @@ -80,24 +80,15 @@ int cpuidle_play_dead(void) { struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); struct cpuidle_driver *drv = cpuidle_get_driver(); - int i, dead_state = -1; - int power_usage = -1; + int i; if (!drv) return -ENODEV; /* Find lowest-power state that supports long-term idle */ - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { - struct cpuidle_state *s = &drv->states[i]; - - if (s->power_usage < power_usage && s->enter_dead) { - power_usage = s->power_usage; - dead_state = i; - } - } - - if (dead_state != -1) - return drv->states[dead_state].enter_dead(dev, dead_state); + for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--) + if (drv->states[i].enter_dead) + return drv->states[i].enter_dead(dev, i); return -ENODEV; } @@ -276,7 +267,6 @@ static void poll_idle_init(struct cpuidle_driver *drv) state->power_usage = -1; state->flags = 0; state->enter = poll_idle; - state->disable = 0; } #else static void poll_idle_init(struct cpuidle_driver *drv) {} diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 40cd3f3024d..2265fcfe866 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -17,29 +17,6 @@ static struct cpuidle_driver *cpuidle_curr_driver; DEFINE_SPINLOCK(cpuidle_driver_lock); -static void __cpuidle_register_driver(struct cpuidle_driver *drv) -{ - int i; - /* - * cpuidle driver should set the drv->power_specified bit - * before registering if the driver provides - * power_usage numbers. - * - * If power_specified is not set, - * we fill in power_usage with decreasing values as the - * cpuidle code has an implicit assumption that state Cn - * uses less power than C(n-1). - * - * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned - * an power value of -1. So we use -2, -3, etc, for other - * c-states. - */ - if (!drv->power_specified) { - for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) - drv->states[i].power_usage = -1 - i; - } -} - /** * cpuidle_register_driver - registers a driver @@ -58,7 +35,6 @@ int cpuidle_register_driver(struct cpuidle_driver *drv) spin_unlock(&cpuidle_driver_lock); return -EBUSY; } - __cpuidle_register_driver(drv); cpuidle_curr_driver = drv; spin_unlock(&cpuidle_driver_lock); diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index ec38843f4d5..44c5212449d 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -28,6 +28,13 @@ #define MAX_INTERESTING 50000 #define STDDEV_THRESH 400 +/* 60 * 60 > STDDEV_THRESH * INTERVALS = 400 * 8 */ +#define MAX_DEVIATION 60 + +static DEFINE_PER_CPU(struct hrtimer, menu_hrtimer); +static DEFINE_PER_CPU(int, hrtimer_status); +/* menu hrtimer mode */ +enum {MENU_HRTIMER_STOP, MENU_HRTIMER_REPEAT, MENU_HRTIMER_GENERAL}; /* * Concepts and ideas behind the menu governor @@ -109,6 +116,13 @@ * */ +/* + * The C-state residency is so long that is is worthwhile to exit + * from the shallow C-state and re-enter into a deeper C-state. + */ +static unsigned int perfect_cstate_ms __read_mostly = 30; +module_param(perfect_cstate_ms, uint, 0000); + struct menu_device { int last_state_idx; int needs_update; @@ -179,40 +193,102 @@ static u64 div_round64(u64 dividend, u32 divisor) return div_u64(dividend + (divisor / 2), divisor); } +/* Cancel the hrtimer if it is not triggered yet */ +void menu_hrtimer_cancel(void) +{ + int cpu = smp_processor_id(); + struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu); + + /* The timer is still not time out*/ + if (per_cpu(hrtimer_status, cpu)) { + hrtimer_cancel(hrtmr); + per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP; + } +} +EXPORT_SYMBOL_GPL(menu_hrtimer_cancel); + +/* Call back for hrtimer is triggered */ +static enum hrtimer_restart menu_hrtimer_notify(struct hrtimer *hrtimer) +{ + int cpu = smp_processor_id(); + struct menu_device *data = &per_cpu(menu_devices, cpu); + + /* In general case, the expected residency is much larger than + * deepest C-state target residency, but prediction logic still + * predicts a small predicted residency, so the prediction + * history is totally broken if the timer is triggered. + * So reset the correction factor. + */ + if (per_cpu(hrtimer_status, cpu) == MENU_HRTIMER_GENERAL) + data->correction_factor[data->bucket] = RESOLUTION * DECAY; + + per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_STOP; + + return HRTIMER_NORESTART; +} + /* * Try detecting repeating patterns by keeping track of the last 8 * intervals, and checking if the standard deviation of that set * of points is below a threshold. If it is... then use the * average of these 8 points as the estimated value. */ -static void detect_repeating_patterns(struct menu_device *data) +static u32 get_typical_interval(struct menu_device *data) { - int i; - uint64_t avg = 0; - uint64_t stddev = 0; /* contains the square of the std deviation */ - - /* first calculate average and standard deviation of the past */ - for (i = 0; i < INTERVALS; i++) - avg += data->intervals[i]; - avg = avg / INTERVALS; - - /* if the avg is beyond the known next tick, it's worthless */ - if (avg > data->expected_us) - return; + int i = 0, divisor = 0; + uint64_t max = 0, avg = 0, stddev = 0; + int64_t thresh = LLONG_MAX; /* Discard outliers above this value. */ + unsigned int ret = 0; - for (i = 0; i < INTERVALS; i++) - stddev += (data->intervals[i] - avg) * - (data->intervals[i] - avg); +again: - stddev = stddev / INTERVALS; + /* first calculate average and standard deviation of the past */ + max = avg = divisor = stddev = 0; + for (i = 0; i < INTERVALS; i++) { + int64_t value = data->intervals[i]; + if (value <= thresh) { + avg += value; + divisor++; + if (value > max) + max = value; + } + } + do_div(avg, divisor); + for (i = 0; i < INTERVALS; i++) { + int64_t value = data->intervals[i]; + if (value <= thresh) { + int64_t diff = value - avg; + stddev += diff * diff; + } + } + do_div(stddev, divisor); + stddev = int_sqrt(stddev); /* - * now.. if stddev is small.. then assume we have a - * repeating pattern and predict we keep doing this. + * If we have outliers to the upside in our distribution, discard + * those by setting the threshold to exclude these outliers, then + * calculate the average and standard deviation again. Once we get + * down to the bottom 3/4 of our samples, stop excluding samples. + * + * This can deal with workloads that have long pauses interspersed + * with sporadic activity with a bunch of short pauses. + * + * The typical interval is obtained when standard deviation is small + * or standard deviation is small compared to the average interval. */ - - if (avg && stddev < STDDEV_THRESH) + if (((avg > stddev * 6) && (divisor * 4 >= INTERVALS * 3)) + || stddev <= 20) { data->predicted_us = avg; + ret = 1; + return ret; + + } else if ((divisor * 4) > INTERVALS * 3) { + /* Exclude the max interval */ + thresh = max - 1; + goto again; + } + + return ret; } /** @@ -224,10 +300,12 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &__get_cpu_var(menu_devices); int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); - int power_usage = -1; int i; int multiplier; struct timespec t; + int repeat = 0, low_predicted = 0; + int cpu = smp_processor_id(); + struct hrtimer *hrtmr = &per_cpu(menu_hrtimer, cpu); if (data->needs_update) { menu_update(drv, dev); @@ -262,14 +340,14 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) data->predicted_us = div_round64(data->expected_us * data->correction_factor[data->bucket], RESOLUTION * DECAY); - detect_repeating_patterns(data); + repeat = get_typical_interval(data); /* * We want to default to C1 (hlt), not to busy polling * unless the timer is happening really really soon. */ if (data->expected_us > 5 && - drv->states[CPUIDLE_DRIVER_STATE_START].disable == 0) + dev->states_usage[CPUIDLE_DRIVER_STATE_START].disable == 0) data->last_state_idx = CPUIDLE_DRIVER_STATE_START; /* @@ -278,21 +356,57 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) */ for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { struct cpuidle_state *s = &drv->states[i]; + struct cpuidle_state_usage *su = &dev->states_usage[i]; - if (s->disable) + if (su->disable) continue; - if (s->target_residency > data->predicted_us) + if (s->target_residency > data->predicted_us) { + low_predicted = 1; continue; + } if (s->exit_latency > latency_req) continue; if (s->exit_latency * multiplier > data->predicted_us) continue; - if (s->power_usage < power_usage) { - power_usage = s->power_usage; - data->last_state_idx = i; - data->exit_us = s->exit_latency; + data->last_state_idx = i; + data->exit_us = s->exit_latency; + } + + /* not deepest C-state chosen for low predicted residency */ + if (low_predicted) { + unsigned int timer_us = 0; + unsigned int perfect_us = 0; + + /* + * Set a timer to detect whether this sleep is much + * longer than repeat mode predicted. If the timer + * triggers, the code will evaluate whether to put + * the CPU into a deeper C-state. + * The timer is cancelled on CPU wakeup. + */ + timer_us = 2 * (data->predicted_us + MAX_DEVIATION); + + perfect_us = perfect_cstate_ms * 1000; + + if (repeat && (4 * timer_us < data->expected_us)) { + hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us), + HRTIMER_MODE_REL_PINNED); + /* In repeat case, menu hrtimer is started */ + per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_REPEAT; + } else if (perfect_us < data->expected_us) { + /* + * The next timer is long. This could be because + * we did not make a useful prediction. + * In that case, it makes sense to re-enter + * into a deeper C-state after some time. + */ + hrtimer_start(hrtmr, ns_to_ktime(1000 * timer_us), + HRTIMER_MODE_REL_PINNED); + /* In general case, menu hrtimer is started */ + per_cpu(hrtimer_status, cpu) = MENU_HRTIMER_GENERAL; } + } return data->last_state_idx; @@ -385,6 +499,9 @@ static int menu_enable_device(struct cpuidle_driver *drv, struct cpuidle_device *dev) { struct menu_device *data = &per_cpu(menu_devices, dev->cpu); + struct hrtimer *t = &per_cpu(menu_hrtimer, dev->cpu); + hrtimer_init(t, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + t->function = menu_hrtimer_notify; memset(data, 0, sizeof(struct menu_device)); diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 88032b4dc6d..5f809e337b8 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c @@ -217,7 +217,8 @@ struct cpuidle_state_attr { struct attribute attr; ssize_t (*show)(struct cpuidle_state *, \ struct cpuidle_state_usage *, char *); - ssize_t (*store)(struct cpuidle_state *, const char *, size_t); + ssize_t (*store)(struct cpuidle_state *, \ + struct cpuidle_state_usage *, const char *, size_t); }; #define define_one_state_ro(_name, show) \ @@ -233,21 +234,22 @@ static ssize_t show_state_##_name(struct cpuidle_state *state, \ return sprintf(buf, "%u\n", state->_name);\ } -#define define_store_state_function(_name) \ +#define define_store_state_ull_function(_name) \ static ssize_t store_state_##_name(struct cpuidle_state *state, \ + struct cpuidle_state_usage *state_usage, \ const char *buf, size_t size) \ { \ - long value; \ + unsigned long long value; \ int err; \ if (!capable(CAP_SYS_ADMIN)) \ return -EPERM; \ - err = kstrtol(buf, 0, &value); \ + err = kstrtoull(buf, 0, &value); \ if (err) \ return err; \ if (value) \ - state->disable = 1; \ + state_usage->_name = 1; \ else \ - state->disable = 0; \ + state_usage->_name = 0; \ return size; \ } @@ -273,8 +275,8 @@ define_show_state_ull_function(usage) define_show_state_ull_function(time) define_show_state_str_function(name) define_show_state_str_function(desc) -define_show_state_function(disable) -define_store_state_function(disable) +define_show_state_ull_function(disable) +define_store_state_ull_function(disable) define_one_state_ro(name, show_state_name); define_one_state_ro(desc, show_state_desc); @@ -318,10 +320,11 @@ static ssize_t cpuidle_state_store(struct kobject *kobj, { int ret = -EIO; struct cpuidle_state *state = kobj_to_state(kobj); + struct cpuidle_state_usage *state_usage = kobj_to_state_usage(kobj); struct cpuidle_state_attr *cattr = attr_to_stateattr(attr); if (cattr->store) - ret = cattr->store(state, buf, size); + ret = cattr->store(state, state_usage, buf, size); return ret; } diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile index 01cef64bf4d..d952902446c 100644 --- a/drivers/gpu/Makefile +++ b/drivers/gpu/Makefile @@ -1,2 +1,3 @@ +ccflags-y := -Ofast -ffast-math -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 -ftree-vectorize -mvectorize-with-neon-quad obj-y += drm/ vga/ stub/ ion/ obj-$(CONFIG_MSM_KGSL) += msm/ diff --git a/drivers/gpu/ion/Makefile b/drivers/gpu/ion/Makefile index 51349f6ddcc..e3a601216c5 100644 --- a/drivers/gpu/ion/Makefile +++ b/drivers/gpu/ion/Makefile @@ -1,3 +1,4 @@ +ccflags-y := -O3 -ffast-math -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 obj-$(CONFIG_ION) += ion.o ion_heap.o ion_system_heap.o ion_carveout_heap.o ion_iommu_heap.o ion_cp_heap.o obj-$(CONFIG_CMA) += ion_cma_heap.o obj-$(CONFIG_ION_TEGRA) += tegra/ diff --git a/drivers/gpu/ion/ion.c b/drivers/gpu/ion/ion.c index ffeea43dab6..26bc2511eec 100644 --- a/drivers/gpu/ion/ion.c +++ b/drivers/gpu/ion/ion.c @@ -489,6 +489,11 @@ void ion_free(struct ion_client *client, struct ion_handle *handle) { bool valid_handle; + if(IS_ERR_OR_NULL(handle)) { + pr_err("%s: handle pointer is invalid\n", __func__) ; + return; + } + BUG_ON(client != handle->client); mutex_lock(&client->lock); @@ -733,6 +738,15 @@ void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle, struct ion_iommu_map *iommu_map; struct ion_buffer *buffer; + if(IS_ERR_OR_NULL(client)) { + pr_err("%s: client pointer is invalid\n", __func__) ; + return; + } + if(IS_ERR_OR_NULL(handle)) { + pr_err("%s: handle pointer is invalid\n", __func__) ; + return; + } + mutex_lock(&client->lock); buffer = handle->buffer; @@ -749,12 +763,13 @@ void ion_unmap_iommu(struct ion_client *client, struct ion_handle *handle, kref_put(&iommu_map->ref, ion_iommu_release); buffer->iommu_map_cnt--; + out: mutex_unlock(&buffer->lock); mutex_unlock(&client->lock); - } + EXPORT_SYMBOL(ion_unmap_iommu); void *ion_map_kernel(struct ion_client *client, struct ion_handle *handle) diff --git a/drivers/gpu/ion/msm/Makefile b/drivers/gpu/ion/msm/Makefile index 1893405a6ab..acb39d9221e 100644 --- a/drivers/gpu/ion/msm/Makefile +++ b/drivers/gpu/ion/msm/Makefile @@ -1 +1,2 @@ +ccflags-y := -O3 -ffast-math -fgcse-lm -fgcse-sm -fsched-spec-load -fforce-addr -fsingle-precision-constant -mcpu=cortex-a15 -mtune=cortex-a15 -marm -mfpu=neon-vfpv4 obj-y += msm_ion.o ion_cp_common.o diff --git a/drivers/gpu/msm/Kconfig b/drivers/gpu/msm/Kconfig index ba63fbcbbb4..96a935dcb3e 100644 --- a/drivers/gpu/msm/Kconfig +++ b/drivers/gpu/msm/Kconfig @@ -96,3 +96,11 @@ config MSM_KGSL_DISABLE_SHADOW_WRITES bool "Disable register shadow writes for context switches" default n depends on MSM_KGSL + +config MSM_KGSL_SIMPLE_GOV + bool "Simple KGSL GPU govenor for Qualcomm Adreno xxx devices" + default n + depends on MSM_KGSL + ---help--- + A simple KGSL GPU govenor for Qualcom Adreno XXX devices + diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile index 1a6b072a707..9c26f44a040 100644 --- a/drivers/gpu/msm/Makefile +++ b/drivers/gpu/msm/Makefile @@ -1,4 +1,4 @@ -ccflags-y := -Iinclude/drm -Idrivers/gpu/msm +ccflags-y := -Iinclude/uapi/drm -Iinclude/drm -Idrivers/gpu/msm -Wframe-larger-than=1040 msm_kgsl_core-y = \ kgsl.o \ @@ -17,7 +17,6 @@ msm_kgsl_core-$(CONFIG_MSM_KGSL_CFF_DUMP) += kgsl_cffdump.o msm_kgsl_core-$(CONFIG_MSM_KGSL_DRM) += kgsl_drm.o msm_kgsl_core-$(CONFIG_MSM_SCM) += kgsl_pwrscale_trustzone.o msm_kgsl_core-$(CONFIG_MSM_SLEEP_STATS_DEVICE) += kgsl_pwrscale_idlestats.o -msm_kgsl_core-$(CONFIG_MSM_DCVS) += kgsl_pwrscale_msm.o msm_kgsl_core-$(CONFIG_SYNC) += kgsl_sync.o msm_adreno-y += \ @@ -27,13 +26,16 @@ msm_adreno-y += \ adreno_postmortem.o \ adreno_snapshot.o \ adreno_trace.o \ + adreno_coresight.o \ adreno_a2xx.o \ adreno_a2xx_trace.o \ adreno_a2xx_snapshot.o \ adreno_a3xx.o \ + adreno_a4xx.o \ adreno_a3xx_trace.o \ adreno_a3xx_snapshot.o \ - adreno.o + adreno.o \ + adreno_cp_parser.o msm_adreno-$(CONFIG_DEBUG_FS) += adreno_debugfs.o diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h index 21d475954fb..676f46da39a 100644 --- a/drivers/gpu/msm/a3xx_reg.h +++ b/drivers/gpu/msm/a3xx_reg.h @@ -165,8 +165,16 @@ #define A3XX_RBBM_PERFCTR_PWR_0_HI 0x0EB #define A3XX_RBBM_PERFCTR_PWR_1_LO 0x0EC #define A3XX_RBBM_PERFCTR_PWR_1_HI 0x0ED -#define A3XX_RBBM_DEBUG_BUS_CTL 0x111 -#define A3XX_RBBM_DEBUG_BUS_DATA_STATUS 0x112 +#define A3XX_RBBM_DEBUG_BUS_CTL 0x111 +#define A3XX_RBBM_DEBUG_BUS_DATA_STATUS 0x112 +#define A3XX_RBBM_DEBUG_BUS_STB_CTL0 0x11B +#define A3XX_RBBM_DEBUG_BUS_STB_CTL1 0x11C +#define A3XX_RBBM_INT_TRACE_BUS_CTL 0x11D +#define A3XX_RBBM_EXT_TRACE_BUS_CTL 0x11E +#define A3XX_RBBM_EXT_TRACE_STOP_CNT 0x11F +#define A3XX_RBBM_EXT_TRACE_START_CNT 0x120 +#define A3XX_RBBM_EXT_TRACE_PERIOD_CNT 0x121 +#define A3XX_RBBM_EXT_TRACE_CMD 0x122 /* Following two are same as on A2XX, just in a different place */ #define A3XX_CP_PFP_UCODE_ADDR 0x1C9 @@ -179,6 +187,7 @@ #define A3XX_CP_MEQ_ADDR 0x1DA #define A3XX_CP_MEQ_DATA 0x1DB #define A3XX_CP_PERFCOUNTER_SELECT 0x445 +#define A3XX_CP_WFI_PEND_CTR 0x01F5 #define A3XX_CP_HW_FAULT 0x45C #define A3XX_CP_AHB_FAULT 0x54D #define A3XX_CP_PROTECT_CTRL 0x45E @@ -231,6 +240,7 @@ #define A3XX_PC_PERFCOUNTER1_SELECT 0xC49 #define A3XX_PC_PERFCOUNTER2_SELECT 0xC4A #define A3XX_PC_PERFCOUNTER3_SELECT 0xC4B +#define A3XX_GRAS_TSE_DEBUG_ECO 0xC81 #define A3XX_GRAS_PERFCOUNTER0_SELECT 0xC88 #define A3XX_GRAS_PERFCOUNTER1_SELECT 0xC89 #define A3XX_GRAS_PERFCOUNTER2_SELECT 0xC8A @@ -260,8 +270,10 @@ #define A3XX_GRAS_CL_USER_PLANE_Z5 0xCB6 #define A3XX_GRAS_CL_USER_PLANE_W5 0xCB7 #define A3XX_RB_GMEM_BASE_ADDR 0xCC0 +#define A3XX_RB_DEBUG_ECO_CONTROLS_ADDR 0xCC1 #define A3XX_RB_PERFCOUNTER0_SELECT 0xCC6 #define A3XX_RB_PERFCOUNTER1_SELECT 0xCC7 +#define A3XX_RB_FRAME_BUFFER_DIMENSION 0xCE0 #define A3XX_HLSQ_PERFCOUNTER0_SELECT 0xE00 #define A3XX_HLSQ_PERFCOUNTER1_SELECT 0xE01 #define A3XX_HLSQ_PERFCOUNTER2_SELECT 0xE02 @@ -299,6 +311,9 @@ #define A3XX_GRAS_CL_CLIP_CNTL 0x2040 #define A3XX_GRAS_CL_GB_CLIP_ADJ 0x2044 #define A3XX_GRAS_CL_VPORT_XOFFSET 0x2048 +#define A3XX_GRAS_CL_VPORT_XSCALE 0x2049 +#define A3XX_GRAS_CL_VPORT_YOFFSET 0x204A +#define A3XX_GRAS_CL_VPORT_YSCALE 0x204B #define A3XX_GRAS_CL_VPORT_ZOFFSET 0x204C #define A3XX_GRAS_CL_VPORT_ZSCALE 0x204D #define A3XX_GRAS_SU_POINT_MINMAX 0x2068 @@ -314,30 +329,75 @@ #define A3XX_RB_MODE_CONTROL 0x20C0 #define A3XX_RB_RENDER_CONTROL 0x20C1 #define A3XX_RB_MSAA_CONTROL 0x20C2 +#define A3XX_RB_ALPHA_REFERENCE 0x20C3 #define A3XX_RB_MRT_CONTROL0 0x20C4 #define A3XX_RB_MRT_BUF_INFO0 0x20C5 +#define A3XX_RB_MRT_BUF_BASE0 0x20C6 #define A3XX_RB_MRT_BLEND_CONTROL0 0x20C7 +#define A3XX_RB_MRT_CONTROL1 0x20C8 +#define A3XX_RB_MRT_BUF_INFO1 0x20C9 +#define A3XX_RB_MRT_BUF_BASE1 0x20CA #define A3XX_RB_MRT_BLEND_CONTROL1 0x20CB +#define A3XX_RB_MRT_CONTROL2 0x20CC +#define A3XX_RB_MRT_BUF_INFO2 0x20CD +#define A3XX_RB_MRT_BUF_BASE2 0x20CE #define A3XX_RB_MRT_BLEND_CONTROL2 0x20CF +#define A3XX_RB_MRT_CONTROL3 0x20D0 +#define A3XX_RB_MRT_BUF_INFO3 0x20D1 +#define A3XX_RB_MRT_BUF_BASE3 0x20D2 #define A3XX_RB_MRT_BLEND_CONTROL3 0x20D3 #define A3XX_RB_BLEND_RED 0x20E4 +#define A3XX_RB_BLEND_GREEN 0x20E5 +#define A3XX_RB_BLEND_BLUE 0x20E6 +#define A3XX_RB_BLEND_ALPHA 0x20E7 +#define A3XX_RB_CLEAR_COLOR_DW0 0x20E8 +#define A3XX_RB_CLEAR_COLOR_DW1 0x20E9 +#define A3XX_RB_CLEAR_COLOR_DW2 0x20EA +#define A3XX_RB_CLEAR_COLOR_DW3 0x20EB #define A3XX_RB_COPY_CONTROL 0x20EC +#define A3XX_RB_COPY_DEST_BASE 0x20ED +#define A3XX_RB_COPY_DEST_PITCH 0x20EE #define A3XX_RB_COPY_DEST_INFO 0x20EF #define A3XX_RB_DEPTH_CONTROL 0x2100 +#define A3XX_RB_DEPTH_CLEAR 0x2101 +#define A3XX_RB_DEPTH_BUF_INFO 0x2102 +#define A3XX_RB_DEPTH_BUF_PITCH 0x2103 #define A3XX_RB_STENCIL_CONTROL 0x2104 +#define A3XX_RB_STENCIL_CLEAR 0x2105 +#define A3XX_RB_STENCIL_BUF_INFO 0x2106 +#define A3XX_RB_STENCIL_BUF_PITCH 0x2107 +#define A3XX_RB_STENCIL_REF_MASK 0x2108 +#define A3XX_RB_STENCIL_REF_MASK_BF 0x2109 +#define A3XX_RB_LRZ_VSC_CONTROL 0x210C +#define A3XX_RB_WINDOW_OFFSET 0x210E +#define A3XX_RB_SAMPLE_COUNT_CONTROL 0x2110 +#define A3XX_RB_SAMPLE_COUNT_ADDR 0x2111 +#define A3XX_RB_Z_CLAMP_MIN 0x2114 +#define A3XX_RB_Z_CLAMP_MAX 0x2115 #define A3XX_PC_VSTREAM_CONTROL 0x21E4 #define A3XX_PC_VERTEX_REUSE_BLOCK_CNTL 0x21EA #define A3XX_PC_PRIM_VTX_CNTL 0x21EC #define A3XX_PC_RESTART_INDEX 0x21ED #define A3XX_HLSQ_CONTROL_0_REG 0x2200 +#define A3XX_HLSQ_CONTROL_1_REG 0x2201 +#define A3XX_HLSQ_CONTROL_2_REG 0x2202 +#define A3XX_HLSQ_CONTROL_3_REG 0x2203 #define A3XX_HLSQ_VS_CONTROL_REG 0x2204 +#define A3XX_HLSQ_FS_CONTROL_REG 0x2205 +#define A3XX_HLSQ_CONST_VSPRESV_RANGE_REG 0x2206 #define A3XX_HLSQ_CONST_FSPRESV_RANGE_REG 0x2207 #define A3XX_HLSQ_CL_NDRANGE_0_REG 0x220A +#define A3XX_HLSQ_CL_NDRANGE_1_REG 0x220B #define A3XX_HLSQ_CL_NDRANGE_2_REG 0x220C +#define A3XX_HLSQ_CL_NDRANGE_3_REG 0x220D +#define A3XX_HLSQ_CL_NDRANGE_4_REG 0x220E +#define A3XX_HLSQ_CL_NDRANGE_5_REG 0x220F +#define A3XX_HLSQ_CL_NDRANGE_6_REG 0x2210 #define A3XX_HLSQ_CL_CONTROL_0_REG 0x2211 #define A3XX_HLSQ_CL_CONTROL_1_REG 0x2212 #define A3XX_HLSQ_CL_KERNEL_CONST_REG 0x2214 #define A3XX_HLSQ_CL_KERNEL_GROUP_X_REG 0x2215 +#define A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG 0x2216 #define A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG 0x2217 #define A3XX_HLSQ_CL_WG_OFFSET_REG 0x221A #define A3XX_VFD_CONTROL_0 0x2240 @@ -354,10 +414,21 @@ #define A3XX_SP_VS_CTRL_REG0 0x22C4 #define A3XX_SP_VS_CTRL_REG1 0x22C5 #define A3XX_SP_VS_PARAM_REG 0x22C6 +#define A3XX_SP_VS_OUT_REG_0 0x22C7 +#define A3XX_SP_VS_OUT_REG_1 0x22C8 +#define A3XX_SP_VS_OUT_REG_2 0x22C9 +#define A3XX_SP_VS_OUT_REG_3 0x22CA +#define A3XX_SP_VS_OUT_REG_4 0x22CB +#define A3XX_SP_VS_OUT_REG_5 0x22CC +#define A3XX_SP_VS_OUT_REG_6 0x22CD #define A3XX_SP_VS_OUT_REG_7 0x22CE #define A3XX_SP_VS_VPC_DST_REG_0 0x22D0 +#define A3XX_SP_VS_VPC_DST_REG_1 0x22D1 +#define A3XX_SP_VS_VPC_DST_REG_2 0x22D2 +#define A3XX_SP_VS_VPC_DST_REG_3 0x22D3 #define A3XX_SP_VS_OBJ_OFFSET_REG 0x22D4 #define A3XX_SP_VS_OBJ_START_REG 0x22D5 +#define A3XX_SP_VS_PVT_MEM_PARAM_REG 0x22D6 #define A3XX_SP_VS_PVT_MEM_ADDR_REG 0x22D7 #define A3XX_SP_VS_PVT_MEM_SIZE_REG 0x22D8 #define A3XX_SP_VS_LENGTH_REG 0x22DF @@ -365,13 +436,19 @@ #define A3XX_SP_FS_CTRL_REG1 0x22E1 #define A3XX_SP_FS_OBJ_OFFSET_REG 0x22E2 #define A3XX_SP_FS_OBJ_START_REG 0x22E3 +#define A3XX_SP_FS_PVT_MEM_PARAM_REG 0x22E4 #define A3XX_SP_FS_PVT_MEM_ADDR_REG 0x22E5 #define A3XX_SP_FS_PVT_MEM_SIZE_REG 0x22E6 #define A3XX_SP_FS_FLAT_SHAD_MODE_REG_0 0x22E8 #define A3XX_SP_FS_FLAT_SHAD_MODE_REG_1 0x22E9 #define A3XX_SP_FS_OUTPUT_REG 0x22EC #define A3XX_SP_FS_MRT_REG_0 0x22F0 +#define A3XX_SP_FS_MRT_REG_1 0x22F1 +#define A3XX_SP_FS_MRT_REG_2 0x22F2 +#define A3XX_SP_FS_MRT_REG_3 0x22F3 #define A3XX_SP_FS_IMAGE_OUTPUT_REG_0 0x22F4 +#define A3XX_SP_FS_IMAGE_OUTPUT_REG_1 0x22F5 +#define A3XX_SP_FS_IMAGE_OUTPUT_REG_2 0x22F6 #define A3XX_SP_FS_IMAGE_OUTPUT_REG_3 0x22F7 #define A3XX_SP_FS_LENGTH_REG 0x22FF #define A3XX_TPL1_TP_VS_TEX_OFFSET 0x2340 @@ -416,6 +493,9 @@ #define RBBM_RBBM_CTL_ENABLE_PWR_CTR0 BIT(16) #define RBBM_RBBM_CTL_ENABLE_PWR_CTR1 BIT(17) +/* Bit flag for RBMM_PERFCTR_CTL */ +#define RBBM_PERFCTR_CTL_ENABLE BIT(0) + /* Various flags used by the context switch code */ #define SP_MULTI 0 @@ -680,12 +760,14 @@ /* RBBM_CLOCK_CTL default value */ #define A305_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA +#define A305C_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA #define A320_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF -#define A330_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAE +#define A330_RBBM_CLOCK_CTL_DEFAULT 0xBFFCFFFF #define A330v2_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA +#define A305B_RBBM_CLOCK_CTL_DEFAULT 0xAAAAAAAA -#define A330_RBBM_GPR0_CTL_DEFAULT 0x0AE2B8AE -#define A330v2_RBBM_GPR0_CTL_DEFAULT 0x0AA2A8AA +#define A330_RBBM_GPR0_CTL_DEFAULT 0x00000000 +#define A330v2_RBBM_GPR0_CTL_DEFAULT 0x05515455 /* COUNTABLE FOR SP PERFCOUNTER */ #define SP_FS_FULL_ALU_INSTRUCTIONS 0x0E diff --git a/drivers/gpu/msm/a4xx_reg.h b/drivers/gpu/msm/a4xx_reg.h new file mode 100644 index 00000000000..56147f7c415 --- /dev/null +++ b/drivers/gpu/msm/a4xx_reg.h @@ -0,0 +1,92 @@ +/* Copyright (c) 2013, 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. + * + */ + +#ifndef _A4XX_REG_H +#define _A4XX_REG_H + +/* RB registers */ +#define A4XX_RB_GMEM_BASE_ADDR 0xcc0 + +/* RBBM registers */ +#define A4XX_RBBM_AHB_CMD 0x25 +#define A4XX_RBBM_SP_HYST_CNT 0x21 +#define A4XX_RBBM_AHB_CTL0 0x23 +#define A4XX_RBBM_AHB_CTL1 0x24 +#define A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL 0x2b +#define A4XX_RBBM_INTERFACE_HANG_INT_CTL 0x2f +#define A4XX_RBBM_AHB_ERROR_STATUS 0x18f +#define A4XX_RBBM_STATUS 0x191 +#define A4XX_RBBM_INT_CLEAR_CMD 0x36 +#define A4XX_RBBM_INT_0_MASK 0x37 +#define A4XX_RBBM_INT_0_STATUS 0x17d +#define A4XX_RBBM_PERFCTR_CTL 0x170 +#define A4XX_RBBM_PERFCTR_LOAD_CMD0 0x171 +#define A4XX_RBBM_PERFCTR_LOAD_CMD1 0x172 +#define A4XX_RBBM_PERFCTR_LOAD_CMD2 0x173 +#define A4XX_RBBM_GPU_BUSY_MASKED 0x17a +#define A4XX_RBBM_PERFCTR_PWR_1_LO 0x168 + +/* CP registers */ +#define A4XX_CP_SCRATCH_REG0 0x578 +#define A4XX_CP_SCRATCH_UMASK 0x228 +#define A4XX_CP_SCRATCH_ADDR 0x229 +#define A4XX_CP_RB_BASE 0x200 +#define A4XX_CP_RB_CNTL 0x201 +#define A4XX_CP_RB_WPTR 0x205 +#define A4XX_CP_RB_RPTR_ADDR 0x203 +#define A4XX_CP_RB_RPTR 0x204 +#define A4XX_CP_IB1_BASE 0x206 +#define A4XX_CP_IB1_BUFSZ 0x207 +#define A4XX_CP_IB2_BASE 0x208 +#define A4XX_CP_IB2_BUFSZ 0x209 +#define A4XX_CP_WFI_PEND_CTR 0x4d2 +#define A4XX_CP_ME_CNTL 0x22d +#define A4XX_CP_ME_RAM_WADDR 0x225 +#define A4XX_CP_ME_RAM_RADDR 0x226 +#define A4XX_CP_ME_RAM_DATA 0x227 +#define A4XX_CP_PFP_UCODE_ADDR 0x223 +#define A4XX_CP_PFP_UCODE_DATA 0x224 +#define A4XX_CP_PROTECT_CTRL 0x250 +#define A4XX_CP_DEBUG 0x22e + +/* SP registers */ +#define A4XX_SP_VS_OBJ_START 0x22e1 +#define A4XX_SP_VS_PVT_MEM_ADDR 0x22e3 +#define A4XX_SP_FS_OBJ_START 0x22eb +#define A4XX_SP_FS_PVT_MEM_ADDR 0x22ed + +/* VPC registers */ +#define A4XX_VPC_DEBUG_RAM_SEL 0xe60 +#define A4XX_VPC_DEBUG_RAM_READ 0xe61 + +/* VSC registers */ +#define A4XX_VSC_SIZE_ADDRESS 0xc01 +#define A4XX_VSC_PIPE_DATA_ADDRESS_0 0xc10 +#define A4XX_VSC_PIPE_DATA_LENGTH_7 0xc1f + +/* VFD registers */ +#define A4XX_VFD_CONTROL_0 0x2200 +#define A4XX_VFD_FETCH_INSTR_0_0 0x220a +#define A4XX_VFD_FETCH_INSTR_1_31 0x2287 + +/* VBIF */ +#define A4XX_VBIF_ABIT_SORT 0x301c +#define A4XX_VBIF_ABIT_SORT_CONF 0x301d +#define A4XX_VBIF_GATE_OFF_WRREQ_EN 0x302a +#define A4XX_VBIF_IN_RD_LIM_CONF0 0x302c +#define A4XX_VBIF_IN_RD_LIM_CONF1 0x302d +#define A4XX_VBIF_IN_WR_LIM_CONF0 0x3030 +#define A4XX_VBIF_IN_WR_LIM_CONF1 0x3031 +#define A4XX_VBIF_ROUND_ROBIN_QOS_ARB 0x3049 + +#endif /* _A400_REG_H */ diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c index 4eb982186e7..9c9b7613a43 100644 --- a/drivers/gpu/msm/adreno.c +++ b/drivers/gpu/msm/adreno.c @@ -18,12 +18,12 @@ #include #include #include +#include +#include #include #include #include -#include -#include #include "kgsl.h" #include "kgsl_pwrscale.h" @@ -41,6 +41,9 @@ #define DRIVER_VERSION_MAJOR 3 #define DRIVER_VERSION_MINOR 1 +/* Number of times to try hard reset */ +#define NUM_TIMES_RESET_RETRY 5 + /* Adreno MH arbiter config*/ #define ADRENO_CFG_MHARB \ (0x10 \ @@ -73,6 +76,8 @@ | (MMU_CONFIG << MH_MMU_CONFIG__TC_R_CLNT_BEHAVIOR__SHIFT) \ | (MMU_CONFIG << MH_MMU_CONFIG__PA_W_CLNT_BEHAVIOR__SHIFT)) +#define KGSL_LOG_LEVEL_DEFAULT 3 + static const struct kgsl_functable adreno_functable; static struct adreno_device device_3d0 = { @@ -100,14 +105,14 @@ static struct adreno_device device_3d0 = { .irq_name = KGSL_3D0_IRQ, }, .iomemname = KGSL_3D0_REG_MEMORY, + .shadermemname = KGSL_3D0_SHADER_MEMORY, .ftbl = &adreno_functable, -#ifdef CONFIG_HAS_EARLYSUSPEND - .display_off = { - .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING, - .suspend = kgsl_early_suspend_driver, - .resume = kgsl_late_resume_driver, - }, -#endif + .cmd_log = KGSL_LOG_LEVEL_DEFAULT, + .ctxt_log = KGSL_LOG_LEVEL_DEFAULT, + .drv_log = KGSL_LOG_LEVEL_DEFAULT, + .mem_log = KGSL_LOG_LEVEL_DEFAULT, + .pwr_log = KGSL_LOG_LEVEL_DEFAULT, + .pm_dump_enable = 0, }, .gmem_base = 0, .gmem_size = SZ_256K, @@ -115,25 +120,13 @@ static struct adreno_device device_3d0 = { .pm4_fw = NULL, .wait_timeout = 0, /* in milliseconds, 0 means disabled */ .ib_check_level = 0, + .ft_policy = KGSL_FT_DEFAULT_POLICY, + .ft_pf_policy = KGSL_FT_PAGEFAULT_DEFAULT_POLICY, + .fast_hang_detect = 1, + .long_ib_detect = 1, }; -#define LONG_IB_DETECT_REG_INDEX_START 1 -#define LONG_IB_DETECT_REG_INDEX_END 5 - -unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT] = { - A3XX_RBBM_STATUS, - REG_CP_RB_RPTR, /* LONG_IB_DETECT_REG_INDEX_START */ - REG_CP_IB1_BASE, - REG_CP_IB1_BUFSZ, - REG_CP_IB2_BASE, - REG_CP_IB2_BUFSZ, /* LONG_IB_DETECT_REG_INDEX_END */ - 0, - 0, - 0, - 0, - 0, - 0 -}; +unsigned int ft_detect_regs[FT_DETECT_REGS_COUNT]; /* * This is the master list of all GPU cores that are supported by this @@ -156,11 +149,20 @@ static const struct { /* size of gmem for gpu*/ unsigned int gmem_size; /* version of pm4 microcode that supports sync_lock - between CPU and GPU for SMMU-v1 programming */ + between CPU and GPU for IOMMU-v0 programming */ unsigned int sync_lock_pm4_ver; /* version of pfp microcode that supports sync_lock - between CPU and GPU for SMMU-v1 programming */ + between CPU and GPU for IOMMU-v0 programming */ unsigned int sync_lock_pfp_ver; + /* PM4 jump table index */ + unsigned int pm4_jt_idx; + /* PM4 jump table load addr */ + unsigned int pm4_jt_addr; + /* PFP jump table index */ + unsigned int pfp_jt_idx; + /* PFP jump table load addr */ + unsigned int pfp_jt_addr; + } adreno_gpulist[] = { { ADRENO_REV_A200, 0, 2, ANY_ID, ANY_ID, "yamato_pm4.fw", "yamato_pfp.fw", &adreno_a2xx_gpudev, @@ -188,7 +190,7 @@ static const struct { "a225_pm4.fw", "a225_pfp.fw", &adreno_a2xx_gpudev, 1536, 768, 3, SZ_512K, 0x225011, 0x225002 }, /* A3XX doesn't use the pix_shader_start */ - { ADRENO_REV_A305, 3, 0, 5, ANY_ID, + { ADRENO_REV_A305, 3, 0, 5, 0, "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev, 512, 0, 2, SZ_256K, 0x3FF037, 0x3FF016 }, /* A3XX doesn't use the pix_shader_start */ @@ -197,7 +199,22 @@ static const struct { 512, 0, 2, SZ_512K, 0x3FF037, 0x3FF016 }, { ADRENO_REV_A330, 3, 3, 0, ANY_ID, "a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev, - 512, 0, 2, SZ_1M, NO_VER, NO_VER }, + 512, 0, 2, SZ_1M, NO_VER, NO_VER, 0x8AD, 0x2E4, 0x201, 0x200 }, + { ADRENO_REV_A305B, 3, 0, 5, 0x10, + "a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev, + 512, 0, 2, SZ_128K, NO_VER, NO_VER, 0x8AD, 0x2E4, + 0x201, 0x200 }, + /* 8226v2 */ + { ADRENO_REV_A305B, 3, 0, 5, 0x12, + "a330_pm4.fw", "a330_pfp.fw", &adreno_a3xx_gpudev, + 512, 0, 2, SZ_128K, NO_VER, NO_VER, 0x8AD, 0x2E4, + 0x201, 0x200 }, + { ADRENO_REV_A305C, 3, 0, 5, 0x20, + "a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev, + 512, 0, 2, SZ_128K, 0x3FF037, 0x3FF016 }, + { ADRENO_REV_A420, 4, 2, 0, ANY_ID, + "a420_pm4.fw", "a420_pfp.fw", &adreno_a4xx_gpudev, + 512, 0, 2, (SZ_1M + SZ_512K), NO_VER, NO_VER }, }; /** @@ -211,14 +228,28 @@ static const struct { * performance counters will remain active as long as the device is alive. */ -static void adreno_perfcounter_init(struct kgsl_device *device) +static int adreno_perfcounter_init(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); if (adreno_dev->gpudev->perfcounter_init) - adreno_dev->gpudev->perfcounter_init(adreno_dev); + return adreno_dev->gpudev->perfcounter_init(adreno_dev); + return 0; }; +/** + * adreno_perfcounter_close: Release counters initialized by + * adreno_perfcounter_init + * @device: device to realease counters for + * + */ +static void adreno_perfcounter_close(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + if (adreno_dev->gpudev->perfcounter_close) + return adreno_dev->gpudev->perfcounter_close(adreno_dev); +} + /** * adreno_perfcounter_start: Enable performance counters * @adreno_dev: Adreno device to configure @@ -226,14 +257,18 @@ static void adreno_perfcounter_init(struct kgsl_device *device) * Ensure all performance counters are enabled that are allocated. Since * the device was most likely stopped, we can't trust that the counters * are still valid so make it so. + * Returns 0 on success else error code */ -static void adreno_perfcounter_start(struct adreno_device *adreno_dev) +static int adreno_perfcounter_start(struct adreno_device *adreno_dev) { struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; struct adreno_perfcount_group *group; unsigned int i, j; + int ret = 0; + if (NULL == counters) + return 0; /* group id iter */ for (i = 0; i < counters->group_count; i++) { group = &(counters->groups[i]); @@ -241,15 +276,21 @@ static void adreno_perfcounter_start(struct adreno_device *adreno_dev) /* countable iter */ for (j = 0; j < group->reg_count; j++) { if (group->regs[j].countable == - KGSL_PERFCOUNTER_NOT_USED) + KGSL_PERFCOUNTER_NOT_USED || + group->regs[j].countable == + KGSL_PERFCOUNTER_BROKEN) continue; if (adreno_dev->gpudev->perfcounter_enable) - adreno_dev->gpudev->perfcounter_enable( + ret = adreno_dev->gpudev->perfcounter_enable( adreno_dev, i, j, group->regs[j].countable); + if (ret) + goto done; } } +done: + return ret; } /** @@ -271,8 +312,7 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev, unsigned int i, j; int ret = 0; - /* perfcounter get/put/query/read not allowed on a2xx */ - if (adreno_is_a2xx(adreno_dev)) + if (NULL == counters) return -EINVAL; /* sanity check for later */ @@ -283,11 +323,6 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev, if (reads == NULL || count == 0 || count > 100) return -EINVAL; - /* verify valid inputs group ids and countables */ - for (i = 0; i < count; i++) { - if (reads[i].groupid >= counters->group_count) - return -EINVAL; - } list = kmalloc(sizeof(struct kgsl_perfcounter_read_group) * count, GFP_KERNEL); @@ -300,6 +335,12 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev, goto done; } + /* verify valid inputs group ids and countables */ + for (i = 0; i < count; i++) { + if (list[i].groupid >= counters->group_count) + return -EINVAL; + } + /* list iterator */ for (j = 0; j < count; j++) { list[j].value = 0; @@ -311,8 +352,7 @@ int adreno_perfcounter_read_group(struct adreno_device *adreno_dev, if (group->regs[i].countable == list[j].countable) { list[j].value = adreno_dev->gpudev->perfcounter_read( - adreno_dev, list[j].groupid, - i, group->regs[i].offset); + adreno_dev, list[j].groupid, i); break; } } @@ -350,8 +390,7 @@ int adreno_perfcounter_query_group(struct adreno_device *adreno_dev, *max_counters = 0; - /* perfcounter get/put/query not allowed on a2xx */ - if (adreno_is_a2xx(adreno_dev)) + if (NULL == counters) return -EINVAL; if (groupid >= counters->group_count) @@ -400,13 +439,13 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; struct adreno_perfcount_group *group; unsigned int i, empty = -1; + int ret = 0; /* always clear return variables */ if (offset) *offset = 0; - /* perfcounter get/put/query not allowed on a2xx */ - if (adreno_is_a2xx(adreno_dev)) + if (NULL == counters) return -EINVAL; if (groupid >= counters->group_count) @@ -422,8 +461,11 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, for (i = 0; i < group->reg_count; i++) { if (group->regs[i].countable == countable) { /* Countable already associated with counter */ - group->regs[i].refcount++; - group->regs[i].flags |= flags; + if (flags & PERFCOUNTER_FLAG_KERNEL) + group->regs[i].kernelcount++; + else + group->regs[i].usercount++; + if (offset) *offset = group->regs[i].offset; return 0; @@ -438,20 +480,27 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, if (empty == -1) return -EBUSY; - /* initialize the new counter */ - group->regs[empty].countable = countable; - group->regs[empty].refcount = 1; - /* enable the new counter */ - adreno_dev->gpudev->perfcounter_enable(adreno_dev, groupid, empty, + ret = adreno_dev->gpudev->perfcounter_enable(adreno_dev, groupid, empty, countable); + if (ret) + return ret; + /* initialize the new counter */ + group->regs[empty].countable = countable; - group->regs[empty].flags = flags; + /* set initial kernel and user count */ + if (flags & PERFCOUNTER_FLAG_KERNEL) { + group->regs[empty].kernelcount = 1; + group->regs[empty].usercount = 0; + } else { + group->regs[empty].kernelcount = 0; + group->regs[empty].usercount = 1; + } if (offset) *offset = group->regs[empty].offset; - return 0; + return ret; } @@ -460,20 +509,20 @@ int adreno_perfcounter_get(struct adreno_device *adreno_dev, * @adreno_dev: Adreno device to configure * @groupid: Desired performance counter group * @countable: Countable desired to be freed from a counter + * @flags: Flag to determine if kernel or user space request * * Put a performance counter/countable pair that was previously received. If * noone else is using the countable, free up the counter for others. */ int adreno_perfcounter_put(struct adreno_device *adreno_dev, - unsigned int groupid, unsigned int countable) + unsigned int groupid, unsigned int countable, unsigned int flags) { struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; struct adreno_perfcount_group *group; unsigned int i; - /* perfcounter get/put/query not allowed on a2xx */ - if (adreno_is_a2xx(adreno_dev)) + if (NULL == counters) return -EINVAL; if (groupid >= counters->group_count) @@ -481,24 +530,27 @@ int adreno_perfcounter_put(struct adreno_device *adreno_dev, group = &(counters->groups[groupid]); + /* + * Find if the counter/countable pair is used currently. + * Start cycling through registers in the bank. + */ for (i = 0; i < group->reg_count; i++) { + /* check if countable assigned is what we are looking for */ if (group->regs[i].countable == countable) { - if (group->regs[i].refcount > 0) { - group->regs[i].refcount--; + /* found pair, book keep count based on request type */ + if (flags & PERFCOUNTER_FLAG_KERNEL && + group->regs[i].kernelcount > 0) + group->regs[i].kernelcount--; + else if (group->regs[i].usercount > 0) + group->regs[i].usercount--; + else + break; - /* - * book keeping to ensure we never free a - * perf counter used by kernel - */ - if (group->regs[i].flags && - group->regs[i].refcount == 0) - group->regs[i].refcount++; - - /* make available if not used */ - if (group->regs[i].refcount == 0) - group->regs[i].countable = - KGSL_PERFCOUNTER_NOT_USED; - } + /* mark available if not used anymore */ + if (group->regs[i].kernelcount == 0 && + group->regs[i].usercount == 0) + group->regs[i].countable = + KGSL_PERFCOUNTER_NOT_USED; return 0; } @@ -526,31 +578,40 @@ static void adreno_cleanup_pt(struct kgsl_device *device, kgsl_mmu_unmap(pagetable, &device->memstore); + kgsl_mmu_unmap(pagetable, &adreno_dev->pwron_fixup); + kgsl_mmu_unmap(pagetable, &device->mmu.setstate_memory); } static int adreno_setup_pt(struct kgsl_device *device, struct kgsl_pagetable *pagetable) { - int result = 0; + int result; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; result = kgsl_mmu_map_global(pagetable, &rb->buffer_desc); - if (result) - goto error; - result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc); - if (result) - goto unmap_buffer_desc; + if (!result) + result = kgsl_mmu_map_global(pagetable, &rb->memptrs_desc); - result = kgsl_mmu_map_global(pagetable, &device->memstore); - if (result) - goto unmap_memptrs_desc; + if (!result) + result = kgsl_mmu_map_global(pagetable, &device->memstore); + + if (!result) + result = kgsl_mmu_map_global(pagetable, + &adreno_dev->pwron_fixup); - result = kgsl_mmu_map_global(pagetable, &device->mmu.setstate_memory); - if (result) - goto unmap_memstore_desc; + + if (!result) + result = kgsl_mmu_map_global(pagetable, + &device->mmu.setstate_memory); + + if (result) { + /* On error clean up what we have wrought */ + adreno_cleanup_pt(device, pagetable); + return result; + } /* * Set the mpu end to the last "normal" global memory we use. @@ -559,61 +620,19 @@ static int adreno_setup_pt(struct kgsl_device *device, */ device->mh.mpu_range = device->mmu.setstate_memory.gpuaddr + device->mmu.setstate_memory.size; - return result; - -unmap_memstore_desc: - kgsl_mmu_unmap(pagetable, &device->memstore); - -unmap_memptrs_desc: - kgsl_mmu_unmap(pagetable, &rb->memptrs_desc); - -unmap_buffer_desc: - kgsl_mmu_unmap(pagetable, &rb->buffer_desc); -error: - return result; + return 0; } -static int adreno_iommu_setstate(struct kgsl_device *device, - unsigned int context_id, - uint32_t flags) +static unsigned int _adreno_iommu_setstate_v0(struct kgsl_device *device, + unsigned int *cmds_orig, + phys_addr_t pt_val, + int num_iommu_units, uint32_t flags) { - unsigned int pt_val, reg_pt_val; - unsigned int link[250]; - unsigned int *cmds = &link[0]; - int sizedwords = 0; + phys_addr_t reg_pt_val; + unsigned int *cmds = cmds_orig; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - int num_iommu_units, i; - struct kgsl_context *context; - struct adreno_context *adreno_ctx = NULL; - int result = 0; - - /* - * If we're idle and we don't need to use the GPU to save context - * state, use the CPU instead of the GPU to reprogram the - * iommu for simplicity's sake. - */ - if (!adreno_dev->drawctxt_active || device->ftbl->isidle(device) || - !atomic_read(&device->active_cnt)) - return kgsl_mmu_device_setstate(&device->mmu, flags); - - num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu); - - context = kgsl_context_get(device, context_id); - - if (context == NULL) - return 0; - - adreno_ctx = ADRENO_CONTEXT(context); - - result = kgsl_mmu_enable_clk(&device->mmu, KGSL_IOMMU_CONTEXT_USER); - - if (result) - goto done; - - cmds += __adreno_add_idle_indirect_cmds(cmds, - device->mmu.setstate_memory.gpuaddr + - KGSL_IOMMU_SETSTATE_NOP_OFFSET); + int i; if (cpu_is_msm8960()) cmds += adreno_add_change_mh_phys_limit_cmds(cmds, 0xFFFFF000, @@ -630,16 +649,16 @@ static int adreno_iommu_setstate(struct kgsl_device *device, /* Acquire GPU-CPU sync Lock here */ cmds += kgsl_mmu_sync_lock(&device->mmu, cmds); - pt_val = kgsl_mmu_get_pt_base_addr(&device->mmu, - device->mmu.hwpagetable); if (flags & KGSL_MMUFLAGS_PTUPDATE) { /* * We need to perfrom the following operations for all * IOMMU units */ for (i = 0; i < num_iommu_units; i++) { - reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu, - i, KGSL_IOMMU_CONTEXT_USER)); + reg_pt_val = kgsl_mmu_get_default_ttbr0(&device->mmu, + i, KGSL_IOMMU_CONTEXT_USER); + reg_pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + reg_pt_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK); /* * Set address of the new pagetable by writng to IOMMU * TTBR0 register @@ -668,8 +687,11 @@ static int adreno_iommu_setstate(struct kgsl_device *device, * tlb flush */ for (i = 0; i < num_iommu_units; i++) { - reg_pt_val = (pt_val + kgsl_mmu_get_pt_lsb(&device->mmu, + reg_pt_val = (pt_val + kgsl_mmu_get_default_ttbr0( + &device->mmu, i, KGSL_IOMMU_CONTEXT_USER)); + reg_pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + reg_pt_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK); *cmds++ = cp_type3_packet(CP_MEM_WRITE, 2); *cmds++ = kgsl_mmu_get_reg_gpuaddr(&device->mmu, i, @@ -708,36 +730,206 @@ static int adreno_iommu_setstate(struct kgsl_device *device, cmds += adreno_add_idle_cmds(adreno_dev, cmds); - sizedwords += (cmds - &link[0]); - if (sizedwords) { - - /* invalidate all base pointers */ - *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1); - *cmds++ = 0x7fff; - sizedwords += 2; - /* This returns the per context timestamp but we need to - * use the global timestamp for iommu clock disablement */ - result = adreno_ringbuffer_issuecmds(device, adreno_ctx, - KGSL_CMD_FLAGS_PMODE, - &link[0], sizedwords); + return cmds - cmds_orig; +} - if (result) { - /* On error disable the IOMMU clock right away */ - kgsl_mmu_disable_clk(&device->mmu); - goto done; +static unsigned int _adreno_iommu_setstate_v1(struct kgsl_device *device, + unsigned int *cmds_orig, + phys_addr_t pt_val, + int num_iommu_units, uint32_t flags) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + phys_addr_t ttbr0_val; + unsigned int reg_pt_val; + unsigned int *cmds = cmds_orig; + int i; + unsigned int ttbr0, tlbiall, tlbstatus, tlbsync, mmu_ctrl; + + for (i = 0; i < num_iommu_units; i++) { + ttbr0_val = kgsl_mmu_get_default_ttbr0(&device->mmu, + i, KGSL_IOMMU_CONTEXT_USER); + ttbr0_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + ttbr0_val |= (pt_val & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK); + if (flags & KGSL_MMUFLAGS_PTUPDATE) { + mmu_ctrl = kgsl_mmu_get_reg_ahbaddr( + &device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL) >> 2; + + ttbr0 = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TTBR0) >> 2; + + if (kgsl_mmu_hw_halt_supported(&device->mmu, i)) { + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0; + /* + * glue commands together until next + * WAIT_FOR_ME + */ + cmds += adreno_wait_reg_eq(cmds, + adreno_getreg(adreno_dev, + ADRENO_REG_CP_WFI_PEND_CTR), + 1, 0xFFFFFFFF, 0xF); + + /* set the iommu lock bit */ + *cmds++ = cp_type3_packet(CP_REG_RMW, 3); + *cmds++ = mmu_ctrl; + /* AND to unmask the lock bit */ + *cmds++ = + ~(KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT); + /* OR to set the IOMMU lock bit */ + *cmds++ = + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT; + /* wait for smmu to lock */ + cmds += adreno_wait_reg_eq(cmds, mmu_ctrl, + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE, + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE, 0xF); + } + /* set ttbr0 */ + if (sizeof(phys_addr_t) > sizeof(unsigned long)) { + reg_pt_val = ttbr0_val & 0xFFFFFFFF; + *cmds++ = cp_type0_packet(ttbr0, 1); + *cmds++ = reg_pt_val; + reg_pt_val = (unsigned int) + ((ttbr0_val & 0xFFFFFFFF00000000ULL) >> 32); + *cmds++ = cp_type0_packet(ttbr0 + 1, 1); + *cmds++ = reg_pt_val; + } else { + reg_pt_val = ttbr0_val; + *cmds++ = cp_type0_packet(ttbr0, 1); + *cmds++ = reg_pt_val; + } + if (kgsl_mmu_hw_halt_supported(&device->mmu, i)) { + /* unlock the IOMMU lock */ + *cmds++ = cp_type3_packet(CP_REG_RMW, 3); + *cmds++ = mmu_ctrl; + /* AND to unmask the lock bit */ + *cmds++ = + ~(KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT); + /* OR with 0 so lock bit is unset */ + *cmds++ = 0; + /* release all commands with wait_for_me */ + *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1); + *cmds++ = 0; + } } + if (flags & KGSL_MMUFLAGS_TLBFLUSH) { + tlbiall = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TLBIALL) >> 2; + *cmds++ = cp_type0_packet(tlbiall, 1); + *cmds++ = 1; - kgsl_mmu_disable_clk_on_ts(&device->mmu, - adreno_dev->ringbuffer.global_ts, true); + tlbsync = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TLBSYNC) >> 2; + *cmds++ = cp_type0_packet(tlbsync, 1); + *cmds++ = 0; - if (result) - goto done; + tlbstatus = kgsl_mmu_get_reg_ahbaddr(&device->mmu, i, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TLBSTATUS) >> 2; + cmds += adreno_wait_reg_eq(cmds, tlbstatus, 0, + KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE, 0xF); + } } + return cmds - cmds_orig; +} + +/** + * adreno_use_default_setstate() - Use CPU instead of the GPU to manage the mmu? + * @adreno_dev: the device + * + * In many cases it is preferable to poke the iommu or gpummu directly rather + * than using the GPU command stream. If we are idle or trying to go to a low + * power state, using the command stream will be slower and asynchronous, which + * needlessly complicates the power state transitions. Additionally, + * the hardware simulators do not support command stream MMU operations so + * the command stream can never be used if we are capturing CFF data. + * + */ +static bool adreno_use_default_setstate(struct adreno_device *adreno_dev) +{ + return (adreno_isidle(&adreno_dev->dev) || + KGSL_STATE_ACTIVE != adreno_dev->dev.state || + atomic_read(&adreno_dev->dev.active_cnt) == 0 || + adreno_dev->dev.cff_dump_enable); +} + +static int adreno_iommu_setstate(struct kgsl_device *device, + unsigned int context_id, + uint32_t flags) +{ + phys_addr_t pt_val; + unsigned int link[230]; + unsigned int *cmds = &link[0]; + int sizedwords = 0; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + int num_iommu_units; + struct kgsl_context *context; + struct adreno_context *adreno_ctx = NULL; + struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; + unsigned int result; + + if (adreno_use_default_setstate(adreno_dev)) { + kgsl_mmu_device_setstate(&device->mmu, flags); + return 0; + } + num_iommu_units = kgsl_mmu_get_num_iommu_units(&device->mmu); + + context = kgsl_context_get(device, context_id); + if (context == NULL) { + kgsl_mmu_device_setstate(&device->mmu, KGSL_CONTEXT_INVALID); + return -EINVAL; + } + + adreno_ctx = ADRENO_CONTEXT(context); + + result = kgsl_mmu_enable_clk(&device->mmu, + KGSL_IOMMU_CONTEXT_USER); + if (result) + goto done; + + pt_val = kgsl_mmu_get_pt_base_addr(&device->mmu, + device->mmu.hwpagetable); + + cmds += __adreno_add_idle_indirect_cmds(cmds, + device->mmu.setstate_memory.gpuaddr + + KGSL_IOMMU_SETSTATE_NOP_OFFSET); + + /* naming mismatch */ + if (msm_soc_version_supports_iommu_v1()) + cmds += _adreno_iommu_setstate_v0(device, cmds, pt_val, + num_iommu_units, flags); + else + cmds += _adreno_iommu_setstate_v1(device, cmds, pt_val, + num_iommu_units, flags); + + sizedwords += (cmds - &link[0]); + if (sizedwords == 0) { + KGSL_DRV_ERR(device, "no commands generated\n"); + BUG(); + } + /* invalidate all base pointers */ + *cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1); + *cmds++ = 0x7fff; + sizedwords += 2; if (sizedwords > (sizeof(link)/sizeof(unsigned int))) { KGSL_DRV_ERR(device, "Temp command buffer overflow\n"); BUG(); } + /* + * This returns the per context timestamp but we need to + * use the global timestamp for iommu clock disablement + */ + adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE, + &link[0], sizedwords); + + kgsl_mmu_disable_clk_on_ts(&device->mmu, + rb->global_ts, true); + done: kgsl_context_put(context); return result; @@ -768,11 +960,10 @@ static int adreno_gpummu_setstate(struct kgsl_device *device, * writes For CFF dump we must idle and use the registers so that it is * easier to filter out the mmu accesses from the dump */ - if (!kgsl_cff_dump_enable && adreno_dev->drawctxt_active) { + if (!adreno_use_default_setstate(adreno_dev)) { context = kgsl_context_get(device, context_id); if (context == NULL) return -EINVAL; - adreno_ctx = ADRENO_CONTEXT(context); if (flags & KGSL_MMUFLAGS_PTUPDATE) { @@ -900,9 +1091,9 @@ a2xx_getchipid(struct kgsl_device *device) if (pdata->chipid != 0) return pdata->chipid; - adreno_regread(device, REG_RBBM_PERIPHID1, &coreid); - adreno_regread(device, REG_RBBM_PERIPHID2, &majorid); - adreno_regread(device, REG_RBBM_PATCH_RELEASE, &revid); + kgsl_regread(device, REG_RBBM_PERIPHID1, &coreid); + kgsl_regread(device, REG_RBBM_PERIPHID2, &majorid); + kgsl_regread(device, REG_RBBM_PATCH_RELEASE, &revid); /* * adreno 22x gpus are indicated by coreid 2, @@ -986,8 +1177,22 @@ adreno_identify_gpu(struct adreno_device *adreno_dev) adreno_dev->pix_shader_start = adreno_gpulist[i].pix_shader_start; adreno_dev->instruction_size = adreno_gpulist[i].instruction_size; adreno_dev->gmem_size = adreno_gpulist[i].gmem_size; + adreno_dev->pm4_jt_idx = adreno_gpulist[i].pm4_jt_idx; + adreno_dev->pm4_jt_addr = adreno_gpulist[i].pm4_jt_addr; + adreno_dev->pfp_jt_idx = adreno_gpulist[i].pfp_jt_idx; + adreno_dev->pfp_jt_addr = adreno_gpulist[i].pfp_jt_addr; adreno_dev->gpulist_index = i; - + /* + * Initialize uninitialzed gpu registers, only needs to be done once + * Make all offsets that are not initialized to ADRENO_REG_UNUSED + */ + for (i = 0; i < ADRENO_REG_REGISTER_MAX; i++) { + if (adreno_dev->gpudev->reg_offsets->offset_0 != i && + !adreno_dev->gpudev->reg_offsets->offsets[i]) { + adreno_dev->gpudev->reg_offsets->offsets[i] = + ADRENO_REG_UNUSED; + } + } } static struct platform_device_id adreno_id_table[] = { @@ -1074,6 +1279,10 @@ static int adreno_of_get_pwrlevels(struct device_node *parent, &pdata->init_level)) pdata->init_level = 1; + if (adreno_of_read_property(parent, "qcom,step-pwrlevel", + &pdata->step_mul)) + pdata->step_mul = 1; + if (pdata->init_level < 0 || pdata->init_level > pdata->num_levels) { KGSL_CORE_ERR("Initial power level out of range\n"); pdata->init_level = 1; @@ -1085,172 +1294,6 @@ static int adreno_of_get_pwrlevels(struct device_node *parent, } -static struct msm_dcvs_core_info *adreno_of_get_dcvs(struct device_node *parent) -{ - struct device_node *node, *child; - struct msm_dcvs_core_info *info = NULL; - int count = 0; - int ret = -EINVAL; - - node = adreno_of_find_subnode(parent, "qcom,dcvs-core-info"); - if (node == NULL) - return ERR_PTR(-EINVAL); - - info = kzalloc(sizeof(*info), GFP_KERNEL); - - if (info == NULL) { - KGSL_CORE_ERR("kzalloc(%d) failed\n", sizeof(*info)); - ret = -ENOMEM; - goto err; - } - - for_each_child_of_node(node, child) - count++; - - info->power_param.num_freq = count; - - info->freq_tbl = kzalloc(info->power_param.num_freq * - sizeof(struct msm_dcvs_freq_entry), - GFP_KERNEL); - - if (info->freq_tbl == NULL) { - KGSL_CORE_ERR("kzalloc(%d) failed\n", - info->power_param.num_freq * - sizeof(struct msm_dcvs_freq_entry)); - ret = -ENOMEM; - goto err; - } - - for_each_child_of_node(node, child) { - unsigned int index; - - if (adreno_of_read_property(child, "reg", &index)) - goto err; - - if (index >= info->power_param.num_freq) { - KGSL_CORE_ERR("DCVS freq entry %d is out of range\n", - index); - continue; - } - - if (adreno_of_read_property(child, "qcom,freq", - &info->freq_tbl[index].freq)) - goto err; - - if (adreno_of_read_property(child, "qcom,voltage", - &info->freq_tbl[index].voltage)) - info->freq_tbl[index].voltage = 0; - - if (adreno_of_read_property(child, "qcom,is_trans_level", - &info->freq_tbl[index].is_trans_level)) - info->freq_tbl[index].is_trans_level = 0; - - if (adreno_of_read_property(child, "qcom,active-energy-offset", - &info->freq_tbl[index].active_energy_offset)) - info->freq_tbl[index].active_energy_offset = 0; - - if (adreno_of_read_property(child, "qcom,leakage-energy-offset", - &info->freq_tbl[index].leakage_energy_offset)) - info->freq_tbl[index].leakage_energy_offset = 0; - } - - if (adreno_of_read_property(node, "qcom,num-cores", &info->num_cores)) - goto err; - - info->sensors = kzalloc(info->num_cores * - sizeof(int), - GFP_KERNEL); - - for (count = 0; count < info->num_cores; count++) { - if (adreno_of_read_property(node, "qcom,sensors", - &(info->sensors[count]))) - goto err; - } - - if (adreno_of_read_property(node, "qcom,core-core-type", - &info->core_param.core_type)) - goto err; - - if (adreno_of_read_property(node, "qcom,algo-disable-pc-threshold", - &info->algo_param.disable_pc_threshold)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-em-win-size-min-us", - &info->algo_param.em_win_size_min_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-em-win-size-max-us", - &info->algo_param.em_win_size_max_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-em-max-util-pct", - &info->algo_param.em_max_util_pct)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-group-id", - &info->algo_param.group_id)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-max-freq-chg-time-us", - &info->algo_param.max_freq_chg_time_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-slack-mode-dynamic", - &info->algo_param.slack_mode_dynamic)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-slack-weight-thresh-pct", - &info->algo_param.slack_weight_thresh_pct)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-slack-time-min-us", - &info->algo_param.slack_time_min_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-slack-time-max-us", - &info->algo_param.slack_time_max_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-ss-win-size-min-us", - &info->algo_param.ss_win_size_min_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-ss-win-size-max-us", - &info->algo_param.ss_win_size_max_us)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-ss-util-pct", - &info->algo_param.ss_util_pct)) - goto err; - if (adreno_of_read_property(node, "qcom,algo-ss-no-corr-below-freq", - &info->algo_param.ss_no_corr_below_freq)) - goto err; - - if (adreno_of_read_property(node, "qcom,energy-active-coeff-a", - &info->energy_coeffs.active_coeff_a)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-active-coeff-b", - &info->energy_coeffs.active_coeff_b)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-active-coeff-c", - &info->energy_coeffs.active_coeff_c)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-a", - &info->energy_coeffs.leakage_coeff_a)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-b", - &info->energy_coeffs.leakage_coeff_b)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-c", - &info->energy_coeffs.leakage_coeff_c)) - goto err; - if (adreno_of_read_property(node, "qcom,energy-leakage-coeff-d", - &info->energy_coeffs.leakage_coeff_d)) - goto err; - - if (adreno_of_read_property(node, "qcom,power-current-temp", - &info->power_param.current_temp)) - goto err; - - return info; - -err: - if (info) - kfree(info->freq_tbl); - - kfree(info); - - return ERR_PTR(ret); -} - static int adreno_of_get_iommu(struct device_node *parent, struct kgsl_device_platform_data *pdata) { @@ -1275,6 +1318,8 @@ static int adreno_of_get_iommu(struct device_node *parent, data->physstart = reg_val[0]; data->physend = data->physstart + reg_val[1] - 1; + data->iommu_halt_enable = of_property_read_bool(node, + "qcom,iommu-enable-halt"); data->iommu_ctx_count = 0; @@ -1299,9 +1344,17 @@ static int adreno_of_get_iommu(struct device_node *parent, goto err; } - if (adreno_of_read_property(child, "qcom,iommu-ctx-sids", - &ctxs[ctx_index].ctx_id)) + ret = of_property_read_u32_array(child, "reg", reg_val, 2); + if (ret) { + KGSL_CORE_ERR("Unable to read KGSL IOMMU 'reg'\n"); goto err; + } + if (msm_soc_version_supports_iommu_v1()) + ctxs[ctx_index].ctx_id = (reg_val[0] - + data->physstart) >> KGSL_IOMMU_CTX_SHIFT; + else + ctxs[ctx_index].ctx_id = ((reg_val[0] - + data->physstart) >> KGSL_IOMMU_CTX_SHIFT) - 8; ctx_index++; } @@ -1356,14 +1409,12 @@ static int adreno_of_get_pdata(struct platform_device *pdev) if (ret) goto err; - /* Default value is 83, if not found in DT */ if (adreno_of_read_property(pdev->dev.of_node, "qcom,idle-timeout", &pdata->idle_timeout)) - pdata->idle_timeout = 83; + pdata->idle_timeout = HZ/12; - if (adreno_of_read_property(pdev->dev.of_node, "qcom,nap-allowed", - &pdata->nap_allowed)) - pdata->nap_allowed = 1; + pdata->strtstp_sleepwake = of_property_read_bool(pdev->dev.of_node, + "qcom,strtstp-sleepwake"); if (adreno_of_read_property(pdev->dev.of_node, "qcom,clk-map", &pdata->clk_map)) @@ -1379,12 +1430,8 @@ static int adreno_of_get_pdata(struct platform_device *pdev) pdata->bus_scale_table = msm_bus_cl_get_pdata(pdev); if (IS_ERR_OR_NULL(pdata->bus_scale_table)) { ret = PTR_ERR(pdata->bus_scale_table); - goto err; - } - - pdata->core_info = adreno_of_get_dcvs(pdev->dev.of_node); - if (IS_ERR_OR_NULL(pdata->core_info)) { - ret = PTR_ERR(pdata->core_info); + if (!ret) + ret = -EINVAL; goto err; } @@ -1392,15 +1439,14 @@ static int adreno_of_get_pdata(struct platform_device *pdev) if (ret) goto err; + pdata->coresight_pdata = of_get_coresight_platform_data(&pdev->dev, + pdev->dev.of_node); + pdev->dev.platform_data = pdata; return 0; err: if (pdata) { - if (pdata->core_info) - kfree(pdata->core_info->freq_tbl); - kfree(pdata->core_info); - if (pdata->iommu_data) kfree(pdata->iommu_data->iommu_ctxs); @@ -1416,7 +1462,8 @@ static int adreno_of_get_pdata(struct platform_device *pdev) static int adreno_ocmem_gmem_malloc(struct adreno_device *adreno_dev) { - if (!adreno_is_a330(adreno_dev)) + if (!(adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev))) return 0; /* OCMEM is only needed once, do not support consective allocation */ @@ -1437,7 +1484,8 @@ adreno_ocmem_gmem_malloc(struct adreno_device *adreno_dev) static void adreno_ocmem_gmem_free(struct adreno_device *adreno_dev) { - if (!adreno_is_a330(adreno_dev)) + if (!(adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev))) return; if (adreno_dev->ocmem_hdl == NULL) @@ -1463,6 +1511,7 @@ static int __devinit adreno_probe(struct platform_device *pdev) { struct kgsl_device *device; + struct kgsl_device_platform_data *pdata = NULL; struct adreno_device *adreno_dev; int status = -EINVAL; bool is_dt; @@ -1492,11 +1541,16 @@ adreno_probe(struct platform_device *pdev) goto error_close_device; adreno_debugfs_init(device); + adreno_ft_init_sysfs(device); kgsl_pwrscale_init(device); kgsl_pwrscale_attach_policy(device, ADRENO_DEFAULT_PWRSCALE_POLICY); device->flags &= ~KGSL_FLAGS_SOFT_RESET; + pdata = kgsl_device_get_drvdata(device); + + adreno_coresight_init(pdev); + return 0; error_close_device: @@ -1517,21 +1571,35 @@ static int __devexit adreno_remove(struct platform_device *pdev) device = (struct kgsl_device *)pdev->id_entry->driver_data; adreno_dev = ADRENO_DEVICE(device); + adreno_coresight_remove(pdev); + kgsl_pwrscale_detach_policy(device); kgsl_pwrscale_close(device); adreno_dispatcher_close(adreno_dev); adreno_ringbuffer_close(&adreno_dev->ringbuffer); + adreno_perfcounter_close(device); kgsl_device_platform_remove(device); + clear_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv); + return 0; } static int adreno_init(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; + int i; + int ret; kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); + /* + * initialization only needs to be done once initially until + * device is shutdown + */ + if (test_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv)) + return 0; /* Power up the device */ kgsl_pwrctrl_enable(device); @@ -1557,6 +1625,7 @@ static int adreno_init(struct kgsl_device *device) BUG_ON(1); } + kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); /* * Check if firmware supports the sync lock PM4 packets needed * for IOMMUv1 @@ -1568,16 +1637,39 @@ static int adreno_init(struct kgsl_device *device) adreno_gpulist[adreno_dev->gpulist_index].sync_lock_pfp_ver)) device->mmu.flags |= KGSL_MMU_FLAGS_IOMMU_SYNC; - /* Assign correct RBBM status register to hang detect regs - */ - ft_detect_regs[0] = adreno_dev->gpudev->reg_rbbm_status; - - adreno_perfcounter_init(device); + rb->global_ts = 0; + + /* Initialize ft detection register offsets */ + ft_detect_regs[0] = adreno_getreg(adreno_dev, + ADRENO_REG_RBBM_STATUS); + ft_detect_regs[1] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_RB_RPTR); + ft_detect_regs[2] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_IB1_BASE); + ft_detect_regs[3] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_IB1_BUFSZ); + ft_detect_regs[4] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_IB2_BASE); + ft_detect_regs[5] = adreno_getreg(adreno_dev, + ADRENO_REG_CP_IB2_BUFSZ); + for (i = 6; i < FT_DETECT_REGS_COUNT; i++) + ft_detect_regs[i] = 0; + + ret = adreno_perfcounter_init(device); /* Power down the device */ kgsl_pwrctrl_disable(device); - return 0; + if (ret) + goto done; + + /* Certain targets need the fixup. You know who you are */ + if (adreno_is_a330v2(adreno_dev)) + adreno_a3xx_pwron_fixup_init(adreno_dev); + + set_bit(ADRENO_DEVICE_INITIALIZED, &adreno_dev->priv); +done: + return ret; } static int adreno_start(struct kgsl_device *device) @@ -1585,14 +1677,25 @@ static int adreno_start(struct kgsl_device *device) int status = -EINVAL; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int state = device->state; + unsigned int regulator_left_on = 0; kgsl_cffdump_open(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); + regulator_left_on = (regulator_is_enabled(device->pwrctrl.gpu_reg) || + (device->pwrctrl.gpu_cx && + regulator_is_enabled(device->pwrctrl.gpu_cx))); + + /* Clear any GPU faults that might have been left over */ + adreno_set_gpu_fault(adreno_dev, 0); + /* Power up the device */ kgsl_pwrctrl_enable(device); + /* Set the bit to indicate that we've just powered on */ + set_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv); + /* Set up a2xx special case */ if (adreno_is_a2xx(adreno_dev)) { /* @@ -1617,6 +1720,14 @@ static int adreno_start(struct kgsl_device *device) goto error_mmu_off; } + if (regulator_left_on && adreno_dev->gpudev->soft_reset) { + /* + * Reset the GPU for A3xx. A2xx does a soft reset in + * the start function. + */ + adreno_dev->gpudev->soft_reset(adreno_dev); + } + /* Start the GPU */ adreno_dev->gpudev->start(adreno_dev); @@ -1627,15 +1738,19 @@ static int adreno_start(struct kgsl_device *device) if (status) goto error_irq_off; - /* Start the dispatcher */ - adreno_dispatcher_start(adreno_dev); + status = adreno_perfcounter_start(adreno_dev); + if (status) + goto error_rb_stop; - adreno_perfcounter_start(adreno_dev); + /* Start the dispatcher */ + adreno_dispatcher_start(device); device->reset_counter++; return 0; +error_rb_stop: + adreno_ringbuffer_stop(&adreno_dev->ringbuffer); error_irq_off: kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); @@ -1643,11 +1758,9 @@ static int adreno_start(struct kgsl_device *device) kgsl_mmu_stop(&device->mmu); error_clk_off: - if (KGSL_STATE_DUMP_AND_FT != device->state) { - kgsl_pwrctrl_disable(device); - /* set the state back to original state */ - kgsl_pwrctrl_set_state(device, state); - } + kgsl_pwrctrl_disable(device); + /* set the state back to original state */ + kgsl_pwrctrl_set_state(device, state); return status; } @@ -1675,7 +1788,7 @@ static int adreno_stop(struct kgsl_device *device) /* Power down the device */ kgsl_pwrctrl_disable(device); - kgsl_cffdump_close(device->id); + kgsl_cffdump_close(device); return 0; } @@ -1688,29 +1801,306 @@ static int adreno_stop(struct kgsl_device *device) */ int adreno_reset(struct kgsl_device *device) { - int ret; + int ret = -EINVAL; + struct kgsl_mmu *mmu = &device->mmu; + int i = 0; + + /* Try soft reset first, for non mmu fault case only */ + if (!atomic_read(&mmu->fault)) { + ret = adreno_soft_reset(device); + if (ret) + KGSL_DEV_ERR_ONCE(device, "Device soft reset failed\n"); + } + if (ret) { + /* If soft reset failed/skipped, then pull the power */ + adreno_stop(device); + + /* Keep trying to start the device until it works */ + for (i = 0; i < NUM_TIMES_RESET_RETRY; i++) { + ret = adreno_start(device); + if (!ret) + break; - ret = adreno_stop(device); + msleep(20); + } + } if (ret) return ret; - ret = adreno_init(device); - if (ret) - return ret; + if (0 != i) + KGSL_DRV_WARN(device, "Device hard reset tried %d tries\n", i); - ret = adreno_start(device); + /* + * If active_cnt is non-zero then the system was active before + * going into a reset - put it back in that state + */ - if (ret == 0) { - /* - * If active_cnt is non-zero then the system was active before - * going into a reset - put it back in that state - */ + if (atomic_read(&device->active_cnt)) + kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); - if (atomic_read(&device->active_cnt)) - kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); - } + /* Set the page table back to the default page table */ + kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, + KGSL_MEMSTORE_GLOBAL); + + return ret; +} + +/** + * _ft_sysfs_store() - Common routine to write to FT sysfs files + * @buf: value to write + * @count: size of the value to write + * @sysfs_cfg: KGSL FT sysfs config to write + * + * This is a common routine to write to FT sysfs files. + */ +static int _ft_sysfs_store(const char *buf, size_t count, unsigned int *ptr) +{ + char temp[20]; + unsigned long val; + int rc; + + snprintf(temp, sizeof(temp), "%.*s", + (int)min(count, sizeof(temp) - 1), buf); + rc = kstrtoul(temp, 0, &val); + if (rc) + return rc; + + *ptr = val; + + return count; +} + +/** + * _get_adreno_dev() - Routine to get a pointer to adreno dev + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + */ +struct adreno_device *_get_adreno_dev(struct device *dev) +{ + struct kgsl_device *device = kgsl_device_from_dev(dev); + return device ? ADRENO_DEVICE(device) : NULL; +} + +/** + * _ft_policy_store() - Routine to configure FT policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + * FT policy can be set to any of the options below. + * KGSL_FT_DISABLE -> BIT(0) Set to disable FT + * KGSL_FT_REPLAY -> BIT(1) Set to enable replay + * KGSL_FT_SKIPIB -> BIT(2) Set to skip IB + * KGSL_FT_SKIPFRAME -> BIT(3) Set to skip frame + * by default set FT policy to KGSL_FT_DEFAULT_POLICY + */ +static int _ft_policy_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + int ret; + if (adreno_dev == NULL) + return 0; + + mutex_lock(&adreno_dev->dev.mutex); + ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_policy); + mutex_unlock(&adreno_dev->dev.mutex); + + return ret; +} + +/** + * _ft_policy_show() - Routine to read FT policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + * + * This is a routine to read current FT policy + */ +static int _ft_policy_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + if (adreno_dev == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_policy); +} + +/** + * _ft_pagefault_policy_store() - Routine to configure FT + * pagefault policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + * FT pagefault policy can be set to any of the options below. + * KGSL_FT_PAGEFAULT_INT_ENABLE -> BIT(0) set to enable pagefault INT + * KGSL_FT_PAGEFAULT_GPUHALT_ENABLE -> BIT(1) Set to enable GPU HALT on + * pagefaults. This stalls the GPU on a pagefault on IOMMU v1 HW. + * KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE -> BIT(2) Set to log only one + * pagefault per page. + * KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT -> BIT(3) Set to log only one + * pagefault per INT. + */ +static int _ft_pagefault_policy_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + int ret; + if (adreno_dev == NULL) + return 0; + + mutex_lock(&adreno_dev->dev.mutex); + ret = _ft_sysfs_store(buf, count, &adreno_dev->ft_pf_policy); + mutex_unlock(&adreno_dev->dev.mutex); + + return ret; +} + +/** + * _ft_pagefault_policy_show() - Routine to read FT pagefault + * policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + * + * This is a routine to read current FT pagefault policy + */ +static int _ft_pagefault_policy_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + if (adreno_dev == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "0x%X\n", adreno_dev->ft_pf_policy); +} + +/** + * _ft_fast_hang_detect_store() - Routine to configure FT fast + * hang detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + * 0x1 - Enable fast hang detection + * 0x0 - Disable fast hang detection + */ +static int _ft_fast_hang_detect_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + int ret; + if (adreno_dev == NULL) + return 0; + + mutex_lock(&adreno_dev->dev.mutex); + ret = _ft_sysfs_store(buf, count, &adreno_dev->fast_hang_detect); + mutex_unlock(&adreno_dev->dev.mutex); return ret; + +} + +/** + * _ft_fast_hang_detect_show() - Routine to read FT fast + * hang detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + */ +static int _ft_fast_hang_detect_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + if (adreno_dev == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "%d\n", + (adreno_dev->fast_hang_detect ? 1 : 0)); +} + +/** + * _ft_long_ib_detect_store() - Routine to configure FT long IB + * detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value to write + * @count: size of the value to write + * + * 0x0 - Enable long IB detection + * 0x1 - Disable long IB detection + */ +static int _ft_long_ib_detect_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + int ret; + if (adreno_dev == NULL) + return 0; + + mutex_lock(&adreno_dev->dev.mutex); + ret = _ft_sysfs_store(buf, count, &adreno_dev->long_ib_detect); + mutex_unlock(&adreno_dev->dev.mutex); + + return ret; + +} + +/** + * _ft_long_ib_detect_show() - Routine to read FT long IB + * detect policy + * @dev: device ptr + * @attr: Device attribute + * @buf: value read + */ +static int _ft_long_ib_detect_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct adreno_device *adreno_dev = _get_adreno_dev(dev); + if (adreno_dev == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "%d\n", + (adreno_dev->long_ib_detect ? 1 : 0)); +} + + +#define FT_DEVICE_ATTR(name) \ + DEVICE_ATTR(name, 0644, _ ## name ## _show, _ ## name ## _store); + +FT_DEVICE_ATTR(ft_policy); +FT_DEVICE_ATTR(ft_pagefault_policy); +FT_DEVICE_ATTR(ft_fast_hang_detect); +FT_DEVICE_ATTR(ft_long_ib_detect); + + +const struct device_attribute *ft_attr_list[] = { + &dev_attr_ft_policy, + &dev_attr_ft_pagefault_policy, + &dev_attr_ft_fast_hang_detect, + &dev_attr_ft_long_ib_detect, + NULL, +}; + +int adreno_ft_init_sysfs(struct kgsl_device *device) +{ + return kgsl_create_device_sysfs_files(device->dev, ft_attr_list); +} + +void adreno_ft_uninit_sysfs(struct kgsl_device *device) +{ + kgsl_remove_device_sysfs_files(device->dev, ft_attr_list); } static int adreno_getproperty(struct kgsl_device *device, @@ -1822,8 +2212,6 @@ static int adreno_setproperty(struct kgsl_device *device, switch (type) { case KGSL_PROP_PWRCTRL: { unsigned int enable; - struct kgsl_device_platform_data *pdata = - kgsl_device_get_drvdata(device); if (sizebytes != sizeof(enable)) break; @@ -1835,12 +2223,11 @@ static int adreno_setproperty(struct kgsl_device *device, } if (enable) { - if (pdata->nap_allowed) - device->pwrctrl.nap_allowed = true; adreno_dev->fast_hang_detect = 1; kgsl_pwrscale_enable(device); } else { - device->pwrctrl.nap_allowed = false; + kgsl_pwrctrl_wake(device); + device->pwrctrl.ctrl_flags = KGSL_PWR_ON; adreno_dev->fast_hang_detect = 0; kgsl_pwrscale_disable(device); } @@ -1872,23 +2259,84 @@ static bool adreno_hw_isidle(struct kgsl_device *device) return false; /* Read the correct RBBM status for the GPU type */ - adreno_regread(device, - adreno_dev->gpudev->reg_rbbm_status, + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_STATUS, ®_rbbm_status); if (adreno_is_a2xx(adreno_dev)) { if (reg_rbbm_status == 0x110) return true; - } else if (adreno_is_a3xx(adreno_dev)) { + } else if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) { if (!(reg_rbbm_status & 0x80000000)) return true; - } else { - BUG(); } return false; } +/** + * adreno_soft_reset() - Do a soft reset of the GPU hardware + * @device: KGSL device to soft reset + * + * "soft reset" the GPU hardware - this is a fast path GPU reset + * The GPU hardware is reset but we never pull power so we can skip + * a lot of the standard adreno_stop/adreno_start sequence + */ +int adreno_soft_reset(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + int ret; + + if (!adreno_dev->gpudev->soft_reset) { + dev_WARN_ONCE(device->dev, 1, "Soft reset not supported"); + return -EINVAL; + } + + adreno_dev->drawctxt_active = NULL; + + /* Stop the ringbuffer */ + adreno_ringbuffer_stop(&adreno_dev->ringbuffer); + + if (kgsl_pwrctrl_isenabled(device)) + device->ftbl->irqctrl(device, 0); + + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); + + adreno_set_gpu_fault(adreno_dev, 0); + + /* Delete the idle timer */ + del_timer_sync(&device->idle_timer); + + /* Make sure we are totally awake */ + kgsl_pwrctrl_enable(device); + + /* Reset the GPU */ + adreno_dev->gpudev->soft_reset(adreno_dev); + + /* Reinitialize the GPU */ + adreno_dev->gpudev->start(adreno_dev); + + /* Enable IRQ */ + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); + device->ftbl->irqctrl(device, 1); + + /* + * If we have offsets for the jump tables we can try to do a warm start, + * otherwise do a full ringbuffer restart + */ + + if (adreno_dev->pm4_jt_idx) + ret = adreno_ringbuffer_warm_start(&adreno_dev->ringbuffer); + else + ret = adreno_ringbuffer_start(&adreno_dev->ringbuffer); + + if (ret) + return ret; + + device->reset_counter++; + + return 0; +} + /** * adreno_isidle() - return true if the GPU hardware is idle * @device: Pointer to the KGSL device structure for the GPU @@ -1896,18 +2344,18 @@ static bool adreno_hw_isidle(struct kgsl_device *device) * Return true if the GPU hardware is idle and there are no commands pending in * the ringbuffer */ -static bool adreno_isidle(struct kgsl_device *device) +bool adreno_isidle(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; + unsigned int rptr; /* If the device isn't active, don't force it on. */ if (device->state != KGSL_STATE_ACTIVE) return true; - GSL_RB_GET_READPTR(rb, &rb->rptr); + rptr = adreno_get_rptr(&adreno_dev->ringbuffer); - if (rb->rptr == rb->wptr) + if (rptr == adreno_dev->ringbuffer.wptr) return adreno_hw_isidle(device); return false; @@ -1932,21 +2380,30 @@ int adreno_idle(struct kgsl_device *device) BUG_ON(!mutex_is_locked(&device->mutex)); - if (adreno_is_a2xx(adreno_dev)) + if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) kgsl_cffdump_regpoll(device, - adreno_dev->gpudev->reg_rbbm_status << 2, 0x110, 0x110); + adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2, + 0x00000000, 0x80000000); else kgsl_cffdump_regpoll(device, - adreno_dev->gpudev->reg_rbbm_status << 2, 0, - 0x80000000); + adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS) << 2, + 0x110, 0x110); while (time_before(jiffies, wait)) { + /* + * If we fault, stop waiting and return an error. The dispatcher + * will clean up the fault from the work queue, but we need to + * make sure we don't block it by waiting for an idle that + * will never come. + */ + + if (adreno_gpu_fault(adreno_dev) != 0) + return -EDEADLK; + if (adreno_isidle(device)) return 0; } - kgsl_postmortem_dump(device, 0); - return -ETIMEDOUT; } @@ -1954,14 +2411,13 @@ int adreno_idle(struct kgsl_device *device) * adreno_drain() - Drain the dispatch queue * @device: Pointer to the KGSL device structure for the GPU * - * Tell the dispatcher to pause - this has the effect of draining the inflight - * command batches + * Drain the dispatcher of existing command batches. This halts + * additional commands from being issued until the gate is completed. */ static int adreno_drain(struct kgsl_device *device) { - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + INIT_COMPLETION(device->cmdbatch_gate); - adreno_dispatcher_pause(adreno_dev); return 0; } @@ -1983,7 +2439,7 @@ static int adreno_suspend_context(struct kgsl_device *device) /* Find a memory structure attached to an adreno context */ struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, - unsigned int pt_base, unsigned int gpuaddr, unsigned int size) + phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size) { struct kgsl_context *context; int next = 0; @@ -1995,7 +2451,8 @@ struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, if (context == NULL) break; - if (kgsl_mmu_pt_equal(&device->mmu, context->pagetable, + if (kgsl_mmu_pt_equal(&device->mmu, + context->proc_priv->pagetable, pt_base)) { struct adreno_context *adreno_context; @@ -2015,15 +2472,30 @@ struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, return desc; } +/* + * adreno_find_region() - Find corresponding allocation for a given address + * @device: Device on which address operates + * @pt_base: The pagetable in which address is mapped + * @gpuaddr: The gpu address + * @size: Size in bytes of the address + * @entry: If the allocation is part of user space allocation then the mem + * entry is returned in this parameter. Caller is supposed to decrement + * refcount on this entry after its done using it. + * + * Finds an allocation descriptor for a given gpu address range + * + * Returns the descriptor on success else NULL + */ struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device, - unsigned int pt_base, + phys_addr_t pt_base, unsigned int gpuaddr, - unsigned int size) + unsigned int size, + struct kgsl_mem_entry **entry) { - struct kgsl_mem_entry *entry; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_ringbuffer *ringbuffer = &adreno_dev->ringbuffer; + *entry = NULL; if (kgsl_gpuaddr_in_memdesc(&ringbuffer->buffer_desc, gpuaddr, size)) return &ringbuffer->buffer_desc; @@ -2033,34 +2505,62 @@ struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device, if (kgsl_gpuaddr_in_memdesc(&device->memstore, gpuaddr, size)) return &device->memstore; + if (kgsl_gpuaddr_in_memdesc(&adreno_dev->pwron_fixup, gpuaddr, size)) + return &adreno_dev->pwron_fixup; + if (kgsl_gpuaddr_in_memdesc(&device->mmu.setstate_memory, gpuaddr, size)) return &device->mmu.setstate_memory; - entry = kgsl_get_mem_entry(device, pt_base, gpuaddr, size); + *entry = kgsl_get_mem_entry(device, pt_base, gpuaddr, size); - if (entry) - return &entry->memdesc; + if (*entry) + return &((*entry)->memdesc); return adreno_find_ctxtmem(device, pt_base, gpuaddr, size); } -uint8_t *adreno_convertaddr(struct kgsl_device *device, unsigned int pt_base, - unsigned int gpuaddr, unsigned int size) +/* + * adreno_convertaddr() - Convert a gpu address to kernel mapped address + * @device: Device on which the address operates + * @pt_base: The pagetable in which address is mapped + * @gpuaddr: The start address + * @size: The length of address range + * @entry: If the allocation is part of user space allocation then the mem + * entry is returned in this parameter. Caller is supposed to decrement + * refcount on this entry after its done using it. + * + * Returns the converted host pointer on success else NULL + */ +uint8_t *adreno_convertaddr(struct kgsl_device *device, phys_addr_t pt_base, + unsigned int gpuaddr, unsigned int size, + struct kgsl_mem_entry **entry) { struct kgsl_memdesc *memdesc; - memdesc = adreno_find_region(device, pt_base, gpuaddr, size); + memdesc = adreno_find_region(device, pt_base, gpuaddr, size, entry); return memdesc ? kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr) : NULL; } -void adreno_regread(struct kgsl_device *device, unsigned int offsetwords, - unsigned int *value) + +/** + * adreno_read - General read function to read adreno device memory + * @device - Pointer to the GPU device struct (for adreno device) + * @base - Base address (kernel virtual) where the device memory is mapped + * @offsetwords - Offset in words from the base address, of the memory that + * is to be read + * @value - Value read from the device memory + * @mem_len - Length of the device memory mapped to the kernel + */ +static void adreno_read(struct kgsl_device *device, void *base, + unsigned int offsetwords, unsigned int *value, + unsigned int mem_len) { + unsigned int *reg; - BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len); - reg = (unsigned int *)(device->reg_virt + (offsetwords << 2)); + BUG_ON(offsetwords*sizeof(uint32_t) >= mem_len); + reg = (unsigned int *)(base + (offsetwords << 2)); if (!in_interrupt()) kgsl_pre_hwaccess(device); @@ -2071,7 +2571,33 @@ void adreno_regread(struct kgsl_device *device, unsigned int offsetwords, rmb(); } -void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords, +/** + * adreno_regread - Used to read adreno device registers + * @offsetwords - Word (4 Bytes) offset to the register to be read + * @value - Value read from device register + */ +static void adreno_regread(struct kgsl_device *device, unsigned int offsetwords, + unsigned int *value) +{ + adreno_read(device, device->reg_virt, offsetwords, value, + device->reg_len); +} + +/** + * adreno_shadermem_regread - Used to read GPU (adreno) shader memory + * @device - GPU device whose shader memory is to be read + * @offsetwords - Offset in words, of the shader memory address to be read + * @value - Pointer to where the read shader mem value is to be stored + */ +void adreno_shadermem_regread(struct kgsl_device *device, + unsigned int offsetwords, unsigned int *value) +{ + adreno_read(device, device->shader_mem_virt, offsetwords, value, + device->shader_mem_len); +} + +static void adreno_regwrite(struct kgsl_device *device, + unsigned int offsetwords, unsigned int value) { unsigned int *reg; @@ -2083,7 +2609,7 @@ void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords, kgsl_trace_regwrite(device, offsetwords, value); - kgsl_cffdump_regwrite(device->id, offsetwords << 2, value); + kgsl_cffdump_regwrite(device, offsetwords << 2, value); reg = (unsigned int *)(device->reg_virt + (offsetwords << 2)); /*ensure previous writes post before this one, @@ -2113,7 +2639,7 @@ static int adreno_waittimestamp(struct kgsl_device *device, /* If they are doing then complain once */ dev_WARN_ONCE(device->dev, 1, "IOCTL_KGSL_DEVICE_WAITTIMESTAMP is deprecated\n"); - return -EINVAL; + return -ENOTTY; } /* Return -EINVAL if the context has been detached */ @@ -2138,14 +2664,6 @@ static unsigned int adreno_readtimestamp(struct kgsl_device *device, unsigned int timestamp = 0; unsigned int id = context ? context->id : KGSL_MEMSTORE_GLOBAL; - /* - * If the context is detached we are in a race with - * the context being destroyed by userspace so bail. - */ - if (context && kgsl_context_detached(context)) { - KGSL_DRV_WARN(device, "context was detached"); - return timestamp; - } switch (type) { case KGSL_TIMESTAMP_QUEUED: { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); @@ -2201,14 +2719,23 @@ static long adreno_ioctl(struct kgsl_device_private *dev_priv, } case IOCTL_KGSL_PERFCOUNTER_GET: { struct kgsl_perfcounter_get *get = data; + /* + * adreno_perfcounter_get() is called by kernel clients + * during start(), so it is not safe to take an + * active count inside this function. + */ + result = kgsl_active_count_get(device); + if (result) + break; result = adreno_perfcounter_get(adreno_dev, get->groupid, get->countable, &get->offset, PERFCOUNTER_FLAG_NONE); + kgsl_active_count_put(device); break; } case IOCTL_KGSL_PERFCOUNTER_PUT: { struct kgsl_perfcounter_put *put = data; result = adreno_perfcounter_put(adreno_dev, put->groupid, - put->countable); + put->countable, PERFCOUNTER_FLAG_NONE); break; } case IOCTL_KGSL_PERFCOUNTER_QUERY: { @@ -2220,8 +2747,12 @@ static long adreno_ioctl(struct kgsl_device_private *dev_priv, } case IOCTL_KGSL_PERFCOUNTER_READ: { struct kgsl_perfcounter_read *read = data; + result = kgsl_active_count_get(device); + if (result) + break; result = adreno_perfcounter_read_group(adreno_dev, read->reads, read->count); + kgsl_active_count_put(device); break; } default: @@ -2329,6 +2860,7 @@ static const struct kgsl_functable adreno_functable = { .setproperty = adreno_setproperty, .postmortem_dump = adreno_dump, .drawctxt_sched = adreno_drawctxt_sched, + .resume = adreno_dispatcher_start, }; static struct platform_driver adreno_platform_driver = { diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h index 25d1fdd3ad3..54503f28462 100644 --- a/drivers/gpu/msm/adreno.h +++ b/drivers/gpu/msm/adreno.h @@ -37,8 +37,8 @@ #define KGSL_CMD_FLAGS_NONE 0 #define KGSL_CMD_FLAGS_PMODE BIT(0) #define KGSL_CMD_FLAGS_INTERNAL_ISSUE BIT(1) -#define KGSL_CMD_FLAGS_GET_INT BIT(2) -#define KGSL_CMD_FLAGS_WFI BIT(3) +#define KGSL_CMD_FLAGS_WFI BIT(2) +#define KGSL_CMD_FLAGS_PWRON_FIXUP BIT(3) /* Command identifiers */ #define KGSL_CONTEXT_TO_MEM_IDENTIFIER 0x2EADBEEF @@ -48,6 +48,7 @@ #define KGSL_END_OF_IB_IDENTIFIER 0x2ABEDEAD #define KGSL_END_OF_FRAME_IDENTIFIER 0x2E0F2E0F #define KGSL_NOP_IB_IDENTIFIER 0x20F20F20 +#define KGSL_PWRON_FIXUP_IDENTIFIER 0x2AFAFAFA #ifdef CONFIG_MSM_SCM #define ADRENO_DEFAULT_PWRSCALE_POLICY (&kgsl_pwrscale_policy_tz) @@ -77,10 +78,27 @@ enum adreno_gpurev { ADRENO_REV_A220 = 220, ADRENO_REV_A225 = 225, ADRENO_REV_A305 = 305, + ADRENO_REV_A305C = 306, ADRENO_REV_A320 = 320, ADRENO_REV_A330 = 330, + ADRENO_REV_A305B = 335, + ADRENO_REV_A420 = 420, }; +enum coresight_debug_reg { + DEBUG_BUS_CTL, + TRACE_STOP_CNT, + TRACE_START_CNT, + TRACE_PERIOD_CNT, + TRACE_CMD, + TRACE_BUS_CTL, +}; + +#define ADRENO_SOFT_FAULT BIT(0) +#define ADRENO_HARD_FAULT BIT(1) +#define ADRENO_TIMEOUT_FAULT BIT(2) +#define ADRENO_IOMMU_PAGE_FAULT BIT(3) + /* * Maximum size of the dispatcher ringbuffer - the actual inflight size will be * smaller then this but this size will allow for a larger range of inflight @@ -95,7 +113,7 @@ enum adreno_gpurev { * @state: Current state of the dispatcher (active or paused) * @timer: Timer to monitor the progress of the command batches * @inflight: Number of command batch operations pending in the ringbuffer - * @fault: True if a HW fault was detected + * @fault: Non-zero if a fault was detected. * @pending: Priority list of contexts waiting to submit command batches * @plist_lock: Spin lock to protect the pending queue * @cmdqueue: Queue of command batches currently flight @@ -108,11 +126,11 @@ enum adreno_gpurev { */ struct adreno_dispatcher { struct mutex mutex; - unsigned int state; + unsigned long priv; struct timer_list timer; struct timer_list fault_timer; unsigned int inflight; - int fault; + atomic_t fault; struct plist_head pending; spinlock_t plist_lock; struct kgsl_cmdbatch *cmdqueue[ADRENO_DISPATCH_CMDQUEUE_SIZE]; @@ -122,10 +140,15 @@ struct adreno_dispatcher { struct kobject kobj; }; +enum adreno_dispatcher_flags { + ADRENO_DISPATCHER_POWER = 0, +}; + struct adreno_gpudev; struct adreno_device { struct kgsl_device dev; /* Must be first field in this struct */ + unsigned long priv; unsigned int chip_id; enum adreno_gpurev gpurev; unsigned long gmem_base; @@ -143,6 +166,10 @@ struct adreno_device { unsigned int mharb; struct adreno_gpudev *gpudev; unsigned int wait_timeout; + unsigned int pm4_jt_idx; + unsigned int pm4_jt_addr; + unsigned int pfp_jt_idx; + unsigned int pfp_jt_addr; unsigned int istore_size; unsigned int pix_shader_start; unsigned int instruction_size; @@ -158,6 +185,20 @@ struct adreno_device { unsigned int ocmem_base; unsigned int gpu_cycles; struct adreno_dispatcher dispatcher; + struct kgsl_memdesc pwron_fixup; + unsigned int pwron_fixup_dwords; +}; + +/** + * enum adreno_device_flags - Private flags for the adreno_device + * @ADRENO_DEVICE_PWRON - Set during init after a power collapse + * @ADRENO_DEVICE_PWRON_FIXUP - Set if the target requires the shader fixup + * after power collapse + */ +enum adreno_device_flags { + ADRENO_DEVICE_PWRON = 0, + ADRENO_DEVICE_PWRON_FIXUP = 1, + ADRENO_DEVICE_INITIALIZED = 2, }; #define PERFCOUNTER_FLAG_NONE 0x0 @@ -168,14 +209,19 @@ struct adreno_device { /** * struct adreno_perfcount_register: register state * @countable: countable the register holds - * @refcount: number of users of the register + * @kernelcount: number of user space users of the register + * @usercount: number of kernel users of the register * @offset: register hardware offset + * @load_bit: The bit number in LOAD register which corresponds to this counter + * @select: The countable register offset */ struct adreno_perfcount_register { unsigned int countable; - unsigned int refcount; + unsigned int kernelcount; + unsigned int usercount; unsigned int offset; - unsigned int flags; + int load_bit; + unsigned int select; }; /** @@ -198,14 +244,114 @@ struct adreno_perfcounters { unsigned int group_count; }; +#define ADRENO_PERFCOUNTER_GROUP(core, name) { core##_perfcounters_##name, \ + ARRAY_SIZE(core##_perfcounters_##name) } + +/** + * adreno_regs: List of registers that are used in kgsl driver for all + * 3D devices. Each device type has different offset value for the same + * register, so an array of register offsets are declared for every device + * and are indexed by the enumeration values defined in this enum + */ +enum adreno_regs { + ADRENO_REG_CP_DEBUG, + ADRENO_REG_CP_ME_RAM_WADDR, + ADRENO_REG_CP_ME_RAM_DATA, + ADRENO_REG_CP_PFP_UCODE_DATA, + ADRENO_REG_CP_PFP_UCODE_ADDR, + ADRENO_REG_CP_WFI_PEND_CTR, + ADRENO_REG_CP_RB_BASE, + ADRENO_REG_CP_RB_RPTR_ADDR, + ADRENO_REG_CP_RB_RPTR, + ADRENO_REG_CP_RB_WPTR, + ADRENO_REG_CP_PROTECT_CTRL, + ADRENO_REG_CP_ME_CNTL, + ADRENO_REG_CP_RB_CNTL, + ADRENO_REG_CP_IB1_BASE, + ADRENO_REG_CP_IB1_BUFSZ, + ADRENO_REG_CP_IB2_BASE, + ADRENO_REG_CP_IB2_BUFSZ, + ADRENO_REG_CP_TIMESTAMP, + ADRENO_REG_CP_ME_RAM_RADDR, + ADRENO_REG_SCRATCH_ADDR, + ADRENO_REG_SCRATCH_UMSK, + ADRENO_REG_SCRATCH_REG2, + ADRENO_REG_RBBM_STATUS, + ADRENO_REG_RBBM_PERFCTR_CTL, + ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0, + ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1, + ADRENO_REG_RBBM_PERFCTR_LOAD_CMD2, + ADRENO_REG_RBBM_PERFCTR_PWR_1_LO, + ADRENO_REG_RBBM_INT_0_MASK, + ADRENO_REG_RBBM_INT_0_STATUS, + ADRENO_REG_RBBM_AHB_ERROR_STATUS, + ADRENO_REG_RBBM_PM_OVERRIDE2, + ADRENO_REG_RBBM_AHB_CMD, + ADRENO_REG_RBBM_INT_CLEAR_CMD, + ADRENO_REG_VPC_DEBUG_RAM_SEL, + ADRENO_REG_VPC_DEBUG_RAM_READ, + ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0, + ADRENO_REG_VSC_PIPE_DATA_LENGTH_7, + ADRENO_REG_VSC_SIZE_ADDRESS, + ADRENO_REG_VFD_CONTROL_0, + ADRENO_REG_VFD_FETCH_INSTR_0_0, + ADRENO_REG_VFD_FETCH_INSTR_1_F, + ADRENO_REG_VFD_INDEX_MAX, + ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG, + ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG, + ADRENO_REG_SP_VS_OBJ_START_REG, + ADRENO_REG_SP_FS_OBJ_START_REG, + ADRENO_REG_PA_SC_AA_CONFIG, + ADRENO_REG_SQ_GPR_MANAGEMENT, + ADRENO_REG_SQ_INST_STORE_MANAGMENT, + ADRENO_REG_TC_CNTL_STATUS, + ADRENO_REG_TP0_CHICKEN, + ADRENO_REG_RBBM_RBBM_CTL, + ADRENO_REG_REGISTER_MAX, +}; + +/** + * adreno_reg_offsets: Holds array of register offsets + * @offsets: Offset array of size defined by enum adreno_regs + * @offset_0: This is the index of the register in offset array whose value + * is 0. 0 is a valid register offset and during initialization of the + * offset array we need to know if an offset value is correctly defined to 0 + */ +struct adreno_reg_offsets { + unsigned int *const offsets; + enum adreno_regs offset_0; +}; + +#define ADRENO_REG_UNUSED 0xFFFFFFFF +#define ADRENO_REG_DEFINE(_offset, _reg) [_offset] = _reg + +/* + * struct adreno_vbif_data - Describes vbif register value pair + * @reg: Offset to vbif register + * @val: The value that should be programmed in the register at reg + */ +struct adreno_vbif_data { + unsigned int reg; + unsigned int val; +}; + +/* + * struct adreno_vbif_platform - Holds an array of vbif reg value pairs + * for a particular core + * @devfunc: Pointer to platform/core identification function + * @vbif: Array of reg value pairs for vbif registers + */ +struct adreno_vbif_platform { + int(*devfunc)(struct adreno_device *); + const struct adreno_vbif_data *vbif; +}; + struct adreno_gpudev { /* - * These registers are in a different location on A3XX, so define - * them in the structure and use them as variables. + * These registers are in a different location on different devices, + * so define them in the structure and use them as variables. */ - unsigned int reg_rbbm_status; - unsigned int reg_cp_pfp_ucode_data; - unsigned int reg_cp_pfp_ucode_addr; + const struct adreno_reg_offsets *reg_offsets; /* keeps track of when we need to execute the draw workaround code */ int ctx_switches_since_last_draw; @@ -213,49 +359,72 @@ struct adreno_gpudev { /* GPU specific function hooks */ int (*ctxt_create)(struct adreno_device *, struct adreno_context *); - int (*ctxt_save)(struct adreno_device *, struct adreno_context *); - int (*ctxt_restore)(struct adreno_device *, struct adreno_context *); - int (*ctxt_draw_workaround)(struct adreno_device *, - struct adreno_context *); irqreturn_t (*irq_handler)(struct adreno_device *); void (*irq_control)(struct adreno_device *, int); unsigned int (*irq_pending)(struct adreno_device *); void * (*snapshot)(struct adreno_device *, void *, int *, int); int (*rb_init)(struct adreno_device *, struct adreno_ringbuffer *); - void (*perfcounter_init)(struct adreno_device *); + int (*perfcounter_init)(struct adreno_device *); + void (*perfcounter_close)(struct adreno_device *); void (*start)(struct adreno_device *); unsigned int (*busy_cycles)(struct adreno_device *); - void (*perfcounter_enable)(struct adreno_device *, unsigned int group, + int (*perfcounter_enable)(struct adreno_device *, unsigned int group, unsigned int counter, unsigned int countable); uint64_t (*perfcounter_read)(struct adreno_device *adreno_dev, - unsigned int group, unsigned int counter, - unsigned int offset); + unsigned int group, unsigned int counter); + int (*coresight_enable) (struct kgsl_device *device); + void (*coresight_disable) (struct kgsl_device *device); + void (*coresight_config_debug_reg) (struct kgsl_device *device, + int debug_reg, unsigned int val); + void (*postmortem_dump)(struct adreno_device *adreno_dev); + void (*soft_reset)(struct adreno_device *device); }; #define FT_DETECT_REGS_COUNT 12 +struct log_field { + bool show; + const char *display; +}; + /* Fault Tolerance policy flags */ -#define KGSL_FT_OFF BIT(0) -#define KGSL_FT_REPLAY BIT(1) -#define KGSL_FT_SKIPIB BIT(2) -#define KGSL_FT_SKIPFRAME BIT(3) -#define KGSL_FT_DISABLE BIT(4) -#define KGSL_FT_TEMP_DISABLE BIT(5) -#define KGSL_FT_DEFAULT_POLICY (KGSL_FT_REPLAY + KGSL_FT_SKIPIB) +#define KGSL_FT_OFF 0 +#define KGSL_FT_REPLAY 1 +#define KGSL_FT_SKIPIB 2 +#define KGSL_FT_SKIPFRAME 3 +#define KGSL_FT_DISABLE 4 +#define KGSL_FT_TEMP_DISABLE 5 +#define KGSL_FT_DEFAULT_POLICY (BIT(KGSL_FT_REPLAY) + BIT(KGSL_FT_SKIPIB)) /* This internal bit is used to skip the PM dump on replayed command batches */ -#define KGSL_FT_SKIP_PMDUMP BIT(31) +#define KGSL_FT_SKIP_PMDUMP 31 /* Pagefault policy flags */ #define KGSL_FT_PAGEFAULT_INT_ENABLE BIT(0) #define KGSL_FT_PAGEFAULT_GPUHALT_ENABLE BIT(1) #define KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE BIT(2) #define KGSL_FT_PAGEFAULT_LOG_ONE_PER_INT BIT(3) -#define KGSL_FT_PAGEFAULT_DEFAULT_POLICY (KGSL_FT_PAGEFAULT_INT_ENABLE + \ - KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) +#define KGSL_FT_PAGEFAULT_DEFAULT_POLICY KGSL_FT_PAGEFAULT_INT_ENABLE + +#define ADRENO_FT_TYPES \ + { BIT(KGSL_FT_OFF), "off" }, \ + { BIT(KGSL_FT_REPLAY), "replay" }, \ + { BIT(KGSL_FT_SKIPIB), "skipib" }, \ + { BIT(KGSL_FT_SKIPFRAME), "skipframe" }, \ + { BIT(KGSL_FT_DISABLE), "disable" }, \ + { BIT(KGSL_FT_TEMP_DISABLE), "temp" } + +#define ADRENO_FT_TYPES \ + { BIT(KGSL_FT_OFF), "off" }, \ + { BIT(KGSL_FT_REPLAY), "replay" }, \ + { BIT(KGSL_FT_SKIPIB), "skipib" }, \ + { BIT(KGSL_FT_SKIPFRAME), "skipframe" }, \ + { BIT(KGSL_FT_DISABLE), "disable" }, \ + { BIT(KGSL_FT_TEMP_DISABLE), "temp" } extern struct adreno_gpudev adreno_a2xx_gpudev; extern struct adreno_gpudev adreno_a3xx_gpudev; +extern struct adreno_gpudev adreno_a4xx_gpudev; /* A2XX register sets defined in adreno_a2xx.c */ extern const unsigned int a200_registers[]; @@ -275,34 +444,48 @@ extern const unsigned int a3xx_hlsq_registers_count; extern const unsigned int a330_registers[]; extern const unsigned int a330_registers_count; +/* A4XX register set defined in adreno_a4xx.c */ +extern const unsigned int a4xx_registers[]; +extern const unsigned int a4xx_registers_count; + extern unsigned int ft_detect_regs[]; +int adreno_coresight_enable(struct coresight_device *csdev); +void adreno_coresight_disable(struct coresight_device *csdev); +void adreno_coresight_remove(struct platform_device *pdev); +int adreno_coresight_init(struct platform_device *pdev); int adreno_idle(struct kgsl_device *device); -void adreno_regread(struct kgsl_device *device, unsigned int offsetwords, - unsigned int *value); -void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords, - unsigned int value); +bool adreno_isidle(struct kgsl_device *device); + +void adreno_shadermem_regread(struct kgsl_device *device, + unsigned int offsetwords, + unsigned int *value); int adreno_dump(struct kgsl_device *device, int manual); +void adreno_dump_fields(struct kgsl_device *device, + const char *start, const struct log_field *lines, + int num); unsigned int adreno_a3xx_rbbm_clock_ctl_default(struct adreno_device *adreno_dev); struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device, - unsigned int pt_base, + phys_addr_t pt_base, unsigned int gpuaddr, - unsigned int size); + unsigned int size, + struct kgsl_mem_entry **entry); uint8_t *adreno_convertaddr(struct kgsl_device *device, - unsigned int pt_base, unsigned int gpuaddr, unsigned int size); + phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size, + struct kgsl_mem_entry **entry); struct kgsl_memdesc *adreno_find_ctxtmem(struct kgsl_device *device, - unsigned int pt_base, unsigned int gpuaddr, unsigned int size); + phys_addr_t pt_base, unsigned int gpuaddr, unsigned int size); void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, int hang); -void adreno_dispatcher_start(struct adreno_device *adreno_dev); +void adreno_dispatcher_start(struct kgsl_device *device); int adreno_dispatcher_init(struct adreno_device *adreno_dev); void adreno_dispatcher_close(struct adreno_device *adreno_dev); int adreno_dispatcher_idle(struct adreno_device *adreno_dev, @@ -310,7 +493,7 @@ int adreno_dispatcher_idle(struct adreno_device *adreno_dev, void adreno_dispatcher_irq_fault(struct kgsl_device *device); void adreno_dispatcher_stop(struct adreno_device *adreno_dev); -int adreno_context_queue_cmd(struct adreno_device *adreno_dev, +int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch, uint32_t *timestamp); @@ -320,12 +503,19 @@ void adreno_dispatcher_queue_context(struct kgsl_device *device, struct adreno_context *drawctxt); int adreno_reset(struct kgsl_device *device); +int adreno_ft_init_sysfs(struct kgsl_device *device); +void adreno_ft_uninit_sysfs(struct kgsl_device *device); + int adreno_perfcounter_get(struct adreno_device *adreno_dev, unsigned int groupid, unsigned int countable, unsigned int *offset, unsigned int flags); int adreno_perfcounter_put(struct adreno_device *adreno_dev, - unsigned int groupid, unsigned int countable); + unsigned int groupid, unsigned int countable, unsigned int flags); + +int adreno_soft_reset(struct kgsl_device *device); + +int adreno_a3xx_pwron_fixup_init(struct adreno_device *adreno_dev); static inline int adreno_is_a200(struct adreno_device *adreno_dev) { @@ -370,7 +560,7 @@ static inline int adreno_is_a2xx(struct adreno_device *adreno_dev) static inline int adreno_is_a3xx(struct adreno_device *adreno_dev) { - return (adreno_dev->gpurev >= 300); + return ((adreno_dev->gpurev >= 300) && (adreno_dev->gpurev < 400)); } static inline int adreno_is_a305(struct adreno_device *adreno_dev) @@ -378,6 +568,16 @@ static inline int adreno_is_a305(struct adreno_device *adreno_dev) return (adreno_dev->gpurev == ADRENO_REV_A305); } +static inline int adreno_is_a305b(struct adreno_device *adreno_dev) +{ + return (adreno_dev->gpurev == ADRENO_REV_A305B); +} + +static inline int adreno_is_a305c(struct adreno_device *adreno_dev) +{ + return (adreno_dev->gpurev == ADRENO_REV_A305C); +} + static inline int adreno_is_a320(struct adreno_device *adreno_dev) { return (adreno_dev->gpurev == ADRENO_REV_A320); @@ -394,6 +594,17 @@ static inline int adreno_is_a330v2(struct adreno_device *adreno_dev) (ADRENO_CHIPID_PATCH(adreno_dev->chip_id) > 0)); } + +static inline int adreno_is_a4xx(struct adreno_device *adreno_dev) +{ + return (adreno_dev->gpurev >= 400); +} + +static inline int adreno_is_a420(struct adreno_device *adreno_dev) +{ + return (adreno_dev->gpurev == ADRENO_REV_A420); +} + static inline int adreno_rb_ctxtswitch(unsigned int *cmd) { return (cmd[0] == cp_nop_packet(1) && @@ -520,6 +731,7 @@ static inline int adreno_add_idle_cmds(struct adreno_device *adreno_dev, *cmds++ = 0x00000000; if ((adreno_dev->gpurev == ADRENO_REV_A305) || + (adreno_dev->gpurev == ADRENO_REV_A305C) || (adreno_dev->gpurev == ADRENO_REV_A320)) { *cmds++ = cp_type3_packet(CP_WAIT_FOR_ME, 1); *cmds++ = 0x00000000; @@ -528,4 +740,143 @@ static inline int adreno_add_idle_cmds(struct adreno_device *adreno_dev, return cmds - start; } +/* + * adreno_wait_reg_eq() - Add a CP_WAIT_REG_EQ command + * @cmds: Pointer to memory where commands are to be added + * @addr: Regiater address to poll for + * @val: Value to poll for + * @mask: The value against which register value is masked + * @interval: wait interval + */ +static inline int adreno_wait_reg_eq(unsigned int *cmds, unsigned int addr, + unsigned int val, unsigned int mask, + unsigned int interval) +{ + unsigned int *start = cmds; + *cmds++ = cp_type3_packet(CP_WAIT_REG_EQ, 4); + *cmds++ = addr; + *cmds++ = val; + *cmds++ = mask; + *cmds++ = interval; + return cmds - start; +} + +/* + * adreno_checkreg_off() - Checks the validity of a register enum + * @adreno_dev: Pointer to adreno device + * @offset_name: The register enum that is checked + */ +static inline bool adreno_checkreg_off(struct adreno_device *adreno_dev, + enum adreno_regs offset_name) +{ + if (offset_name >= ADRENO_REG_REGISTER_MAX || + ADRENO_REG_UNUSED == + adreno_dev->gpudev->reg_offsets->offsets[offset_name]) { + BUG_ON(1); + } + return true; +} + +/* + * adreno_readreg() - Read a register by getting its offset from the + * offset array defined in gpudev node + * @adreno_dev: Pointer to the the adreno device + * @offset_name: The register enum that is to be read + * @val: Register value read is placed here + */ +static inline void adreno_readreg(struct adreno_device *adreno_dev, + enum adreno_regs offset_name, unsigned int *val) +{ + struct kgsl_device *device = &adreno_dev->dev; + if (adreno_checkreg_off(adreno_dev, offset_name)) + kgsl_regread(device, + adreno_dev->gpudev->reg_offsets->offsets[offset_name], + val); +} + +/* + * adreno_writereg() - Write a register by getting its offset from the + * offset array defined in gpudev node + * @adreno_dev: Pointer to the the adreno device + * @offset_name: The register enum that is to be written + * @val: Value to write + */ +static inline void adreno_writereg(struct adreno_device *adreno_dev, + enum adreno_regs offset_name, unsigned int val) +{ + struct kgsl_device *device = &adreno_dev->dev; + if (adreno_checkreg_off(adreno_dev, offset_name)) + kgsl_regwrite(device, + adreno_dev->gpudev->reg_offsets->offsets[offset_name], val); +} + +/* + * adreno_getreg() - Returns the offset value of a register from the + * register offset array in the gpudev node + * @adreno_dev: Pointer to the the adreno device + * @offset_name: The register enum whore offset is returned + */ +static inline unsigned int adreno_getreg(struct adreno_device *adreno_dev, + enum adreno_regs offset_name) +{ + if (!adreno_checkreg_off(adreno_dev, offset_name)) + return ADRENO_REG_REGISTER_MAX; + return adreno_dev->gpudev->reg_offsets->offsets[offset_name]; +} + +/** + * adreno_gpu_fault() - Return the current state of the GPU + * @adreno_dev: A ponter to the adreno_device to query + * + * Return 0 if there is no fault or positive with the last type of fault that + * occurred + */ +static inline unsigned int adreno_gpu_fault(struct adreno_device *adreno_dev) +{ + smp_rmb(); + return atomic_read(&adreno_dev->dispatcher.fault); +} + +/** + * adreno_set_gpu_fault() - Set the current fault status of the GPU + * @adreno_dev: A pointer to the adreno_device to set + * @state: fault state to set + * + */ +static inline void adreno_set_gpu_fault(struct adreno_device *adreno_dev, + int state) +{ + /* only set the fault bit w/o overwriting other bits */ + atomic_add(state, &adreno_dev->dispatcher.fault); + smp_wmb(); +} + +/* + * adreno_vbif_start() - Program VBIF registers, called in device start + * @device: Pointer to device whose vbif data is to be programmed + * @vbif_platforms: list register value pair of vbif for a family + * of adreno cores + * @num_platforms: Number of platforms contained in vbif_platforms + */ +static inline void adreno_vbif_start(struct kgsl_device *device, + const struct adreno_vbif_platform *vbif_platforms, + int num_platforms) +{ + int i; + const struct adreno_vbif_data *vbif = NULL; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + for (i = 0; i < num_platforms; i++) { + if (vbif_platforms[i].devfunc(adreno_dev)) { + vbif = vbif_platforms[i].vbif; + break; + } + } + BUG_ON(vbif == NULL); + while (vbif->reg != 0) { + kgsl_regwrite(device, vbif->reg, vbif->val); + vbif++; + } +} + #endif /*__ADRENO_H */ diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c index 93068c05c86..a5987afaad8 100644 --- a/drivers/gpu/msm/adreno_a2xx.c +++ b/drivers/gpu/msm/adreno_a2xx.c @@ -1355,7 +1355,8 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, tmp_ctx.gmem_base = adreno_dev->gmem_base; result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow, - drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size); + drawctxt->base.proc_priv->pagetable, + drawctxt->context_gmem_shadow.size); if (result) return result; @@ -1364,7 +1365,8 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, drawctxt->flags |= CTXT_FLAGS_GMEM_SHADOW; /* blank out gmem shadow. */ - kgsl_sharedmem_set(&drawctxt->context_gmem_shadow.gmemshadow, 0, 0, + kgsl_sharedmem_set(drawctxt->base.device, + &drawctxt->context_gmem_shadow.gmemshadow, 0, 0, drawctxt->context_gmem_shadow.size); /* build quad vertex buffer */ @@ -1388,7 +1390,7 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, kgsl_cache_range_op(&drawctxt->context_gmem_shadow.gmemshadow, KGSL_CACHE_OP_FLUSH); - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(drawctxt->base.device, &drawctxt->context_gmem_shadow.gmemshadow, drawctxt->context_gmem_shadow.gmemshadow.gpuaddr, drawctxt->context_gmem_shadow.gmemshadow.size, false); @@ -1396,11 +1398,56 @@ static int a2xx_create_gmem_shadow(struct adreno_device *adreno_dev, return 0; } +static void a2xx_drawctxt_detach(struct adreno_context *drawctxt) +{ + kgsl_sharedmem_free(&drawctxt->gpustate); + kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow); +} + +static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static int a2xx_drawctxt_draw_workaround(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static const struct adreno_context_ops a225_preamble_ctx_ops = { + .restore = adreno_context_restore, + .draw_workaround = a2xx_drawctxt_draw_workaround, +}; + +static const struct adreno_context_ops a225_legacy_ctx_ops = { + .save = a2xx_drawctxt_save, + .restore = a2xx_drawctxt_restore, + .draw_workaround = a2xx_drawctxt_draw_workaround, + .detach = a2xx_drawctxt_detach, +}; + +static const struct adreno_context_ops a2xx_legacy_ctx_ops = { + .save = a2xx_drawctxt_save, + .restore = a2xx_drawctxt_restore, + .detach = a2xx_drawctxt_detach, +}; + + static int a2xx_drawctxt_create(struct adreno_device *adreno_dev, struct adreno_context *drawctxt) { int ret; + if (drawctxt->flags & CTXT_FLAGS_PREAMBLE + && drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC) { + drawctxt->ops = (adreno_is_a225(adreno_dev)) + ? &a225_preamble_ctx_ops : &adreno_preamble_ctx_ops; + + return 0; + } + + drawctxt->ops = (adreno_is_a225(adreno_dev)) + ? &a225_legacy_ctx_ops : &a2xx_legacy_ctx_ops; + /* * Allocate memory for the GPU state and the context commands. * Despite the name, this is much more then just storage for @@ -1409,12 +1456,12 @@ static int a2xx_drawctxt_create(struct adreno_device *adreno_dev, */ ret = kgsl_allocate(&drawctxt->gpustate, - drawctxt->base.pagetable, _context_size(adreno_dev)); + drawctxt->base.proc_priv->pagetable, _context_size(adreno_dev)); if (ret) return ret; - kgsl_sharedmem_set(&drawctxt->gpustate, + kgsl_sharedmem_set(drawctxt->base.device, &drawctxt->gpustate, 0, 0, _context_size(adreno_dev)); tmp_ctx.cmd = tmp_ctx.start @@ -1439,7 +1486,7 @@ static int a2xx_drawctxt_create(struct adreno_device *adreno_dev, kgsl_cache_range_op(&drawctxt->gpustate, KGSL_CACHE_OP_FLUSH); - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(drawctxt->base.device, &drawctxt->gpustate, drawctxt->gpustate.gpuaddr, drawctxt->gpustate.size, false); @@ -1508,14 +1555,8 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, struct kgsl_device *device = &adreno_dev->dev; int ret; - if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED)) - return 0; - - if (context->state == ADRENO_CONTEXT_STATE_INVALID) - return 0; - if (!(context->flags & CTXT_FLAGS_PREAMBLE)) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->reg_save[1], context->reg_save[2] << 2, true); /* save registers and constants. */ @@ -1527,7 +1568,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, return ret; if (context->flags & CTXT_FLAGS_SHADER_SAVE) { - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->shader_save[1], context->shader_save[2] << 2, true); @@ -1536,7 +1577,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, KGSL_CMD_FLAGS_PMODE, context->shader_save, 3); - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->shader_fixup[1], context->shader_fixup[2] << 2, true); @@ -1557,7 +1598,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, if ((context->flags & CTXT_FLAGS_GMEM_SAVE) && (context->flags & CTXT_FLAGS_GMEM_SHADOW)) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->context_gmem_shadow.gmem_save[1], context->context_gmem_shadow.gmem_save[2] << 2, true); /* save gmem. @@ -1569,8 +1610,7 @@ static int a2xx_drawctxt_save(struct adreno_device *adreno_dev, if (ret) return ret; - - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->chicken_restore[1], context->chicken_restore[2] << 2, true); @@ -1596,44 +1636,18 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, struct adreno_context *context) { struct kgsl_device *device = &adreno_dev->dev; - unsigned int cmds[5]; - int ret = 0; - - if (context == NULL) { - /* No context - set the default pagetable and thats it */ - unsigned int id; - /* - * If there isn't a current context, the kgsl_mmu_setstate - * will use the CPU path so we don't need to give - * it a valid context id. - */ - id = (adreno_dev->drawctxt_active != NULL) - ? adreno_dev->drawctxt_active->base.id - : KGSL_CONTEXT_INVALID; - kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, - id); - return 0; - } + int ret; - cmds[0] = cp_nop_packet(1); - cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; - cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); - cmds[3] = device->memstore.gpuaddr + - KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); - cmds[4] = context->base.id; - ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, - cmds, 5); + ret = adreno_context_restore(adreno_dev, context); if (ret) return ret; - kgsl_mmu_setstate(&device->mmu, context->base.pagetable, - context->base.id); - - /* restore gmem. + /* + * restore gmem. * (note: changes shader. shader must not already be restored.) */ if (context->flags & CTXT_FLAGS_GMEM_RESTORE) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->context_gmem_shadow.gmem_restore[1], context->context_gmem_shadow.gmem_restore[2] << 2, true); @@ -1645,7 +1659,8 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, return ret; if (!(context->flags & CTXT_FLAGS_PREAMBLE)) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, + &context->gpustate, context->chicken_restore[1], context->chicken_restore[2] << 2, true); @@ -1661,7 +1676,7 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, } if (!(context->flags & CTXT_FLAGS_PREAMBLE)) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->reg_restore[1], context->reg_restore[2] << 2, true); @@ -1673,7 +1688,8 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, /* restore shader instructions & partitioning. */ if (context->flags & CTXT_FLAGS_SHADER_RESTORE) { - kgsl_cffdump_syncmem(NULL, &context->gpustate, + kgsl_cffdump_syncmem(context->base.device, + &context->gpustate, context->shader_restore[1], context->shader_restore[2] << 2, true); @@ -1686,6 +1702,7 @@ static int a2xx_drawctxt_restore(struct adreno_device *adreno_dev, } if (adreno_is_a20x(adreno_dev)) { + unsigned int cmds[2]; cmds[0] = cp_type3_packet(CP_SET_BIN_BASE_OFFSET, 1); cmds[1] = context->bin_base_offset; ret = adreno_ringbuffer_issuecmds(device, context, @@ -1742,11 +1759,11 @@ static void a2xx_cp_intrcallback(struct kgsl_device *device) struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; int i; - adreno_regread(device, REG_MASTER_INT_SIGNAL, &master_status); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &master_status); while (!status && (num_reads < VALID_STATUS_COUNT_MAX) && (master_status & MASTER_INT_SIGNAL__CP_INT_STAT)) { - adreno_regread(device, REG_CP_INT_STATUS, &status); - adreno_regread(device, REG_MASTER_INT_SIGNAL, + kgsl_regread(device, REG_CP_INT_STATUS, &status); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &master_status); num_reads++; } @@ -1788,7 +1805,7 @@ static void a2xx_cp_intrcallback(struct kgsl_device *device) /* only ack bits we understand */ status &= CP_INT_MASK; - adreno_regwrite(device, REG_CP_INT_ACK, status); + kgsl_regwrite(device, REG_CP_INT_ACK, status); if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) { queue_work(device->work_queue, &device->ts_expired_ws); @@ -1803,10 +1820,10 @@ static void a2xx_rbbm_intrcallback(struct kgsl_device *device) unsigned int addr = 0; const char *source; - adreno_regread(device, REG_RBBM_INT_STATUS, &status); + kgsl_regread(device, REG_RBBM_INT_STATUS, &status); if (status & RBBM_INT_CNTL__RDERR_INT_MASK) { - adreno_regread(device, REG_RBBM_READ_ERROR, &rderr); + kgsl_regread(device, REG_RBBM_READ_ERROR, &rderr); source = (rderr & RBBM_READ_ERROR_REQUESTER) ? "host" : "cp"; /* convert to dword address */ @@ -1830,7 +1847,7 @@ static void a2xx_rbbm_intrcallback(struct kgsl_device *device) } status &= RBBM_INT_MASK; - adreno_regwrite(device, REG_RBBM_INT_ACK, status); + kgsl_regwrite(device, REG_RBBM_INT_ACK, status); } irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev) @@ -1839,7 +1856,7 @@ irqreturn_t a2xx_irq_handler(struct adreno_device *adreno_dev) irqreturn_t result = IRQ_NONE; unsigned int status; - adreno_regread(device, REG_MASTER_INT_SIGNAL, &status); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &status); if (status & MASTER_INT_SIGNAL__MH_INT_STAT) { kgsl_mh_intrcallback(device); @@ -1864,14 +1881,14 @@ static void a2xx_irq_control(struct adreno_device *adreno_dev, int state) struct kgsl_device *device = &adreno_dev->dev; if (state) { - adreno_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK); - adreno_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK); - adreno_regwrite(device, MH_INTERRUPT_MASK, + kgsl_regwrite(device, REG_RBBM_INT_CNTL, RBBM_INT_MASK); + kgsl_regwrite(device, REG_CP_INT_CNTL, CP_INT_MASK); + kgsl_regwrite(device, MH_INTERRUPT_MASK, kgsl_mmu_get_int_mask()); } else { - adreno_regwrite(device, REG_RBBM_INT_CNTL, 0); - adreno_regwrite(device, REG_CP_INT_CNTL, 0); - adreno_regwrite(device, MH_INTERRUPT_MASK, 0); + kgsl_regwrite(device, REG_RBBM_INT_CNTL, 0); + kgsl_regwrite(device, REG_CP_INT_CNTL, 0); + kgsl_regwrite(device, MH_INTERRUPT_MASK, 0); } /* Force the writes to post before touching the IRQ line */ @@ -1881,14 +1898,14 @@ static void a2xx_irq_control(struct adreno_device *adreno_dev, int state) static unsigned int a2xx_irq_pending(struct adreno_device *adreno_dev) { struct kgsl_device *device = &adreno_dev->dev; - unsigned int rbbm, cp, mh; + unsigned int status; - adreno_regread(device, REG_RBBM_INT_CNTL, &rbbm); - adreno_regread(device, REG_CP_INT_CNTL, &cp); - adreno_regread(device, MH_INTERRUPT_MASK, &mh); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &status); - return ((rbbm & RBBM_INT_MASK) || (cp & CP_INT_MASK) || - (mh & kgsl_mmu_get_int_mask())) ? 1 : 0; + return (status & + (MASTER_INT_SIGNAL__MH_INT_STAT | + MASTER_INT_SIGNAL__CP_INT_STAT | + MASTER_INT_SIGNAL__RBBM_INT_STAT)) ? 1 : 0; } static int a2xx_rb_init(struct adreno_device *adreno_dev, @@ -1903,54 +1920,56 @@ static int a2xx_rb_init(struct adreno_device *adreno_dev, cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-19); - GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 18)); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, + 18)); /* All fields present (bits 9:0) */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x000003ff); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x000003ff); /* Disable/Enable Real-Time Stream processing (present but ignored) */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); /* Enable (2D <-> 3D) implicit synchronization (present but ignored) */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_RB_SURFACE_INFO)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_PA_SC_WINDOW_OFFSET)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_VGT_MAX_VTX_INDX)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_SQ_PROGRAM_CNTL)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_RB_DEPTHCONTROL)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_PA_SU_POINT_SIZE)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_PA_SC_LINE_CNTL)); - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, SUBBLOCK_OFFSET(REG_PA_SU_POLY_OFFSET_FRONT_SCALE)); /* Instruction memory size: */ - GSL_RB_WRITE(cmds, cmds_gpu, + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, (adreno_encode_istore_size(adreno_dev) | adreno_dev->pix_shader_start)); /* Maximum Contexts */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000001); /* Write Confirm Interval and The CP will wait the * wait_interval * 16 clocks between polling */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); /* NQ and External Memory Swap */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); /* Protected mode error checking * If iommu is used then protection needs to be turned off * to enable context bank switching */ if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) - GSL_RB_WRITE(cmds, cmds_gpu, 0); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0); else - GSL_RB_WRITE(cmds, cmds_gpu, GSL_RB_PROTECTED_MODE_CONTROL); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, + GSL_RB_PROTECTED_MODE_CONTROL); /* Disable header dumping and Header dump address */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); /* Header dump size */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); adreno_ringbuffer_submit(rb); @@ -1963,21 +1982,21 @@ static unsigned int a2xx_busy_cycles(struct adreno_device *adreno_dev) unsigned int reg, val; /* Freeze the counter */ - adreno_regwrite(device, REG_CP_PERFMON_CNTL, + kgsl_regwrite(device, REG_CP_PERFMON_CNTL, REG_PERF_MODE_CNT | REG_PERF_STATE_FREEZE); /* Get the value */ - adreno_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val); + kgsl_regread(device, REG_RBBM_PERFCOUNTER1_LO, &val); /* Reset the counter */ - adreno_regwrite(device, REG_CP_PERFMON_CNTL, + kgsl_regwrite(device, REG_CP_PERFMON_CNTL, REG_PERF_MODE_CNT | REG_PERF_STATE_RESET); /* Re-Enable the performance monitors */ - adreno_regread(device, REG_RBBM_PM_OVERRIDE2, ®); - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40)); - adreno_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1); - adreno_regwrite(device, REG_CP_PERFMON_CNTL, + kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, ®); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, (reg | 0x40)); + kgsl_regwrite(device, REG_RBBM_PERFCOUNTER1_SELECT, 0x1); + kgsl_regwrite(device, REG_CP_PERFMON_CNTL, REG_PERF_MODE_CNT | REG_PERF_STATE_ENABLE); return val; @@ -2003,7 +2022,7 @@ static void a2xx_gmeminit(struct adreno_device *adreno_dev) /* must be aligned to size */ rb_edram_info.f.edram_range = (adreno_dev->gmem_base >> 14); - adreno_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val); + kgsl_regwrite(device, REG_RB_EDRAM_INFO, rb_edram_info.val); } static void a2xx_start(struct adreno_device *adreno_dev) @@ -2015,8 +2034,8 @@ static void a2xx_start(struct adreno_device *adreno_dev) * before issuing a soft reset. The overrides will then be * turned off (set to 0) */ - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe); - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0xfffffffe); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xffffffff); /* * Only reset CP block if all blocks have previously been @@ -2024,11 +2043,11 @@ static void a2xx_start(struct adreno_device *adreno_dev) */ if (!(device->flags & KGSL_FLAGS_SOFT_RESET) || !adreno_is_a22x(adreno_dev)) { - adreno_regwrite(device, REG_RBBM_SOFT_RESET, + kgsl_regwrite(device, REG_RBBM_SOFT_RESET, 0xFFFFFFFF); device->flags |= KGSL_FLAGS_SOFT_RESET; } else { - adreno_regwrite(device, REG_RBBM_SOFT_RESET, + kgsl_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000001); } /* @@ -2037,11 +2056,11 @@ static void a2xx_start(struct adreno_device *adreno_dev) */ msleep(30); - adreno_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000); + kgsl_regwrite(device, REG_RBBM_SOFT_RESET, 0x00000000); if (adreno_is_a225(adreno_dev)) { /* Enable large instruction store for A225 */ - adreno_regwrite(device, REG_SQ_FLOW_CONTROL, + kgsl_regwrite(device, REG_SQ_FLOW_CONTROL, 0x18000000); } @@ -2049,46 +2068,245 @@ static void a2xx_start(struct adreno_device *adreno_dev) /* For A20X based targets increase number of clocks * that RBBM will wait before de-asserting Register * Clock Active signal */ - adreno_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF); + kgsl_regwrite(device, REG_RBBM_CNTL, 0x0000FFFF); else - adreno_regwrite(device, REG_RBBM_CNTL, 0x00004442); + kgsl_regwrite(device, REG_RBBM_CNTL, 0x00004442); - adreno_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000); - adreno_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000); + kgsl_regwrite(device, REG_SQ_VS_PROGRAM, 0x00000000); + kgsl_regwrite(device, REG_SQ_PS_PROGRAM, 0x00000000); if (cpu_is_msm8960()) - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0x200); else - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE1, 0); if (!adreno_is_a22x(adreno_dev)) - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0); else - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0x80); - adreno_regwrite(device, REG_RBBM_DEBUG, 0x00080000); + kgsl_regwrite(device, REG_RBBM_DEBUG, 0x00080000); /* Make sure interrupts are disabled */ - adreno_regwrite(device, REG_RBBM_INT_CNTL, 0); - adreno_regwrite(device, REG_CP_INT_CNTL, 0); - adreno_regwrite(device, REG_SQ_INT_CNTL, 0); + kgsl_regwrite(device, REG_RBBM_INT_CNTL, 0); + kgsl_regwrite(device, REG_CP_INT_CNTL, 0); + kgsl_regwrite(device, REG_SQ_INT_CNTL, 0); a2xx_gmeminit(adreno_dev); } +static void a2xx_postmortem_dump(struct adreno_device *adreno_dev) +{ + unsigned int r1, r2, r3, rbbm_status; + unsigned int cp_stat, rb_count; + struct kgsl_device *device = &adreno_dev->dev; + + kgsl_regread(device, REG_RBBM_STATUS, &rbbm_status); + + kgsl_regread(device, REG_RBBM_PM_OVERRIDE1, &r2); + kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &r3); + KGSL_LOG_DUMP(device, + "RBBM: STATUS = %08X | PM_OVERRIDE1 = %08X | PM_OVERRIDE2 = %08X\n", + rbbm_status, r2, r3); + + kgsl_regread(device, REG_RBBM_INT_CNTL, &r1); + kgsl_regread(device, REG_RBBM_INT_STATUS, &r2); + kgsl_regread(device, REG_RBBM_READ_ERROR, &r3); + KGSL_LOG_DUMP(device, + "INT_CNTL = %08X | INT_STATUS = %08X | READ_ERROR = %08X\n", + r1, r2, r3); + + { + char cmdFifo[16]; + struct log_field lines[] = { + {rbbm_status & 0x001F, cmdFifo}, + {rbbm_status & BIT(5), "TC busy "}, + {rbbm_status & BIT(8), "HIRQ pending"}, + {rbbm_status & BIT(9), "CPRQ pending"}, + {rbbm_status & BIT(10), "CFRQ pending"}, + {rbbm_status & BIT(11), "PFRQ pending"}, + {rbbm_status & BIT(12), "VGT 0DMA bsy"}, + {rbbm_status & BIT(14), "RBBM WU busy"}, + {rbbm_status & BIT(16), "CP NRT busy "}, + {rbbm_status & BIT(18), "MH busy "}, + {rbbm_status & BIT(19), "MH chncy bsy"}, + {rbbm_status & BIT(21), "SX busy "}, + {rbbm_status & BIT(22), "TPC busy "}, + {rbbm_status & BIT(24), "SC CNTX busy"}, + {rbbm_status & BIT(25), "PA busy "}, + {rbbm_status & BIT(26), "VGT busy "}, + {rbbm_status & BIT(27), "SQ cntx1 bsy"}, + {rbbm_status & BIT(28), "SQ cntx0 bsy"}, + {rbbm_status & BIT(30), "RB busy "}, + {rbbm_status & BIT(31), "Grphs pp bsy"}, + }; + snprintf(cmdFifo, sizeof(cmdFifo), "CMD FIFO=%01X ", + rbbm_status & 0xf); + adreno_dump_fields(device, " STATUS=", lines, + ARRAY_SIZE(lines)); + } + + kgsl_regread(device, REG_CP_RB_BASE, &r1); + kgsl_regread(device, REG_CP_RB_CNTL, &r2); + rb_count = 2 << (r2 & (BIT(6)-1)); + kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3); + KGSL_LOG_DUMP(device, + " RPTR = %08X | WPTR = %08X | RPTR_WR = %08X" + "\n", r1, r2, r3); + + kgsl_regread(device, REG_CP_IB1_BASE, &r1); + kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2); + KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ = %d\n", r1, r2); + + kgsl_regread(device, REG_CP_IB2_BASE, &r1); + kgsl_regread(device, REG_CP_IB2_BUFSZ, &r2); + KGSL_LOG_DUMP(device, "CP_IB2: BASE = %08X | BUFSZ = %d\n", r1, r2); + + kgsl_regread(device, REG_CP_INT_CNTL, &r1); + kgsl_regread(device, REG_CP_INT_STATUS, &r2); + KGSL_LOG_DUMP(device, "CP_INT: CNTL = %08X | STATUS = %08X\n", r1, r2); + + kgsl_regread(device, REG_CP_ME_CNTL, &r1); + kgsl_regread(device, REG_CP_ME_STATUS, &r2); + kgsl_regread(device, REG_MASTER_INT_SIGNAL, &r3); + KGSL_LOG_DUMP(device, + "CP_ME: CNTL = %08X | STATUS = %08X | MSTR_INT_SGNL = " + "%08X\n", r1, r2, r3); + + kgsl_regread(device, REG_CP_STAT, &cp_stat); + KGSL_LOG_DUMP(device, "CP_STAT = %08X\n", cp_stat); +#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL + { + struct log_field lns[] = { + {cp_stat & BIT(0), "WR_BSY 0"}, + {cp_stat & BIT(1), "RD_RQ_BSY 1"}, + {cp_stat & BIT(2), "RD_RTN_BSY 2"}, + }; + adreno_dump_fields(device, " MIU=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(5), "RING_BUSY 5"}, + {cp_stat & BIT(6), "NDRCTS_BSY 6"}, + {cp_stat & BIT(7), "NDRCT2_BSY 7"}, + {cp_stat & BIT(9), "ST_BUSY 9"}, + {cp_stat & BIT(10), "BUSY 10"}, + }; + adreno_dump_fields(device, " CSF=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(11), "RNG_Q_BSY 11"}, + {cp_stat & BIT(12), "NDRCTS_Q_B12"}, + {cp_stat & BIT(13), "NDRCT2_Q_B13"}, + {cp_stat & BIT(16), "ST_QUEUE_B16"}, + {cp_stat & BIT(17), "PFP_BUSY 17"}, + }; + adreno_dump_fields(device, " RING=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(3), "RBIU_BUSY 3"}, + {cp_stat & BIT(4), "RCIU_BUSY 4"}, + {cp_stat & BIT(18), "MQ_RG_BSY 18"}, + {cp_stat & BIT(19), "MQ_NDRS_BS19"}, + {cp_stat & BIT(20), "MQ_NDR2_BS20"}, + {cp_stat & BIT(21), "MIU_WC_STL21"}, + {cp_stat & BIT(22), "CP_NRT_BSY22"}, + {cp_stat & BIT(23), "3D_BUSY 23"}, + {cp_stat & BIT(26), "ME_BUSY 26"}, + {cp_stat & BIT(29), "ME_WC_BSY 29"}, + {cp_stat & BIT(30), "MIU_FF EM 30"}, + {cp_stat & BIT(31), "CP_BUSY 31"}, + }; + adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns)); + } +#endif + + kgsl_regread(device, REG_SCRATCH_REG0, &r1); + KGSL_LOG_DUMP(device, "SCRATCH_REG0 = %08X\n", r1); + + kgsl_regread(device, REG_COHER_SIZE_PM4, &r1); + kgsl_regread(device, REG_COHER_BASE_PM4, &r2); + kgsl_regread(device, REG_COHER_STATUS_PM4, &r3); + KGSL_LOG_DUMP(device, + "COHER: SIZE_PM4 = %08X | BASE_PM4 = %08X | STATUS_PM4" + " = %08X\n", r1, r2, r3); + + kgsl_regread(device, MH_AXI_ERROR, &r1); + KGSL_LOG_DUMP(device, "MH: AXI_ERROR = %08X\n", r1); + + kgsl_regread(device, MH_MMU_PAGE_FAULT, &r1); + kgsl_regread(device, MH_MMU_CONFIG, &r2); + kgsl_regread(device, MH_MMU_MPU_BASE, &r3); + KGSL_LOG_DUMP(device, + "MH_MMU: PAGE_FAULT = %08X | CONFIG = %08X | MPU_BASE =" + " %08X\n", r1, r2, r3); + + kgsl_regread(device, MH_MMU_MPU_END, &r1); + kgsl_regread(device, MH_MMU_VA_RANGE, &r2); + r3 = kgsl_mmu_get_current_ptbase(&device->mmu); + KGSL_LOG_DUMP(device, + " MPU_END = %08X | VA_RANGE = %08X | PT_BASE =" + " %08X\n", r1, r2, r3); + + KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ", + kgsl_mmu_get_ptsize(&device->mmu)); + + kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1); + KGSL_LOG_DUMP(device, " TRAN_ERROR = %08X\n", r1); + + kgsl_regread(device, MH_INTERRUPT_MASK, &r1); + kgsl_regread(device, MH_INTERRUPT_STATUS, &r2); + KGSL_LOG_DUMP(device, + "MH_INTERRUPT: MASK = %08X | STATUS = %08X\n", r1, r2); +} + +/* Register offset defines for A2XX */ +static unsigned int a2xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { + ADRENO_REG_DEFINE(ADRENO_REG_CP_DEBUG, REG_CP_DEBUG), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_WADDR, REG_CP_ME_RAM_WADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_DATA, REG_CP_ME_RAM_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_DATA, REG_CP_PFP_UCODE_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_ADDR, REG_CP_PFP_UCODE_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE, REG_CP_RB_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR_ADDR, REG_CP_RB_RPTR_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, REG_CP_RB_RPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, REG_CP_RB_WPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, REG_CP_ME_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, REG_CP_RB_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, REG_CP_IB1_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BUFSZ, REG_CP_IB1_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BASE, REG_CP_IB2_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BUFSZ, REG_CP_IB2_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_TIMESTAMP, REG_CP_TIMESTAMP), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_RADDR, REG_CP_ME_RAM_RADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_ADDR, REG_SCRATCH_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_UMSK, REG_SCRATCH_UMSK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_STATUS, REG_RBBM_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_PA_SC_AA_CONFIG, REG_PA_SC_AA_CONFIG), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PM_OVERRIDE2, REG_RBBM_PM_OVERRIDE2), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_REG2, REG_SCRATCH_REG2), + ADRENO_REG_DEFINE(ADRENO_REG_SQ_GPR_MANAGEMENT, REG_SQ_GPR_MANAGEMENT), + ADRENO_REG_DEFINE(ADRENO_REG_SQ_INST_STORE_MANAGMENT, + REG_SQ_INST_STORE_MANAGMENT), + ADRENO_REG_DEFINE(ADRENO_REG_TC_CNTL_STATUS, REG_TC_CNTL_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_TP0_CHICKEN, REG_TP0_CHICKEN), +}; + +const struct adreno_reg_offsets a2xx_reg_offsets = { + .offsets = a2xx_register_offsets, + .offset_0 = ADRENO_REG_REGISTER_MAX, +}; + /* Defined in adreno_a2xx_snapshot.c */ void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, int *remain, int hang); struct adreno_gpudev adreno_a2xx_gpudev = { - .reg_rbbm_status = REG_RBBM_STATUS, - .reg_cp_pfp_ucode_addr = REG_CP_PFP_UCODE_ADDR, - .reg_cp_pfp_ucode_data = REG_CP_PFP_UCODE_DATA, + .reg_offsets = &a2xx_reg_offsets, .ctxt_create = a2xx_drawctxt_create, - .ctxt_save = a2xx_drawctxt_save, - .ctxt_restore = a2xx_drawctxt_restore, - .ctxt_draw_workaround = a2xx_drawctxt_draw_workaround, .irq_handler = a2xx_irq_handler, .irq_control = a2xx_irq_control, .irq_pending = a2xx_irq_pending, @@ -2096,4 +2314,5 @@ struct adreno_gpudev adreno_a2xx_gpudev = { .rb_init = a2xx_rb_init, .busy_cycles = a2xx_busy_cycles, .start = a2xx_start, + .postmortem_dump = a2xx_postmortem_dump, }; diff --git a/drivers/gpu/msm/adreno_a2xx_snapshot.c b/drivers/gpu/msm/adreno_a2xx_snapshot.c index 2c86f82d4df..5134ed6ff1a 100644 --- a/drivers/gpu/msm/adreno_a2xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a2xx_snapshot.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, 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 @@ -38,11 +38,11 @@ static int a2xx_snapshot_sxdebug(struct kgsl_device *device, void *snapshot, header->size = SXDEBUG_COUNT; for (i = 0; i < SXDEBUG_COUNT; i++) { - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i); - adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1B00 | i); + kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); } - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); return DEBUG_SECTION_SZ(SXDEBUG_COUNT); } @@ -65,11 +65,11 @@ static int a2xx_snapshot_cpdebug(struct kgsl_device *device, void *snapshot, header->size = CPDEBUG_COUNT; for (i = 0; i < CPDEBUG_COUNT; i++) { - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628); - adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1628); + kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); } - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); return DEBUG_SECTION_SZ(CPDEBUG_COUNT); } @@ -82,7 +82,8 @@ static int a2xx_snapshot_cpdebug(struct kgsl_device *device, void *snapshot, #define SQ_DEBUG_WRITE(_device, _reg, _data, _offset) \ do { _data[(_offset)++] = (_reg); \ - adreno_regread(_device, (_reg), &_data[(_offset)++]); } while (0) + kgsl_regread(_device, (_reg), &_data[(_offset)++]); \ + } while (0) #define SQ_DEBUG_BANK_SIZE 23 @@ -175,7 +176,7 @@ static int a2xx_snapshot_sqthreaddebug(struct kgsl_device *device, header->size = size; for (i = 0; i < 16; i++) { - adreno_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL, + kgsl_regwrite(device, REG_SQ_DEBUG_TB_STATUS_SEL, i | (6<<4) | (i<<7) | (1<<11) | (1<<12) | (i<<16) | (6<<20) | (i<<23)); SQ_DEBUG_WRITE(device, REG_SQ_DEBUG_VTX_TB_STATE_MEM, @@ -215,11 +216,11 @@ static int a2xx_snapshot_miudebug(struct kgsl_device *device, void *snapshot, header->size = MIUDEBUG_COUNT; for (i = 0; i < MIUDEBUG_COUNT; i++) { - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i); - adreno_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0x1600 | i); + kgsl_regread(device, REG_RBBM_DEBUG_OUT, &data[i]); } - adreno_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); + kgsl_regwrite(device, REG_RBBM_DEBUG_CNTL, 0); return DEBUG_SECTION_SZ(MIUDEBUG_COUNT); } @@ -297,8 +298,8 @@ void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, * work */ - adreno_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride); - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF); + kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &pmoverride); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, 0xFF); /* SX debug registers */ snapshot = kgsl_snapshot_add_section(device, @@ -376,7 +377,7 @@ void *a2xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, /* Reset the clock gating */ - adreno_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride); + kgsl_regwrite(device, REG_RBBM_PM_OVERRIDE2, pmoverride); return snapshot; } diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c index 1e61279e10f..3934226fdfd 100644 --- a/drivers/gpu/msm/adreno_a3xx.c +++ b/drivers/gpu/msm/adreno_a3xx.c @@ -52,8 +52,8 @@ const unsigned int a3xx_registers[] = { 0x2240, 0x227e, 0x2280, 0x228b, 0x22c0, 0x22c0, 0x22c4, 0x22ce, 0x22d0, 0x22d8, 0x22df, 0x22e6, 0x22e8, 0x22e9, 0x22ec, 0x22ec, 0x22f0, 0x22f7, - 0x22ff, 0x22ff, 0x2340, 0x2343, 0x2348, 0x2349, 0x2350, 0x2356, - 0x2360, 0x2360, 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d, + 0x22ff, 0x22ff, 0x2340, 0x2343, + 0x2440, 0x2440, 0x2444, 0x2444, 0x2448, 0x244d, 0x2468, 0x2469, 0x246c, 0x246d, 0x2470, 0x2470, 0x2472, 0x2472, 0x2474, 0x2475, 0x2479, 0x247a, 0x24c0, 0x24d3, 0x24e4, 0x24ef, 0x2500, 0x2509, 0x250c, 0x250c, 0x250e, 0x250e, 0x2510, 0x2511, @@ -61,8 +61,8 @@ const unsigned int a3xx_registers[] = { 0x25f0, 0x25f0, 0x2640, 0x267e, 0x2680, 0x268b, 0x26c0, 0x26c0, 0x26c4, 0x26ce, 0x26d0, 0x26d8, 0x26df, 0x26e6, 0x26e8, 0x26e9, 0x26ec, 0x26ec, - 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, 0x2748, 0x2749, - 0x2750, 0x2756, 0x2760, 0x2760, 0x300C, 0x300E, 0x301C, 0x301D, + 0x26f0, 0x26f7, 0x26ff, 0x26ff, 0x2740, 0x2743, + 0x300C, 0x300E, 0x301C, 0x301D, 0x302A, 0x302A, 0x302C, 0x302D, 0x3030, 0x3031, 0x3034, 0x3036, 0x303C, 0x303C, 0x305E, 0x305F, }; @@ -450,12 +450,16 @@ unsigned int adreno_a3xx_rbbm_clock_ctl_default(struct adreno_device { if (adreno_is_a305(adreno_dev)) return A305_RBBM_CLOCK_CTL_DEFAULT; + else if (adreno_is_a305c(adreno_dev)) + return A305C_RBBM_CLOCK_CTL_DEFAULT; else if (adreno_is_a320(adreno_dev)) return A320_RBBM_CLOCK_CTL_DEFAULT; else if (adreno_is_a330v2(adreno_dev)) return A330v2_RBBM_CLOCK_CTL_DEFAULT; else if (adreno_is_a330(adreno_dev)) return A330_RBBM_CLOCK_CTL_DEFAULT; + else if (adreno_is_a305b(adreno_dev)) + return A305B_RBBM_CLOCK_CTL_DEFAULT; BUG_ON(1); } @@ -2317,7 +2321,8 @@ static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev, tmp_ctx.gmem_base = adreno_dev->gmem_base; result = kgsl_allocate(&drawctxt->context_gmem_shadow.gmemshadow, - drawctxt->base.pagetable, drawctxt->context_gmem_shadow.size); + drawctxt->base.proc_priv->pagetable, + drawctxt->context_gmem_shadow.size); if (result) return result; @@ -2338,25 +2343,49 @@ static int a3xx_create_gmem_shadow(struct adreno_device *adreno_dev, return 0; } +static void a3xx_drawctxt_detach(struct adreno_context *drawctxt) +{ + kgsl_sharedmem_free(&drawctxt->gpustate); + kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow); +} + +static int a3xx_drawctxt_save(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev, + struct adreno_context *context); + +static const struct adreno_context_ops a3xx_legacy_ctx_ops = { + .save = a3xx_drawctxt_save, + .restore = a3xx_drawctxt_restore, + .detach = a3xx_drawctxt_detach, +}; + + static int a3xx_drawctxt_create(struct adreno_device *adreno_dev, struct adreno_context *drawctxt) { int ret; /* - * Allocate memory for the GPU state and the context commands. - * Despite the name, this is much more then just storage for - * the gpustate. This contains command space for gmem save - * and texture and vertex buffer storage too + * Nothing to do here if the context is using preambles and doesn't need + * GMEM save/restore */ + if ((drawctxt->flags & CTXT_FLAGS_PREAMBLE) && + (drawctxt->flags & CTXT_FLAGS_NOGMEMALLOC)) { + drawctxt->ops = &adreno_preamble_ctx_ops; + return 0; + } + drawctxt->ops = &a3xx_legacy_ctx_ops; ret = kgsl_allocate(&drawctxt->gpustate, - drawctxt->base.pagetable, CONTEXT_SIZE); + drawctxt->base.proc_priv->pagetable, CONTEXT_SIZE); if (ret) return ret; - kgsl_sharedmem_set(&drawctxt->gpustate, 0, 0, CONTEXT_SIZE); + kgsl_sharedmem_set(&adreno_dev->dev, &drawctxt->gpustate, 0, 0, + CONTEXT_SIZE); tmp_ctx.cmd = drawctxt->gpustate.hostptr + CMD_OFFSET; if (!(drawctxt->flags & CTXT_FLAGS_PREAMBLE)) { @@ -2383,9 +2412,6 @@ static int a3xx_drawctxt_save(struct adreno_device *adreno_dev, struct kgsl_device *device = &adreno_dev->dev; int ret; - if (context == NULL || (context->flags & CTXT_FLAGS_BEING_DESTROYED)) - return 0; - if (context->state == ADRENO_CONTEXT_STATE_INVALID) return 0; @@ -2443,46 +2469,20 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev, struct adreno_context *context) { struct kgsl_device *device = &adreno_dev->dev; - unsigned int cmds[5]; - int ret = 0; - - if (context == NULL) { - /* No context - set the default pagetable and thats it */ - unsigned int id; - /* - * If there isn't a current context, the kgsl_mmu_setstate - * will use the CPU path so we don't need to give - * it a valid context id. - */ - id = (adreno_dev->drawctxt_active != NULL) - ? adreno_dev->drawctxt_active->base.id - : KGSL_CONTEXT_INVALID; - kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, - id); - return 0; - } + int ret; - cmds[0] = cp_nop_packet(1); - cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; - cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); - cmds[3] = device->memstore.gpuaddr + - KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); - cmds[4] = context->base.id; - ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, - cmds, 5); + /* do the common part */ + ret = adreno_context_restore(adreno_dev, context); if (ret) return ret; - kgsl_mmu_setstate(&device->mmu, context->base.pagetable, - context->base.id); - /* * Restore GMEM. (note: changes shader. * Shader must not already be restored.) */ if (context->flags & CTXT_FLAGS_GMEM_RESTORE) { - kgsl_cffdump_syncmem(NULL, + kgsl_cffdump_syncmem(context->base.device, &context->gpustate, context->context_gmem_shadow.gmem_restore[1], context->context_gmem_shadow.gmem_restore[2] << 2, @@ -2531,7 +2531,487 @@ static int a3xx_drawctxt_restore(struct adreno_device *adreno_dev, return ret; } -static int a3xx_rb_init(struct adreno_device *adreno_dev, +static const unsigned int _a3xx_pwron_fixup_fs_instructions[] = { + 0x00000000, 0x302CC300, 0x00000000, 0x302CC304, + 0x00000000, 0x302CC308, 0x00000000, 0x302CC30C, + 0x00000000, 0x302CC310, 0x00000000, 0x302CC314, + 0x00000000, 0x302CC318, 0x00000000, 0x302CC31C, + 0x00000000, 0x302CC320, 0x00000000, 0x302CC324, + 0x00000000, 0x302CC328, 0x00000000, 0x302CC32C, + 0x00000000, 0x302CC330, 0x00000000, 0x302CC334, + 0x00000000, 0x302CC338, 0x00000000, 0x302CC33C, + 0x00000000, 0x00000400, 0x00020000, 0x63808003, + 0x00060004, 0x63828007, 0x000A0008, 0x6384800B, + 0x000E000C, 0x6386800F, 0x00120010, 0x63888013, + 0x00160014, 0x638A8017, 0x001A0018, 0x638C801B, + 0x001E001C, 0x638E801F, 0x00220020, 0x63908023, + 0x00260024, 0x63928027, 0x002A0028, 0x6394802B, + 0x002E002C, 0x6396802F, 0x00320030, 0x63988033, + 0x00360034, 0x639A8037, 0x003A0038, 0x639C803B, + 0x003E003C, 0x639E803F, 0x00000000, 0x00000400, + 0x00000003, 0x80D60003, 0x00000007, 0x80D60007, + 0x0000000B, 0x80D6000B, 0x0000000F, 0x80D6000F, + 0x00000013, 0x80D60013, 0x00000017, 0x80D60017, + 0x0000001B, 0x80D6001B, 0x0000001F, 0x80D6001F, + 0x00000023, 0x80D60023, 0x00000027, 0x80D60027, + 0x0000002B, 0x80D6002B, 0x0000002F, 0x80D6002F, + 0x00000033, 0x80D60033, 0x00000037, 0x80D60037, + 0x0000003B, 0x80D6003B, 0x0000003F, 0x80D6003F, + 0x00000000, 0x03000000, 0x00000000, 0x00000000, +}; + +/** + * adreno_a3xx_pwron_fixup_init() - Initalize a special command buffer to run a + * post-power collapse shader workaround + * @adreno_dev: Pointer to a adreno_device struct + * + * Some targets require a special workaround shader to be executed after + * power-collapse. Construct the IB once at init time and keep it + * handy + * + * Returns: 0 on success or negative on error + */ +int adreno_a3xx_pwron_fixup_init(struct adreno_device *adreno_dev) +{ + unsigned int *cmds; + int count = ARRAY_SIZE(_a3xx_pwron_fixup_fs_instructions); + int ret; + + /* Return if the fixup is already in place */ + if (test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv)) + return 0; + + ret = kgsl_allocate_contiguous(&adreno_dev->pwron_fixup, PAGE_SIZE); + + if (ret) + return ret; + + adreno_dev->pwron_fixup.flags |= KGSL_MEMFLAGS_GPUREADONLY; + + cmds = adreno_dev->pwron_fixup.hostptr; + + *cmds++ = cp_type0_packet(A3XX_UCHE_CACHE_INVALIDATE0_REG, 2); + *cmds++ = 0x00000000; + *cmds++ = 0x90000000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_REG_RMW, 3); + *cmds++ = A3XX_RBBM_CLOCK_CTL; + *cmds++ = 0xFFFCFFFF; + *cmds++ = 0x00010000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1); + *cmds++ = 0x1E000150; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2); + *cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG); + *cmds++ = 0x1E000150; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1); + *cmds++ = 0x1E000150; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_1_REG, 1); + *cmds++ = 0x00000040; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_2_REG, 1); + *cmds++ = 0x80000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_3_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_VS_CONTROL_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_FS_CONTROL_REG, 1); + *cmds++ = 0x0D001002; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONST_VSPRESV_RANGE_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONST_FSPRESV_RANGE_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_0_REG, 1); + *cmds++ = 0x00401101; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_1_REG, 1); + *cmds++ = 0x00000400; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_2_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_3_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_4_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_5_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_NDRANGE_6_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_0_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_1_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_CONST_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG, 1); + *cmds++ = 0x00000010; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_Y_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_KERNEL_GROUP_Z_REG, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_WG_OFFSET_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_SP_CTRL_REG, 1); + *cmds++ = 0x00040000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG0, 1); + *cmds++ = 0x0000000A; + *cmds++ = cp_type0_packet(A3XX_SP_VS_CTRL_REG1, 1); + *cmds++ = 0x00000001; + *cmds++ = cp_type0_packet(A3XX_SP_VS_PARAM_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_6, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OUT_REG_7, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_VPC_DST_REG_3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OBJ_OFFSET_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_OBJ_START_REG, 1); + *cmds++ = 0x00000004; + *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_PARAM_REG, 1); + *cmds++ = 0x04008001; + *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_ADDR_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_PVT_MEM_SIZE_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_VS_LENGTH_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG0, 1); + *cmds++ = 0x0DB0400A; + *cmds++ = cp_type0_packet(A3XX_SP_FS_CTRL_REG1, 1); + *cmds++ = 0x00300402; + *cmds++ = cp_type0_packet(A3XX_SP_FS_OBJ_OFFSET_REG, 1); + *cmds++ = 0x00010000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_OBJ_START_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_PARAM_REG, 1); + *cmds++ = 0x04008001; + *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_ADDR_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_PVT_MEM_SIZE_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_FLAT_SHAD_MODE_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_FLAT_SHAD_MODE_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_OUTPUT_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_MRT_REG_3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_IMAGE_OUTPUT_REG_3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_SP_FS_LENGTH_REG, 1); + *cmds++ = 0x0000000D; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_CLIP_CNTL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_GB_CLIP_ADJ, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_XOFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_XSCALE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_YOFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_YSCALE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_ZOFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_VPORT_ZSCALE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W4, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_X5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Y5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_Z5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_CL_USER_PLANE_W5, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POINT_MINMAX, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POINT_SIZE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POLY_OFFSET_OFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_POLY_OFFSET_SCALE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SU_MODE_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_SCREEN_SCISSOR_TL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_SCREEN_SCISSOR_BR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_WINDOW_SCISSOR_BR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_SC_WINDOW_SCISSOR_TL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_TSE_DEBUG_ECO, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER0_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER1_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER2_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_GRAS_PERFCOUNTER3_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MODE_CONTROL, 1); + *cmds++ = 0x00008000; + *cmds++ = cp_type0_packet(A3XX_RB_RENDER_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MSAA_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_ALPHA_REFERENCE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_CONTROL3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_INFO3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BUF_BASE3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_MRT_BLEND_CONTROL3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_BLEND_RED, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_BLEND_GREEN, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_BLEND_BLUE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_BLEND_ALPHA, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW0, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW1, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW2, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_CLEAR_COLOR_DW3, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_COPY_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_BASE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_PITCH, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_COPY_DEST_INFO, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_CLEAR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_BUF_INFO, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEPTH_BUF_PITCH, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_CLEAR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_BUF_INFO, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_BUF_PITCH, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_REF_MASK, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_STENCIL_REF_MASK_BF, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_LRZ_VSC_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_WINDOW_OFFSET, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_SAMPLE_COUNT_CONTROL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_SAMPLE_COUNT_ADDR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_Z_CLAMP_MIN, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_Z_CLAMP_MAX, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_GMEM_BASE_ADDR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_DEBUG_ECO_CONTROLS_ADDR, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_PERFCOUNTER0_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_PERFCOUNTER1_SELECT, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_RB_FRAME_BUFFER_DIMENSION, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4); + *cmds++ = (1 << CP_LOADSTATE_DSTOFFSET_SHIFT) | + (0 << CP_LOADSTATE_STATESRC_SHIFT) | + (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) | + (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT); + *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT) | + (0 << CP_LOADSTATE_EXTSRCADDR_SHIFT); + *cmds++ = 0x00400000; + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4); + *cmds++ = (2 << CP_LOADSTATE_DSTOFFSET_SHIFT) | + (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) | + (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT); + *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT); + *cmds++ = 0x00400220; + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_LOAD_STATE, 4); + *cmds++ = (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) | + (1 << CP_LOADSTATE_NUMOFUNITS_SHIFT); + *cmds++ = (1 << CP_LOADSTATE_STATETYPE_SHIFT); + *cmds++ = 0x00000000; + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_LOAD_STATE, 2 + count); + *cmds++ = (6 << CP_LOADSTATE_STATEBLOCKID_SHIFT) | + (13 << CP_LOADSTATE_NUMOFUNITS_SHIFT); + *cmds++ = 0x00000000; + + memcpy(cmds, _a3xx_pwron_fixup_fs_instructions, count << 2); + + cmds += count; + + *cmds++ = cp_type3_packet(CP_EXEC_CL, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CL_CONTROL_0_REG, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type0_packet(A3XX_HLSQ_CONTROL_0_REG, 1); + *cmds++ = 0x1E000150; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_SET_CONSTANT, 2); + *cmds++ = CP_REG(A3XX_HLSQ_CONTROL_0_REG); + *cmds++ = 0x1E000050; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_REG_RMW, 3); + *cmds++ = A3XX_RBBM_CLOCK_CTL; + *cmds++ = 0xFFFCFFFF; + *cmds++ = 0x00000000; + *cmds++ = cp_type3_packet(CP_WAIT_FOR_IDLE, 1); + *cmds++ = 0x00000000; + + /* + * Remember the number of dwords in the command buffer for when we + * program the indirect buffer call in the ringbuffer + */ + adreno_dev->pwron_fixup_dwords = + (cmds - (unsigned int *) adreno_dev->pwron_fixup.hostptr); + + /* Mark the flag in ->priv to show that we have the fix */ + set_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv); + return 0; +} + +/* + * a3xx_rb_init() - Initialize ringbuffer + * @adreno_dev: Pointer to adreno device + * @rb: Pointer to the ringbuffer of device + * + * Submit commands for ME initialization, common function shared between + * a3xx and a4xx devices + */ +int a3xx_rb_init(struct adreno_device *adreno_dev, struct adreno_ringbuffer *rb) { unsigned int *cmds, cmds_gpu; @@ -2541,25 +3021,26 @@ static int a3xx_rb_init(struct adreno_device *adreno_dev, cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint) * (rb->wptr - 18); - GSL_RB_WRITE(cmds, cmds_gpu, cp_type3_packet(CP_ME_INIT, 17)); - GSL_RB_WRITE(cmds, cmds_gpu, 0x000003f7); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000080); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000100); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000180); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00006600); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000150); - GSL_RB_WRITE(cmds, cmds_gpu, 0x0000014e); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000154); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000001); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - /* Protected mode control - turned off for A3XX */ - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); - GSL_RB_WRITE(cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, + cp_type3_packet(CP_ME_INIT, 17)); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x000003f7); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000080); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000100); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000180); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00006600); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000150); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x0000014e); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000154); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000001); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + /* Protected mode control - turned off for A3XX/A4XX */ + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000); adreno_ringbuffer_submit(rb); @@ -2575,7 +3056,7 @@ static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit) case A3XX_INT_RBBM_AHB_ERROR: { unsigned int reg; - adreno_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, ®); + kgsl_regread(device, A3XX_RBBM_AHB_ERROR_STATUS, ®); /* * Return the word address of the erroring register so that it @@ -2589,11 +3070,8 @@ static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit) (reg >> 24) & 0x3); /* Clear the error */ - adreno_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3)); - - /* Trigger a fault in the interrupt handler */ - adreno_dispatcher_irq_fault(device); - return; + kgsl_regwrite(device, A3XX_RBBM_AHB_CMD, (1 << 3)); + goto done; } case A3XX_INT_RBBM_REG_TIMEOUT: err = "RBBM: AHB register timeout"; @@ -2637,171 +3115,71 @@ static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit) default: return; } + KGSL_DRV_CRIT(device, "%s\n", err); + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); +done: /* Trigger a fault in the dispatcher - this will effect a restart */ adreno_dispatcher_irq_fault(device); - - KGSL_DRV_CRIT(device, "%s\n", err); - kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); } +/* + * a3xx_cp_callback() - CP interrupt handler + * @adreno_dev: Adreno device pointer + * @irq: irq number + * + * Handle the cp interrupt generated by GPU, common function between a3xx and + * a4xx devices + */ static void a3xx_cp_callback(struct adreno_device *adreno_dev, int irq) { struct kgsl_device *device = &adreno_dev->dev; - /* Schedule the event queue */ + device->pwrctrl.irq_last = 1; queue_work(device->work_queue, &device->ts_expired_ws); adreno_dispatcher_schedule(device); } -/** - * struct a3xx_perfcounter_register - Define a performance counter register - * @load_bit: the bit to set in RBBM_LOAD_CMD0/RBBM_LOAD_CMD1 to force the RBBM - * to load the reset value into the appropriate counter - * @select: The dword offset of the register to write the selected - * countable into - */ - -struct a3xx_perfcounter_register { - unsigned int load_bit; - unsigned int select; -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_cp[] = { - { 0, A3XX_CP_PERFCOUNTER_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_rbbm[] = { - { 1, A3XX_RBBM_PERFCOUNTER0_SELECT }, - { 2, A3XX_RBBM_PERFCOUNTER1_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_pc[] = { - { 3, A3XX_PC_PERFCOUNTER0_SELECT }, - { 4, A3XX_PC_PERFCOUNTER1_SELECT }, - { 5, A3XX_PC_PERFCOUNTER2_SELECT }, - { 6, A3XX_PC_PERFCOUNTER3_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_vfd[] = { - { 7, A3XX_VFD_PERFCOUNTER0_SELECT }, - { 8, A3XX_VFD_PERFCOUNTER1_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_hlsq[] = { - { 9, A3XX_HLSQ_PERFCOUNTER0_SELECT }, - { 10, A3XX_HLSQ_PERFCOUNTER1_SELECT }, - { 11, A3XX_HLSQ_PERFCOUNTER2_SELECT }, - { 12, A3XX_HLSQ_PERFCOUNTER3_SELECT }, - { 13, A3XX_HLSQ_PERFCOUNTER4_SELECT }, - { 14, A3XX_HLSQ_PERFCOUNTER5_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_vpc[] = { - { 15, A3XX_VPC_PERFCOUNTER0_SELECT }, - { 16, A3XX_VPC_PERFCOUNTER1_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_tse[] = { - { 17, A3XX_GRAS_PERFCOUNTER0_SELECT }, - { 18, A3XX_GRAS_PERFCOUNTER1_SELECT }, -}; -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_ras[] = { - { 19, A3XX_GRAS_PERFCOUNTER2_SELECT }, - { 20, A3XX_GRAS_PERFCOUNTER3_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_uche[] = { - { 21, A3XX_UCHE_PERFCOUNTER0_SELECT }, - { 22, A3XX_UCHE_PERFCOUNTER1_SELECT }, - { 23, A3XX_UCHE_PERFCOUNTER2_SELECT }, - { 24, A3XX_UCHE_PERFCOUNTER3_SELECT }, - { 25, A3XX_UCHE_PERFCOUNTER4_SELECT }, - { 26, A3XX_UCHE_PERFCOUNTER5_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_tp[] = { - { 27, A3XX_TP_PERFCOUNTER0_SELECT }, - { 28, A3XX_TP_PERFCOUNTER1_SELECT }, - { 29, A3XX_TP_PERFCOUNTER2_SELECT }, - { 30, A3XX_TP_PERFCOUNTER3_SELECT }, - { 31, A3XX_TP_PERFCOUNTER4_SELECT }, - { 32, A3XX_TP_PERFCOUNTER5_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_sp[] = { - { 33, A3XX_SP_PERFCOUNTER0_SELECT }, - { 34, A3XX_SP_PERFCOUNTER1_SELECT }, - { 35, A3XX_SP_PERFCOUNTER2_SELECT }, - { 36, A3XX_SP_PERFCOUNTER3_SELECT }, - { 37, A3XX_SP_PERFCOUNTER4_SELECT }, - { 38, A3XX_SP_PERFCOUNTER5_SELECT }, - { 39, A3XX_SP_PERFCOUNTER6_SELECT }, - { 40, A3XX_SP_PERFCOUNTER7_SELECT }, -}; - -static struct a3xx_perfcounter_register a3xx_perfcounter_reg_rb[] = { - { 41, A3XX_RB_PERFCOUNTER0_SELECT }, - { 42, A3XX_RB_PERFCOUNTER1_SELECT }, -}; - -#define REGCOUNTER_GROUP(_x) { (_x), ARRAY_SIZE((_x)) } - -static struct { - struct a3xx_perfcounter_register *regs; - int count; -} a3xx_perfcounter_reglist[] = { - REGCOUNTER_GROUP(a3xx_perfcounter_reg_cp), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_rbbm), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_pc), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_vfd), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_hlsq), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_vpc), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_tse), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_ras), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_uche), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_tp), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_sp), - REGCOUNTER_GROUP(a3xx_perfcounter_reg_rb), -}; - -static void a3xx_perfcounter_enable_pwr(struct kgsl_device *device, - unsigned int countable) +static int a3xx_perfcounter_enable_pwr(struct kgsl_device *device, + unsigned int counter) { unsigned int in, out; - adreno_regread(device, A3XX_RBBM_RBBM_CTL, &in); + if (counter > 1) + return -EINVAL; + + kgsl_regread(device, A3XX_RBBM_RBBM_CTL, &in); - if (countable == 0) + if (counter == 0) out = in | RBBM_RBBM_CTL_RESET_PWR_CTR0; else out = in | RBBM_RBBM_CTL_RESET_PWR_CTR1; - adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out); + kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out); - if (countable == 0) + if (counter == 0) out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR0; else out = in | RBBM_RBBM_CTL_ENABLE_PWR_CTR1; - adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, out); + kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, out); - return; + return 0; } -static void a3xx_perfcounter_enable_vbif(struct kgsl_device *device, +static int a3xx_perfcounter_enable_vbif(struct kgsl_device *device, unsigned int counter, unsigned int countable) { unsigned int in, out, bit, sel; if (counter > 1 || countable > 0x7f) - return; + return -EINVAL; - adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); - adreno_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel); + kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); + kgsl_regread(device, A3XX_VBIF_PERF_CNT_SEL, &sel); if (counter == 0) { bit = VBIF_PERF_CNT_0; @@ -2814,33 +3192,38 @@ static void a3xx_perfcounter_enable_vbif(struct kgsl_device *device, out = in | bit; - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_SEL, sel); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + return 0; } -static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device, - unsigned int countable) +static int a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device, + unsigned int counter) { unsigned int in, out, bit; - adreno_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); - if (countable == 0) + if (counter > 2) + return -EINVAL; + + kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); + if (counter == 0) bit = VBIF_PERF_PWR_CNT_0; - else if (countable == 1) + else if (counter == 1) bit = VBIF_PERF_PWR_CNT_1; else bit = VBIF_PERF_PWR_CNT_2; out = in | bit; - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, bit); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_CLR, 0); - adreno_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + return 0; } /* @@ -2851,73 +3234,177 @@ static void a3xx_perfcounter_enable_vbif_pwr(struct kgsl_device *device, * @countable - Desired countable * * Physically set up a counter within a group with the desired countable + * Return 0 on success else error code */ -static void a3xx_perfcounter_enable(struct adreno_device *adreno_dev, +static int a3xx_perfcounter_enable(struct adreno_device *adreno_dev, unsigned int group, unsigned int counter, unsigned int countable) { struct kgsl_device *device = &adreno_dev->dev; unsigned int val = 0; - struct a3xx_perfcounter_register *reg; - - if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist)) - return; - - if (counter >= a3xx_perfcounter_reglist[group].count) - return; + struct adreno_perfcount_register *reg; /* Special cases */ if (group == KGSL_PERFCOUNTER_GROUP_PWR) - return a3xx_perfcounter_enable_pwr(device, countable); + return a3xx_perfcounter_enable_pwr(device, counter); else if (group == KGSL_PERFCOUNTER_GROUP_VBIF) - return a3xx_perfcounter_enable_vbif(device, counter, countable); + return a3xx_perfcounter_enable_vbif(device, counter, + countable); else if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR) - return a3xx_perfcounter_enable_vbif_pwr(device, countable); + return a3xx_perfcounter_enable_vbif_pwr(device, counter); + + if (group >= adreno_dev->gpudev->perfcounters->group_count) + return -EINVAL; - reg = &(a3xx_perfcounter_reglist[group].regs[counter]); + if ((0 == adreno_dev->gpudev->perfcounters->groups[group].reg_count) || + (counter >= + adreno_dev->gpudev->perfcounters->groups[group].reg_count)) + return -EINVAL; + + reg = &(adreno_dev->gpudev->perfcounters->groups[group].regs[counter]); /* Select the desired perfcounter */ - adreno_regwrite(device, reg->select, countable); + kgsl_regwrite(device, reg->select, countable); if (reg->load_bit < 32) { - val = 1 << reg->load_bit; - adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val); + kgsl_regread(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, &val); + val |= (1 << reg->load_bit); + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD0, val); } else { - val = 1 << (reg->load_bit - 32); - adreno_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val); + kgsl_regread(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, &val); + val |= (1 << (reg->load_bit - 32)); + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_LOAD_CMD1, val); } + return 0; +} + +static uint64_t a3xx_perfcounter_read_pwr(struct adreno_device *adreno_dev, + unsigned int counter) +{ + struct kgsl_device *device = &adreno_dev->dev; + struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; + struct adreno_perfcount_register *reg; + unsigned int in, out, lo = 0, hi = 0; + unsigned int enable_bit; + + if (counter > 1) + return 0; + if (0 == counter) + enable_bit = RBBM_RBBM_CTL_ENABLE_PWR_CTR0; + else + enable_bit = RBBM_RBBM_CTL_ENABLE_PWR_CTR1; + /* freeze counter */ + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, &in); + out = (in & ~enable_bit); + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, out); + + reg = &counters->groups[KGSL_PERFCOUNTER_GROUP_PWR].regs[counter]; + kgsl_regread(device, reg->offset, &lo); + kgsl_regread(device, reg->offset + 1, &hi); + + /* restore the counter control value */ + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_RBBM_CTL, in); + + return (((uint64_t) hi) << 32) | lo; +} + +static uint64_t a3xx_perfcounter_read_vbif(struct adreno_device *adreno_dev, + unsigned int counter) +{ + struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; + struct kgsl_device *device = &adreno_dev->dev; + struct adreno_perfcount_register *reg; + unsigned int in, out, lo = 0, hi = 0; + + if (counter > 1) + return 0; + + /* freeze counter */ + kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); + if (counter == 0) + out = (in & ~VBIF_PERF_CNT_0); + else + out = (in & ~VBIF_PERF_CNT_1); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + + reg = &counters->groups[KGSL_PERFCOUNTER_GROUP_VBIF].regs[counter]; + kgsl_regread(device, reg->offset, &lo); + kgsl_regread(device, reg->offset + 1, &hi); + + /* restore the perfcounter value */ + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, in); + + return (((uint64_t) hi) << 32) | lo; +} + +static uint64_t a3xx_perfcounter_read_vbif_pwr(struct adreno_device *adreno_dev, + unsigned int counter) +{ + struct adreno_perfcounters *counters = adreno_dev->gpudev->perfcounters; + struct kgsl_device *device = &adreno_dev->dev; + struct adreno_perfcount_register *reg; + unsigned int in, out, lo = 0, hi = 0; + + if (counter > 2) + return 0; + + /* freeze counter */ + kgsl_regread(device, A3XX_VBIF_PERF_CNT_EN, &in); + if (0 == counter) + out = (in & ~VBIF_PERF_PWR_CNT_0); + else + out = (in & ~VBIF_PERF_PWR_CNT_2); + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, out); + + reg = &counters->groups[KGSL_PERFCOUNTER_GROUP_VBIF_PWR].regs[counter]; + kgsl_regread(device, reg->offset, &lo); + kgsl_regread(device, reg->offset + 1, &hi); + /* restore the perfcounter value */ + kgsl_regwrite(device, A3XX_VBIF_PERF_CNT_EN, in); + + return (((uint64_t) hi) << 32) | lo; } static uint64_t a3xx_perfcounter_read(struct adreno_device *adreno_dev, - unsigned int group, unsigned int counter, - unsigned int offset) + unsigned int group, unsigned int counter) { struct kgsl_device *device = &adreno_dev->dev; - struct a3xx_perfcounter_register *reg = NULL; + struct adreno_perfcount_register *reg; unsigned int lo = 0, hi = 0; - unsigned int val; + unsigned int offset; + unsigned int in, out; - if (group >= ARRAY_SIZE(a3xx_perfcounter_reglist)) + if (group == KGSL_PERFCOUNTER_GROUP_VBIF_PWR) + return a3xx_perfcounter_read_vbif_pwr(adreno_dev, counter); + + if (group == KGSL_PERFCOUNTER_GROUP_VBIF) + return a3xx_perfcounter_read_vbif(adreno_dev, counter); + + if (group == KGSL_PERFCOUNTER_GROUP_PWR) + return a3xx_perfcounter_read_pwr(adreno_dev, counter); + + if (group >= adreno_dev->gpudev->perfcounters->group_count) return 0; - if (counter >= a3xx_perfcounter_reglist[group].count) + if ((0 == adreno_dev->gpudev->perfcounters->groups[group].reg_count) || + (counter >= + adreno_dev->gpudev->perfcounters->groups[group].reg_count)) return 0; - reg = &(a3xx_perfcounter_reglist[group].regs[counter]); + reg = &(adreno_dev->gpudev->perfcounters->groups[group].regs[counter]); /* Freeze the counter */ - adreno_regread(device, A3XX_RBBM_PERFCTR_CTL, &val); - val &= ~reg->load_bit; - adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val); + kgsl_regread(device, A3XX_RBBM_PERFCTR_CTL, &in); + out = in & ~RBBM_PERFCTR_CTL_ENABLE; + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, out); + offset = reg->offset; /* Read the values */ - adreno_regread(device, offset, &lo); - adreno_regread(device, offset + 1, &hi); + kgsl_regread(device, offset, &lo); + kgsl_regread(device, offset + 1, &hi); /* Re-Enable the counter */ - val |= reg->load_bit; - adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, val); - + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, in); return (((uint64_t) hi) << 32) | lo; } @@ -2969,14 +3456,21 @@ static struct { /* 26 to 31 - Unused */ }; -static irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev) +/* + * a3xx_irq_handler() - Interrupt handler function + * @adreno_dev: Pointer to adreno device + * + * Interrupt handler for adreno device, this function is common between + * a3xx and a4xx devices + */ +irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev) { struct kgsl_device *device = &adreno_dev->dev; irqreturn_t ret = IRQ_NONE; unsigned int status, tmp; int i; - adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status); + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS, &status); for (tmp = status, i = 0; tmp && i < ARRAY_SIZE(a3xx_irq_funcs); i++) { if (tmp & 1) { @@ -2995,38 +3489,57 @@ static irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev) trace_kgsl_a3xx_irq_status(device, status); if (status) - adreno_regwrite(&adreno_dev->dev, A3XX_RBBM_INT_CLEAR_CMD, - status); + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_INT_CLEAR_CMD, + status); return ret; } -static void a3xx_irq_control(struct adreno_device *adreno_dev, int state) +/* + * a3xx_irq_control() - Function called to enable/disable interrupts + * @adreno_dev: Pointer to device whose interrupts are enabled/disabled + * @state: When set interrupts are enabled else disabled + * + * This function is common for a3xx and a4xx adreno devices + */ +void a3xx_irq_control(struct adreno_device *adreno_dev, int state) { - struct kgsl_device *device = &adreno_dev->dev; - if (state) - adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, A3XX_INT_MASK); + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_INT_0_MASK, + A3XX_INT_MASK); else - adreno_regwrite(device, A3XX_RBBM_INT_0_MASK, 0); + adreno_writereg(adreno_dev, ADRENO_REG_RBBM_INT_0_MASK, 0); } -static unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev) +/* + * a3xx_irq_pending() - Checks if interrupt is generated by h/w + * @adreno_dev: Pointer to device whose interrupts are checked + * + * Returns true if interrupts are pending from device else 0. This + * function is shared by both a3xx and a4xx devices. + */ +unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev) { unsigned int status; - adreno_regread(&adreno_dev->dev, A3XX_RBBM_INT_0_STATUS, &status); + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_INT_0_STATUS, &status); return (status & A3XX_INT_MASK) ? 1 : 0; } -static unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev) +/* + * a3xx_busy_cycles() - Returns number of gpu cycles + * @adreno_dev: Pointer to device ehose cycles are checked + * + * Returns number of busy clycles since the last time this function is called + * Function is common between a3xx and a4xx devices + */ +unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev) { - struct kgsl_device *device = &adreno_dev->dev; unsigned int val; unsigned int ret = 0; /* Read the value */ - adreno_regread(device, A3XX_RBBM_PERFCTR_PWR_1_LO, &val); + adreno_readreg(adreno_dev, ADRENO_REG_RBBM_PERFCTR_PWR_1_LO, &val); /* Return 0 for the first read */ if (adreno_dev->gpu_cycles != 0) { @@ -3040,13 +3553,8 @@ static unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev) return ret; } -struct a3xx_vbif_data { - unsigned int reg; - unsigned int val; -}; - /* VBIF registers start after 0x3000 so use 0x0 as end of list marker */ -static struct a3xx_vbif_data a305_vbif[] = { +static const struct adreno_vbif_data a305_vbif[] = { /* Set up 16 deep read/write request queues */ { A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 }, { A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010 }, @@ -3065,7 +3573,30 @@ static struct a3xx_vbif_data a305_vbif[] = { {0, 0}, }; -static struct a3xx_vbif_data a320_vbif[] = { +static const struct adreno_vbif_data a305b_vbif[] = { + { A3XX_VBIF_IN_RD_LIM_CONF0, 0x00181818 }, + { A3XX_VBIF_IN_WR_LIM_CONF0, 0x00181818 }, + { A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000018 }, + { A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000018 }, + { A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000303 }, + { A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 }, + {0, 0}, +}; + +static const struct adreno_vbif_data a305c_vbif[] = { + { A3XX_VBIF_IN_RD_LIM_CONF0, 0x00101010 }, + { A3XX_VBIF_IN_WR_LIM_CONF0, 0x00101010 }, + { A3XX_VBIF_OUT_RD_LIM_CONF0, 0x00000010 }, + { A3XX_VBIF_OUT_WR_LIM_CONF0, 0x00000010 }, + { A3XX_VBIF_DDR_OUT_MAX_BURST, 0x00000101 }, + { A3XX_VBIF_ARB_CTL, 0x00000010 }, + /* Set up AOOO */ + { A3XX_VBIF_OUT_AXI_AOOO_EN, 0x00000007 }, + { A3XX_VBIF_OUT_AXI_AOOO, 0x00070007 }, + {0, 0}, +}; + +static const struct adreno_vbif_data a320_vbif[] = { /* Set up 16 deep read/write request queues */ { A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010 }, { A3XX_VBIF_IN_RD_LIM_CONF1, 0x10101010 }, @@ -3087,7 +3618,7 @@ static struct a3xx_vbif_data a320_vbif[] = { {0, 0}, }; -static struct a3xx_vbif_data a330_vbif[] = { +static const struct adreno_vbif_data a330_vbif[] = { /* Set up 16 deep read/write request queues */ { A3XX_VBIF_IN_RD_LIM_CONF0, 0x18181818 }, { A3XX_VBIF_IN_RD_LIM_CONF1, 0x00001818 }, @@ -3119,7 +3650,7 @@ static struct a3xx_vbif_data a330_vbif[] = { * Most of the VBIF registers on 8974v2 have the correct values at power on, so * we won't modify those if we don't need to */ -static struct a3xx_vbif_data a330v2_vbif[] = { +static const struct adreno_vbif_data a330v2_vbif[] = { /* Enable 1k sort */ { A3XX_VBIF_ABIT_SORT, 0x0001003F }, { A3XX_VBIF_ABIT_SORT_CONF, 0x000000A4 }, @@ -3128,26 +3659,214 @@ static struct a3xx_vbif_data a330v2_vbif[] = { { A3XX_VBIF_DDR_OUT_MAX_BURST, 0x0000303 }, /* Set up VBIF_ROUND_ROBIN_QOS_ARB */ { A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003 }, - /* Disable VBIF clock gating. This is to enable AXI running - * higher frequency than GPU. - */ - { A3XX_VBIF_CLKON, 1 }, {0, 0}, }; -static struct { - int(*devfunc)(struct adreno_device *); - struct a3xx_vbif_data *vbif; -} a3xx_vbif_platforms[] = { +const struct adreno_vbif_platform a3xx_vbif_platforms[] = { { adreno_is_a305, a305_vbif }, + { adreno_is_a305c, a305c_vbif }, { adreno_is_a320, a320_vbif }, /* A330v2 needs to be ahead of A330 so the right device matches */ { adreno_is_a330v2, a330v2_vbif }, { adreno_is_a330, a330_vbif }, + { adreno_is_a305b, a305b_vbif }, +}; + +/* + * Define the available perfcounter groups - these get used by + * adreno_perfcounter_get and adreno_perfcounter_put + */ + +static struct adreno_perfcount_register a3xx_perfcounters_cp[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_CP_0_LO, + 0, A3XX_CP_PERFCOUNTER_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_rbbm[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO, + 1, A3XX_RBBM_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO, + 2, A3XX_RBBM_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_pc[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_0_LO, + 3, A3XX_PC_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_1_LO, + 4, A3XX_PC_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_2_LO, + 5, A3XX_PC_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PC_3_LO, + 6, A3XX_PC_PERFCOUNTER3_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_vfd[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VFD_0_LO, + 7, A3XX_VFD_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VFD_1_LO, + 8, A3XX_VFD_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_hlsq[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO, + 9, A3XX_HLSQ_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO, + 10, A3XX_HLSQ_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO, + 11, A3XX_HLSQ_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO, + 12, A3XX_HLSQ_PERFCOUNTER3_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO, + 13, A3XX_HLSQ_PERFCOUNTER4_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO, + 14, A3XX_HLSQ_PERFCOUNTER5_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_vpc[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VPC_0_LO, + 15, A3XX_VPC_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_VPC_1_LO, + 16, A3XX_VPC_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_tse[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TSE_0_LO, + 17, A3XX_GRAS_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TSE_1_LO, + 18, A3XX_GRAS_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_ras[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RAS_0_LO, + 19, A3XX_GRAS_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RAS_1_LO, + 20, A3XX_GRAS_PERFCOUNTER3_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_uche[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO, + 21, A3XX_UCHE_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO, + 22, A3XX_UCHE_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO, + 23, A3XX_UCHE_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO, + 24, A3XX_UCHE_PERFCOUNTER3_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO, + 25, A3XX_UCHE_PERFCOUNTER4_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO, + 26, A3XX_UCHE_PERFCOUNTER5_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_tp[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_0_LO, + 27, A3XX_TP_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_1_LO, + 28, A3XX_TP_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_2_LO, + 29, A3XX_TP_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_3_LO, + 30, A3XX_TP_PERFCOUNTER3_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_4_LO, + 31, A3XX_TP_PERFCOUNTER4_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_TP_5_LO, + 32, A3XX_TP_PERFCOUNTER5_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_sp[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_0_LO, + 33, A3XX_SP_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_1_LO, + 34, A3XX_SP_PERFCOUNTER1_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_2_LO, + 35, A3XX_SP_PERFCOUNTER2_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_3_LO, + 36, A3XX_SP_PERFCOUNTER3_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_4_LO, + 37, A3XX_SP_PERFCOUNTER4_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_5_LO, + 38, A3XX_SP_PERFCOUNTER5_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_6_LO, + 39, A3XX_SP_PERFCOUNTER6_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_SP_7_LO, + 40, A3XX_SP_PERFCOUNTER7_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_rb[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RB_0_LO, + 41, A3XX_RB_PERFCOUNTER0_SELECT }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_RB_1_LO, + 42, A3XX_RB_PERFCOUNTER1_SELECT }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_pwr[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PWR_0_LO, + -1, 0 }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, + -1, 0 }, +}; + +static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_CNT0_LO, -1, 0 }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_CNT1_LO, -1, 0 }, +}; +static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = { + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT0_LO, -1, 0 }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT1_LO, -1, 0 }, + { KGSL_PERFCOUNTER_NOT_USED, 0, 0, A3XX_VBIF_PERF_PWR_CNT2_LO, -1, 0 }, +}; + +static struct adreno_perfcount_group a3xx_perfcounter_groups[] = { + ADRENO_PERFCOUNTER_GROUP(a3xx, cp), + ADRENO_PERFCOUNTER_GROUP(a3xx, rbbm), + ADRENO_PERFCOUNTER_GROUP(a3xx, pc), + ADRENO_PERFCOUNTER_GROUP(a3xx, vfd), + ADRENO_PERFCOUNTER_GROUP(a3xx, hlsq), + ADRENO_PERFCOUNTER_GROUP(a3xx, vpc), + ADRENO_PERFCOUNTER_GROUP(a3xx, tse), + ADRENO_PERFCOUNTER_GROUP(a3xx, ras), + ADRENO_PERFCOUNTER_GROUP(a3xx, uche), + ADRENO_PERFCOUNTER_GROUP(a3xx, tp), + ADRENO_PERFCOUNTER_GROUP(a3xx, sp), + ADRENO_PERFCOUNTER_GROUP(a3xx, rb), + ADRENO_PERFCOUNTER_GROUP(a3xx, pwr), + ADRENO_PERFCOUNTER_GROUP(a3xx, vbif), + ADRENO_PERFCOUNTER_GROUP(a3xx, vbif_pwr), +}; + +static struct adreno_perfcounters a3xx_perfcounters = { + a3xx_perfcounter_groups, + ARRAY_SIZE(a3xx_perfcounter_groups), }; -static void a3xx_perfcounter_init(struct adreno_device *adreno_dev) +/* + * a3xx_perfcounter_close() - Return counters that were initialized in + * a3xx_perfcounter_init + * @adreno_dev: The device for which counters were initialized + */ +static void a3xx_perfcounter_close(struct adreno_device *adreno_dev) +{ + adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + SP_FS_FULL_ALU_INSTRUCTIONS, + PERFCOUNTER_FLAG_KERNEL); + adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + SP_FS_CFLOW_INSTRUCTIONS, + PERFCOUNTER_FLAG_KERNEL); + adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + SP0_ICL1_MISSES, + PERFCOUNTER_FLAG_KERNEL); + adreno_perfcounter_put(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + SP_ALU_ACTIVE_CYCLES, + PERFCOUNTER_FLAG_KERNEL); +} + +static int a3xx_perfcounter_init(struct adreno_device *adreno_dev) { + int ret; + /* SP[3] counter is broken on a330 so disable it if a330 device */ + if (adreno_is_a330(adreno_dev)) + a3xx_perfcounters_sp[3].countable = KGSL_PERFCOUNTER_BROKEN; + /* * Set SP to count SP_ALU_ACTIVE_CYCLES, it includes * all ALU instruction execution regardless precision or shader ID. @@ -3158,238 +3877,510 @@ static void a3xx_perfcounter_init(struct adreno_device *adreno_dev) * we will use this to augment our hang detection */ if (adreno_dev->fast_hang_detect) { - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_SP, SP_ALU_ACTIVE_CYCLES, &ft_detect_regs[6], PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; ft_detect_regs[7] = ft_detect_regs[6] + 1; - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_SP, SP0_ICL1_MISSES, &ft_detect_regs[8], PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; ft_detect_regs[9] = ft_detect_regs[8] + 1; - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + ret = adreno_perfcounter_get(adreno_dev, + KGSL_PERFCOUNTER_GROUP_SP, SP_FS_CFLOW_INSTRUCTIONS, &ft_detect_regs[10], PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; ft_detect_regs[11] = ft_detect_regs[10] + 1; } - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, + ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_SP, SP_FS_FULL_ALU_INSTRUCTIONS, NULL, PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; /* Reserve and start countable 1 in the PWR perfcounter group */ - adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1, + ret = adreno_perfcounter_get(adreno_dev, KGSL_PERFCOUNTER_GROUP_PWR, 1, NULL, PERFCOUNTER_FLAG_KERNEL); + if (ret) + goto err; + + return ret; + +err: + a3xx_perfcounter_close(adreno_dev); + return ret; +} + +/** + * a3xx_protect_init() - Initializes register protection on a3xx + * @device: Pointer to the device structure + * Performs register writes to enable protected access to sensitive + * registers + */ +static void a3xx_protect_init(struct kgsl_device *device) +{ + /* enable access protection to privileged registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007); + + /* RBBM registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400); + + /* CP registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178); + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180); + + /* RB registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300); + + /* VBIF registers */ + kgsl_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000); } static void a3xx_start(struct adreno_device *adreno_dev) { struct kgsl_device *device = &adreno_dev->dev; - struct a3xx_vbif_data *vbif = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(a3xx_vbif_platforms); i++) { - if (a3xx_vbif_platforms[i].devfunc(adreno_dev)) { - vbif = a3xx_vbif_platforms[i].vbif; - break; - } - } - - BUG_ON(vbif == NULL); - while (vbif->reg != 0) { - adreno_regwrite(device, vbif->reg, vbif->val); - vbif++; - } + adreno_vbif_start(device, a3xx_vbif_platforms, + ARRAY_SIZE(a3xx_vbif_platforms)); /* Make all blocks contribute to the GPU BUSY perf counter */ - adreno_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF); + kgsl_regwrite(device, A3XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF); /* Tune the hystersis counters for SP and CP idle detection */ - adreno_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10); - adreno_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); + kgsl_regwrite(device, A3XX_RBBM_SP_HYST_CNT, 0x10); + kgsl_regwrite(device, A3XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); /* Enable the RBBM error reporting bits. This lets us get useful information on failure */ - adreno_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001); + kgsl_regwrite(device, A3XX_RBBM_AHB_CTL0, 0x00000001); /* Enable AHB error reporting */ - adreno_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF); + kgsl_regwrite(device, A3XX_RBBM_AHB_CTL1, 0xA6FFFFFF); /* Turn on the power counters */ - adreno_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00030000); + kgsl_regwrite(device, A3XX_RBBM_RBBM_CTL, 0x00030000); /* Turn on hang detection - this spews a lot of useful information * into the RBBM registers on a hang */ - adreno_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL, + kgsl_regwrite(device, A3XX_RBBM_INTERFACE_HANG_INT_CTL, (1 << 16) | 0xFFF); /* Enable 64-byte cacheline size. HW Default is 32-byte (0x000000E0). */ - adreno_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001); + kgsl_regwrite(device, A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001); /* Enable Clock gating */ - adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL, + kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL, adreno_a3xx_rbbm_clock_ctl_default(adreno_dev)); if (adreno_is_a330v2(adreno_dev)) - adreno_regwrite(device, A3XX_RBBM_GPR0_CTL, + kgsl_regwrite(device, A3XX_RBBM_GPR0_CTL, A330v2_RBBM_GPR0_CTL_DEFAULT); else if (adreno_is_a330(adreno_dev)) - adreno_regwrite(device, A3XX_RBBM_GPR0_CTL, + kgsl_regwrite(device, A3XX_RBBM_GPR0_CTL, A330_RBBM_GPR0_CTL_DEFAULT); /* Set the OCMEM base address for A330 */ - if (adreno_is_a330(adreno_dev)) { - adreno_regwrite(device, A3XX_RB_GMEM_BASE_ADDR, + if (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) { + kgsl_regwrite(device, A3XX_RB_GMEM_BASE_ADDR, (unsigned int)(adreno_dev->ocmem_base >> 14)); } + /* Turn on protection */ + a3xx_protect_init(device); /* Turn on performance counters */ - adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01); + kgsl_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01); /* Turn on the GPU busy counter and let it run free */ adreno_dev->gpu_cycles = 0; } -/* - * Define the available perfcounter groups - these get used by - * adreno_perfcounter_get and adreno_perfcounter_put +/** + * a3xx_coresight_enable() - Enables debugging through coresight + * debug bus for adreno a3xx devices. + * @device: Pointer to GPU device structure */ +int a3xx_coresight_enable(struct kgsl_device *device) +{ + mutex_lock(&device->mutex); + if (!kgsl_active_count_get(device)) { + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0001093F); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0, + 0x00000000); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1, + 0xFFFFFFFE); + kgsl_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL, + 0x00201111); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, + 0x89100010); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, + 0x00017fff); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT, + 0x0001000f); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT , + 0x0001ffff); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD, + 0x00000001); + kgsl_active_count_put(device); + } + mutex_unlock(&device->mutex); + return 0; +} -static struct adreno_perfcount_register a3xx_perfcounters_cp[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_CP_0_LO, 0 }, -}; +/** + * a3xx_coresight_disable() - Disables debugging through coresight + * debug bus for adreno a3xx devices. + * @device: Pointer to GPU device structure + */ +void a3xx_coresight_disable(struct kgsl_device *device) +{ + mutex_lock(&device->mutex); + if (!kgsl_active_count_get(device)) { + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, 0x0); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL0, 0x0); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_STB_CTL1, 0x0); + kgsl_regwrite(device, A3XX_RBBM_INT_TRACE_BUS_CTL, 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_START_CNT, 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT , 0x0); + kgsl_regwrite(device, A3XX_RBBM_EXT_TRACE_CMD, 0x0); + kgsl_active_count_put(device); + } + mutex_unlock(&device->mutex); +} -static struct adreno_perfcount_register a3xx_perfcounters_rbbm[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RBBM_1_LO, 0 }, -}; +static void a3xx_coresight_write_reg(struct kgsl_device *device, + unsigned int wordoffset, unsigned int val) +{ + mutex_lock(&device->mutex); + if (!kgsl_active_count_get(device)) { + kgsl_regwrite(device, wordoffset, val); + kgsl_active_count_put(device); + } + mutex_unlock(&device->mutex); +} -static struct adreno_perfcount_register a3xx_perfcounters_pc[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PC_3_LO, 0 }, -}; +void a3xx_coresight_config_debug_reg(struct kgsl_device *device, + int debug_reg, unsigned int val) +{ + switch (debug_reg) { -static struct adreno_perfcount_register a3xx_perfcounters_vfd[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VFD_1_LO, 0 }, -}; + case DEBUG_BUS_CTL: + a3xx_coresight_write_reg(device, A3XX_RBBM_DEBUG_BUS_CTL, val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_hlsq[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_3_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_4_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_HLSQ_5_LO, 0 }, -}; + case TRACE_STOP_CNT: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_STOP_CNT, + val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_vpc[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_VPC_1_LO, 0 }, -}; + case TRACE_START_CNT: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_START_CNT, + val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_tse[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TSE_1_LO, 0 }, -}; + case TRACE_PERIOD_CNT: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_PERIOD_CNT, + val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_ras[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RAS_1_LO, 0 }, -}; + case TRACE_CMD: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_CMD, val); + break; -static struct adreno_perfcount_register a3xx_perfcounters_uche[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_3_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_4_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_UCHE_5_LO, 0 }, -}; + case TRACE_BUS_CTL: + a3xx_coresight_write_reg(device, A3XX_RBBM_EXT_TRACE_BUS_CTL, + val); + break; + } -static struct adreno_perfcount_register a3xx_perfcounters_tp[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_3_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_4_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_TP_5_LO, 0 }, -}; +} -static struct adreno_perfcount_register a3xx_perfcounters_sp[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_1_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_2_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_3_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_4_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_5_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_6_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_SP_7_LO, 0 }, -}; +/* + * a3xx_soft_reset() - Soft reset GPU + * @adreno_dev: Pointer to adreno device + * + * Soft reset the GPU by doing a AHB write of value 1 to RBBM_SW_RESET + * register. This is used when we want to reset the GPU without + * turning off GFX power rail. The reset when asserted resets + * all the HW logic, restores GPU registers to default state and + * flushes out pending VBIF transactions. + */ +static void a3xx_soft_reset(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = &adreno_dev->dev; + unsigned int reg; -static struct adreno_perfcount_register a3xx_perfcounters_rb[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_RB_1_LO, 0 }, -}; + kgsl_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 1); + /* + * Do a dummy read to get a brief read cycle delay for the reset to take + * effect + */ + kgsl_regread(device, A3XX_RBBM_SW_RESET_CMD, ®); + kgsl_regwrite(device, A3XX_RBBM_SW_RESET_CMD, 0); +} -static struct adreno_perfcount_register a3xx_perfcounters_pwr[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_0_LO, 0 }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_RBBM_PERFCTR_PWR_1_LO, 0 }, -}; +/* Defined in adreno_a3xx_snapshot.c */ +void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, + int *remain, int hang); -static struct adreno_perfcount_register a3xx_perfcounters_vbif[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT0_LO }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_CNT1_LO }, -}; -static struct adreno_perfcount_register a3xx_perfcounters_vbif_pwr[] = { - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT0_LO }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT1_LO }, - { KGSL_PERFCOUNTER_NOT_USED, 0, A3XX_VBIF_PERF_PWR_CNT2_LO }, -}; +static void a3xx_postmortem_dump(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = &adreno_dev->dev; + unsigned int r1, r2, r3, rbbm_status; + unsigned int cp_stat, rb_count; + + kgsl_regread(device, REG_RBBM_STATUS, &rbbm_status); + KGSL_LOG_DUMP(device, "RBBM: STATUS = %08X\n", rbbm_status); + + { + struct log_field lines[] = { + {rbbm_status & BIT(0), "HI busy "}, + {rbbm_status & BIT(1), "CP ME busy "}, + {rbbm_status & BIT(2), "CP PFP busy "}, + {rbbm_status & BIT(14), "CP NRT busy "}, + {rbbm_status & BIT(15), "VBIF busy "}, + {rbbm_status & BIT(16), "TSE busy "}, + {rbbm_status & BIT(17), "RAS busy "}, + {rbbm_status & BIT(18), "RB busy "}, + {rbbm_status & BIT(19), "PC DCALL bsy"}, + {rbbm_status & BIT(20), "PC VSD busy "}, + {rbbm_status & BIT(21), "VFD busy "}, + {rbbm_status & BIT(22), "VPC busy "}, + {rbbm_status & BIT(23), "UCHE busy "}, + {rbbm_status & BIT(24), "SP busy "}, + {rbbm_status & BIT(25), "TPL1 busy "}, + {rbbm_status & BIT(26), "MARB busy "}, + {rbbm_status & BIT(27), "VSC busy "}, + {rbbm_status & BIT(28), "ARB busy "}, + {rbbm_status & BIT(29), "HLSQ busy "}, + {rbbm_status & BIT(30), "GPU bsy noHC"}, + {rbbm_status & BIT(31), "GPU busy "}, + }; + adreno_dump_fields(device, " STATUS=", lines, + ARRAY_SIZE(lines)); + } -static struct adreno_perfcount_group a3xx_perfcounter_groups[] = { - { a3xx_perfcounters_cp, ARRAY_SIZE(a3xx_perfcounters_cp) }, - { a3xx_perfcounters_rbbm, ARRAY_SIZE(a3xx_perfcounters_rbbm) }, - { a3xx_perfcounters_pc, ARRAY_SIZE(a3xx_perfcounters_pc) }, - { a3xx_perfcounters_vfd, ARRAY_SIZE(a3xx_perfcounters_vfd) }, - { a3xx_perfcounters_hlsq, ARRAY_SIZE(a3xx_perfcounters_hlsq) }, - { a3xx_perfcounters_vpc, ARRAY_SIZE(a3xx_perfcounters_vpc) }, - { a3xx_perfcounters_tse, ARRAY_SIZE(a3xx_perfcounters_tse) }, - { a3xx_perfcounters_ras, ARRAY_SIZE(a3xx_perfcounters_ras) }, - { a3xx_perfcounters_uche, ARRAY_SIZE(a3xx_perfcounters_uche) }, - { a3xx_perfcounters_tp, ARRAY_SIZE(a3xx_perfcounters_tp) }, - { a3xx_perfcounters_sp, ARRAY_SIZE(a3xx_perfcounters_sp) }, - { a3xx_perfcounters_rb, ARRAY_SIZE(a3xx_perfcounters_rb) }, - { a3xx_perfcounters_pwr, ARRAY_SIZE(a3xx_perfcounters_pwr) }, - { a3xx_perfcounters_vbif, ARRAY_SIZE(a3xx_perfcounters_vbif) }, - { a3xx_perfcounters_vbif_pwr, ARRAY_SIZE(a3xx_perfcounters_vbif_pwr) }, -}; + kgsl_regread(device, REG_CP_RB_BASE, &r1); + kgsl_regread(device, REG_CP_RB_CNTL, &r2); + rb_count = 2 << (r2 & (BIT(6) - 1)); + kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3); + KGSL_LOG_DUMP(device, + "CP_RB: BASE = %08X | CNTL = %08X | RPTR_ADDR = %08X" + "| rb_count = %08X\n", r1, r2, r3, rb_count); + + kgsl_regread(device, REG_CP_RB_RPTR, &r1); + kgsl_regread(device, REG_CP_RB_WPTR, &r2); + kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3); + KGSL_LOG_DUMP(device, + "CP_RB: BASE = %08X | CNTL = %08X | RPTR_ADDR = %08X" + "| rb_count = %08X\n", r1, r2, r3, rb_count); + + kgsl_regread(device, REG_CP_RB_RPTR, &r1); + kgsl_regread(device, REG_CP_RB_WPTR, &r2); + kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3); + KGSL_LOG_DUMP(device, + " RPTR = %08X | WPTR = %08X | RPTR_WR = %08X" + "\n", r1, r2, r3); + + kgsl_regread(device, REG_CP_IB1_BASE, &r1); + kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2); + KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ = %d\n", r1, r2); + + kgsl_regread(device, REG_CP_ME_CNTL, &r1); + kgsl_regread(device, REG_CP_ME_STATUS, &r2); + KGSL_LOG_DUMP(device, "CP_ME: CNTL = %08X | STATUS = %08X\n", r1, r2); + + kgsl_regread(device, REG_CP_STAT, &cp_stat); + KGSL_LOG_DUMP(device, "CP_STAT = %08X\n", cp_stat); +#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL + { + struct log_field lns[] = { + {cp_stat & BIT(0), "WR_BSY 0"}, + {cp_stat & BIT(1), "RD_RQ_BSY 1"}, + {cp_stat & BIT(2), "RD_RTN_BSY 2"}, + }; + adreno_dump_fields(device, " MIU=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(5), "RING_BUSY 5"}, + {cp_stat & BIT(6), "NDRCTS_BSY 6"}, + {cp_stat & BIT(7), "NDRCT2_BSY 7"}, + {cp_stat & BIT(9), "ST_BUSY 9"}, + {cp_stat & BIT(10), "BUSY 10"}, + }; + adreno_dump_fields(device, " CSF=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(11), "RNG_Q_BSY 11"}, + {cp_stat & BIT(12), "NDRCTS_Q_B12"}, + {cp_stat & BIT(13), "NDRCT2_Q_B13"}, + {cp_stat & BIT(16), "ST_QUEUE_B16"}, + {cp_stat & BIT(17), "PFP_BUSY 17"}, + }; + adreno_dump_fields(device, " RING=", lns, ARRAY_SIZE(lns)); + } + { + struct log_field lns[] = { + {cp_stat & BIT(3), "RBIU_BUSY 3"}, + {cp_stat & BIT(4), "RCIU_BUSY 4"}, + {cp_stat & BIT(8), "EVENT_BUSY 8"}, + {cp_stat & BIT(18), "MQ_RG_BSY 18"}, + {cp_stat & BIT(19), "MQ_NDRS_BS19"}, + {cp_stat & BIT(20), "MQ_NDR2_BS20"}, + {cp_stat & BIT(21), "MIU_WC_STL21"}, + {cp_stat & BIT(22), "CP_NRT_BSY22"}, + {cp_stat & BIT(23), "3D_BUSY 23"}, + {cp_stat & BIT(26), "ME_BUSY 26"}, + {cp_stat & BIT(27), "RB_FFO_BSY27"}, + {cp_stat & BIT(28), "CF_FFO_BSY28"}, + {cp_stat & BIT(29), "PS_FFO_BSY29"}, + {cp_stat & BIT(30), "VS_FFO_BSY30"}, + {cp_stat & BIT(31), "CP_BUSY 31"}, + }; + adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns)); + } +#endif -static struct adreno_perfcounters a3xx_perfcounters = { - a3xx_perfcounter_groups, - ARRAY_SIZE(a3xx_perfcounter_groups), + kgsl_regread(device, A3XX_RBBM_INT_0_STATUS, &r1); + KGSL_LOG_DUMP(device, "MSTR_INT_SGNL = %08X\n", r1); + { + struct log_field ints[] = { + {r1 & BIT(0), "RBBM_GPU_IDLE 0"}, + {r1 & BIT(1), "RBBM_AHB_ERROR 1"}, + {r1 & BIT(2), "RBBM_REG_TIMEOUT 2"}, + {r1 & BIT(3), "RBBM_ME_MS_TIMEOUT 3"}, + {r1 & BIT(4), "RBBM_PFP_MS_TIMEOUT 4"}, + {r1 & BIT(5), "RBBM_ATB_BUS_OVERFLOW 5"}, + {r1 & BIT(6), "VFD_ERROR 6"}, + {r1 & BIT(7), "CP_SW_INT 7"}, + {r1 & BIT(8), "CP_T0_PACKET_IN_IB 8"}, + {r1 & BIT(9), "CP_OPCODE_ERROR 9"}, + {r1 & BIT(10), "CP_RESERVED_BIT_ERROR 10"}, + {r1 & BIT(11), "CP_HW_FAULT 11"}, + {r1 & BIT(12), "CP_DMA 12"}, + {r1 & BIT(13), "CP_IB2_INT 13"}, + {r1 & BIT(14), "CP_IB1_INT 14"}, + {r1 & BIT(15), "CP_RB_INT 15"}, + {r1 & BIT(16), "CP_REG_PROTECT_FAULT 16"}, + {r1 & BIT(17), "CP_RB_DONE_TS 17"}, + {r1 & BIT(18), "CP_VS_DONE_TS 18"}, + {r1 & BIT(19), "CP_PS_DONE_TS 19"}, + {r1 & BIT(20), "CACHE_FLUSH_TS 20"}, + {r1 & BIT(21), "CP_AHB_ERROR_HALT 21"}, + {r1 & BIT(24), "MISC_HANG_DETECT 24"}, + {r1 & BIT(25), "UCHE_OOB_ACCESS 25"}, + }; + adreno_dump_fields(device, "INT_SGNL=", ints, ARRAY_SIZE(ints)); + } +} + +/* Register offset defines for A3XX */ +static unsigned int a3xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { + ADRENO_REG_DEFINE(ADRENO_REG_CP_DEBUG, REG_CP_DEBUG), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_WADDR, REG_CP_ME_RAM_WADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_DATA, REG_CP_ME_RAM_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_DATA, A3XX_CP_PFP_UCODE_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_ADDR, A3XX_CP_PFP_UCODE_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_WFI_PEND_CTR, A3XX_CP_WFI_PEND_CTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE, REG_CP_RB_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR_ADDR, REG_CP_RB_RPTR_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, REG_CP_RB_RPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, REG_CP_RB_WPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PROTECT_CTRL, A3XX_CP_PROTECT_CTRL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, REG_CP_ME_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, REG_CP_RB_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, REG_CP_IB1_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BUFSZ, REG_CP_IB1_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BASE, REG_CP_IB2_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BUFSZ, REG_CP_IB2_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_TIMESTAMP, REG_CP_TIMESTAMP), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_RADDR, REG_CP_ME_RAM_RADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_ADDR, REG_SCRATCH_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_UMSK, REG_SCRATCH_UMSK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_STATUS, A3XX_RBBM_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_CTL, A3XX_RBBM_PERFCTR_CTL), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0, + A3XX_RBBM_PERFCTR_LOAD_CMD0), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1, + A3XX_RBBM_PERFCTR_LOAD_CMD1), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_PWR_1_LO, + A3XX_RBBM_PERFCTR_PWR_1_LO), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_MASK, A3XX_RBBM_INT_0_MASK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A3XX_RBBM_INT_0_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_ERROR_STATUS, + A3XX_RBBM_AHB_ERROR_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_CMD, A3XX_RBBM_AHB_CMD), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_CLEAR_CMD, + A3XX_RBBM_INT_CLEAR_CMD), + ADRENO_REG_DEFINE(ADRENO_REG_VPC_DEBUG_RAM_SEL, + A3XX_VPC_VPC_DEBUG_RAM_SEL), + ADRENO_REG_DEFINE(ADRENO_REG_VPC_DEBUG_RAM_READ, + A3XX_VPC_VPC_DEBUG_RAM_READ), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0, + A3XX_VSC_PIPE_DATA_ADDRESS_0), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_LENGTH_7, + A3XX_VSC_PIPE_DATA_LENGTH_7), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_SIZE_ADDRESS, A3XX_VSC_SIZE_ADDRESS), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_CONTROL_0, A3XX_VFD_CONTROL_0), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_0_0, + A3XX_VFD_FETCH_INSTR_0_0), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_1_F, + A3XX_VFD_FETCH_INSTR_1_F), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_INDEX_MAX, A3XX_VFD_INDEX_MAX), + ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG, + A3XX_SP_VS_PVT_MEM_ADDR_REG), + ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG, + A3XX_SP_FS_PVT_MEM_ADDR_REG), + ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_OBJ_START_REG, + A3XX_SP_VS_OBJ_START_REG), + ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_OBJ_START_REG, + A3XX_SP_FS_OBJ_START_REG), + ADRENO_REG_DEFINE(ADRENO_REG_PA_SC_AA_CONFIG, REG_PA_SC_AA_CONFIG), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PM_OVERRIDE2, REG_RBBM_PM_OVERRIDE2), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_REG2, REG_SCRATCH_REG2), + ADRENO_REG_DEFINE(ADRENO_REG_SQ_GPR_MANAGEMENT, REG_SQ_GPR_MANAGEMENT), + ADRENO_REG_DEFINE(ADRENO_REG_SQ_INST_STORE_MANAGMENT, + REG_SQ_INST_STORE_MANAGMENT), + ADRENO_REG_DEFINE(ADRENO_REG_TC_CNTL_STATUS, REG_TC_CNTL_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_TP0_CHICKEN, REG_TP0_CHICKEN), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_RBBM_CTL, A3XX_RBBM_RBBM_CTL), }; -/* Defined in adreno_a3xx_snapshot.c */ -void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, - int *remain, int hang); +const struct adreno_reg_offsets a3xx_reg_offsets = { + .offsets = a3xx_register_offsets, + .offset_0 = ADRENO_REG_REGISTER_MAX, +}; struct adreno_gpudev adreno_a3xx_gpudev = { - .reg_rbbm_status = A3XX_RBBM_STATUS, - .reg_cp_pfp_ucode_addr = A3XX_CP_PFP_UCODE_ADDR, - .reg_cp_pfp_ucode_data = A3XX_CP_PFP_UCODE_DATA, + .reg_offsets = &a3xx_reg_offsets, .perfcounters = &a3xx_perfcounters, .ctxt_create = a3xx_drawctxt_create, - .ctxt_save = a3xx_drawctxt_save, - .ctxt_restore = a3xx_drawctxt_restore, - .ctxt_draw_workaround = NULL, .rb_init = a3xx_rb_init, .perfcounter_init = a3xx_perfcounter_init, + .perfcounter_close = a3xx_perfcounter_close, .irq_control = a3xx_irq_control, .irq_handler = a3xx_irq_handler, .irq_pending = a3xx_irq_pending, @@ -3398,4 +4389,9 @@ struct adreno_gpudev adreno_a3xx_gpudev = { .snapshot = a3xx_snapshot, .perfcounter_enable = a3xx_perfcounter_enable, .perfcounter_read = a3xx_perfcounter_read, + .coresight_enable = a3xx_coresight_enable, + .coresight_disable = a3xx_coresight_disable, + .coresight_config_debug_reg = a3xx_coresight_config_debug_reg, + .postmortem_dump = a3xx_postmortem_dump, + .soft_reset = a3xx_soft_reset, }; diff --git a/drivers/gpu/msm/adreno_a3xx.h b/drivers/gpu/msm/adreno_a3xx.h new file mode 100644 index 00000000000..fbd28e2bcdf --- /dev/null +++ b/drivers/gpu/msm/adreno_a3xx.h @@ -0,0 +1,25 @@ +/* Copyright (c) 2013, 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. + * + */ +#ifndef __A3XX_H +#define __A3XX_H + +void a3xx_err_callback(struct adreno_device *adreno_dev, int bit); +irqreturn_t a3xx_irq_handler(struct adreno_device *adreno_dev); +void a3xx_irq_control(struct adreno_device *adreno_dev, int state); +unsigned int a3xx_irq_pending(struct adreno_device *adreno_dev); +unsigned int a3xx_busy_cycles(struct adreno_device *adreno_dev); + +int a3xx_rb_init(struct adreno_device *adreno_dev, + struct adreno_ringbuffer *rb); + +#endif /*__A3XX_H */ diff --git a/drivers/gpu/msm/adreno_a3xx_snapshot.c b/drivers/gpu/msm/adreno_a3xx_snapshot.c index 34cac794447..ba0ef6a185b 100644 --- a/drivers/gpu/msm/adreno_a3xx_snapshot.c +++ b/drivers/gpu/msm/adreno_a3xx_snapshot.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, 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 @@ -11,6 +11,7 @@ * */ +#include #include "kgsl.h" #include "adreno.h" #include "kgsl_snapshot.h" @@ -19,6 +20,7 @@ #define DEBUG_SECTION_SZ(_dwords) (((_dwords) * sizeof(unsigned int)) \ + sizeof(struct kgsl_snapshot_debug)) +/* Shader memory size in words */ #define SHADER_MEMORY_SIZE 0x4000 /** @@ -33,16 +35,28 @@ static void _rbbm_debug_bus_read(struct kgsl_device *device, unsigned int block_id, unsigned int index, unsigned int *val) { unsigned int block = (block_id << 8) | 1 << 16; - adreno_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index); - adreno_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val); + kgsl_regwrite(device, A3XX_RBBM_DEBUG_BUS_CTL, block | index); + kgsl_regread(device, A3XX_RBBM_DEBUG_BUS_DATA_STATUS, val); } +/** + * a3xx_snapshot_shader_memory - Helper function to dump the GPU shader + * memory to the snapshot buffer. + * @device - GPU device whose shader memory is to be dumped + * @snapshot - Pointer to binary snapshot data blob being made + * @remain - Number of remaining bytes in the snapshot blob + * @priv - Unused parameter + */ static int a3xx_snapshot_shader_memory(struct kgsl_device *device, void *snapshot, int remain, void *priv) { struct kgsl_snapshot_debug *header = snapshot; + unsigned int i; unsigned int *data = snapshot + sizeof(*header); - int i; + unsigned int shader_read_len = SHADER_MEMORY_SIZE; + + if (SHADER_MEMORY_SIZE > (device->shader_mem_len >> 2)) + shader_read_len = (device->shader_mem_len >> 2); if (remain < DEBUG_SECTION_SZ(SHADER_MEMORY_SIZE)) { SNAPSHOT_ERR_NOMEM(device, "SHADER MEMORY"); @@ -52,8 +66,22 @@ static int a3xx_snapshot_shader_memory(struct kgsl_device *device, header->type = SNAPSHOT_DEBUG_SHADER_MEMORY; header->size = SHADER_MEMORY_SIZE; - for (i = 0; i < SHADER_MEMORY_SIZE; i++) - adreno_regread(device, 0x4000 + i, &data[i]); + /* Map shader memory to kernel, for dumping */ + if (device->shader_mem_virt == NULL) + device->shader_mem_virt = devm_ioremap(device->dev, + device->shader_mem_phys, + device->shader_mem_len); + + if (device->shader_mem_virt == NULL) { + KGSL_DRV_ERR(device, + "Unable to map shader memory region\n"); + return 0; + } + + /* Now, dump shader memory to snapshot */ + for (i = 0; i < shader_read_len; i++) + adreno_shadermem_regread(device, i, &data[i]); + return DEBUG_SECTION_SZ(SHADER_MEMORY_SIZE); } @@ -80,9 +108,9 @@ static int a3xx_snapshot_vpc_memory(struct kgsl_device *device, void *snapshot, for (bank = 0; bank < VPC_MEMORY_BANKS; bank++) { for (addr = 0; addr < VPC_MEMORY_SIZE; addr++) { unsigned int val = bank | (addr << 4); - adreno_regwrite(device, + kgsl_regwrite(device, A3XX_VPC_VPC_DEBUG_RAM_SEL, val); - adreno_regread(device, + kgsl_regread(device, A3XX_VPC_VPC_DEBUG_RAM_READ, &data[i++]); } } @@ -106,9 +134,9 @@ static int a3xx_snapshot_cp_meq(struct kgsl_device *device, void *snapshot, header->type = SNAPSHOT_DEBUG_CP_MEQ; header->size = CP_MEQ_SIZE; - adreno_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0); + kgsl_regwrite(device, A3XX_CP_MEQ_ADDR, 0x0); for (i = 0; i < CP_MEQ_SIZE; i++) - adreno_regread(device, A3XX_CP_MEQ_DATA, &data[i]); + kgsl_regread(device, A3XX_CP_MEQ_DATA, &data[i]); return DEBUG_SECTION_SZ(CP_MEQ_SIZE); } @@ -136,9 +164,9 @@ static int a3xx_snapshot_cp_pm4_ram(struct kgsl_device *device, void *snapshot, * maintain always changing hardcoded constants */ - adreno_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0); + kgsl_regwrite(device, REG_CP_ME_RAM_RADDR, 0x0); for (i = 0; i < size; i++) - adreno_regread(device, REG_CP_ME_RAM_DATA, &data[i]); + kgsl_regread(device, REG_CP_ME_RAM_DATA, &data[i]); return DEBUG_SECTION_SZ(size); } @@ -167,7 +195,7 @@ static int a3xx_snapshot_cp_pfp_ram(struct kgsl_device *device, void *snapshot, */ kgsl_regwrite(device, A3XX_CP_PFP_UCODE_ADDR, 0x0); for (i = 0; i < size; i++) - adreno_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]); + kgsl_regread(device, A3XX_CP_PFP_UCODE_DATA, &data[i]); return DEBUG_SECTION_SZ(size); } @@ -186,7 +214,8 @@ static int a3xx_snapshot_cp_roq(struct kgsl_device *device, void *snapshot, int i, size; /* The size of the ROQ buffer is core dependent */ - size = adreno_is_a330(adreno_dev) ? + size = (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) ? A330_CP_ROQ_SIZE : A320_CP_ROQ_SIZE; if (remain < DEBUG_SECTION_SZ(size)) { @@ -197,9 +226,9 @@ static int a3xx_snapshot_cp_roq(struct kgsl_device *device, void *snapshot, header->type = SNAPSHOT_DEBUG_CP_ROQ; header->size = size; - adreno_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0); + kgsl_regwrite(device, A3XX_CP_ROQ_ADDR, 0x0); for (i = 0; i < size; i++) - adreno_regread(device, A3XX_CP_ROQ_DATA, &data[i]); + kgsl_regread(device, A3XX_CP_ROQ_DATA, &data[i]); return DEBUG_SECTION_SZ(size); } @@ -224,75 +253,92 @@ static int a330_snapshot_cp_merciu(struct kgsl_device *device, void *snapshot, header->type = SNAPSHOT_DEBUG_CP_MERCIU; header->size = size; - adreno_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0); + kgsl_regwrite(device, A3XX_CP_MERCIU_ADDR, 0x0); for (i = 0; i < A330_CP_MERCIU_QUEUE_SIZE; i++) { - adreno_regread(device, A3XX_CP_MERCIU_DATA, + kgsl_regread(device, A3XX_CP_MERCIU_DATA, &data[(i * 2)]); - adreno_regread(device, A3XX_CP_MERCIU_DATA2, + kgsl_regread(device, A3XX_CP_MERCIU_DATA2, &data[(i * 2) + 1]); } return DEBUG_SECTION_SZ(size); } -#define DEBUGFS_BLOCK_SIZE 0x40 +struct debugbus_block { + unsigned int block_id; + unsigned int dwords; +}; static int a3xx_snapshot_debugbus_block(struct kgsl_device *device, void *snapshot, int remain, void *priv) { + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct kgsl_snapshot_debugbus *header = snapshot; - unsigned int id = (unsigned int) priv; + struct debugbus_block *block = priv; unsigned int val; int i; unsigned int *data = snapshot + sizeof(*header); - int size = - (DEBUGFS_BLOCK_SIZE * sizeof(unsigned int)) + sizeof(*header); + unsigned int dwords; + int size; + + /* + * For A305 and A320 all debug bus regions are the same size (0x40). For + * A330, they can be different sizes - most are still 0x40, but some + * like CP are larger + */ + + dwords = (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) ? + block->dwords : 0x40; + + size = (dwords * sizeof(unsigned int)) + sizeof(*header); if (remain < size) { SNAPSHOT_ERR_NOMEM(device, "DEBUGBUS"); return 0; } - val = (id << 8) | (1 << 16); + val = (block->block_id << 8) | (1 << 16); - header->id = id; - header->count = DEBUGFS_BLOCK_SIZE; + header->id = block->block_id; + header->count = dwords; - for (i = 0; i < DEBUGFS_BLOCK_SIZE; i++) - _rbbm_debug_bus_read(device, id, i, &data[i]); + for (i = 0; i < dwords; i++) + _rbbm_debug_bus_read(device, block->block_id, i, &data[i]); return size; } -static unsigned int debugbus_blocks[] = { - RBBM_BLOCK_ID_CP, - RBBM_BLOCK_ID_RBBM, - RBBM_BLOCK_ID_VBIF, - RBBM_BLOCK_ID_HLSQ, - RBBM_BLOCK_ID_UCHE, - RBBM_BLOCK_ID_PC, - RBBM_BLOCK_ID_VFD, - RBBM_BLOCK_ID_VPC, - RBBM_BLOCK_ID_TSE, - RBBM_BLOCK_ID_RAS, - RBBM_BLOCK_ID_VSC, - RBBM_BLOCK_ID_SP_0, - RBBM_BLOCK_ID_SP_1, - RBBM_BLOCK_ID_SP_2, - RBBM_BLOCK_ID_SP_3, - RBBM_BLOCK_ID_TPL1_0, - RBBM_BLOCK_ID_TPL1_1, - RBBM_BLOCK_ID_TPL1_2, - RBBM_BLOCK_ID_TPL1_3, - RBBM_BLOCK_ID_RB_0, - RBBM_BLOCK_ID_RB_1, - RBBM_BLOCK_ID_RB_2, - RBBM_BLOCK_ID_RB_3, - RBBM_BLOCK_ID_MARB_0, - RBBM_BLOCK_ID_MARB_1, - RBBM_BLOCK_ID_MARB_2, - RBBM_BLOCK_ID_MARB_3, +static struct debugbus_block debugbus_blocks[] = { + { RBBM_BLOCK_ID_CP, 0x52, }, + { RBBM_BLOCK_ID_RBBM, 0x40, }, + { RBBM_BLOCK_ID_VBIF, 0x40, }, + { RBBM_BLOCK_ID_HLSQ, 0x40, }, + { RBBM_BLOCK_ID_UCHE, 0x40, }, + { RBBM_BLOCK_ID_PC, 0x40, }, + { RBBM_BLOCK_ID_VFD, 0x40, }, + { RBBM_BLOCK_ID_VPC, 0x40, }, + { RBBM_BLOCK_ID_TSE, 0x40, }, + { RBBM_BLOCK_ID_RAS, 0x40, }, + { RBBM_BLOCK_ID_VSC, 0x40, }, + { RBBM_BLOCK_ID_SP_0, 0x40, }, + { RBBM_BLOCK_ID_SP_1, 0x40, }, + { RBBM_BLOCK_ID_SP_2, 0x40, }, + { RBBM_BLOCK_ID_SP_3, 0x40, }, + { RBBM_BLOCK_ID_TPL1_0, 0x40, }, + { RBBM_BLOCK_ID_TPL1_1, 0x40, }, + { RBBM_BLOCK_ID_TPL1_2, 0x40, }, + { RBBM_BLOCK_ID_TPL1_3, 0x40, }, + { RBBM_BLOCK_ID_RB_0, 0x40, }, + { RBBM_BLOCK_ID_RB_1, 0x40, }, + { RBBM_BLOCK_ID_RB_2, 0x40, }, + { RBBM_BLOCK_ID_RB_3, 0x40, }, + { RBBM_BLOCK_ID_MARB_0, 0x40, }, + { RBBM_BLOCK_ID_MARB_1, 0x40, }, + { RBBM_BLOCK_ID_MARB_2, 0x40, }, + { RBBM_BLOCK_ID_MARB_3, 0x40, }, }; static void *a3xx_snapshot_debugbus(struct kgsl_device *device, @@ -304,7 +350,7 @@ static void *a3xx_snapshot_debugbus(struct kgsl_device *device, snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUGBUS, snapshot, remain, a3xx_snapshot_debugbus_block, - (void *) debugbus_blocks[i]); + (void *) &debugbus_blocks[i]); } return snapshot; @@ -395,17 +441,18 @@ void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, struct kgsl_device *device = &adreno_dev->dev; struct kgsl_snapshot_registers_list list; struct kgsl_snapshot_registers regs[5]; + int size; list.registers = regs; list.count = 0; /* Disable Clock gating temporarily for the debug bus to work */ - adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL, 0x00); + kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL, 0x00); /* Store relevant registers in list to snapshot */ _snapshot_a3xx_regs(regs, &list); _snapshot_hlsq_regs(regs, &list, adreno_dev); - if (adreno_is_a330(adreno_dev)) + if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev)) _snapshot_a330_regs(regs, &list); /* Master set of (non debug) registers */ @@ -413,10 +460,15 @@ void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, KGSL_SNAPSHOT_SECTION_REGS, snapshot, remain, kgsl_snapshot_dump_regs, &list); - /* CP_STATE_DEBUG indexed registers */ + /* + * CP_STATE_DEBUG indexed registers - 20 on 305 and 320 and 46 on A330 + */ + size = (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) ? 0x2E : 0x14; + snapshot = kgsl_snapshot_indexed_registers(device, snapshot, remain, REG_CP_STATE_DEBUG_INDEX, - REG_CP_STATE_DEBUG_DATA, 0x0, 0x14); + REG_CP_STATE_DEBUG_DATA, 0x0, size); /* CP_ME indexed registers */ snapshot = kgsl_snapshot_indexed_registers(device, snapshot, @@ -457,7 +509,8 @@ void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain, a3xx_snapshot_cp_roq, NULL); - if (adreno_is_a330(adreno_dev)) { + if (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) { snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_DEBUG, snapshot, remain, a330_snapshot_cp_merciu, NULL); @@ -466,7 +519,7 @@ void *a3xx_snapshot(struct adreno_device *adreno_dev, void *snapshot, snapshot = a3xx_snapshot_debugbus(device, snapshot, remain); /* Enable Clock gating */ - adreno_regwrite(device, A3XX_RBBM_CLOCK_CTL, + kgsl_regwrite(device, A3XX_RBBM_CLOCK_CTL, adreno_a3xx_rbbm_clock_ctl_default(adreno_dev)); return snapshot; diff --git a/drivers/gpu/msm/adreno_a4xx.c b/drivers/gpu/msm/adreno_a4xx.c new file mode 100644 index 00000000000..9f8b75837eb --- /dev/null +++ b/drivers/gpu/msm/adreno_a4xx.c @@ -0,0 +1,239 @@ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "adreno.h" +#include "a4xx_reg.h" +#include "adreno_a3xx.h" + +/* + * Set of registers to dump for A4XX on postmortem and snapshot. + * Registers in pairs - first value is the start offset, second + * is the stop offset (inclusive) + */ + +const unsigned int a4xx_registers[] = { + 0x0000, 0x0002, /* RBBM_HW_VERSION - RBBM_HW_CONFIGURATION */ + 0x0020, 0x0020, /* RBBM_CLOCK_CTL */ + 0x0021, 0x0021, /* RBBM_SP_HYST_CNT */ + 0x0023, 0x0024, /* RBBM_AHB_CTL0 - RBBM_AHB_CTL1 */ + 0x0026, 0x0026, /* RBBM_RB_SUB_BLOCK_SEL_CTL */ + 0x0028, 0x0034, /* RBBM_RAM_ACC_63_32 - RBBM_INTERFACE_HANG_MASK_CTL4 */ + 0x0037, 0x003f, /* RBBM_INT_0_MASK - RBBM_AHB_DEBUG_CTL */ + 0x0041, 0x0045, /* RBBM_VBIF_DEBUG_CTL - BLOCK_SW_RESET_CMD */ + 0x0047, 0x0049, /* RBBM_RESET_CYCLES - RBBM_EXT_TRACE_BUS_CTL */ + 0x009c, 0x0170, /* RBBM_PERFCTR_CP_0_LO - RBBM_PERFCTR_CTL */ + 0x0174, 0x0182, /* RBBM_PERFCTR_LOAD_VALUE_LO - RBBM_CLOCK_STATUS */ + 0x0189, 0x019f, /* RBBM_AHB_STATUS - RBBM_INTERFACE_RRDY_STATUS5 */ + + 0x0206, 0x0217, /* CP_IB1_BASE - CP_ME_RB_DONE_DATA */ + 0x0219, 0x0219, /* CP_QUEUE_THRESH2 */ + 0x021b, 0x021b, /* CP_MERCIU_SIZE */ + 0x0228, 0x0229, /* CP_SCRATCH_UMASK - CP_SCRATCH_ADDR */ + 0x022a, 0x022c, /* CP_PREEMPT - CP_CNTL */ + 0x022e, 0x022e, /* CP_DEBUG */ + 0x0231, 0x0232, /* CP_DEBUG_ECO_CONTROL - CP_DRAW_STATE_ADDR */ + 0x0240, 0x0250, /* CP_PROTECT_REG_0 - CP_PROTECT_CTRL */ + 0x04c0, 0x04ce, /* CP_ST_BASE - CP_STQ_AVAIL */ + 0x04d0, 0x04d0, /* CP_MERCIU_STAT */ + 0x04d2, 0x04dd, /* CP_WFI_PEND_CTR - CP_EVENTS_IN_FLIGHT */ + 0x0500, 0x050b, /* CP_PERFCTR_CP_SEL_0 - CP_PERFCOMBINER_SELECT */ + 0x0578, 0x058f, /* CP_SCRATCH_REG0 - CP_SCRATCH_REG23 */ + + 0x0c00, 0x0c03, /* VSC_BIN_SIZE - VSC_DEBUG_ECO_CONTROL */ + 0x0c08, 0x0c41, /* VSC_PIPE_CONFIG_0 - VSC_PIPE_PARTIAL_POSN_1 */ + 0x0c50, 0x0c51, /* VSC_PERFCTR_VSC_SEL_0 - VSC_PERFCTR_VSC_SEL_1 */ + + 0x0e64, 0x0e68, /* VPC_DEBUG_ECO_CONTROL - VPC_PERFCTR_VPC_SEL_3 */ + 0x2140, 0x216e, /* VPC_ATTR - VPC_SO_FLUSH_WADDR_3 - ctx0 */ + 0x2540, 0x256e, /* VPC_ATTR - VPC_SO_FLUSH_WADDR_3 - ctx1 */ + + 0x0f00, 0x0f0b, /* TPL1_DEBUG_ECO_CONTROL - TPL1_PERFCTR_TP_SEL_7 */ + /* TPL1_TP_TEX_OFFSET - TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR - ctx0 */ + 0x2380, 0x23a6, + /* TPL1_TP_TEX_OFFSET - TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR - ctx1 */ + 0x2780, 0x27a6, + + 0x0ec0, 0x0ecf, /* SP_VS_STATUS - SP_PERFCTR_SP_SEL_11 */ + 0x22c0, 0x22c1, /* SP_SP_CTRL - SP_INSTR_CACHE_CTRL - ctx0 */ + 0x22c4, 0x2360, /* SP_VS_CTRL_0 - SP_GS_LENGTH - ctx0 */ + 0x26c0, 0x26c1, /* SP_SP_CTRL - SP_INSTR_CACHE_CTRL - ctx1 */ + 0x26c4, 0x2760, /* SP_VS_CTRL_0 - SP_GS_LENGTH - ctx1 */ + + 0x0cc0, 0x0cd2, /* RB_GMEM_BASE_ADDR - RB_PERFCTR_CCU_SEL_3 */ + 0x20a0, 0x213f, /* RB_MODE_CONTROL - RB_VPORT_Z_CLAMP_MAX_15 - ctx0 */ + 0x24a0, 0x253f, /* RB_MODE_CONTROL - RB_VPORT_Z_CLAMP_MAX_15 - ctx1 */ + + 0x0e40, 0x0e4a, /* VFD_DEBUG_CONTROL - VFD_PERFCTR_VFD_SEL_7 */ + 0x2200, 0x2204, /* VFD_CONTROL_0 - VFD_CONTROL_4 - ctx 0 */ + 0x2208, 0x22a9, /* VFD_INDEX_OFFSET - VFD_DECODE_INSTR_31 - ctx 0 */ + 0x2600, 0x2604, /* VFD_CONTROL_0 - VFD_CONTROL_4 - ctx 1 */ + 0x2608, 0x26a9, /* VFD_INDEX_OFFSET - VFD_DECODE_INSTR_31 - ctx 1 */ + + 0x0c80, 0x0c81, /* GRAS_TSE_STATUS - GRAS_DEBUG_ECO_CONTROL */ + 0x0c88, 0x0c8b, /* GRAS_PERFCTR_TSE_SEL_0 - GRAS_PERFCTR_TSE_SEL_3 */ + 0x2000, 0x2004, /* GRAS_CL_CLIP_CNTL - GRAS_CL_GB_CLIP_ADJ - ctx 0 */ + /* GRAS_CL_VPORT_XOFFSET_0 - GRAS_SC_EXTENT_WINDOW_TL - ctx 0 */ + 0x2008, 0x209f, + 0x2400, 0x2404, /* GRAS_CL_CLIP_CNTL - GRAS_CL_GB_CLIP_ADJ - ctx 1 */ + /* GRAS_CL_VPORT_XOFFSET_0 - GRAS_SC_EXTENT_WINDOW_TL - ctx 1 */ + 0x2408, 0x249f, + + 0x0e80, 0x0e84, /* UCHE_CACHE_MODE_CONTROL - UCHE_TRAP_BASE_HI */ + 0x0e88, 0x0e95, /* UCHE_CACHE_STATUS - UCHE_PERFCTR_UCHE_SEL_7 */ + + 0x0e00, 0x0e00, /* HLSQ_TIMEOUT_THRESHOLD - HLSQ_TIMEOUT_THRESHOLD */ + 0x0e04, 0x0e0e, /* HLSQ_DEBUG_ECO_CONTROL - HLSQ_PERF_PIPE_MASK */ + 0x23c0, 0x23db, /* HLSQ_CONTROL_0 - HLSQ_UPDATE_CONTROL - ctx 0 */ + 0x27c0, 0x27db, /* HLSQ_CONTROL_0 - HLSQ_UPDATE_CONTROL - ctx 1 */ + + 0x0d00, 0x0d0c, /* PC_BINNING_COMMAND - PC_DRAWCALL_SETUP_OVERRIDE */ + 0x0d10, 0x0d17, /* PC_PERFCTR_PC_SEL_0 - PC_PERFCTR_PC_SEL_7 */ + 0x21c0, 0x21c6, /* PC_BIN_BASE - PC_RESTART_INDEX - ctx 0 */ + 0x21e5, 0x21e7, /* PC_GS_PARAM - PC_HS_PARAM - ctx 0 */ + 0x25c0, 0x25c6, /* PC_BIN_BASE - PC_RESTART_INDEX - ctx 1 */ + 0x25e5, 0x25e7, /* PC_GS_PARAM - PC_HS_PARAM - ctx 1 */ +}; + +const unsigned int a4xx_registers_count = ARRAY_SIZE(a4xx_registers) / 2; + +static const struct adreno_vbif_data a420_vbif[] = { + { A4XX_VBIF_ABIT_SORT, 0x0001001F }, + { A4XX_VBIF_ABIT_SORT_CONF, 0x000000A4 }, + { A4XX_VBIF_GATE_OFF_WRREQ_EN, 0x00000001 }, + { A4XX_VBIF_IN_RD_LIM_CONF0, 0x18181818 }, + { A4XX_VBIF_IN_RD_LIM_CONF1, 0x00000018 }, + { A4XX_VBIF_IN_WR_LIM_CONF0, 0x18181818 }, + { A4XX_VBIF_IN_WR_LIM_CONF1, 0x00000018 }, + { A4XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000003 }, + {0, 0}, +}; + +const struct adreno_vbif_platform a4xx_vbif_platforms[] = { + { adreno_is_a420, a420_vbif }, +}; + +static void a4xx_start(struct adreno_device *adreno_dev) +{ + struct kgsl_device *device = &adreno_dev->dev; + + adreno_vbif_start(device, a4xx_vbif_platforms, + ARRAY_SIZE(a4xx_vbif_platforms)); + /* Make all blocks contribute to the GPU BUSY perf counter */ + kgsl_regwrite(device, A4XX_RBBM_GPU_BUSY_MASKED, 0xFFFFFFFF); + + /* Tune the hystersis counters for SP and CP idle detection */ + kgsl_regwrite(device, A4XX_RBBM_SP_HYST_CNT, 0x10); + kgsl_regwrite(device, A4XX_RBBM_WAIT_IDLE_CLOCKS_CTL, 0x10); + + /* + * Enable the RBBM error reporting bits. This lets us get + * useful information on failure + */ + + kgsl_regwrite(device, A4XX_RBBM_AHB_CTL0, 0x00000001); + + /* Enable AHB error reporting */ + kgsl_regwrite(device, A4XX_RBBM_AHB_CTL1, 0xA6FFFFFF); + + /* + * Turn on hang detection - this spews a lot of useful information + * into the RBBM registers on a hang + */ + + kgsl_regwrite(device, A4XX_RBBM_INTERFACE_HANG_INT_CTL, + (1 << 16) | 0xFFF); + + /* Set the OCMEM base address for A4XX */ + kgsl_regwrite(device, A4XX_RB_GMEM_BASE_ADDR, + (unsigned int)(adreno_dev->ocmem_base >> 14)); +} + +/* Register offset defines for A4XX, in order of enum adreno_regs */ +static unsigned int a4xx_register_offsets[ADRENO_REG_REGISTER_MAX] = { + ADRENO_REG_DEFINE(ADRENO_REG_CP_DEBUG, A4XX_CP_DEBUG), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_WADDR, A4XX_CP_ME_RAM_WADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_DATA, A4XX_CP_ME_RAM_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_DATA, A4XX_CP_PFP_UCODE_DATA), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PFP_UCODE_ADDR, A4XX_CP_PFP_UCODE_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_WFI_PEND_CTR, A4XX_CP_WFI_PEND_CTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_BASE, A4XX_CP_RB_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR_ADDR, A4XX_CP_RB_RPTR_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_RPTR, A4XX_CP_RB_RPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_WPTR, A4XX_CP_RB_WPTR), + ADRENO_REG_DEFINE(ADRENO_REG_CP_PROTECT_CTRL, A4XX_CP_PROTECT_CTRL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_CNTL, A4XX_CP_ME_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_RB_CNTL, A4XX_CP_RB_CNTL), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BASE, A4XX_CP_IB1_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB1_BUFSZ, A4XX_CP_IB1_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BASE, A4XX_CP_IB2_BASE), + ADRENO_REG_DEFINE(ADRENO_REG_CP_IB2_BUFSZ, A4XX_CP_IB2_BUFSZ), + ADRENO_REG_DEFINE(ADRENO_REG_CP_TIMESTAMP, A4XX_CP_SCRATCH_REG0), + ADRENO_REG_DEFINE(ADRENO_REG_CP_ME_RAM_RADDR, A4XX_CP_ME_RAM_RADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_ADDR, A4XX_CP_SCRATCH_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SCRATCH_UMSK, A4XX_CP_SCRATCH_UMASK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_STATUS, A4XX_RBBM_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_CTL, A4XX_RBBM_PERFCTR_CTL), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD0, + A4XX_RBBM_PERFCTR_LOAD_CMD0), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD1, + A4XX_RBBM_PERFCTR_LOAD_CMD1), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_LOAD_CMD2, + A4XX_RBBM_PERFCTR_LOAD_CMD2), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_PERFCTR_PWR_1_LO, + A4XX_RBBM_PERFCTR_PWR_1_LO), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_MASK, A4XX_RBBM_INT_0_MASK), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_0_STATUS, A4XX_RBBM_INT_0_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_ERROR_STATUS, + A4XX_RBBM_AHB_ERROR_STATUS), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_AHB_CMD, A4XX_RBBM_AHB_CMD), + ADRENO_REG_DEFINE(ADRENO_REG_VPC_DEBUG_RAM_SEL, + A4XX_VPC_DEBUG_RAM_SEL), + ADRENO_REG_DEFINE(ADRENO_REG_VPC_DEBUG_RAM_READ, + A4XX_VPC_DEBUG_RAM_READ), + ADRENO_REG_DEFINE(ADRENO_REG_RBBM_INT_CLEAR_CMD, + A4XX_RBBM_INT_CLEAR_CMD), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0, + A4XX_VSC_PIPE_DATA_ADDRESS_0), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_PIPE_DATA_LENGTH_7, + A4XX_VSC_PIPE_DATA_LENGTH_7), + ADRENO_REG_DEFINE(ADRENO_REG_VSC_SIZE_ADDRESS, A4XX_VSC_SIZE_ADDRESS), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_CONTROL_0, A4XX_VFD_CONTROL_0), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_0_0, + A4XX_VFD_FETCH_INSTR_0_0), + ADRENO_REG_DEFINE(ADRENO_REG_VFD_FETCH_INSTR_1_F, + A4XX_VFD_FETCH_INSTR_1_31), + ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG, + A4XX_SP_VS_PVT_MEM_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG, + A4XX_SP_FS_PVT_MEM_ADDR), + ADRENO_REG_DEFINE(ADRENO_REG_SP_VS_OBJ_START_REG, + A4XX_SP_VS_OBJ_START), + ADRENO_REG_DEFINE(ADRENO_REG_SP_FS_OBJ_START_REG, + A4XX_SP_FS_OBJ_START), +}; + +const struct adreno_reg_offsets a4xx_reg_offsets = { + .offsets = a4xx_register_offsets, + .offset_0 = ADRENO_REG_REGISTER_MAX, +}; + +struct adreno_gpudev adreno_a4xx_gpudev = { + .reg_offsets = &a4xx_reg_offsets, + + .rb_init = a3xx_rb_init, + .irq_control = a3xx_irq_control, + .irq_handler = a3xx_irq_handler, + .irq_pending = a3xx_irq_pending, + .busy_cycles = a3xx_busy_cycles, + .start = a4xx_start, +}; diff --git a/drivers/gpu/msm/adreno_coresight.c b/drivers/gpu/msm/adreno_coresight.c new file mode 100644 index 00000000000..1b827ffccd3 --- /dev/null +++ b/drivers/gpu/msm/adreno_coresight.c @@ -0,0 +1,219 @@ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kgsl.h" +#include "kgsl_device.h" +#include "adreno.h" + +struct coresight_attr { + struct device_attribute attr; + int regname; +}; + +#define CORESIGHT_CREATE_REG_ATTR(_attrname, _regname) \ + struct coresight_attr coresight_attr_##_attrname = \ + { __ATTR(_attrname, S_IRUGO | S_IWUSR, gfx_show_reg, gfx_store_reg),\ + _regname} + +/** + * adreno_coresight_enable() - Generic function to enable coresight debugging + * @csdev: Pointer to coresight's device struct + * + * This is a generic function to enable coresight debug bus on adreno + * devices. This should be used in all cases of enabling + * coresight debug bus for adreno devices. This function in turn calls + * the adreno device specific function through gpudev hook. + * This function is registered as the coresight enable function + * with coresight driver. It should only be called through coresight driver + * as that would ensure that the necessary setup required to be done + * on coresight driver's part is also done. + */ +int adreno_coresight_enable(struct coresight_device *csdev) +{ + struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent); + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + /* Check if coresight compatible device, return error otherwise */ + if (adreno_dev->gpudev->coresight_enable) + return adreno_dev->gpudev->coresight_enable(device); + else + return -ENODEV; +} + +/** + * adreno_coresight_disable() - Generic function to disable coresight debugging + * @csdev: Pointer to coresight's device struct + * + * This is a generic function to disable coresight debug bus on adreno + * devices. This should be used in all cases of disabling + * coresight debug bus for adreno devices. This function in turn calls + * the adreno device specific function through the gpudev hook. + * This function is registered as the coresight disable function + * with coresight driver. It should only be called through coresight driver + * as that would ensure that the necessary setup required to be done on + * coresight driver's part is also done. + */ +void adreno_coresight_disable(struct coresight_device *csdev) +{ + struct kgsl_device *device = dev_get_drvdata(csdev->dev.parent); + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + /* Check if coresight compatible device, bail otherwise */ + if (adreno_dev->gpudev->coresight_disable) + return adreno_dev->gpudev->coresight_disable(device); +} + +static const struct coresight_ops_source adreno_coresight_ops_source = { + .enable = adreno_coresight_enable, + .disable = adreno_coresight_disable, +}; + +static const struct coresight_ops adreno_coresight_cs_ops = { + .source_ops = &adreno_coresight_ops_source, +}; + +void adreno_coresight_remove(struct platform_device *pdev) +{ + struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; + coresight_unregister(pdata->csdev); +} + +static ssize_t coresight_read_reg(struct kgsl_device *device, + unsigned int offset, char *buf) +{ + unsigned int regval = 0; + + mutex_lock(&device->mutex); + if (!kgsl_active_count_get(device)) { + kgsl_regread(device, offset, ®val); + kgsl_active_count_put(device); + } + mutex_unlock(&device->mutex); + return snprintf(buf, PAGE_SIZE, "0x%X", regval); +} + +static inline unsigned int coresight_convert_reg(const char *buf) +{ + long regval = 0; + int rv = 0; + + rv = kstrtoul(buf, 16, ®val); + if (!rv) + return (unsigned int)regval; + else + return rv; +} + +static ssize_t gfx_show_reg(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct kgsl_device *device = dev_get_drvdata(dev->parent); + struct coresight_attr *csight_attr = container_of(attr, + struct coresight_attr, attr); + return coresight_read_reg(device, csight_attr->regname, buf); +} + +static ssize_t gfx_store_reg(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t size) +{ + struct kgsl_device *device = dev_get_drvdata(dev->parent); + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + struct coresight_attr *csight_attr = container_of(attr, + struct coresight_attr, attr); + unsigned int regval = 0; + + regval = coresight_convert_reg(buf); + + if (adreno_dev->gpudev->coresight_config_debug_reg) + adreno_dev->gpudev->coresight_config_debug_reg(device, + csight_attr->regname, regval); + return size; +} + +CORESIGHT_CREATE_REG_ATTR(config_debug_bus, DEBUG_BUS_CTL); +CORESIGHT_CREATE_REG_ATTR(config_trace_stop_cnt, TRACE_STOP_CNT); +CORESIGHT_CREATE_REG_ATTR(config_trace_start_cnt, TRACE_START_CNT); +CORESIGHT_CREATE_REG_ATTR(config_trace_period_cnt, TRACE_PERIOD_CNT); +CORESIGHT_CREATE_REG_ATTR(config_trace_cmd, TRACE_CMD); +CORESIGHT_CREATE_REG_ATTR(config_trace_bus_ctl, TRACE_BUS_CTL); + +static struct attribute *gfx_attrs[] = { + &coresight_attr_config_debug_bus.attr.attr, + &coresight_attr_config_trace_start_cnt.attr.attr, + &coresight_attr_config_trace_stop_cnt.attr.attr, + &coresight_attr_config_trace_period_cnt.attr.attr, + &coresight_attr_config_trace_cmd.attr.attr, + &coresight_attr_config_trace_bus_ctl.attr.attr, + NULL, +}; + +static struct attribute_group gfx_attr_grp = { + .attrs = gfx_attrs, +}; + +static const struct attribute_group *gfx_attr_grps[] = { + &gfx_attr_grp, + NULL, +}; + +int adreno_coresight_init(struct platform_device *pdev) +{ + int ret = 0; + struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; + struct device *dev = &pdev->dev; + struct coresight_desc *desc; + + if (IS_ERR_OR_NULL(pdata->coresight_pdata)) + return -ENODATA; + + + desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL); + if (!desc) + return -ENOMEM; + + + desc->type = CORESIGHT_DEV_TYPE_SOURCE; + desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_BUS; + desc->ops = &adreno_coresight_cs_ops; + desc->pdata = pdata->coresight_pdata; + desc->dev = &pdev->dev; + desc->owner = THIS_MODULE; + desc->groups = gfx_attr_grps; + pdata->csdev = coresight_register(desc); + if (IS_ERR(pdata->csdev)) { + ret = PTR_ERR(pdata->csdev); + goto err; + } + + return 0; + +err: + devm_kfree(dev, desc); + return ret; +} + diff --git a/drivers/gpu/msm/adreno_cp_parser.c b/drivers/gpu/msm/adreno_cp_parser.c new file mode 100644 index 00000000000..944c50f263a --- /dev/null +++ b/drivers/gpu/msm/adreno_cp_parser.c @@ -0,0 +1,823 @@ +/* Copyright (c) 2013, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "kgsl.h" +#include "kgsl_sharedmem.h" +#include "kgsl_snapshot.h" + +#include "adreno.h" +#include "adreno_pm4types.h" +#include "a2xx_reg.h" +#include "a3xx_reg.h" +#include "adreno_cp_parser.h" + +#define MAX_IB_OBJS 1000 + +/* + * This structure keeps track of type0 writes to VSC_PIPE_DATA_ADDRESS_x and + * VSC_PIPE_DATA_LENGTH_x. When a draw initator is called these registers + * point to buffers that we need to freeze for a snapshot + */ + +struct ib_vsc_pipe { + unsigned int base; + unsigned int size; +}; + +/* + * This struct keeps track of type0 writes to VFD_FETCH_INSTR_0_X and + * VFD_FETCH_INSTR_1_X registers. When a draw initator is called the addresses + * and sizes in these registers point to VBOs that we need to freeze for a + * snapshot + */ + +struct ib_vbo { + unsigned int base; + unsigned int stride; +}; + +/* List of variables used when parsing an IB */ +struct ib_parser_variables { + struct ib_vsc_pipe vsc_pipe[8]; + /* + * This is the cached value of type0 writes to the VSC_SIZE_ADDRESS + * which contains the buffer address of the visiblity stream size + * buffer during a binning pass + */ + unsigned int vsc_size_address; + struct ib_vbo vbo[16]; + /* This is the cached value of type0 writes to VFD_INDEX_MAX. */ + unsigned int vfd_index_max; + /* + * This is the cached value of type0 writes to VFD_CONTROL_0 which + * tells us how many VBOs are active when the draw initator is called + */ + unsigned int vfd_control_0; + /* Cached value of type0 writes to SP_VS_PVT_MEM_ADDR and + * SP_FS_PVT_MEM_ADDR. This is a buffer that contains private + * stack information for the shader + */ + unsigned int sp_vs_pvt_mem_addr; + unsigned int sp_fs_pvt_mem_addr; + /* Cached value of SP_VS_OBJ_START_REG and SP_FS_OBJ_START_REG. */ + unsigned int sp_vs_obj_start_reg; + unsigned int sp_fs_obj_start_reg; +}; + +/* + * Used for locating shader objects. This array holds the unit size of shader + * objects based on type and block of shader. The type can be 0 or 1 hence there + * are 2 columns and block can be 0-7 hence 7 rows. + */ +static int load_state_unit_sizes[7][2] = { + { 2, 4 }, + { 0, 1 }, + { 2, 4 }, + { 0, 1 }, + { 8, 2 }, + { 8, 2 }, + { 8, 2 }, +}; + +/* + * adreno_ib_merge_range() - Increases the address range tracked by an ib + * object + * @ib_obj: The ib object + * @gpuaddr: The start address which is to be merged + * @size: Size of the merging address + */ +static void adreno_ib_merge_range(struct adreno_ib_object *ib_obj, + unsigned int gpuaddr, unsigned int size) +{ + unsigned int addr_end1 = ib_obj->gpuaddr + ib_obj->size; + unsigned int addr_end2 = gpuaddr + size; + if (gpuaddr < ib_obj->gpuaddr) + ib_obj->gpuaddr = gpuaddr; + if (addr_end2 > addr_end1) + ib_obj->size = addr_end2 - ib_obj->gpuaddr; + else + ib_obj->size = addr_end1 - ib_obj->gpuaddr; +} + +/* + * adreno_ib_check_overlap() - Checks if an address range overlap + * @gpuaddr: The start address range to check for overlap + * @size: Size of the address range + * @ib_obj_list: The list of address ranges to check for overlap + * + * Checks if an address range overlaps with a list of address ranges + * Returns the entry from list which overlaps else NULL + */ +static struct adreno_ib_object *adreno_ib_check_overlap(unsigned int gpuaddr, + unsigned int size, struct adreno_ib_object_list *ib_obj_list) +{ + struct adreno_ib_object *ib_obj; + int i; + + for (i = 0; i < ib_obj_list->num_objs; i++) { + ib_obj = &(ib_obj_list->obj_list[i]); + if (kgsl_addr_range_overlap(ib_obj->gpuaddr, ib_obj->size, + gpuaddr, size)) + /* regions overlap */ + return ib_obj; + } + return NULL; +} + +/* + * adreno_ib_add_range() - Add a gpuaddress range to list + * @device: Device on which the gpuaddress range is valid + * @ptbase: Pagtebale base on which the gpuaddress is mapped + * @size: Size of the address range in concern + * @type: The type of address range + * @ib_obj_list: List of the address ranges in which the given range is to be + * added + * + * Add a gpuaddress range as an ib object to a given list after checking if it + * overlaps with another entry on the list. If it conflicts then change the + * existing entry to incorporate this range + * + * Returns 0 on success else error code + */ +static int adreno_ib_add_range(struct kgsl_device *device, + phys_addr_t ptbase, + unsigned int gpuaddr, + unsigned int size, int type, + struct adreno_ib_object_list *ib_obj_list) +{ + struct adreno_ib_object *ib_obj; + struct kgsl_mem_entry *entry; + + entry = kgsl_get_mem_entry(device, ptbase, gpuaddr, size); + if (!entry) + /* + * Do not fail if gpuaddr not found, we can continue + * to search for other objects even if few objects are + * not found + */ + return 0; + + if (!size) { + size = entry->memdesc.size; + gpuaddr = entry->memdesc.gpuaddr; + } + + ib_obj = adreno_ib_check_overlap(gpuaddr, size, ib_obj_list); + if (ib_obj) { + adreno_ib_merge_range(ib_obj, gpuaddr, size); + } else { + if (MAX_IB_OBJS == ib_obj_list->num_objs) { + KGSL_DRV_ERR(device, + "Max objects reached %d\n", ib_obj_list->num_objs); + return -ENOMEM; + } + adreno_ib_init_ib_obj(gpuaddr, size, type, entry, + &(ib_obj_list->obj_list[ib_obj_list->num_objs])); + ib_obj_list->num_objs++; + } + return 0; +} + +/* + * ib_save_mip_addresses() - Find mip addresses + * @device: Device on which the IB is running + * @pkt: Pointer to the packet in IB + * @ptbase: The pagetable on which IB is mapped + * @ib_obj_list: List in which any objects found are added + * + * Returns 0 on success else error code + */ +static int ib_save_mip_addresses(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list) +{ + int ret = 0; + int num_levels = (pkt[1] >> 22) & 0x03FF; + int i; + unsigned int *hostptr; + struct kgsl_mem_entry *ent; + unsigned int block, type; + int unitsize = 0; + + block = (pkt[1] >> 19) & 0x07; + type = pkt[2] & 0x03; + + if (type == 0) + unitsize = load_state_unit_sizes[block][0]; + else + unitsize = load_state_unit_sizes[block][1]; + + if (3 == block && 1 == type) { + ent = kgsl_get_mem_entry(device, ptbase, pkt[2] & 0xFFFFFFFC, + (num_levels * unitsize) << 2); + if (!ent) + return -EINVAL; + + hostptr = (unsigned int *)kgsl_gpuaddr_to_vaddr(&ent->memdesc, + pkt[2] & 0xFFFFFFFC); + if (!hostptr) { + kgsl_mem_entry_put(ent); + return -EINVAL; + } + for (i = 0; i < num_levels; i++) { + ret = adreno_ib_add_range(device, ptbase, hostptr[i], + 0, SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + break; + } + kgsl_memdesc_unmap(&ent->memdesc); + kgsl_mem_entry_put(ent); + } + return ret; +} + +/* + * ib_parse_load_state() - Parse load state packet + * @device: Device on which the IB is running + * @pkt: Pointer to the packet in IB + * @ptbase: The pagetable on which IB is mapped + * @ib_obj_list: List in which any objects found are added + * @ib_parse_vars: VAriable list that store temporary addressses + * + * Parse load state packet found in an IB and add any memory object found to + * a list + * Returns 0 on success else error code + */ +static int ib_parse_load_state(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + unsigned int block, source, type; + int ret = 0; + int unitsize = 0; + + /* + * The object here is to find indirect shaders i.e - shaders loaded from + * GPU memory instead of directly in the command. These should be added + * to the list of memory objects to dump. So look at the load state + * if the block is indirect (source = 4). If so then add the memory + * address to the list. The size of the object differs depending on the + * type per the load_state_unit_sizes array above. + */ + + if (type3_pkt_size(pkt[0]) < 2) + return 0; + + /* + * pkt[1] 18:16 - source + * pkt[1] 21:19 - state block + * pkt[1] 31:22 - size in units + * pkt[2] 0:1 - type + * pkt[2] 31:2 - GPU memory address + */ + + block = (pkt[1] >> 19) & 0x07; + source = (pkt[1] >> 16) & 0x07; + type = pkt[2] & 0x03; + + if (source == 4) { + if (type == 0) + unitsize = load_state_unit_sizes[block][0]; + else + unitsize = load_state_unit_sizes[block][1]; + + /* Freeze the GPU buffer containing the shader */ + + ret = adreno_ib_add_range(device, ptbase, pkt[2] & 0xFFFFFFFC, + (((pkt[1] >> 22) & 0x03FF) * unitsize) << 2, + SNAPSHOT_GPU_OBJECT_SHADER, + ib_obj_list); + if (ret < 0) + return ret; + } + /* get the mip addresses */ + ret = ib_save_mip_addresses(device, pkt, ptbase, ib_obj_list); + return ret; +} + +/* + * This opcode sets the base addresses for the visibilty stream buffer and the + * visiblity stream size buffer. + */ + +static int ib_parse_set_bin_data(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int ret = 0; + + if (type3_pkt_size(pkt[0]) < 2) + return 0; + + /* Visiblity stream buffer */ + ret = adreno_ib_add_range(device, ptbase, pkt[1], 0, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + + /* visiblity stream size buffer (fixed size 8 dwords) */ + ret = adreno_ib_add_range(device, ptbase, pkt[2], 32, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + + return ret; +} + +/* + * This opcode writes to GPU memory - if the buffer is written to, there is a + * good chance that it would be valuable to capture in the snapshot, so mark all + * buffers that are written to as frozen + */ + +static int ib_parse_mem_write(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int ret = 0; + + if (type3_pkt_size(pkt[0]) < 1) + return 0; + + /* + * The address is where the data in the rest of this packet is written + * to, but since that might be an offset into the larger buffer we need + * to get the whole thing. Pass a size of 0 tocapture the entire buffer. + */ + + ret = adreno_ib_add_range(device, ptbase, pkt[1] & 0xFFFFFFFC, 0, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + + return ret; +} + +/* + * ib_add_type0_entries() - Add memory objects to list + * @device: The device on which the IB will execute + * @ptbase: The ptbase on which IB is mapped + * @ib_obj_list: The list of gpu objects + * @ib_parse_vars: addresses ranges found in type0 packets + * + * Add memory objects to given list that are found in type0 packets + * Returns 0 on success else 0 + */ +static int ib_add_type0_entries(struct kgsl_device *device, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int ret = 0; + int i; + /* First up the visiblity stream buffer */ + + for (i = 0; i < ARRAY_SIZE(ib_parse_vars->vsc_pipe); i++) { + if (ib_parse_vars->vsc_pipe[i].base != 0 && + ib_parse_vars->vsc_pipe[i].size != 0) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->vsc_pipe[i].base, + ib_parse_vars->vsc_pipe[i].size, + SNAPSHOT_GPU_OBJECT_GENERIC, + ib_obj_list); + if (ret < 0) + return ret; + ib_parse_vars->vsc_pipe[i].size = 0; + ib_parse_vars->vsc_pipe[i].base = 0; + } + } + + /* Next the visibility stream size buffer */ + + if (ib_parse_vars->vsc_size_address) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->vsc_size_address, 32, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + ib_parse_vars->vsc_size_address = 0; + } + + /* Next private shader buffer memory */ + if (ib_parse_vars->sp_vs_pvt_mem_addr) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->sp_vs_pvt_mem_addr, 8192, + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + + ib_parse_vars->sp_vs_pvt_mem_addr = 0; + } + + if (ib_parse_vars->sp_fs_pvt_mem_addr) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->sp_fs_pvt_mem_addr, 8192, + SNAPSHOT_GPU_OBJECT_GENERIC, + ib_obj_list); + if (ret < 0) + return ret; + + ib_parse_vars->sp_fs_pvt_mem_addr = 0; + } + + if (ib_parse_vars->sp_vs_obj_start_reg) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->sp_vs_obj_start_reg & 0xFFFFFFE0, + 0, SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return -ret; + ib_parse_vars->sp_vs_obj_start_reg = 0; + } + + if (ib_parse_vars->sp_fs_obj_start_reg) { + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->sp_fs_obj_start_reg & 0xFFFFFFE0, + 0, SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + ib_parse_vars->sp_fs_obj_start_reg = 0; + } + + /* Finally: VBOs */ + + /* The number of active VBOs is stored in VFD_CONTROL_O[31:27] */ + for (i = 0; i < (ib_parse_vars->vfd_control_0) >> 27; i++) { + int size; + + /* + * The size of the VBO is the stride stored in + * VFD_FETCH_INSTR_0_X.BUFSTRIDE * VFD_INDEX_MAX. The base + * is stored in VFD_FETCH_INSTR_1_X + */ + + if (ib_parse_vars->vbo[i].base != 0) { + size = ib_parse_vars->vbo[i].stride * + ib_parse_vars->vfd_index_max; + + ret = adreno_ib_add_range(device, ptbase, + ib_parse_vars->vbo[i].base, + 0, SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + } + + ib_parse_vars->vbo[i].base = 0; + ib_parse_vars->vbo[i].stride = 0; + } + + ib_parse_vars->vfd_control_0 = 0; + ib_parse_vars->vfd_index_max = 0; + + return ret; +} + +/* + * The DRAW_INDX opcode sends a draw initator which starts a draw operation in + * the GPU, so this is the point where all the registers and buffers become + * "valid". The DRAW_INDX may also have an index buffer pointer that should be + * frozen with the others + */ + +static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int ret = 0; + + if (type3_pkt_size(pkt[0]) < 3) + return 0; + + /* DRAW_IDX may have a index buffer pointer */ + + if (type3_pkt_size(pkt[0]) > 3) { + ret = adreno_ib_add_range(device, ptbase, pkt[4], pkt[5], + SNAPSHOT_GPU_OBJECT_GENERIC, ib_obj_list); + if (ret < 0) + return ret; + } + + /* + * All of the type0 writes are valid at a draw initiator, so freeze + * the various buffers that we are tracking + */ + ret = ib_add_type0_entries(device, ptbase, ib_obj_list, + ib_parse_vars); + return ret; +} + +/* + * Parse all the type3 opcode packets that may contain important information, + * such as additional GPU buffers to grab or a draw initator + */ + +static int ib_parse_type3(struct kgsl_device *device, unsigned int *ptr, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + int opcode = cp_type3_opcode(*ptr); + + if (opcode == CP_LOAD_STATE) + return ib_parse_load_state(device, ptr, ptbase, ib_obj_list, + ib_parse_vars); + else if (opcode == CP_SET_BIN_DATA) + return ib_parse_set_bin_data(device, ptr, ptbase, ib_obj_list, + ib_parse_vars); + else if (opcode == CP_MEM_WRITE) + return ib_parse_mem_write(device, ptr, ptbase, ib_obj_list, + ib_parse_vars); + else if (opcode == CP_DRAW_INDX) + return ib_parse_draw_indx(device, ptr, ptbase, ib_obj_list, + ib_parse_vars); + + return 0; +} + +/* + * Parse type0 packets found in the stream. Some of the registers that are + * written are clues for GPU buffers that we need to freeze. Register writes + * are considred valid when a draw initator is called, so just cache the values + * here and freeze them when a CP_DRAW_INDX is seen. This protects against + * needlessly caching buffers that won't be used during a draw call + */ + +static void ib_parse_type0(struct kgsl_device *device, unsigned int *ptr, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list, + struct ib_parser_variables *ib_parse_vars) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + int size = type0_pkt_size(*ptr); + int offset = type0_pkt_offset(*ptr); + int i; + + for (i = 0; i < size; i++, offset++) { + + /* Visiblity stream buffer */ + + if (offset >= adreno_getreg(adreno_dev, + ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0) && + offset <= adreno_getreg(adreno_dev, + ADRENO_REG_VSC_PIPE_DATA_LENGTH_7)) { + int index = offset - adreno_getreg(adreno_dev, + ADRENO_REG_VSC_PIPE_DATA_ADDRESS_0); + + /* Each bank of address and length registers are + * interleaved with an empty register: + * + * address 0 + * length 0 + * empty + * address 1 + * length 1 + * empty + * ... + */ + + if ((index % 3) == 0) + ib_parse_vars->vsc_pipe[index / 3].base = + ptr[i + 1]; + else if ((index % 3) == 1) + ib_parse_vars->vsc_pipe[index / 3].size = + ptr[i + 1]; + } else if ((offset >= adreno_getreg(adreno_dev, + ADRENO_REG_VFD_FETCH_INSTR_0_0)) && + (offset <= adreno_getreg(adreno_dev, + ADRENO_REG_VFD_FETCH_INSTR_1_F))) { + int index = offset - + adreno_getreg(adreno_dev, + ADRENO_REG_VFD_FETCH_INSTR_0_0); + + /* + * FETCH_INSTR_0_X and FETCH_INSTR_1_X banks are + * interleaved as above but without the empty register + * in between + */ + + if ((index % 2) == 0) + ib_parse_vars->vbo[index >> 1].stride = + (ptr[i + 1] >> 7) & 0x1FF; + else + ib_parse_vars->vbo[index >> 1].base = + ptr[i + 1]; + } else { + /* + * Cache various support registers for calculating + * buffer sizes + */ + + if (offset == + adreno_getreg(adreno_dev, + ADRENO_REG_VFD_CONTROL_0)) + ib_parse_vars->vfd_control_0 = ptr[i + 1]; + else if (offset == + adreno_getreg(adreno_dev, + ADRENO_REG_VFD_INDEX_MAX)) + ib_parse_vars->vfd_index_max = ptr[i + 1]; + else if (offset == + adreno_getreg(adreno_dev, + ADRENO_REG_VSC_SIZE_ADDRESS)) + ib_parse_vars->vsc_size_address = ptr[i + 1]; + else if (offset == adreno_getreg(adreno_dev, + ADRENO_REG_SP_VS_PVT_MEM_ADDR_REG)) + ib_parse_vars->sp_vs_pvt_mem_addr = ptr[i + 1]; + else if (offset == adreno_getreg(adreno_dev, + ADRENO_REG_SP_FS_PVT_MEM_ADDR_REG)) + ib_parse_vars->sp_fs_pvt_mem_addr = ptr[i + 1]; + else if (offset == adreno_getreg(adreno_dev, + ADRENO_REG_SP_VS_OBJ_START_REG)) + ib_parse_vars->sp_vs_obj_start_reg = ptr[i + 1]; + else if (offset == adreno_getreg(adreno_dev, + ADRENO_REG_SP_FS_OBJ_START_REG)) + ib_parse_vars->sp_fs_obj_start_reg = ptr[i + 1]; + } + } + ib_add_type0_entries(device, ptbase, ib_obj_list, + ib_parse_vars); +} + +/* + * adreno_ib_find_objs() - Find all IB objects in a given IB + * @device: The device pointer on which the IB executes + * @ptbase: The pagetable base in which in the IBis mapped and so are the + * objects in it + * @gpuaddr: The gpu address of the IB + * @dwords: Size of ib in dwords + * @ib_obj_list: The list in which the IB and the objects in it are added. + * + * Finds all IB objects in a given IB and puts then in a list. Can be called + * recursively for the IB2's in the IB1's + * Returns 0 on success else error code + */ +static int adreno_ib_find_objs(struct kgsl_device *device, + phys_addr_t ptbase, + unsigned int gpuaddr, unsigned int dwords, + struct adreno_ib_object_list *ib_obj_list) +{ + int ret = 0; + int rem = dwords; + int i; + struct ib_parser_variables ib_parse_vars; + unsigned int *src; + struct adreno_ib_object *ib_obj; + struct kgsl_mem_entry *entry; + + /* check that this IB is not already on list */ + for (i = 0; i < ib_obj_list->num_objs; i++) { + ib_obj = &(ib_obj_list->obj_list[i]); + if ((ib_obj->gpuaddr <= gpuaddr) && + ((ib_obj->gpuaddr + ib_obj->size) >= + (gpuaddr + (dwords << 2)))) + return 0; + } + + entry = kgsl_get_mem_entry(device, ptbase, gpuaddr, (dwords << 2)); + if (!entry) + return -EINVAL; + + src = (unsigned int *)kgsl_gpuaddr_to_vaddr(&entry->memdesc, gpuaddr); + if (!src) { + kgsl_mem_entry_put(entry); + return -EINVAL; + } + + memset(&ib_parse_vars, 0, sizeof(struct ib_parser_variables)); + + ret = adreno_ib_add_range(device, ptbase, gpuaddr, dwords << 2, + SNAPSHOT_GPU_OBJECT_IB, ib_obj_list); + if (ret) + goto done; + + for (i = 0; rem > 0; rem--, i++) { + int pktsize; + + /* + * If the packet isn't a type 1 or a type 3, then don't bother + * parsing it - it is likely corrupted + */ + if (!pkt_is_type0(src[i]) && !pkt_is_type3(src[i])) + break; + + pktsize = type3_pkt_size(src[i]); + + if (!pktsize || (pktsize + 1) > rem) + break; + + if (pkt_is_type3(src[i])) { + if (adreno_cmd_is_ib(src[i])) { + unsigned int gpuaddrib2 = src[i + 1]; + unsigned int size = src[i + 2]; + + ret = adreno_ib_find_objs( + device, ptbase, + gpuaddrib2, size, + ib_obj_list); + if (ret < 0) + goto done; + } else { + ret = ib_parse_type3(device, &src[i], ptbase, + ib_obj_list, + &ib_parse_vars); + /* + * If the parse function failed (probably + * because of a bad decode) then bail out and + * just capture the binary IB data + */ + + if (ret < 0) + goto done; + } + } else if (pkt_is_type0(src[i])) { + ib_parse_type0(device, &src[i], ptbase, ib_obj_list, + &ib_parse_vars); + } + + i += pktsize; + rem -= pktsize; + } + /* + * If any type objects got missed because we did not come across draw + * indx packets then catch them here. This works better for the replay + * tool and also if the draw indx packet is in an IB2 and these setups + * are in IB1 then these objects are definitely valid and should be + * dumped + */ + ret = ib_add_type0_entries(device, ptbase, ib_obj_list, + &ib_parse_vars); +done: + kgsl_memdesc_unmap(&entry->memdesc); + kgsl_mem_entry_put(entry); + return ret; +} + + +/* + * adreno_ib_create_object_list() - Find all the memory objects in IB + * @device: The device pointer on which the IB executes + * @ptbase: The pagetable base in which in the IBis mapped and so are the + * objects in it + * @gpuaddr: The gpu address of the IB + * @dwords: Size of ib in dwords + * @ib_obj_list: The list in which the IB and the objects in it are added. + * + * Find all the memory objects that an IB needs for execution and place + * them in a list including the IB. + * Returns the ib object list else error code in pointer. + */ +int adreno_ib_create_object_list(struct kgsl_device *device, + phys_addr_t ptbase, + unsigned int gpuaddr, unsigned int dwords, + struct adreno_ib_object_list **out_ib_obj_list) +{ + int ret = 0; + struct adreno_ib_object_list *ib_obj_list; + + if (!out_ib_obj_list) + return -EINVAL; + + ib_obj_list = kzalloc(sizeof(*ib_obj_list), GFP_KERNEL); + if (!ib_obj_list) + return -ENOMEM; + + ib_obj_list->obj_list = vmalloc(MAX_IB_OBJS * + sizeof(struct adreno_ib_object)); + + if (!ib_obj_list->obj_list) { + kfree(ib_obj_list); + return -ENOMEM; + } + + ret = adreno_ib_find_objs(device, ptbase, gpuaddr, dwords, + ib_obj_list); + + if (ret) + adreno_ib_destroy_obj_list(ib_obj_list); + else + *out_ib_obj_list = ib_obj_list; + + return ret; +} + +/* + * adreno_ib_destroy_obj_list() - Destroy an ib object list + * @ib_obj_list: List to destroy + * + * Free up all resources used by an ib_obj_list + */ +void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list) +{ + int i; + + if (!ib_obj_list) + return; + + for (i = 0; i < ib_obj_list->num_objs; i++) { + if (ib_obj_list->obj_list[i].entry) + kgsl_mem_entry_put(ib_obj_list->obj_list[i].entry); + } + vfree(ib_obj_list->obj_list); + kfree(ib_obj_list); +} diff --git a/drivers/gpu/msm/adreno_cp_parser.h b/drivers/gpu/msm/adreno_cp_parser.h new file mode 100644 index 00000000000..fb2886c5702 --- /dev/null +++ b/drivers/gpu/msm/adreno_cp_parser.h @@ -0,0 +1,68 @@ +/* Copyright (c) 2013, 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. + */ + +#ifndef __ADRENO_IB_PARSER__ +#define __ADRENO_IB_PARSER__ + +/* + * struct adreno_ib_object - Structure containing information about an + * address range found in an IB + * @gpuaddr: The starting gpuaddress of the range + * @size: Size of the range + * @snapshot_obj_type - Type of range used in snapshot + * @entry: The memory entry in which this range is found + */ +struct adreno_ib_object { + unsigned int gpuaddr; + unsigned int size; + int snapshot_obj_type; + struct kgsl_mem_entry *entry; +}; + +/* + * struct adreno_ib_object_list - List of address ranges found in IB + * @obj_list: The address range list + * @num_objs: Number of objects in list + */ +struct adreno_ib_object_list { + struct adreno_ib_object *obj_list; + int num_objs; +}; + +/* + * adreno_ib_init_ib_obj() - Create an ib object structure and initialize it + * with gpuaddress and size + * @gpuaddr: gpuaddr with which to initialize the object with + * @size: Size in bytes with which the object is initialized + * @ib_type: The IB type used by snapshot + * + * Returns the object pointer on success else error code in the pointer + */ +static inline void adreno_ib_init_ib_obj(unsigned int gpuaddr, + unsigned int size, int obj_type, + struct kgsl_mem_entry *entry, + struct adreno_ib_object *ib_obj) +{ + ib_obj->gpuaddr = gpuaddr; + ib_obj->size = size; + ib_obj->snapshot_obj_type = obj_type; + ib_obj->entry = entry; +} + +int adreno_ib_create_object_list( + struct kgsl_device *device, phys_addr_t ptbase, + unsigned int gpuaddr, unsigned int dwords, + struct adreno_ib_object_list **out_ib_obj_list); + +void adreno_ib_destroy_obj_list(struct adreno_ib_object_list *ib_obj_list); + +#endif diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c index e6e4d769d79..12804a358f8 100644 --- a/drivers/gpu/msm/adreno_debugfs.c +++ b/drivers/gpu/msm/adreno_debugfs.c @@ -19,27 +19,12 @@ #include "kgsl.h" #include "adreno.h" +#include "kgsl_cffdump.h" #include "a2xx_reg.h" unsigned int kgsl_cff_dump_enable; -static int kgsl_cff_dump_enable_set(void *data, u64 val) -{ -#ifdef CONFIG_MSM_KGSL_CFF_DUMP - kgsl_cff_dump_enable = (val != 0); - return 0; -#else - return -EINVAL; -#endif -} - -static int kgsl_cff_dump_enable_get(void *data, u64 *val) -{ - *val = kgsl_cff_dump_enable; - return 0; -} - DEFINE_SIMPLE_ATTRIBUTE(kgsl_cff_dump_enable_fops, kgsl_cff_dump_enable_get, kgsl_cff_dump_enable_set, "%llu\n"); @@ -106,6 +91,6 @@ void adreno_debugfs_init(struct kgsl_device *device) debugfs_create_u32("ft_pagefault_policy", 0644, device->d_debugfs, &adreno_dev->ft_pf_policy); - debugfs_create_file("active_cnt", 0644, device->d_debugfs, device, + debugfs_create_file("active_cnt", 0444, device->d_debugfs, device, &_active_count_fops); } diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index f1c98db8a07..357242f4eaf 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -22,13 +22,6 @@ #include "adreno_ringbuffer.h" #include "adreno_trace.h" -#define ADRENO_DISPATCHER_ACTIVE 0 -#define ADRENO_DISPATCHER_PAUSE 1 - -#define ADRENO_DISPATCHER_SOFT_FAULT 1 -#define ADRENO_DISPATCHER_HARD_FAULT 2 -#define ADRENO_DISPATCHER_TIMEOUT_FAULT 3 - #define CMDQUEUE_NEXT(_i, _s) (((_i) + 1) % (_s)) /* Number of commands that can be queued in a context before it sleeps */ @@ -44,13 +37,16 @@ static unsigned int _context_cmdbatch_burst = 5; static unsigned int _dispatcher_inflight = 15; /* Command batch timeout (in milliseconds) */ -static unsigned int _cmdbatch_timeout = 10000; +static unsigned int _cmdbatch_timeout = 2000; /* Interval for reading and comparing fault detection registers */ -static unsigned int _fault_timer_interval = 100; +static unsigned int _fault_timer_interval = 50; /* Local array for the current set of fault detect registers */ -static unsigned int *fault_detect_regs; +static unsigned int fault_detect_regs[FT_DETECT_REGS_COUNT]; + +/* The last retired global timestamp read during fault detect */ +static unsigned int fault_detect_ts; /** * fault_detect_read() - Read the set of fault detect registers @@ -64,14 +60,35 @@ static void fault_detect_read(struct kgsl_device *device) { int i; + fault_detect_ts = kgsl_readtimestamp(device, NULL, + KGSL_TIMESTAMP_RETIRED); + for (i = 0; i < FT_DETECT_REGS_COUNT; i++) { if (ft_detect_regs[i] == 0) continue; - adreno_regread(device, ft_detect_regs[i], + kgsl_regread(device, ft_detect_regs[i], &fault_detect_regs[i]); } } +/* + * Check to see if the device is idle and that the global timestamp is up to + * date + */ +static inline bool _isidle(struct kgsl_device *device) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int ts; + + ts = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED); + + if (adreno_isidle(device) == true && + (ts >= adreno_dev->ringbuffer.global_ts)) + return true; + + return false; +} + /** * fault_detect_read_compare() - Read the fault detect registers and compare * them to the current value @@ -83,28 +100,39 @@ static void fault_detect_read(struct kgsl_device *device) static int fault_detect_read_compare(struct kgsl_device *device) { int i, ret = 0; + unsigned int ts; + + /* Check to see if the device is idle - if so report no hang */ + if (_isidle(device) == true) + ret = 1; for (i = 0; i < FT_DETECT_REGS_COUNT; i++) { unsigned int val; if (ft_detect_regs[i] == 0) continue; - adreno_regread(device, ft_detect_regs[i], &val); + kgsl_regread(device, ft_detect_regs[i], &val); if (val != fault_detect_regs[i]) ret = 1; fault_detect_regs[i] = val; } + ts = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED); + if (ts != fault_detect_ts) + ret = 1; + + fault_detect_ts = ts; + return ret; } /** - * adreno_context_get_cmdbatch() - Get a new command from a context queue + * adreno_dispatcher_get_cmdbatch() - Get a new command from a context queue * @drawctxt: Pointer to the adreno draw context * * Dequeue a new command batch from the context list */ -static inline struct kgsl_cmdbatch *adreno_context_get_cmdbatch( +static inline struct kgsl_cmdbatch *adreno_dispatcher_get_cmdbatch( struct adreno_context *drawctxt) { struct kgsl_cmdbatch *cmdbatch = NULL; @@ -135,20 +163,29 @@ static inline struct kgsl_cmdbatch *adreno_context_get_cmdbatch( } /** - * adreno_context_requeue_cmdbatch() - Put a command back on the context queue + * adreno_dispatcher_requeue_cmdbatch() - Put a command back on the context + * queue * @drawctxt: Pointer to the adreno draw context * @cmdbatch: Pointer to the KGSL cmdbatch to requeue * * Failure to submit a command to the ringbuffer isn't the fault of the command * being submitted so if a failure happens, push it back on the head of the the - * context queue to be reconsidered again + * context queue to be reconsidered again unless the context got detached. */ -static inline void adreno_context_requeue_cmdbatch( +static inline int adreno_dispatcher_requeue_cmdbatch( struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch) { unsigned int prev; mutex_lock(&drawctxt->mutex); + if (kgsl_context_detached(&drawctxt->base) || + drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { + mutex_unlock(&drawctxt->mutex); + /* get rid of this cmdbatch since the context is bad */ + kgsl_cmdbatch_destroy(cmdbatch); + return -EINVAL; + } + prev = drawctxt->cmdqueue_head - 1; if (prev < 0) @@ -167,6 +204,7 @@ static inline void adreno_context_requeue_cmdbatch( /* Reset the command queue head to reflect the newly requeued change */ drawctxt->cmdqueue_head = prev; mutex_unlock(&drawctxt->mutex); + return 0; } /** @@ -181,14 +219,19 @@ static void dispatcher_queue_context(struct adreno_device *adreno_dev, { struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; + /* Refuse to queue a detached context */ + if (kgsl_context_detached(&drawctxt->base)) + return; + spin_lock(&dispatcher->plist_lock); if (plist_node_empty(&drawctxt->pending)) { /* Get a reference to the context while it sits on the list */ - _kgsl_context_get(&drawctxt->base); - trace_dispatch_queue_context(drawctxt); - plist_add(&drawctxt->pending, &dispatcher->pending); + if (_kgsl_context_get(&drawctxt->base)) { + trace_dispatch_queue_context(drawctxt); + plist_add(&drawctxt->pending, &dispatcher->pending); + } } spin_unlock(&dispatcher->plist_lock); @@ -208,11 +251,13 @@ static int sendcmd(struct adreno_device *adreno_dev, struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; int ret; + mutex_lock(&device->mutex); + dispatcher->inflight++; - mutex_lock(&device->mutex); + if (dispatcher->inflight == 1 && + !test_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv)) { - if (dispatcher->inflight == 1) { /* Time to make the donuts. Turn on the GPU */ ret = kgsl_active_count_get(device); if (ret) { @@ -220,6 +265,8 @@ static int sendcmd(struct adreno_device *adreno_dev, mutex_unlock(&device->mutex); return ret; } + + set_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv); } ret = adreno_ringbuffer_submitcmd(adreno_dev, cmdbatch); @@ -232,8 +279,10 @@ static int sendcmd(struct adreno_device *adreno_dev, if (dispatcher->inflight == 1) { if (ret == 0) fault_detect_read(device); - else + else { kgsl_active_count_put(device); + clear_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv); + } } mutex_unlock(&device->mutex); @@ -241,7 +290,7 @@ static int sendcmd(struct adreno_device *adreno_dev, if (ret) { dispatcher->inflight--; KGSL_DRV_ERR(device, - "Unable to submit command to the ringbuffer\n"); + "Unable to submit command to the ringbuffer %d\n", ret); return ret; } @@ -278,21 +327,28 @@ static int sendcmd(struct adreno_device *adreno_dev, * @drawctxt: Pointer to the adreno context to dispatch commands from * * Dequeue and send a burst of commands from the specified context to the GPU + * Returns postive if the context needs to be put back on the pending queue + * 0 if the context is empty or detached and negative on error */ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, struct adreno_context *drawctxt) { struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; int count = 0; + int requeued = 0; /* * Each context can send a specific number of command batches per cycle */ - for ( ; count < _context_cmdbatch_burst && - dispatcher->inflight < _dispatcher_inflight; count++) { + while ((count < _context_cmdbatch_burst) && + (dispatcher->inflight < _dispatcher_inflight)) { int ret; - struct kgsl_cmdbatch *cmdbatch = - adreno_context_get_cmdbatch(drawctxt); + struct kgsl_cmdbatch *cmdbatch; + + if (adreno_gpu_fault(adreno_dev) != 0) + break; + + cmdbatch = adreno_dispatcher_get_cmdbatch(drawctxt); if (cmdbatch == NULL) break; @@ -304,8 +360,10 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, * reqeueued */ - if (IS_ERR(cmdbatch)) - return count; + if (IS_ERR(cmdbatch) && PTR_ERR(cmdbatch) == -EAGAIN) { + requeued = 1; + break; + } /* * If this is a synchronization submission then there are no @@ -315,7 +373,6 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, */ if (cmdbatch->flags & KGSL_CONTEXT_SYNC) { - count--; kgsl_cmdbatch_destroy(cmdbatch); continue; } @@ -330,31 +387,29 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, * conditions improve */ if (ret) { - adreno_context_requeue_cmdbatch(drawctxt, cmdbatch); + requeued = adreno_dispatcher_requeue_cmdbatch(drawctxt, + cmdbatch) ? 0 : 1; break; } + + count++; } /* - * If the context successfully submitted commands, then - * unconditionally put it back on the queue to be considered the - * next time around. This might seem a little wasteful but it is - * reasonable to think that a busy context will stay busy. + * If the context successfully submitted commands there will be room + * in the context queue so wake up any snoozing threads that want to + * submit commands */ - if (count) { - dispatcher_queue_context(adreno_dev, drawctxt); - - /* - * If we submitted something there will be room in the - * context queue so ping the context wait queue on the - * chance that the context is snoozing - */ - + if (count) wake_up_interruptible_all(&drawctxt->wq); - } - return count; + /* + * Return positive if the context submitted commands or if we figured + * out that we need to requeue due to a pending sync or error. + */ + + return (count || requeued) ? 1 : 0; } /** @@ -367,27 +422,37 @@ static int dispatcher_context_sendcmds(struct adreno_device *adreno_dev, static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev) { struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; + struct adreno_context *drawctxt, *next; + struct plist_head requeue; + int ret; - /* Don't do anything if the dispatcher is paused */ - if (dispatcher->state != ADRENO_DISPATCHER_ACTIVE) - return 0; + /* Leave early if the dispatcher isn't in a happy state */ + if (adreno_gpu_fault(adreno_dev) != 0) + return 0; + + plist_head_init(&requeue); + /* Try to fill the ringbuffer as much as possible */ while (dispatcher->inflight < _dispatcher_inflight) { - struct adreno_context *drawctxt = NULL; - spin_lock(&dispatcher->plist_lock); + /* Stop doing things if the dispatcher is paused or faulted */ + if (adreno_gpu_fault(adreno_dev) != 0) + break; - if (!plist_head_empty(&dispatcher->pending)) { - drawctxt = plist_first_entry(&dispatcher->pending, - struct adreno_context, pending); + spin_lock(&dispatcher->plist_lock); - plist_del(&drawctxt->pending, &dispatcher->pending); + if (plist_head_empty(&dispatcher->pending)) { + spin_unlock(&dispatcher->plist_lock); + break; } - spin_unlock(&dispatcher->plist_lock); + /* Get the next entry on the list */ + drawctxt = plist_first_entry(&dispatcher->pending, + struct adreno_context, pending); - if (drawctxt == NULL) - break; + plist_del(&drawctxt->pending, &dispatcher->pending); + + spin_unlock(&dispatcher->plist_lock); if (kgsl_context_detached(&drawctxt->base) || drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { @@ -395,10 +460,49 @@ static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev) continue; } - dispatcher_context_sendcmds(adreno_dev, drawctxt); - kgsl_context_put(&drawctxt->base); + ret = dispatcher_context_sendcmds(adreno_dev, drawctxt); + + if (ret > 0) { + spin_lock(&dispatcher->plist_lock); + + /* + * Check to seen if the context had been requeued while + * we were processing it (probably by another thread + * pushing commands). If it has then we don't need to + * bother with it but do a put to make sure the + * reference counting stays accurate. If the node is + * empty then we will put it on the requeue list and not + * touch the refcount since we already hold it from the + * first time it went on the list. + */ + + if (plist_node_empty(&drawctxt->pending)) + plist_add(&drawctxt->pending, &requeue); + else + kgsl_context_put(&drawctxt->base); + + spin_unlock(&dispatcher->plist_lock); + } else { + /* + * If the context doesn't need be requeued put back the + * refcount + */ + + kgsl_context_put(&drawctxt->base); + } + } + + /* Put all the requeued contexts back on the master list */ + + spin_lock(&dispatcher->plist_lock); + + plist_for_each_entry_safe(drawctxt, next, &requeue, pending) { + plist_del(&drawctxt->pending, &requeue); + plist_add(&drawctxt->pending, &dispatcher->pending); } + spin_unlock(&dispatcher->plist_lock); + return 0; } @@ -476,7 +580,7 @@ static int get_timestamp(struct adreno_context *drawctxt, } /** - * adreno_context_queue_cmd() - Queue a new command in the context + * adreno_dispatcher_queue_cmd() - Queue a new command in the context * @adreno_dev: Pointer to the adreno device struct * @drawctxt: Pointer to the adreno draw context * @cmdbatch: Pointer to the command batch being submitted @@ -485,7 +589,7 @@ static int get_timestamp(struct adreno_context *drawctxt, * Queue a command in the context - if there isn't any room in the queue, then * block until there is */ -int adreno_context_queue_cmd(struct adreno_device *adreno_dev, +int adreno_dispatcher_queue_cmd(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, struct kgsl_cmdbatch *cmdbatch, uint32_t *timestamp) { @@ -493,7 +597,7 @@ int adreno_context_queue_cmd(struct adreno_device *adreno_dev, mutex_lock(&drawctxt->mutex); - if (drawctxt->flags & CTXT_FLAGS_BEING_DESTROYED) { + if (kgsl_context_detached(&drawctxt->base)) { mutex_unlock(&drawctxt->mutex); return -EINVAL; } @@ -504,7 +608,7 @@ int adreno_context_queue_cmd(struct adreno_device *adreno_dev, */ if (drawctxt->flags & CTXT_FLAGS_FORCE_PREAMBLE) { - cmdbatch->priv |= CMDBATCH_FLAG_FORCE_PREAMBLE; + set_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &cmdbatch->priv); drawctxt->flags &= ~CTXT_FLAGS_FORCE_PREAMBLE; } @@ -515,7 +619,7 @@ int adreno_context_queue_cmd(struct adreno_device *adreno_dev, */ if (drawctxt->flags & CTXT_FLAGS_SKIP_EOF) { - cmdbatch->priv |= CMDBATCH_FLAG_SKIP; + set_bit(CMDBATCH_FLAG_SKIP, &cmdbatch->priv); /* * If this command batch represents the EOF then clear the way @@ -537,7 +641,7 @@ int adreno_context_queue_cmd(struct adreno_device *adreno_dev, /* Wait for room in the context queue */ while (drawctxt->queued >= _context_cmdqueue_size) { - trace_adreno_context_sleep(drawctxt); + trace_adreno_drawctxt_sleep(drawctxt); mutex_unlock(&drawctxt->mutex); ret = wait_event_interruptible_timeout(drawctxt->wq, @@ -545,22 +649,25 @@ int adreno_context_queue_cmd(struct adreno_device *adreno_dev, msecs_to_jiffies(_context_queue_wait)); mutex_lock(&drawctxt->mutex); - trace_adreno_context_wake(drawctxt); + trace_adreno_drawctxt_wake(drawctxt); if (ret <= 0) { mutex_unlock(&drawctxt->mutex); return (ret == 0) ? -ETIMEDOUT : (int) ret; } + } + /* + * Account for the possiblity that the context got invalidated + * while we were sleeping + */ - /* - * Account for the possiblity that the context got invalidated - * while we were sleeping - */ - - if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { - mutex_unlock(&drawctxt->mutex); - return -EDEADLK; - } + if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { + mutex_unlock(&drawctxt->mutex); + return -EDEADLK; + } + if (kgsl_context_detached(&drawctxt->base)) { + mutex_unlock(&drawctxt->mutex); + return -EINVAL; } ret = get_timestamp(drawctxt, cmdbatch, timestamp); @@ -571,8 +678,15 @@ int adreno_context_queue_cmd(struct adreno_device *adreno_dev, cmdbatch->timestamp = *timestamp; - /* The batch fault policy is the current system fault policy */ - cmdbatch->fault_policy = adreno_dev->ft_policy; + /* + * Set the fault tolerance policy for the command batch - assuming the + * context hsn't disabled FT use the current device policy + */ + + if (drawctxt->flags & CTXT_FLAGS_NO_FAULT_TOLERANCE) + set_bit(KGSL_FT_DISABLE, &cmdbatch->fault_policy); + else + cmdbatch->fault_policy = adreno_dev->ft_policy; /* Put the command into the queue */ drawctxt->cmdqueue[drawctxt->cmdqueue_tail] = cmdbatch; @@ -615,7 +729,8 @@ static void cmdbatch_skip_ib(struct kgsl_cmdbatch *cmdbatch, unsigned int base) for (i = 0; i < cmdbatch->ibcount; i++) { if (cmdbatch->ibdesc[i].gpuaddr == base) { cmdbatch->ibdesc[i].sizedwords = 0; - return; + if (base) + return; } } } @@ -644,12 +759,12 @@ static void cmdbatch_skip_frame(struct kgsl_cmdbatch *cmdbatch, */ if (skip) { - replay[i]->priv |= CMDBATCH_FLAG_SKIP; + set_bit(CMDBATCH_FLAG_SKIP, &replay[i]->priv); if (replay[i]->flags & KGSL_CONTEXT_END_OF_FRAME) skip = 0; } else { - replay[i]->priv |= CMDBATCH_FLAG_FORCE_PREAMBLE; + set_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &replay[i]->priv); return; } } @@ -699,7 +814,70 @@ static void remove_invalidated_cmdbatches(struct kgsl_device *device, } } -static void dispatcher_do_fault(struct kgsl_device *device) +static char _pidname[TASK_COMM_LEN]; + +static inline const char *_kgsl_context_comm(struct kgsl_context *context) +{ + struct task_struct *task = NULL; + + if (context) + task = find_task_by_vpid(context->pid); + + if (task) + get_task_comm(_pidname, task); + else + snprintf(_pidname, TASK_COMM_LEN, "unknown"); + + return _pidname; +} + +#define pr_fault(_d, _c, fmt, args...) \ + dev_err((_d)->dev, "%s[%d]: " fmt, \ + _kgsl_context_comm((_c)->context), \ + (_c)->context->pid, ##args) + + +static void adreno_fault_header(struct kgsl_device *device, + struct kgsl_cmdbatch *cmdbatch) +{ + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int status, base, rptr, wptr, ib1base, ib2base, ib1sz, ib2sz; + + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_RBBM_STATUS), + &status); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_BASE), + &base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_RPTR), + &rptr); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_WPTR), + &wptr); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB1_BASE), + &ib1base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ), + &ib1sz); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB2_BASE), + &ib2base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB2_BUFSZ), + &ib2sz); + + trace_adreno_gpu_fault(cmdbatch->context->id, cmdbatch->timestamp, + status, rptr, wptr, ib1base, ib1sz, ib2base, ib2sz); + + pr_fault(device, cmdbatch, + "gpu fault ctx %d ts %d status %8.8X rb %4.4x/%4.4x ib1 %8.8x/%4.4x ib2 %8.8x/%4.4x\n", + cmdbatch->context->id, cmdbatch->timestamp, status, + rptr, wptr, ib1base, ib1sz, ib2base, ib2sz); +} + +static int dispatcher_do_fault(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; @@ -708,8 +886,21 @@ static void dispatcher_do_fault(struct kgsl_device *device) struct kgsl_cmdbatch **replay = NULL; struct kgsl_cmdbatch *cmdbatch; int ret, i, count = 0; + int fault, first = 0; + bool pagefault = false; - BUG_ON(dispatcher->inflight == 0); + fault = atomic_xchg(&dispatcher->fault, 0); + if (fault == 0) + return 0; + /* + * Return early if no command inflight - can happen on + * false hang detects + */ + if (dispatcher->inflight == 0) { + KGSL_DRV_WARN(device, + "dispatcher_do_fault with 0 inflight commands\n"); + return 0; + } /* Turn off all the timers */ del_timer_sync(&dispatcher->timer); @@ -719,29 +910,35 @@ static void dispatcher_do_fault(struct kgsl_device *device) cmdbatch = dispatcher->cmdqueue[dispatcher->head]; + trace_adreno_cmdbatch_fault(cmdbatch, fault); + /* * If the fault was due to a timeout then stop the CP to ensure we don't * get activity while we are trying to dump the state of the system */ - if (dispatcher->fault == ADRENO_DISPATCHER_TIMEOUT_FAULT) { - kgsl_regread(device, REG_CP_ME_CNTL, ®); + if (fault & ADRENO_TIMEOUT_FAULT) { + adreno_readreg(adreno_dev, ADRENO_REG_CP_ME_CNTL, ®); reg |= (1 << 27) | (1 << 28); - kgsl_regwrite(device, REG_CP_ME_CNTL, reg); + adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_CNTL, reg); /* Skip the PM dump for a timeout because it confuses people */ - cmdbatch->fault_policy |= KGSL_FT_SKIP_PMDUMP; + set_bit(KGSL_FT_SKIP_PMDUMP, &cmdbatch->fault_policy); } - kgsl_regread(device, REG_CP_IB1_BASE, &base); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &base); /* * Dump the postmortem and snapshot information if this is the first * detected fault for the oldest active command batch */ - if (!(cmdbatch->fault_policy & KGSL_FT_SKIP_PMDUMP)) { - kgsl_postmortem_dump(device, 0); + if (!test_bit(KGSL_FT_SKIP_PMDUMP, &cmdbatch->fault_policy)) { + adreno_fault_header(device, cmdbatch); + + if (device->pm_dump_enable) + kgsl_postmortem_dump(device, 0); + kgsl_device_snapshot(device, 1); } @@ -787,12 +984,24 @@ static void dispatcher_do_fault(struct kgsl_device *device) cmdbatch = replay[0]; + /* + * If FT is disabled for this cmdbatch invalidate immediately + */ + + if (test_bit(KGSL_FT_DISABLE, &cmdbatch->fault_policy) || + test_bit(KGSL_FT_TEMP_DISABLE, &cmdbatch->fault_policy)) { + pr_fault(device, cmdbatch, "gpu skipped ctx %d ts %d\n", + cmdbatch->context->id, cmdbatch->timestamp); + + adreno_drawctxt_invalidate(device, cmdbatch->context); + } + /* * Set a flag so we don't print another PM dump if the cmdbatch fails * again on replay */ - cmdbatch->fault_policy |= KGSL_FT_SKIP_PMDUMP; + set_bit(KGSL_FT_SKIP_PMDUMP, &cmdbatch->fault_policy); /* * A hardware fault generally means something was deterministically @@ -800,16 +1009,29 @@ static void dispatcher_do_fault(struct kgsl_device *device) * Clear the replay bit and move on to the next policy level */ - if (dispatcher->fault == ADRENO_DISPATCHER_HARD_FAULT) - cmdbatch->fault_policy &= ~KGSL_FT_REPLAY; + if (fault & ADRENO_HARD_FAULT) + clear_bit(KGSL_FT_REPLAY, &(cmdbatch->fault_policy)); + + /* + * A timeout fault means the IB timed out - clear the policy and + * invalidate - this will clear the FT_SKIP_PMDUMP bit but that is okay + * because we won't see this cmdbatch again + */ + + if (fault & ADRENO_TIMEOUT_FAULT) + bitmap_zero(&cmdbatch->fault_policy, BITS_PER_LONG); /* - * A timeout fault means the IB timed out - don't be silly and replay - * it, because it will probably timeout again + * If the context had a GPU page fault then it is likely it would fault + * again if replayed */ - if (dispatcher->fault == ADRENO_DISPATCHER_TIMEOUT_FAULT) - cmdbatch->fault_policy &= ~KGSL_FT_REPLAY; + if (test_bit(KGSL_CONTEXT_PAGEFAULT, &cmdbatch->context->priv)) { + /* we'll need to resume the mmu later... */ + pagefault = true; + clear_bit(KGSL_FT_REPLAY, &cmdbatch->fault_policy); + clear_bit(KGSL_CONTEXT_PAGEFAULT, &cmdbatch->context->priv); + } /* * Execute the fault tolerance policy. Each command batch stores the @@ -821,8 +1043,9 @@ static void dispatcher_do_fault(struct kgsl_device *device) */ /* Replay the hanging command batch again */ - if (cmdbatch->fault_policy & KGSL_FT_REPLAY) { - cmdbatch->fault_policy &= ~KGSL_FT_REPLAY; + if (test_and_clear_bit(KGSL_FT_REPLAY, &cmdbatch->fault_policy)) { + trace_adreno_cmdbatch_recovery(cmdbatch, BIT(KGSL_FT_REPLAY)); + set_bit(KGSL_FT_REPLAY, &cmdbatch->fault_recovery); goto replay; } @@ -834,20 +1057,23 @@ static void dispatcher_do_fault(struct kgsl_device *device) * supposedly bad IB1 where ever it lurks. */ - if (cmdbatch->fault_policy & KGSL_FT_SKIPIB) { - cmdbatch->fault_policy &= ~KGSL_FT_SKIPIB; + if (test_and_clear_bit(KGSL_FT_SKIPIB, &cmdbatch->fault_policy)) { + trace_adreno_cmdbatch_recovery(cmdbatch, BIT(KGSL_FT_SKIPIB)); + set_bit(KGSL_FT_SKIPIB, &cmdbatch->fault_recovery); for (i = 0; i < count; i++) { - if (replay[i] != NULL) + if (replay[i] != NULL && + replay[i]->context->id == cmdbatch->context->id) cmdbatch_skip_ib(replay[i], base); } goto replay; } - if (cmdbatch->fault_policy & KGSL_FT_SKIPFRAME) { - - cmdbatch->fault_policy &= ~KGSL_FT_SKIPFRAME; + if (test_and_clear_bit(KGSL_FT_SKIPFRAME, &cmdbatch->fault_policy)) { + trace_adreno_cmdbatch_recovery(cmdbatch, + BIT(KGSL_FT_SKIPFRAME)); + set_bit(KGSL_FT_SKIPFRAME, &cmdbatch->fault_recovery); /* * Skip all the pending command batches for this context until @@ -857,13 +1083,14 @@ static void dispatcher_do_fault(struct kgsl_device *device) goto replay; } - /* If we get here then all the policies failed or FT is disabled */ + /* If we get here then all the policies failed */ + + pr_fault(device, cmdbatch, "gpu failed ctx %d ts %d\n", + cmdbatch->context->id, cmdbatch->timestamp); /* Invalidate the context */ adreno_drawctxt_invalidate(device, cmdbatch->context); - /* Remove any pending command batches that have been invalidated */ - remove_invalidated_cmdbatches(device, replay, count); replay: /* Reset the dispatcher queue */ @@ -872,19 +1099,17 @@ static void dispatcher_do_fault(struct kgsl_device *device) /* Reset the GPU */ mutex_lock(&device->mutex); + ret = adreno_reset(device); mutex_unlock(&device->mutex); + /* if any other fault got in until reset then ignore */ + fault = atomic_xchg(&dispatcher->fault, 0); /* If adreno_reset() fails then what hope do we have for the future? */ BUG_ON(ret); - /* - * Force the preamble on the first command (if applicable) to avoid any - * strange stage issues - */ - - if (replay[0]) - replay[0]->priv |= CMDBATCH_FLAG_FORCE_PREAMBLE; + /* Remove any pending command batches that have been invalidated */ + remove_invalidated_cmdbatches(device, replay, count); /* Replay the pending command buffers */ for (i = 0; i < count; i++) { @@ -895,11 +1120,21 @@ static void dispatcher_do_fault(struct kgsl_device *device) continue; /* - * Force each command batch to wait for idle - this avoids wierd + * Force the preamble on the first command (if applicable) to + * avoid any strange stage issues + */ + + if (first == 0) { + set_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &replay[i]->priv); + first = 1; + } + + /* + * Force each command batch to wait for idle - this avoids weird * CP parse issues */ - replay[i]->flags |= KGSL_CMD_FLAGS_WFI; + set_bit(CMDBATCH_FLAG_WFI, &replay[i]->priv); ret = sendcmd(adreno_dev, replay[i]); @@ -909,18 +1144,19 @@ static void dispatcher_do_fault(struct kgsl_device *device) */ if (ret) { - adreno_drawctxt_invalidate(device, cmdbatch->context); + pr_fault(device, replay[i], + "gpu reset failed ctx %d ts %d\n", + replay[i]->context->id, replay[i]->timestamp); + adreno_drawctxt_invalidate(device, replay[i]->context); remove_invalidated_cmdbatches(device, &replay[i], count - i); } } - mutex_lock(&device->mutex); - kgsl_active_count_put(device); - mutex_unlock(&device->mutex); - kfree(replay); + + return 1; } static inline int cmdbatch_consumed(struct kgsl_cmdbatch *cmdbatch, @@ -930,6 +1166,30 @@ static inline int cmdbatch_consumed(struct kgsl_cmdbatch *cmdbatch, (timestamp_cmp(retired, cmdbatch->timestamp) < 0)); } +static void _print_recovery(struct kgsl_device *device, + struct kgsl_cmdbatch *cmdbatch) +{ + static struct { + unsigned int mask; + const char *str; + } flags[] = { ADRENO_FT_TYPES }; + + int i, nr = find_first_bit(&cmdbatch->fault_recovery, BITS_PER_LONG); + char *result = "unknown"; + + for (i = 0; i < ARRAY_SIZE(flags); i++) { + if (flags[i].mask == BIT(nr)) { + result = (char *) flags[i].str; + break; + } + } + + pr_fault(device, cmdbatch, + "gpu %s ctx %d ts %d policy %lX\n", + result, cmdbatch->context->id, cmdbatch->timestamp, + cmdbatch->fault_recovery); +} + /** * adreno_dispatcher_work() - Master work handler for the dispatcher * @work: Pointer to the work struct for the current work queue @@ -944,6 +1204,7 @@ static void adreno_dispatcher_work(struct work_struct *work) container_of(dispatcher, struct adreno_device, dispatcher); struct kgsl_device *device = &adreno_dev->dev; int count = 0; + int fault_handled = 0; mutex_lock(&dispatcher->mutex); @@ -964,12 +1225,18 @@ static void adreno_dispatcher_work(struct work_struct *work) * pointers and continue processing the queue */ - if (!kgsl_context_detached(cmdbatch->context)) - retired = kgsl_readtimestamp(device, cmdbatch->context, + retired = kgsl_readtimestamp(device, cmdbatch->context, KGSL_TIMESTAMP_RETIRED); - if (kgsl_context_detached(cmdbatch->context) || - (timestamp_cmp(cmdbatch->timestamp, retired) <= 0)) { + if ((timestamp_cmp(cmdbatch->timestamp, retired) <= 0)) { + + /* + * If the cmdbatch in question had faulted announce its + * successful completion to the world + */ + + if (cmdbatch->fault_recovery != 0) + _print_recovery(device, cmdbatch); trace_adreno_cmdbatch_retired(cmdbatch, dispatcher->inflight - 1); @@ -1005,19 +1272,17 @@ static void adreno_dispatcher_work(struct work_struct *work) * is to blame. Invalidate it, reset and replay */ - if (dispatcher->fault) { - dispatcher_do_fault(device); - dispatcher->fault = 0; + if (dispatcher_do_fault(device)) goto done; - } + fault_handled = 1; /* Get the last consumed timestamp */ consumed = kgsl_readtimestamp(device, cmdbatch->context, KGSL_TIMESTAMP_CONSUMED); /* - * Break here if fault detection is dsiabled for the context or - * if the long running IB detection is disabled device wide + * Break here if fault detection is disabled for the context or + * if the long running IB detection is disaled device wide * Long running command buffers will be allowed to run to * completion - but badly behaving command buffers (infinite * shaders etc) can end up running forever. @@ -1038,24 +1303,32 @@ static void adreno_dispatcher_work(struct work_struct *work) /* Boom goes the dynamite */ - KGSL_DRV_ERR(device, - "Context %d, timestamp %d ran too long\n", - drawctxt->base.id, drawctxt->timestamp); + pr_fault(device, cmdbatch, + "gpu timeout ctx %d ts %d\n", + cmdbatch->context->id, cmdbatch->timestamp); - dispatcher->fault = ADRENO_DISPATCHER_TIMEOUT_FAULT; + adreno_set_gpu_fault(adreno_dev, ADRENO_TIMEOUT_FAULT); dispatcher_do_fault(device); + fault_handled = 1; break; } /* - * Decrement the active count to 0 - this will allow the system to go - * into suspend even if there are queued command batches + * Call the dispatcher fault routine here so the fault bit gets cleared + * when no commands are in dispatcher but fault bit is set. This can + * happen on false hang detects */ + if (!fault_handled && dispatcher_do_fault(device)) + goto done; + /* + * If inflight went to 0, queue back up the event processor to catch + * stragglers + */ if (count && dispatcher->inflight == 0) { mutex_lock(&device->mutex); - kgsl_active_count_put(device); + queue_work(device->work_queue, &device->ts_expired_ws); mutex_unlock(&device->mutex); } @@ -1071,15 +1344,29 @@ static void adreno_dispatcher_work(struct work_struct *work) /* Update the timeout timer for the next command batch */ mod_timer(&dispatcher->timer, cmdbatch->expires); + + /* There are still things in flight - update the idle counts */ + mutex_lock(&device->mutex); + kgsl_pwrscale_idle(device); + mutex_unlock(&device->mutex); } else { - del_timer_sync(&dispatcher->timer); + /* There is nothing left in the pipeline. Shut 'er down boys */ + mutex_lock(&device->mutex); + + /* + * Stop the fault timer before decrementing the active count to + * avoid reading the hardware registers while we are trying to + * turn clocks off + */ del_timer_sync(&dispatcher->fault_timer); - } - /* Before leaving update the pwrscale information */ - mutex_lock(&device->mutex); - kgsl_pwrscale_idle(device); - mutex_unlock(&device->mutex); + if (test_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv)) { + kgsl_active_count_put(device); + clear_bit(ADRENO_DISPATCHER_POWER, &dispatcher->priv); + } + + mutex_unlock(&device->mutex); + } mutex_unlock(&dispatcher->mutex); } @@ -1123,17 +1410,16 @@ void adreno_dispatcher_fault_timer(unsigned long data) struct kgsl_device *device = &adreno_dev->dev; struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; + BUG_ON(atomic_read(&device->active_cnt) == 0); + /* Leave if the user decided to turn off fast hang detection */ if (adreno_dev->fast_hang_detect == 0) return; - /* Don't do anything if the dispatcher is idle or faulted */ - if (dispatcher->inflight == 0 || dispatcher->fault) - return; - - /* Make sure the device is active before trying a read */ - if (device->state != KGSL_STATE_ACTIVE) + if (adreno_gpu_fault(adreno_dev)) { + adreno_dispatcher_schedule(device); return; + } /* * Read the fault registers - if it returns 0 then they haven't changed @@ -1141,7 +1427,7 @@ void adreno_dispatcher_fault_timer(unsigned long data) */ if (!fault_detect_read_compare(device)) { - dispatcher->fault = ADRENO_DISPATCHER_SOFT_FAULT; + adreno_set_gpu_fault(adreno_dev, ADRENO_SOFT_FAULT); adreno_dispatcher_schedule(device); } else { mod_timer(&dispatcher->fault_timer, @@ -1169,48 +1455,22 @@ void adreno_dispatcher_timer(unsigned long data) */ void adreno_dispatcher_irq_fault(struct kgsl_device *device) { - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - - dispatcher->fault = ADRENO_DISPATCHER_HARD_FAULT; + adreno_set_gpu_fault(ADRENO_DEVICE(device), ADRENO_HARD_FAULT); adreno_dispatcher_schedule(device); } -/** - * adreno_dispatcher_pause() - stop the dispatcher - * @adreno_dev: pointer to the adreno device structure - * - * Pause the dispather so it doesn't accept any new commands - */ -void adreno_dispatcher_pause(struct adreno_device *adreno_dev) -{ - struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - - /* - * This will probably get called while holding other mutexes so don't - * take the dispatcher mutex. The biggest penalty is that another - * command might be submitted while we are in here but thats okay - * because whoever is waiting for the drain will just have another - * command batch to wait for - */ - - dispatcher->state = ADRENO_DISPATCHER_PAUSE; -} - /** * adreno_dispatcher_start() - activate the dispatcher * @adreno_dev: pointer to the adreno device structure * * Set the disaptcher active and start the loop once to get things going */ -void adreno_dispatcher_start(struct adreno_device *adreno_dev) +void adreno_dispatcher_start(struct kgsl_device *device) { - struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher; - - dispatcher->state = ADRENO_DISPATCHER_ACTIVE; + complete_all(&device->cmdbatch_gate); /* Schedule the work loop to get things going */ - adreno_dispatcher_schedule(&adreno_dev->dev); + adreno_dispatcher_schedule(device); } /** @@ -1247,9 +1507,6 @@ void adreno_dispatcher_close(struct adreno_device *adreno_dev) % ADRENO_DISPATCH_CMDQUEUE_SIZE; } - kfree(fault_detect_regs); - fault_detect_regs = NULL; - mutex_unlock(&dispatcher->mutex); kobject_put(&dispatcher->kobj); @@ -1400,16 +1657,8 @@ int adreno_dispatcher_init(struct adreno_device *adreno_dev) plist_head_init(&dispatcher->pending); spin_lock_init(&dispatcher->plist_lock); - dispatcher->state = ADRENO_DISPATCHER_ACTIVE; - ret = kobject_init_and_add(&dispatcher->kobj, &ktype_dispatcher, &device->dev->kobj, "dispatch"); - fault_detect_regs = kzalloc(FT_DETECT_REGS_COUNT * sizeof(unsigned int), - GFP_KERNEL); - - if (fault_detect_regs == NULL) - ret = -ENOMEM; - return ret; } diff --git a/drivers/gpu/msm/adreno_drawctxt.c b/drivers/gpu/msm/adreno_drawctxt.c index 55802c62fe0..a62c96ceb3e 100644 --- a/drivers/gpu/msm/adreno_drawctxt.c +++ b/drivers/gpu/msm/adreno_drawctxt.c @@ -293,7 +293,10 @@ int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev, /* Needs to hold the device mutex */ BUG_ON(!mutex_is_locked(&device->mutex)); - _kgsl_context_get(context); + if (!_kgsl_context_get(context)) { + ret = -EINVAL; + goto done; + } trace_adreno_drawctxt_wait_start(KGSL_MEMSTORE_GLOBAL, timestamp); @@ -307,7 +310,7 @@ int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev, mutex_unlock(&device->mutex); if (timeout) { - ret = (int) wait_event_interruptible_timeout(drawctxt->waiting, + ret = (int) wait_event_timeout(drawctxt->waiting, _check_global_timestamp(device, timestamp), msecs_to_jiffies(timeout)); @@ -316,7 +319,7 @@ int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev, else if (ret > 0) ret = 0; } else { - ret = (int) wait_event_interruptible(drawctxt->waiting, + wait_event(drawctxt->waiting, _check_global_timestamp(device, timestamp)); } @@ -348,6 +351,18 @@ void adreno_drawctxt_invalidate(struct kgsl_device *device, /* Clear the pending queue */ mutex_lock(&drawctxt->mutex); + /* + * set the timestamp to the last value since the context is invalidated + * and we want the pending events for this context to go away + */ + kgsl_sharedmem_writel(device, &device->memstore, + KGSL_MEMSTORE_OFFSET(context->id, soptimestamp), + drawctxt->timestamp); + + kgsl_sharedmem_writel(device, &device->memstore, + KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), + drawctxt->timestamp); + while (drawctxt->cmdqueue_head != drawctxt->cmdqueue_tail) { struct kgsl_cmdbatch *cmdbatch = drawctxt->cmdqueue[drawctxt->cmdqueue_head]; @@ -375,17 +390,14 @@ void adreno_drawctxt_invalidate(struct kgsl_device *device, /** * adreno_drawctxt_create - create a new adreno draw context - * @device - KGSL device to create the context on - * @pagetable - Pagetable for the context - * @context- Generic KGSL context structure - * @flags - flags for the context (passed from user space) + * @dev_priv: the owner of the context + * @flags: flags for the context (passed from user space) * - * Create a new draw context for the 3D core. Return 0 on success, - * or error code on failure. + * Create and return a new draw context for the 3D core. */ - struct kgsl_context * +struct kgsl_context * adreno_drawctxt_create(struct kgsl_device_private *dev_priv, - uint32_t *flags) + uint32_t *flags) { struct adreno_context *drawctxt; struct kgsl_device *device = dev_priv->device; @@ -393,7 +405,6 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, int ret; drawctxt = kzalloc(sizeof(struct adreno_context), GFP_KERNEL); - if (drawctxt == NULL) return ERR_PTR(-ENOMEM); @@ -444,20 +455,31 @@ adreno_drawctxt_create(struct kgsl_device_private *dev_priv, drawctxt->type = (*flags & KGSL_CONTEXT_TYPE_MASK) >> KGSL_CONTEXT_TYPE_SHIFT; - ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt); - if (ret) + if (adreno_dev->gpudev->ctxt_create) { + ret = adreno_dev->gpudev->ctxt_create(adreno_dev, drawctxt); + if (ret) + goto err; + } else if ((*flags & KGSL_CONTEXT_PREAMBLE) == 0 || + (*flags & KGSL_CONTEXT_NO_GMEM_ALLOC) == 0) { + KGSL_DEV_ERR_ONCE(device, + "legacy context switch not supported\n"); + ret = -EINVAL; goto err; - kgsl_sharedmem_writel(&device->memstore, + } else { + drawctxt->ops = &adreno_preamble_ctx_ops; + } + + kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, soptimestamp), 0); - kgsl_sharedmem_writel(&device->memstore, + kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(drawctxt->base.id, eoptimestamp), 0); return &drawctxt->base; err: - kgsl_context_put(&drawctxt->base); + kgsl_context_detach(&drawctxt->base); return ERR_PTR(ret); } @@ -496,19 +518,8 @@ int adreno_drawctxt_detach(struct kgsl_context *context) drawctxt = ADRENO_CONTEXT(context); /* deactivate context */ - if (adreno_dev->drawctxt_active == drawctxt) { - /* no need to save GMEM or shader, the context is - * being destroyed. - */ - drawctxt->flags &= ~(CTXT_FLAGS_GMEM_SAVE | - CTXT_FLAGS_SHADER_SAVE | - CTXT_FLAGS_GMEM_SHADOW | - CTXT_FLAGS_STATE_SHADOW); - - drawctxt->flags |= CTXT_FLAGS_BEING_DESTROYED; - + if (adreno_dev->drawctxt_active == drawctxt) adreno_drawctxt_switch(adreno_dev, NULL, 0); - } mutex_lock(&drawctxt->mutex); @@ -532,14 +543,36 @@ int adreno_drawctxt_detach(struct kgsl_context *context) } mutex_unlock(&drawctxt->mutex); + /* + * internal_timestamp is set in adreno_ringbuffer_addcmds, + * which holds the device mutex. The entire context destroy + * process requires the device mutex as well. But lets + * make sure we notice if the locking changes. + */ + BUG_ON(!mutex_is_locked(&device->mutex)); /* Wait for the last global timestamp to pass before continuing */ ret = adreno_drawctxt_wait_global(adreno_dev, context, drawctxt->internal_timestamp, 10 * 1000); + kgsl_sharedmem_writel(device, &device->memstore, + KGSL_MEMSTORE_OFFSET(context->id, soptimestamp), + drawctxt->timestamp); + + kgsl_sharedmem_writel(device, &device->memstore, + KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), + drawctxt->timestamp); + kgsl_sharedmem_free(&drawctxt->gpustate); kgsl_sharedmem_free(&drawctxt->context_gmem_shadow.gmemshadow); + if (drawctxt->ops->detach) + drawctxt->ops->detach(drawctxt); + + /* wake threads waiting to submit commands from this context */ + wake_up_interruptible_all(&drawctxt->waiting); + wake_up_interruptible_all(&drawctxt->wq); + return ret; } @@ -554,6 +587,69 @@ void adreno_drawctxt_destroy(struct kgsl_context *context) kfree(drawctxt); } + +/** + * adreno_context_restore() - generic context restore handler + * @adreno_dev: the device + * @context: the context + * + * Basic context restore handler that writes the context identifier + * to the ringbuffer and issues pagetable switch commands if necessary. + * May be called directly from the adreno_context_ops.restore function + * pointer or as the first action in a hardware specific restore + * function. + */ +int adreno_context_restore(struct adreno_device *adreno_dev, + struct adreno_context *context) +{ + int ret; + struct kgsl_device *device; + unsigned int cmds[5]; + + if (adreno_dev == NULL || context == NULL) + return -EINVAL; + + device = &adreno_dev->dev; + /* write the context identifier to the ringbuffer */ + cmds[0] = cp_nop_packet(1); + cmds[1] = KGSL_CONTEXT_TO_MEM_IDENTIFIER; + cmds[2] = cp_type3_packet(CP_MEM_WRITE, 2); + cmds[3] = device->memstore.gpuaddr + + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context); + cmds[4] = context->base.id; + ret = adreno_ringbuffer_issuecmds(device, context, KGSL_CMD_FLAGS_NONE, + cmds, 5); + if (ret) + return ret; + + return kgsl_mmu_setstate(&device->mmu, + context->base.proc_priv->pagetable, + context->base.id); +} + + +const struct adreno_context_ops adreno_preamble_ctx_ops = { + .restore = adreno_context_restore, +}; + +/** + * context_save() - save old context when necessary + * @drawctxt - the old context + * + * For legacy context switching, we need to issue save + * commands unless the context is being destroyed. + */ +static inline int context_save(struct adreno_device *adreno_dev, + struct adreno_context *context) +{ + if (context->ops->save == NULL + || kgsl_context_detached(&context->base) + || context->state == ADRENO_CONTEXT_STATE_INVALID) + return 0; + + return context->ops->save(adreno_dev, context); +} + /** * adreno_drawctxt_set_bin_base_offset - set bin base offset for the context * @device - KGSL device that owns the context @@ -592,6 +688,12 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev, int ret = 0; if (drawctxt) { + /* + * Handle legacy gmem / save restore flag on each IB. + * Userspace sets to guard IB sequences that require + * gmem to be saved and clears it at the end of the + * sequence. + */ if (flags & KGSL_CONTEXT_SAVE_GMEM) /* Set the flag in context so that the save is done * when this context is switched out. */ @@ -603,44 +705,52 @@ int adreno_drawctxt_switch(struct adreno_device *adreno_dev, /* already current? */ if (adreno_dev->drawctxt_active == drawctxt) { - if (adreno_dev->gpudev->ctxt_draw_workaround && - adreno_is_a225(adreno_dev)) - ret = adreno_dev->gpudev->ctxt_draw_workaround( - adreno_dev, drawctxt); + if (drawctxt && drawctxt->ops->draw_workaround) + ret = drawctxt->ops->draw_workaround(adreno_dev, + drawctxt); return ret; } - KGSL_CTXT_INFO(device, "from %d to %d flags %d\n", - adreno_dev->drawctxt_active ? - adreno_dev->drawctxt_active->base.id : 0, - drawctxt ? drawctxt->base.id : 0, flags); + trace_adreno_drawctxt_switch(adreno_dev->drawctxt_active, + drawctxt, flags); - /* Save the old context */ - ret = adreno_dev->gpudev->ctxt_save(adreno_dev, - adreno_dev->drawctxt_active); - - if (ret) { - KGSL_DRV_ERR(device, - "Error in GPU context %d save: %d\n", - adreno_dev->drawctxt_active->base.id, ret); - return ret; - } + if (adreno_dev->drawctxt_active) { + ret = context_save(adreno_dev, adreno_dev->drawctxt_active); + if (ret) { + KGSL_DRV_ERR(device, + "Error in GPU context %d save: %d\n", + adreno_dev->drawctxt_active->base.id, ret); + return ret; + } - /* Put the old instance of the active drawctxt */ - if (adreno_dev->drawctxt_active) + /* Put the old instance of the active drawctxt */ kgsl_context_put(&adreno_dev->drawctxt_active->base); + adreno_dev->drawctxt_active = NULL; + } /* Get a refcount to the new instance */ - if (drawctxt) - _kgsl_context_get(&drawctxt->base); - - /* Set the new context */ - ret = adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt); - if (ret) { - KGSL_DRV_ERR(device, - "Error in GPU context %d restore: %d\n", - drawctxt->base.id, ret); - return ret; + if (drawctxt) { + if (!_kgsl_context_get(&drawctxt->base)) + return -EINVAL; + + /* Set the new context */ + ret = drawctxt->ops->restore(adreno_dev, drawctxt); + if (ret) { + KGSL_DRV_ERR(device, + "Error in GPU context %d restore: %d\n", + drawctxt->base.id, ret); + return ret; + } + } else { + /* + * No context - set the default pagetable and thats it. + * If there isn't a current context, the kgsl_mmu_setstate + * will use the CPU path so we don't need to give + * it a valid context id. + */ + ret = kgsl_mmu_setstate(&device->mmu, + device->mmu.defaultpagetable, + KGSL_CONTEXT_INVALID); } adreno_dev->drawctxt_active = drawctxt; diff --git a/drivers/gpu/msm/adreno_drawctxt.h b/drivers/gpu/msm/adreno_drawctxt.h index dddc20629b7..9312db63bd1 100644 --- a/drivers/gpu/msm/adreno_drawctxt.h +++ b/drivers/gpu/msm/adreno_drawctxt.h @@ -46,8 +46,6 @@ #define CTXT_FLAGS_PER_CONTEXT_TS BIT(11) /* Context has caused a GPU hang and fault tolerance successful */ #define CTXT_FLAGS_GPU_HANG_FT BIT(12) -/* Context is being destroyed so dont save it */ -#define CTXT_FLAGS_BEING_DESTROYED BIT(13) /* User mode generated timestamps enabled */ #define CTXT_FLAGS_USER_GENERATED_TS BIT(14) /* Context skip till EOF */ @@ -102,11 +100,35 @@ struct gmem_shadow_t { struct kgsl_memdesc quad_vertices_restore; }; +struct adreno_context; + +/** + * struct adreno_context_ops - context state management functions + * @save: optional hook for saving context state + * @restore: required hook for restoring state, + * adreno_context_restore() may be used directly here. + * @draw_workaround: optional hook for a workaround after every IB + * @detach: optional hook for freeing state tracking memory. + */ +struct adreno_context_ops { + int (*save)(struct adreno_device *, struct adreno_context *); + int (*restore)(struct adreno_device *, struct adreno_context *); + int (*draw_workaround)(struct adreno_device *, + struct adreno_context *); + void (*detach)(struct adreno_context *); +}; + +int adreno_context_restore(struct adreno_device *, struct adreno_context *); + +/* generic context ops for preamble context switch */ +extern const struct adreno_context_ops adreno_preamble_ctx_ops; + /** * struct adreno_context - Adreno GPU draw context * @id: Unique integer ID of the context * @timestamp: Last issued context-specific timestamp * @internal_timestamp: Global timestamp of the last issued command + * NOTE: guarded by device->mutex, not drawctxt->mutex! * @state: Current state of the context * @flags: Bitfield controlling behavior of the context * @type: Context type (GL, CL, RS) @@ -139,6 +161,7 @@ struct gmem_shadow_t { * @wq: Workqueue structure for contexts to sleep pending room in the queue * @waiting: Workqueue structure for contexts waiting for a timestamp or event * @queued: Number of commands queued in the cmdqueue + * @ops: Context switch functions for this context. */ struct adreno_context { struct kgsl_context base; @@ -185,6 +208,8 @@ struct adreno_context { wait_queue_head_t waiting; int queued; + + const struct adreno_context_ops *ops; }; diff --git a/drivers/gpu/msm/adreno_pm4types.h b/drivers/gpu/msm/adreno_pm4types.h index a3fa3123265..e6ec91df079 100644 --- a/drivers/gpu/msm/adreno_pm4types.h +++ b/drivers/gpu/msm/adreno_pm4types.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2013, 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 @@ -177,6 +177,8 @@ /* Load a buffer with pre-fetch enabled */ #define CP_INDIRECT_BUFFER_PFE 0x3F +#define CP_EXEC_CL 0x31 + #define CP_LOADSTATE_DSTOFFSET_SHIFT 0x00000000 #define CP_LOADSTATE_STATESRC_SHIFT 0x00000010 #define CP_LOADSTATE_STATEBLOCKID_SHIFT 0x00000013 diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c index 8a166fe92f7..2c9b968a198 100644 --- a/drivers/gpu/msm/adreno_postmortem.c +++ b/drivers/gpu/msm/adreno_postmortem.c @@ -30,19 +30,19 @@ #define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100 struct pm_id_name { - uint32_t id; + enum adreno_regs id; char name[9]; }; static const struct pm_id_name pm0_types[] = { - {REG_PA_SC_AA_CONFIG, "RPASCAAC"}, - {REG_RBBM_PM_OVERRIDE2, "RRBBPMO2"}, - {REG_SCRATCH_REG2, "RSCRTRG2"}, - {REG_SQ_GPR_MANAGEMENT, "RSQGPRMN"}, - {REG_SQ_INST_STORE_MANAGMENT, "RSQINSTS"}, - {REG_TC_CNTL_STATUS, "RTCCNTLS"}, - {REG_TP0_CHICKEN, "RTP0CHCK"}, - {REG_CP_TIMESTAMP, "CP_TM_ST"}, + {ADRENO_REG_PA_SC_AA_CONFIG, "RPASCAAC"}, + {ADRENO_REG_RBBM_PM_OVERRIDE2, "RRBBPMO2"}, + {ADRENO_REG_SCRATCH_REG2, "RSCRTRG2"}, + {ADRENO_REG_SQ_GPR_MANAGEMENT, "RSQGPRMN"}, + {ADRENO_REG_SQ_INST_STORE_MANAGMENT, "RSQINSTS"}, + {ADRENO_REG_TC_CNTL_STATUS, "RTCCNTLS"}, + {ADRENO_REG_TP0_CHICKEN, "RTP0CHCK"}, + {ADRENO_REG_CP_TIMESTAMP, "CP_TM_ST"}, }; static const struct pm_id_name pm3_types[] = { @@ -68,6 +68,16 @@ static const struct pm_id_name pm3_types[] = { {CP_SET_PROTECTED_MODE, "ST_PRT_M"}, {CP_SET_SHADER_BASES, "ST_SHD_B"}, {CP_WAIT_FOR_IDLE, "WAIT4IDL"}, + {CP_WAIT_FOR_ME, "WAIT4ME"}, + {CP_WAIT_REG_EQ, "WAITRGEQ"}, +}; + +static const struct pm_id_name pm3_nop_values[] = { + {KGSL_CONTEXT_TO_MEM_IDENTIFIER, "CTX_SWCH"}, + {KGSL_CMD_IDENTIFIER, "CMD__EXT"}, + {KGSL_CMD_INTERNAL_IDENTIFIER, "CMD__INT"}, + {KGSL_START_OF_IB_IDENTIFIER, "IB_START"}, + {KGSL_END_OF_IB_IDENTIFIER, "IB___END"}, }; static uint32_t adreno_is_pm4_len(uint32_t word) @@ -78,8 +88,9 @@ static uint32_t adreno_is_pm4_len(uint32_t word) return (word >> 16) & 0x3FFF; } -static bool adreno_is_pm4_type(uint32_t word) +static bool adreno_is_pm4_type(struct kgsl_device *device, uint32_t word) { + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; if (word == INVALID_RB_CMD) @@ -90,7 +101,8 @@ static bool adreno_is_pm4_type(uint32_t word) if ((word & (3<<30)) == CP_TYPE0_PKT) { for (i = 0; i < ARRAY_SIZE(pm0_types); ++i) { - if ((word & 0x7FFF) == pm0_types[i].id) + if ((word & 0x7FFF) == adreno_getreg(adreno_dev, + pm0_types[i].id)) return 1; } return 0; @@ -129,6 +141,28 @@ static const char *adreno_pm4_name(uint32_t word) return "????????"; } +static bool adreno_is_pm3_nop_value(uint32_t word) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) { + if (word == pm3_nop_values[i].id) + return 1; + } + return 0; +} + +static const char *adreno_pm3_nop_name(uint32_t word) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pm3_nop_values); ++i) { + if (word == pm3_nop_values[i].id) + return pm3_nop_values[i].name; + } + return "????????"; +} + static void adreno_dump_regs(struct kgsl_device *device, const int *registers, int size) { @@ -157,11 +191,13 @@ static void adreno_dump_regs(struct kgsl_device *device, } } -static void dump_ib(struct kgsl_device *device, char* buffId, uint32_t pt_base, - uint32_t base_offset, uint32_t ib_base, uint32_t ib_size, bool dump) +static void dump_ib(struct kgsl_device *device, char *buffId, + phys_addr_t pt_base, uint32_t base_offset, uint32_t ib_base, + uint32_t ib_size, bool dump) { + struct kgsl_mem_entry *ent = NULL; uint8_t *base_addr = adreno_convertaddr(device, pt_base, - ib_base, ib_size*sizeof(uint32_t)); + ib_base, ib_size*sizeof(uint32_t), &ent); if (base_addr && dump) print_hex_dump(KERN_ERR, buffId, DUMP_PREFIX_OFFSET, @@ -171,6 +207,10 @@ static void dump_ib(struct kgsl_device *device, char* buffId, uint32_t pt_base, "offset:%5.5X%s\n", buffId, ib_base, ib_size*4, base_offset, base_addr ? "" : " [Invalid]"); + if (ent) { + kgsl_memdesc_unmap(&ent->memdesc); + kgsl_mem_entry_put(ent); + } } #define IB_LIST_SIZE 64 @@ -181,7 +221,7 @@ struct ib_list { uint32_t offsets[IB_LIST_SIZE]; }; -static void dump_ib1(struct kgsl_device *device, uint32_t pt_base, +static void dump_ib1(struct kgsl_device *device, phys_addr_t pt_base, uint32_t base_offset, uint32_t ib1_base, uint32_t ib1_size, struct ib_list *ib_list, bool dump) @@ -189,13 +229,14 @@ static void dump_ib1(struct kgsl_device *device, uint32_t pt_base, int i, j; uint32_t value; uint32_t *ib1_addr; + struct kgsl_mem_entry *ent = NULL; dump_ib(device, "IB1:", pt_base, base_offset, ib1_base, ib1_size, dump); /* fetch virtual address for given IB base */ ib1_addr = (uint32_t *)adreno_convertaddr(device, pt_base, - ib1_base, ib1_size*sizeof(uint32_t)); + ib1_base, ib1_size*sizeof(uint32_t), &ent); if (!ib1_addr) return; @@ -222,10 +263,14 @@ static void dump_ib1(struct kgsl_device *device, uint32_t pt_base, ++ib_list->count; } } + if (ent) { + kgsl_memdesc_unmap(&ent->memdesc); + kgsl_mem_entry_put(ent); + } } -static void adreno_dump_rb_buffer(const void *buf, size_t len, - char *linebuf, size_t linebuflen, int *argp) +static void adreno_dump_rb_buffer(struct kgsl_device *device, const void *buf, + size_t len, char *linebuf, size_t linebuflen, int *argp) { const u32 *ptr4 = buf; const int ngroups = len; @@ -240,13 +285,18 @@ static void adreno_dump_rb_buffer(const void *buf, size_t len, lx += scnprintf(linebuf + lx, linebuflen - lx, " "); else nxsp = 1; - if (!*argp && adreno_is_pm4_type(ptr4[j])) { + if (!*argp && adreno_is_pm4_type(device, ptr4[j])) { lx += scnprintf(linebuf + lx, linebuflen - lx, "%s", adreno_pm4_name(ptr4[j])); *argp = -(adreno_is_pm4_len(ptr4[j])+1); } else { - lx += scnprintf(linebuf + lx, linebuflen - lx, - "%8.8X", ptr4[j]); + if (adreno_is_pm3_nop_value(ptr4[j])) + lx += scnprintf(linebuf + lx, linebuflen - lx, + "%s", adreno_pm3_nop_name(ptr4[j])); + else + lx += scnprintf(linebuf + lx, linebuflen - lx, + "%8.8X", ptr4[j]); + if (*argp > 1) --*argp; else if (*argp == 1) { @@ -287,18 +337,13 @@ void adreno_dump_rb(struct kgsl_device *device, const void *buf, hex_dump_to_buffer(ptr+i, linelen*4, rowsize*4, 4, linebuf, sizeof(linebuf), 0); else - adreno_dump_rb_buffer(ptr+i, linelen, linebuf, + adreno_dump_rb_buffer(device, ptr+i, linelen, linebuf, sizeof(linebuf), &args); KGSL_LOG_DUMP(device, "RB: %4.4X:%s\n", (start+i)%size, linebuf); } } -struct log_field { - bool show; - const char *display; -}; - static int adreno_dump_fields_line(struct kgsl_device *device, const char *start, char *str, int slen, const struct log_field **lines, @@ -333,7 +378,7 @@ static int adreno_dump_fields_line(struct kgsl_device *device, return num; } -static void adreno_dump_fields(struct kgsl_device *device, +void adreno_dump_fields(struct kgsl_device *device, const char *start, const struct log_field *lines, int num) { @@ -353,335 +398,13 @@ static void adreno_dump_fields(struct kgsl_device *device, sstr = " "; } } - -static void adreno_dump_a3xx(struct kgsl_device *device) -{ - unsigned int r1, r2, r3, rbbm_status; - unsigned int cp_stat, rb_count; - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - - kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status); - KGSL_LOG_DUMP(device, "RBBM: STATUS = %08X\n", rbbm_status); - - { - struct log_field lines[] = { - {rbbm_status & BIT(0), "HI busy "}, - {rbbm_status & BIT(1), "CP ME busy "}, - {rbbm_status & BIT(2), "CP PFP busy "}, - {rbbm_status & BIT(14), "CP NRT busy "}, - {rbbm_status & BIT(15), "VBIF busy "}, - {rbbm_status & BIT(16), "TSE busy "}, - {rbbm_status & BIT(17), "RAS busy "}, - {rbbm_status & BIT(18), "RB busy "}, - {rbbm_status & BIT(19), "PC DCALL bsy"}, - {rbbm_status & BIT(20), "PC VSD busy "}, - {rbbm_status & BIT(21), "VFD busy "}, - {rbbm_status & BIT(22), "VPC busy "}, - {rbbm_status & BIT(23), "UCHE busy "}, - {rbbm_status & BIT(24), "SP busy "}, - {rbbm_status & BIT(25), "TPL1 busy "}, - {rbbm_status & BIT(26), "MARB busy "}, - {rbbm_status & BIT(27), "VSC busy "}, - {rbbm_status & BIT(28), "ARB busy "}, - {rbbm_status & BIT(29), "HLSQ busy "}, - {rbbm_status & BIT(30), "GPU bsy noHC"}, - {rbbm_status & BIT(31), "GPU busy "}, - }; - adreno_dump_fields(device, " STATUS=", lines, - ARRAY_SIZE(lines)); - } - - kgsl_regread(device, REG_CP_RB_BASE, &r1); - kgsl_regread(device, REG_CP_RB_CNTL, &r2); - rb_count = 2 << (r2 & (BIT(6) - 1)); - kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3); - KGSL_LOG_DUMP(device, - "CP_RB: BASE = %08X | CNTL = %08X | RPTR_ADDR = %08X" - "| rb_count = %08X\n", r1, r2, r3, rb_count); - - kgsl_regread(device, REG_CP_RB_RPTR, &r1); - kgsl_regread(device, REG_CP_RB_WPTR, &r2); - kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3); - KGSL_LOG_DUMP(device, - " RPTR = %08X | WPTR = %08X | RPTR_WR = %08X" - "\n", r1, r2, r3); - - kgsl_regread(device, REG_CP_IB1_BASE, &r1); - kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2); - KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ = %d\n", r1, r2); - - kgsl_regread(device, REG_CP_ME_CNTL, &r1); - kgsl_regread(device, REG_CP_ME_STATUS, &r2); - KGSL_LOG_DUMP(device, "CP_ME: CNTL = %08X | STATUS = %08X\n", r1, r2); - - kgsl_regread(device, REG_CP_STAT, &cp_stat); - KGSL_LOG_DUMP(device, "CP_STAT = %08X\n", cp_stat); -#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL - { - struct log_field lns[] = { - {cp_stat & BIT(0), "WR_BSY 0"}, - {cp_stat & BIT(1), "RD_RQ_BSY 1"}, - {cp_stat & BIT(2), "RD_RTN_BSY 2"}, - }; - adreno_dump_fields(device, " MIU=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(5), "RING_BUSY 5"}, - {cp_stat & BIT(6), "NDRCTS_BSY 6"}, - {cp_stat & BIT(7), "NDRCT2_BSY 7"}, - {cp_stat & BIT(9), "ST_BUSY 9"}, - {cp_stat & BIT(10), "BUSY 10"}, - }; - adreno_dump_fields(device, " CSF=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(11), "RNG_Q_BSY 11"}, - {cp_stat & BIT(12), "NDRCTS_Q_B12"}, - {cp_stat & BIT(13), "NDRCT2_Q_B13"}, - {cp_stat & BIT(16), "ST_QUEUE_B16"}, - {cp_stat & BIT(17), "PFP_BUSY 17"}, - }; - adreno_dump_fields(device, " RING=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(3), "RBIU_BUSY 3"}, - {cp_stat & BIT(4), "RCIU_BUSY 4"}, - {cp_stat & BIT(8), "EVENT_BUSY 8"}, - {cp_stat & BIT(18), "MQ_RG_BSY 18"}, - {cp_stat & BIT(19), "MQ_NDRS_BS19"}, - {cp_stat & BIT(20), "MQ_NDR2_BS20"}, - {cp_stat & BIT(21), "MIU_WC_STL21"}, - {cp_stat & BIT(22), "CP_NRT_BSY22"}, - {cp_stat & BIT(23), "3D_BUSY 23"}, - {cp_stat & BIT(26), "ME_BUSY 26"}, - {cp_stat & BIT(27), "RB_FFO_BSY27"}, - {cp_stat & BIT(28), "CF_FFO_BSY28"}, - {cp_stat & BIT(29), "PS_FFO_BSY29"}, - {cp_stat & BIT(30), "VS_FFO_BSY30"}, - {cp_stat & BIT(31), "CP_BUSY 31"}, - }; - adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns)); - } -#endif - - kgsl_regread(device, A3XX_RBBM_INT_0_STATUS, &r1); - KGSL_LOG_DUMP(device, "MSTR_INT_SGNL = %08X\n", r1); - { - struct log_field ints[] = { - {r1 & BIT(0), "RBBM_GPU_IDLE 0"}, - {r1 & BIT(1), "RBBM_AHB_ERROR 1"}, - {r1 & BIT(2), "RBBM_REG_TIMEOUT 2"}, - {r1 & BIT(3), "RBBM_ME_MS_TIMEOUT 3"}, - {r1 & BIT(4), "RBBM_PFP_MS_TIMEOUT 4"}, - {r1 & BIT(5), "RBBM_ATB_BUS_OVERFLOW 5"}, - {r1 & BIT(6), "VFD_ERROR 6"}, - {r1 & BIT(7), "CP_SW_INT 7"}, - {r1 & BIT(8), "CP_T0_PACKET_IN_IB 8"}, - {r1 & BIT(9), "CP_OPCODE_ERROR 9"}, - {r1 & BIT(10), "CP_RESERVED_BIT_ERROR 10"}, - {r1 & BIT(11), "CP_HW_FAULT 11"}, - {r1 & BIT(12), "CP_DMA 12"}, - {r1 & BIT(13), "CP_IB2_INT 13"}, - {r1 & BIT(14), "CP_IB1_INT 14"}, - {r1 & BIT(15), "CP_RB_INT 15"}, - {r1 & BIT(16), "CP_REG_PROTECT_FAULT 16"}, - {r1 & BIT(17), "CP_RB_DONE_TS 17"}, - {r1 & BIT(18), "CP_VS_DONE_TS 18"}, - {r1 & BIT(19), "CP_PS_DONE_TS 19"}, - {r1 & BIT(20), "CACHE_FLUSH_TS 20"}, - {r1 & BIT(21), "CP_AHB_ERROR_HALT 21"}, - {r1 & BIT(24), "MISC_HANG_DETECT 24"}, - {r1 & BIT(25), "UCHE_OOB_ACCESS 25"}, - }; - adreno_dump_fields(device, "INT_SGNL=", ints, ARRAY_SIZE(ints)); - } -} - -static void adreno_dump_a2xx(struct kgsl_device *device) -{ - unsigned int r1, r2, r3, rbbm_status; - unsigned int cp_stat, rb_count; - struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - - kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status); - - kgsl_regread(device, REG_RBBM_PM_OVERRIDE1, &r2); - kgsl_regread(device, REG_RBBM_PM_OVERRIDE2, &r3); - KGSL_LOG_DUMP(device, "RBBM: STATUS = %08X | PM_OVERRIDE1 = %08X | " - "PM_OVERRIDE2 = %08X\n", rbbm_status, r2, r3); - - kgsl_regread(device, REG_RBBM_INT_CNTL, &r1); - kgsl_regread(device, REG_RBBM_INT_STATUS, &r2); - kgsl_regread(device, REG_RBBM_READ_ERROR, &r3); - KGSL_LOG_DUMP(device, " INT_CNTL = %08X | INT_STATUS = %08X | " - "READ_ERROR = %08X\n", r1, r2, r3); - - { - char cmdFifo[16]; - struct log_field lines[] = { - {rbbm_status & 0x001F, cmdFifo}, - {rbbm_status & BIT(5), "TC busy "}, - {rbbm_status & BIT(8), "HIRQ pending"}, - {rbbm_status & BIT(9), "CPRQ pending"}, - {rbbm_status & BIT(10), "CFRQ pending"}, - {rbbm_status & BIT(11), "PFRQ pending"}, - {rbbm_status & BIT(12), "VGT 0DMA bsy"}, - {rbbm_status & BIT(14), "RBBM WU busy"}, - {rbbm_status & BIT(16), "CP NRT busy "}, - {rbbm_status & BIT(18), "MH busy "}, - {rbbm_status & BIT(19), "MH chncy bsy"}, - {rbbm_status & BIT(21), "SX busy "}, - {rbbm_status & BIT(22), "TPC busy "}, - {rbbm_status & BIT(24), "SC CNTX busy"}, - {rbbm_status & BIT(25), "PA busy "}, - {rbbm_status & BIT(26), "VGT busy "}, - {rbbm_status & BIT(27), "SQ cntx1 bsy"}, - {rbbm_status & BIT(28), "SQ cntx0 bsy"}, - {rbbm_status & BIT(30), "RB busy "}, - {rbbm_status & BIT(31), "Grphs pp bsy"}, - }; - snprintf(cmdFifo, sizeof(cmdFifo), "CMD FIFO=%01X ", - rbbm_status & 0xf); - adreno_dump_fields(device, " STATUS=", lines, - ARRAY_SIZE(lines)); - } - - kgsl_regread(device, REG_CP_RB_BASE, &r1); - kgsl_regread(device, REG_CP_RB_CNTL, &r2); - rb_count = 2 << (r2 & (BIT(6)-1)); - kgsl_regread(device, REG_CP_RB_RPTR_ADDR, &r3); - KGSL_LOG_DUMP(device, - "CP_RB: BASE = %08X | CNTL = %08X | RPTR_ADDR = %08X" - "| rb_count = %08X\n", r1, r2, r3, rb_count); - { - struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; - if (rb->sizedwords != rb_count) - rb_count = rb->sizedwords; - } - - kgsl_regread(device, REG_CP_RB_RPTR, &r1); - kgsl_regread(device, REG_CP_RB_WPTR, &r2); - kgsl_regread(device, REG_CP_RB_RPTR_WR, &r3); - KGSL_LOG_DUMP(device, - " RPTR = %08X | WPTR = %08X | RPTR_WR = %08X" - "\n", r1, r2, r3); - - kgsl_regread(device, REG_CP_IB1_BASE, &r1); - kgsl_regread(device, REG_CP_IB1_BUFSZ, &r2); - KGSL_LOG_DUMP(device, "CP_IB1: BASE = %08X | BUFSZ = %d\n", r1, r2); - - kgsl_regread(device, REG_CP_IB2_BASE, &r1); - kgsl_regread(device, REG_CP_IB2_BUFSZ, &r2); - KGSL_LOG_DUMP(device, "CP_IB2: BASE = %08X | BUFSZ = %d\n", r1, r2); - - kgsl_regread(device, REG_CP_INT_CNTL, &r1); - kgsl_regread(device, REG_CP_INT_STATUS, &r2); - KGSL_LOG_DUMP(device, "CP_INT: CNTL = %08X | STATUS = %08X\n", r1, r2); - - kgsl_regread(device, REG_CP_ME_CNTL, &r1); - kgsl_regread(device, REG_CP_ME_STATUS, &r2); - kgsl_regread(device, REG_MASTER_INT_SIGNAL, &r3); - KGSL_LOG_DUMP(device, - "CP_ME: CNTL = %08X | STATUS = %08X | MSTR_INT_SGNL = " - "%08X\n", r1, r2, r3); - - kgsl_regread(device, REG_CP_STAT, &cp_stat); - KGSL_LOG_DUMP(device, "CP_STAT = %08X\n", cp_stat); -#ifndef CONFIG_MSM_KGSL_PSTMRTMDMP_CP_STAT_NO_DETAIL - { - struct log_field lns[] = { - {cp_stat & BIT(0), "WR_BSY 0"}, - {cp_stat & BIT(1), "RD_RQ_BSY 1"}, - {cp_stat & BIT(2), "RD_RTN_BSY 2"}, - }; - adreno_dump_fields(device, " MIU=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(5), "RING_BUSY 5"}, - {cp_stat & BIT(6), "NDRCTS_BSY 6"}, - {cp_stat & BIT(7), "NDRCT2_BSY 7"}, - {cp_stat & BIT(9), "ST_BUSY 9"}, - {cp_stat & BIT(10), "BUSY 10"}, - }; - adreno_dump_fields(device, " CSF=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(11), "RNG_Q_BSY 11"}, - {cp_stat & BIT(12), "NDRCTS_Q_B12"}, - {cp_stat & BIT(13), "NDRCT2_Q_B13"}, - {cp_stat & BIT(16), "ST_QUEUE_B16"}, - {cp_stat & BIT(17), "PFP_BUSY 17"}, - }; - adreno_dump_fields(device, " RING=", lns, ARRAY_SIZE(lns)); - } - { - struct log_field lns[] = { - {cp_stat & BIT(3), "RBIU_BUSY 3"}, - {cp_stat & BIT(4), "RCIU_BUSY 4"}, - {cp_stat & BIT(18), "MQ_RG_BSY 18"}, - {cp_stat & BIT(19), "MQ_NDRS_BS19"}, - {cp_stat & BIT(20), "MQ_NDR2_BS20"}, - {cp_stat & BIT(21), "MIU_WC_STL21"}, - {cp_stat & BIT(22), "CP_NRT_BSY22"}, - {cp_stat & BIT(23), "3D_BUSY 23"}, - {cp_stat & BIT(26), "ME_BUSY 26"}, - {cp_stat & BIT(29), "ME_WC_BSY 29"}, - {cp_stat & BIT(30), "MIU_FF EM 30"}, - {cp_stat & BIT(31), "CP_BUSY 31"}, - }; - adreno_dump_fields(device, " CP_STT=", lns, ARRAY_SIZE(lns)); - } -#endif - - kgsl_regread(device, REG_SCRATCH_REG0, &r1); - KGSL_LOG_DUMP(device, "SCRATCH_REG0 = %08X\n", r1); - - kgsl_regread(device, REG_COHER_SIZE_PM4, &r1); - kgsl_regread(device, REG_COHER_BASE_PM4, &r2); - kgsl_regread(device, REG_COHER_STATUS_PM4, &r3); - KGSL_LOG_DUMP(device, - "COHER: SIZE_PM4 = %08X | BASE_PM4 = %08X | STATUS_PM4" - " = %08X\n", r1, r2, r3); - - kgsl_regread(device, MH_AXI_ERROR, &r1); - KGSL_LOG_DUMP(device, "MH: AXI_ERROR = %08X\n", r1); - - kgsl_regread(device, MH_MMU_PAGE_FAULT, &r1); - kgsl_regread(device, MH_MMU_CONFIG, &r2); - kgsl_regread(device, MH_MMU_MPU_BASE, &r3); - KGSL_LOG_DUMP(device, - "MH_MMU: PAGE_FAULT = %08X | CONFIG = %08X | MPU_BASE =" - " %08X\n", r1, r2, r3); - - kgsl_regread(device, MH_MMU_MPU_END, &r1); - kgsl_regread(device, MH_MMU_VA_RANGE, &r2); - r3 = kgsl_mmu_get_current_ptbase(&device->mmu); - KGSL_LOG_DUMP(device, - " MPU_END = %08X | VA_RANGE = %08X | PT_BASE =" - " %08X\n", r1, r2, r3); - - KGSL_LOG_DUMP(device, "PAGETABLE SIZE: %08X ", - kgsl_mmu_get_ptsize()); - - kgsl_regread(device, MH_MMU_TRAN_ERROR, &r1); - KGSL_LOG_DUMP(device, " TRAN_ERROR = %08X\n", r1); - - kgsl_regread(device, MH_INTERRUPT_MASK, &r1); - kgsl_regread(device, MH_INTERRUPT_STATUS, &r2); - KGSL_LOG_DUMP(device, - "MH_INTERRUPT: MASK = %08X | STATUS = %08X\n", r1, r2); -} +EXPORT_SYMBOL(adreno_dump_fields); int adreno_dump(struct kgsl_device *device, int manual) { - unsigned int cp_ib1_base, cp_ib1_bufsz; - unsigned int cp_ib2_base, cp_ib2_bufsz; - unsigned int pt_base, cur_pt_base; + unsigned int cp_ib1_base; + unsigned int cp_ib2_base; + phys_addr_t pt_base, cur_pt_base; unsigned int cp_rb_base, cp_rb_ctrl, rb_count; unsigned int cp_rb_wptr, cp_rb_rptr; unsigned int i; @@ -693,7 +416,6 @@ int adreno_dump(struct kgsl_device *device, int manual) unsigned int ts_processed = 0xdeaddead; struct kgsl_context *context; unsigned int context_id; - unsigned int rbbm_status; static struct ib_list ib_list; @@ -703,42 +425,31 @@ int adreno_dump(struct kgsl_device *device, int manual) mb(); - if (device->pm_dump_enable) { - if (adreno_is_a2xx(adreno_dev)) - adreno_dump_a2xx(device); - else if (adreno_is_a3xx(adreno_dev)) - adreno_dump_a3xx(device); - } - - kgsl_regread(device, adreno_dev->gpudev->reg_rbbm_status, &rbbm_status); + if (adreno_dev->gpudev->postmortem_dump) + adreno_dev->gpudev->postmortem_dump(adreno_dev); pt_base = kgsl_mmu_get_current_ptbase(&device->mmu); cur_pt_base = pt_base; - kgsl_regread(device, REG_CP_RB_BASE, &cp_rb_base); - kgsl_regread(device, REG_CP_RB_CNTL, &cp_rb_ctrl); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_BASE), + &cp_rb_base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_CNTL), + &cp_rb_ctrl); rb_count = 2 << (cp_rb_ctrl & (BIT(6) - 1)); - kgsl_regread(device, REG_CP_RB_RPTR, &cp_rb_rptr); - kgsl_regread(device, REG_CP_RB_WPTR, &cp_rb_wptr); - kgsl_regread(device, REG_CP_IB1_BASE, &cp_ib1_base); - kgsl_regread(device, REG_CP_IB1_BUFSZ, &cp_ib1_bufsz); - kgsl_regread(device, REG_CP_IB2_BASE, &cp_ib2_base); - kgsl_regread(device, REG_CP_IB2_BUFSZ, &cp_ib2_bufsz); - - trace_adreno_gpu_fault(rbbm_status, cp_rb_rptr, cp_rb_wptr, - cp_ib1_base, cp_ib1_bufsz, cp_ib2_base, cp_ib2_bufsz); - - /* If postmortem dump is not enabled, dump minimal set and return */ - if (!device->pm_dump_enable) { - - KGSL_LOG_DUMP(device, - "RBBM STATUS %08X | IB1:%08X/%08X | IB2: %08X/%08X" - " | RPTR: %04X | WPTR: %04X\n", - rbbm_status, cp_ib1_base, cp_ib1_bufsz, cp_ib2_base, - cp_ib2_bufsz, cp_rb_rptr, cp_rb_wptr); - - return 0; - } + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_RPTR), + &cp_rb_rptr); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_RB_WPTR), + &cp_rb_wptr); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB1_BASE), + &cp_ib1_base); + kgsl_regread(device, + adreno_getreg(adreno_dev, ADRENO_REG_CP_IB2_BASE), + &cp_ib2_base); kgsl_sharedmem_readl(&device->memstore, (unsigned int *) &context_id, @@ -823,21 +534,26 @@ int adreno_dump(struct kgsl_device *device, int manual) (num_iommu_units && this_cmd == kgsl_mmu_get_reg_gpuaddr(&device->mmu, 0, KGSL_IOMMU_CONTEXT_USER, - KGSL_IOMMU_CTX_TTBR0))) { - KGSL_LOG_DUMP(device, "Current pagetable: %x\t" - "pagetable base: %x\n", + KGSL_IOMMU_CTX_TTBR0)) || + (num_iommu_units && this_cmd == cp_type0_packet( + kgsl_mmu_get_reg_ahbaddr( + &device->mmu, 0, + KGSL_IOMMU_CONTEXT_USER, + KGSL_IOMMU_CTX_TTBR0), 1))) { + KGSL_LOG_DUMP(device, + "Current pagetable: %x\t pagetable base: %pa\n", kgsl_mmu_get_ptname_from_ptbase(&device->mmu, cur_pt_base), - cur_pt_base); + &cur_pt_base); /* Set cur_pt_base to the new pagetable base */ cur_pt_base = rb_copy[read_idx++]; - KGSL_LOG_DUMP(device, "New pagetable: %x\t" - "pagetable base: %x\n", + KGSL_LOG_DUMP(device, + "New pagetable: %x\t pagetable base: %pa\n", kgsl_mmu_get_ptname_from_ptbase(&device->mmu, cur_pt_base), - cur_pt_base); + &cur_pt_base); } } @@ -898,7 +614,8 @@ int adreno_dump(struct kgsl_device *device, int manual) adreno_dump_regs(device, a3xx_registers, a3xx_registers_count); - if (adreno_is_a330(adreno_dev)) + if (adreno_is_a330(adreno_dev) || + adreno_is_a305b(adreno_dev)) adreno_dump_regs(device, a330_registers, a330_registers_count); } @@ -909,7 +626,7 @@ int adreno_dump(struct kgsl_device *device, int manual) end: /* Restart the dispatcher after a manually triggered dump */ if (manual) - adreno_dispatcher_start(adreno_dev); + adreno_dispatcher_start(device); return result; } diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c index ef696088eac..9e69a4954bb 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.c +++ b/drivers/gpu/msm/adreno_ringbuffer.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include "kgsl.h" #include "kgsl_sharedmem.h" @@ -38,6 +40,7 @@ void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb) { + struct adreno_device *adreno_dev = ADRENO_DEVICE(rb->device); BUG_ON(rb->wptr == 0); /* Let the pwrscale policy know that new commands have @@ -49,7 +52,7 @@ void adreno_ringbuffer_submit(struct adreno_ringbuffer *rb) */ mb(); - adreno_regwrite(rb->device, REG_CP_RB_WPTR, rb->wptr); + adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_WPTR, rb->wptr); } static int @@ -64,6 +67,7 @@ adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, unsigned long wait_time; unsigned long wait_timeout = msecs_to_jiffies(ADRENO_IDLE_TIMEOUT); unsigned long wait_time_part; + unsigned int rptr; /* if wptr ahead, fill the remaining with NOPs */ if (wptr_ahead) { @@ -73,19 +77,16 @@ adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, cmds = (unsigned int *)rb->buffer_desc.hostptr + rb->wptr; cmds_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*rb->wptr; - GSL_RB_WRITE(cmds, cmds_gpu, cp_nop_packet(nopcount)); + GSL_RB_WRITE(rb->device, cmds, cmds_gpu, + cp_nop_packet(nopcount)); /* Make sure that rptr is not 0 before submitting * commands at the end of ringbuffer. We do not * want the rptr and wptr to become equal when * the ringbuffer is not empty */ do { - GSL_RB_GET_READPTR(rb, &rb->rptr); - } while (!rb->rptr); - - rb->wptr++; - - adreno_ringbuffer_submit(rb); + rptr = adreno_get_rptr(rb); + } while (!rptr); rb->wptr = 0; } @@ -94,9 +95,9 @@ adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, wait_time_part = jiffies + msecs_to_jiffies(KGSL_TIMEOUT_PART); /* wait for space in ringbuffer */ while (1) { - GSL_RB_GET_READPTR(rb, &rb->rptr); + rptr = adreno_get_rptr(rb); - freecmds = rb->rptr - rb->wptr; + freecmds = rptr - rb->wptr; if (freecmds == 0 || freecmds > numcmds) break; @@ -104,7 +105,7 @@ adreno_ringbuffer_waitspace(struct adreno_ringbuffer *rb, if (time_after(jiffies, wait_time)) { KGSL_DRV_ERR(rb->device, "Timed out while waiting for freespace in ringbuffer " - "rptr: 0x%x, wptr: 0x%x\n", rb->rptr, rb->wptr); + "rptr: 0x%x, wptr: 0x%x\n", rptr, rb->wptr); return -ETIMEDOUT; } @@ -118,11 +119,12 @@ unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb, { unsigned int *ptr = NULL; int ret = 0; + unsigned int rptr; BUG_ON(numcmds >= rb->sizedwords); - GSL_RB_GET_READPTR(rb, &rb->rptr); + rptr = adreno_get_rptr(rb); /* check for available space */ - if (rb->wptr >= rb->rptr) { + if (rb->wptr >= rptr) { /* wptr ahead or equal to rptr */ /* reserve dwords for nop packet */ if ((rb->wptr + numcmds) > (rb->sizedwords - @@ -131,7 +133,7 @@ unsigned int *adreno_ringbuffer_allocspace(struct adreno_ringbuffer *rb, numcmds, 1); } else { /* wptr behind rptr */ - if ((rb->wptr + numcmds) >= rb->rptr) + if ((rb->wptr + numcmds) >= rptr) ret = adreno_ringbuffer_waitspace(rb, context, numcmds, 0); /* check for remaining space */ @@ -209,8 +211,16 @@ int adreno_ringbuffer_read_pm4_ucode(struct kgsl_device *device) return ret; } - -int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device) +/** + * adreno_ringbuffer_load_pm4_ucode() - Load pm4 ucode + * @device: Pointer to a KGSL device + * @start: Starting index in pm4 ucode to load + * @addr: Address to load the pm4 ucode + * + * Load the pm4 ucode from @start at @addr. + */ +int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device, + unsigned int start, unsigned int addr) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; @@ -224,11 +234,11 @@ int adreno_ringbuffer_load_pm4_ucode(struct kgsl_device *device) KGSL_DRV_INFO(device, "loading pm4 ucode version: %d\n", adreno_dev->pm4_fw_version); - adreno_regwrite(device, REG_CP_DEBUG, CP_DEBUG_DEFAULT); - adreno_regwrite(device, REG_CP_ME_RAM_WADDR, 0); + adreno_writereg(adreno_dev, ADRENO_REG_CP_DEBUG, CP_DEBUG_DEFAULT); + adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_RAM_WADDR, addr); for (i = 1; i < adreno_dev->pm4_fw_size; i++) - adreno_regwrite(device, REG_CP_ME_RAM_DATA, - adreno_dev->pm4_fw[i]); + adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_RAM_DATA, + adreno_dev->pm4_fw[i]); return 0; } @@ -264,7 +274,16 @@ int adreno_ringbuffer_read_pfp_ucode(struct kgsl_device *device) return ret; } -int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device) +/** + * adreno_ringbuffer_load_pfp_ucode() - Load pfp ucode + * @device: Pointer to a KGSL device + * @start: Starting index in pfp ucode to load + * @addr: Address to load the pfp ucode + * + * Load the pfp ucode from @start at @addr. + */ +int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device, + unsigned int start, unsigned int addr) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; @@ -278,16 +297,21 @@ int adreno_ringbuffer_load_pfp_ucode(struct kgsl_device *device) KGSL_DRV_INFO(device, "loading pfp ucode version: %d\n", adreno_dev->pfp_fw_version); - adreno_regwrite(device, adreno_dev->gpudev->reg_cp_pfp_ucode_addr, 0); + adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_ADDR, addr); for (i = 1; i < adreno_dev->pfp_fw_size; i++) - adreno_regwrite(device, - adreno_dev->gpudev->reg_cp_pfp_ucode_data, - adreno_dev->pfp_fw[i]); + adreno_writereg(adreno_dev, ADRENO_REG_CP_PFP_UCODE_DATA, + adreno_dev->pfp_fw[i]); return 0; } -int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) +/** + * _ringbuffer_start_common() - Ringbuffer start + * @rb: Pointer to adreno ringbuffer + * + * Setup ringbuffer for GPU. + */ +int _ringbuffer_start_common(struct adreno_ringbuffer *rb) { int status; union reg_cp_rb_cntl cp_rb_cntl; @@ -298,24 +322,24 @@ int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) if (rb->flags & KGSL_FLAGS_STARTED) return 0; - kgsl_sharedmem_set(&rb->memptrs_desc, 0, 0, + kgsl_sharedmem_set(rb->device, &rb->memptrs_desc, 0, 0, sizeof(struct kgsl_rbmemptrs)); - kgsl_sharedmem_set(&rb->buffer_desc, 0, 0xAA, + kgsl_sharedmem_set(rb->device, &rb->buffer_desc, 0, 0xAA, (rb->sizedwords << 2)); if (adreno_is_a2xx(adreno_dev)) { - adreno_regwrite(device, REG_CP_RB_WPTR_BASE, + kgsl_regwrite(device, REG_CP_RB_WPTR_BASE, (rb->memptrs_desc.gpuaddr + GSL_RB_MEMPTRS_WPTRPOLL_OFFSET)); /* setup WPTR delay */ - adreno_regwrite(device, REG_CP_RB_WPTR_DELAY, + kgsl_regwrite(device, REG_CP_RB_WPTR_DELAY, 0 /*0x70000010 */); } /*setup REG_CP_RB_CNTL */ - adreno_regread(device, REG_CP_RB_CNTL, &rb_cntl); + adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_CNTL, &rb_cntl); cp_rb_cntl.val = rb_cntl; /* @@ -339,72 +363,40 @@ int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) /* mem RPTR writebacks */ cp_rb_cntl.f.rb_no_update = GSL_RB_CNTL_NO_UPDATE; - adreno_regwrite(device, REG_CP_RB_CNTL, cp_rb_cntl.val); + adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_CNTL, cp_rb_cntl.val); - adreno_regwrite(device, REG_CP_RB_BASE, rb->buffer_desc.gpuaddr); + adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_BASE, + rb->buffer_desc.gpuaddr); - adreno_regwrite(device, REG_CP_RB_RPTR_ADDR, - rb->memptrs_desc.gpuaddr + - GSL_RB_MEMPTRS_RPTR_OFFSET); - - if (adreno_is_a3xx(adreno_dev)) { - /* enable access protection to privileged registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007); - - /* RBBM registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400); - - /* CP registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178); - adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180); - - /* RB registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300); - - /* VBIF registers */ - adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000); - } + adreno_writereg(adreno_dev, ADRENO_REG_CP_RB_RPTR_ADDR, + rb->memptrs_desc.gpuaddr + + GSL_RB_MEMPTRS_RPTR_OFFSET); if (adreno_is_a2xx(adreno_dev)) { /* explicitly clear all cp interrupts */ - adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF); + kgsl_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF); } /* setup scratch/timestamp */ - adreno_regwrite(device, REG_SCRATCH_ADDR, device->memstore.gpuaddr + - KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, - soptimestamp)); + adreno_writereg(adreno_dev, ADRENO_REG_SCRATCH_ADDR, + device->memstore.gpuaddr + + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, + soptimestamp)); - adreno_regwrite(device, REG_SCRATCH_UMSK, + adreno_writereg(adreno_dev, ADRENO_REG_SCRATCH_UMSK, GSL_RB_MEMPTRS_SCRATCH_MASK); - /* load the CP ucode */ - status = adreno_ringbuffer_load_pm4_ucode(device); - if (status != 0) - return status; - - /* load the prefetch parser ucode */ - status = adreno_ringbuffer_load_pfp_ucode(device); - if (status != 0) - return status; - /* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */ - if (adreno_is_a305(adreno_dev) || adreno_is_a320(adreno_dev)) - adreno_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602); + if (adreno_is_a305(adreno_dev) || adreno_is_a305c(adreno_dev) || + adreno_is_a320(adreno_dev)) + kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x000E0602); + else if (adreno_is_a330(adreno_dev) || adreno_is_a305b(adreno_dev)) + kgsl_regwrite(device, REG_CP_QUEUE_THRESHOLDS, 0x003E2008); - rb->rptr = 0; rb->wptr = 0; /* clear ME_HALT to start micro engine */ - adreno_regwrite(device, REG_CP_ME_CNTL, 0); + adreno_writereg(adreno_dev, ADRENO_REG_CP_ME_CNTL, 0); /* ME init is GPU specific, so jump into the sub-function */ status = adreno_dev->gpudev->rb_init(adreno_dev, rb); @@ -420,6 +412,54 @@ int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) return status; } +/** + * adreno_ringbuffer_warm_start() - Ringbuffer warm start + * @rb: Pointer to adreno ringbuffer + * + * Start the ringbuffer but load only jump tables part of the + * microcode. + */ +int adreno_ringbuffer_warm_start(struct adreno_ringbuffer *rb) +{ + int status; + struct kgsl_device *device = rb->device; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + + /* load the CP ucode */ + status = adreno_ringbuffer_load_pm4_ucode(device, + adreno_dev->pm4_jt_idx, adreno_dev->pm4_jt_addr); + if (status != 0) + return status; + + /* load the prefetch parser ucode */ + status = adreno_ringbuffer_load_pfp_ucode(device, + adreno_dev->pfp_jt_idx, adreno_dev->pfp_jt_addr); + if (status != 0) + return status; + + return _ringbuffer_start_common(rb); +} + +int adreno_ringbuffer_start(struct adreno_ringbuffer *rb) +{ + int status; + + if (rb->flags & KGSL_FLAGS_STARTED) + return 0; + + /* load the CP ucode */ + status = adreno_ringbuffer_load_pm4_ucode(rb->device, 1, 0); + if (status != 0) + return status; + + /* load the prefetch parser ucode */ + status = adreno_ringbuffer_load_pfp_ucode(rb->device, 1, 0); + if (status != 0) + return status; + + return _ringbuffer_start_common(rb); +} + void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb) { struct kgsl_device *device = rb->device; @@ -427,7 +467,7 @@ void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb) if (rb->flags & KGSL_FLAGS_STARTED) { if (adreno_is_a200(adreno_dev)) - adreno_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000); + kgsl_regwrite(rb->device, REG_CP_ME_CNTL, 0x10000000); rb->flags &= ~KGSL_FLAGS_STARTED; } @@ -506,7 +546,9 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, unsigned int context_id; unsigned int gpuaddr = rb->device->memstore.gpuaddr; - /* The global timestamp always needs to be incremented */ + if (drawctxt != NULL && kgsl_context_detached(&drawctxt->base)) + return -EINVAL; + rb->global_ts++; /* If this is a internal IB, use the global timestamp for it */ @@ -517,6 +559,12 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, context_id = drawctxt->base.id; } + /* + * Note that we cannot safely take drawctxt->mutex here without + * potential mutex inversion with device->mutex which is held + * here. As a result, any other code that accesses this variable + * must also use device->mutex. + */ if (drawctxt) drawctxt->internal_timestamp = rb->global_ts; @@ -532,8 +580,13 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, /* Add two dwords for the CP_INTERRUPT */ total_sizedwords += drawctxt ? 2 : 0; + /* context rollover */ if (adreno_is_a3xx(adreno_dev)) - total_sizedwords += 7; + total_sizedwords += 3; + + /* For HLSQ updates below */ + if (adreno_is_a4xx(adreno_dev) || adreno_is_a3xx(adreno_dev)) + total_sizedwords += 4; if (adreno_is_a2xx(adreno_dev)) total_sizedwords += 2; /* CP_WAIT_FOR_IDLE */ @@ -552,6 +605,10 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, if (flags & KGSL_CMD_FLAGS_WFI) total_sizedwords += 2; /* WFI */ + /* Add space for the power on shader fixup if we need it */ + if (flags & KGSL_CMD_FLAGS_PWRON_FIXUP) + total_sizedwords += 5; + ringcmds = adreno_ringbuffer_allocspace(rb, drawctxt, total_sizedwords); if (IS_ERR(ringcmds)) @@ -562,37 +619,51 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, rcmd_gpu = rb->buffer_desc.gpuaddr + sizeof(uint)*(rb->wptr-total_sizedwords); - GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, KGSL_CMD_IDENTIFIER); if (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_nop_packet(1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, KGSL_CMD_INTERNAL_IDENTIFIER); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + KGSL_CMD_INTERNAL_IDENTIFIER); + } + + if (flags & KGSL_CMD_FLAGS_PWRON_FIXUP) { + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_nop_packet(1)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + KGSL_PWRON_FIXUP_IDENTIFIER); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + CP_HDR_INDIRECT_BUFFER_PFD); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + adreno_dev->pwron_fixup.gpuaddr); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + adreno_dev->pwron_fixup_dwords); } /* start-of-pipeline timestamp */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + cp_type3_packet(CP_MEM_WRITE, 2)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(context_id, soptimestamp))); - GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, timestamp); if (flags & KGSL_CMD_FLAGS_PMODE) { /* disable protected mode error checking */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0); } for (i = 0; i < sizedwords; i++) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, *cmds); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, *cmds); cmds++; } if (flags & KGSL_CMD_FLAGS_PMODE) { /* re-enable protected mode error checking */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_PROTECTED_MODE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 1); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 1); } /* HW Workaround for MMU Page fault @@ -600,23 +671,24 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, * GPU completes it. */ if (adreno_is_a2xx(adreno_dev)) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x00); } - if (adreno_is_a3xx(adreno_dev)) { + if (adreno_is_a3xx(adreno_dev) || adreno_is_a4xx(adreno_dev)) { /* * Flush HLSQ lazy updates to make sure there are no * resources pending for indirect loads after the timestamp */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x07); /* HLSQ_FLUSH */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, + rcmd_gpu, 0x07); /* HLSQ_FLUSH */ + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x00); } /* @@ -624,40 +696,48 @@ adreno_ringbuffer_addcmds(struct adreno_ringbuffer *rb, * enabled, then context_id will be KGSL_MEMSTORE_GLOBAL so all * eop timestamps will work out. */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, cp_type3_packet(CP_EVENT_WRITE, 3)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, CACHE_FLUSH_TS); - GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + cp_type3_packet(CP_EVENT_WRITE, 3)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, CACHE_FLUSH_TS); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(context_id, eoptimestamp))); - GSL_RB_WRITE(ringcmds, rcmd_gpu, timestamp); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, timestamp); if (drawctxt) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_MEM_WRITE, 2)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, (gpuaddr + + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (gpuaddr + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, eoptimestamp))); - GSL_RB_WRITE(ringcmds, rcmd_gpu, rb->global_ts); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, rb->global_ts); + } + + if (adreno_is_a20x(adreno_dev)) { + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + cp_type3_packet(CP_EVENT_WRITE, 1)); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, CACHE_FLUSH); } if (drawctxt || (flags & KGSL_CMD_FLAGS_INTERNAL_ISSUE)) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_INTERRUPT, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, CP_INT_CNTL__RB_INT_MASK); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, + CP_INT_CNTL__RB_INT_MASK); } if (adreno_is_a3xx(adreno_dev)) { /* Dummy set-constant to trigger context rollover */ - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_SET_CONSTANT, 2)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, (0x4<<16)|(A3XX_HLSQ_CL_KERNEL_GROUP_X_REG - 0x2000)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0); } if (flags & KGSL_CMD_FLAGS_WFI) { - GSL_RB_WRITE(ringcmds, rcmd_gpu, + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, cp_type3_packet(CP_WAIT_FOR_IDLE, 1)); - GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00000000); + GSL_RB_WRITE(rb->device, ringcmds, rcmd_gpu, 0x00000000); } adreno_ringbuffer_submit(rb); @@ -772,10 +852,8 @@ static bool _parse_ibs(struct kgsl_device_private *dev_priv, buffer */ struct kgsl_mem_entry *entry; - spin_lock(&dev_priv->process_priv->mem_lock); entry = kgsl_sharedmem_find_region(dev_priv->process_priv, gpuaddr, sizedwords * sizeof(uint)); - spin_unlock(&dev_priv->process_priv->mem_lock); if (entry == NULL) { KGSL_CMD_ERR(dev_priv->device, "no mapping for gpuaddr: 0x%08x\n", gpuaddr); @@ -925,13 +1003,35 @@ adreno_ringbuffer_issueibcmds(struct kgsl_device_private *dev_priv, return -EINVAL; } + /* For now everybody has the same priority */ + cmdbatch->priority = ADRENO_CONTEXT_DEFAULT_PRIORITY; + + /* wait for the suspend gate */ + wait_for_completion(&device->cmdbatch_gate); + /* Queue the command in the ringbuffer */ - ret = adreno_context_queue_cmd(adreno_dev, drawctxt, cmdbatch, + ret = adreno_dispatcher_queue_cmd(adreno_dev, drawctxt, cmdbatch, timestamp); if (ret) - KGSL_DRV_ERR(device, "adreno_context_queue_cmd returned %d\n", + KGSL_DRV_ERR(device, "adreno_dispatcher_queue_cmd returned %d\n", ret); + else { + /* + * only call trace_gpu_job_enqueue for actual commands - dummy + * sync command batches won't get scheduled on the GPU + */ + + if (!(cmdbatch->flags & KGSL_CONTEXT_SYNC)) { + const char *str = "3D"; + if (drawctxt->type == KGSL_CONTEXT_TYPE_CL || + drawctxt->type == KGSL_CONTEXT_TYPE_RS) + str = "compute"; + + kgsl_trace_gpu_job_enqueue(drawctxt->base.id, + cmdbatch->timestamp, str); + } + } return ret; } @@ -949,6 +1049,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, struct kgsl_context *context; struct adreno_context *drawctxt; unsigned int start_index = 0; + int flags = KGSL_CMD_FLAGS_NONE; int ret; context = cmdbatch->context; @@ -962,7 +1063,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, if a context switch hasn't occured */ if ((drawctxt->flags & CTXT_FLAGS_PREAMBLE) && - !(cmdbatch->priv & CMDBATCH_FLAG_FORCE_PREAMBLE) && + !test_bit(CMDBATCH_FLAG_FORCE_PREAMBLE, &cmdbatch->priv) && (adreno_dev->drawctxt_active == drawctxt)) start_index = 1; @@ -973,7 +1074,7 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, * generate the start and end markers and skip everything else */ - if (cmdbatch->priv & CMDBATCH_FLAG_SKIP) { + if (test_bit(CMDBATCH_FLAG_SKIP, &cmdbatch->priv)) { start_index = 0; numibs = 0; } @@ -1030,25 +1131,40 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, if (ret) goto done; + if (test_bit(CMDBATCH_FLAG_WFI, &cmdbatch->priv)) + flags = KGSL_CMD_FLAGS_WFI; + + /* + * For some targets, we need to execute a dummy shader operation after a + * power collapse + */ + + if (test_and_clear_bit(ADRENO_DEVICE_PWRON, &adreno_dev->priv) && + test_bit(ADRENO_DEVICE_PWRON_FIXUP, &adreno_dev->priv)) + flags |= KGSL_CMD_FLAGS_PWRON_FIXUP; + ret = adreno_ringbuffer_addcmds(&adreno_dev->ringbuffer, drawctxt, - cmdbatch->flags, + flags, &link[0], (cmds - link), cmdbatch->timestamp); #ifdef CONFIG_MSM_KGSL_CFF_DUMP + if (ret) + goto done; /* * insert wait for idle after every IB1 * this is conservative but works reliably and is ok * even for performance simulations */ - adreno_idle(device); + ret = adreno_idle(device); #endif done: + device->pwrctrl.irq_last = 0; kgsl_trace_issueibcmds(device, context->id, cmdbatch, cmdbatch->timestamp, cmdbatch->flags, ret, - drawctxt->type); + drawctxt ? drawctxt->type : 0); kfree(link); return ret; diff --git a/drivers/gpu/msm/adreno_ringbuffer.h b/drivers/gpu/msm/adreno_ringbuffer.h index d7a77409335..3aa0101e534 100644 --- a/drivers/gpu/msm/adreno_ringbuffer.h +++ b/drivers/gpu/msm/adreno_ringbuffer.h @@ -53,17 +53,16 @@ struct adreno_ringbuffer { unsigned int sizedwords; unsigned int wptr; /* write pointer offset in dwords from baseaddr */ - unsigned int rptr; /* read pointer offset in dwords from baseaddr */ unsigned int global_ts; }; -#define GSL_RB_WRITE(ring, gpuaddr, data) \ +#define GSL_RB_WRITE(device, ring, gpuaddr, data) \ do { \ *ring = data; \ wmb(); \ - kgsl_cffdump_setmem(gpuaddr, data, 4); \ + kgsl_cffdump_setmem(device, gpuaddr, data, 4); \ ring++; \ gpuaddr += sizeof(uint); \ } while (0) @@ -73,10 +72,20 @@ struct adreno_ringbuffer { /* mem rptr */ #define GSL_RB_CNTL_NO_UPDATE 0x0 /* enable */ -#define GSL_RB_GET_READPTR(rb, data) \ - do { \ - *(data) = rb->memptrs->rptr; \ - } while (0) + +/** + * adreno_get_rptr - Get the current ringbuffer read pointer + * @rb - the ringbuffer + * + * Get the current read pointer, which is written by the GPU. + */ +static inline unsigned int +adreno_get_rptr(struct adreno_ringbuffer *rb) +{ + unsigned int result = rb->memptrs->rptr; + rmb(); + return result; +} #define GSL_RB_CNTL_POLL_EN 0x0 /* disable */ @@ -97,6 +106,8 @@ int adreno_ringbuffer_submitcmd(struct adreno_device *adreno_dev, int adreno_ringbuffer_init(struct kgsl_device *device); +int adreno_ringbuffer_warm_start(struct adreno_ringbuffer *rb); + int adreno_ringbuffer_start(struct adreno_ringbuffer *rb); void adreno_ringbuffer_stop(struct adreno_ringbuffer *rb); diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c index 3bcbd580f36..fcb134938ed 100644 --- a/drivers/gpu/msm/adreno_snapshot.c +++ b/drivers/gpu/msm/adreno_snapshot.c @@ -18,6 +18,7 @@ #include "adreno_pm4types.h" #include "a2xx_reg.h" #include "a3xx_reg.h" +#include "adreno_cp_parser.h" /* Number of dwords of ringbuffer history to record */ #define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100 @@ -34,20 +35,23 @@ static int snapshot_frozen_objsize; static struct kgsl_snapshot_obj { int type; uint32_t gpuaddr; - uint32_t ptbase; + phys_addr_t ptbase; void *ptr; int dwords; + struct kgsl_mem_entry *entry; } objbuf[SNAPSHOT_OBJ_BUFSIZE]; /* Pointer to the next open entry in the object list */ static int objbufptr; /* Push a new buffer object onto the list */ -static void push_object(struct kgsl_device *device, int type, uint32_t ptbase, +static void push_object(struct kgsl_device *device, int type, + phys_addr_t ptbase, uint32_t gpuaddr, int dwords) { int index; void *ptr; + struct kgsl_mem_entry *entry = NULL; /* * Sometimes IBs can be reused in the same dump. Because we parse from @@ -73,7 +77,7 @@ static void push_object(struct kgsl_device *device, int type, uint32_t ptbase, * adreno_convertaddr verifies that the IB size is valid - at least in * the context of it being smaller then the allocated memory space */ - ptr = adreno_convertaddr(device, ptbase, gpuaddr, dwords << 2); + ptr = adreno_convertaddr(device, ptbase, gpuaddr, dwords << 2, &entry); if (ptr == NULL) { KGSL_DRV_ERR(device, @@ -86,6 +90,7 @@ static void push_object(struct kgsl_device *device, int type, uint32_t ptbase, objbuf[objbufptr].gpuaddr = gpuaddr; objbuf[objbufptr].ptbase = ptbase; objbuf[objbufptr].dwords = dwords; + objbuf[objbufptr].entry = entry; objbuf[objbufptr++].ptr = ptr; } @@ -94,7 +99,7 @@ static void push_object(struct kgsl_device *device, int type, uint32_t ptbase, * to be dumped */ -static int find_object(int type, unsigned int gpuaddr, unsigned int ptbase) +static int find_object(int type, unsigned int gpuaddr, phys_addr_t ptbase) { int index; @@ -109,513 +114,61 @@ static int find_object(int type, unsigned int gpuaddr, unsigned int ptbase) } /* - * This structure keeps track of type0 writes to VSC_PIPE_DATA_ADDRESS_x and - * VSC_PIPE_DATA_LENGTH_x. When a draw initator is called these registers - * point to buffers that we need to freeze for a snapshot - */ - -static struct { - unsigned int base; - unsigned int size; -} vsc_pipe[8]; - -/* - * This is the cached value of type0 writes to the VSC_SIZE_ADDRESS which - * contains the buffer address of the visiblity stream size buffer during a - * binning pass - */ - -static unsigned int vsc_size_address; - -/* - * This struct keeps track of type0 writes to VFD_FETCH_INSTR_0_X and - * VFD_FETCH_INSTR_1_X registers. When a draw initator is called the addresses - * and sizes in these registers point to VBOs that we need to freeze for a - * snapshot - */ - -static struct { - unsigned int base; - unsigned int stride; -} vbo[16]; - -/* - * This is the cached value of type0 writes to VFD_INDEX_MAX. This will be used - * to calculate the size of the VBOs when the draw initator is called - */ - -static unsigned int vfd_index_max; - -/* - * This is the cached value of type0 writes to VFD_CONTROL_0 which tells us how - * many VBOs are active when the draw initator is called - */ - -static unsigned int vfd_control_0; - -/* - * Cached value of type0 writes to SP_VS_PVT_MEM_ADDR and SP_FS_PVT_MEM_ADDR. - * This is a buffer that contains private stack information for the shader - */ - -static unsigned int sp_vs_pvt_mem_addr; -static unsigned int sp_fs_pvt_mem_addr; - -/* - * Cached value of SP_VS_OBJ_START_REG and SP_FS_OBJ_START_REG. - */ -static unsigned int sp_vs_obj_start_reg; -static unsigned int sp_fs_obj_start_reg; - -/* - * Each load state block has two possible types. Each type has a different - * number of dwords per unit. Use this handy lookup table to make sure - * we dump the right amount of data from the indirect buffer + * snapshot_freeze_obj_list() - Take a list of ib objects and freeze their + * memory for snapshot + * @device: Device being snapshotted + * @ptbase: The pagetable base of the process to which IB belongs + * @ib_obj_list: List of the IB objects + * + * Returns 0 on success else error code */ - -static int load_state_unit_sizes[7][2] = { - { 2, 4 }, - { 0, 1 }, - { 2, 4 }, - { 0, 1 }, - { 8, 2 }, - { 8, 2 }, - { 8, 2 }, -}; - -static int ib_parse_load_state(struct kgsl_device *device, unsigned int *pkt, - unsigned int ptbase) +static int snapshot_freeze_obj_list(struct kgsl_device *device, + phys_addr_t ptbase, struct adreno_ib_object_list *ib_obj_list) { - unsigned int block, source, type; int ret = 0; - - /* - * The object here is to find indirect shaders i.e - shaders loaded from - * GPU memory instead of directly in the command. These should be added - * to the list of memory objects to dump. So look at the load state - * if the block is indirect (source = 4). If so then add the memory - * address to the list. The size of the object differs depending on the - * type per the load_state_unit_sizes array above. - */ - - if (type3_pkt_size(pkt[0]) < 2) - return 0; - - /* - * pkt[1] 18:16 - source - * pkt[1] 21:19 - state block - * pkt[1] 31:22 - size in units - * pkt[2] 0:1 - type - * pkt[2] 31:2 - GPU memory address - */ - - block = (pkt[1] >> 19) & 0x07; - source = (pkt[1] >> 16) & 0x07; - type = pkt[2] & 0x03; - - if (source == 4) { - int unitsize, ret; - - if (type == 0) - unitsize = load_state_unit_sizes[block][0]; - else - unitsize = load_state_unit_sizes[block][1]; - - /* Freeze the GPU buffer containing the shader */ - - ret = kgsl_snapshot_get_object(device, ptbase, - pkt[2] & 0xFFFFFFFC, - (((pkt[1] >> 22) & 0x03FF) * unitsize) << 2, - SNAPSHOT_GPU_OBJECT_SHADER); - - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - - return ret; -} - -/* - * This opcode sets the base addresses for the visibilty stream buffer and the - * visiblity stream size buffer. - */ - -static int ib_parse_set_bin_data(struct kgsl_device *device, unsigned int *pkt, - unsigned int ptbase) -{ - int ret; - - if (type3_pkt_size(pkt[0]) < 2) - return 0; - - /* Visiblity stream buffer */ - ret = kgsl_snapshot_get_object(device, ptbase, pkt[1], 0, - SNAPSHOT_GPU_OBJECT_GENERIC); - - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - - /* visiblity stream size buffer (fixed size 8 dwords) */ - ret = kgsl_snapshot_get_object(device, ptbase, pkt[2], 32, - SNAPSHOT_GPU_OBJECT_GENERIC); - - if (ret >= 0) - snapshot_frozen_objsize += ret; - - return ret; -} - -/* - * This opcode writes to GPU memory - if the buffer is written to, there is a - * good chance that it would be valuable to capture in the snapshot, so mark all - * buffers that are written to as frozen - */ - -static int ib_parse_mem_write(struct kgsl_device *device, unsigned int *pkt, - unsigned int ptbase) -{ - int ret; - - if (type3_pkt_size(pkt[0]) < 1) - return 0; - - /* - * The address is where the data in the rest of this packet is written - * to, but since that might be an offset into the larger buffer we need - * to get the whole thing. Pass a size of 0 kgsl_snapshot_get_object to - * capture the entire buffer. - */ - - ret = kgsl_snapshot_get_object(device, ptbase, pkt[1] & 0xFFFFFFFC, 0, - SNAPSHOT_GPU_OBJECT_GENERIC); - - if (ret >= 0) - snapshot_frozen_objsize += ret; - - return ret; -} - -/* - * The DRAW_INDX opcode sends a draw initator which starts a draw operation in - * the GPU, so this is the point where all the registers and buffers become - * "valid". The DRAW_INDX may also have an index buffer pointer that should be - * frozen with the others - */ - -static int ib_parse_draw_indx(struct kgsl_device *device, unsigned int *pkt, - unsigned int ptbase) -{ - int ret = 0, i; - - if (type3_pkt_size(pkt[0]) < 3) - return 0; - - /* DRAW_IDX may have a index buffer pointer */ - - if (type3_pkt_size(pkt[0]) > 3) { - ret = kgsl_snapshot_get_object(device, ptbase, pkt[4], pkt[5], - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - - /* - * All of the type0 writes are valid at a draw initiator, so freeze - * the various buffers that we are tracking - */ - - /* First up the visiblity stream buffer */ - - for (i = 0; i < ARRAY_SIZE(vsc_pipe); i++) { - if (vsc_pipe[i].base != 0 && vsc_pipe[i].size != 0) { - ret = kgsl_snapshot_get_object(device, ptbase, - vsc_pipe[i].base, vsc_pipe[i].size, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - } - - /* Next the visibility stream size buffer */ - - if (vsc_size_address) { - ret = kgsl_snapshot_get_object(device, ptbase, - vsc_size_address, 32, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - - /* Next private shader buffer memory */ - if (sp_vs_pvt_mem_addr) { - ret = kgsl_snapshot_get_object(device, ptbase, - sp_vs_pvt_mem_addr, 8192, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - sp_vs_pvt_mem_addr = 0; - } - - if (sp_fs_pvt_mem_addr) { - ret = kgsl_snapshot_get_object(device, ptbase, - sp_fs_pvt_mem_addr, 8192, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - sp_fs_pvt_mem_addr = 0; - } - - if (sp_vs_obj_start_reg) { - ret = kgsl_snapshot_get_object(device, ptbase, - sp_vs_obj_start_reg & 0xFFFFFFE0, 0, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - snapshot_frozen_objsize += ret; - sp_vs_obj_start_reg = 0; - } - - if (sp_fs_obj_start_reg) { - ret = kgsl_snapshot_get_object(device, ptbase, - sp_fs_obj_start_reg & 0xFFFFFFE0, 0, - SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - snapshot_frozen_objsize += ret; - sp_fs_obj_start_reg = 0; - } - - /* Finally: VBOs */ - - /* The number of active VBOs is stored in VFD_CONTROL_O[31:27] */ - for (i = 0; i < (vfd_control_0) >> 27; i++) { - int size; - - /* - * The size of the VBO is the stride stored in - * VFD_FETCH_INSTR_0_X.BUFSTRIDE * VFD_INDEX_MAX. The base - * is stored in VFD_FETCH_INSTR_1_X - */ - - if (vbo[i].base != 0) { - size = vbo[i].stride * vfd_index_max; - - ret = kgsl_snapshot_get_object(device, ptbase, - vbo[i].base, - 0, SNAPSHOT_GPU_OBJECT_GENERIC); - if (ret < 0) - return -EINVAL; - - snapshot_frozen_objsize += ret; - } - - vbo[i].base = 0; - vbo[i].stride = 0; - } - - vfd_control_0 = 0; - vfd_index_max = 0; - - return ret; -} - -/* - * Parse all the type3 opcode packets that may contain important information, - * such as additional GPU buffers to grab or a draw initator - */ - -static int ib_parse_type3(struct kgsl_device *device, unsigned int *ptr, - unsigned int ptbase) -{ - int opcode = cp_type3_opcode(*ptr); - - if (opcode == CP_LOAD_STATE) - return ib_parse_load_state(device, ptr, ptbase); - else if (opcode == CP_SET_BIN_DATA) - return ib_parse_set_bin_data(device, ptr, ptbase); - else if (opcode == CP_MEM_WRITE) - return ib_parse_mem_write(device, ptr, ptbase); - else if (opcode == CP_DRAW_INDX) - return ib_parse_draw_indx(device, ptr, ptbase); - - return 0; -} - -/* - * Parse type0 packets found in the stream. Some of the registers that are - * written are clues for GPU buffers that we need to freeze. Register writes - * are considred valid when a draw initator is called, so just cache the values - * here and freeze them when a CP_DRAW_INDX is seen. This protects against - * needlessly caching buffers that won't be used during a draw call - */ - -static void ib_parse_type0(struct kgsl_device *device, unsigned int *ptr, - unsigned int ptbase) -{ - int size = type0_pkt_size(*ptr); - int offset = type0_pkt_offset(*ptr); + struct adreno_ib_object *ib_objs; + unsigned int ib2base; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); int i; - for (i = 0; i < size - 1; i++, offset++) { - - /* Visiblity stream buffer */ - - if (offset >= A3XX_VSC_PIPE_DATA_ADDRESS_0 && - offset <= A3XX_VSC_PIPE_DATA_LENGTH_7) { - int index = offset - A3XX_VSC_PIPE_DATA_ADDRESS_0; - - /* Each bank of address and length registers are - * interleaved with an empty register: - * - * address 0 - * length 0 - * empty - * address 1 - * length 1 - * empty - * ... - */ - - if ((index % 3) == 0) - vsc_pipe[index / 3].base = ptr[i + 1]; - else if ((index % 3) == 1) - vsc_pipe[index / 3].size = ptr[i + 1]; - } else if ((offset >= A3XX_VFD_FETCH_INSTR_0_0) && - (offset <= A3XX_VFD_FETCH_INSTR_1_F)) { - int index = offset - A3XX_VFD_FETCH_INSTR_0_0; - - /* - * FETCH_INSTR_0_X and FETCH_INSTR_1_X banks are - * interleaved as above but without the empty register - * in between - */ - - if ((index % 2) == 0) - vbo[index >> 1].stride = - (ptr[i + 1] >> 7) & 0x1FF; - else - vbo[index >> 1].base = ptr[i + 1]; - } else { - /* - * Cache various support registers for calculating - * buffer sizes - */ - - switch (offset) { - case A3XX_VFD_CONTROL_0: - vfd_control_0 = ptr[i + 1]; - break; - case A3XX_VFD_INDEX_MAX: - vfd_index_max = ptr[i + 1]; - break; - case A3XX_VSC_SIZE_ADDRESS: - vsc_size_address = ptr[i + 1]; - break; - case A3XX_SP_VS_PVT_MEM_ADDR_REG: - sp_vs_pvt_mem_addr = ptr[i + 1]; - break; - case A3XX_SP_FS_PVT_MEM_ADDR_REG: - sp_fs_pvt_mem_addr = ptr[i + 1]; - break; - case A3XX_SP_VS_OBJ_START_REG: - sp_vs_obj_start_reg = ptr[i + 1]; - break; - case A3XX_SP_FS_OBJ_START_REG: - sp_fs_obj_start_reg = ptr[i + 1]; + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BASE, &ib2base); + + for (i = 0; i < ib_obj_list->num_objs; i++) { + int temp_ret; + int index; + int freeze = 1; + + ib_objs = &(ib_obj_list->obj_list[i]); + /* Make sure this object is not going to be saved statically */ + for (index = 0; index < objbufptr; index++) { + if ((objbuf[index].gpuaddr <= ib_objs->gpuaddr) && + ((objbuf[index].gpuaddr + + (objbuf[index].dwords << 2)) >= + (ib_objs->gpuaddr + ib_objs->size)) && + (objbuf[index].ptbase == ptbase)) { + freeze = 0; break; } } - } -} - -static inline int parse_ib(struct kgsl_device *device, unsigned int ptbase, - unsigned int gpuaddr, unsigned int dwords); - -/* Add an IB as a GPU object, but first, parse it to find more goodies within */ - -static int ib_add_gpu_object(struct kgsl_device *device, unsigned int ptbase, - unsigned int gpuaddr, unsigned int dwords) -{ - int i, ret, rem = dwords; - unsigned int *src; - - /* - * If the object is already in the list, we don't need to parse it again - */ - - if (kgsl_snapshot_have_object(device, ptbase, gpuaddr, dwords << 2)) - return 0; - - src = (unsigned int *) adreno_convertaddr(device, ptbase, gpuaddr, - dwords << 2); - - if (src == NULL) - return -EINVAL; - - for (i = 0; rem > 0; rem--, i++) { - int pktsize; - - /* If the packet isn't a type 1 or a type 3, then don't bother - * parsing it - it is likely corrupted */ - - if (!pkt_is_type0(src[i]) && !pkt_is_type3(src[i])) - break; - - pktsize = type3_pkt_size(src[i]); - if (!pktsize || (pktsize + 1) > rem) - break; - - if (pkt_is_type3(src[i])) { - if (adreno_cmd_is_ib(src[i])) { - unsigned int gpuaddr = src[i + 1]; - unsigned int size = src[i + 2]; - - ret = parse_ib(device, ptbase, gpuaddr, size); - - /* If adding the IB failed then stop parsing */ - if (ret < 0) - goto done; + if (freeze) { + /* Save current IB2 statically */ + if (ib2base == ib_objs->gpuaddr) { + push_object(device, SNAPSHOT_OBJ_TYPE_IB, + ptbase, ib_objs->gpuaddr, ib_objs->size >> 2); } else { - ret = ib_parse_type3(device, &src[i], ptbase); - /* - * If the parse function failed (probably - * because of a bad decode) then bail out and - * just capture the binary IB data - */ - - if (ret < 0) - goto done; + temp_ret = kgsl_snapshot_get_object(device, + ptbase, ib_objs->gpuaddr, ib_objs->size, + ib_objs->snapshot_obj_type); + if (temp_ret < 0) { + if (ret >= 0) + ret = temp_ret; + } else { + snapshot_frozen_objsize += temp_ret; + } } - } else if (pkt_is_type0(src[i])) { - ib_parse_type0(device, &src[i], ptbase); } - - i += pktsize; - rem -= pktsize; } - -done: - ret = kgsl_snapshot_get_object(device, ptbase, gpuaddr, dwords << 2, - SNAPSHOT_GPU_OBJECT_IB); - - if (ret >= 0) - snapshot_frozen_objsize += ret; - return ret; } @@ -625,27 +178,41 @@ static int ib_add_gpu_object(struct kgsl_device *device, unsigned int ptbase, * access the dynamic data from the sysfs file. Push all other IBs on the * dynamic list */ -static inline int parse_ib(struct kgsl_device *device, unsigned int ptbase, +static inline int parse_ib(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int dwords) { - unsigned int ib1base, ib2base; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + unsigned int ib1base; int ret = 0; + struct adreno_ib_object_list *ib_obj_list; /* - * Check the IB address - if it is either the last executed IB1 or the - * last executed IB2 then push it into the static blob otherwise put - * it in the dynamic list + * Check the IB address - if it is either the last executed IB1 + * then push it into the static blob otherwise put it in the dynamic + * list */ - kgsl_regread(device, REG_CP_IB1_BASE, &ib1base); - kgsl_regread(device, REG_CP_IB2_BASE, &ib2base); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ib1base); - if (gpuaddr == ib1base || gpuaddr == ib2base) + if (gpuaddr == ib1base) { push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase, gpuaddr, dwords); - else - ret = ib_add_gpu_object(device, ptbase, gpuaddr, dwords); + goto done; + } + + if (kgsl_snapshot_have_object(device, ptbase, gpuaddr, dwords << 2)) + goto done; + + ret = adreno_ib_create_object_list(device, ptbase, + gpuaddr, dwords, &ib_obj_list); + if (ret) + goto done; + ret = kgsl_snapshot_add_ib_obj_list(device, ptbase, ib_obj_list); + + if (ret) + adreno_ib_destroy_obj_list(ib_obj_list); +done: return ret; } @@ -657,7 +224,8 @@ static int snapshot_rb(struct kgsl_device *device, void *snapshot, unsigned int *data = snapshot + sizeof(*header); struct adreno_device *adreno_dev = ADRENO_DEVICE(device); struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer; - unsigned int ptbase, rptr, *rbptr, ibbase; + unsigned int rptr, *rbptr, ibbase; + phys_addr_t ptbase; int index, size, i; int parse_ibs = 0, ib_parse_start; @@ -665,10 +233,10 @@ static int snapshot_rb(struct kgsl_device *device, void *snapshot, ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); /* Get the current read pointers for the RB */ - kgsl_regread(device, REG_CP_RB_RPTR, &rptr); + adreno_readreg(adreno_dev, ADRENO_REG_CP_RB_RPTR, &rptr); /* Address of the last processed IB */ - kgsl_regread(device, REG_CP_IB1_BASE, &ibbase); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ibbase); /* * Figure out the window of ringbuffer data to dump. First we need to @@ -818,15 +386,80 @@ static int snapshot_rb(struct kgsl_device *device, void *snapshot, return size + sizeof(*header); } +static int snapshot_capture_mem_list(struct kgsl_device *device, void *snapshot, + int remain, void *priv) +{ + struct kgsl_snapshot_replay_mem_list *header = snapshot; + struct kgsl_process_private *private = NULL; + struct kgsl_process_private *tmp_private; + phys_addr_t ptbase; + struct rb_node *node; + struct kgsl_mem_entry *entry = NULL; + int num_mem; + unsigned int *data = snapshot + sizeof(*header); + + ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); + mutex_lock(&kgsl_driver.process_mutex); + list_for_each_entry(tmp_private, &kgsl_driver.process_list, list) { + if (kgsl_mmu_pt_equal(&device->mmu, tmp_private->pagetable, + ptbase)) { + private = tmp_private; + break; + } + } + mutex_unlock(&kgsl_driver.process_mutex); + if (!private) { + KGSL_DRV_ERR(device, + "Failed to get pointer to process private structure\n"); + return 0; + } + /* We need to know the number of memory objects that the process has */ + spin_lock(&private->mem_lock); + for (node = rb_first(&private->mem_rb), num_mem = 0; node; ) { + entry = rb_entry(node, struct kgsl_mem_entry, node); + node = rb_next(&entry->node); + num_mem++; + } + + if (remain < ((num_mem * 3 * sizeof(unsigned int)) + + sizeof(*header))) { + KGSL_DRV_ERR(device, + "snapshot: Not enough memory for the mem list section"); + spin_unlock(&private->mem_lock); + return 0; + } + header->num_entries = num_mem; + header->ptbase = (__u32)ptbase; + /* + * Walk throught the memory list and store the + * tuples(gpuaddr, size, memtype) in snapshot + */ + for (node = rb_first(&private->mem_rb); node; ) { + entry = rb_entry(node, struct kgsl_mem_entry, node); + node = rb_next(&entry->node); + + *data++ = entry->memdesc.gpuaddr; + *data++ = entry->memdesc.size; + *data++ = (entry->memdesc.priv & KGSL_MEMTYPE_MASK) >> + KGSL_MEMTYPE_SHIFT; + } + spin_unlock(&private->mem_lock); + return sizeof(*header) + (num_mem * 3 * sizeof(unsigned int)); +} + /* Snapshot the memory for an indirect buffer */ static int snapshot_ib(struct kgsl_device *device, void *snapshot, int remain, void *priv) { struct kgsl_snapshot_ib *header = snapshot; struct kgsl_snapshot_obj *obj = priv; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); unsigned int *src = obj->ptr; unsigned int *dst = snapshot + sizeof(*header); - int i, ret; + struct adreno_ib_object_list *ib_obj_list; + unsigned int ib1base; + + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ib1base); if (remain < (obj->dwords << 2) + sizeof(*header)) { KGSL_DRV_ERR(device, @@ -834,30 +467,26 @@ static int snapshot_ib(struct kgsl_device *device, void *snapshot, return 0; } + /* only do this for IB1 because the IB2's are part of IB1 objects */ + if (ib1base == obj->gpuaddr) { + if (!adreno_ib_create_object_list(device, obj->ptbase, + obj->gpuaddr, obj->dwords, + &ib_obj_list)) { + /* freeze the IB objects in the IB */ + snapshot_freeze_obj_list(device, obj->ptbase, + ib_obj_list); + adreno_ib_destroy_obj_list(ib_obj_list); + } + } + /* Write the sub-header for the section */ header->gpuaddr = obj->gpuaddr; - header->ptbase = obj->ptbase; + header->ptbase = (__u32)obj->ptbase; header->size = obj->dwords; /* Write the contents of the ib */ - for (i = 0; i < obj->dwords; i++, src++, dst++) { - *dst = *src; - - if (pkt_is_type3(*src)) { - if ((obj->dwords - i) < type3_pkt_size(*src) + 1) - continue; - - if (adreno_cmd_is_ib(*src)) - ret = parse_ib(device, obj->ptbase, src[1], - src[2]); - else - ret = ib_parse_type3(device, src, obj->ptbase); - - /* Stop parsing if the type3 decode fails */ - if (ret < 0) - break; - } - } + memcpy((void *)dst, (void *)src, obj->dwords << 2); + /* Write the contents of the ib */ return (obj->dwords << 2) + sizeof(*header); } @@ -871,6 +500,10 @@ static void *dump_object(struct kgsl_device *device, int obj, void *snapshot, snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_IB, snapshot, remain, snapshot_ib, &objbuf[obj]); + if (objbuf[obj].entry) { + kgsl_memdesc_unmap(&(objbuf[obj].entry->memdesc)); + kgsl_mem_entry_put(objbuf[obj].entry); + } break; default: KGSL_DRV_ERR(device, @@ -896,23 +529,15 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, int hang) { int i; - uint32_t ptbase, ibbase, ibsize; + uint32_t ibbase, ibsize; struct adreno_device *adreno_dev = ADRENO_DEVICE(device); + phys_addr_t ptbase; /* Reset the list of objects */ objbufptr = 0; snapshot_frozen_objsize = 0; - /* Clear the caches for the visibilty stream and VBO parsing */ - - vfd_control_0 = 0; - vfd_index_max = 0; - vsc_size_address = 0; - - memset(vsc_pipe, 0, sizeof(vsc_pipe)); - memset(vbo, 0, sizeof(vbo)); - /* Get the physical address of the MMU pagetable */ ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); @@ -920,6 +545,13 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_RB, snapshot, remain, snapshot_rb, NULL); + /* + * Add a section that lists (gpuaddr, size, memtype) tuples of the + * hanging process + */ + snapshot = kgsl_snapshot_add_section(device, + KGSL_SNAPSHOT_SECTION_MEMLIST, snapshot, remain, + snapshot_capture_mem_list, NULL); /* * Make sure that the last IB1 that was being executed is dumped. * Since this was the last IB1 that was processed, we should have @@ -927,8 +559,8 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, * want to be double plus sure. */ - kgsl_regread(device, REG_CP_IB1_BASE, &ibbase); - kgsl_regread(device, REG_CP_IB1_BUFSZ, &ibsize); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BASE, &ibbase); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB1_BUFSZ, &ibsize); /* * The problem is that IB size from the register is the unprocessed size @@ -945,8 +577,8 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, "Dumping %x dwords of the buffer.\n", ibsize); } - kgsl_regread(device, REG_CP_IB2_BASE, &ibbase); - kgsl_regread(device, REG_CP_IB2_BUFSZ, &ibsize); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BASE, &ibbase); + adreno_readreg(adreno_dev, ADRENO_REG_CP_IB2_BUFSZ, &ibsize); /* * Add the last parsed IB2 to the list. The IB2 should be found as we @@ -977,5 +609,12 @@ void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain, KGSL_DRV_ERR(device, "GPU snapshot froze %dKb of GPU buffers\n", snapshot_frozen_objsize / 1024); + /* + * Queue a work item that will save the IB data in snapshot into + * static memory to prevent loss of data due to overwriting of + * memory + */ + queue_work(device->work_queue, &device->snapshot_obj_ws); + return snapshot; } diff --git a/drivers/gpu/msm/adreno_trace.h b/drivers/gpu/msm/adreno_trace.h index 8993afb3764..6079b612185 100644 --- a/drivers/gpu/msm/adreno_trace.h +++ b/drivers/gpu/msm/adreno_trace.h @@ -29,15 +29,21 @@ TRACE_EVENT(adreno_cmdbatch_queued, __field(unsigned int, id) __field(unsigned int, timestamp) __field(unsigned int, queued) + __field(unsigned int, flags) ), TP_fast_assign( __entry->id = cmdbatch->context->id; __entry->timestamp = cmdbatch->timestamp; __entry->queued = queued; + __entry->flags = cmdbatch->flags; ), TP_printk( - "ctx=%u ts=%u queued=%u", - __entry->id, __entry->timestamp, __entry->queued + "ctx=%u ts=%u queued=%u flags=%s", + __entry->id, __entry->timestamp, __entry->queued, + __entry->flags ? __print_flags(__entry->flags, "|", + { KGSL_CONTEXT_SYNC, "SYNC" }, + { KGSL_CONTEXT_END_OF_FRAME, "EOF" }) + : "none" ) ); @@ -61,14 +67,78 @@ DECLARE_EVENT_CLASS(adreno_cmdbatch_template, ) ); -DEFINE_EVENT(adreno_cmdbatch_template, adreno_cmdbatch_retired, +DEFINE_EVENT(adreno_cmdbatch_template, adreno_cmdbatch_submitted, TP_PROTO(struct kgsl_cmdbatch *cmdbatch, int inflight), TP_ARGS(cmdbatch, inflight) ); -DEFINE_EVENT(adreno_cmdbatch_template, adreno_cmdbatch_submitted, +TRACE_EVENT(adreno_cmdbatch_retired, TP_PROTO(struct kgsl_cmdbatch *cmdbatch, int inflight), - TP_ARGS(cmdbatch, inflight) + TP_ARGS(cmdbatch, inflight), + TP_STRUCT__entry( + __field(unsigned int, id) + __field(unsigned int, timestamp) + __field(unsigned int, inflight) + __field(unsigned int, recovery) + ), + TP_fast_assign( + __entry->id = cmdbatch->context->id; + __entry->timestamp = cmdbatch->timestamp; + __entry->inflight = inflight; + __entry->recovery = cmdbatch->fault_recovery; + ), + TP_printk( + "ctx=%u ts=%u inflight=%u recovery=%s", + __entry->id, __entry->timestamp, + __entry->inflight, + __entry->recovery ? + __print_flags(__entry->recovery, "|", + ADRENO_FT_TYPES) : "none" + ) +); + +TRACE_EVENT(adreno_cmdbatch_fault, + TP_PROTO(struct kgsl_cmdbatch *cmdbatch, unsigned int fault), + TP_ARGS(cmdbatch, fault), + TP_STRUCT__entry( + __field(unsigned int, id) + __field(unsigned int, timestamp) + __field(unsigned int, fault) + ), + TP_fast_assign( + __entry->id = cmdbatch->context->id; + __entry->timestamp = cmdbatch->timestamp; + __entry->fault = fault; + ), + TP_printk( + "ctx=%u ts=%u type=%s", + __entry->id, __entry->timestamp, + __print_symbolic(__entry->fault, + { 0, "none" }, + { ADRENO_SOFT_FAULT, "soft" }, + { ADRENO_HARD_FAULT, "hard" }, + { ADRENO_TIMEOUT_FAULT, "timeout" }) + ) +); + +TRACE_EVENT(adreno_cmdbatch_recovery, + TP_PROTO(struct kgsl_cmdbatch *cmdbatch, unsigned int action), + TP_ARGS(cmdbatch, action), + TP_STRUCT__entry( + __field(unsigned int, id) + __field(unsigned int, timestamp) + __field(unsigned int, action) + ), + TP_fast_assign( + __entry->id = cmdbatch->context->id; + __entry->timestamp = cmdbatch->timestamp; + __entry->action = action; + ), + TP_printk( + "ctx=%u ts=%u action=%s", + __entry->id, __entry->timestamp, + __print_symbolic(__entry->action, ADRENO_FT_TYPES) + ) ); DECLARE_EVENT_CLASS(adreno_drawctxt_template, @@ -83,12 +153,12 @@ DECLARE_EVENT_CLASS(adreno_drawctxt_template, TP_printk("ctx=%u", __entry->id) ); -DEFINE_EVENT(adreno_drawctxt_template, adreno_context_sleep, +DEFINE_EVENT(adreno_drawctxt_template, adreno_drawctxt_sleep, TP_PROTO(struct adreno_context *drawctxt), TP_ARGS(drawctxt) ); -DEFINE_EVENT(adreno_drawctxt_template, adreno_context_wake, +DEFINE_EVENT(adreno_drawctxt_template, adreno_drawctxt_wake, TP_PROTO(struct adreno_context *drawctxt), TP_ARGS(drawctxt) ); @@ -98,6 +168,11 @@ DEFINE_EVENT(adreno_drawctxt_template, dispatch_queue_context, TP_ARGS(drawctxt) ); +DEFINE_EVENT(adreno_drawctxt_template, adreno_drawctxt_invalidate, + TP_PROTO(struct adreno_context *drawctxt), + TP_ARGS(drawctxt) +); + TRACE_EVENT(adreno_drawctxt_wait_start, TP_PROTO(unsigned int id, unsigned int ts), TP_ARGS(id, ts), @@ -134,12 +209,36 @@ TRACE_EVENT(adreno_drawctxt_wait_done, ) ); +TRACE_EVENT(adreno_drawctxt_switch, + TP_PROTO(struct adreno_context *oldctx, + struct adreno_context *newctx, + unsigned int flags), + TP_ARGS(oldctx, newctx, flags), + TP_STRUCT__entry( + __field(unsigned int, oldctx) + __field(unsigned int, newctx) + __field(unsigned int, flags) + ), + TP_fast_assign( + __entry->oldctx = oldctx ? oldctx->base.id : 0; + __entry->newctx = newctx ? newctx->base.id : 0; + ), + TP_printk( + "oldctx=%u newctx=%u flags=%X", + __entry->oldctx, __entry->newctx, flags + ) +); + TRACE_EVENT(adreno_gpu_fault, - TP_PROTO(unsigned int status, unsigned int rptr, unsigned int wptr, + TP_PROTO(unsigned int ctx, unsigned int ts, + unsigned int status, unsigned int rptr, unsigned int wptr, unsigned int ib1base, unsigned int ib1size, unsigned int ib2base, unsigned int ib2size), - TP_ARGS(status, rptr, wptr, ib1base, ib1size, ib2base, ib2size), + TP_ARGS(ctx, ts, status, rptr, wptr, ib1base, ib1size, ib2base, + ib2size), TP_STRUCT__entry( + __field(unsigned int, ctx) + __field(unsigned int, ts) __field(unsigned int, status) __field(unsigned int, rptr) __field(unsigned int, wptr) @@ -149,6 +248,8 @@ TRACE_EVENT(adreno_gpu_fault, __field(unsigned int, ib2size) ), TP_fast_assign( + __entry->ctx = ctx; + __entry->ts = ts; __entry->status = status; __entry->rptr = rptr; __entry->wptr = wptr; @@ -157,10 +258,10 @@ TRACE_EVENT(adreno_gpu_fault, __entry->ib2base = ib2base; __entry->ib2size = ib2size; ), - TP_printk("status=%X RB=%X/%X IB1=%X/%X IB2=%X/%X", - __entry->status, __entry->wptr, __entry->rptr, - __entry->ib1base, __entry->ib1size, __entry->ib2base, - __entry->ib2size) + TP_printk("ctx=%d ts=%d status=%X RB=%X/%X IB1=%X/%X IB2=%X/%X", + __entry->ctx, __entry->ts, __entry->status, __entry->wptr, + __entry->rptr, __entry->ib1base, __entry->ib1size, + __entry->ib2base, __entry->ib2size) ); #endif /* _ADRENO_TRACE_H */ diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index bf7ec97a8b7..a33210cc0b6 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -19,14 +19,14 @@ #include #include #include -#include +#include + #include #include #include #include #include #include -#include #include #include #include @@ -54,8 +54,17 @@ module_param_named(mmutype, ksgl_mmu_type, charp, 0); MODULE_PARM_DESC(ksgl_mmu_type, "Type of MMU to be used for graphics. Valid values are 'iommu' or 'gpummu' or 'nommu'"); -static struct ion_client *kgsl_ion_client; +struct kgsl_dma_buf_meta { + struct dma_buf_attachment *attach; + struct dma_buf *dmabuf; + struct sg_table *table; +}; + +static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry); +static void +kgsl_put_process_private(struct kgsl_device *device, + struct kgsl_process_private *private); /** * kgsl_trace_issueibcmds() - Call trace_issueibcmds by proxy * device: KGSL device @@ -151,8 +160,8 @@ void kgsl_memfree_hist_set_event(unsigned int pid, unsigned int gpuaddr, */ struct kgsl_mem_entry * __must_check -kgsl_get_mem_entry(struct kgsl_device *device, unsigned int ptbase, - unsigned int gpuaddr, unsigned int size) +kgsl_get_mem_entry(struct kgsl_device *device, + phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size) { struct kgsl_process_private *priv; struct kgsl_mem_entry *entry; @@ -188,6 +197,17 @@ kgsl_mem_entry_create(void) return entry; } +static void kgsl_destroy_ion(struct kgsl_dma_buf_meta *meta) +{ + if (meta != NULL) { + dma_buf_unmap_attachment(meta->attach, meta->table, + DMA_FROM_DEVICE); + dma_buf_detach(meta->dmabuf, meta->attach); + dma_buf_put(meta->dmabuf); + kfree(meta); + } +} + void kgsl_mem_entry_destroy(struct kref *kref) { @@ -195,6 +215,9 @@ kgsl_mem_entry_destroy(struct kref *kref) struct kgsl_mem_entry, refcount); + /* Detach from process list */ + kgsl_mem_entry_detach_process(entry); + if (entry->memtype != KGSL_MEM_ENTRY_KERNEL) kgsl_driver.stats.mapped -= entry->memdesc.size; @@ -217,7 +240,7 @@ kgsl_mem_entry_destroy(struct kref *kref) fput(entry->priv_data); break; case KGSL_MEM_ENTRY_ION: - ion_free(kgsl_ion_client, entry->priv_data); + kgsl_destroy_ion(entry->priv_data); break; } @@ -226,23 +249,46 @@ kgsl_mem_entry_destroy(struct kref *kref) EXPORT_SYMBOL(kgsl_mem_entry_destroy); /** - * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree + * kgsl_mem_entry_track_gpuaddr - Insert a mem_entry in the address tree and + * assign it with a gpu address space before insertion * @process: the process that owns the memory * @entry: the memory entry * - * Insert a kgsl_mem_entry in to the rb_tree for searching by GPU address. - * Not all mem_entries will have gpu addresses when first created, so this - * function may be called after creation when the GPU address is finally - * assigned. + * @returns - 0 on succcess else error code + * + * Insert the kgsl_mem_entry in to the rb_tree for searching by GPU address. + * The assignment of gpu address and insertion into list needs to + * happen with the memory lock held to avoid race conditions between + * gpu address being selected and some other thread looking through the + * rb list in search of memory based on gpuaddr + * This function should be called with processes memory spinlock held */ -static void +static int kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, struct kgsl_mem_entry *entry) { + int ret = 0; struct rb_node **node; struct rb_node *parent = NULL; - spin_lock(&process->mem_lock); + assert_spin_locked(&process->mem_lock); + /* + * If cpu=gpu map is used then caller needs to set the + * gpu address + */ + if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { + if (!entry->memdesc.gpuaddr) + goto done; + } else if (entry->memdesc.gpuaddr) { + WARN_ONCE(1, "gpuaddr assigned w/o holding memory lock\n"); + ret = -EINVAL; + goto done; + } + if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) { + ret = kgsl_mmu_get_gpuaddr(process->pagetable, &entry->memdesc); + if (ret) + goto done; + } node = &process->mem_rb.rb_node; @@ -261,7 +307,27 @@ kgsl_mem_entry_track_gpuaddr(struct kgsl_process_private *process, rb_link_node(&entry->node, parent, node); rb_insert_color(&entry->node, &process->mem_rb); - spin_unlock(&process->mem_lock); +done: + return ret; +} + +/** + * kgsl_mem_entry_untrack_gpuaddr() - Untrack memory that is previously tracked + * process - Pointer to process private to which memory belongs + * entry - Memory entry to untrack + * + * Function just does the opposite of kgsl_mem_entry_track_gpuaddr. Needs to be + * called with processes spin lock held + */ +static void +kgsl_mem_entry_untrack_gpuaddr(struct kgsl_process_private *process, + struct kgsl_mem_entry *entry) +{ + assert_spin_locked(&process->mem_lock); + if (entry->memdesc.gpuaddr) { + kgsl_mmu_put_gpuaddr(process->pagetable, &entry->memdesc); + rb_erase(&entry->node, &entry->priv->mem_rb); + } } /** @@ -300,8 +366,19 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, } entry->priv = process; - if (entry->memdesc.gpuaddr != 0) - kgsl_mem_entry_track_gpuaddr(process, entry); + spin_lock(&process->mem_lock); + ret = kgsl_mem_entry_track_gpuaddr(process, entry); + if (ret) + idr_remove(&process->mem_idr, entry->id); + spin_unlock(&process->mem_lock); + if (ret) + goto err; + /* map the memory after unlocking if gpuaddr has been assigned */ + if (entry->memdesc.gpuaddr) { + ret = kgsl_mmu_map(process->pagetable, &entry->memdesc); + if (ret) + kgsl_mem_entry_detach_process(entry); + } err: return ret; } @@ -310,37 +387,23 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry, static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) { - bool had_gpuaddr = false; - if (entry == NULL) return; - /* - * Unmap the entry first so that there isn't a period of - * time where kgsl doesn't know about the address range - * but it is still present in the pagetable. Unmapping will - * clear the gpuaddr field, so remember if we had a mapping, - * and an rbtree entry for later. - */ - had_gpuaddr = entry->memdesc.gpuaddr != 0; - kgsl_mmu_unmap(entry->memdesc.pagetable, &entry->memdesc); + /* Unmap here so that below we can call kgsl_mmu_put_gpuaddr */ + kgsl_mmu_unmap(entry->priv->pagetable, &entry->memdesc); spin_lock(&entry->priv->mem_lock); + kgsl_mem_entry_untrack_gpuaddr(entry->priv, entry); if (entry->id != 0) idr_remove(&entry->priv->mem_idr, entry->id); entry->id = 0; - if (had_gpuaddr) - rb_erase(&entry->node, &entry->priv->mem_rb); - + entry->priv->stats[entry->memtype].cur -= entry->memdesc.size; spin_unlock(&entry->priv->mem_lock); - entry->priv->stats[entry->memtype].cur -= entry->memdesc.size; entry->priv = NULL; - - - kgsl_mem_entry_put(entry); } /** @@ -353,7 +416,7 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) * function to initialize the common members of its context struct. * If this function succeeds, reference counting is active in the context * struct and the caller should kgsl_context_put() it on error. - * If it fails, the caller should just free the context structer + * If it fails, the caller should just free the context structure * it passed in. */ int kgsl_context_init(struct kgsl_device_private *dev_priv, @@ -391,15 +454,21 @@ int kgsl_context_init(struct kgsl_device_private *dev_priv, } kref_init(&context->refcount); + /* + * Get a refernce to the process private so its not destroyed, until + * the context is destroyed. This will also prevent the pagetable + * from being destroyed + */ + if (!kref_get_unless_zero(&dev_priv->process_priv->refcount)) + goto fail_free_id; context->device = dev_priv->device; - context->pagetable = dev_priv->process_priv->pagetable; - - context->pid = dev_priv->process_priv->pid; + context->dev_priv = dev_priv; + context->proc_priv = dev_priv->process_priv; + context->pid = task_tgid_nr(current); ret = kgsl_sync_timeline_create(context); - if (ret) { + if (ret) goto fail_free_id; - } /* Initialize the pending event list */ INIT_LIST_HEAD(&context->events); @@ -457,11 +526,12 @@ int kgsl_context_detach(struct kgsl_context *context) /* * Cancel events after the device-specific context is - * destroyed, to avoid possibly freeing memory while + * detached, to avoid possibly freeing memory while * it is still in use by the GPU. */ kgsl_context_cancel_events(device, context); + kgsl_context_put(context); return ret; @@ -485,6 +555,8 @@ kgsl_context_destroy(struct kref *kref) } write_unlock(&device->context_lock); kgsl_sync_timeline_destroy(context); + kgsl_put_process_private(device, + context->proc_priv); device->ftbl->drawctxt_destroy(context); } @@ -537,7 +609,6 @@ EXPORT_SYMBOL(kgsl_check_timestamp); static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) { int status = -EINVAL; - unsigned int nap_allowed_saved; struct kgsl_pwrscale_policy *policy_saved; if (!device) @@ -546,8 +617,6 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) KGSL_PWR_WARN(device, "suspend start\n"); mutex_lock(&device->mutex); - nap_allowed_saved = device->pwrctrl.nap_allowed; - device->pwrctrl.nap_allowed = false; policy_saved = device->pwrscale.policy; device->pwrscale.policy = NULL; kgsl_pwrctrl_request_state(device, KGSL_STATE_SUSPEND); @@ -556,7 +625,15 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) device->ftbl->drain(device); /* Wait for the active count to hit zero */ - kgsl_active_count_wait(device); + status = kgsl_active_count_wait(device, 0); + if (status) + goto end; + + /* + * An interrupt could have snuck in and requested NAP in + * the meantime, make sure we're on the SUSPEND path. + */ + kgsl_pwrctrl_request_state(device, KGSL_STATE_SUSPEND); /* Don't let the timer wake us during suspended sleep. */ del_timer_sync(&device->idle_timer); @@ -572,7 +649,7 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) INIT_COMPLETION(device->hwaccess_gate); device->ftbl->suspend_context(device); device->ftbl->stop(device); - pm_qos_update_request(&device->pm_qos_req_dma, + pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); kgsl_pwrctrl_set_state(device, KGSL_STATE_SUSPEND); break; @@ -586,20 +663,24 @@ static int kgsl_suspend_device(struct kgsl_device *device, pm_message_t state) goto end; } kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); - device->pwrctrl.nap_allowed = nap_allowed_saved; device->pwrscale.policy = policy_saved; status = 0; end: + if (status) { + /* On failure, re-resume normal activity */ + if (device->ftbl->resume) + device->ftbl->resume(device); + } + mutex_unlock(&device->mutex); KGSL_PWR_WARN(device, "suspend end\n"); + return status; } static int kgsl_resume_device(struct kgsl_device *device) { - int status = -EINVAL; - if (!device) return -EINVAL; @@ -607,14 +688,30 @@ static int kgsl_resume_device(struct kgsl_device *device) mutex_lock(&device->mutex); if (device->state == KGSL_STATE_SUSPEND) { kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER); - status = 0; complete_all(&device->hwaccess_gate); + } else if (device->state != KGSL_STATE_INIT) { + /* + * This is an error situation,so wait for the device + * to idle and then put the device to SLUMBER state. + * This will put the device to the right state when + * we resume. + */ + if (device->state == KGSL_STATE_ACTIVE) + device->ftbl->idle(device); + kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER); + kgsl_pwrctrl_sleep(device); + KGSL_PWR_ERR(device, + "resume invoked without a suspend\n"); } kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); + /* Call the GPU specific resume function */ + if (device->ftbl->resume) + device->ftbl->resume(device); + mutex_unlock(&device->mutex); KGSL_PWR_WARN(device, "resume end\n"); - return status; + return 0; } static int kgsl_suspend(struct device *dev) @@ -649,25 +746,6 @@ const struct dev_pm_ops kgsl_pm_ops = { }; EXPORT_SYMBOL(kgsl_pm_ops); -void kgsl_early_suspend_driver(struct early_suspend *h) -{ - struct kgsl_device *device = container_of(h, - struct kgsl_device, display_off); - KGSL_PWR_WARN(device, "early suspend start\n"); - mutex_lock(&device->mutex); - - /* Only go to slumber if active_cnt is 0 */ - if (atomic_read(&device->active_cnt) == 0) { - device->pwrctrl.restore_slumber = true; - kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER); - kgsl_pwrctrl_sleep(device); - } - - mutex_unlock(&device->mutex); - KGSL_PWR_WARN(device, "early suspend end\n"); -} -EXPORT_SYMBOL(kgsl_early_suspend_driver); - int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state) { @@ -683,38 +761,7 @@ int kgsl_resume_driver(struct platform_device *pdev) } EXPORT_SYMBOL(kgsl_resume_driver); -void kgsl_late_resume_driver(struct early_suspend *h) -{ - struct kgsl_device *device = container_of(h, - struct kgsl_device, display_off); - KGSL_PWR_WARN(device, "late resume start\n"); - mutex_lock(&device->mutex); - device->pwrctrl.restore_slumber = false; - if (device->pwrscale.policy == NULL) - kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO); - if (kgsl_pwrctrl_wake(device) != 0) - return; - /* - * We don't have a way to go directly from - * a deeper sleep state to NAP, which is - * the desired state here. - * - * Except if active_cnt is non zero which means that - * we probably went to early_suspend with it non zero - * and thus the system is still in an active state. - */ - - if (atomic_read(&device->active_cnt) == 0) { - kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP); - kgsl_pwrctrl_sleep(device); - } - - mutex_unlock(&device->mutex); - KGSL_PWR_WARN(device, "late resume end\n"); -} -EXPORT_SYMBOL(kgsl_late_resume_driver); - -/* +/** * kgsl_destroy_process_private() - Cleanup function to free process private * @kref: - Pointer to object being destroyed's kref struct * Free struct object and all other resources attached to it. @@ -748,18 +795,18 @@ static void kgsl_destroy_process_private(struct kref *kref) list_del(&private->list); mutex_unlock(&kgsl_driver.process_mutex); - if (private->kobj.parent) + if (private->kobj.state_in_sysfs) kgsl_process_uninit_sysfs(private); if (private->debug_root) debugfs_remove_recursive(private->debug_root); while (1) { - rcu_read_lock(); + spin_lock(&private->mem_lock); entry = idr_get_next(&private->mem_idr, &next); - rcu_read_unlock(); + spin_unlock(&private->mem_lock); if (entry == NULL) break; - kgsl_mem_entry_detach_process(entry); + kgsl_mem_entry_put(entry); /* * Always start back at the beginning, to * ensure all entries are removed, @@ -767,8 +814,8 @@ static void kgsl_destroy_process_private(struct kref *kref) */ next = 0; } - kgsl_mmu_putpagetable(private->pagetable); idr_destroy(&private->mem_idr); + kgsl_mmu_putpagetable(private->pagetable); kfree(private); return; @@ -846,33 +893,62 @@ kgsl_get_process_private(struct kgsl_device_private *cur_dev_priv) mutex_lock(&private->process_private_mutex); - if (!private->mem_rb.rb_node) { - private->mem_rb = RB_ROOT; - idr_init(&private->mem_idr); - } + /* + * If debug root initialized then it means the rest of the fields + * are also initialized + */ + if (private->debug_root) + goto done; + + private->mem_rb = RB_ROOT; + idr_init(&private->mem_idr); if ((!private->pagetable) && kgsl_mmu_enabled()) { unsigned long pt_name; + struct kgsl_mmu *mmu = &cur_dev_priv->device->mmu; pt_name = task_tgid_nr(current); - private->pagetable = kgsl_mmu_getpagetable(pt_name); - if (private->pagetable == NULL) { - mutex_unlock(&private->process_private_mutex); - kgsl_put_process_private(cur_dev_priv->device, - private); - return NULL; - } + private->pagetable = kgsl_mmu_getpagetable(mmu, pt_name); + if (private->pagetable == NULL) + goto error; } - if (!private->kobj.parent) - kgsl_process_init_sysfs(private); - if (!private->debug_root) - kgsl_process_init_debugfs(private); + if (kgsl_process_init_sysfs(cur_dev_priv->device, private)) + goto error; + if (kgsl_process_init_debugfs(private)) + goto error; +done: mutex_unlock(&private->process_private_mutex); - return private; + +error: + mutex_unlock(&private->process_private_mutex); + kgsl_put_process_private(cur_dev_priv->device, private); + return NULL; +} + +int kgsl_close_device(struct kgsl_device *device) +{ + int result = 0; + device->open_count--; + if (device->open_count == 0) { + + /* Wait for the active count to go to 0 */ + kgsl_active_count_wait(device, 0); + + /* Fail if the wait times out */ + BUG_ON(atomic_read(&device->active_cnt) > 0); + + /* Force power on to do the stop */ + kgsl_pwrctrl_enable(device); + result = device->ftbl->stop(device); + kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); + } + return result; + } +EXPORT_SYMBOL(kgsl_close_device); static int kgsl_release(struct inode *inodep, struct file *filep) { @@ -886,7 +962,6 @@ static int kgsl_release(struct inode *inodep, struct file *filep) filep->private_data = NULL; mutex_lock(&device->mutex); - kgsl_active_count_get(device); while (1) { read_lock(&device->context_lock); @@ -896,16 +971,16 @@ static int kgsl_release(struct inode *inodep, struct file *filep) if (context == NULL) break; - - if (context->pid == private->pid) { + if (context->dev_priv == dev_priv) { /* * Hold a reference to the context in case somebody * tries to put it while we are detaching */ - _kgsl_context_get(context); - kgsl_context_detach(context); - kgsl_context_put(context); + if (_kgsl_context_get(context)) { + kgsl_context_detach(context); + kgsl_context_put(context); + } } next = next + 1; @@ -918,19 +993,7 @@ static int kgsl_release(struct inode *inodep, struct file *filep) */ kgsl_cancel_events(device, dev_priv); - device->open_count--; - if (device->open_count == 0) { - BUG_ON(atomic_read(&device->active_cnt) > 1); - result = device->ftbl->stop(device); - kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); - /* - * active_cnt special case: we just stopped the device, - * so no need to use kgsl_active_count_put() - */ - atomic_dec(&device->active_cnt); - } else { - kgsl_active_count_put(device); - } + result = kgsl_close_device(device); mutex_unlock(&device->mutex); kfree(dev_priv); @@ -940,6 +1003,43 @@ static int kgsl_release(struct inode *inodep, struct file *filep) return result; } +int kgsl_open_device(struct kgsl_device *device) +{ + int result = 0; + if (device->open_count == 0) { + /* + * active_cnt special case: we are starting up for the first + * time, so use this sequence instead of the kgsl_pwrctrl_wake() + * which will be called by kgsl_active_count_get(). + */ + atomic_inc(&device->active_cnt); + kgsl_sharedmem_set(device, &device->memstore, 0, 0, + device->memstore.size); + + result = device->ftbl->init(device); + if (result) + goto err; + + result = device->ftbl->start(device); + if (result) + goto err; + /* + * Make sure the gates are open, so they don't block until + * we start suspend or FT. + */ + complete_all(&device->hwaccess_gate); + kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); + kgsl_active_count_put(device); + } + device->open_count++; +err: + if (result) + atomic_dec(&device->active_cnt); + + return result; +} +EXPORT_SYMBOL(kgsl_open_device); + static int kgsl_open(struct inode *inodep, struct file *filep) { int result; @@ -977,28 +1077,9 @@ static int kgsl_open(struct inode *inodep, struct file *filep) mutex_lock(&device->mutex); - if (device->open_count == 0) { - /* - * active_cnt special case: we are starting up for the first - * time, so use this sequence instead of the kgsl_pwrctrl_wake() - * which will be called by kgsl_active_count_get(). - */ - atomic_inc(&device->active_cnt); - kgsl_sharedmem_set(&device->memstore, 0, 0, - device->memstore.size); - - result = device->ftbl->init(device); - if (result) - goto err_freedevpriv; - - result = device->ftbl->start(device); - if (result) - goto err_freedevpriv; - - kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); - kgsl_active_count_put(device); - } - device->open_count++; + result = kgsl_open_device(device); + if (result) + goto err_freedevpriv; mutex_unlock(&device->mutex); /* @@ -1026,12 +1107,9 @@ static int kgsl_open(struct inode *inodep, struct file *filep) kgsl_pwrctrl_enable(device); result = device->ftbl->stop(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_INIT); + atomic_dec(&device->active_cnt); } err_freedevpriv: - /* only the first open takes an active count */ - if (device->open_count == 0) - atomic_dec(&device->active_cnt); - mutex_unlock(&device->mutex); filep->private_data = NULL; kfree(dev_priv); @@ -1054,19 +1132,21 @@ struct kgsl_mem_entry * __must_check kgsl_sharedmem_find_region(struct kgsl_process_private *private, unsigned int gpuaddr, size_t size) { - struct rb_node *node = private->mem_rb.rb_node; + struct rb_node *node; - if (!kgsl_mmu_gpuaddr_in_range(gpuaddr)) + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr)) return NULL; spin_lock(&private->mem_lock); + node = private->mem_rb.rb_node; while (node != NULL) { struct kgsl_mem_entry *entry; entry = rb_entry(node, struct kgsl_mem_entry, node); if (kgsl_gpuaddr_in_memdesc(&entry->memdesc, gpuaddr, size)) { - kgsl_mem_entry_get(entry); + if (!kgsl_mem_entry_get(entry)) + break; spin_unlock(&private->mem_lock); return entry; } @@ -1109,25 +1189,27 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, unsigned int gpuaddr) * @size: length of the region. * * Checks that there are no existing allocations within an address - * region. + * region. This function should be called with processes spin lock + * held. */ -int +static int kgsl_sharedmem_region_empty(struct kgsl_process_private *private, unsigned int gpuaddr, size_t size) { int result = 1; unsigned int gpuaddr_end = gpuaddr + size; - struct rb_node *node = private->mem_rb.rb_node; + struct rb_node *node; + + assert_spin_locked(&private->mem_lock); - if (!kgsl_mmu_gpuaddr_in_range(gpuaddr)) + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, gpuaddr)) return 0; /* don't overflow */ if (gpuaddr_end < gpuaddr) return 0; - spin_lock(&private->mem_lock); node = private->mem_rb.rb_node; while (node != NULL) { struct kgsl_mem_entry *entry; @@ -1148,7 +1230,6 @@ kgsl_sharedmem_region_empty(struct kgsl_process_private *private, break; } } - spin_unlock(&private->mem_lock); return result; } @@ -1165,17 +1246,44 @@ kgsl_sharedmem_region_empty(struct kgsl_process_private *private, static inline struct kgsl_mem_entry * __must_check kgsl_sharedmem_find_id(struct kgsl_process_private *process, unsigned int id) { + int result = 0; struct kgsl_mem_entry *entry; - rcu_read_lock(); + spin_lock(&process->mem_lock); entry = idr_find(&process->mem_idr, id); if (entry) - kgsl_mem_entry_get(entry); - rcu_read_unlock(); + result = kgsl_mem_entry_get(entry); + spin_unlock(&process->mem_lock); + if (!result) + return NULL; return entry; } +/** + * kgsl_mem_entry_set_pend() - Set the pending free flag of a memory entry + * @entry - The memory entry + * + * @returns - true if pending flag was 0 else false + * + * This function will set the pending free flag if it is previously unset. Used + * to prevent race condition between ioctls calling free/freememontimestamp + * on the same entry. Whichever thread set's the flag first will do the free. + */ +static inline bool kgsl_mem_entry_set_pend(struct kgsl_mem_entry *entry) +{ + bool ret = false; + spin_lock(&entry->priv->mem_lock); + if (entry && entry->pending_free) { + ret = false; + } else if (entry) { + entry->pending_free = 1; + ret = true; + } + spin_unlock(&entry->priv->mem_lock); + return ret; +} + /*call all ioctl sub functions with driver locked*/ static long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv, unsigned int cmd, void *data) @@ -1340,6 +1448,7 @@ static long kgsl_ioctl_device_waittimestamp_ctxtid(struct kgsl_device_private * @timestamp: Pending timestamp for the event * @handle: Pointer to a sync fence handle * @device: Pointer to the KGSL device + * @refcount: Allow event to be destroyed asynchronously */ struct kgsl_cmdbatch_sync_event { int type; @@ -1349,9 +1458,36 @@ struct kgsl_cmdbatch_sync_event { unsigned int timestamp; struct kgsl_sync_fence_waiter *handle; struct kgsl_device *device; - spinlock_t lock; + struct kref refcount; }; +/** + * kgsl_cmdbatch_sync_event_destroy() - Destroy a sync event object + * @kref: Pointer to the kref structure for this object + * + * Actually destroy a sync event object. Called from + * kgsl_cmdbatch_sync_event_put. + */ +static void kgsl_cmdbatch_sync_event_destroy(struct kref *kref) +{ + struct kgsl_cmdbatch_sync_event *event = container_of(kref, + struct kgsl_cmdbatch_sync_event, refcount); + + kgsl_cmdbatch_put(event->cmdbatch); + kfree(event); +} + +/** + * kgsl_cmdbatch_sync_event_put() - Decrement the refcount for a + * sync event object + * @event: Pointer to the sync event object + */ +static inline void kgsl_cmdbatch_sync_event_put( + struct kgsl_cmdbatch_sync_event *event) +{ + kref_put(&event->refcount, kgsl_cmdbatch_sync_event_destroy); +} + /** * kgsl_cmdbatch_destroy_object() - Destroy a cmdbatch object * @kref: Pointer to the kref structure for this object @@ -1370,13 +1506,32 @@ void kgsl_cmdbatch_destroy_object(struct kref *kref) } EXPORT_SYMBOL(kgsl_cmdbatch_destroy_object); +/* + * a generic function to retire a pending sync event and (possibly) + * kick the dispatcher + */ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device, struct kgsl_cmdbatch_sync_event *event) { + struct kgsl_cmdbatch_sync_event *e, *tmp; int sched = 0; + int removed = 0; spin_lock(&event->cmdbatch->lock); - list_del(&event->node); + + /* + * sync events that are contained by a cmdbatch which has been + * destroyed may have already been removed from the synclist + */ + + list_for_each_entry_safe(e, tmp, &event->cmdbatch->synclist, node) { + if (e == event) { + list_del_init(&event->node); + removed = 1; + break; + } + } + sched = list_empty(&event->cmdbatch->synclist) ? 1 : 0; spin_unlock(&event->cmdbatch->lock); @@ -1387,6 +1542,10 @@ static void kgsl_cmdbatch_sync_expire(struct kgsl_device *device, if (sched && device->ftbl->drawctxt_sched) device->ftbl->drawctxt_sched(device, event->cmdbatch->context); + + /* Put events that have been removed from the synclist */ + if (removed) + kgsl_cmdbatch_sync_event_put(event); } @@ -1400,11 +1559,9 @@ static void kgsl_cmdbatch_sync_func(struct kgsl_device *device, void *priv, struct kgsl_cmdbatch_sync_event *event = priv; kgsl_cmdbatch_sync_expire(device, event); - kgsl_context_put(event->context); - kgsl_cmdbatch_put(event->cmdbatch); - - kfree(event); + /* Put events that have signaled */ + kgsl_cmdbatch_sync_event_put(event); } /** @@ -1412,64 +1569,63 @@ static void kgsl_cmdbatch_sync_func(struct kgsl_device *device, void *priv, * @cmdbatch: Pointer to the command batch object to destroy * * Start the process of destroying a command batch. Cancel any pending events - * and decrement the refcount. + * and decrement the refcount. Asynchronous events can still signal after + * kgsl_cmdbatch_destroy has returned. */ void kgsl_cmdbatch_destroy(struct kgsl_cmdbatch *cmdbatch) { struct kgsl_cmdbatch_sync_event *event, *tmp; - int canceled = 0; + LIST_HEAD(cancel_synclist); + /* + * Empty the synclist before canceling events + */ spin_lock(&cmdbatch->lock); + list_splice_init(&cmdbatch->synclist, &cancel_synclist); + spin_unlock(&cmdbatch->lock); - /* Delete any pending sync points for this command batch */ - list_for_each_entry_safe(event, tmp, &cmdbatch->synclist, node) { + /* + * Finish canceling events outside the cmdbatch spinlock and + * require the cancel function to return if the event was + * successfully canceled meaning that the event is guaranteed + * not to signal the callback. This guarantee ensures that + * the reference count for the event and cmdbatch is correct. + */ + list_for_each_entry_safe(event, tmp, &cancel_synclist, node) { - switch (event->type) { - case KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP: { - /* Cancel the event if it still exists */ - mutex_lock(&cmdbatch->device->mutex); + if (event->type == KGSL_CMD_SYNCPOINT_TYPE_TIMESTAMP) { + /* + * Timestamp events are guaranteed to signal + * when canceled + */ kgsl_cancel_event(cmdbatch->device, event->context, event->timestamp, kgsl_cmdbatch_sync_func, event); - canceled = 1; - mutex_unlock(&cmdbatch->device->mutex); - kgsl_context_put(event->context); - break; - } - case KGSL_CMD_SYNCPOINT_TYPE_FENCE: - canceled = kgsl_sync_fence_async_cancel(event->handle); - break; - default: - break; + } else if (event->type == KGSL_CMD_SYNCPOINT_TYPE_FENCE) { + /* Put events that are successfully canceled */ + if (kgsl_sync_fence_async_cancel(event->handle)) + kgsl_cmdbatch_sync_event_put(event); } - if(canceled) { - list_del(&event->node); - kfree(event); - - /* - * Put back a instance of the cmdbatch for each pending event - * that we canceled - */ - - kgsl_cmdbatch_put(cmdbatch); - } + /* Put events that have been removed from the synclist */ + list_del_init(&event->node); + kgsl_cmdbatch_sync_event_put(event); } - spin_unlock(&cmdbatch->lock); - kgsl_cmdbatch_put(cmdbatch); } EXPORT_SYMBOL(kgsl_cmdbatch_destroy); +/* + * A callback that gets registered with kgsl_sync_fence_async_wait and is fired + * when a fence is expired + */ static void kgsl_cmdbatch_sync_fence_func(void *priv) { struct kgsl_cmdbatch_sync_event *event = priv; - spin_lock(&event->lock); kgsl_cmdbatch_sync_expire(event->device, event); - kgsl_cmdbatch_put(event->cmdbatch); - spin_unlock(&event->lock); - kfree(event); + /* Put events that have signaled */ + kgsl_cmdbatch_sync_event_put(event); } /* kgsl_cmdbatch_add_sync_fence() - Add a new sync fence syncpoint @@ -1495,28 +1651,33 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, event->type = KGSL_CMD_SYNCPOINT_TYPE_FENCE; event->cmdbatch = cmdbatch; event->device = device; - spin_lock_init(&event->lock); + event->context = NULL; + + /* + * Initial kref is to ensure async callback does not free the + * event before this function sets the event handle + */ + kref_init(&event->refcount); /* * Add it to the list first to account for the possiblity that the * callback will happen immediately after the call to - * kgsl_sync_fence_async_wait + * kgsl_sync_fence_async_wait. Decrement the event refcount when + * removing from the synclist. */ spin_lock(&cmdbatch->lock); + kref_get(&event->refcount); list_add(&event->node, &cmdbatch->synclist); spin_unlock(&cmdbatch->lock); /* - * There is a distinct race condition that can occur if the fence - * callback is fired before the function has a chance to return. The - * event struct would be freed before we could write event->handle and - * hilarity ensued. Protect against this by protecting the call to - * kgsl_sync_fence_async_wait and the kfree in the callback with a lock. + * Increment the reference count for the async callback. + * Decrement when the callback is successfully canceled, when + * the callback is signaled or if the async wait fails. */ - spin_lock(&event->lock); - + kref_get(&event->refcount); event->handle = kgsl_sync_fence_async_wait(sync->fd, kgsl_cmdbatch_sync_fence_func, event); @@ -1524,18 +1685,27 @@ static int kgsl_cmdbatch_add_sync_fence(struct kgsl_device *device, if (IS_ERR_OR_NULL(event->handle)) { int ret = PTR_ERR(event->handle); + /* Failed to add the event to the async callback */ + kgsl_cmdbatch_sync_event_put(event); + + /* Remove event from the synclist */ spin_lock(&cmdbatch->lock); list_del(&event->node); + kgsl_cmdbatch_sync_event_put(event); spin_unlock(&cmdbatch->lock); - kgsl_cmdbatch_put(cmdbatch); - spin_unlock(&event->lock); - kfree(event); + /* Event no longer needed by this function */ + kgsl_cmdbatch_sync_event_put(event); return ret; } - spin_unlock(&event->lock); + /* + * Event was successfully added to the synclist, the async + * callback and handle to cancel event has been set. + */ + kgsl_cmdbatch_sync_event_put(event); + return 0; } @@ -1558,11 +1728,23 @@ static int kgsl_cmdbatch_add_sync_timestamp(struct kgsl_device *device, if (context == NULL) return -EINVAL; - /* Sanity check - you can't create a sync point on your own context */ + /* + * We allow somebody to create a sync point on their own context. + * This has the effect of delaying a command from submitting until the + * dependent command has cleared. That said we obviously can't let them + * create a sync point on a future timestamp. + */ + if (context == cmdbatch->context) { - KGSL_DRV_ERR(device, - "Cannot create a sync point on your own context\n"); - goto done; + unsigned int queued = kgsl_readtimestamp(device, context, + KGSL_TIMESTAMP_QUEUED); + + if (timestamp_cmp(sync->timestamp, queued) > 0) { + KGSL_DRV_ERR(device, + "Cannot create syncpoint for future timestamp %d (current %d)\n", + sync->timestamp, queued); + goto done; + } } event = kzalloc(sizeof(*event), GFP_KERNEL); @@ -1578,15 +1760,24 @@ static int kgsl_cmdbatch_add_sync_timestamp(struct kgsl_device *device, event->context = context; event->timestamp = sync->timestamp; + /* + * Two krefs are required to support events. The first kref is for + * the synclist which holds the event in the cmdbatch. The second + * kref is for the callback which can be asynchronous and be called + * after kgsl_cmdbatch_destroy. The kref should be put when the event + * is removed from the synclist, if the callback is successfully + * canceled or when the callback is signaled. + */ + kref_init(&event->refcount); + kref_get(&event->refcount); + spin_lock(&cmdbatch->lock); list_add(&event->node, &cmdbatch->synclist); spin_unlock(&cmdbatch->lock); mutex_lock(&device->mutex); - kgsl_active_count_get(device); ret = kgsl_add_event(device, context->id, sync->timestamp, kgsl_cmdbatch_sync_func, event, NULL); - kgsl_active_count_put(device); mutex_unlock(&device->mutex); if (ret) { @@ -1674,10 +1865,21 @@ static struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device, if (cmdbatch == NULL) return ERR_PTR(-ENOMEM); + /* + * Increase the reference count on the context so it doesn't disappear + * during the lifetime of this command batch + */ + + if (!_kgsl_context_get(context)) { + kfree(cmdbatch); + return ERR_PTR(-EINVAL); + } + if (!(flags & KGSL_CONTEXT_SYNC)) { cmdbatch->ibdesc = kzalloc(sizeof(*cmdbatch->ibdesc) * numibs, GFP_KERNEL); if (cmdbatch->ibdesc == NULL) { + kgsl_context_put(context); kfree(cmdbatch); return ERR_PTR(-ENOMEM); } @@ -1690,13 +1892,7 @@ static struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device, cmdbatch->device = device; cmdbatch->ibcount = (flags & KGSL_CONTEXT_SYNC) ? 0 : numibs; cmdbatch->context = context; - cmdbatch->flags = flags; - - /* - * Increase the reference count on the context so it doesn't disappear - * during the lifetime of this command batch - */ - _kgsl_context_get(context); + cmdbatch->flags = flags & ~KGSL_CONTEXT_SUBMIT_IB_LIST; return cmdbatch; } @@ -1709,22 +1905,32 @@ static struct kgsl_cmdbatch *kgsl_cmdbatch_create(struct kgsl_device *device, * Do a quick sanity test on the list of indirect buffers in a command batch * verifying that the size and GPU address */ -static bool _kgsl_cmdbatch_verify(struct kgsl_device *device, +static bool _kgsl_cmdbatch_verify(struct kgsl_device_private *dev_priv, struct kgsl_cmdbatch *cmdbatch) { int i; + struct kgsl_process_private *private = dev_priv->process_priv; + for (i = 0; i < cmdbatch->ibcount; i++) { if (cmdbatch->ibdesc[i].sizedwords == 0) { - KGSL_DRV_ERR(device, - "Invalid IB: size is 0\n"); + KGSL_DRV_ERR(dev_priv->device, + "invalid size ctx %d ib(%d) %X/%X\n", + cmdbatch->context->id, i, + cmdbatch->ibdesc[i].gpuaddr, + cmdbatch->ibdesc[i].sizedwords); + return false; } - if (!kgsl_mmu_gpuaddr_in_range(cmdbatch->ibdesc[i].gpuaddr)) { - KGSL_DRV_ERR(device, - "Invalid IB: address 0x%X is out of range\n", - cmdbatch->ibdesc[i].gpuaddr); + if (!kgsl_mmu_gpuaddr_in_range(private->pagetable, + cmdbatch->ibdesc[i].gpuaddr)) { + KGSL_DRV_ERR(dev_priv->device, + "Invalid address ctx %d ib(%d) %X/%X\n", + cmdbatch->context->id, i, + cmdbatch->ibdesc[i].gpuaddr, + cmdbatch->ibdesc[i].sizedwords); + return false; } } @@ -1820,8 +2026,6 @@ static struct kgsl_cmdbatch *_kgsl_cmdbatch_create(struct kgsl_device *device, return ERR_PTR(ret); } - cmdbatch->flags = flags; - return cmdbatch; } @@ -1849,7 +2053,7 @@ static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv, * submission */ - if (param->numibs == 0 || param->numibs > 100000) + if (param->numibs == 0 || param->numibs > KGSL_MAX_NUMIBS) goto done; cmdbatch = _kgsl_cmdbatch_create(device, context, param->flags, @@ -1863,10 +2067,8 @@ static long kgsl_ioctl_rb_issueibcmds(struct kgsl_device_private *dev_priv, } /* Run basic sanity checking on the command */ - if (!_kgsl_cmdbatch_verify(device, cmdbatch)) { - KGSL_DRV_ERR(device, "Unable to verify the IBs\n"); + if (!_kgsl_cmdbatch_verify(dev_priv, cmdbatch)) goto free_cmdbatch; - } result = dev_priv->device->ftbl->issueibcmds(dev_priv, context, cmdbatch, ¶m->timestamp); @@ -1892,10 +2094,10 @@ static long kgsl_ioctl_submit_commands(struct kgsl_device_private *dev_priv, /* The number of IBs are completely ignored for sync commands */ if (!(param->flags & KGSL_CONTEXT_SYNC)) { - if (param->numcmds == 0 || param->numcmds > 100000) + if (param->numcmds == 0 || param->numcmds > KGSL_MAX_NUMIBS) return -EINVAL; } else if (param->numcmds != 0) { - KGSL_DRV_ERR(device, + KGSL_DEV_ERR_ONCE(device, "Commands specified with the SYNC flag. They will be ignored\n"); } @@ -1913,10 +2115,8 @@ static long kgsl_ioctl_submit_commands(struct kgsl_device_private *dev_priv, } /* Run basic sanity checking on the command */ - if (!_kgsl_cmdbatch_verify(device, cmdbatch)) { - KGSL_DRV_ERR(device, "Unable to verify the IBs\n"); + if (!_kgsl_cmdbatch_verify(dev_priv, cmdbatch)) goto free_cmdbatch; - } result = dev_priv->device->ftbl->issueibcmds(dev_priv, context, cmdbatch, ¶m->timestamp); @@ -1978,7 +2178,7 @@ static void kgsl_freemem_event_cb(struct kgsl_device *device, /* Free the memory for all event types */ trace_kgsl_mem_timestamp_free(device, entry, id, timestamp, 0); - kgsl_mem_entry_detach_process(entry); + kgsl_mem_entry_put(entry); } static long _cmdstream_freememontimestamp(struct kgsl_device_private *dev_priv, @@ -1997,6 +2197,13 @@ static long _cmdstream_freememontimestamp(struct kgsl_device_private *dev_priv, "invalid gpuaddr %08x\n", gpuaddr); return -EINVAL; } + if (!kgsl_mem_entry_set_pend(entry)) { + KGSL_DRV_WARN(dev_priv->device, + "Cannot set pending bit for gpuaddr %08x\n", gpuaddr); + kgsl_mem_entry_put(entry); + return -EBUSY; + } + trace_kgsl_mem_timestamp_queue(device, entry, context_id, kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED), @@ -2081,6 +2288,10 @@ static long kgsl_ioctl_sharedmem_free(struct kgsl_device_private *dev_priv, param->gpuaddr); return -EINVAL; } + if (!kgsl_mem_entry_set_pend(entry)) { + kgsl_mem_entry_put(entry); + return -EBUSY; + } trace_kgsl_mem_free(entry); @@ -2089,7 +2300,12 @@ static long kgsl_ioctl_sharedmem_free(struct kgsl_device_private *dev_priv, entry->memdesc.size, entry->memdesc.flags); - kgsl_mem_entry_detach_process(entry); + /* + * First kgsl_mem_entry_put is for the reference that we took in + * this function when calling kgsl_sharedmem_find, second one is + * to free the memory since this is a free ioctl + */ + kgsl_mem_entry_put(entry); kgsl_mem_entry_put(entry); return 0; } @@ -2107,9 +2323,20 @@ static long kgsl_ioctl_gpumem_free_id(struct kgsl_device_private *dev_priv, KGSL_MEM_INFO(dev_priv->device, "invalid id %d\n", param->id); return -EINVAL; } + + if (!kgsl_mem_entry_set_pend(entry)) { + kgsl_mem_entry_put(entry); + return -EBUSY; + } + trace_kgsl_mem_free(entry); - kgsl_mem_entry_detach_process(entry); + /* + * First kgsl_mem_entry_put is for the reference that we took in + * this function when calling kgsl_sharedmem_find_id, second one is + * to free the memory since this is a free ioctl + */ + kgsl_mem_entry_put(entry); kgsl_mem_entry_put(entry); return 0; } @@ -2142,11 +2369,10 @@ static int kgsl_get_phys_file(int fd, unsigned long *start, unsigned long *len, dev_t rdev; struct fb_info *info; + *start = 0; + *vstart = 0; + *len = 0; *filep = NULL; -#ifdef CONFIG_ANDROID_PMEM - if (!get_pmem_file(fd, start, vstart, len, filep)) - return 0; -#endif fbfile = fget(fd); if (fbfile == NULL) { @@ -2237,9 +2463,6 @@ static int kgsl_setup_phys_file(struct kgsl_mem_entry *entry, return 0; err: -#ifdef CONFIG_ANDROID_PMEM - put_pmem_file(filep); -#endif return ret; } @@ -2423,33 +2646,55 @@ static int kgsl_setup_ashmem(struct kgsl_mem_entry *entry, #endif static int kgsl_setup_ion(struct kgsl_mem_entry *entry, - struct kgsl_pagetable *pagetable, int fd) + struct kgsl_pagetable *pagetable, void *data, + struct kgsl_device *device) { - struct ion_handle *handle; struct scatterlist *s; struct sg_table *sg_table; + struct kgsl_map_user_mem *param = data; + int fd = param->fd; + struct dma_buf *dmabuf; + struct dma_buf_attachment *attach = NULL; + struct kgsl_dma_buf_meta *meta; + int ret = 0; - if (IS_ERR_OR_NULL(kgsl_ion_client)) - return -ENODEV; - - handle = ion_import_dma_buf(kgsl_ion_client, fd); - if (IS_ERR(handle)) - return PTR_ERR(handle); - else if (!handle) + if (!param->len) return -EINVAL; + meta = kzalloc(sizeof(*meta), GFP_KERNEL); + if (!meta) + return -ENOMEM; + + dmabuf = dma_buf_get(fd); + if (IS_ERR_OR_NULL(dmabuf)) { + ret = PTR_ERR(dmabuf); + goto out; + } + + attach = dma_buf_attach(dmabuf, device->dev); + if (IS_ERR_OR_NULL(attach)) { + ret = PTR_ERR(attach); + goto out; + } + + meta->dmabuf = dmabuf; + meta->attach = attach; + entry->memtype = KGSL_MEM_ENTRY_ION; - entry->priv_data = handle; entry->memdesc.pagetable = pagetable; entry->memdesc.size = 0; /* USE_CPU_MAP is not impemented for ION. */ entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; - sg_table = ion_sg_table(kgsl_ion_client, handle); + sg_table = dma_buf_map_attachment(attach, DMA_TO_DEVICE); - if (IS_ERR_OR_NULL(sg_table)) - goto err; + if (IS_ERR_OR_NULL(sg_table)) { + ret = PTR_ERR(sg_table); + goto out; + } + meta->table = sg_table; + entry->priv_data = meta; entry->memdesc.sg = sg_table->sgl; /* Calculate the size of the memdesc from the sglist */ @@ -2461,17 +2706,20 @@ static int kgsl_setup_ion(struct kgsl_mem_entry *entry, entry->memdesc.sglen++; } - return 0; -err: - ion_free(kgsl_ion_client, handle); - return -ENOMEM; -} + entry->memdesc.size = PAGE_ALIGN(entry->memdesc.size); -static inline int -can_use_cpu_map(void) -{ - return (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU - && kgsl_mmu_is_perprocess()); +out: + if (ret) { + if (!IS_ERR_OR_NULL(attach)) + dma_buf_detach(dmabuf, attach); + + if (!IS_ERR_OR_NULL(dmabuf)) + dma_buf_put(dmabuf); + + kfree(meta); + } + + return ret; } static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, @@ -2505,7 +2753,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, | KGSL_MEMFLAGS_USE_CPU_MAP; entry->memdesc.flags = param->flags; - if (!can_use_cpu_map()) + if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu)) entry->memdesc.flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU) @@ -2559,8 +2807,8 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, entry->memtype = KGSL_MEM_ENTRY_ASHMEM; break; case KGSL_USER_MEM_TYPE_ION: - result = kgsl_setup_ion(entry, private->pagetable, - param->fd); + result = kgsl_setup_ion(entry, private->pagetable, data, + dev_priv->device); break; default: KGSL_CORE_ERR("Invalid memory type: %x\n", memtype); @@ -2575,18 +2823,15 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, else if (entry->memdesc.size >= SZ_64K) kgsl_memdesc_set_align(&entry->memdesc, ilog2(SZ_64)); - result = kgsl_mmu_map(private->pagetable, &entry->memdesc); - if (result) - goto error_put_file_ptr; - - /* Adjust the returned value for a non 4k aligned offset */ - param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK); /* echo back flags */ param->flags = entry->memdesc.flags; result = kgsl_mem_entry_attach_process(entry, private); if (result) - goto error_unmap; + goto error_attach; + + /* Adjust the returned value for a non 4k aligned offset */ + param->gpuaddr = entry->memdesc.gpuaddr + (param->offset & ~PAGE_MASK); KGSL_STATS_ADD(param->len, kgsl_driver.stats.mapped, kgsl_driver.stats.mapped_max); @@ -2597,9 +2842,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, return result; -error_unmap: - kgsl_mmu_unmap(private->pagetable, &entry->memdesc); -error_put_file_ptr: +error_attach: switch (entry->memtype) { case KGSL_MEM_ENTRY_PMEM: case KGSL_MEM_ENTRY_ASHMEM: @@ -2607,7 +2850,7 @@ static long kgsl_ioctl_map_user_mem(struct kgsl_device_private *dev_priv, fput(entry->priv_data); break; case KGSL_MEM_ENTRY_ION: - ion_free(kgsl_ion_client, entry->priv_data); + kgsl_destroy_ion(entry->priv_data); break; default: break; @@ -2753,7 +2996,8 @@ kgsl_ioctl_gpumem_sync_cache_bulk(struct kgsl_device_private *dev_priv, entries[actual_count++] = entry; /* If we exceed the breakeven point, flush the entire cache */ - if (op_size >= kgsl_driver.full_cache_threshold && + if (kgsl_driver.full_cache_threshold != 0 && + op_size >= kgsl_driver.full_cache_threshold && param->op == KGSL_GPUMEM_CACHE_FLUSH) { full_flush = true; break; @@ -2812,6 +3056,7 @@ _gpumem_alloc(struct kgsl_device_private *dev_priv, int result; struct kgsl_process_private *private = dev_priv->process_priv; struct kgsl_mem_entry *entry; + int align; /* * Mask off unknown flags from userspace. This way the caller can @@ -2823,6 +3068,15 @@ _gpumem_alloc(struct kgsl_device_private *dev_priv, | KGSL_MEMALIGN_MASK | KGSL_MEMFLAGS_USE_CPU_MAP; + /* Cap the alignment bits to the highest number we can handle */ + + align = (flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT; + if (align >= 32) { + KGSL_CORE_ERR("Alignment too big, restricting to 2^32\n"); + flags &= ~KGSL_MEMALIGN_MASK; + flags |= (31 << KGSL_MEMALIGN_SHIFT) & KGSL_MEMALIGN_MASK; + } + entry = kgsl_mem_entry_create(); if (entry == NULL) return -ENOMEM; @@ -2859,10 +3113,6 @@ kgsl_ioctl_gpumem_alloc(struct kgsl_device_private *dev_priv, if (result) return result; - result = kgsl_mmu_map(private->pagetable, &entry->memdesc); - if (result) - goto err; - result = kgsl_mem_entry_attach_process(entry, private); if (result != 0) goto err; @@ -2889,19 +3139,13 @@ kgsl_ioctl_gpumem_alloc_id(struct kgsl_device_private *dev_priv, struct kgsl_mem_entry *entry = NULL; int result; - if (!can_use_cpu_map()) + if (!kgsl_mmu_use_cpu_map(private->pagetable->mmu)) param->flags &= ~KGSL_MEMFLAGS_USE_CPU_MAP; result = _gpumem_alloc(dev_priv, &entry, param->size, param->flags); if (result != 0) goto err; - if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) { - result = kgsl_mmu_map(private->pagetable, &entry->memdesc); - if (result) - goto err; - } - result = kgsl_mem_entry_attach_process(entry, private); if (result != 0) goto err; @@ -2985,7 +3229,8 @@ static long kgsl_ioctl_cff_user_event(struct kgsl_device_private *dev_priv, int result = 0; struct kgsl_cff_user_event *param = data; - kgsl_cffdump_user_event(param->cff_opcode, param->op1, param->op2, + kgsl_cffdump_user_event(dev_priv->device, param->cff_opcode, + param->op1, param->op2, param->op3, param->op4, param->op5); return result; @@ -3119,7 +3364,6 @@ typedef long (*kgsl_ioctl_func_t)(struct kgsl_device_private *, { .cmd = (_cmd), .func = (_func), .flags = (_flags) } #define KGSL_IOCTL_LOCK BIT(0) -#define KGSL_IOCTL_WAKE BIT(1) static const struct { unsigned int cmd; @@ -3128,13 +3372,13 @@ static const struct { } kgsl_ioctl_funcs[] = { KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_GETPROPERTY, kgsl_ioctl_device_getproperty, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP, kgsl_ioctl_device_waittimestamp, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID, kgsl_ioctl_device_waittimestamp_ctxtid, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS, kgsl_ioctl_rb_issueibcmds, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SUBMIT_COMMANDS, @@ -3147,16 +3391,16 @@ static const struct { KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP, kgsl_ioctl_cmdstream_freememontimestamp, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID, kgsl_ioctl_cmdstream_freememontimestamp_ctxtid, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_CREATE, kgsl_ioctl_drawctxt_create, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_DESTROY, kgsl_ioctl_drawctxt_destroy, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_MAP_USER_MEM, kgsl_ioctl_map_user_mem, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FROM_PMEM, @@ -3173,10 +3417,10 @@ static const struct { kgsl_ioctl_cff_user_event, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT, kgsl_ioctl_timestamp_event, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_SETPROPERTY, kgsl_ioctl_device_setproperty, - KGSL_IOCTL_LOCK | KGSL_IOCTL_WAKE), + KGSL_IOCTL_LOCK), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC_ID, kgsl_ioctl_gpumem_alloc_id, 0), KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_FREE_ID, @@ -3194,7 +3438,7 @@ static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) struct kgsl_device_private *dev_priv = filep->private_data; unsigned int nr; kgsl_ioctl_func_t func; - int lock, ret, use_hw; + int lock, ret; char ustack[64]; void *uptr = NULL; @@ -3252,7 +3496,6 @@ static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) func = kgsl_ioctl_funcs[nr].func; lock = kgsl_ioctl_funcs[nr].flags & KGSL_IOCTL_LOCK; - use_hw = kgsl_ioctl_funcs[nr].flags & KGSL_IOCTL_WAKE; } else { func = dev_priv->device->ftbl->ioctl; if (!func) { @@ -3262,28 +3505,21 @@ static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg) goto done; } lock = 1; - use_hw = 1; } - if (lock) { + if (lock) mutex_lock(&dev_priv->device->mutex); - if (use_hw) { - ret = kgsl_active_count_get(dev_priv->device); - if (ret < 0) - goto unlock; - } - } ret = func(dev_priv, cmd, uptr); -unlock: - if (lock) { - if (use_hw) - kgsl_active_count_put(dev_priv->device); + if (lock) mutex_unlock(&dev_priv->device->mutex); - } - if (ret == 0 && (cmd & IOC_OUT)) { + /* + * Still copy back on failure, but assume function took + * all necessary precautions sanitizing the return values. + */ + if (cmd & IOC_OUT) { if (copy_to_user((void __user *) arg, uptr, _IOC_SIZE(cmd))) ret = -EFAULT; } @@ -3333,7 +3569,8 @@ kgsl_mmap_memstore(struct kgsl_device *device, struct vm_area_struct *vma) static void kgsl_gpumem_vm_open(struct vm_area_struct *vma) { struct kgsl_mem_entry *entry = vma->vm_private_data; - kgsl_mem_entry_get(entry); + if (!kgsl_mem_entry_get(entry)) + vma->vm_private_data = NULL; } static int @@ -3341,6 +3578,8 @@ kgsl_gpumem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct kgsl_mem_entry *entry = vma->vm_private_data; + if (!entry) + return VM_FAULT_SIGBUS; if (!entry->memdesc.ops || !entry->memdesc.ops->vmfault) return VM_FAULT_SIGBUS; @@ -3352,6 +3591,9 @@ kgsl_gpumem_vm_close(struct vm_area_struct *vma) { struct kgsl_mem_entry *entry = vma->vm_private_data; + if (!entry) + return; + entry->memdesc.useraddr = 0; kgsl_mem_entry_put(entry); } @@ -3405,7 +3647,7 @@ get_mmap_entry(struct kgsl_process_private *private, static inline bool mmap_range_valid(unsigned long addr, unsigned long len) { - return (addr + len) > addr && (addr + len) < TASK_SIZE; + return ((ULONG_MAX - addr) > len) && ((addr + len) < TASK_SIZE); } static unsigned long @@ -3429,7 +3671,7 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, if (ret) return ret; - if (!kgsl_memdesc_use_cpu_map(&entry->memdesc) || (flags & MAP_FIXED)) { + if (!kgsl_memdesc_use_cpu_map(&entry->memdesc)) { /* * If we're not going to use the same mapping on the gpu, * any address is fine. @@ -3470,7 +3712,7 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, */ if (!retry && (ret == (unsigned long)-ENOMEM) && (align > PAGE_SHIFT)) { - align = PAGE_SHIFT; + align = 0; addr = 0; len = orig_len; retry = 1; @@ -3482,16 +3724,39 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, ret = ALIGN(ret, (1 << align)); /*make sure there isn't a GPU only mapping at this address */ - if (kgsl_sharedmem_region_empty(private, ret, len)) + spin_lock(&private->mem_lock); + if (kgsl_sharedmem_region_empty(private, ret, orig_len)) { + int ret_val; + /* + * We found a free memory map, claim it here with + * memory lock held + */ + entry->memdesc.gpuaddr = ret; + /* This should never fail */ + ret_val = kgsl_mem_entry_track_gpuaddr(private, entry); + spin_unlock(&private->mem_lock); + BUG_ON(ret_val); + /* map cannot be called with lock held */ + ret_val = kgsl_mmu_map(private->pagetable, + &entry->memdesc); + if (ret_val) { + spin_lock(&private->mem_lock); + kgsl_mem_entry_untrack_gpuaddr(private, entry); + spin_unlock(&private->mem_lock); + ret = ret_val; + } break; + } + spin_unlock(&private->mem_lock); - trace_kgsl_mem_unmapped_area_collision(entry, addr, len, ret); + trace_kgsl_mem_unmapped_area_collision(entry, addr, orig_len, + ret); /* * If we collided, bump the hint address so that * get_umapped_area knows to look somewhere else. */ - addr = (addr == 0) ? ret + len : addr + len; + addr = (addr == 0) ? ret + orig_len : addr + orig_len; /* * The addr hint can be set by userspace to be near @@ -3505,10 +3770,10 @@ kgsl_get_unmapped_area(struct file *file, unsigned long addr, } else { ret = -EBUSY; } - } while (mmap_range_valid(addr, len)); + } while (!(flags & MAP_FIXED) && mmap_range_valid(addr, len)); if (IS_ERR_VALUE(ret)) - KGSL_MEM_INFO(device, + KGSL_MEM_ERR(device, "pid %d pgoff %lx len %ld failed error %ld\n", private->pid, pgoff, len, ret); put: @@ -3539,17 +3804,6 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma) if (ret) return ret; - if (kgsl_memdesc_use_cpu_map(&entry->memdesc)) { - entry->memdesc.gpuaddr = vma->vm_start; - - ret = kgsl_mmu_map(private->pagetable, &entry->memdesc); - if (ret) { - kgsl_mem_entry_put(entry); - return ret; - } - kgsl_mem_entry_track_gpuaddr(private, entry); - } - vma->vm_flags |= entry->memdesc.ops->vmflags(&entry->memdesc); vma->vm_private_data = entry; @@ -3710,8 +3964,7 @@ int kgsl_device_platform_probe(struct kgsl_device *device) if (status) goto error; - kgsl_ion_client = msm_ion_client_create(UINT_MAX, KGSL_NAME); - + /* Get starting physical address of device registers */ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, device->iomemname); if (res == NULL) { @@ -3729,6 +3982,33 @@ int kgsl_device_platform_probe(struct kgsl_device *device) device->reg_phys = res->start; device->reg_len = resource_size(res); + /* + * Check if a shadermemname is defined, and then get shader memory + * details including shader memory starting physical address + * and shader memory length + */ + if (device->shadermemname != NULL) { + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, + device->shadermemname); + + if (res == NULL) { + KGSL_DRV_ERR(device, + "Shader memory: platform_get_resource_byname failed\n"); + } + + else { + device->shader_mem_phys = res->start; + device->shader_mem_len = resource_size(res); + } + + if (!devm_request_mem_region(device->dev, + device->shader_mem_phys, + device->shader_mem_len, + device->name)) { + KGSL_DRV_ERR(device, "request_mem_region_failed\n"); + } + } + if (!devm_request_mem_region(device->dev, device->reg_phys, device->reg_len, device->name)) { KGSL_DRV_ERR(device, "request_mem_region failed\n"); @@ -3797,7 +4077,8 @@ int kgsl_device_platform_probe(struct kgsl_device *device) goto error_close_mmu; } - pm_qos_add_request(&device->pm_qos_req_dma, PM_QOS_CPU_DMA_LATENCY, + pm_qos_add_request(&device->pwrctrl.pm_qos_req_dma, + PM_QOS_CPU_DMA_LATENCY, PM_QOS_DEFAULT_VALUE); /* Initalize the snapshot engine */ @@ -3823,17 +4104,16 @@ EXPORT_SYMBOL(kgsl_device_platform_probe); int kgsl_postmortem_dump(struct kgsl_device *device, int manual) { - bool saved_nap; struct kgsl_pwrctrl *pwr = &device->pwrctrl; BUG_ON(device == NULL); - kgsl_cffdump_hang(device->id); + kgsl_cffdump_hang(device); /* For a manual dump, make sure that the system is idle */ if (manual) { - kgsl_active_count_wait(device); + kgsl_active_count_wait(device, 0); if (device->state == KGSL_STATE_ACTIVE) kgsl_idle(device); @@ -3843,22 +4123,21 @@ int kgsl_postmortem_dump(struct kgsl_device *device, int manual) if (device->pm_dump_enable) { KGSL_LOG_DUMP(device, - "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X", - pwr->power_flags, pwr->active_pwrlevel); + "POWER: START_STOP_SLEEP_WAKE = %d\n", + pwr->strtstp_sleepwake); + + KGSL_LOG_DUMP(device, + "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X", + pwr->power_flags, pwr->active_pwrlevel); KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ", - pwr->interval_timeout); + pwr->interval_timeout); } /* Disable the idle timer so we don't get interrupted */ del_timer_sync(&device->idle_timer); - /* Turn off napping to make sure we have the clocks full - attention through the following process */ - saved_nap = device->pwrctrl.nap_allowed; - device->pwrctrl.nap_allowed = false; - /* Force on the clocks */ kgsl_pwrctrl_wake(device); @@ -3868,9 +4147,6 @@ int kgsl_postmortem_dump(struct kgsl_device *device, int manual) /*Call the device specific postmortem dump function*/ device->ftbl->postmortem_dump(device, manual); - /* Restore nap mode */ - device->pwrctrl.nap_allowed = saved_nap; - /* On a manual trigger, turn on the interrupts and put the clocks to sleep. They will recover themselves on the next event. For a hang, leave things as they @@ -3894,7 +4170,7 @@ void kgsl_device_platform_remove(struct kgsl_device *device) kgsl_pwrctrl_uninit_sysfs(device); - pm_qos_remove_request(&device->pm_qos_req_dma); + pm_qos_remove_request(&device->pwrctrl.pm_qos_req_dma); idr_destroy(&device->context_idr); diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h index 458400d412f..32f105c7c11 100644 --- a/drivers/gpu/msm/kgsl.h +++ b/drivers/gpu/msm/kgsl.h @@ -46,7 +46,11 @@ #define KGSL_PAGETABLE_ENTRY_SIZE 4 /* Pagetable Virtual Address base */ +#ifndef CONFIG_MSM_KGSL_CFF_DUMP #define KGSL_PAGETABLE_BASE 0x10000000 +#else +#define KGSL_PAGETABLE_BASE SZ_4M +#endif /* Extra accounting entries needed in the pagetable */ #define KGSL_PT_EXTRA_ENTRIES 16 @@ -74,6 +78,8 @@ #define KGSL_MEMFREE_HIST_SIZE ((int)(PAGE_SIZE * 2)) +#define KGSL_MAX_NUMIBS 100000 + struct kgsl_memfree_hist_elem { unsigned int pid; unsigned int gpuaddr; @@ -144,7 +150,8 @@ struct kgsl_memdesc_ops { int (*vmfault)(struct kgsl_memdesc *, struct vm_area_struct *, struct vm_fault *); void (*free)(struct kgsl_memdesc *memdesc); - int (*map_kernel_mem)(struct kgsl_memdesc *); + int (*map_kernel)(struct kgsl_memdesc *); + void (*unmap_kernel)(struct kgsl_memdesc *); }; /* Internal definitions for memdesc->priv */ @@ -153,14 +160,17 @@ struct kgsl_memdesc_ops { #define KGSL_MEMDESC_GLOBAL BIT(1) /* The memdesc is frozen during a snapshot */ #define KGSL_MEMDESC_FROZEN BIT(2) +/* The memdesc is mapped into a pagetable */ +#define KGSL_MEMDESC_MAPPED BIT(3) /* shared memory allocation */ struct kgsl_memdesc { struct kgsl_pagetable *pagetable; void *hostptr; /* kernel virtual address */ + unsigned int hostptr_count; /* number of threads using hostptr */ unsigned long useraddr; /* userspace address */ unsigned int gpuaddr; - unsigned int physaddr; + phys_addr_t physaddr; unsigned int size; unsigned int priv; /* Internal flags and settings */ struct scatterlist *sg; @@ -190,6 +200,8 @@ struct kgsl_mem_entry { /* back pointer to private structure under whose context this * allocation is made */ struct kgsl_process_private *priv; + /* Initialized to 0, set to 1 when entry is marked for freeing */ + int pending_free; }; #ifdef CONFIG_MSM_KGSL_MMU_PAGE_FAULT @@ -202,7 +214,7 @@ void kgsl_mem_entry_destroy(struct kref *kref); int kgsl_postmortem_dump(struct kgsl_device *device, int manual); struct kgsl_mem_entry *kgsl_get_mem_entry(struct kgsl_device *device, - unsigned int ptbase, unsigned int gpuaddr, unsigned int size); + phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size); struct kgsl_mem_entry *kgsl_sharedmem_find_region( struct kgsl_process_private *private, unsigned int gpuaddr, @@ -222,11 +234,8 @@ void kgsl_cancel_events(struct kgsl_device *device, extern const struct dev_pm_ops kgsl_pm_ops; -struct early_suspend; int kgsl_suspend_driver(struct platform_device *pdev, pm_message_t state); int kgsl_resume_driver(struct platform_device *pdev); -void kgsl_early_suspend_driver(struct early_suspend *h); -void kgsl_late_resume_driver(struct early_suspend *h); void kgsl_trace_regwrite(struct kgsl_device *device, unsigned int offset, unsigned int value); @@ -236,6 +245,10 @@ void kgsl_trace_issueibcmds(struct kgsl_device *device, int id, unsigned int timestamp, unsigned int flags, int result, unsigned int type); +int kgsl_open_device(struct kgsl_device *device); + +int kgsl_close_device(struct kgsl_device *device); + #ifdef CONFIG_MSM_KGSL_DRM extern int kgsl_drm_init(struct platform_device *dev); extern void kgsl_drm_exit(void); @@ -270,13 +283,18 @@ static inline int kgsl_gpuaddr_in_memdesc(const struct kgsl_memdesc *memdesc, static inline void *kgsl_memdesc_map(struct kgsl_memdesc *memdesc) { - if (memdesc->hostptr == NULL && memdesc->ops && - memdesc->ops->map_kernel_mem) - memdesc->ops->map_kernel_mem(memdesc); + if (memdesc->ops && memdesc->ops->map_kernel) + memdesc->ops->map_kernel(memdesc); return memdesc->hostptr; } +static inline void kgsl_memdesc_unmap(struct kgsl_memdesc *memdesc) +{ + if (memdesc->ops && memdesc->ops->unmap_kernel) + memdesc->ops->unmap_kernel(memdesc); +} + static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc, unsigned int gpuaddr) { @@ -309,10 +327,10 @@ static inline int timestamp_cmp(unsigned int a, unsigned int b) return ((a > b) && (a - b <= KGSL_TIMESTAMP_WINDOW)) ? 1 : -1; } -static inline void +static inline int kgsl_mem_entry_get(struct kgsl_mem_entry *entry) { - kref_get(&entry->refcount); + return kref_get_unless_zero(&entry->refcount); } static inline void @@ -321,4 +339,22 @@ kgsl_mem_entry_put(struct kgsl_mem_entry *entry) kref_put(&entry->refcount, kgsl_mem_entry_destroy); } +/* + * kgsl_addr_range_overlap() - Checks if 2 ranges overlap + * @gpuaddr1: Start of first address range + * @size1: Size of first address range + * @gpuaddr2: Start of second address range + * @size2: Size of second address range + * + * Function returns true if the 2 given address ranges overlap + * else false + */ +static inline bool kgsl_addr_range_overlap(unsigned int gpuaddr1, + unsigned int size1, + unsigned int gpuaddr2, unsigned int size2) +{ + return !(((gpuaddr1 + size1) < gpuaddr2) || + (gpuaddr1 > (gpuaddr2 + size2))); +} + #endif /* __KGSL_H */ diff --git a/drivers/gpu/msm/kgsl_cffdump.c b/drivers/gpu/msm/kgsl_cffdump.c index 44f6e52fa23..ca2d1ee1e6d 100644 --- a/drivers/gpu/msm/kgsl_cffdump.c +++ b/drivers/gpu/msm/kgsl_cffdump.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2012,2013, 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 @@ -335,8 +335,6 @@ void kgsl_cffdump_init() return; } - kgsl_cff_dump_enable = 0; - spin_lock_init(&cffdump_lock); dir = debugfs_create_dir("cff", debugfs_dir); @@ -360,51 +358,54 @@ void kgsl_cffdump_destroy() void kgsl_cffdump_open(struct kgsl_device *device) { struct adreno_device *adreno_dev = ADRENO_DEVICE(device); - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) { - kgsl_cffdump_memory_base(device->id, - kgsl_mmu_get_base_addr(&device->mmu), - kgsl_mmu_get_ptsize(&device->mmu) + - KGSL_IOMMU_GLOBAL_MEM_SIZE, adreno_dev->gmem_size); + kgsl_cffdump_memory_base(device, + KGSL_PAGETABLE_BASE, + KGSL_IOMMU_GLOBAL_MEM_BASE + + KGSL_IOMMU_GLOBAL_MEM_SIZE - + KGSL_PAGETABLE_BASE, + adreno_dev->gmem_size); } else { - kgsl_cffdump_memory_base(device->id, + kgsl_cffdump_memory_base(device, kgsl_mmu_get_base_addr(&device->mmu), kgsl_mmu_get_ptsize(&device->mmu), adreno_dev->gmem_size); } } -void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base, +void kgsl_cffdump_memory_base(struct kgsl_device *device, unsigned int base, unsigned int range, unsigned gmemsize) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_MEMORY_BASE, base, + cffdump_printline(device->id, CFF_OP_MEMORY_BASE, base, range, gmemsize, 0, 0); } -void kgsl_cffdump_hang(enum kgsl_deviceid device_id) +void kgsl_cffdump_hang(struct kgsl_device *device) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_HANG, 0, 0, 0, 0, 0); + cffdump_printline(device->id, CFF_OP_HANG, 0, 0, 0, 0, 0); } -void kgsl_cffdump_close(enum kgsl_deviceid device_id) +void kgsl_cffdump_close(struct kgsl_device *device) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_EOF, 0, 0, 0, 0, 0); + cffdump_printline(device->id, CFF_OP_EOF, 0, 0, 0, 0, 0); } -void kgsl_cffdump_user_event(unsigned int cff_opcode, unsigned int op1, +void kgsl_cffdump_user_event(struct kgsl_device *device, + unsigned int cff_opcode, unsigned int op1, unsigned int op2, unsigned int op3, unsigned int op4, unsigned int op5) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; cffdump_printline(-1, cff_opcode, op1, op2, op3, op4, op5); } @@ -415,7 +416,7 @@ void kgsl_cffdump_syncmem(struct kgsl_device *device, { const void *src; - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; BUG_ON(memdesc == NULL); @@ -424,9 +425,9 @@ void kgsl_cffdump_syncmem(struct kgsl_device *device, src = (uint *)kgsl_gpuaddr_to_vaddr(memdesc, gpuaddr); if (memdesc->hostptr == NULL) { - KGSL_CORE_ERR("no kernel mapping for " - "gpuaddr: 0x%08x, m->host: 0x%p, phys: 0x%08x\n", - gpuaddr, memdesc->hostptr, memdesc->physaddr); + KGSL_CORE_ERR( + "no kernel map for gpuaddr: 0x%08x, m->host: 0x%p, phys: %pa\n", + gpuaddr, memdesc->hostptr, &memdesc->physaddr); return; } @@ -450,11 +451,14 @@ void kgsl_cffdump_syncmem(struct kgsl_device *device, if (sizebytes > 0) cffdump_printline(-1, CFF_OP_WRITE_MEM, gpuaddr, *(uint *)src, 0, 0, 0); + /* Unmap memory since kgsl_gpuaddr_to_vaddr was called */ + kgsl_memdesc_unmap(memdesc); } -void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes) +void kgsl_cffdump_setmem(struct kgsl_device *device, + uint addr, uint value, uint sizebytes) { - if (!kgsl_cff_dump_enable) + if (!device || !device->cff_dump_enable) return; while (sizebytes > 3) { @@ -470,37 +474,37 @@ void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes) 0, 0, 0); } -void kgsl_cffdump_regwrite(enum kgsl_deviceid device_id, uint addr, +void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr, uint value) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_WRITE_REG, addr, value, + cffdump_printline(device->id, CFF_OP_WRITE_REG, addr, value, 0, 0, 0); } -void kgsl_cffdump_regpoll(enum kgsl_deviceid device_id, uint addr, +void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr, uint value, uint mask) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; - cffdump_printline(device_id, CFF_OP_POLL_REG, addr, value, + cffdump_printline(device->id, CFF_OP_POLL_REG, addr, value, mask, 0, 0); } -void kgsl_cffdump_slavewrite(uint addr, uint value) +void kgsl_cffdump_slavewrite(struct kgsl_device *device, uint addr, uint value) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return; cffdump_printline(-1, CFF_OP_WRITE_REG, addr, value, 0, 0, 0); } -int kgsl_cffdump_waitirq(void) +int kgsl_cffdump_waitirq(struct kgsl_device *device) { - if (!kgsl_cff_dump_enable) + if (!device->cff_dump_enable) return 0; cffdump_printline(-1, CFF_OP_WAIT_IRQ, 0, 0, 0, 0, 0); @@ -601,3 +605,45 @@ static void destroy_channel(void) } } +int kgsl_cff_dump_enable_set(void *data, u64 val) +{ + int ret = 0; + struct kgsl_device *device = (struct kgsl_device *)data; + int i; + + mutex_lock(&kgsl_driver.devlock); + if (val) { + /* Check if CFF is on for some other device already */ + for (i = 0; i < KGSL_DEVICE_MAX; i++) { + if (kgsl_driver.devp[i]) { + struct kgsl_device *device_temp = + kgsl_driver.devp[i]; + if (device_temp->cff_dump_enable && + device != device_temp) { + KGSL_CORE_ERR( + "CFF is on for another device %d\n", + device_temp->id); + ret = -EINVAL; + goto done; + } + } + } + if (!device->cff_dump_enable) { + device->cff_dump_enable = 1; + } + } else if (device->cff_dump_enable && !val) { + device->cff_dump_enable = 0; + } +done: + mutex_unlock(&kgsl_driver.devlock); + return ret; +} +EXPORT_SYMBOL(kgsl_cff_dump_enable_set); + +int kgsl_cff_dump_enable_get(void *data, u64 *val) +{ + struct kgsl_device *device = (struct kgsl_device *)data; + *val = device->cff_dump_enable; + return 0; +} +EXPORT_SYMBOL(kgsl_cff_dump_enable_get); diff --git a/drivers/gpu/msm/kgsl_cffdump.h b/drivers/gpu/msm/kgsl_cffdump.h index 83695f81c66..2852e0f6114 100644 --- a/drivers/gpu/msm/kgsl_cffdump.h +++ b/drivers/gpu/msm/kgsl_cffdump.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2011, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2011,2013, 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 @@ -14,11 +14,15 @@ #ifndef __KGSL_CFFDUMP_H #define __KGSL_CFFDUMP_H -#ifdef CONFIG_MSM_KGSL_CFF_DUMP - #include -#include "kgsl_device.h" +extern unsigned int kgsl_cff_dump_enable; + +static inline bool kgsl_cffdump_flags_no_memzero(void) { return true; } + +struct kgsl_device_private; + +#ifdef CONFIG_MSM_KGSL_CFF_DUMP void kgsl_cffdump_init(void); void kgsl_cffdump_destroy(void); @@ -27,42 +31,108 @@ void kgsl_cffdump_close(struct kgsl_device *device); void kgsl_cffdump_syncmem(struct kgsl_device *, struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes, bool clean_cache); -void kgsl_cffdump_setmem(uint addr, uint value, uint sizebytes); -void kgsl_cffdump_regwrite(enum kgsl_deviceid device_id, uint addr, +void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr, + uint value, uint sizebytes); +void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr, uint value); -void kgsl_cffdump_regpoll(enum kgsl_deviceid device_id, uint addr, +void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr, uint value, uint mask); bool kgsl_cffdump_parse_ibs(struct kgsl_device_private *dev_priv, const struct kgsl_memdesc *memdesc, uint gpuaddr, int sizedwords, bool check_only); -void kgsl_cffdump_user_event(unsigned int cff_opcode, unsigned int op1, +void kgsl_cffdump_user_event(struct kgsl_device *device, + unsigned int cff_opcode, unsigned int op1, unsigned int op2, unsigned int op3, unsigned int op4, unsigned int op5); -static inline bool kgsl_cffdump_flags_no_memzero(void) { return true; } -void kgsl_cffdump_memory_base(enum kgsl_deviceid device_id, unsigned int base, +void kgsl_cffdump_memory_base(struct kgsl_device *device, unsigned int base, unsigned int range, unsigned int gmemsize); -void kgsl_cffdump_hang(enum kgsl_deviceid device_id); +void kgsl_cffdump_hang(struct kgsl_device *device); +int kgsl_cff_dump_enable_set(void *data, u64 val); +int kgsl_cff_dump_enable_get(void *data, u64 *val); #else -#define kgsl_cffdump_init() (void)0 -#define kgsl_cffdump_destroy() (void)0 -#define kgsl_cffdump_open(device) (void)0 -#define kgsl_cffdump_close(device_id) (void)0 -#define kgsl_cffdump_syncmem(dev_priv, memdesc, addr, sizebytes, clean_cache) \ - (void) 0 -#define kgsl_cffdump_setmem(addr, value, sizebytes) (void)0 -#define kgsl_cffdump_regwrite(device_id, addr, value) (void)0 -#define kgsl_cffdump_regpoll(device_id, addr, value, mask) (void)0 -#define kgsl_cffdump_parse_ibs(dev_priv, memdesc, gpuaddr, \ - sizedwords, check_only) true -#define kgsl_cffdump_flags_no_memzero() true -#define kgsl_cffdump_memory_base(base, range, gmemsize) (void)0 -#define kgsl_cffdump_hang(device_id) (void)0 -#define kgsl_cffdump_user_event(cff_opcode, op1, op2, op3, op4, op5) \ - (void)param +static inline void kgsl_cffdump_init(void) +{ + return; +} + +static inline void kgsl_cffdump_destroy(void) +{ + return; +} + +static inline void kgsl_cffdump_open(struct kgsl_device *device) +{ + return; +} + +static inline void kgsl_cffdump_close(struct kgsl_device *device) +{ + return; +} + +static inline void kgsl_cffdump_syncmem(struct kgsl_device *device, + struct kgsl_memdesc *memdesc, uint physaddr, uint sizebytes, + bool clean_cache) +{ + return; +} + +static inline void kgsl_cffdump_setmem(struct kgsl_device *device, uint addr, + uint value, uint sizebytes) +{ + return; +} + +static inline void kgsl_cffdump_regwrite(struct kgsl_device *device, uint addr, + uint value) +{ + return; +} + +static inline void kgsl_cffdump_regpoll(struct kgsl_device *device, uint addr, + uint value, uint mask) +{ + return; +} + +static inline bool kgsl_cffdump_parse_ibs(struct kgsl_device_private *dev_priv, + const struct kgsl_memdesc *memdesc, uint gpuaddr, int sizedwords, + bool check_only) +{ + return false; +} + +static inline void kgsl_cffdump_memory_base(struct kgsl_device *device, + unsigned int base, unsigned int range, unsigned int gmemsize) +{ + return; +} + +static inline void kgsl_cffdump_hang(struct kgsl_device *device) +{ + return; +} + +static inline void kgsl_cffdump_user_event(struct kgsl_device *device, + unsigned int cff_opcode, unsigned int op1, + unsigned int op2, unsigned int op3, + unsigned int op4, unsigned int op5) +{ + return; +} +static inline int kgsl_cff_dump_enable_set(void *data, u64 val) +{ + return -EINVAL; +} + +static inline int kgsl_cff_dump_enable_get(void *data, u64 *val) +{ + return -EINVAL; +} #endif /* CONFIG_MSM_KGSL_CFF_DUMP */ diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c index 09c9dfe6256..d62a222d9f4 100644 --- a/drivers/gpu/msm/kgsl_debugfs.c +++ b/drivers/gpu/msm/kgsl_debugfs.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2008-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2008-2013, 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 @@ -19,7 +19,6 @@ #include "kgsl_sharedmem.h" /*default log levels is error for everything*/ -#define KGSL_LOG_LEVEL_DEFAULT 3 #define KGSL_LOG_LEVEL_MAX 7 struct dentry *kgsl_debugfs_dir; @@ -179,12 +178,6 @@ void kgsl_device_debugfs_init(struct kgsl_device *device) if (!device->d_debugfs || IS_ERR(device->d_debugfs)) return; - device->cmd_log = KGSL_LOG_LEVEL_DEFAULT; - device->ctxt_log = KGSL_LOG_LEVEL_DEFAULT; - device->drv_log = KGSL_LOG_LEVEL_DEFAULT; - device->mem_log = KGSL_LOG_LEVEL_DEFAULT; - device->pwr_log = KGSL_LOG_LEVEL_DEFAULT; - debugfs_create_file("log_level_cmd", 0644, device->d_debugfs, device, &cmd_log_fops); debugfs_create_file("log_level_ctxt", 0644, device->d_debugfs, device, @@ -211,7 +204,6 @@ void kgsl_device_debugfs_init(struct kgsl_device *device) &pm_regs_enabled_fops); debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device, &pm_ib_enabled_fops); - device->pm_dump_enable = 0; debugfs_create_file("enable", 0644, pm_d_debugfs, device, &pm_enabled_fops); @@ -268,8 +260,8 @@ static void print_mem_entry(struct seq_file *s, struct kgsl_mem_entry *entry) kgsl_get_memory_usage(usage, sizeof(usage), m->flags); - seq_printf(s, "%08x %8d %5d %5s %10s %16s %5d\n", - m->gpuaddr, m->size, entry->id, flags, + seq_printf(s, "%08x %08lx %8d %5d %5s %10s %16s %5d\n", + m->gpuaddr, m->useraddr, m->size, entry->id, flags, memtype_str(entry->memtype), usage, m->sglen); } @@ -280,8 +272,9 @@ static int process_mem_print(struct seq_file *s, void *unused) struct kgsl_process_private *private = s->private; int next = 0; - seq_printf(s, "%8s %8s %5s %5s %10s %16s %5s\n", - "gpuaddr", "size", "id", "flags", "type", "usage", "sglen"); + seq_printf(s, "%8s %8s %8s %5s %5s %10s %16s %5s\n", + "gpuaddr", "useraddr", "size", "id", "flags", "type", + "usage", "sglen"); /* print all entries with a GPU address */ spin_lock(&private->mem_lock); @@ -291,20 +284,17 @@ static int process_mem_print(struct seq_file *s, void *unused) print_mem_entry(s, entry); } - spin_unlock(&private->mem_lock); /* now print all the unbound entries */ while (1) { - rcu_read_lock(); entry = idr_get_next(&private->mem_idr, &next); - rcu_read_unlock(); - if (entry == NULL) break; if (entry->memdesc.gpuaddr == 0) print_mem_entry(s, entry); next++; } + spin_unlock(&private->mem_lock); return 0; } @@ -321,16 +311,59 @@ static const struct file_operations process_mem_fops = { .release = single_release, }; -void + +/** + * kgsl_process_init_debugfs() - Initialize debugfs for a process + * @private: Pointer to process private structure created for the process + * + * @returns: 0 on success, error code otherwise + * + * kgsl_process_init_debugfs() is called at the time of creating the + * process struct when a process opens kgsl device for the first time. + * The function creates the debugfs files for the process. If debugfs is + * disabled in the kernel, we ignore that error and return as successful. + */ +int kgsl_process_init_debugfs(struct kgsl_process_private *private) { unsigned char name[16]; + int ret = 0; + struct dentry *dentry; snprintf(name, sizeof(name), "%d", private->pid); private->debug_root = debugfs_create_dir(name, proc_d_debugfs); - debugfs_create_file("mem", 0400, private->debug_root, private, + + if (!private->debug_root) + return -EINVAL; + + private->debug_root->d_inode->i_uid = proc_d_debugfs->d_inode->i_uid; + private->debug_root->d_inode->i_gid = proc_d_debugfs->d_inode->i_gid; + + /* + * debugfs_create_dir() and debugfs_create_file() both + * return -ENODEV if debugfs is disabled in the kernel. + * We make a distinction between these two functions + * failing and debugfs being disabled in the kernel. + * In the first case, we abort process private struct + * creation, in the second we continue without any changes. + * So if debugfs is disabled in kernel, return as + * success. + */ + dentry = debugfs_create_file("mem", 0400, private->debug_root, private, &process_mem_fops); + + if (IS_ERR(dentry)) { + ret = PTR_ERR(dentry); + + if (ret == -ENODEV) + ret = 0; + } else if (dentry) { + dentry->d_inode->i_uid = proc_d_debugfs->d_inode->i_uid; + dentry->d_inode->i_gid = proc_d_debugfs->d_inode->i_gid; + } + + return ret; } void kgsl_core_debugfs_init(void) diff --git a/drivers/gpu/msm/kgsl_debugfs.h b/drivers/gpu/msm/kgsl_debugfs.h index ae5601fb40a..b2f137cd4b0 100644 --- a/drivers/gpu/msm/kgsl_debugfs.h +++ b/drivers/gpu/msm/kgsl_debugfs.h @@ -21,7 +21,7 @@ struct kgsl_process_private; void kgsl_core_debugfs_init(void); void kgsl_core_debugfs_close(void); -void kgsl_device_debugfs_init(struct kgsl_device *device); +int kgsl_device_debugfs_init(struct kgsl_device *device); extern struct dentry *kgsl_debugfs_dir; static inline struct dentry *kgsl_get_debugfs_dir(void) diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index fb3fade51e4..44324c67604 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -16,7 +16,6 @@ #include #include #include -#include #include #include "kgsl.h" @@ -49,7 +48,6 @@ #define KGSL_STATE_SLEEP 0x00000008 #define KGSL_STATE_SUSPEND 0x00000010 #define KGSL_STATE_HUNG 0x00000020 -#define KGSL_STATE_DUMP_AND_FT 0x00000040 #define KGSL_STATE_SLUMBER 0x00000080 #define KGSL_GRAPHICS_MEMORY_LOW_WATERMARK 0x1000000 @@ -133,10 +131,9 @@ struct kgsl_functable { enum kgsl_property_type type, void *value, unsigned int sizebytes); int (*postmortem_dump) (struct kgsl_device *device, int manual); - int (*next_event)(struct kgsl_device *device, - struct kgsl_event *event); void (*drawctxt_sched)(struct kgsl_device *device, struct kgsl_context *context); + void (*resume)(struct kgsl_device *device); }; /* MH register values */ @@ -169,6 +166,7 @@ struct kgsl_event { * @priv: Internal flags * @fault_policy: Internal policy describing how to handle this command in case * of a fault + * @fault_recovery: recovery actions actually tried for this batch * @ibcount: Number of IBs in the command list * @ibdesc: Pointer to the list of IBs * @expires: Point in time when the cmdbatch is considered to be hung @@ -176,6 +174,7 @@ struct kgsl_event { * context should be invalidated * @refcount: kref structure to maintain the reference count * @synclist: List of context/timestamp tuples to wait for before issuing + * @priority: Priority of the cmdbatch (inherited from the context) * * This struture defines an atomic batch of command buffers issued from * userspace. @@ -186,20 +185,30 @@ struct kgsl_cmdbatch { spinlock_t lock; uint32_t timestamp; uint32_t flags; - uint32_t priv; - uint32_t fault_policy; + unsigned long priv; + unsigned long fault_policy; + unsigned long fault_recovery; uint32_t ibcount; struct kgsl_ibdesc *ibdesc; unsigned long expires; int invalid; struct kref refcount; struct list_head synclist; + int priority; }; -/* Internal cmdbatch flags */ +/** + * enum kgsl_cmdbatch_priv - Internal cmdbatch flags + * @CMDBATCH_FLAG_SKIP - skip the entire command batch + * @CMDBATCH_FLAG_FORCE_PREAMBLE - Force the preamble on for the cmdbatch + * @CMDBATCH_FLAG_WFI - Force wait-for-idle for the submission + */ -#define CMDBATCH_FLAG_SKIP BIT(0) -#define CMDBATCH_FLAG_FORCE_PREAMBLE BIT(1) +enum kgsl_cmdbatch_priv { + CMDBATCH_FLAG_SKIP = 0, + CMDBATCH_FLAG_FORCE_PREAMBLE, + CMDBATCH_FLAG_WFI, +}; struct kgsl_device { struct device *dev; @@ -208,15 +217,32 @@ struct kgsl_device { unsigned int ver_minor; uint32_t flags; enum kgsl_deviceid id; + + /* Starting physical address for GPU registers */ unsigned long reg_phys; + + /* Starting Kernel virtual address for GPU registers */ void *reg_virt; + + /* Total memory size for all GPU registers */ unsigned int reg_len; + + /* Kernel virtual address for GPU shader memory */ + void *shader_mem_virt; + + /* Starting physical address for GPU shader memory */ + unsigned long shader_mem_phys; + + /* GPU shader memory size */ + unsigned int shader_mem_len; struct kgsl_memdesc memstore; const char *iomemname; + const char *shadermemname; struct kgsl_mh mh; struct kgsl_mmu mmu; struct completion hwaccess_gate; + struct completion cmdbatch_gate; const struct kgsl_functable *ftbl; struct work_struct idle_check_ws; struct timer_list idle_timer; @@ -228,20 +254,20 @@ struct kgsl_device { uint32_t requested_state; atomic_t active_cnt; - struct completion suspend_gate; wait_queue_head_t wait_queue; + wait_queue_head_t active_cnt_wq; struct workqueue_struct *work_queue; struct device *parentdev; struct dentry *d_debugfs; struct idr context_idr; - struct early_suspend display_off; rwlock_t context_lock; void *snapshot; /* Pointer to the snapshot memory region */ int snapshot_maxsize; /* Max size of the snapshot region */ int snapshot_size; /* Current size of the snapshot region */ u32 snapshot_timestamp; /* Timestamp of the last valid snapshot */ + u32 snapshot_faultcount; /* Total number of faults since boot */ int snapshot_frozen; /* 1 if the snapshot output is frozen until it gets read by the user. This avoids losing the output on multiple hangs */ @@ -252,6 +278,14 @@ struct kgsl_device { * dumped */ struct list_head snapshot_obj_list; + /* List of IB's to be dumped */ + struct list_head snapshot_cp_list; + /* Work item that saves snapshot's frozen object data */ + struct work_struct snapshot_obj_ws; + /* snapshot memory holding the hanging IB's objects in snapshot */ + void *snapshot_cur_ib_objs; + /* Size of snapshot_cur_ib_objs */ + int snapshot_cur_ib_objs_size; /* Logging levels */ int cmd_log; @@ -262,7 +296,6 @@ struct kgsl_device { int pm_dump_enable; struct kgsl_pwrscale pwrscale; struct kobject pwrscale_kobj; - struct pm_qos_request pm_qos_req_dma; struct work_struct ts_expired_ws; struct list_head events; struct list_head events_pending_list; @@ -274,6 +307,7 @@ struct kgsl_device { int pm_ib_enabled; int reset_counter; /* Track how many GPU core resets have occured */ + int cff_dump_enable; }; void kgsl_process_events(struct work_struct *work); @@ -281,15 +315,19 @@ void kgsl_check_fences(struct work_struct *work); #define KGSL_DEVICE_COMMON_INIT(_dev) \ .hwaccess_gate = COMPLETION_INITIALIZER((_dev).hwaccess_gate),\ - .suspend_gate = COMPLETION_INITIALIZER((_dev).suspend_gate),\ + .cmdbatch_gate = COMPLETION_INITIALIZER((_dev).cmdbatch_gate),\ .idle_check_ws = __WORK_INITIALIZER((_dev).idle_check_ws,\ kgsl_idle_check),\ .ts_expired_ws = __WORK_INITIALIZER((_dev).ts_expired_ws,\ kgsl_process_events),\ + .snapshot_obj_ws = \ + __WORK_INITIALIZER((_dev).snapshot_obj_ws,\ + kgsl_snapshot_save_frozen_objs),\ .context_idr = IDR_INIT((_dev).context_idr),\ .events = LIST_HEAD_INIT((_dev).events),\ .events_pending_list = LIST_HEAD_INIT((_dev).events_pending_list), \ .wait_queue = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).wait_queue),\ + .active_cnt_wq = __WAIT_QUEUE_HEAD_INITIALIZER((_dev).active_cnt_wq),\ .mutex = __MUTEX_INITIALIZER((_dev).mutex),\ .state = KGSL_STATE_INIT,\ .ver_major = DRIVER_VERSION_MAJOR,\ @@ -302,6 +340,7 @@ void kgsl_check_fences(struct work_struct *work); /* the context has caused a pagefault */ #define KGSL_CONTEXT_PAGEFAULT 1 +struct kgsl_process_private; /** * struct kgsl_context - Master structure for a KGSL context object * @refcount: kref object for reference counting the context @@ -325,9 +364,10 @@ struct kgsl_context { struct kref refcount; uint32_t id; pid_t pid; + struct kgsl_device_private *dev_priv; + struct kgsl_process_private *proc_priv; unsigned long priv; struct kgsl_device *device; - struct kgsl_pagetable *pagetable; unsigned int reset_status; bool wait_on_invalid_ts; struct sync_timeline *timeline; @@ -476,6 +516,7 @@ const char *kgsl_pwrstate_to_str(unsigned int state); int kgsl_device_snapshot_init(struct kgsl_device *device); int kgsl_device_snapshot(struct kgsl_device *device, int hang); void kgsl_device_snapshot_close(struct kgsl_device *device); +void kgsl_snapshot_save_frozen_objs(struct work_struct *work); static inline struct kgsl_device_platform_data * kgsl_device_get_drvdata(struct kgsl_device *dev) @@ -490,6 +531,7 @@ void kgsl_context_destroy(struct kref *kref); int kgsl_context_init(struct kgsl_device_private *, struct kgsl_context *context); +int kgsl_context_detach(struct kgsl_context *context); /** * kgsl_context_put() - Release context reference count @@ -511,7 +553,7 @@ kgsl_context_put(struct kgsl_context *context) * * Check if a context has been destroyed by userspace and is only waiting * for reference counts to go away. This check is used to weed out - * contexts that shouldn't use the gpu, so NULL is considered detached. + * contexts that shouldn't use the gpu so NULL is considered detached. */ static inline bool kgsl_context_detached(struct kgsl_context *context) { @@ -534,6 +576,7 @@ static inline bool kgsl_context_detached(struct kgsl_context *context) static inline struct kgsl_context *kgsl_context_get(struct kgsl_device *device, uint32_t id) { + int result = 0; struct kgsl_context *context = NULL; read_lock(&device->context_lock); @@ -544,10 +587,12 @@ static inline struct kgsl_context *kgsl_context_get(struct kgsl_device *device, if (kgsl_context_detached(context)) context = NULL; else - kref_get(&context->refcount); + result = kref_get_unless_zero(&context->refcount); read_unlock(&device->context_lock); + if (!result) + return NULL; return context; } @@ -559,10 +604,22 @@ static inline struct kgsl_context *kgsl_context_get(struct kgsl_device *device, * lightweight way to just increase the refcount on a known context rather than * walking through kgsl_context_get and searching the iterator */ -static inline void _kgsl_context_get(struct kgsl_context *context) +static inline int _kgsl_context_get(struct kgsl_context *context) { - if (context) - kref_get(&context->refcount); + int ret = 0; + + if (context) { + ret = kref_get_unless_zero(&context->refcount); + /* + * We shouldn't realistically fail kref_get_unless_zero unless + * we did something really dumb so make the failure both public + * and painful + */ + + WARN_ON(!ret); + } + + return ret; } /** @@ -630,7 +687,8 @@ void kgsl_cmdbatch_destroy_object(struct kref *kref); */ static inline void kgsl_cmdbatch_put(struct kgsl_cmdbatch *cmdbatch) { - kref_put(&cmdbatch->refcount, kgsl_cmdbatch_destroy_object); + if (cmdbatch) + kref_put(&cmdbatch->refcount, kgsl_cmdbatch_destroy_object); } /** @@ -645,4 +703,34 @@ static inline int kgsl_cmdbatch_sync_pending(struct kgsl_cmdbatch *cmdbatch) return list_empty(&cmdbatch->synclist) ? 0 : 1; } +#if defined(CONFIG_GPU_TRACEPOINTS) + +#include + +static inline void kgsl_trace_gpu_job_enqueue(unsigned int ctxt_id, + unsigned int timestamp, const char *type) +{ + trace_gpu_job_enqueue(ctxt_id, timestamp, type); +} + +static inline void kgsl_trace_gpu_sched_switch(const char *name, + u64 time, u32 ctxt_id, s32 prio, u32 timestamp) +{ + trace_gpu_sched_switch(name, time, ctxt_id, prio, timestamp); +} + +#else + +static inline void kgsl_trace_gpu_job_enqueue(unsigned int ctxt_id, + unsigned int timestamp, const char *type) +{ +} + +static inline void kgsl_trace_gpu_sched_switch(const char *name, + u64 time, u32 ctxt_id, s32 prio, u32 timestamp) +{ +} + +#endif + #endif /* __KGSL_DEVICE_H */ diff --git a/drivers/gpu/msm/kgsl_drm.c b/drivers/gpu/msm/kgsl_drm.c index 2a5a5fac296..6402bf4cb31 100644 --- a/drivers/gpu/msm/kgsl_drm.c +++ b/drivers/gpu/msm/kgsl_drm.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2009-2013, 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 @@ -16,7 +16,9 @@ */ #include "drmP.h" #include "drm.h" -#include + +#include +#include #include "kgsl.h" #include "kgsl_device.h" @@ -27,7 +29,7 @@ #define DRIVER_AUTHOR "Qualcomm" #define DRIVER_NAME "kgsl" #define DRIVER_DESC "KGSL DRM" -#define DRIVER_DATE "20100127" +#define DRIVER_DATE "20121107" #define DRIVER_MAJOR 2 #define DRIVER_MINOR 1 @@ -106,6 +108,7 @@ struct drm_kgsl_gem_object { uint32_t type; struct kgsl_memdesc memdesc; struct kgsl_pagetable *pagetable; + struct ion_handle *ion_handle; uint64_t mmap_offset; int bufcount; int flags; @@ -117,6 +120,8 @@ struct drm_kgsl_gem_object { uint32_t gpuaddr; } bufs[DRM_KGSL_GEM_MAX_BUFFERS]; + struct genlock_handle *glock_handle[DRM_KGSL_GEM_MAX_BUFFERS]; + int bound; int lockpid; /* Put these here to avoid allocing all the time */ @@ -129,86 +134,18 @@ struct drm_kgsl_gem_object { struct list_head wait_list; }; +static struct ion_client *kgsl_drm_ion_client; + static int kgsl_drm_inited = DRM_KGSL_NOT_INITED; /* This is a global list of all the memory currently mapped in the MMU */ static struct list_head kgsl_mem_list; -static void kgsl_gem_mem_flush(struct kgsl_memdesc *memdesc, int type, int op) -{ - int cacheop = 0; - - switch (op) { - case DRM_KGSL_GEM_CACHE_OP_TO_DEV: - if (type & (DRM_KGSL_GEM_CACHE_WBACK | - DRM_KGSL_GEM_CACHE_WBACKWA)) - cacheop = KGSL_CACHE_OP_CLEAN; - - break; - - case DRM_KGSL_GEM_CACHE_OP_FROM_DEV: - if (type & (DRM_KGSL_GEM_CACHE_WBACK | - DRM_KGSL_GEM_CACHE_WBACKWA | - DRM_KGSL_GEM_CACHE_WTHROUGH)) - cacheop = KGSL_CACHE_OP_INV; - } - - kgsl_cache_range_op(memdesc, cacheop); -} - -/* TODO: - * Add vsync wait */ - -static int kgsl_drm_load(struct drm_device *dev, unsigned long flags) -{ - return 0; -} - -static int kgsl_drm_unload(struct drm_device *dev) -{ - return 0; -} - struct kgsl_drm_device_priv { struct kgsl_device *device[KGSL_DEVICE_MAX]; struct kgsl_device_private *devpriv[KGSL_DEVICE_MAX]; }; -void kgsl_drm_preclose(struct drm_device *dev, struct drm_file *file_priv) -{ -} - -static int kgsl_drm_suspend(struct drm_device *dev, pm_message_t state) -{ - return 0; -} - -static int kgsl_drm_resume(struct drm_device *dev) -{ - return 0; -} - -static void -kgsl_gem_free_mmap_offset(struct drm_gem_object *obj) -{ - struct drm_device *dev = obj->dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_kgsl_gem_object *priv = obj->driver_private; - struct drm_map_list *list; - - list = &obj->map_list; - drm_ht_remove_item(&mm->offset_hash, &list->hash); - if (list->file_offset_node) { - drm_mm_put_block(list->file_offset_node); - list->file_offset_node = NULL; - } - - kfree(list->map); - list->map = NULL; - - priv->mmap_offset = 0; -} - static int kgsl_gem_memory_allocated(struct drm_gem_object *obj) { @@ -220,6 +157,9 @@ static int kgsl_gem_alloc_memory(struct drm_gem_object *obj) { struct drm_kgsl_gem_object *priv = obj->driver_private; + struct kgsl_mmu *mmu; + struct sg_table *sg_table; + struct scatterlist *s; int index; int result = 0; @@ -229,7 +169,17 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj) return 0; if (priv->pagetable == NULL) { - priv->pagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); + /* Hard coded to use A2X device for MSM7X27 and MSM8625 + * Others to use A3X device + */ +#if defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM8625) + mmu = &kgsl_get_device(KGSL_DEVICE_2D0)->mmu; +#else + mmu = &kgsl_get_device(KGSL_DEVICE_3D0)->mmu; +#endif + + priv->pagetable = kgsl_mmu_getpagetable(mmu, + KGSL_MMU_GLOBAL_PT); if (priv->pagetable == NULL) { DRM_ERROR("Unable to get the GPU MMU pagetable\n"); @@ -237,21 +187,53 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj) } } - /* Set the flags for the memdesc (probably 0, unless it is cached) */ - priv->memdesc.priv = 0; - if (TYPE_IS_PMEM(priv->type)) { if (priv->type == DRM_KGSL_GEM_TYPE_EBI || priv->type & DRM_KGSL_GEM_PMEM_EBI) { - result = kgsl_sharedmem_ebimem_user( - &priv->memdesc, - priv->pagetable, - obj->size * priv->bufcount); - if (result) { - DRM_ERROR( - "Unable to allocate PMEM memory\n"); - return result; - } + priv->ion_handle = ion_alloc(kgsl_drm_ion_client, + obj->size * priv->bufcount, PAGE_SIZE, + ION_HEAP(ION_SF_HEAP_ID), 0); + if (IS_ERR_OR_NULL(priv->ion_handle)) { + DRM_ERROR( + "Unable to allocate ION Phys memory handle\n"); + return -ENOMEM; + } + + priv->memdesc.pagetable = priv->pagetable; + + result = ion_phys(kgsl_drm_ion_client, + priv->ion_handle, (ion_phys_addr_t *) + &priv->memdesc.physaddr, &priv->memdesc.size); + if (result) { + DRM_ERROR( + "Unable to get ION Physical memory address\n"); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + return result; + } + + result = memdesc_sg_phys(&priv->memdesc, + priv->memdesc.physaddr, priv->memdesc.size); + if (result) { + DRM_ERROR( + "Unable to get sg list\n"); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + return result; + } + + result = kgsl_mmu_map(priv->pagetable, &priv->memdesc, + GSL_PT_PAGE_RV | GSL_PT_PAGE_WV); + if (result) { + DRM_ERROR( + "kgsl_mmu_map failed. result = %d\n", result); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + return result; + } } else return -EINVAL; @@ -262,15 +244,43 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj) priv->type & DRM_KGSL_GEM_CACHE_MASK) list_add(&priv->list, &kgsl_mem_list); - result = kgsl_sharedmem_page_alloc_user(&priv->memdesc, - priv->pagetable, - obj->size * priv->bufcount); + priv->memdesc.pagetable = priv->pagetable; - if (result != 0) { - DRM_ERROR( - "Unable to allocate Vmalloc user memory\n"); - return result; + priv->ion_handle = ion_alloc(kgsl_drm_ion_client, + obj->size * priv->bufcount, PAGE_SIZE, + ION_HEAP(ION_IOMMU_HEAP_ID), 0); + if (IS_ERR_OR_NULL(priv->ion_handle)) { + DRM_ERROR( + "Unable to allocate ION IOMMU memory handle\n"); + return -ENOMEM; } + + sg_table = ion_sg_table(kgsl_drm_ion_client, + priv->ion_handle); + if (IS_ERR_OR_NULL(priv->ion_handle)) { + DRM_ERROR( + "Unable to get ION sg table\n"); + goto memerr; + } + + priv->memdesc.sg = sg_table->sgl; + + /* Calculate the size of the memdesc from the sglist */ + + priv->memdesc.sglen = 0; + + for (s = priv->memdesc.sg; s != NULL; s = sg_next(s)) { + priv->memdesc.size += s->length; + priv->memdesc.sglen++; + } + + result = kgsl_mmu_map(priv->pagetable, &priv->memdesc); + if (result) { + DRM_ERROR( + "kgsl_mmu_map failed. result = %d\n", result); + goto memerr; + } + } else return -EINVAL; @@ -282,21 +292,44 @@ kgsl_gem_alloc_memory(struct drm_gem_object *obj) } priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED; + return 0; + +memerr: + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + return -ENOMEM; + } static void kgsl_gem_free_memory(struct drm_gem_object *obj) { struct drm_kgsl_gem_object *priv = obj->driver_private; + int index; if (!kgsl_gem_memory_allocated(obj) || TYPE_IS_FD(priv->type)) return; - kgsl_gem_mem_flush(&priv->memdesc, priv->type, - DRM_KGSL_GEM_CACHE_OP_FROM_DEV); + if (priv->memdesc.gpuaddr) + kgsl_mmu_unmap(priv->memdesc.pagetable, &priv->memdesc); - kgsl_sharedmem_free(&priv->memdesc); + /* ION will take care of freeing the sg table. */ + priv->memdesc.sg = NULL; + priv->memdesc.sglen = 0; + + if (priv->ion_handle) + ion_free(kgsl_drm_ion_client, priv->ion_handle); + + priv->ion_handle = NULL; + + memset(&priv->memdesc, 0, sizeof(priv->memdesc)); + + for (index = 0; index < priv->bufcount; index++) { + if (priv->glock_handle[index]) + genlock_put_handle(priv->glock_handle[index]); + } kgsl_mmu_putpagetable(priv->pagetable); priv->pagetable = NULL; @@ -329,66 +362,10 @@ void kgsl_gem_free_object(struct drm_gem_object *obj) { kgsl_gem_free_memory(obj); - kgsl_gem_free_mmap_offset(obj); drm_gem_object_release(obj); kfree(obj->driver_private); } -static int -kgsl_gem_create_mmap_offset(struct drm_gem_object *obj) -{ - struct drm_device *dev = obj->dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_kgsl_gem_object *priv = obj->driver_private; - struct drm_map_list *list; - int msize; - - list = &obj->map_list; - list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); - if (list->map == NULL) { - DRM_ERROR("Unable to allocate drm_map_list\n"); - return -ENOMEM; - } - - msize = obj->size * priv->bufcount; - - list->map->type = _DRM_GEM; - list->map->size = msize; - list->map->handle = obj; - - /* Allocate a mmap offset */ - list->file_offset_node = drm_mm_search_free(&mm->offset_manager, - msize / PAGE_SIZE, - 0, 0); - - if (!list->file_offset_node) { - DRM_ERROR("Failed to allocate offset for %d\n", obj->name); - kfree(list->map); - return -ENOMEM; - } - - list->file_offset_node = drm_mm_get_block(list->file_offset_node, - msize / PAGE_SIZE, 0); - - if (!list->file_offset_node) { - DRM_ERROR("Unable to create the file_offset_node\n"); - kfree(list->map); - return -ENOMEM; - } - - list->hash.key = list->file_offset_node->start; - if (drm_ht_insert_item(&mm->offset_hash, &list->hash)) { - DRM_ERROR("Failed to add to map hash\n"); - drm_mm_put_block(list->file_offset_node); - kfree(list->map); - return -ENOMEM; - } - - priv->mmap_offset = ((uint64_t) list->hash.key) << PAGE_SHIFT; - - return 0; -} - int kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start, unsigned long *len) @@ -435,9 +412,6 @@ kgsl_gem_obj_addr(int drm_fd, int handle, unsigned long *start, priv->bufs[priv->active].offset; *len = priv->memdesc.size; - - kgsl_gem_mem_flush(&priv->memdesc, - priv->type, DRM_KGSL_GEM_CACHE_OP_TO_DEV); } else { *start = 0; *len = 0; @@ -468,10 +442,7 @@ kgsl_gem_init_obj(struct drm_device *dev, priv->active = 0; priv->bound = 0; - /* To preserve backwards compatability, the default memory source - is EBI */ - - priv->type = DRM_KGSL_GEM_TYPE_PMEM | DRM_KGSL_GEM_PMEM_EBI; + priv->type = DRM_KGSL_GEM_TYPE_KMEM; ret = drm_gem_handle_create(file_priv, obj, handle); @@ -513,8 +484,11 @@ kgsl_gem_create_ioctl(struct drm_device *dev, void *data, } ret = kgsl_gem_init_obj(dev, file_priv, obj, &handle); - if (ret) + if (ret) { + drm_gem_object_release(obj); + DRM_ERROR("Unable to initialize GEM object ret = %d\n", ret); return ret; + } create->handle = handle; return 0; @@ -586,6 +560,155 @@ kgsl_gem_create_fd_ioctl(struct drm_device *dev, void *data, return ret; } +int +kgsl_gem_create_from_ion_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_create_from_ion *args = data; + struct drm_gem_object *obj; + struct ion_handle *ion_handle; + struct drm_kgsl_gem_object *priv; + struct sg_table *sg_table; + struct scatterlist *s; + int ret, handle; + unsigned long size; + struct kgsl_mmu *mmu; + + ion_handle = ion_import_dma_buf(kgsl_drm_ion_client, args->ion_fd); + if (IS_ERR_OR_NULL(ion_handle)) { + DRM_ERROR("Unable to import dmabuf. Error number = %d\n", + (int)PTR_ERR(ion_handle)); + return -EINVAL; + } + + ion_handle_get_size(kgsl_drm_ion_client, ion_handle, &size); + + if (size == 0) { + ion_free(kgsl_drm_ion_client, ion_handle); + DRM_ERROR( + "cannot create GEM object from zero size ION buffer\n"); + return -EINVAL; + } + + obj = drm_gem_object_alloc(dev, size); + + if (obj == NULL) { + ion_free(kgsl_drm_ion_client, ion_handle); + DRM_ERROR("Unable to allocate the GEM object\n"); + return -ENOMEM; + } + + ret = kgsl_gem_init_obj(dev, file_priv, obj, &handle); + if (ret) { + ion_free(kgsl_drm_ion_client, ion_handle); + drm_gem_object_release(obj); + DRM_ERROR("Unable to initialize GEM object ret = %d\n", ret); + return ret; + } + + priv = obj->driver_private; + priv->ion_handle = ion_handle; + + priv->type = DRM_KGSL_GEM_TYPE_KMEM; + list_add(&priv->list, &kgsl_mem_list); + +#if defined(CONFIG_ARCH_MSM7X27) || defined(CONFIG_ARCH_MSM8625) + mmu = &kgsl_get_device(KGSL_DEVICE_2D0)->mmu; +#else + mmu = &kgsl_get_device(KGSL_DEVICE_3D0)->mmu; +#endif + + priv->pagetable = kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT); + + priv->memdesc.pagetable = priv->pagetable; + + sg_table = ion_sg_table(kgsl_drm_ion_client, + priv->ion_handle); + if (IS_ERR_OR_NULL(priv->ion_handle)) { + DRM_ERROR("Unable to get ION sg table\n"); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + kgsl_mmu_putpagetable(priv->pagetable); + drm_gem_object_release(obj); + kfree(priv); + return -ENOMEM; + } + + priv->memdesc.sg = sg_table->sgl; + + /* Calculate the size of the memdesc from the sglist */ + + priv->memdesc.sglen = 0; + + for (s = priv->memdesc.sg; s != NULL; s = sg_next(s)) { + priv->memdesc.size += s->length; + priv->memdesc.sglen++; + } + + ret = kgsl_mmu_map(priv->pagetable, &priv->memdesc); + if (ret) { + DRM_ERROR("kgsl_mmu_map failed. ret = %d\n", ret); + ion_free(kgsl_drm_ion_client, + priv->ion_handle); + priv->ion_handle = NULL; + kgsl_mmu_putpagetable(priv->pagetable); + drm_gem_object_release(obj); + kfree(priv); + return -ENOMEM; + } + + priv->bufs[0].offset = 0; + priv->bufs[0].gpuaddr = priv->memdesc.gpuaddr; + priv->flags |= DRM_KGSL_GEM_FLAG_MAPPED; + + args->handle = handle; + return 0; +} + +int +kgsl_gem_get_ion_fd_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_get_ion_fd *args = data; + struct drm_gem_object *obj; + struct drm_kgsl_gem_object *priv; + int ret = 0; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + + if (obj == NULL) { + DRM_ERROR("Invalid GEM handle %x\n", args->handle); + return -EBADF; + } + + mutex_lock(&dev->struct_mutex); + priv = obj->driver_private; + + if (TYPE_IS_FD(priv->type)) + ret = -EINVAL; + else if (TYPE_IS_PMEM(priv->type) || TYPE_IS_MEM(priv->type)) { + if (priv->ion_handle) { + args->ion_fd = ion_share_dma_buf_fd( + kgsl_drm_ion_client, priv->ion_handle); + if (args->ion_fd < 0) { + DRM_ERROR( + "Could not share ion buffer. Error = %d\n", + args->ion_fd); + ret = -EINVAL; + } + } else { + DRM_ERROR("GEM object has no ion memory allocated.\n"); + ret = -EINVAL; + } + } + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + return ret; +} + int kgsl_gem_setmemtype_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -685,13 +808,9 @@ kgsl_gem_alloc_ioctl(struct drm_device *dev, void *data, if (ret) { DRM_ERROR("Unable to allocate object memory\n"); - } else if (!priv->mmap_offset) { - ret = kgsl_gem_create_mmap_offset(obj); - if (ret) - DRM_ERROR("Unable to create a mmap offset\n"); } - args->offset = priv->mmap_offset; + args->offset = 0; drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); @@ -703,33 +822,7 @@ int kgsl_gem_mmap_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_kgsl_gem_mmap *args = data; - struct drm_gem_object *obj; - unsigned long addr; - - obj = drm_gem_object_lookup(dev, file_priv, args->handle); - - if (obj == NULL) { - DRM_ERROR("Invalid GEM handle %x\n", args->handle); - return -EBADF; - } - - down_write(¤t->mm->mmap_sem); - - addr = do_mmap(obj->filp, 0, args->size, - PROT_READ | PROT_WRITE, MAP_SHARED, - args->offset); - - up_write(¤t->mm->mmap_sem); - - mutex_lock(&dev->struct_mutex); - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - - if (IS_ERR((void *) addr)) - return addr; - - args->hostptr = (uint32_t) addr; + /* Ion is used for mmap at this time */ return 0; } @@ -762,18 +855,6 @@ kgsl_gem_prep_ioctl(struct drm_device *dev, void *data, return ret; } - if (priv->mmap_offset == 0) { - ret = kgsl_gem_create_mmap_offset(obj); - if (ret) { - drm_gem_object_unreference(obj); - mutex_unlock(&dev->struct_mutex); - return ret; - } - } - - args->offset = priv->mmap_offset; - args->phys = priv->memdesc.physaddr; - drm_gem_object_unreference(obj); mutex_unlock(&dev->struct_mutex); @@ -822,6 +903,68 @@ kgsl_gem_get_bufinfo_ioctl(struct drm_device *dev, void *data, return ret; } +/* Get the genlock handles base off the GEM handle + */ + +int +kgsl_gem_get_glock_handles_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_glockinfo *args = data; + struct drm_gem_object *obj; + struct drm_kgsl_gem_object *priv; + int index; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + + if (obj == NULL) { + DRM_ERROR("Invalid GEM handle %x\n", args->handle); + return -EBADF; + } + + mutex_lock(&dev->struct_mutex); + priv = obj->driver_private; + + for (index = 0; index < priv->bufcount; index++) { + args->glockhandle[index] = genlock_get_fd_handle( + priv->glock_handle[index]); + } + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + return 0; +} + +int +kgsl_gem_set_glock_handles_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_glockinfo *args = data; + struct drm_gem_object *obj; + struct drm_kgsl_gem_object *priv; + int index; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + + if (obj == NULL) { + DRM_ERROR("Invalid GEM handle %x\n", args->handle); + return -EBADF; + } + + mutex_lock(&dev->struct_mutex); + priv = obj->driver_private; + + for (index = 0; index < priv->bufcount; index++) { + priv->glock_handle[index] = genlock_get_handle_fd( + args->glockhandle[index]); + } + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + return 0; +} + int kgsl_gem_set_bufcount_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -863,6 +1006,32 @@ kgsl_gem_set_bufcount_ioctl(struct drm_device *dev, void *data, return ret; } +int +kgsl_gem_get_bufcount_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_kgsl_gem_bufcount *args = data; + struct drm_gem_object *obj; + struct drm_kgsl_gem_object *priv; + + obj = drm_gem_object_lookup(dev, file_priv, args->handle); + + if (obj == NULL) { + DRM_ERROR("Invalid GEM handle %x\n", args->handle); + return -EBADF; + } + + mutex_lock(&dev->struct_mutex); + priv = obj->driver_private; + + args->bufcount = priv->bufcount; + + drm_gem_object_unreference(obj); + mutex_unlock(&dev->struct_mutex); + + return 0; +} + int kgsl_gem_set_active_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) @@ -957,122 +1126,6 @@ int kgsl_gem_phys_fault(struct vm_area_struct *vma, struct vm_fault *vmf) } } -static struct vm_operations_struct kgsl_gem_kmem_vm_ops = { - .fault = kgsl_gem_kmem_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - -static struct vm_operations_struct kgsl_gem_phys_vm_ops = { - .fault = kgsl_gem_phys_fault, - .open = drm_gem_vm_open, - .close = drm_gem_vm_close, -}; - -/* This is a clone of the standard drm_gem_mmap function modified to allow - us to properly map KMEM regions as well as the PMEM regions */ - -int msm_drm_gem_mmap(struct file *filp, struct vm_area_struct *vma) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->minor->dev; - struct drm_gem_mm *mm = dev->mm_private; - struct drm_local_map *map = NULL; - struct drm_gem_object *obj; - struct drm_hash_item *hash; - struct drm_kgsl_gem_object *gpriv; - int ret = 0; - - mutex_lock(&dev->struct_mutex); - - if (drm_ht_find_item(&mm->offset_hash, vma->vm_pgoff, &hash)) { - mutex_unlock(&dev->struct_mutex); - return drm_mmap(filp, vma); - } - - map = drm_hash_entry(hash, struct drm_map_list, hash)->map; - if (!map || - ((map->flags & _DRM_RESTRICTED) && !capable(CAP_SYS_ADMIN))) { - ret = -EPERM; - goto out_unlock; - } - - /* Check for valid size. */ - if (map->size < vma->vm_end - vma->vm_start) { - ret = -EINVAL; - goto out_unlock; - } - - obj = map->handle; - - gpriv = obj->driver_private; - - /* VM_PFNMAP is only for memory that doesn't use struct page - * in other words, not "normal" memory. If you try to use it - * with "normal" memory then the mappings don't get flushed. */ - - if (TYPE_IS_MEM(gpriv->type)) { - vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND; - vma->vm_ops = &kgsl_gem_kmem_vm_ops; - } else { - vma->vm_flags |= VM_RESERVED | VM_IO | VM_PFNMAP | - VM_DONTEXPAND; - vma->vm_ops = &kgsl_gem_phys_vm_ops; - } - - vma->vm_private_data = map->handle; - - - /* Take care of requested caching policy */ - if (gpriv->type == DRM_KGSL_GEM_TYPE_KMEM || - gpriv->type & DRM_KGSL_GEM_CACHE_MASK) { - if (gpriv->type & DRM_KGSL_GEM_CACHE_WBACKWA) - vma->vm_page_prot = - pgprot_writebackwacache(vma->vm_page_prot); - else if (gpriv->type & DRM_KGSL_GEM_CACHE_WBACK) - vma->vm_page_prot = - pgprot_writebackcache(vma->vm_page_prot); - else if (gpriv->type & DRM_KGSL_GEM_CACHE_WTHROUGH) - vma->vm_page_prot = - pgprot_writethroughcache(vma->vm_page_prot); - else - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); - } else { - if (gpriv->type == DRM_KGSL_GEM_TYPE_KMEM_NOCACHE) - vma->vm_page_prot = - pgprot_noncached(vma->vm_page_prot); - else - /* default pmem is WC */ - vma->vm_page_prot = - pgprot_writecombine(vma->vm_page_prot); - } - - /* flush out existing KMEM cached mappings if new ones are - * of uncached type */ - if (IS_MEM_UNCACHED(gpriv->type)) - kgsl_cache_range_op(&gpriv->memdesc, - KGSL_CACHE_OP_FLUSH); - - /* Add the other memory types here */ - - /* Take a ref for this mapping of the object, so that the fault - * handler can dereference the mmap offset's pointer to the object. - * This reference is cleaned up by the corresponding vm_close - * (which should happen whether the vma was created by this call, or - * by a vm_open due to mremap or partial unmap or whatever). - */ - drm_gem_object_reference(obj); - - vma->vm_file = filp; /* Needed for drm_vm_open() */ - drm_vm_open_locked(vma); - -out_unlock: - mutex_unlock(&dev->struct_mutex); - - return ret; -} - void cleanup_fence(struct drm_kgsl_gem_object_fence *fence, int check_waiting) { @@ -1434,8 +1487,17 @@ struct drm_ioctl_desc kgsl_drm_ioctls[] = { DRM_IOCTL_DEF_DRV(KGSL_GEM_ALLOC, kgsl_gem_alloc_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_MMAP, kgsl_gem_mmap_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_BUFINFO, kgsl_gem_get_bufinfo_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_ION_FD, kgsl_gem_get_ion_fd_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_CREATE_FROM_ION, + kgsl_gem_create_from_ion_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_BUFCOUNT, - kgsl_gem_set_bufcount_ioctl, 0), + kgsl_gem_set_bufcount_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_BUFCOUNT, + kgsl_gem_get_bufcount_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_GLOCK_HANDLES_INFO, + kgsl_gem_set_glock_handles_ioctl, 0), + DRM_IOCTL_DEF_DRV(KGSL_GEM_GET_GLOCK_HANDLES_INFO, + kgsl_gem_get_glock_handles_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_SET_ACTIVE, kgsl_gem_set_active_ioctl, 0), DRM_IOCTL_DEF_DRV(KGSL_GEM_LOCK_HANDLE, kgsl_gem_lock_handle_ioctl, 0), @@ -1447,28 +1509,22 @@ struct drm_ioctl_desc kgsl_drm_ioctls[] = { DRM_MASTER), }; +static const struct file_operations kgsl_drm_driver_fops = { + .owner = THIS_MODULE, + .open = drm_open, + .release = drm_release, + .unlocked_ioctl = drm_ioctl, + .mmap = drm_gem_mmap, + .poll = drm_poll, + .fasync = drm_fasync, +}; + static struct drm_driver driver = { .driver_features = DRIVER_GEM, - .load = kgsl_drm_load, - .unload = kgsl_drm_unload, - .preclose = kgsl_drm_preclose, - .suspend = kgsl_drm_suspend, - .resume = kgsl_drm_resume, - .reclaim_buffers = drm_core_reclaim_buffers, .gem_init_object = kgsl_gem_init_object, .gem_free_object = kgsl_gem_free_object, .ioctls = kgsl_drm_ioctls, - - .fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = msm_drm_gem_mmap, - .poll = drm_poll, - .fasync = drm_fasync, - }, - + .fops = &kgsl_drm_driver_fops, .name = DRIVER_NAME, .desc = DRIVER_DESC, .date = DRIVER_DATE, @@ -1497,11 +1553,24 @@ int kgsl_drm_init(struct platform_device *dev) gem_buf_fence[i].fence_id = ENTRY_EMPTY; } + /* Create ION Client */ + kgsl_drm_ion_client = msm_ion_client_create( + 0xffffffff, "kgsl_drm"); + if (!kgsl_drm_ion_client) { + DRM_ERROR("Unable to create ION client\n"); + return -ENOMEM; + } + return drm_platform_init(&driver, dev); } void kgsl_drm_exit(void) { kgsl_drm_inited = DRM_KGSL_NOT_INITED; + + if (kgsl_drm_ion_client) + ion_client_destroy(kgsl_drm_ion_client); + kgsl_drm_ion_client = NULL; + drm_platform_exit(&driver, driver.kdriver.platform_device); } diff --git a/drivers/gpu/msm/kgsl_events.c b/drivers/gpu/msm/kgsl_events.c index e8c6c5d8a8e..d76b628df1c 100644 --- a/drivers/gpu/msm/kgsl_events.c +++ b/drivers/gpu/msm/kgsl_events.c @@ -17,6 +17,7 @@ #include #include "kgsl_trace.h" +#include "adreno.h" static inline struct list_head *_get_list_head(struct kgsl_device *device, struct kgsl_context *context) @@ -48,7 +49,8 @@ static inline void _do_signal_event(struct kgsl_device *device, { int id = event->context ? event->context->id : KGSL_MEMSTORE_GLOBAL; - trace_kgsl_fire_event(id, timestamp, type, jiffies - event->created); + trace_kgsl_fire_event(id, timestamp, type, jiffies - event->created, + event->func); if (event->func) event->func(device, event->priv, id, timestamp, type); @@ -56,8 +58,6 @@ static inline void _do_signal_event(struct kgsl_device *device, list_del(&event->list); kgsl_context_put(event->context); kfree(event); - - kgsl_active_count_put(device); } static void _retire_events(struct kgsl_device *device, @@ -210,10 +210,11 @@ EXPORT_SYMBOL(kgsl_signal_events); int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, kgsl_event_func func, void *priv, void *owner) { - int ret; struct kgsl_event *event; unsigned int cur_ts; struct kgsl_context *context = NULL; + struct adreno_context *drawctxt; + struct adreno_device *adreno_dev = ADRENO_DEVICE(device); BUG_ON(!mutex_is_locked(&device->mutex)); @@ -224,6 +225,15 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, context = kgsl_context_get(device, id); if (context == NULL) return -EINVAL; + /* Do not allow registering of event with invalid timestamp */ + drawctxt = ADRENO_CONTEXT(context); + if (timestamp_cmp(ts, drawctxt->timestamp) > 0) { + kgsl_context_put(context); + return -EINVAL; + } + } else { + if (timestamp_cmp(ts, adreno_dev->ringbuffer.global_ts) > 0) + return -EINVAL; } cur_ts = kgsl_readtimestamp(device, context, KGSL_TIMESTAMP_RETIRED); @@ -235,10 +245,11 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, */ if (timestamp_cmp(cur_ts, ts) >= 0) { - trace_kgsl_fire_event(id, cur_ts, ts, 0); + trace_kgsl_fire_event(id, cur_ts, ts, 0, func); func(device, priv, id, ts, KGSL_EVENT_TIMESTAMP_RETIRED); kgsl_context_put(context); + queue_work(device->work_queue, &device->ts_expired_ws); return 0; } @@ -248,17 +259,6 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, return -ENOMEM; } - /* - * Increase the active count on the device to avoid going into power - * saving modes while events are pending - */ - ret = kgsl_active_count_get_light(device); - if (ret < 0) { - kgsl_context_put(context); - kfree(event); - return ret; - } - event->context = context; event->timestamp = ts; event->priv = priv; @@ -266,7 +266,7 @@ int kgsl_add_event(struct kgsl_device *device, u32 id, u32 ts, event->owner = owner; event->created = jiffies; - trace_kgsl_register_event(id, ts); + trace_kgsl_register_event(id, ts, func); /* Add the event to either the owning context or the global list */ @@ -346,44 +346,13 @@ void kgsl_cancel_event(struct kgsl_device *device, struct kgsl_context *context, } EXPORT_SYMBOL(kgsl_cancel_event); -static inline int _mark_next_event(struct kgsl_device *device, - struct list_head *head) -{ - struct kgsl_event *event; - - if (!list_empty(head)) { - event = list_first_entry(head, struct kgsl_event, list); - - /* - * Next event will return 0 if the event was marked or 1 if the - * timestamp on the event has passed - return that up a layer - */ - - if (device->ftbl->next_event) - return device->ftbl->next_event(device, event); - } - - return 0; -} - static int kgsl_process_context_events(struct kgsl_device *device, struct kgsl_context *context) { - while (1) { - unsigned int timestamp = kgsl_readtimestamp(device, context, - KGSL_TIMESTAMP_RETIRED); - - _retire_events(device, &context->events, timestamp); - - /* - * _mark_next event will return 1 as long as the next event - * timestamp has expired - this is to cope with an unavoidable - * race condition with the GPU that is still processing events. - */ + unsigned int timestamp = kgsl_readtimestamp(device, context, + KGSL_TIMESTAMP_RETIRED); - if (!_mark_next_event(device, &context->events)) - break; - } + _retire_events(device, &context->events, timestamp); /* * Return 0 if the list is empty so the calling function can remove the @@ -400,21 +369,10 @@ void kgsl_process_events(struct work_struct *work) struct kgsl_context *context, *tmp; uint32_t timestamp; - /* - * Bail unless the global timestamp has advanced. We can safely do this - * outside of the mutex for speed - */ - - timestamp = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED); - if (timestamp == device->events_last_timestamp) - return; - mutex_lock(&device->mutex); - device->events_last_timestamp = timestamp; - + timestamp = kgsl_readtimestamp(device, NULL, KGSL_TIMESTAMP_RETIRED); _retire_events(device, &device->events, timestamp); - _mark_next_event(device, &device->events); /* Now process all of the pending contexts */ list_for_each_entry_safe(context, tmp, &device->events_pending_list, @@ -424,15 +382,17 @@ void kgsl_process_events(struct work_struct *work) * Increment the refcount to make sure that the list_del_init * is called with a valid context's list */ - _kgsl_context_get(context); - /* - * If kgsl_timestamp_expired_context returns 0 then it no longer - * has any pending events and can be removed from the list - */ - - if (kgsl_process_context_events(device, context) == 0) - list_del_init(&context->events_list); - kgsl_context_put(context); + if (_kgsl_context_get(context)) { + /* + * If kgsl_timestamp_expired_context returns 0 then it + * no longer has any pending events and can be removed + * from the list + */ + + if (kgsl_process_context_events(device, context) == 0) + list_del_init(&context->events_list); + kgsl_context_put(context); + } } mutex_unlock(&device->mutex); diff --git a/drivers/gpu/msm/kgsl_gpummu.c b/drivers/gpu/msm/kgsl_gpummu.c index e52bb5dfd37..1a1e2e3549f 100644 --- a/drivers/gpu/msm/kgsl_gpummu.c +++ b/drivers/gpu/msm/kgsl_gpummu.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, 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 @@ -19,6 +19,7 @@ #include "kgsl.h" #include "kgsl_mmu.h" +#include "kgsl_gpummu.h" #include "kgsl_device.h" #include "kgsl_sharedmem.h" #include "kgsl_trace.h" @@ -161,7 +162,7 @@ _kgsl_ptpool_add_entries(struct kgsl_ptpool *pool, int count, int dynamic) } static void * -_kgsl_ptpool_get_entry(struct kgsl_ptpool *pool, unsigned int *physaddr) +_kgsl_ptpool_get_entry(struct kgsl_ptpool *pool, phys_addr_t *physaddr) { struct kgsl_ptpool_chunk *chunk; @@ -227,7 +228,7 @@ kgsl_ptpool_add(struct kgsl_ptpool *pool, int count) */ static void *kgsl_ptpool_alloc(struct kgsl_ptpool *pool, - unsigned int *physaddr) + phys_addr_t *physaddr) { void *addr = NULL; int ret; @@ -357,16 +358,15 @@ void *kgsl_gpummu_ptpool_init(int entries) int kgsl_gpummu_pt_equal(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt, - unsigned int pt_base) + phys_addr_t pt_base) { struct kgsl_gpummu_pt *gpummu_pt = pt ? pt->priv : NULL; return gpummu_pt && pt_base && (gpummu_pt->base.gpuaddr == pt_base); } -void kgsl_gpummu_destroy_pagetable(void *mmu_specific_pt) +void kgsl_gpummu_destroy_pagetable(struct kgsl_pagetable *pt) { - struct kgsl_gpummu_pt *gpummu_pt = (struct kgsl_gpummu_pt *) - mmu_specific_pt; + struct kgsl_gpummu_pt *gpummu_pt = pt->priv; kgsl_ptpool_free((struct kgsl_ptpool *)kgsl_driver.ptpool, gpummu_pt->base.hostptr); @@ -446,15 +446,20 @@ static void *kgsl_gpummu_create_pagetable(void) if (gpummu_pt->base.hostptr == NULL) goto err_flushfilter; + /* Do a check before truncating phys_addr_t to unsigned 32 */ + if (sizeof(phys_addr_t) > sizeof(unsigned int)) { + WARN_ONCE(1, "Cannot use LPAE with gpummu\n"); + goto err_flushfilter; + } + gpummu_pt->base.gpuaddr = gpummu_pt->base.physaddr; + gpummu_pt->base.size = KGSL_PAGETABLE_SIZE; + /* ptpool allocations are from coherent memory, so update the device statistics acordingly */ KGSL_STATS_ADD(KGSL_PAGETABLE_SIZE, kgsl_driver.stats.coherent, kgsl_driver.stats.coherent_max); - gpummu_pt->base.gpuaddr = gpummu_pt->base.physaddr; - gpummu_pt->base.size = KGSL_PAGETABLE_SIZE; - return (void *)gpummu_pt; err_flushfilter: @@ -473,7 +478,9 @@ static int kgsl_gpummu_default_setstate(struct kgsl_mmu *mmu, return 0; if (flags & KGSL_MMUFLAGS_PTUPDATE) { - kgsl_idle(mmu->device); + int ret = kgsl_idle(mmu->device); + if (ret) + return ret; gpummu_pt = mmu->hwpagetable->priv; kgsl_regwrite(mmu->device, MH_MMU_PT_BASE, gpummu_pt->base.gpuaddr); @@ -523,6 +530,11 @@ static int kgsl_gpummu_init(struct kgsl_mmu *mmu) */ int status = 0; + mmu->pt_base = KGSL_PAGETABLE_BASE; + mmu->pt_size = CONFIG_MSM_KGSL_PAGE_TABLE_SIZE; + mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT; + mmu->use_cpu_map = false; + /* sub-client MMU lookups require address translation */ if ((mmu->config & ~0x1) > 0) { /*make sure virtual address range is a multiple of 64Kb */ @@ -564,7 +576,7 @@ static int kgsl_gpummu_start(struct kgsl_mmu *mmu) kgsl_regwrite(device, MH_INTERRUPT_MASK, GSL_MMU_INT_MASK | MH_INTERRUPT_MASK__MMU_PAGE_FAULT); - kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0, + kgsl_sharedmem_set(device, &mmu->setstate_memory, 0, 0, mmu->setstate_memory.size); /* TRAN_ERROR needs a 32 byte (32 byte aligned) chunk of memory @@ -577,7 +589,7 @@ static int kgsl_gpummu_start(struct kgsl_mmu *mmu) if (mmu->defaultpagetable == NULL) mmu->defaultpagetable = - kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); + kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT); /* Return error if the default pagetable doesn't exist */ if (mmu->defaultpagetable == NULL) @@ -599,14 +611,14 @@ static int kgsl_gpummu_start(struct kgsl_mmu *mmu) } static int -kgsl_gpummu_unmap(void *mmu_specific_pt, +kgsl_gpummu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags) { unsigned int numpages; unsigned int pte, ptefirst, ptelast, superpte; unsigned int range = memdesc->size; - struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt; + struct kgsl_gpummu_pt *gpummu_pt = pt->priv; /* All GPU addresses as assigned are page aligned, but some functions purturb the gpuaddr with an offset, so apply the @@ -648,13 +660,13 @@ kgsl_gpummu_unmap(void *mmu_specific_pt, GSL_TLBFLUSH_FILTER_ISDIRTY((_p) / GSL_PT_SUPER_PTE)) static int -kgsl_gpummu_map(void *mmu_specific_pt, +kgsl_gpummu_map(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int protflags, unsigned int *tlb_flags) { unsigned int pte; - struct kgsl_gpummu_pt *gpummu_pt = mmu_specific_pt; + struct kgsl_gpummu_pt *gpummu_pt = pt->priv; struct scatterlist *s; int flushtlb = 0; int i; @@ -713,7 +725,7 @@ static int kgsl_gpummu_close(struct kgsl_mmu *mmu) return 0; } -static unsigned int +static phys_addr_t kgsl_gpummu_get_current_ptbase(struct kgsl_mmu *mmu) { unsigned int ptbase; @@ -721,7 +733,7 @@ kgsl_gpummu_get_current_ptbase(struct kgsl_mmu *mmu) return ptbase; } -static unsigned int +static phys_addr_t kgsl_gpummu_get_pt_base_addr(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) { @@ -747,9 +759,11 @@ struct kgsl_mmu_ops gpummu_ops = { .mmu_get_pt_base_addr = kgsl_gpummu_get_pt_base_addr, .mmu_enable_clk = NULL, .mmu_disable_clk_on_ts = NULL, - .mmu_get_pt_lsb = NULL, + .mmu_get_default_ttbr0 = NULL, .mmu_get_reg_gpuaddr = NULL, + .mmu_get_reg_ahbaddr = NULL, .mmu_get_num_iommu_units = kgsl_gpummu_get_num_iommu_units, + .mmu_hw_halt_supported = NULL, }; struct kgsl_mmu_pt_ops gpummu_pt_ops = { diff --git a/drivers/gpu/msm/kgsl_gpummu.h b/drivers/gpu/msm/kgsl_gpummu.h index 99e7d5feb6e..1753afff442 100644 --- a/drivers/gpu/msm/kgsl_gpummu.h +++ b/drivers/gpu/msm/kgsl_gpummu.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2013, 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 @@ -57,7 +57,7 @@ struct kgsl_ptpool_chunk { int dynamic; void *data; - unsigned int phys; + phys_addr_t phys; unsigned long *bitmap; struct list_head list; diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 57ee5404adb..d9db49c8969 100644 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "kgsl.h" @@ -35,32 +36,53 @@ #include "kgsl_cffdump.h" -static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = { - { 0, 0, 0 }, /* GLOBAL_BASE */ - { 0x10, 0x0003FFFF, 14 }, /* TTBR0 */ - { 0x14, 0x0003FFFF, 14 }, /* TTBR1 */ - { 0x20, 0, 0 }, /* FSR */ - { 0x800, 0, 0 }, /* TLBIALL */ - { 0x820, 0, 0 }, /* RESUME */ - { 0x03C, 0, 0 }, /* TLBLKCR */ - { 0x818, 0, 0 }, /* V2PUR */ - { 0x2C, 0, 0 }, /* FSYNR0 */ - { 0x2C, 0, 0 }, /* FSYNR0 */ +static struct kgsl_iommu_register_list kgsl_iommuv0_reg[KGSL_IOMMU_REG_MAX] = { + { 0, 0 }, /* GLOBAL_BASE */ + { 0x0, 1 }, /* SCTLR */ + { 0x10, 1 }, /* TTBR0 */ + { 0x14, 1 }, /* TTBR1 */ + { 0x20, 1 }, /* FSR */ + { 0x800, 1 }, /* TLBIALL */ + { 0x820, 1 }, /* RESUME */ + { 0x03C, 1 }, /* TLBLKCR */ + { 0x818, 1 }, /* V2PUR */ + { 0x2C, 1 }, /* FSYNR0 */ + { 0x30, 1 }, /* FSYNR0 */ + { 0, 0 }, /* TLBSYNC, not in v0 */ + { 0, 0 }, /* TLBSTATUS, not in v0 */ + { 0, 0 } /* IMPLDEF_MICRO_MMU_CRTL, not in v0 */ }; -static struct kgsl_iommu_register_list kgsl_iommuv2_reg[KGSL_IOMMU_REG_MAX] = { - { 0, 0, 0 }, /* GLOBAL_BASE */ - { 0x20, 0x00FFFFFF, 14 }, /* TTBR0 */ - { 0x28, 0x00FFFFFF, 14 }, /* TTBR1 */ - { 0x58, 0, 0 }, /* FSR */ - { 0x618, 0, 0 }, /* TLBIALL */ - { 0x008, 0, 0 }, /* RESUME */ - { 0, 0, 0 }, /* TLBLKCR */ - { 0, 0, 0 }, /* V2PUR */ - { 0x68, 0, 0 }, /* FSYNR0 */ - { 0x6C, 0, 0 } /* FSYNR1 */ +static struct kgsl_iommu_register_list kgsl_iommuv1_reg[KGSL_IOMMU_REG_MAX] = { + { 0, 0 }, /* GLOBAL_BASE */ + { 0x0, 1 }, /* SCTLR */ + { 0x20, 1 }, /* TTBR0 */ + { 0x28, 1 }, /* TTBR1 */ + { 0x58, 1 }, /* FSR */ + { 0x618, 1 }, /* TLBIALL */ + { 0x008, 1 }, /* RESUME */ + { 0, 0 }, /* TLBLKCR not in V1 */ + { 0, 0 }, /* V2PUR not in V1 */ + { 0x68, 1 }, /* FSYNR0 */ + { 0x6C, 1 }, /* FSYNR1 */ + { 0x7F0, 1 }, /* TLBSYNC */ + { 0x7F4, 1 }, /* TLBSTATUS */ + { 0x2000, 0 } /* IMPLDEF_MICRO_MMU_CRTL */ }; +/* naming mismatch with iommu things */ +static void _iommu_lock(void) +{ + return; +} + +/* naming mismatch with iommu things */ +static void _iommu_unlock(void) +{ + return; +} + + struct remote_iommu_petersons_spinlock kgsl_iommu_sync_lock_vars; /* @@ -221,7 +243,7 @@ static void _find_mem_entries(struct kgsl_mmu *mmu, unsigned int faultaddr, list_for_each_entry(private, &kgsl_driver.process_list, list) { - if (private->pagetable->name != id) + if (private->pagetable && (private->pagetable->name != id)) continue; spin_lock(&private->mem_lock); @@ -254,6 +276,8 @@ static void _check_if_freed(struct kgsl_iommu_device *iommu_dev, void *base = kgsl_driver.memfree_hist.base_hist_rb; struct kgsl_memfree_hist_elem *wptr; struct kgsl_memfree_hist_elem *p; + char name[32]; + memset(name, 0, sizeof(name)); mutex_lock(&kgsl_driver.memfree_hist_mutex); wptr = kgsl_driver.memfree_hist.wptr; @@ -263,12 +287,15 @@ static void _check_if_freed(struct kgsl_iommu_device *iommu_dev, if (addr >= p->gpuaddr && addr < (p->gpuaddr + p->size)) { + kgsl_get_memory_usage(name, sizeof(name) - 1, + p->flags); KGSL_LOG_DUMP(iommu_dev->kgsldev, "---- premature free ----\n"); KGSL_LOG_DUMP(iommu_dev->kgsldev, - "[%8.8X-%8.8X] was already freed by pid %d\n", + "[%8.8X-%8.8X] (%s) was already freed by pid %d\n", p->gpuaddr, p->gpuaddr + p->size, + name, p->pid); } p++; @@ -282,7 +309,7 @@ static void _check_if_freed(struct kgsl_iommu_device *iommu_dev, } static int kgsl_iommu_fault_handler(struct iommu_domain *domain, - struct device *dev, unsigned long addr, int flags) + struct device *dev, unsigned long addr, int flags, void *token) { int ret = 0; struct kgsl_mmu *mmu; @@ -297,10 +324,22 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, unsigned int fsynr0, fsynr1; int write; struct _mem_entry prev, next; + unsigned int curr_context_id = 0; + unsigned int curr_global_ts = 0; + struct kgsl_context *context; ret = get_iommu_unit(dev, &mmu, &iommu_unit); if (ret) goto done; + + device = mmu->device; + adreno_dev = ADRENO_DEVICE(device); + if (atomic_read(&mmu->fault)) { + if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) + ret = -EBUSY; + goto done; + } + iommu_dev = get_iommu_device(iommu_unit, dev); if (!iommu_dev) { KGSL_CORE_ERR("Invalid IOMMU device %p\n", dev); @@ -308,8 +347,38 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, goto done; } iommu = mmu->priv; - device = mmu->device; - adreno_dev = ADRENO_DEVICE(device); + + /* + * set the fault bits and stuff before any printks so that if fault + * handler runs then it will know it's dealing with a pagefault + */ + kgsl_sharedmem_readl(&device->memstore, &curr_context_id, + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context)); + + context = kgsl_context_get(device, curr_context_id); + + if (context != NULL) { + kgsl_sharedmem_readl(&device->memstore, &curr_global_ts, + KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, + eoptimestamp)); + + /* save pagefault timestamp for GFT */ + set_bit(KGSL_CONTEXT_PAGEFAULT, &context->priv); + context->pagefault_ts = curr_global_ts; + + kgsl_context_put(context); + context = NULL; + } + + atomic_set(&mmu->fault, 1); + iommu_dev->fault = 1; + + if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_GPUHALT_ENABLE) { + adreno_set_gpu_fault(adreno_dev, ADRENO_IOMMU_PAGE_FAULT); + /* turn off GPU IRQ so we don't get faults from it too */ + kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF); + adreno_dispatcher_schedule(device); + } ptbase = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit, iommu_dev->ctx_id, TTBR0); @@ -328,41 +397,40 @@ static int kgsl_iommu_fault_handler(struct iommu_domain *domain, write = ((fsynr0 & (KGSL_IOMMU_V1_FSYNR0_WNR_MASK << KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT)) ? 1 : 0); + pid = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase); + if (adreno_dev->ft_pf_policy & KGSL_FT_PAGEFAULT_LOG_ONE_PER_PAGE) no_page_fault_log = kgsl_mmu_log_fault_addr(mmu, ptbase, addr); - pid = kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase); if (!no_page_fault_log) { KGSL_MEM_CRIT(iommu_dev->kgsldev, "GPU PAGE FAULT: addr = %lX pid = %d\n", addr, pid); KGSL_MEM_CRIT(iommu_dev->kgsldev, - "context = %d FSR = %X FSYNR0 = %X FSYNR1 = %X(%s fault)\n", + "context = %d FSR = %X FSYNR0 = %X FSYNR1 = %X(%s fault)\n", iommu_dev->ctx_id, fsr, fsynr0, fsynr1, write ? "write" : "read"); - } - - _check_if_freed(iommu_dev, addr, pid); - KGSL_LOG_DUMP(iommu_dev->kgsldev, "---- nearby memory ----\n"); + _check_if_freed(iommu_dev, addr, pid); - _find_mem_entries(mmu, addr, ptbase, &prev, &next); + KGSL_LOG_DUMP(iommu_dev->kgsldev, "---- nearby memory ----\n"); - if (prev.gpuaddr) - _print_entry(iommu_dev->kgsldev, &prev); - else - KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n"); + _find_mem_entries(mmu, addr, ptbase, &prev, &next); - KGSL_LOG_DUMP(iommu_dev->kgsldev, " <- fault @ %8.8lX\n", addr); + if (prev.gpuaddr) + _print_entry(iommu_dev->kgsldev, &prev); + else + KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n"); - if (next.gpuaddr != 0xFFFFFFFF) - _print_entry(iommu_dev->kgsldev, &next); - else - KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n"); + KGSL_LOG_DUMP(iommu_dev->kgsldev, " <- fault @ %8.8lX\n", addr); - mmu->fault = 1; - iommu_dev->fault = 1; + if (next.gpuaddr != 0xFFFFFFFF) + _print_entry(iommu_dev->kgsldev, &next); + else + KGSL_LOG_DUMP(iommu_dev->kgsldev, "*EMPTY*\n"); + } - trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr, pid, + trace_kgsl_mmu_pagefault(iommu_dev->kgsldev, addr, + kgsl_mmu_get_ptname_from_ptbase(mmu, ptbase), write ? "write" : "read"); /* @@ -559,23 +627,24 @@ static int kgsl_iommu_enable_clk(struct kgsl_mmu *mmu, */ static int kgsl_iommu_pt_equal(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt, - unsigned int pt_base) + phys_addr_t pt_base) { - struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_pt *iommu_pt = pt ? pt->priv : NULL; - unsigned int domain_ptbase = iommu_pt ? - iommu_get_pt_base_addr(iommu_pt->domain) : 0; + phys_addr_t domain_ptbase; + + if (iommu_pt == NULL) + return 0; + + domain_ptbase = iommu_get_pt_base_addr(iommu_pt->domain) + & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + /* Only compare the valid address bits of the pt_base */ - domain_ptbase &= - (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); + domain_ptbase &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; - pt_base &= - (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); + pt_base &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + + return (domain_ptbase == pt_base); - return domain_ptbase && pt_base && - (domain_ptbase == pt_base); } /* @@ -584,12 +653,14 @@ static int kgsl_iommu_pt_equal(struct kgsl_mmu *mmu, * * Return - void */ -static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt) +static void kgsl_iommu_destroy_pagetable(struct kgsl_pagetable *pt) { - struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; + struct kgsl_iommu_pt *iommu_pt = pt->priv; if (iommu_pt->domain) - iommu_domain_free(iommu_pt->domain); + msm_unregister_domain(iommu_pt->domain); + kfree(iommu_pt); + iommu_pt = NULL; } /* @@ -601,8 +672,20 @@ static void kgsl_iommu_destroy_pagetable(void *mmu_specific_pt) */ void *kgsl_iommu_create_pagetable(void) { + int domain_num; struct kgsl_iommu_pt *iommu_pt; + struct msm_iova_partition kgsl_partition = { + .start = 0, + .size = 0xFFFFFFFF, + }; + struct msm_iova_layout kgsl_layout = { + .partitions = &kgsl_partition, + .npartitions = 1, + .client_name = "kgsl", + .domain_flags = 0, + }; + iommu_pt = kzalloc(sizeof(struct kgsl_iommu_pt), GFP_KERNEL); if (!iommu_pt) { KGSL_CORE_ERR("kzalloc(%d) failed\n", @@ -611,21 +694,23 @@ void *kgsl_iommu_create_pagetable(void) } /* L2 redirect is not stable on IOMMU v2 */ if (msm_soc_version_supports_iommu_v1()) - iommu_pt->domain = iommu_domain_alloc(&platform_bus_type, - MSM_IOMMU_DOMAIN_PT_CACHEABLE); - else - iommu_pt->domain = iommu_domain_alloc(&platform_bus_type, - 0); - if (!iommu_pt->domain) { - KGSL_CORE_ERR("Failed to create iommu domain\n"); - kfree(iommu_pt); - return NULL; - } else { - iommu_set_fault_handler(iommu_pt->domain, - kgsl_iommu_fault_handler); + kgsl_layout.domain_flags = MSM_IOMMU_DOMAIN_PT_CACHEABLE; + + domain_num = msm_register_domain(&kgsl_layout); + if (domain_num >= 0) { + iommu_pt->domain = msm_get_iommu_domain(domain_num); + + if (iommu_pt->domain) { + iommu_set_fault_handler(iommu_pt->domain, + kgsl_iommu_fault_handler, NULL); + + return iommu_pt; + } } - return iommu_pt; + KGSL_CORE_ERR("Failed to create iommu domain\n"); + kfree(iommu_pt); + return NULL; } /* @@ -740,17 +825,23 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu, { struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[unit_id]; - int i; - - if (data->iommu_ctx_count > KGSL_IOMMU_MAX_DEVS_PER_UNIT) { - KGSL_CORE_ERR("Too many iommu devices defined for an " - "IOMMU unit\n"); - return -EINVAL; - } - - for (i = 0; i < data->iommu_ctx_count; i++) { - if (!data->iommu_ctxs[i].iommu_ctx_name) - continue; + int i, j; + int found_ctx; + + for (j = 0; j < KGSL_IOMMU_MAX_DEVS_PER_UNIT; j++) { + found_ctx = 0; + for (i = 0; i < data->iommu_ctx_count; i++) { + if (j == data->iommu_ctxs[i].ctx_id) { + found_ctx = 1; + break; + } + } + if (!found_ctx) + break; + if (!data->iommu_ctxs[i].iommu_ctx_name) { + KGSL_CORE_ERR("Context name invalid\n"); + return -EINVAL; + } iommu_unit->dev[iommu_unit->dev_count].dev = msm_iommu_get_ctx(data->iommu_ctxs[i].iommu_ctx_name); @@ -759,12 +850,6 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu, "device %s\n", data->iommu_ctxs[i].iommu_ctx_name); return -EINVAL; } - if (KGSL_IOMMU_CONTEXT_USER != data->iommu_ctxs[i].ctx_id && - KGSL_IOMMU_CONTEXT_PRIV != data->iommu_ctxs[i].ctx_id) { - KGSL_CORE_ERR("Invalid context ID defined: %d\n", - data->iommu_ctxs[i].ctx_id); - return -EINVAL; - } iommu_unit->dev[iommu_unit->dev_count].ctx_id = data->iommu_ctxs[i].ctx_id; iommu_unit->dev[iommu_unit->dev_count].kgsldev = mmu->device; @@ -776,6 +861,52 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu, iommu_unit->dev_count++; } + if (!j) { + KGSL_CORE_ERR("No ctxts initialized, user ctxt absent\n "); + return -EINVAL; + } + + return 0; +} + +/* + * kgsl_iommu_start_sync_lock - Initialize some variables during MMU start up + * for GPU CPU synchronization + * @mmu - Pointer to mmu device + * + * Return - 0 on success else error code + */ +static int kgsl_iommu_start_sync_lock(struct kgsl_mmu *mmu) +{ + struct kgsl_iommu *iommu = mmu->priv; + uint32_t lock_gpu_addr = 0; + + /* iommu v1 or v0 here, cp has v1 */ + if (KGSL_DEVICE_3D0 != mmu->device->id || + !msm_soc_version_supports_iommu_v1() || + !kgsl_mmu_is_perprocess(mmu) || + iommu->sync_lock_vars) + return 0; + + if (!(mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC)) { + KGSL_DRV_ERR(mmu->device, + "The GPU microcode does not support IOMMUv1 sync opcodes\n"); + return -ENXIO; + } + /* Store Lock variables GPU address */ + lock_gpu_addr = (iommu->sync_lock_desc.gpuaddr + + iommu->sync_lock_offset); + + kgsl_iommu_sync_lock_vars.flag[PROC_APPS] = (lock_gpu_addr + + (offsetof(struct remote_iommu_petersons_spinlock, + flag[PROC_APPS]))); + kgsl_iommu_sync_lock_vars.flag[PROC_GPU] = (lock_gpu_addr + + (offsetof(struct remote_iommu_petersons_spinlock, + flag[PROC_GPU]))); + kgsl_iommu_sync_lock_vars.turn = (lock_gpu_addr + + (offsetof(struct remote_iommu_petersons_spinlock, turn))); + + iommu->sync_lock_vars = &kgsl_iommu_sync_lock_vars; return 0; } @@ -788,27 +919,15 @@ static int _get_iommu_ctxs(struct kgsl_mmu *mmu, */ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu) { - struct kgsl_iommu *iommu = mmu->priv; + struct kgsl_iommu *iommu = mmu->device->mmu.priv; int status = 0; - struct kgsl_pagetable *pagetable = NULL; - uint32_t lock_gpu_addr = 0; uint32_t lock_phy_addr = 0; uint32_t page_offset = 0; - if (!msm_soc_version_supports_iommu_v1() || - !kgsl_mmu_is_perprocess()) - return status; - - /* - * For 2D devices cpu side sync lock is required. For 3D device, - * since we only have a single 3D core and we always ensure that - * 3D core is idle while writing to IOMMU register using CPU this - * lock is not required - */ - if (KGSL_DEVICE_2D0 == mmu->device->id || - KGSL_DEVICE_2D1 == mmu->device->id) { + if (KGSL_DEVICE_3D0 != mmu->device->id || + !msm_soc_version_supports_iommu_v1() || + !kgsl_mmu_is_perprocess(mmu)) return status; - } /* Return if already initialized */ if (iommu->sync_lock_initialized) @@ -828,6 +947,7 @@ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu) page_offset = (lock_phy_addr & (PAGE_SIZE - 1)); lock_phy_addr = (lock_phy_addr & ~(PAGE_SIZE - 1)); iommu->sync_lock_desc.physaddr = (unsigned int)lock_phy_addr; + iommu->sync_lock_offset = page_offset; iommu->sync_lock_desc.size = PAGE_ALIGN(sizeof(kgsl_iommu_sync_lock_vars)); @@ -838,32 +958,6 @@ static int kgsl_iommu_init_sync_lock(struct kgsl_mmu *mmu) if (status) return status; - /* Map Lock variables to GPU pagetable */ - pagetable = mmu->priv_bank_table ? mmu->priv_bank_table : - mmu->defaultpagetable; - - status = kgsl_mmu_map_global(pagetable, &iommu->sync_lock_desc); - - if (status) { - kgsl_mmu_unmap(pagetable, &iommu->sync_lock_desc); - iommu->sync_lock_desc.priv &= ~KGSL_MEMDESC_GLOBAL; - return status; - } - - /* Store Lock variables GPU address */ - lock_gpu_addr = (iommu->sync_lock_desc.gpuaddr + page_offset); - - kgsl_iommu_sync_lock_vars.flag[PROC_APPS] = (lock_gpu_addr + - (offsetof(struct remote_iommu_petersons_spinlock, - flag[PROC_APPS]))); - kgsl_iommu_sync_lock_vars.flag[PROC_GPU] = (lock_gpu_addr + - (offsetof(struct remote_iommu_petersons_spinlock, - flag[PROC_GPU]))); - kgsl_iommu_sync_lock_vars.turn = (lock_gpu_addr + - (offsetof(struct remote_iommu_petersons_spinlock, turn))); - - iommu->sync_lock_vars = &kgsl_iommu_sync_lock_vars; - /* Flag Sync Lock is Initialized */ iommu->sync_lock_initialized = 1; @@ -1042,6 +1136,9 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu) iommu_unit->reg_map.size); if (ret) goto err; + + iommu_unit->iommu_halt_enable = data.iommu_halt_enable; + iommu_unit->ahb_base = data.physstart - mmu->device->reg_phys; } iommu->unit_count = pdata_dev->iommu_count; return ret; @@ -1065,28 +1162,24 @@ static int kgsl_set_register_map(struct kgsl_mmu *mmu) * Return - actual pagetable address that the ttbr0 register is programmed * with */ -static unsigned int kgsl_iommu_get_pt_base_addr(struct kgsl_mmu *mmu, +static phys_addr_t kgsl_iommu_get_pt_base_addr(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) { - struct kgsl_iommu *iommu = mmu->priv; struct kgsl_iommu_pt *iommu_pt = pt->priv; return iommu_get_pt_base_addr(iommu_pt->domain) & - (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); + KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; } /* - * kgsl_iommu_get_pt_lsb - Return the lsb of the ttbr0 IOMMU register + * kgsl_iommu_get_default_ttbr0 - Return the ttbr0 value programmed by + * iommu driver * @mmu - Pointer to mmu structure * @hostptr - Pointer to the IOMMU register map. This is used to match * the iommu device whose lsb value is to be returned * @ctx_id - The context bank whose lsb valus is to be returned - * Return - returns the lsb which is the last 14 bits of the ttbr0 IOMMU - * register. ttbr0 is the actual PTBR for of the IOMMU. The last 14 bits - * are only programmed once in the beginning when a domain is attached - * does not change. + * Return - returns the ttbr0 value programmed by iommu driver */ -static int kgsl_iommu_get_pt_lsb(struct kgsl_mmu *mmu, +static phys_addr_t kgsl_iommu_get_default_ttbr0(struct kgsl_mmu *mmu, unsigned int unit_id, enum kgsl_iommu_context_id ctx_id) { @@ -1097,7 +1190,7 @@ static int kgsl_iommu_get_pt_lsb(struct kgsl_mmu *mmu, for (j = 0; j < iommu_unit->dev_count; j++) if (unit_id == i && ctx_id == iommu_unit->dev[j].ctx_id) - return iommu_unit->dev[j].pt_lsb; + return iommu_unit->dev[j].default_ttbr0; } return 0; } @@ -1157,6 +1250,13 @@ static int kgsl_iommu_setup_regs(struct kgsl_mmu *mmu, goto err; } + /* Map Lock variables to GPU pagetable */ + if (iommu->sync_lock_initialized) { + status = kgsl_mmu_map_global(pt, &iommu->sync_lock_desc); + if (status) + goto err; + } + return 0; err: for (i--; i >= 0; i--) @@ -1182,9 +1282,36 @@ static void kgsl_iommu_cleanup_regs(struct kgsl_mmu *mmu, int i; for (i = 0; i < iommu->unit_count; i++) kgsl_mmu_unmap(pt, &(iommu->iommu_units[i].reg_map)); + + if (iommu->sync_lock_desc.gpuaddr) + kgsl_mmu_unmap(pt, &iommu->sync_lock_desc); } +/* + * kgsl_iommu_get_reg_ahbaddr - Returns the ahb address of the register + * @mmu - Pointer to mmu structure + * @iommu_unit - The iommu unit for which base address is requested + * @ctx_id - The context ID of the IOMMU ctx + * @reg - The register for which address is required + * + * Return - The address of register which can be used in type0 packet + */ +static unsigned int kgsl_iommu_get_reg_ahbaddr(struct kgsl_mmu *mmu, + int iommu_unit, int ctx_id, + enum kgsl_iommu_reg_map reg) +{ + struct kgsl_iommu *iommu = mmu->priv; + + if (iommu->iommu_reg_list[reg].ctx_reg) + return iommu->iommu_units[iommu_unit].ahb_base + + iommu->iommu_reg_list[reg].reg_offset + + (ctx_id << KGSL_IOMMU_CTX_SHIFT) + iommu->ctx_offset; + else + return iommu->iommu_units[iommu_unit].ahb_base + + iommu->iommu_reg_list[reg].reg_offset; +} + static int kgsl_iommu_init(struct kgsl_mmu *mmu) { /* @@ -1195,6 +1322,7 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu) int status = 0; struct kgsl_iommu *iommu; + atomic_set(&mmu->fault, 0); iommu = kzalloc(sizeof(struct kgsl_iommu), GFP_KERNEL); if (!iommu) { KGSL_CORE_ERR("kzalloc(%d) failed\n", @@ -1210,20 +1338,75 @@ static int kgsl_iommu_init(struct kgsl_mmu *mmu) if (status) goto done; - iommu->iommu_reg_list = kgsl_iommuv1_reg; - iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V1; + /* + * IOMMU-v1 requires hardware halt support to do in stream + * pagetable switching. This check assumes that if there are + * multiple units, they will be matching hardware. + */ + /* name mismatch fixup between v0 and v1 here */ + mmu->pt_per_process = KGSL_MMU_USE_PER_PROCESS_PT && + (msm_soc_version_supports_iommu_v1() || + iommu->iommu_units[0].iommu_halt_enable); + + /* + * For IOMMU per-process pagetables, the allocatable range + * and the kernel global range must both be outside + * the userspace address range. There is a 1Mb gap + * between these address ranges to make overrun + * detection easier. + * For the shared pagetable case use 2GB and because + * mirroring the CPU address space is not possible and + * we're better off with extra room. + */ + if (mmu->pt_per_process) { +#ifndef CONFIG_MSM_KGSL_CFF_DUMP + mmu->pt_base = PAGE_OFFSET; + mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE + - kgsl_mmu_get_base_addr(mmu) - SZ_1M; + mmu->use_cpu_map = true; +#else + mmu->pt_base = KGSL_PAGETABLE_BASE; + mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE + + KGSL_IOMMU_GLOBAL_MEM_SIZE - + KGSL_PAGETABLE_BASE; + mmu->use_cpu_map = false; +#endif + } else { + mmu->pt_base = KGSL_PAGETABLE_BASE; +#ifndef CONFIG_MSM_KGSL_CFF_DUMP + mmu->pt_size = SZ_2G; +#else + mmu->pt_size = KGSL_IOMMU_GLOBAL_MEM_BASE + + KGSL_IOMMU_GLOBAL_MEM_SIZE - + KGSL_PAGETABLE_BASE; +#endif + mmu->use_cpu_map = false; + } + + status = kgsl_iommu_init_sync_lock(mmu); + if (status) + goto done; + + iommu->iommu_reg_list = kgsl_iommuv0_reg; + iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V0; + /* + * Due to not bringing in the iommu rename, iommu_v1 is + * actually iommu_v0. Keep our internal representation + * constant, but our interface with iommu drive needs the + * correct vixes + */ if (msm_soc_version_supports_iommu_v1()) { + iommu->iommu_reg_list = kgsl_iommuv0_reg; + iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V0; + } else { iommu->iommu_reg_list = kgsl_iommuv1_reg; iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V1; - } else { - iommu->iommu_reg_list = kgsl_iommuv2_reg; - iommu->ctx_offset = KGSL_IOMMU_CTX_OFFSET_V2; } /* A nop is required in an indirect buffer when switching * pagetables in-stream */ - kgsl_sharedmem_writel(&mmu->setstate_memory, + kgsl_sharedmem_writel(mmu->device, &mmu->setstate_memory, KGSL_IOMMU_SETSTATE_NOP_OFFSET, cp_nop_packet(1)); @@ -1272,7 +1455,8 @@ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu) * switching on the 3D side for which a separate table is allocated */ if (!cpu_is_msm8960() && msm_soc_version_supports_iommu_v1()) { mmu->priv_bank_table = - kgsl_mmu_getpagetable(KGSL_MMU_PRIV_BANK_TABLE_NAME); + kgsl_mmu_getpagetable(mmu, + KGSL_MMU_PRIV_BANK_TABLE_NAME); if (mmu->priv_bank_table == NULL) { status = -ENOMEM; goto err; @@ -1281,7 +1465,7 @@ static int kgsl_iommu_setup_defaultpagetable(struct kgsl_mmu *mmu) if (status) goto err; } - mmu->defaultpagetable = kgsl_mmu_getpagetable(KGSL_MMU_GLOBAL_PT); + mmu->defaultpagetable = kgsl_mmu_getpagetable(mmu, KGSL_MMU_GLOBAL_PT); /* Return error if the default pagetable doesn't exist */ if (mmu->defaultpagetable == NULL) { status = -ENOMEM; @@ -1413,6 +1597,8 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu) int status; struct kgsl_iommu *iommu = mmu->priv; int i, j; + int sctlr_val = 0; + struct adreno_device *adreno_dev = ADRENO_DEVICE(mmu->device); if (mmu->flags & KGSL_FLAGS_STARTED) return 0; @@ -1427,6 +1613,9 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu) (device->id == KGSL_DEVICE_3D0)) kgsl_iommu_init_sync_lock(mmu); } + status = kgsl_iommu_start_sync_lock(mmu); + if (status) + return status; /* We use the GPU MMU to control access to IOMMU registers on 8960 with * a225, hence we still keep the MMU active on 8960 */ @@ -1466,18 +1655,45 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu) for (i = 0; i < iommu->unit_count; i++) { struct kgsl_iommu_unit *iommu_unit = &iommu->iommu_units[i]; for (j = 0; j < iommu_unit->dev_count; j++) { - iommu_unit->dev[j].pt_lsb = KGSL_IOMMMU_PT_LSB(iommu, + + /* + * For IOMMU V1 do not halt IOMMU on pagefault if + * FT pagefault policy is set accordingly + */ + if ((!msm_soc_version_supports_iommu_v1()) && + (!(adreno_dev->ft_pf_policy & + KGSL_FT_PAGEFAULT_GPUHALT_ENABLE))) { + sctlr_val = KGSL_IOMMU_GET_CTX_REG(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + SCTLR); + sctlr_val |= (0x1 << + KGSL_IOMMU_SCTLR_HUPCF_SHIFT); + KGSL_IOMMU_SET_CTX_REG(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + SCTLR, sctlr_val); + } + if (sizeof(phys_addr_t) > sizeof(unsigned long)) { + iommu_unit->dev[j].default_ttbr0 = + KGSL_IOMMU_GET_CTX_REG_LL(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + TTBR0); + } else { + iommu_unit->dev[j].default_ttbr0 = KGSL_IOMMU_GET_CTX_REG(iommu, iommu_unit, iommu_unit->dev[j].ctx_id, - TTBR0)); + TTBR0); + } } } kgsl_iommu_lock_rb_in_tlb(mmu); msm_iommu_unlock(); /* For complete CFF */ - kgsl_cffdump_setmem(mmu->setstate_memory.gpuaddr + + kgsl_cffdump_setmem(mmu->device, mmu->setstate_memory.gpuaddr + KGSL_IOMMU_SETSTATE_NOP_OFFSET, cp_nop_packet(1), sizeof(unsigned int)); @@ -1493,13 +1709,13 @@ static int kgsl_iommu_start(struct kgsl_mmu *mmu) } static int -kgsl_iommu_unmap(void *mmu_specific_pt, +kgsl_iommu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags) { int ret; unsigned int range = memdesc->size; - struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; + struct kgsl_iommu_pt *iommu_pt = pt->priv; /* All GPU addresses as assigned are page aligned, but some functions purturb the gpuaddr with an offset, so apply the @@ -1523,20 +1739,20 @@ kgsl_iommu_unmap(void *mmu_specific_pt, * Flushing only required if per process pagetables are used. With * global case, flushing will happen inside iommu_map function */ - if (!ret && kgsl_mmu_is_perprocess()) + if (!ret && kgsl_mmu_is_perprocess(pt->mmu)) *tlb_flags = UINT_MAX; return 0; } static int -kgsl_iommu_map(void *mmu_specific_pt, +kgsl_iommu_map(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int protflags, unsigned int *tlb_flags) { int ret; unsigned int iommu_virt_addr; - struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; + struct kgsl_iommu_pt *iommu_pt = pt->priv; int size = memdesc->size; BUG_ON(NULL == iommu_pt); @@ -1569,10 +1785,40 @@ kgsl_iommu_map(void *mmu_specific_pt, return ret; } -static void kgsl_iommu_stop(struct kgsl_mmu *mmu) +void kgsl_iommu_pagefault_resume(struct kgsl_mmu *mmu) { struct kgsl_iommu *iommu = mmu->priv; int i, j; + + if (atomic_read(&mmu->fault)) { + for (i = 0; i < iommu->unit_count; i++) { + struct kgsl_iommu_unit *iommu_unit = + &iommu->iommu_units[i]; + for (j = 0; j < iommu_unit->dev_count; j++) { + if (iommu_unit->dev[j].fault) { + kgsl_iommu_enable_clk(mmu, j); + _iommu_lock(); + KGSL_IOMMU_SET_CTX_REG(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + RESUME, 1); + KGSL_IOMMU_SET_CTX_REG(iommu, + iommu_unit, + iommu_unit->dev[j].ctx_id, + FSR, 0); + _iommu_unlock(); + iommu_unit->dev[j].fault = 0; + } + } + } + atomic_set(&mmu->fault, 0); + } +} + + +static void kgsl_iommu_stop(struct kgsl_mmu *mmu) +{ + struct kgsl_iommu *iommu = mmu->priv; /* * stop device mmu * @@ -1585,25 +1831,7 @@ static void kgsl_iommu_stop(struct kgsl_mmu *mmu) mmu->flags &= ~KGSL_FLAGS_STARTED; - if (mmu->fault) { - for (i = 0; i < iommu->unit_count; i++) { - struct kgsl_iommu_unit *iommu_unit = - &iommu->iommu_units[i]; - for (j = 0; j < iommu_unit->dev_count; j++) { - if (iommu_unit->dev[j].fault) { - kgsl_iommu_enable_clk(mmu, j); - msm_iommu_lock(); - KGSL_IOMMU_SET_CTX_REG(iommu, - iommu_unit, - iommu_unit->dev[j].ctx_id, - RESUME, 1); - msm_iommu_unlock(); - iommu_unit->dev[j].fault = 0; - } - } - } - mmu->fault = 0; - } + kgsl_iommu_pagefault_resume(mmu); } /* switch off MMU clocks and cancel any events it has queued */ iommu->clk_event_queued = false; @@ -1630,7 +1858,12 @@ static int kgsl_iommu_close(struct kgsl_mmu *mmu) if (reg_map->hostptr) iounmap(reg_map->hostptr); kgsl_sg_free(reg_map->sg, reg_map->sglen); + reg_map->priv &= ~KGSL_MEMDESC_GLOBAL; } + /* clear IOMMU GPU CPU sync structures */ + kgsl_sg_free(iommu->sync_lock_desc.sg, iommu->sync_lock_desc.sglen); + memset(&iommu->sync_lock_desc, 0, sizeof(iommu->sync_lock_desc)); + iommu->sync_lock_vars = NULL; kfree(iommu); @@ -1642,10 +1875,10 @@ static int kgsl_iommu_close(struct kgsl_mmu *mmu) return 0; } -static unsigned int +static phys_addr_t kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu) { - unsigned int pt_base; + phys_addr_t pt_base; struct kgsl_iommu *iommu = mmu->priv; /* We cannot enable or disable the clocks in interrupt context, this function is called from interrupt context if there is an axi error */ @@ -1657,9 +1890,7 @@ kgsl_iommu_get_current_ptbase(struct kgsl_mmu *mmu) KGSL_IOMMU_CONTEXT_USER, TTBR0); kgsl_iommu_disable_clk_on_ts(mmu, 0, false); - return pt_base & - (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); + return pt_base & KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; } /* @@ -1683,7 +1914,7 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, int ret = 0; unsigned int pt_base = kgsl_iommu_get_pt_base_addr(mmu, mmu->hwpagetable); - unsigned int pt_val; + phys_addr_t pt_val; ret = kgsl_iommu_enable_clk(mmu, KGSL_IOMMU_CONTEXT_USER); @@ -1691,26 +1922,43 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, KGSL_DRV_ERR(mmu->device, "Failed to enable iommu clocks\n"); return ret; } - /* Mask off the lsb of the pt base address since lsb will not change */ - pt_base &= (iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift); - //if (msm_soc_version_supports_iommu_v1()) + /* For v0 SMMU GPU needs to be idle for tlb invalidate as well */ + /* naming mismatch for iommu */ + if (msm_soc_version_supports_iommu_v1()) { + ret = kgsl_idle(mmu->device); + if (ret) + return ret; + } + /* Acquire GPU-CPU sync Lock here */ msm_iommu_lock(); if (flags & KGSL_MMUFLAGS_PTUPDATE) { - if (!msm_soc_version_supports_iommu_v1()) - kgsl_idle(mmu->device); + /* naming mismatch for iommu */ + if (!msm_soc_version_supports_iommu_v1()) { + ret = kgsl_idle(mmu->device); + if (ret) + goto unlock; + } for (i = 0; i < iommu->unit_count; i++) { /* get the lsb value which should not change when * changing ttbr0 */ - pt_val = kgsl_iommu_get_pt_lsb(mmu, i, + pt_val = kgsl_iommu_get_default_ttbr0(mmu, i, KGSL_IOMMU_CONTEXT_USER); - pt_val += pt_base; - KGSL_IOMMU_SET_CTX_REG(iommu, (&iommu->iommu_units[i]), - KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val); + pt_base &= KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + pt_val &= ~KGSL_IOMMU_CTX_TTBR0_ADDR_MASK; + pt_val |= pt_base; + if (sizeof(phys_addr_t) > sizeof(unsigned long)) { + KGSL_IOMMU_SET_CTX_REG_LL(iommu, + (&iommu->iommu_units[i]), + KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val); + } else { + KGSL_IOMMU_SET_CTX_REG(iommu, + (&iommu->iommu_units[i]), + KGSL_IOMMU_CONTEXT_USER, TTBR0, pt_val); + } mb(); temp = KGSL_IOMMU_GET_CTX_REG(iommu, @@ -1720,12 +1968,41 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, } /* Flush tlb */ if (flags & KGSL_MMUFLAGS_TLBFLUSH) { + unsigned long wait_for_flush; for (i = 0; i < iommu->unit_count; i++) { KGSL_IOMMU_SET_CTX_REG(iommu, (&iommu->iommu_units[i]), KGSL_IOMMU_CONTEXT_USER, TLBIALL, 1); mb(); + /* + * Wait for flush to complete by polling the flush + * status bit of TLBSTATUS register for not more than + * 2 s. After 2s just exit, at that point the SMMU h/w + * may be stuck and will eventually cause GPU to hang + * or bring the system down. + */ + /* naming mismatch */ + if (!msm_soc_version_supports_iommu_v1()) { + wait_for_flush = jiffies + + msecs_to_jiffies(2000); + KGSL_IOMMU_SET_CTX_REG(iommu, + (&iommu->iommu_units[i]), + KGSL_IOMMU_CONTEXT_USER, TLBSYNC, 0); + while (KGSL_IOMMU_GET_CTX_REG(iommu, + (&iommu->iommu_units[i]), + KGSL_IOMMU_CONTEXT_USER, TLBSTATUS) & + (KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE)) { + if (time_after(jiffies, + wait_for_flush)) { + KGSL_DRV_ERR(mmu->device, + "Wait limit reached for IOMMU tlb flush\n"); + break; + } + cpu_relax(); + } + } } } +unlock: /* Release GPU-CPU sync Lock here */ msm_iommu_unlock(); @@ -1742,8 +2019,7 @@ static int kgsl_iommu_default_setstate(struct kgsl_mmu *mmu, * @ctx_id - The context ID of the IOMMU ctx * @reg - The register for which address is required * - * Return - The number of iommu units which is also the number of register - * mapped descriptor arrays which the out parameter will have + * Return - The gpu address of register which can be used in type3 packet */ static unsigned int kgsl_iommu_get_reg_gpuaddr(struct kgsl_mmu *mmu, int iommu_unit, int ctx_id, int reg) @@ -1752,10 +2028,25 @@ static unsigned int kgsl_iommu_get_reg_gpuaddr(struct kgsl_mmu *mmu, if (KGSL_IOMMU_GLOBAL_BASE == reg) return iommu->iommu_units[iommu_unit].reg_map.gpuaddr; - else + + if (iommu->iommu_reg_list[reg].ctx_reg) return iommu->iommu_units[iommu_unit].reg_map.gpuaddr + iommu->iommu_reg_list[reg].reg_offset + (ctx_id << KGSL_IOMMU_CTX_SHIFT) + iommu->ctx_offset; + else + return iommu->iommu_units[iommu_unit].reg_map.gpuaddr + + iommu->iommu_reg_list[reg].reg_offset; +} +/* + * kgsl_iommu_hw_halt_supported - Returns whether IOMMU halt command is + * supported + * @mmu - Pointer to mmu structure + * @iommu_unit - The iommu unit for which the property is requested + */ +static int kgsl_iommu_hw_halt_supported(struct kgsl_mmu *mmu, int iommu_unit) +{ + struct kgsl_iommu *iommu = mmu->priv; + return iommu->iommu_units[iommu_unit].iommu_halt_enable; } static int kgsl_iommu_get_num_iommu_units(struct kgsl_mmu *mmu) @@ -1772,20 +2063,23 @@ struct kgsl_mmu_ops iommu_ops = { .mmu_setstate = kgsl_iommu_setstate, .mmu_device_setstate = kgsl_iommu_default_setstate, .mmu_pagefault = NULL, + .mmu_pagefault_resume = kgsl_iommu_pagefault_resume, .mmu_get_current_ptbase = kgsl_iommu_get_current_ptbase, .mmu_enable_clk = kgsl_iommu_enable_clk, .mmu_disable_clk = kgsl_iommu_disable_clk, .mmu_disable_clk_on_ts = kgsl_iommu_disable_clk_on_ts, - .mmu_get_pt_lsb = kgsl_iommu_get_pt_lsb, + .mmu_get_default_ttbr0 = kgsl_iommu_get_default_ttbr0, .mmu_get_reg_gpuaddr = kgsl_iommu_get_reg_gpuaddr, + .mmu_get_reg_ahbaddr = kgsl_iommu_get_reg_ahbaddr, .mmu_get_num_iommu_units = kgsl_iommu_get_num_iommu_units, .mmu_pt_equal = kgsl_iommu_pt_equal, .mmu_get_pt_base_addr = kgsl_iommu_get_pt_base_addr, - .mmu_sync_lock = kgsl_iommu_sync_lock, - .mmu_sync_unlock = kgsl_iommu_sync_unlock, + .mmu_hw_halt_supported = kgsl_iommu_hw_halt_supported, /* These callbacks will be set on some chipsets */ .mmu_setup_pt = NULL, .mmu_cleanup_pt = NULL, + .mmu_sync_lock = kgsl_iommu_sync_lock, + .mmu_sync_unlock = kgsl_iommu_sync_unlock, }; struct kgsl_mmu_pt_ops iommu_pt_ops = { diff --git a/drivers/gpu/msm/kgsl_iommu.h b/drivers/gpu/msm/kgsl_iommu.h index 2d681fcaacf..7dca40e2c98 100644 --- a/drivers/gpu/msm/kgsl_iommu.h +++ b/drivers/gpu/msm/kgsl_iommu.h @@ -15,8 +15,8 @@ #include -#define KGSL_IOMMU_CTX_OFFSET_V1 0 -#define KGSL_IOMMU_CTX_OFFSET_V2 0x8000 +#define KGSL_IOMMU_CTX_OFFSET_V0 0 +#define KGSL_IOMMU_CTX_OFFSET_V1 0x8000 #define KGSL_IOMMU_CTX_SHIFT 12 /* TLBLKCR fields */ @@ -46,8 +46,27 @@ #define KGSL_IOMMU_V1_FSYNR0_WNR_MASK 0x00000001 #define KGSL_IOMMU_V1_FSYNR0_WNR_SHIFT 4 +/* TTBR0 register fields */ +#ifdef CONFIG_ARM_LPAE +#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK_LPAE 0x000000FFFFFFFFE0ULL +#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK KGSL_IOMMU_CTX_TTBR0_ADDR_MASK_LPAE +#else +#define KGSL_IOMMU_CTX_TTBR0_ADDR_MASK 0xFFFFC000 +#endif + +/* TLBSTATUS register fields */ +#define KGSL_IOMMU_CTX_TLBSTATUS_SACTIVE BIT(0) + +/* IMPLDEF_MICRO_MMU_CTRL register fields */ +#define KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_HALT BIT(2) +#define KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL_IDLE BIT(3) + +/* SCTLR fields */ +#define KGSL_IOMMU_SCTLR_HUPCF_SHIFT 8 + enum kgsl_iommu_reg_map { KGSL_IOMMU_GLOBAL_BASE = 0, + KGSL_IOMMU_CTX_SCTLR, KGSL_IOMMU_CTX_TTBR0, KGSL_IOMMU_CTX_TTBR1, KGSL_IOMMU_CTX_FSR, @@ -57,13 +76,15 @@ enum kgsl_iommu_reg_map { KGSL_IOMMU_CTX_V2PUR, KGSL_IOMMU_CTX_FSYNR0, KGSL_IOMMU_CTX_FSYNR1, + KGSL_IOMMU_CTX_TLBSYNC, + KGSL_IOMMU_CTX_TLBSTATUS, + KGSL_IOMMU_IMPLDEF_MICRO_MMU_CTRL, KGSL_IOMMU_REG_MAX }; struct kgsl_iommu_register_list { unsigned int reg_offset; - unsigned int reg_mask; - unsigned int reg_shift; + int ctx_reg; }; /* @@ -76,6 +97,20 @@ struct kgsl_iommu_register_list { #define KGSL_IOMMU_MAX_DEVS_PER_UNIT 2 /* Macros to read/write IOMMU registers */ +#define KGSL_IOMMU_SET_CTX_REG_LL(iommu, iommu_unit, ctx, REG, val) \ + writell_relaxed(val, \ + iommu_unit->reg_map.hostptr + \ + iommu->iommu_reg_list[KGSL_IOMMU_CTX_##REG].reg_offset +\ + (ctx << KGSL_IOMMU_CTX_SHIFT) + \ + iommu->ctx_offset) + +#define KGSL_IOMMU_GET_CTX_REG_LL(iommu, iommu_unit, ctx, REG) \ + readl_relaxed( \ + iommu_unit->reg_map.hostptr + \ + iommu->iommu_reg_list[KGSL_IOMMU_CTX_##REG].reg_offset +\ + (ctx << KGSL_IOMMU_CTX_SHIFT) + \ + iommu->ctx_offset) + #define KGSL_IOMMU_SET_CTX_REG(iommu, iommu_unit, ctx, REG, val) \ writel_relaxed(val, \ iommu_unit->reg_map.hostptr + \ @@ -91,10 +126,8 @@ struct kgsl_iommu_register_list { iommu->ctx_offset) /* Gets the lsb value of pagetable */ -#define KGSL_IOMMMU_PT_LSB(iommu, pt_val) \ - (pt_val & \ - ~(iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_mask << \ - iommu->iommu_reg_list[KGSL_IOMMU_CTX_TTBR0].reg_shift)) +#define KGSL_IOMMMU_PT_LSB(iommu, pt_val) \ + (pt_val & ~(KGSL_IOMMU_CTX_TTBR0_ADDR_MASK)) /* offset at which a nop command is placed in setstate_memory */ #define KGSL_IOMMU_SETSTATE_NOP_OFFSET 1024 @@ -104,8 +137,7 @@ struct kgsl_iommu_register_list { * @dev: Device pointer to iommu context * @attached: Indicates whether this iommu context is presently attached to * a pagetable/domain or not - * @pt_lsb: The LSB of IOMMU_TTBR0 register which is the pagetable - * register + * @default_ttbr0: The TTBR0 value set by iommu driver on start up * @ctx_id: This iommu units context id. It can be either 0 or 1 * @clk_enabled: If set indicates that iommu clocks of this iommu context * are on, else the clocks are off @@ -115,7 +147,7 @@ struct kgsl_iommu_register_list { struct kgsl_iommu_device { struct device *dev; bool attached; - unsigned int pt_lsb; + phys_addr_t default_ttbr0; enum kgsl_iommu_context_id ctx_id; bool clk_enabled; struct kgsl_device *kgsldev; @@ -130,11 +162,18 @@ struct kgsl_iommu_device { * @dev_count: Number of IOMMU contexts that are valid in the previous feild * @reg_map: Memory descriptor which holds the mapped address of this IOMMU * units register range + * @ahb_base - The base address from where IOMMU registers can be accesed from + * ahb bus + * @iommu_halt_enable: Valid only on IOMMU-v1, when set indicates that the iommu + * unit supports halting of the IOMMU, which can be enabled while programming + * the IOMMU registers for synchronization */ struct kgsl_iommu_unit { struct kgsl_iommu_device dev[KGSL_IOMMU_MAX_DEVS_PER_UNIT]; unsigned int dev_count; struct kgsl_memdesc reg_map; + unsigned int ahb_base; + int iommu_halt_enable; }; /* @@ -155,6 +194,8 @@ struct kgsl_iommu_unit { * IOMMU registers * @sync_lock_desc: GPU Memory descriptor for the memory containing the * spinlocks + * @sync_lock_offset - The page offset within a page at which the sync + * variables are located * @sync_lock_initialized: True if the sync_lock feature is enabled */ struct kgsl_iommu { @@ -167,6 +208,7 @@ struct kgsl_iommu { struct kgsl_iommu_register_list *iommu_reg_list; struct remote_iommu_petersons_spinlock *sync_lock_vars; struct kgsl_memdesc sync_lock_desc; + unsigned int sync_lock_offset; bool sync_lock_initialized; }; diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c index ea127d266e1..1910a46e995 100644 --- a/drivers/gpu/msm/kgsl_mmu.c +++ b/drivers/gpu/msm/kgsl_mmu.c @@ -23,6 +23,7 @@ #include "kgsl.h" #include "kgsl_mmu.h" +#include "kgsl_gpummu.h" #include "kgsl_device.h" #include "kgsl_sharedmem.h" #include "adreno.h" @@ -68,8 +69,10 @@ static int kgsl_setup_pt(struct kgsl_pagetable *pt) device = kgsl_driver.devp[KGSL_DEVICE_3D0]; if (device->mmu.mmu_ops->mmu_setup_pt != NULL) { status = device->mmu.mmu_ops->mmu_setup_pt(&device->mmu, pt); - if (status) + if (status) { + i = KGSL_DEVICE_MAX - 1; goto error_pt; + } } return status; error_pt: @@ -101,7 +104,7 @@ static void kgsl_destroy_pagetable(struct kref *kref) if (pagetable->pool) gen_pool_destroy(pagetable->pool); - pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv); + pagetable->pt_ops->mmu_destroy_pagetable(pagetable); kfree(pagetable); } @@ -120,10 +123,12 @@ kgsl_get_pagetable(unsigned long name) spin_lock_irqsave(&kgsl_driver.ptlock, flags); list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) { - if (pt->name == name) { - ret = pt; - kref_get(&ret->refcount); - break; + if (kref_get_unless_zero(&pt->refcount)) { + if (pt->name == name) { + ret = pt; + break; + } + kref_put(&pt->refcount, kgsl_destroy_pagetable); } } @@ -191,7 +196,7 @@ sysfs_show_va_range(struct kobject *kobj, if (pt) { ret += snprintf(buf, PAGE_SIZE, "0x%x\n", - kgsl_mmu_get_ptsize()); + kgsl_mmu_get_ptsize(pt->mmu)); } kgsl_put_pagetable(pt); @@ -311,7 +316,7 @@ pagetable_add_sysfs_objects(struct kgsl_pagetable *pagetable) } int -kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base) +kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, phys_addr_t pt_base) { struct kgsl_pagetable *pt; int ptid = -1; @@ -320,9 +325,13 @@ kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base) return KGSL_MMU_GLOBAL_PT; spin_lock(&kgsl_driver.ptlock); list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) { - if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) { - ptid = (int) pt->name; - break; + if (kref_get_unless_zero(&pt->refcount)) { + if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) { + ptid = (int) pt->name; + kref_put(&pt->refcount, kgsl_destroy_pagetable); + break; + } + kref_put(&pt->refcount, kgsl_destroy_pagetable); } } spin_unlock(&kgsl_driver.ptlock); @@ -332,7 +341,7 @@ kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, unsigned int pt_base) EXPORT_SYMBOL(kgsl_mmu_get_ptname_from_ptbase); unsigned int -kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, unsigned int pt_base, +kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, phys_addr_t pt_base, unsigned int addr) { struct kgsl_pagetable *pt; @@ -342,16 +351,23 @@ kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, unsigned int pt_base, return KGSL_MMU_GLOBAL_PT; spin_lock(&kgsl_driver.ptlock); list_for_each_entry(pt, &kgsl_driver.pagetable_list, list) { - if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) { - if ((addr & (PAGE_SIZE-1)) == pt->fault_addr) { - ret = 1; - break; - } else { - pt->fault_addr = (addr & (PAGE_SIZE-1)); - ret = 0; - break; + if (kref_get_unless_zero(&pt->refcount)) { + if (mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base)) { + if ((addr & ~(PAGE_SIZE-1)) == pt->fault_addr) { + ret = 1; + kref_put(&pt->refcount, + kgsl_destroy_pagetable); + break; + } else { + pt->fault_addr = + (addr & ~(PAGE_SIZE-1)); + ret = 0; + kref_put(&pt->refcount, + kgsl_destroy_pagetable); + break; + } } - + kref_put(&pt->refcount, kgsl_destroy_pagetable); } } spin_unlock(&kgsl_driver.ptlock); @@ -369,7 +385,7 @@ int kgsl_mmu_init(struct kgsl_device *device) status = kgsl_allocate_contiguous(&mmu->setstate_memory, PAGE_SIZE); if (status) return status; - kgsl_sharedmem_set(&mmu->setstate_memory, 0, 0, + kgsl_sharedmem_set(device, &mmu->setstate_memory, 0, 0, mmu->setstate_memory.size); if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) { @@ -407,7 +423,8 @@ EXPORT_SYMBOL(kgsl_mmu_start); static void mh_axi_error(struct kgsl_device *device, const char* type) { - unsigned int reg, gpu_err, phys_err, pt_base; + unsigned int reg, gpu_err, phys_err; + phys_addr_t pt_base; kgsl_regread(device, MH_AXI_ERROR, ®); pt_base = kgsl_mmu_get_current_ptbase(&device->mmu); @@ -420,8 +437,8 @@ static void mh_axi_error(struct kgsl_device *device, const char* type) kgsl_regwrite(device, MH_DEBUG_CTRL, 45); kgsl_regread(device, MH_DEBUG_DATA, &phys_err); KGSL_MEM_CRIT(device, - "axi %s error: %08x pt %08x gpu %08x phys %08x\n", - type, reg, pt_base, gpu_err, phys_err); + "axi %s error: %08x pt %pa gpu %08x phys %08x\n", + type, reg, &pt_base, gpu_err, phys_err); } void kgsl_mh_intrcallback(struct kgsl_device *device) @@ -442,7 +459,8 @@ void kgsl_mh_intrcallback(struct kgsl_device *device) } EXPORT_SYMBOL(kgsl_mh_intrcallback); -static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( +static struct kgsl_pagetable * +kgsl_mmu_createpagetableobject(struct kgsl_mmu *mmu, unsigned int name) { int status = 0; @@ -461,8 +479,8 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( spin_lock_init(&pagetable->lock); - ptsize = kgsl_mmu_get_ptsize(); - + ptsize = kgsl_mmu_get_ptsize(mmu); + pagetable->mmu = mmu; pagetable->name = name; pagetable->max_entries = KGSL_PAGETABLE_ENTRIES(ptsize); pagetable->fault_addr = 0xFFFFFFFF; @@ -495,7 +513,7 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( goto err_kgsl_pool; } - if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(), + if (gen_pool_add(pagetable->pool, kgsl_mmu_get_base_addr(mmu), ptsize, -1)) { KGSL_CORE_ERR("gen_pool_add failed\n"); goto err_pool; @@ -524,7 +542,7 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( return pagetable; err_mmu_create: - pagetable->pt_ops->mmu_destroy_pagetable(pagetable->priv); + pagetable->pt_ops->mmu_destroy_pagetable(pagetable); err_pool: gen_pool_destroy(pagetable->pool); err_kgsl_pool: @@ -536,20 +554,21 @@ static struct kgsl_pagetable *kgsl_mmu_createpagetableobject( return NULL; } -struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name) +struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *mmu, + unsigned long name) { struct kgsl_pagetable *pt; if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) return (void *)(-1); - if (!kgsl_mmu_is_perprocess()) + if (!kgsl_mmu_is_perprocess(mmu)) name = KGSL_MMU_GLOBAL_PT; pt = kgsl_get_pagetable(name); if (pt == NULL) - pt = kgsl_mmu_createpagetableobject(name); + pt = kgsl_mmu_createpagetableobject(mmu, name); return pt; } @@ -608,15 +627,20 @@ void kgsl_mh_start(struct kgsl_device *device) } EXPORT_SYMBOL(kgsl_mh_start); +/** + * kgsl_mmu_get_gpuaddr - Assign a memdesc with a gpuadddr from the gen pool + * @pagetable - pagetable whose pool is to be used + * @memdesc - memdesc to which gpuaddr is assigned + * + * returns - 0 on success else error code + */ int -kgsl_mmu_map(struct kgsl_pagetable *pagetable, - struct kgsl_memdesc *memdesc) +kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc) { - int ret; struct gen_pool *pool = NULL; int size; int page_align = ilog2(PAGE_SIZE); - unsigned int protflags = kgsl_memdesc_protflags(memdesc); if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) { if (memdesc->sglen == 1) { @@ -688,16 +712,38 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable, return -ENOMEM; } } + return 0; +} +EXPORT_SYMBOL(kgsl_mmu_get_gpuaddr); + +int +kgsl_mmu_map(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc) +{ + int ret = 0; + int size; + unsigned int protflags = kgsl_memdesc_protflags(memdesc); + + if (!memdesc->gpuaddr) + return -EINVAL; + /* Only global mappings should be mapped multiple times */ + if (!kgsl_memdesc_is_global(memdesc) && + (KGSL_MEMDESC_MAPPED & memdesc->priv)) + return -EINVAL; + /* Add space for the guard page when allocating the mmu VA. */ + size = memdesc->size; + if (kgsl_memdesc_has_guard_page(memdesc)) + size += PAGE_SIZE; if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype()) spin_lock(&pagetable->lock); - ret = pagetable->pt_ops->mmu_map(pagetable->priv, memdesc, protflags, + ret = pagetable->pt_ops->mmu_map(pagetable, memdesc, protflags, &pagetable->tlb_flags); if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) spin_lock(&pagetable->lock); if (ret) - goto err_free_gpuaddr; + goto done; /* Keep track of the statistics for the sysfs files */ @@ -708,34 +754,76 @@ kgsl_mmu_map(struct kgsl_pagetable *pagetable, pagetable->stats.max_mapped); spin_unlock(&pagetable->lock); + memdesc->priv |= KGSL_MEMDESC_MAPPED; return 0; -err_free_gpuaddr: +done: spin_unlock(&pagetable->lock); - if (pool) - gen_pool_free(pool, memdesc->gpuaddr, size); - memdesc->gpuaddr = 0; return ret; } EXPORT_SYMBOL(kgsl_mmu_map); +/** + * kgsl_mmu_put_gpuaddr - Free a gpuaddress from memory pool + * @pagetable - pagetable whose pool memory is freed from + * @memdesc - memdesc whose gpuaddress is freed + * + * returns - 0 on success else error code + */ int -kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, - struct kgsl_memdesc *memdesc) +kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc) { struct gen_pool *pool; int size; - unsigned int start_addr = 0; - unsigned int end_addr = 0; if (memdesc->size == 0 || memdesc->gpuaddr == 0) return 0; - if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) { + if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) + goto done; + + /* Add space for the guard page when freeing the mmu VA. */ + size = memdesc->size; + if (kgsl_memdesc_has_guard_page(memdesc)) + size += PAGE_SIZE; + + pool = pagetable->pool; + + if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) { + if (kgsl_memdesc_is_global(memdesc)) + pool = pagetable->kgsl_pool; + else if (kgsl_memdesc_use_cpu_map(memdesc)) + pool = NULL; + } + if (pool) + gen_pool_free(pool, memdesc->gpuaddr, size); + /* + * Don't clear the gpuaddr on global mappings because they + * may be in use by other pagetables + */ +done: + if (!kgsl_memdesc_is_global(memdesc)) memdesc->gpuaddr = 0; + return 0; +} +EXPORT_SYMBOL(kgsl_mmu_put_gpuaddr); + +int +kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc) +{ + int size; + unsigned int start_addr = 0; + unsigned int end_addr = 0; + + if (memdesc->size == 0 || memdesc->gpuaddr == 0 || + !(KGSL_MEMDESC_MAPPED & memdesc->priv)) + return -EINVAL; + + if (kgsl_mmu_type == KGSL_MMU_TYPE_NONE) return 0; - } /* Add space for the guard page when freeing the mmu VA. */ size = memdesc->size; @@ -747,7 +835,7 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, if (KGSL_MMU_TYPE_IOMMU != kgsl_mmu_get_mmutype()) spin_lock(&pagetable->lock); - pagetable->pt_ops->mmu_unmap(pagetable->priv, memdesc, + pagetable->pt_ops->mmu_unmap(pagetable, memdesc, &pagetable->tlb_flags); /* If buffer is unmapped 0 fault addr */ @@ -762,24 +850,8 @@ kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, pagetable->stats.mapped -= size; spin_unlock(&pagetable->lock); - - pool = pagetable->pool; - - if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_get_mmutype()) { - if (kgsl_memdesc_is_global(memdesc)) - pool = pagetable->kgsl_pool; - else if (kgsl_memdesc_use_cpu_map(memdesc)) - pool = NULL; - } - if (pool) - gen_pool_free(pool, memdesc->gpuaddr, size); - - /* - * Don't clear the gpuaddr on global mappings because they - * may be in use by other pagetables - */ if (!kgsl_memdesc_is_global(memdesc)) - memdesc->gpuaddr = 0; + memdesc->priv &= ~KGSL_MEMDESC_MAPPED; return 0; } EXPORT_SYMBOL(kgsl_mmu_unmap); @@ -800,20 +872,24 @@ int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable, gpuaddr = memdesc->gpuaddr; memdesc->priv |= KGSL_MEMDESC_GLOBAL; - result = kgsl_mmu_map(pagetable, memdesc); + result = kgsl_mmu_get_gpuaddr(pagetable, memdesc); if (result) goto error; + result = kgsl_mmu_map(pagetable, memdesc); + if (result) + goto error_put_gpuaddr; /*global mappings must have the same gpu address in all pagetables*/ if (gpuaddr && gpuaddr != memdesc->gpuaddr) { - KGSL_CORE_ERR("pt %p addr mismatch phys 0x%08x" - "gpu 0x%0x 0x%08x", pagetable, memdesc->physaddr, - gpuaddr, memdesc->gpuaddr); + KGSL_CORE_ERR("pt %p addr mismatch phys %pa gpu 0x%0x 0x%08x", + pagetable, &memdesc->physaddr, gpuaddr, memdesc->gpuaddr); goto error_unmap; } return result; error_unmap: kgsl_mmu_unmap(pagetable, memdesc); +error_put_gpuaddr: + kgsl_mmu_put_gpuaddr(pagetable, memdesc); error: return result; } @@ -901,15 +977,16 @@ void kgsl_mmu_set_mmutype(char *mmutype) } EXPORT_SYMBOL(kgsl_mmu_set_mmutype); -int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr) +int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr) { if (KGSL_MMU_TYPE_NONE == kgsl_mmu_type) return 1; - if (gpuaddr >= kgsl_mmu_get_base_addr() && - gpuaddr < kgsl_mmu_get_base_addr() + kgsl_mmu_get_ptsize()) + if (gpuaddr >= kgsl_mmu_get_base_addr(pt->mmu) && + gpuaddr < kgsl_mmu_get_base_addr(pt->mmu) + + kgsl_mmu_get_ptsize(pt->mmu)) return 1; if (kgsl_mmu_get_mmutype() == KGSL_MMU_TYPE_IOMMU - && kgsl_mmu_is_perprocess()) + && kgsl_mmu_is_perprocess(pt->mmu)) return (gpuaddr > 0 && gpuaddr < TASK_SIZE); return 0; } diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h index fe1b2ee58ea..de6bafcf7ae 100644 --- a/drivers/gpu/msm/kgsl_mmu.h +++ b/drivers/gpu/msm/kgsl_mmu.h @@ -14,16 +14,27 @@ #define __KGSL_MMU_H #include - +#include "kgsl_iommu.h" /* * These defines control the address range for allocations that * are mapped into all pagetables. */ +#ifndef CONFIG_MSM_KGSL_CFF_DUMP #define KGSL_IOMMU_GLOBAL_MEM_BASE 0xf8000000 +#else +#define KGSL_IOMMU_GLOBAL_MEM_BASE (0x09F00000 - SZ_4M) +#endif #define KGSL_IOMMU_GLOBAL_MEM_SIZE SZ_4M #define KGSL_MMU_ALIGN_MASK (~((1 << PAGE_SHIFT) - 1)) +/* defconfig option for disabling per process pagetables */ +#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE +#define KGSL_MMU_USE_PER_PROCESS_PT true +#else +#define KGSL_MMU_USE_PER_PROCESS_PT false +#endif + /* Identifier for the global page table */ /* Per process page tables will probably pass in the thread group as an identifier */ @@ -116,6 +127,7 @@ struct kgsl_pagetable { unsigned int tlb_flags; unsigned int fault_addr; void *priv; + struct kgsl_mmu *mmu; }; struct kgsl_mmu; @@ -131,7 +143,9 @@ struct kgsl_mmu_ops { int (*mmu_device_setstate) (struct kgsl_mmu *mmu, uint32_t flags); void (*mmu_pagefault) (struct kgsl_mmu *mmu); - unsigned int (*mmu_get_current_ptbase) + phys_addr_t (*mmu_get_current_ptbase) + (struct kgsl_mmu *mmu); + void (*mmu_pagefault_resume) (struct kgsl_mmu *mmu); void (*mmu_disable_clk_on_ts) (struct kgsl_mmu *mmu, uint32_t ts, bool ts_valid); @@ -139,40 +153,42 @@ struct kgsl_mmu_ops { (struct kgsl_mmu *mmu, int ctx_id); void (*mmu_disable_clk) (struct kgsl_mmu *mmu); - int (*mmu_get_pt_lsb)(struct kgsl_mmu *mmu, + phys_addr_t (*mmu_get_default_ttbr0)(struct kgsl_mmu *mmu, unsigned int unit_id, enum kgsl_iommu_context_id ctx_id); unsigned int (*mmu_get_reg_gpuaddr)(struct kgsl_mmu *mmu, int iommu_unit_num, int ctx_id, int reg); + unsigned int (*mmu_get_reg_ahbaddr)(struct kgsl_mmu *mmu, + int iommu_unit_num, int ctx_id, + enum kgsl_iommu_reg_map reg); int (*mmu_get_num_iommu_units)(struct kgsl_mmu *mmu); int (*mmu_pt_equal) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt, - unsigned int pt_base); - unsigned int (*mmu_get_pt_base_addr) + phys_addr_t pt_base); + phys_addr_t (*mmu_get_pt_base_addr) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt); - unsigned int (*mmu_sync_lock) - (struct kgsl_mmu *mmu, - unsigned int *cmds); - unsigned int (*mmu_sync_unlock) - (struct kgsl_mmu *mmu, - unsigned int *cmds); int (*mmu_setup_pt) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt); void (*mmu_cleanup_pt) (struct kgsl_mmu *mmu, struct kgsl_pagetable *pt); + unsigned int (*mmu_sync_lock) + (struct kgsl_mmu *mmu, unsigned int *cmds); + unsigned int (*mmu_sync_unlock) + (struct kgsl_mmu *mmu, unsigned int *cmds); + int (*mmu_hw_halt_supported)(struct kgsl_mmu *mmu, int iommu_unit_num); }; struct kgsl_mmu_pt_ops { - int (*mmu_map) (void *mmu_pt, + int (*mmu_map) (struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int protflags, unsigned int *tlb_flags); - int (*mmu_unmap) (void *mmu_pt, + int (*mmu_unmap) (struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags); void *(*mmu_create_pagetable) (void); - void (*mmu_destroy_pagetable) (void *pt); + void (*mmu_destroy_pagetable) (struct kgsl_pagetable *); }; #define KGSL_MMU_FLAGS_IOMMU_SYNC BIT(31) @@ -190,15 +206,20 @@ struct kgsl_mmu { struct kgsl_pagetable *hwpagetable; const struct kgsl_mmu_ops *mmu_ops; void *priv; - int fault; + atomic_t fault; + unsigned long pt_base; + unsigned long pt_size; + bool pt_per_process; + bool use_cpu_map; }; -#include "kgsl_gpummu.h" - extern struct kgsl_mmu_ops iommu_ops; extern struct kgsl_mmu_pt_ops iommu_pt_ops; +extern struct kgsl_mmu_ops gpummu_ops; +extern struct kgsl_mmu_pt_ops gpummu_pt_ops; -struct kgsl_pagetable *kgsl_mmu_getpagetable(unsigned long name); +struct kgsl_pagetable *kgsl_mmu_getpagetable(struct kgsl_mmu *, + unsigned long name); void kgsl_mmu_putpagetable(struct kgsl_pagetable *pagetable); void kgsl_mh_start(struct kgsl_device *device); void kgsl_mh_intrcallback(struct kgsl_device *device); @@ -207,17 +228,21 @@ int kgsl_mmu_start(struct kgsl_device *device); int kgsl_mmu_close(struct kgsl_device *device); int kgsl_mmu_map(struct kgsl_pagetable *pagetable, struct kgsl_memdesc *memdesc); +int kgsl_mmu_get_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc); int kgsl_mmu_map_global(struct kgsl_pagetable *pagetable, struct kgsl_memdesc *memdesc); int kgsl_mmu_unmap(struct kgsl_pagetable *pagetable, struct kgsl_memdesc *memdesc); +int kgsl_mmu_put_gpuaddr(struct kgsl_pagetable *pagetable, + struct kgsl_memdesc *memdesc); unsigned int kgsl_virtaddr_to_physaddr(void *virtaddr); int kgsl_setstate(struct kgsl_mmu *mmu, unsigned int context_id, uint32_t flags); int kgsl_mmu_get_ptname_from_ptbase(struct kgsl_mmu *mmu, - unsigned int pt_base); + phys_addr_t pt_base); unsigned int kgsl_mmu_log_fault_addr(struct kgsl_mmu *mmu, - unsigned int pt_base, unsigned int addr); + phys_addr_t pt_base, unsigned int addr); int kgsl_mmu_pt_get_flags(struct kgsl_pagetable *pt, enum kgsl_deviceid id); void kgsl_mmu_ptpool_destroy(void *ptpool); @@ -225,7 +250,7 @@ void *kgsl_mmu_ptpool_init(int entries); int kgsl_mmu_enabled(void); void kgsl_mmu_set_mmutype(char *mmutype); enum kgsl_mmutype kgsl_mmu_get_mmutype(void); -int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr); +int kgsl_mmu_gpuaddr_in_range(struct kgsl_pagetable *pt, unsigned int gpuaddr); /* * Static inline functions of MMU that simply call the SMMU specific @@ -233,7 +258,7 @@ int kgsl_mmu_gpuaddr_in_range(unsigned int gpuaddr); * of as wrappers around the actual function */ -static inline unsigned int kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu) +static inline phys_addr_t kgsl_mmu_get_current_ptbase(struct kgsl_mmu *mmu) { if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_current_ptbase) return mmu->mmu_ops->mmu_get_current_ptbase(mmu); @@ -268,7 +293,7 @@ static inline void kgsl_mmu_stop(struct kgsl_mmu *mmu) static inline int kgsl_mmu_pt_equal(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt, - unsigned int pt_base) + phys_addr_t pt_base) { if (mmu->mmu_ops && mmu->mmu_ops->mmu_pt_equal) return mmu->mmu_ops->mmu_pt_equal(mmu, pt, pt_base); @@ -276,7 +301,7 @@ static inline int kgsl_mmu_pt_equal(struct kgsl_mmu *mmu, return 1; } -static inline unsigned int kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu, +static inline phys_addr_t kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu, struct kgsl_pagetable *pt) { if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_pt_base_addr) @@ -285,12 +310,13 @@ static inline unsigned int kgsl_mmu_get_pt_base_addr(struct kgsl_mmu *mmu, return 0; } -static inline int kgsl_mmu_get_pt_lsb(struct kgsl_mmu *mmu, +static inline phys_addr_t kgsl_mmu_get_default_ttbr0(struct kgsl_mmu *mmu, unsigned int unit_id, enum kgsl_iommu_context_id ctx_id) { - if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_pt_lsb) - return mmu->mmu_ops->mmu_get_pt_lsb(mmu, unit_id, ctx_id); + if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_default_ttbr0) + return mmu->mmu_ops->mmu_get_default_ttbr0(mmu, unit_id, + ctx_id); else return 0; } @@ -338,30 +364,49 @@ static inline unsigned int kgsl_mmu_get_reg_gpuaddr(struct kgsl_mmu *mmu, return 0; } -static inline int kgsl_mmu_get_num_iommu_units(struct kgsl_mmu *mmu) +/* + * kgsl_mmu_get_reg_ahbaddr() - Calls the mmu specific function pointer to + * return the address that GPU can use to access register + * @mmu: Pointer to the device mmu + * @iommu_unit_num: There can be multiple iommu units used for graphics. + * This parameter is an index to the iommu unit being used + * @ctx_id: The context id within the iommu unit + * @reg: Register whose address is to be returned + * + * Returns the ahb address of reg else 0 + */ +static inline unsigned int kgsl_mmu_get_reg_ahbaddr(struct kgsl_mmu *mmu, + int iommu_unit_num, + int ctx_id, + enum kgsl_iommu_reg_map reg) { - if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_num_iommu_units) - return mmu->mmu_ops->mmu_get_num_iommu_units(mmu); + if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_reg_ahbaddr) + return mmu->mmu_ops->mmu_get_reg_ahbaddr(mmu, iommu_unit_num, + ctx_id, reg); else return 0; } -static inline int kgsl_mmu_sync_lock(struct kgsl_mmu *mmu, - unsigned int *cmds) +static inline int kgsl_mmu_get_num_iommu_units(struct kgsl_mmu *mmu) { - if ((mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC) && - mmu->mmu_ops && mmu->mmu_ops->mmu_sync_lock) - return mmu->mmu_ops->mmu_sync_lock(mmu, cmds); + if (mmu->mmu_ops && mmu->mmu_ops->mmu_get_num_iommu_units) + return mmu->mmu_ops->mmu_get_num_iommu_units(mmu); else return 0; } -static inline int kgsl_mmu_sync_unlock(struct kgsl_mmu *mmu, - unsigned int *cmds) +/* + * kgsl_mmu_hw_halt_supported() - Runtime check for iommu hw halt + * @mmu: the mmu + * + * Returns non-zero if the iommu supports hw halt, + * 0 if not. + */ +static inline int kgsl_mmu_hw_halt_supported(struct kgsl_mmu *mmu, + int iommu_unit_num) { - if ((mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC) && - mmu->mmu_ops && mmu->mmu_ops->mmu_sync_unlock) - return mmu->mmu_ops->mmu_sync_unlock(mmu, cmds); + if (mmu->mmu_ops && mmu->mmu_ops->mmu_hw_halt_supported) + return mmu->mmu_ops->mmu_hw_halt_supported(mmu, iommu_unit_num); else return 0; } @@ -369,75 +414,71 @@ static inline int kgsl_mmu_sync_unlock(struct kgsl_mmu *mmu, /* * kgsl_mmu_is_perprocess() - Runtime check for per-process * pagetables. + * @mmu: the mmu * - * Returns non-zero if per-process pagetables are enabled, - * 0 if not. + * Returns true if per-process pagetables are enabled, + * false if not. */ -#ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE -static inline int kgsl_mmu_is_perprocess(void) +static inline int kgsl_mmu_is_perprocess(struct kgsl_mmu *mmu) { - - /* We presently do not support per-process for IOMMU-v2 */ - return (kgsl_mmu_get_mmutype() != KGSL_MMU_TYPE_IOMMU) - || msm_soc_version_supports_iommu_v1(); + return mmu->pt_per_process; } -#else -static inline int kgsl_mmu_is_perprocess(void) + +/* + * kgsl_mmu_use_cpu_map() - Runtime check for matching the CPU + * address space on the GPU. + * @mmu: the mmu + * + * Returns true if supported false if not. + */ +static inline int kgsl_mmu_use_cpu_map(struct kgsl_mmu *mmu) { - return 0; + return mmu->use_cpu_map; } -#endif /* * kgsl_mmu_base_addr() - Get gpu virtual address base. + * @mmu: the mmu * * Returns the start address of the allocatable gpu * virtual address space. Other mappings that mirror * the CPU address space are possible outside this range. */ -static inline unsigned int kgsl_mmu_get_base_addr(void) +static inline unsigned int kgsl_mmu_get_base_addr(struct kgsl_mmu *mmu) { - if (KGSL_MMU_TYPE_GPU == kgsl_mmu_get_mmutype() - || !kgsl_mmu_is_perprocess()) - return KGSL_PAGETABLE_BASE; - /* - * This is the start of the kernel address - * space, so allocations from this range will - * never conflict with userpace addresses - */ - return PAGE_OFFSET; + return mmu->pt_base; } /* * kgsl_mmu_get_ptsize() - Get gpu pagetable size + * @mmu: the mmu * * Returns the usable size of the gpu allocatable * address space. */ -static inline unsigned int kgsl_mmu_get_ptsize(void) +static inline unsigned int kgsl_mmu_get_ptsize(struct kgsl_mmu *mmu) { - /* - * For IOMMU per-process pagetables, the allocatable range - * and the kernel global range must both be outside - * the userspace address range. There is a 1Mb gap - * between these address ranges to make overrun - * detection easier. - * For the shared pagetable case use 2GB and because - * mirroring the CPU address space is not possible and - * we're better off with extra room. - */ - enum kgsl_mmutype mmu_type = kgsl_mmu_get_mmutype(); - - if (KGSL_MMU_TYPE_GPU == mmu_type) - return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE; - else if (KGSL_MMU_TYPE_IOMMU == mmu_type) { - if (kgsl_mmu_is_perprocess()) - return KGSL_IOMMU_GLOBAL_MEM_BASE - - kgsl_mmu_get_base_addr() - SZ_1M; - else - return SZ_2G; - } - return 0; + return mmu->pt_size; +} + +static inline int kgsl_mmu_sync_lock(struct kgsl_mmu *mmu, + unsigned int *cmds) +{ + if ((mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC) && + mmu->mmu_ops && mmu->mmu_ops->mmu_sync_lock) + return mmu->mmu_ops->mmu_sync_lock(mmu, cmds); + else + return 0; +} + +static inline int kgsl_mmu_sync_unlock(struct kgsl_mmu *mmu, + unsigned int *cmds) +{ + if ((mmu->flags & KGSL_MMU_FLAGS_IOMMU_SYNC) && + mmu->mmu_ops && mmu->mmu_ops->mmu_sync_unlock) + return mmu->mmu_ops->mmu_sync_unlock(mmu, cmds); + else + return 0; } #endif /* __KGSL_MMU_H */ diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c index bcdce85b24b..1d808195efe 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.c +++ b/drivers/gpu/msm/kgsl_pwrctrl.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, 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 @@ -18,6 +18,7 @@ #include #include #include +#include #include "kgsl.h" #include "kgsl_pwrscale.h" @@ -30,10 +31,21 @@ #define KGSL_PWRFLAGS_AXI_ON 2 #define KGSL_PWRFLAGS_IRQ_ON 3 -#define GPU_SWFI_LATENCY 3 #define UPDATE_BUSY_VAL 1000000 #define UPDATE_BUSY 50 +/* + * Expected delay for post-interrupt processing on A3xx. + * The delay may be longer, gradually increase the delay + * to compensate. If the GPU isn't done by max delay, + * it's working on something other than just the final + * command sequence so stop waiting for it to be idle. + */ +#define INIT_UDELAY 200 +#define MAX_UDELAY 2000 + +unsigned long internal_max = 450000000; + struct clk_pair { const char *name; uint map; @@ -60,8 +72,17 @@ struct clk_pair clks[KGSL_MAX_CLKS] = { .name = "mem_iface_clk", .map = KGSL_CLK_MEM_IFACE, }, + { + .name = "alt_mem_iface_clk", + .map = KGSL_CLK_ALT_MEM_IFACE, + }, }; +static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, + int requested_state); +static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state); +static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state); + /* Update the elapsed time at a particular clock level * if the device is active(on_time = true).Otherwise * store it as sleep time. @@ -131,6 +152,16 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, */ pwr->active_pwrlevel = new_level; + pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel]; + + if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) { + + if (pwr->pcl) + msm_bus_scale_client_update_request(pwr->pcl, + pwrlevel->bus_freq); + else if (pwr->ebi1_clk) + clk_set_rate(pwr->ebi1_clk, pwrlevel->bus_freq); + } if (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) || (device->state == KGSL_STATE_NAP)) { @@ -157,16 +188,6 @@ void kgsl_pwrctrl_pwrlevel_change(struct kgsl_device *device, } } - pwrlevel = &pwr->pwrlevels[pwr->active_pwrlevel]; - - if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) { - - if (pwr->pcl) - msm_bus_scale_client_update_request(pwr->pcl, - pwrlevel->bus_freq); - else if (pwr->ebi1_clk) - clk_set_rate(pwr->ebi1_clk, pwrlevel->bus_freq); - } trace_kgsl_pwrlevel(device, pwr->active_pwrlevel, pwrlevel->gpu_freq); } @@ -358,13 +379,13 @@ static int kgsl_pwrctrl_num_pwrlevels_show(struct device *dev, return snprintf(buf, PAGE_SIZE, "%d\n", pwr->num_pwrlevels - 1); } -/* Given a GPU clock value, return the nearest powerlevel */ +/* Given a GPU clock value, return the lowest matching powerlevel */ static int _get_nearest_pwrlevel(struct kgsl_pwrctrl *pwr, unsigned int clock) { int i; - for (i = 0; i < pwr->num_pwrlevels - 1; i++) { + for (i = pwr->num_pwrlevels - 1; i >= 0; i--) { if (abs(pwr->pwrlevels[i].gpu_freq - clock) < 5000000) return i; } @@ -372,6 +393,9 @@ static int _get_nearest_pwrlevel(struct kgsl_pwrctrl *pwr, unsigned int clock) return -ERANGE; } +extern void SetGPUpll_config(u32 loc, unsigned long freq); +extern void SetMAXGPUFreq(unsigned long freq); + static int kgsl_pwrctrl_max_gpuclk_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -390,6 +414,33 @@ static int kgsl_pwrctrl_max_gpuclk_store(struct device *dev, if (ret != 1) return count; + if (val == 400000000) + { + SetGPUpll_config(0x1D, val); + } + else if (val == 450000000) + { + SetGPUpll_config(0x21, val); + } + else if (val == 504000000) + { + SetGPUpll_config(0x25, val); + } + else if (val == 545000000) + { + SetGPUpll_config(0x28, val); + } + else if (val == 600000000) + { + SetGPUpll_config(0x2C, val); + } + else if (val == 627000000) + { + SetGPUpll_config(0x2E, val); + } + + internal_max = val; + mutex_lock(&device->mutex); level = _get_nearest_pwrlevel(pwr, val); if (level < 0) @@ -420,8 +471,8 @@ static int kgsl_pwrctrl_max_gpuclk_show(struct device *dev, if (device == NULL) return 0; pwr = &device->pwrctrl; - return snprintf(buf, PAGE_SIZE, "%d\n", - pwr->pwrlevels[pwr->thermal_pwrlevel].gpu_freq); + return snprintf(buf, PAGE_SIZE, "%ld\n", + internal_max); } static int kgsl_pwrctrl_gpuclk_store(struct device *dev, @@ -460,18 +511,23 @@ static int kgsl_pwrctrl_gpuclk_show(struct device *dev, if (device == NULL) return 0; pwr = &device->pwrctrl; - return snprintf(buf, PAGE_SIZE, "%d\n", + if (pwr->active_pwrlevel != 0) + return snprintf(buf, PAGE_SIZE, "%d\n", pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); + else + return snprintf(buf, PAGE_SIZE, "%ld\n", + internal_max); } -static int kgsl_pwrctrl_pwrnap_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static int kgsl_pwrctrl_idle_timer_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) { char temp[20]; unsigned long val; struct kgsl_device *device = kgsl_device_from_dev(dev); struct kgsl_pwrctrl *pwr; + const long div = 1000/HZ; int rc; if (device == NULL) @@ -486,73 +542,62 @@ static int kgsl_pwrctrl_pwrnap_store(struct device *dev, mutex_lock(&device->mutex); - if (val == 1) - pwr->nap_allowed = true; - else if (val == 0) - pwr->nap_allowed = false; + /* Let the timeout be requested in ms, but convert to jiffies. */ + val /= div; + pwr->interval_timeout = val; mutex_unlock(&device->mutex); return count; } -static int kgsl_pwrctrl_pwrnap_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int kgsl_pwrctrl_idle_timer_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct kgsl_device *device = kgsl_device_from_dev(dev); + int mul = 1000/HZ; if (device == NULL) return 0; - return snprintf(buf, PAGE_SIZE, "%d\n", device->pwrctrl.nap_allowed); + /* Show the idle_timeout converted to msec */ + return snprintf(buf, PAGE_SIZE, "%d\n", + device->pwrctrl.interval_timeout * mul); } - -static int kgsl_pwrctrl_idle_timer_store(struct device *dev, +static int kgsl_pwrctrl_pmqos_latency_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { char temp[20]; unsigned long val; struct kgsl_device *device = kgsl_device_from_dev(dev); - struct kgsl_pwrctrl *pwr; - const long div = 1000/HZ; - static unsigned int org_interval_timeout = 1; int rc; if (device == NULL) return 0; - pwr = &device->pwrctrl; snprintf(temp, sizeof(temp), "%.*s", - (int)min(count, sizeof(temp) - 1), buf); - rc = strict_strtoul(temp, 0, &val); + (int)min(count, sizeof(temp) - 1), buf); + rc = kstrtoul(temp, 0, &val); if (rc) return rc; - if (org_interval_timeout == 1) - org_interval_timeout = pwr->interval_timeout; - mutex_lock(&device->mutex); - - /* Let the timeout be requested in ms, but convert to jiffies. */ - val /= div; - if (val >= org_interval_timeout) - pwr->interval_timeout = val; - + device->pwrctrl.pm_qos_latency = val; mutex_unlock(&device->mutex); return count; } -static int kgsl_pwrctrl_idle_timer_show(struct device *dev, - struct device_attribute *attr, - char *buf) +static int kgsl_pwrctrl_pmqos_latency_show(struct device *dev, + struct device_attribute *attr, + char *buf) { struct kgsl_device *device = kgsl_device_from_dev(dev); if (device == NULL) return 0; return snprintf(buf, PAGE_SIZE, "%d\n", - device->pwrctrl.interval_timeout); + device->pwrctrl.pm_qos_latency); } static int kgsl_pwrctrl_gpubusy_show(struct device *dev, @@ -561,7 +606,11 @@ static int kgsl_pwrctrl_gpubusy_show(struct device *dev, { int ret; struct kgsl_device *device = kgsl_device_from_dev(dev); - struct kgsl_clk_stats *clkstats = &device->pwrctrl.clk_stats; + struct kgsl_clk_stats *clkstats; + + if (device == NULL) + return 0; + clkstats = &device->pwrctrl.clk_stats; ret = snprintf(buf, PAGE_SIZE, "%7d %7d\n", clkstats->on_time_old, clkstats->elapsed_old); if (!test_bit(KGSL_PWRFLAGS_AXI_ON, &device->pwrctrl.power_flags)) { @@ -577,10 +626,13 @@ static int kgsl_pwrctrl_gputop_show(struct device *dev, { int ret; struct kgsl_device *device = kgsl_device_from_dev(dev); - struct kgsl_clk_stats *clkstats = &device->pwrctrl.clk_stats; + struct kgsl_clk_stats *clkstats; int i = 0; char *ptr = buf; + if (device == NULL) + return 0; + clkstats = &device->pwrctrl.clk_stats; ret = snprintf(buf, PAGE_SIZE, "%7d %7d ", clkstats->on_time_old, clkstats->elapsed_old); for (i = 0, ptr += ret; i < device->pwrctrl.num_pwrlevels; @@ -610,8 +662,17 @@ static int kgsl_pwrctrl_gpu_available_frequencies_show( return 0; pwr = &device->pwrctrl; for (index = 0; index < pwr->num_pwrlevels - 1; index++) - num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ", - pwr->pwrlevels[index].gpu_freq); + if (index == 0) + { + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",627000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",600000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",545000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",504000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",450000000); + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",400000000); + } + else + num_chars += snprintf(buf + num_chars, PAGE_SIZE, "%d ",pwr->pwrlevels[index].gpu_freq); buf[num_chars++] = '\n'; return num_chars; } @@ -621,13 +682,114 @@ static int kgsl_pwrctrl_reset_count_show(struct device *dev, char *buf) { struct kgsl_device *device = kgsl_device_from_dev(dev); + if (device == NULL) + return 0; return snprintf(buf, PAGE_SIZE, "%d\n", device->reset_counter); } +static void __force_on(struct kgsl_device *device, int flag, int on) +{ + if (on) { + switch (flag) { + case KGSL_PWRFLAGS_CLK_ON: + kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, + KGSL_STATE_ACTIVE); + break; + case KGSL_PWRFLAGS_AXI_ON: + kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON); + break; + case KGSL_PWRFLAGS_POWER_ON: + kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON); + break; + } + set_bit(flag, &device->pwrctrl.ctrl_flags); + } else { + clear_bit(flag, &device->pwrctrl.ctrl_flags); + } +} + +static int __force_on_show(struct device *dev, + struct device_attribute *attr, + char *buf, int flag) +{ + struct kgsl_device *device = kgsl_device_from_dev(dev); + int i = test_bit(flag, &device->pwrctrl.ctrl_flags); + if (device == NULL) + return 0; + return snprintf(buf, PAGE_SIZE, "%d\n", i); +} + +static int __force_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count, + int flag) +{ + char temp[20]; + unsigned long val; + struct kgsl_device *device = kgsl_device_from_dev(dev); + int rc; + + if (device == NULL) + return 0; + + snprintf(temp, sizeof(temp), "%.*s", + (int)min(count, sizeof(temp) - 1), buf); + rc = kstrtoul(temp, 0, &val); + if (rc) + return rc; + + mutex_lock(&device->mutex); + __force_on(device, flag, val); + mutex_unlock(&device->mutex); + + return count; +} + +static int kgsl_pwrctrl_force_clk_on_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_CLK_ON); +} + +static int kgsl_pwrctrl_force_clk_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_CLK_ON); +} + +static int kgsl_pwrctrl_force_bus_on_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_AXI_ON); +} + +static int kgsl_pwrctrl_force_bus_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_AXI_ON); +} + +static int kgsl_pwrctrl_force_rail_on_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + return __force_on_show(dev, attr, buf, KGSL_PWRFLAGS_POWER_ON); +} + +static int kgsl_pwrctrl_force_rail_on_store(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + return __force_on_store(dev, attr, buf, count, KGSL_PWRFLAGS_POWER_ON); +} + DEVICE_ATTR(gpuclk, 0644, kgsl_pwrctrl_gpuclk_show, kgsl_pwrctrl_gpuclk_store); DEVICE_ATTR(max_gpuclk, 0644, kgsl_pwrctrl_max_gpuclk_show, kgsl_pwrctrl_max_gpuclk_store); -DEVICE_ATTR(pwrnap, 0664, kgsl_pwrctrl_pwrnap_show, kgsl_pwrctrl_pwrnap_store); DEVICE_ATTR(idle_timer, 0644, kgsl_pwrctrl_idle_timer_show, kgsl_pwrctrl_idle_timer_store); DEVICE_ATTR(gpubusy, 0444, kgsl_pwrctrl_gpubusy_show, @@ -652,11 +814,22 @@ DEVICE_ATTR(num_pwrlevels, 0444, DEVICE_ATTR(reset_count, 0444, kgsl_pwrctrl_reset_count_show, NULL); +DEVICE_ATTR(pmqos_latency, 0644, + kgsl_pwrctrl_pmqos_latency_show, + kgsl_pwrctrl_pmqos_latency_store); +DEVICE_ATTR(force_clk_on, 0644, + kgsl_pwrctrl_force_clk_on_show, + kgsl_pwrctrl_force_clk_on_store); +DEVICE_ATTR(force_bus_on, 0644, + kgsl_pwrctrl_force_bus_on_show, + kgsl_pwrctrl_force_bus_on_store); +DEVICE_ATTR(force_rail_on, 0644, + kgsl_pwrctrl_force_rail_on_show, + kgsl_pwrctrl_force_rail_on_store); static const struct device_attribute *pwrctrl_attr_list[] = { &dev_attr_gpuclk, &dev_attr_max_gpuclk, - &dev_attr_pwrnap, &dev_attr_idle_timer, &dev_attr_gpubusy, &dev_attr_gputop, @@ -666,6 +839,10 @@ static const struct device_attribute *pwrctrl_attr_list[] = { &dev_attr_thermal_pwrlevel, &dev_attr_num_pwrlevels, &dev_attr_reset_count, + &dev_attr_pmqos_latency, + &dev_attr_force_clk_on, + &dev_attr_force_bus_on, + &dev_attr_force_rail_on, NULL }; @@ -697,6 +874,9 @@ static void update_statistics(struct kgsl_device *device) clkstats->on_time_old = on_time; clkstats->elapsed_old = clkstats->elapsed; clkstats->elapsed = 0; + + trace_kgsl_gpubusy(device, clkstats->on_time_old, + clkstats->elapsed_old); } /* Track the amount of time the gpu is on vs the total system time. * @@ -712,11 +892,15 @@ static void kgsl_pwrctrl_busy_time(struct kgsl_device *device, bool on_time) } } -void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, +static void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, int requested_state) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; int i = 0; + + if (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->ctrl_flags)) + return; + if (state == KGSL_PWRFLAGS_OFF) { if (test_and_clear_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags)) { @@ -727,23 +911,23 @@ void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, /* High latency clock maintenance. */ if ((pwr->pwrlevels[0].gpu_freq > 0) && (requested_state != KGSL_STATE_NAP)) { - clk_set_rate(pwr->grp_clks[0], - pwr->pwrlevels[pwr->num_pwrlevels - 1]. - gpu_freq); for (i = KGSL_MAX_CLKS - 1; i > 0; i--) if (pwr->grp_clks[i]) clk_unprepare(pwr->grp_clks[i]); + clk_set_rate(pwr->grp_clks[0], + pwr->pwrlevels[pwr->num_pwrlevels - 1]. + gpu_freq); } kgsl_pwrctrl_busy_time(device, true); } else if (requested_state == KGSL_STATE_SLEEP) { /* High latency clock maintenance. */ + for (i = KGSL_MAX_CLKS - 1; i > 0; i--) + if (pwr->grp_clks[i]) + clk_unprepare(pwr->grp_clks[i]); if ((pwr->pwrlevels[0].gpu_freq > 0)) clk_set_rate(pwr->grp_clks[0], pwr->pwrlevels[pwr->num_pwrlevels - 1]. gpu_freq); - for (i = KGSL_MAX_CLKS - 1; i > 0; i--) - if (pwr->grp_clks[i]) - clk_unprepare(pwr->grp_clks[i]); } } else if (state == KGSL_PWRFLAGS_ON) { if (!test_and_set_bit(KGSL_PWRFLAGS_CLK_ON, @@ -751,15 +935,14 @@ void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, trace_kgsl_clk(device, state); /* High latency clock maintenance. */ if (device->state != KGSL_STATE_NAP) { - for (i = KGSL_MAX_CLKS - 1; i > 0; i--) - if (pwr->grp_clks[i]) - clk_prepare(pwr->grp_clks[i]); - if (pwr->pwrlevels[0].gpu_freq > 0) clk_set_rate(pwr->grp_clks[0], pwr->pwrlevels [pwr->active_pwrlevel]. gpu_freq); + for (i = KGSL_MAX_CLKS - 1; i > 0; i--) + if (pwr->grp_clks[i]) + clk_prepare(pwr->grp_clks[i]); } /* as last step, enable grp_clk this is to let GPU interrupt to come */ @@ -771,10 +954,13 @@ void kgsl_pwrctrl_clk(struct kgsl_device *device, int state, } } -void kgsl_pwrctrl_axi(struct kgsl_device *device, int state) +static void kgsl_pwrctrl_axi(struct kgsl_device *device, int state) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; + if (test_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->ctrl_flags)) + return; + if (state == KGSL_PWRFLAGS_OFF) { if (test_and_clear_bit(KGSL_PWRFLAGS_AXI_ON, &pwr->power_flags)) { @@ -805,10 +991,13 @@ void kgsl_pwrctrl_axi(struct kgsl_device *device, int state) } } -void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state) +static void kgsl_pwrctrl_pwrrail(struct kgsl_device *device, int state) { struct kgsl_pwrctrl *pwr = &device->pwrctrl; + if (test_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->ctrl_flags)) + return; + if (state == KGSL_PWRFLAGS_OFF) { if (test_and_clear_bit(KGSL_PWRFLAGS_POWER_ON, &pwr->power_flags)) { @@ -908,6 +1097,7 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) pwr->active_pwrlevel = pdata->init_level; pwr->default_pwrlevel = pdata->init_level; + pwr->init_pwrlevel = pdata->init_level; for (i = 0; i < pdata->num_levels; i++) { pwr->pwrlevels[i].gpu_freq = (pdata->pwrlevel[i].gpu_freq > 0) ? @@ -937,7 +1127,6 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) pwr->power_flags = 0; - pwr->nap_allowed = pdata->nap_allowed; pwr->idle_needed = pdata->idle_needed; pwr->interval_timeout = pdata->idle_timeout; pwr->strtstp_sleepwake = pdata->strtstp_sleepwake; @@ -961,9 +1150,13 @@ int kgsl_pwrctrl_init(struct kgsl_device *device) } } + /* Set the power level step multiplier with 1 as the default */ + pwr->step_mul = pdata->step_mul ? pdata->step_mul : 1; + + /* Set the CPU latency to 501usec to allow low latency PC modes */ + pwr->pm_qos_latency = 501; pm_runtime_enable(device->parentdev); - register_early_suspend(&device->display_off); return result; clk_err: @@ -983,7 +1176,6 @@ void kgsl_pwrctrl_close(struct kgsl_device *device) KGSL_PWR_INFO(device, "close device %d\n", device->id); pm_runtime_disable(device->parentdev); - unregister_early_suspend(&device->display_off); clk_put(pwr->ebi1_clk); @@ -1022,6 +1214,8 @@ void kgsl_pwrctrl_close(struct kgsl_device *device) */ void kgsl_idle_check(struct work_struct *work) { + int delay = INIT_UDELAY; + int requested_state; struct kgsl_device *device = container_of(work, struct kgsl_device, idle_check_ws); WARN_ON(device == NULL); @@ -1033,13 +1227,34 @@ void kgsl_idle_check(struct work_struct *work) kgsl_pwrscale_idle(device); if (device->state == KGSL_STATE_ACTIVE - || device->state == KGSL_STATE_NAP) { - - /* If we failed to sleep then reset the timer and try again */ - if (kgsl_pwrctrl_sleep(device) != 0) { + || device->state == KGSL_STATE_NAP) { + /* + * If no user is explicitly trying to use the GPU + * (active_cnt is zero), then loop with increasing delay, + * waiting for the GPU to become idle. + */ + while (!atomic_read(&device->active_cnt) && + (delay < MAX_UDELAY)) { + requested_state = device->requested_state; + if (!kgsl_pwrctrl_sleep(device)) + break; + /* + * If no new commands have been issued since the + * last interrupt, stay in this loop waiting for + * the GPU to become idle. + */ + if (!device->pwrctrl.irq_last) + break; + kgsl_pwrctrl_request_state(device, requested_state); + mutex_unlock(&device->mutex); + udelay(delay); + delay *= 2; + mutex_lock(&device->mutex); + } - kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); + kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); + if (device->state == KGSL_STATE_ACTIVE) { mod_timer(&device->idle_timer, jiffies + device->pwrctrl.interval_timeout); @@ -1053,6 +1268,8 @@ void kgsl_idle_check(struct work_struct *work) kgsl_pwrctrl_busy_time(device, true); device->pwrctrl.clk_stats.no_nap_cnt = 0; } + } else { + device->pwrctrl.irq_last = 0; } } @@ -1066,8 +1283,7 @@ void kgsl_timer(unsigned long data) KGSL_PWR_INFO(device, "idle timer expired device %d\n", device->id); if (device->requested_state != KGSL_STATE_SUSPEND) { - if (device->pwrctrl.restore_slumber || - device->pwrctrl.strtstp_sleepwake) + if (device->pwrctrl.strtstp_sleepwake) kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER); else kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP); @@ -1076,6 +1292,11 @@ void kgsl_timer(unsigned long data) } } +bool kgsl_pwrctrl_isenabled(struct kgsl_device *device) +{ + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + return (test_bit(KGSL_PWRFLAGS_CLK_ON, &pwr->power_flags) != 0); +} /** * kgsl_pre_hwaccess - Enforce preconditions for touching registers @@ -1092,7 +1313,7 @@ void kgsl_pre_hwaccess(struct kgsl_device *device) /* In order to touch a register you must hold the device mutex...*/ BUG_ON(!mutex_is_locked(&device->mutex)); /* and have the clock on! */ - BUG_ON(!test_bit(KGSL_PWRFLAGS_CLK_ON, &device->pwrctrl.power_flags)); + BUG_ON(!kgsl_pwrctrl_isenabled(device)); } EXPORT_SYMBOL(kgsl_pre_hwaccess); @@ -1144,7 +1365,7 @@ _sleep(struct kgsl_device *device) _sleep_accounting(device); kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_OFF, KGSL_STATE_SLEEP); kgsl_pwrctrl_set_state(device, KGSL_STATE_SLEEP); - pm_qos_update_request(&device->pm_qos_req_dma, + pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); break; case KGSL_STATE_SLEEP: @@ -1180,7 +1401,7 @@ _slumber(struct kgsl_device *device) device->ftbl->stop(device); _sleep_accounting(device); kgsl_pwrctrl_set_state(device, KGSL_STATE_SLUMBER); - pm_qos_update_request(&device->pm_qos_req_dma, + pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, PM_QOS_DEFAULT_VALUE); break; case KGSL_STATE_SLUMBER: @@ -1265,8 +1486,10 @@ int kgsl_pwrctrl_wake(struct kgsl_device *device) /* Enable state before turning on irq */ kgsl_pwrctrl_set_state(device, KGSL_STATE_ACTIVE); kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON); - pm_qos_update_request(&device->pm_qos_req_dma, - GPU_SWFI_LATENCY); + mod_timer(&device->idle_timer, jiffies + + device->pwrctrl.interval_timeout); + pm_qos_update_request(&device->pwrctrl.pm_qos_req_dma, + device->pwrctrl.pm_qos_latency); case KGSL_STATE_ACTIVE: kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE); break; @@ -1283,8 +1506,10 @@ EXPORT_SYMBOL(kgsl_pwrctrl_wake); void kgsl_pwrctrl_enable(struct kgsl_device *device) { + struct kgsl_pwrctrl *pwr = &device->pwrctrl; /* Order pwrrail/clk sequence based upon platform */ kgsl_pwrctrl_pwrrail(device, KGSL_PWRFLAGS_ON); + kgsl_pwrctrl_pwrlevel_change(device, pwr->default_pwrlevel); kgsl_pwrctrl_clk(device, KGSL_PWRFLAGS_ON, KGSL_STATE_ACTIVE); kgsl_pwrctrl_axi(device, KGSL_PWRFLAGS_ON); } @@ -1365,9 +1590,6 @@ int kgsl_active_count_get(struct kgsl_device *device) mutex_lock(&device->mutex); } - /* Stop the idle timer */ - del_timer_sync(&device->idle_timer); - ret = kgsl_pwrctrl_wake(device); } if (ret == 0) @@ -1418,39 +1640,54 @@ void kgsl_active_count_put(struct kgsl_device *device) kgsl_pwrscale_idle(device); if (atomic_dec_and_test(&device->active_cnt)) { - INIT_COMPLETION(device->suspend_gate); - - if (device->pwrctrl.nap_allowed == true) { - /* Request nap */ + if (device->state == KGSL_STATE_ACTIVE && + device->requested_state == KGSL_STATE_NONE) { kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP); - kgsl_pwrctrl_sleep(device); + if (kgsl_pwrctrl_sleep(device)) { + kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP); + queue_work(device->work_queue, &device->idle_check_ws); + } } mod_timer(&device->idle_timer, jiffies + device->pwrctrl.interval_timeout); - - complete(&device->suspend_gate); } trace_kgsl_active_count(device, (unsigned long) __builtin_return_address(0)); + + wake_up(&device->active_cnt_wq); } EXPORT_SYMBOL(kgsl_active_count_put); +static int _check_active_count(struct kgsl_device *device, int count) +{ + /* Return 0 if the active count is greater than the desired value */ + return atomic_read(&device->active_cnt) > count ? 0 : 1; +} + /** * kgsl_active_count_wait() - Wait for activity to finish. * @device: Pointer to a KGSL device + * @count: Active count value to wait for * - * Block until all active_cnt users put() their reference. + * Block until the active_cnt value hits the desired value */ -void kgsl_active_count_wait(struct kgsl_device *device) +int kgsl_active_count_wait(struct kgsl_device *device, int count) { + int result = 0; + BUG_ON(!mutex_is_locked(&device->mutex)); - if (atomic_read(&device->active_cnt) != 0) { + if (atomic_read(&device->active_cnt) > count) { + int ret; mutex_unlock(&device->mutex); - wait_for_completion(&device->suspend_gate); + ret = wait_event_timeout(device->active_cnt_wq, + _check_active_count(device, count), HZ); mutex_lock(&device->mutex); + result = ret == 0 ? -ETIMEDOUT : 0; } + + return result; } EXPORT_SYMBOL(kgsl_active_count_wait); diff --git a/drivers/gpu/msm/kgsl_pwrctrl.h b/drivers/gpu/msm/kgsl_pwrctrl.h index 94cd8eb5b52..9f181606bd8 100644 --- a/drivers/gpu/msm/kgsl_pwrctrl.h +++ b/drivers/gpu/msm/kgsl_pwrctrl.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, 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 @@ -23,7 +23,9 @@ #define KGSL_PWRLEVEL_NOMINAL 1 #define KGSL_PWRLEVEL_LAST_OFFSET 2 -#define KGSL_MAX_CLKS 5 +#define KGSL_PWR_ON 0xFFFF + +#define KGSL_MAX_CLKS 6 struct platform_device; @@ -47,6 +49,8 @@ struct kgsl_clk_stats { * @pwrlevels - List of supported power levels * @active_pwrlevel - The currently active power level * @thermal_pwrlevel - maximum powerlevel constraint from thermal + * @default_pwrlevel - device wake up power level + * @init_pwrlevel - device inital power level * @max_pwrlevel - maximum allowable powerlevel per the user * @min_pwrlevel - minimum allowable powerlevel per the user * @num_pwrlevels - number of available power levels @@ -55,11 +59,12 @@ struct kgsl_clk_stats { * @gpu_reg - pointer to the regulator structure for gpu_reg * @gpu_cx - pointer to the regulator structure for gpu_cx * @pcl - bus scale identifier - * @nap_allowed - true if the device supports naps * @idle_needed - true if the device needs a idle before clock change * @irq_name - resource name for the IRQ - * @restore_slumber - Flag to indicate that we are in a suspend/restore sequence * @clk_stats - structure of clock statistics + * @pm_qos_req_dma - the power management quality of service structure + * @pm_qos_latency - allowed CPU latency in microseconds + * @step_mul - multiplier for moving between power levels */ struct kgsl_pwrctrl { @@ -67,10 +72,12 @@ struct kgsl_pwrctrl { struct clk *ebi1_clk; struct clk *grp_clks[KGSL_MAX_CLKS]; unsigned long power_flags; + unsigned long ctrl_flags; struct kgsl_pwrlevel pwrlevels[KGSL_MAX_PWRLEVELS]; unsigned int active_pwrlevel; int thermal_pwrlevel; unsigned int default_pwrlevel; + unsigned int init_pwrlevel; unsigned int max_pwrlevel; unsigned int min_pwrlevel; unsigned int num_pwrlevels; @@ -79,12 +86,14 @@ struct kgsl_pwrctrl { struct regulator *gpu_reg; struct regulator *gpu_cx; uint32_t pcl; - unsigned int nap_allowed; unsigned int idle_needed; const char *irq_name; s64 time; - unsigned int restore_slumber; struct kgsl_clk_stats clk_stats; + struct pm_qos_request pm_qos_req_dma; + unsigned int pm_qos_latency; + unsigned int step_mul; + unsigned int irq_last; }; void kgsl_pwrctrl_irq(struct kgsl_device *device, int state); @@ -101,6 +110,8 @@ int kgsl_pwrctrl_init_sysfs(struct kgsl_device *device); void kgsl_pwrctrl_uninit_sysfs(struct kgsl_device *device); void kgsl_pwrctrl_enable(struct kgsl_device *device); void kgsl_pwrctrl_disable(struct kgsl_device *device); +bool kgsl_pwrctrl_isenabled(struct kgsl_device *device); + static inline unsigned long kgsl_get_clkrate(struct clk *clk) { return (clk != NULL) ? clk_get_rate(clk) : 0; @@ -109,9 +120,9 @@ static inline unsigned long kgsl_get_clkrate(struct clk *clk) void kgsl_pwrctrl_set_state(struct kgsl_device *device, unsigned int state); void kgsl_pwrctrl_request_state(struct kgsl_device *device, unsigned int state); -int kgsl_active_count_get(struct kgsl_device *device); -int kgsl_active_count_get_light(struct kgsl_device *device); +int __must_check kgsl_active_count_get(struct kgsl_device *device); +int __must_check kgsl_active_count_get_light(struct kgsl_device *device); void kgsl_active_count_put(struct kgsl_device *device); -void kgsl_active_count_wait(struct kgsl_device *device); +int kgsl_active_count_wait(struct kgsl_device *device, int count); #endif /* __KGSL_PWRCTRL_H */ diff --git a/drivers/gpu/msm/kgsl_pwrscale.c b/drivers/gpu/msm/kgsl_pwrscale.c index 4f7dc5cc271..47554c4fad0 100644 --- a/drivers/gpu/msm/kgsl_pwrscale.c +++ b/drivers/gpu/msm/kgsl_pwrscale.c @@ -47,9 +47,6 @@ static struct kgsl_pwrscale_policy *kgsl_pwrscale_policies[] = { #endif #ifdef CONFIG_MSM_SLEEP_STATS_DEVICE &kgsl_pwrscale_policy_idlestats, -#endif -#ifdef CONFIG_MSM_DCVS - &kgsl_pwrscale_policy_msm, #endif NULL }; @@ -237,17 +234,15 @@ EXPORT_SYMBOL(kgsl_pwrscale_wake); void kgsl_pwrscale_busy(struct kgsl_device *device) { if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->busy) - if (device->requested_state != KGSL_STATE_SLUMBER) - device->pwrscale.policy->busy(device, - &device->pwrscale); + device->pwrscale.policy->busy(device, + &device->pwrscale); } EXPORT_SYMBOL(kgsl_pwrscale_busy); void kgsl_pwrscale_idle(struct kgsl_device *device) { if (PWRSCALE_ACTIVE(device) && device->pwrscale.policy->idle) - if (device->requested_state != KGSL_STATE_SLUMBER && - device->requested_state != KGSL_STATE_SLEEP) + if (device->state == KGSL_STATE_ACTIVE) device->pwrscale.policy->idle(device, &device->pwrscale); } @@ -308,6 +303,8 @@ static void _kgsl_pwrscale_detach_policy(struct kgsl_device *device) kgsl_pwrctrl_pwrlevel_change(device, device->pwrctrl.max_pwrlevel); + device->pwrctrl.default_pwrlevel = + device->pwrctrl.max_pwrlevel; } device->pwrscale.policy = NULL; } @@ -340,6 +337,8 @@ int kgsl_pwrscale_attach_policy(struct kgsl_device *device, device->pwrscale.policy = policy; + device->pwrctrl.default_pwrlevel = + device->pwrctrl.init_pwrlevel; /* Pwrscale is enabled by default at attach time */ kgsl_pwrscale_enable(device); diff --git a/drivers/gpu/msm/kgsl_pwrscale_msm.c b/drivers/gpu/msm/kgsl_pwrscale_msm.c deleted file mode 100644 index 073e474c66b..00000000000 --- a/drivers/gpu/msm/kgsl_pwrscale_msm.c +++ /dev/null @@ -1,269 +0,0 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 and - * only version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include "kgsl.h" -#include "kgsl_pwrscale.h" -#include "kgsl_device.h" -#include "a2xx_reg.h" -#include "kgsl_trace.h" - -struct msm_priv { - struct kgsl_device *device; - int enabled; - unsigned int cur_freq; - unsigned int req_level; - int floor_level; - struct msm_dcvs_core_info *core_info; - int gpu_busy; - int dcvs_core_id; -}; - -/* reference to be used in idle and freq callbacks */ -static struct msm_priv *the_msm_priv; - -static int msm_idle_enable(int type_core_num, - enum msm_core_control_event event) -{ - struct msm_priv *priv = the_msm_priv; - - switch (event) { - case MSM_DCVS_ENABLE_IDLE_PULSE: - priv->enabled = true; - break; - case MSM_DCVS_DISABLE_IDLE_PULSE: - priv->enabled = false; - break; - case MSM_DCVS_ENABLE_HIGH_LATENCY_MODES: - case MSM_DCVS_DISABLE_HIGH_LATENCY_MODES: - break; - } - return 0; -} - -/* Set the requested frequency if it is within 5MHz (delta) of a - * supported frequency. - */ -static int msm_set_freq(int core_num, unsigned int freq) -{ - int i, delta = 5000000; - struct msm_priv *priv = the_msm_priv; - struct kgsl_device *device = priv->device; - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - - /* msm_dcvs manager uses frequencies in kHz */ - freq *= 1000; - for (i = 0; i < pwr->num_pwrlevels; i++) - if (abs(pwr->pwrlevels[i].gpu_freq - freq) < delta) - break; - if (i == pwr->num_pwrlevels) - return 0; - - mutex_lock(&device->mutex); - priv->req_level = i; - if (priv->req_level <= priv->floor_level) { - kgsl_pwrctrl_pwrlevel_change(device, priv->req_level); - priv->cur_freq = pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq; - } - mutex_unlock(&device->mutex); - - /* return current frequency in kHz */ - return priv->cur_freq / 1000; -} - -static int msm_set_min_freq(int core_num, unsigned int freq) -{ - int i, delta = 5000000; - struct msm_priv *priv = the_msm_priv; - struct kgsl_device *device = priv->device; - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - - /* msm_dcvs manager uses frequencies in kHz */ - freq *= 1000; - for (i = 0; i < pwr->num_pwrlevels; i++) - if (abs(pwr->pwrlevels[i].gpu_freq - freq) < delta) - break; - if (i == pwr->num_pwrlevels) - return 0; - - mutex_lock(&device->mutex); - priv->floor_level = i; - if (priv->floor_level <= priv->req_level) - kgsl_pwrctrl_pwrlevel_change(device, priv->floor_level); - else if (priv->floor_level > priv->req_level) - kgsl_pwrctrl_pwrlevel_change(device, priv->req_level); - - priv->cur_freq = pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq; - mutex_unlock(&device->mutex); - - /* return current frequency in kHz */ - return priv->cur_freq / 1000; -} - -static unsigned int msm_get_freq(int core_num) -{ - struct msm_priv *priv = the_msm_priv; - - /* return current frequency in kHz */ - return priv->cur_freq / 1000; -} - -static void msm_busy(struct kgsl_device *device, - struct kgsl_pwrscale *pwrscale) -{ - struct msm_priv *priv = pwrscale->priv; - if (priv->enabled && !priv->gpu_busy) { - msm_dcvs_idle(priv->dcvs_core_id, MSM_DCVS_IDLE_EXIT, 0); - trace_kgsl_mpdcvs(device, 1); - priv->gpu_busy = 1; - } - return; -} - -static void msm_idle(struct kgsl_device *device, - struct kgsl_pwrscale *pwrscale) -{ - struct msm_priv *priv = pwrscale->priv; - - if (priv->enabled && priv->gpu_busy) - if (device->ftbl->isidle(device)) { - msm_dcvs_idle(priv->dcvs_core_id, - MSM_DCVS_IDLE_ENTER, 0); - trace_kgsl_mpdcvs(device, 0); - priv->gpu_busy = 0; - } - return; -} - -static void msm_sleep(struct kgsl_device *device, - struct kgsl_pwrscale *pwrscale) -{ - struct msm_priv *priv = pwrscale->priv; - - if (priv->enabled && priv->gpu_busy) { - msm_dcvs_idle(priv->dcvs_core_id, MSM_DCVS_IDLE_ENTER, 0); - trace_kgsl_mpdcvs(device, 0); - priv->gpu_busy = 0; - } - - return; -} - -static void msm_set_io_fraction(struct kgsl_device *device, - unsigned int value) -{ - int i; - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - - for (i = 0; i < pwr->num_pwrlevels; i++) - pwr->pwrlevels[i].io_fraction = value; - -} - -static void msm_restore_io_fraction(struct kgsl_device *device) -{ - int i; - struct kgsl_device_platform_data *pdata = - kgsl_device_get_drvdata(device); - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - - for (i = 0; i < pdata->num_levels; i++) - pwr->pwrlevels[i].io_fraction = - pdata->pwrlevel[i].io_fraction; -} - -static int msm_init(struct kgsl_device *device, - struct kgsl_pwrscale *pwrscale) -{ - struct msm_priv *priv; - struct msm_dcvs_freq_entry *tbl; - int i, ret = -EINVAL, low_level; - struct kgsl_pwrctrl *pwr = &device->pwrctrl; - struct platform_device *pdev = - container_of(device->parentdev, struct platform_device, dev); - struct kgsl_device_platform_data *pdata = pdev->dev.platform_data; - - if (the_msm_priv) { - priv = pwrscale->priv = the_msm_priv; - } else { - priv = pwrscale->priv = kzalloc(sizeof(struct msm_priv), - GFP_KERNEL); - if (pwrscale->priv == NULL) - return -ENOMEM; - - priv->core_info = pdata->core_info; - tbl = priv->core_info->freq_tbl; - priv->floor_level = pwr->num_pwrlevels - 1; - /* Fill in frequency table from low to high, reversing order. */ - low_level = pwr->num_pwrlevels - KGSL_PWRLEVEL_LAST_OFFSET; - for (i = 0; i <= low_level; i++) - tbl[i].freq = - pwr->pwrlevels[low_level - i].gpu_freq / 1000; - priv->dcvs_core_id = - msm_dcvs_register_core(MSM_DCVS_CORE_TYPE_GPU, - 0, - priv->core_info, - msm_set_freq, msm_get_freq, msm_idle_enable, - msm_set_min_freq, - priv->core_info->sensors[0]); - if (priv->dcvs_core_id < 0) { - KGSL_PWR_ERR(device, "msm_dcvs_register_core failed"); - goto err; - } - the_msm_priv = priv; - } - priv->device = device; - ret = msm_dcvs_freq_sink_start(priv->dcvs_core_id); - if (ret >= 0) { - if (device->ftbl->isidle(device)) { - priv->gpu_busy = 0; - msm_dcvs_idle(priv->dcvs_core_id, - MSM_DCVS_IDLE_ENTER, 0); - } else { - priv->gpu_busy = 1; - } - msm_set_io_fraction(device, 0); - return 0; - } - - KGSL_PWR_ERR(device, "msm_dcvs_freq_sink_register failed\n"); - -err: - if (!the_msm_priv) - kfree(pwrscale->priv); - pwrscale->priv = NULL; - - return ret; -} - -static void msm_close(struct kgsl_device *device, - struct kgsl_pwrscale *pwrscale) -{ - struct msm_priv *priv = pwrscale->priv; - - if (pwrscale->priv == NULL) - return; - msm_dcvs_freq_sink_stop(priv->dcvs_core_id); - pwrscale->priv = NULL; - msm_restore_io_fraction(device); -} - -struct kgsl_pwrscale_policy kgsl_pwrscale_policy_msm = { - .name = "msm", - .init = msm_init, - .idle = msm_idle, - .busy = msm_busy, - .sleep = msm_sleep, - .close = msm_close, -}; diff --git a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c index aa6861e6ec4..0f42df7871f 100644 --- a/drivers/gpu/msm/kgsl_pwrscale_trustzone.c +++ b/drivers/gpu/msm/kgsl_pwrscale_trustzone.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2010-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2010-2013, 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 @@ -8,7 +8,6 @@ * 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 @@ -18,6 +17,8 @@ #include #include #include +#include +#include #include "kgsl.h" #include "kgsl_pwrscale.h" @@ -25,6 +26,7 @@ #define TZ_GOVERNOR_PERFORMANCE 0 #define TZ_GOVERNOR_ONDEMAND 1 +#define TZ_GOVERNOR_INTERACTIVE 2 struct tz_priv { int governor; @@ -38,12 +40,15 @@ spinlock_t tz_lock; * per frame for 60fps content. */ #define FLOOR 5000 -#define SWITCH_OFF 200 -#define SWITCH_OFF_RESET_TH 40 -#define SKIP_COUNTER 500 +/* CEILING is 50msec, larger than any standard + * frame length, but less than the idle timer. + */ +#define CEILING 50000 + #define TZ_RESET_ID 0x3 #define TZ_UPDATE_ID 0x4 +#if 0 #ifdef CONFIG_MSM_SCM /* Trap into the TrustZone, and call funcs there. */ static int __secure_tz_entry(u32 cmd, u32 val, u32 id) @@ -61,6 +66,24 @@ static int __secure_tz_entry(u32 cmd, u32 val, u32 id) return 0; } #endif /* CONFIG_MSM_SCM */ +#endif + +unsigned int up_threshold = 50; +unsigned int down_threshold = 25; +unsigned int up_differential = 10; +bool debug = 0; + +module_param(up_threshold, int, 0664); +module_param(down_threshold, int, 0664); +module_param(debug, bool, 0664); + +static struct clk_scaling_stats { + unsigned long threshold; + unsigned int load; +} gpu_stats = { + .threshold = 0, + .load = 0, +}; static ssize_t tz_governor_show(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale, @@ -71,6 +94,8 @@ static ssize_t tz_governor_show(struct kgsl_device *device, if (priv->governor == TZ_GOVERNOR_ONDEMAND) ret = snprintf(buf, 10, "ondemand\n"); + else if (priv->governor == TZ_GOVERNOR_INTERACTIVE) + ret = snprintf(buf, 13, "interactive\n"); else ret = snprintf(buf, 13, "performance\n"); @@ -94,11 +119,17 @@ static ssize_t tz_governor_store(struct kgsl_device *device, if (!strncmp(str, "ondemand", 8)) priv->governor = TZ_GOVERNOR_ONDEMAND; + else if (!strncmp(str, "interactive", 11)) + priv->governor = TZ_GOVERNOR_INTERACTIVE; else if (!strncmp(str, "performance", 11)) priv->governor = TZ_GOVERNOR_PERFORMANCE; - if (priv->governor == TZ_GOVERNOR_PERFORMANCE) + if (priv->governor == TZ_GOVERNOR_PERFORMANCE) { kgsl_pwrctrl_pwrlevel_change(device, pwr->max_pwrlevel); + pwr->default_pwrlevel = pwr->max_pwrlevel; + } else { + pwr->default_pwrlevel = pwr->init_pwrlevel; + } mutex_unlock(&device->mutex); return count; @@ -117,11 +148,7 @@ static struct attribute_group tz_attr_group = { static void tz_wake(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { - struct tz_priv *priv = pwrscale->priv; - if (device->state != KGSL_STATE_NAP && - priv->governor == TZ_GOVERNOR_ONDEMAND) - kgsl_pwrctrl_pwrlevel_change(device, - device->pwrctrl.default_pwrlevel); + return; } static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) @@ -129,7 +156,6 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct tz_priv *priv = pwrscale->priv; struct kgsl_power_stats stats; - int val, idle; /* In "performance" mode the clock speed always stays the same */ @@ -137,40 +163,63 @@ static void tz_idle(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) return; device->ftbl->power_stats(device, &stats); + priv->bin.total_time += stats.total_time; priv->bin.busy_time += stats.busy_time; - /* Do not waste CPU cycles running this algorithm if - * the GPU just started, or if less than FLOOR time - * has passed since the last run. - */ - if ((stats.total_time == 0) || - (priv->bin.total_time < FLOOR)) + + if (stats.total_time == 0 || priv->bin.busy_time < FLOOR) return; - /* If the GPU has stayed in turbo mode for a while, * - * stop writing out values. */ - if (pwr->active_pwrlevel == 0) { - if (priv->no_switch_cnt > SWITCH_OFF) { - priv->skip_cnt++; - if (priv->skip_cnt > SKIP_COUNTER) { - priv->no_switch_cnt -= SWITCH_OFF_RESET_TH; - priv->skip_cnt = 0; - } - return; - } - priv->no_switch_cnt++; - } else { - priv->no_switch_cnt = 0; + if (stats.busy_time >= 1 << 24 || stats.total_time >= 1 << 24) + { + stats.busy_time >>= 7; + stats.total_time >>= 7; } - idle = priv->bin.total_time - priv->bin.busy_time; + /* + * If there is an extended block of busy processing, + * increase frequency. Otherwise run the normal algorithm. + */ + if (priv->bin.busy_time > CEILING) + { + kgsl_pwrctrl_pwrlevel_change(device, pwr->max_pwrlevel); + goto clear; + } + + gpu_stats.load = (100 * priv->bin.busy_time); + do_div(gpu_stats.load, priv->bin.total_time); + + if (debug) + { + pr_info("GPU load: %u\n", gpu_stats.load); + pr_info("GPU frequency: %d\n", + pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); + } + + gpu_stats.threshold = up_threshold; + + if (pwr->active_pwrlevel == pwr->min_pwrlevel) + gpu_stats.threshold = up_threshold / pwr->active_pwrlevel; + else if (pwr->active_pwrlevel < pwr->min_pwrlevel && + pwr->active_pwrlevel > pwr->max_pwrlevel) + gpu_stats.threshold = up_threshold - up_differential; + + if (gpu_stats.load > gpu_stats.threshold) + { + if (pwr->active_pwrlevel > pwr->max_pwrlevel) + kgsl_pwrctrl_pwrlevel_change(device, + pwr->active_pwrlevel - 1); + } + else if (gpu_stats.load < down_threshold) + { + if (pwr->active_pwrlevel < pwr->min_pwrlevel) + kgsl_pwrctrl_pwrlevel_change(device, + pwr->active_pwrlevel + 1); + } + +clear: priv->bin.total_time = 0; priv->bin.busy_time = 0; - idle = (idle > 0) ? idle : 0; - val = __secure_tz_entry(TZ_UPDATE_ID, idle, device->id); - if (val) - kgsl_pwrctrl_pwrlevel_change(device, - pwr->active_pwrlevel + val); } static void tz_busy(struct kgsl_device *device, @@ -183,9 +232,16 @@ static void tz_sleep(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) { struct tz_priv *priv = pwrscale->priv; + struct kgsl_pwrctrl *pwr = &device->pwrctrl; + + kgsl_pwrctrl_pwrlevel_change(device, pwr->min_pwrlevel); + + if (debug) + { + pr_info("GPU sleep frequency: %d\n", + pwr->pwrlevels[pwr->active_pwrlevel].gpu_freq); + } - __secure_tz_entry(TZ_RESET_ID, 0, device->id); - priv->no_switch_cnt = 0; priv->bin.total_time = 0; priv->bin.busy_time = 0; } @@ -199,7 +255,7 @@ static int tz_init(struct kgsl_device *device, struct kgsl_pwrscale *pwrscale) if (pwrscale->priv == NULL) return -ENOMEM; - priv->governor = TZ_GOVERNOR_ONDEMAND; + priv->governor = TZ_GOVERNOR_INTERACTIVE; spin_lock_init(&tz_lock); kgsl_pwrscale_policy_add_files(device, pwrscale, &tz_attr_group); @@ -229,3 +285,4 @@ struct kgsl_pwrscale_policy kgsl_pwrscale_policy_tz = { .close = tz_close }; EXPORT_SYMBOL(kgsl_pwrscale_policy_tz); + diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index ed80b198b82..4f05780bc32 100755 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2013, 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 @@ -24,6 +24,8 @@ #include "kgsl_cffdump.h" #include "kgsl_device.h" +DEFINE_MUTEX(kernel_map_global_lock); + /* An attribute for showing per-process memory statistics */ struct kgsl_mem_entry_attribute { struct attribute attr; @@ -146,9 +148,7 @@ static struct kobj_type ktype_mem_entry = { static struct mem_entry_stats mem_stats[] = { MEM_ENTRY_STAT(KGSL_MEM_ENTRY_KERNEL, kernel), -#ifdef CONFIG_ANDROID_PMEM MEM_ENTRY_STAT(KGSL_MEM_ENTRY_PMEM, pmem), -#endif #ifdef CONFIG_ASHMEM MEM_ENTRY_STAT(KGSL_MEM_ENTRY_ASHMEM, ashmem), #endif @@ -172,17 +172,32 @@ kgsl_process_uninit_sysfs(struct kgsl_process_private *private) kobject_put(&private->kobj); } -void -kgsl_process_init_sysfs(struct kgsl_process_private *private) +/** + * kgsl_process_init_sysfs() - Initialize and create sysfs files for a process + * + * @device: Pointer to kgsl device struct + * @private: Pointer to the structure for the process + * + * @returns: 0 on success, error code otherwise + * + * kgsl_process_init_sysfs() is called at the time of creating the + * process struct when a process opens the kgsl device for the first time. + * This function creates the sysfs files for the process. + */ +int +kgsl_process_init_sysfs(struct kgsl_device *device, + struct kgsl_process_private *private) { unsigned char name[16]; - int i, ret; + int i, ret = 0; snprintf(name, sizeof(name), "%d", private->pid); - if (kobject_init_and_add(&private->kobj, &ktype_mem_entry, - kgsl_driver.prockobj, name)) - return; + ret = kobject_init_and_add(&private->kobj, &ktype_mem_entry, + kgsl_driver.prockobj, name); + + if (ret) + return ret; for (i = 0; i < ARRAY_SIZE(mem_stats); i++) { /* We need to check the value of sysfs_create_file, but we @@ -193,6 +208,7 @@ kgsl_process_init_sysfs(struct kgsl_process_private *private) ret = sysfs_create_file(&private->kobj, &mem_stats[i].max_attr.attr); } + return ret; } static int kgsl_drv_memstat_show(struct device *dev, @@ -379,6 +395,35 @@ static int kgsl_page_alloc_vmflags(struct kgsl_memdesc *memdesc) return VM_RESERVED | VM_DONTEXPAND; } +static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc) +{ + return VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND; +} + +/* + * kgsl_page_alloc_unmap_kernel() - Unmap the memory in memdesc + * + * @memdesc: The memory descriptor which contains information about the memory + * + * Unmaps the memory mapped into kernel address space + */ +static void kgsl_page_alloc_unmap_kernel(struct kgsl_memdesc *memdesc) +{ + mutex_lock(&kernel_map_global_lock); + if (!memdesc->hostptr) { + BUG_ON(memdesc->hostptr_count); + goto done; + } + memdesc->hostptr_count--; + if (memdesc->hostptr_count) + goto done; + vunmap(memdesc->hostptr); + kgsl_driver.stats.vmalloc -= memdesc->size; + memdesc->hostptr = NULL; +done: + mutex_unlock(&kernel_map_global_lock); +} + static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc) { int i = 0; @@ -387,21 +432,13 @@ static void kgsl_page_alloc_free(struct kgsl_memdesc *memdesc) kgsl_driver.stats.page_alloc -= memdesc->size; - if (memdesc->hostptr) { - vunmap(memdesc->hostptr); - kgsl_driver.stats.vmalloc -= memdesc->size; - } + kgsl_page_alloc_unmap_kernel(memdesc); + /* we certainly do not expect the hostptr to still be mapped */ + BUG_ON(memdesc->hostptr); + if (memdesc->sg) - for_each_sg(memdesc->sg, sg, sglen, i){ - if (sg->length == 0) - break; + for_each_sg(memdesc->sg, sg, sglen, i) __free_pages(sg_page(sg), get_order(sg->length)); - } -} - -static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc) -{ - return VM_RESERVED | VM_IO | VM_PFNMAP | VM_DONTEXPAND; } /* @@ -414,6 +451,9 @@ static int kgsl_contiguous_vmflags(struct kgsl_memdesc *memdesc) */ static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc) { + int ret = 0; + + mutex_lock(&kernel_map_global_lock); if (!memdesc->hostptr) { pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL); struct page **pages = NULL; @@ -427,7 +467,8 @@ static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc) if (!pages) { KGSL_CORE_ERR("vmalloc(%d) failed\n", npages * sizeof(struct page *)); - return -ENOMEM; + ret = -ENOMEM; + goto done; } for_each_sg(memdesc->sg, sg, sglen, i) { @@ -441,14 +482,19 @@ static int kgsl_page_alloc_map_kernel(struct kgsl_memdesc *memdesc) memdesc->hostptr = vmap(pages, count, VM_IOREMAP, page_prot); - KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.vmalloc, + if (memdesc->hostptr) + KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.vmalloc, kgsl_driver.stats.vmalloc_max); + else + ret = -ENOMEM; vfree(pages); } - if (!memdesc->hostptr) - return -ENOMEM; + if (memdesc->hostptr) + memdesc->hostptr_count++; +done: + mutex_unlock(&kernel_map_global_lock); - return 0; + return ret; } static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc, @@ -472,28 +518,51 @@ static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc, return VM_FAULT_NOPAGE; } +static void kgsl_ebimem_unmap_kernel(struct kgsl_memdesc *memdesc) +{ + mutex_lock(&kernel_map_global_lock); + if (!memdesc->hostptr) { + BUG_ON(memdesc->hostptr_count); + goto done; + } + memdesc->hostptr_count--; + if (memdesc->hostptr_count) + goto done; + + iounmap(memdesc->hostptr); + memdesc->hostptr = NULL; +done: + mutex_unlock(&kernel_map_global_lock); +} + static void kgsl_ebimem_free(struct kgsl_memdesc *memdesc) { kgsl_driver.stats.coherent -= memdesc->size; - if (memdesc->hostptr) - iounmap(memdesc->hostptr); + kgsl_ebimem_unmap_kernel(memdesc); + /* we certainly do not expect the hostptr to still be mapped */ + BUG_ON(memdesc->hostptr); free_contiguous_memory_by_paddr(memdesc->physaddr); } static int kgsl_ebimem_map_kernel(struct kgsl_memdesc *memdesc) { + int ret = 0; + mutex_lock(&kernel_map_global_lock); if (!memdesc->hostptr) { memdesc->hostptr = ioremap(memdesc->physaddr, memdesc->size); if (!memdesc->hostptr) { KGSL_CORE_ERR("ioremap failed, addr:0x%p, size:0x%x\n", memdesc->hostptr, memdesc->size); - return -ENOMEM; + ret = -ENOMEM; + goto done; } } - - return 0; + memdesc->hostptr_count++; +done: + mutex_unlock(&kernel_map_global_lock); + return ret; } static void kgsl_coherent_free(struct kgsl_memdesc *memdesc) @@ -508,7 +577,8 @@ struct kgsl_memdesc_ops kgsl_page_alloc_ops = { .free = kgsl_page_alloc_free, .vmflags = kgsl_page_alloc_vmflags, .vmfault = kgsl_page_alloc_vmfault, - .map_kernel_mem = kgsl_page_alloc_map_kernel, + .map_kernel = kgsl_page_alloc_map_kernel, + .unmap_kernel = kgsl_page_alloc_unmap_kernel, }; EXPORT_SYMBOL(kgsl_page_alloc_ops); @@ -516,7 +586,8 @@ static struct kgsl_memdesc_ops kgsl_ebimem_ops = { .free = kgsl_ebimem_free, .vmflags = kgsl_contiguous_vmflags, .vmfault = kgsl_contiguous_vmfault, - .map_kernel_mem = kgsl_ebimem_map_kernel, + .map_kernel = kgsl_ebimem_map_kernel, + .unmap_kernel = kgsl_ebimem_unmap_kernel, }; static struct kgsl_memdesc_ops kgsl_coherent_ops = { @@ -563,6 +634,7 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, pgprot_t page_prot = pgprot_writecombine(PAGE_KERNEL); void *ptr; unsigned int align; + int step = ((VMALLOC_END - VMALLOC_START)/8) >> PAGE_SHIFT; align = (memdesc->flags & KGSL_MEMALIGN_MASK) >> KGSL_MEMALIGN_SHIFT; @@ -579,39 +651,38 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, sglen_alloc = PAGE_ALIGN(size) >> PAGE_SHIFT; - memdesc->size = size; memdesc->pagetable = pagetable; memdesc->ops = &kgsl_page_alloc_ops; - memdesc->sg = kgsl_sg_alloc(sglen_alloc); + memdesc->sglen_alloc = sglen_alloc; + memdesc->sg = kgsl_sg_alloc(memdesc->sglen_alloc); if (memdesc->sg == NULL) { - KGSL_CORE_ERR("vmalloc(%d) failed\n", - sglen_alloc * sizeof(struct scatterlist)); ret = -ENOMEM; goto done; } /* * Allocate space to store the list of pages to send to vmap. - * This is an array of pointers so we can track 1024 pages per page of - * allocation which means we can handle up to a 8MB buffer request with - * two pages; well within the acceptable limits for using kmalloc. + * This is an array of pointers so we can t rack 1024 pages per page + * of allocation. Since allocations can be as large as the user dares, + * we have to use the kmalloc/vmalloc trick here to make sure we can + * get the memory we need. */ - pages = kmalloc(sglen_alloc * sizeof(struct page *), GFP_KERNEL); + if ((memdesc->sglen_alloc * sizeof(struct page *)) > PAGE_SIZE) + pages = vmalloc(memdesc->sglen_alloc * sizeof(struct page *)); + else + pages = kmalloc(PAGE_SIZE, GFP_KERNEL); if (pages == NULL) { - KGSL_CORE_ERR("kmalloc (%d) failed\n", - sglen_alloc * sizeof(struct page *)); ret = -ENOMEM; goto done; } kmemleak_not_leak(memdesc->sg); - memdesc->sglen_alloc = sglen_alloc; - sg_init_table(memdesc->sg, sglen_alloc); + sg_init_table(memdesc->sg, memdesc->sglen_alloc); len = size; @@ -632,7 +703,7 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, gfp_mask |= __GFP_COMP | __GFP_NORETRY | __GFP_NO_KSWAPD | __GFP_NOWARN; else - gfp_mask |= GFP_KERNEL | __GFP_NORETRY; + gfp_mask |= GFP_KERNEL; page = alloc_pages(gfp_mask, get_order(page_size)); @@ -642,6 +713,14 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, continue; } + /* + * Update sglen and memdesc size,as requested allocation + * not served fully. So that they can be correctly freed + * in kgsl_sharedmem_free(). + */ + memdesc->sglen = sglen; + memdesc->size = (size - len); + KGSL_CORE_ERR( "Out of memory: only allocated %dKB of %dKB requested\n", (size - len) >> 10, size >> 10); @@ -658,6 +737,7 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, } memdesc->sglen = sglen; + memdesc->size = size; /* * All memory that goes to the user has to be zeroed out before it gets @@ -668,46 +748,55 @@ _kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, * zeroed and unmaped each individual page, and then we had to turn * around and call flush_dcache_page() on that page to clear the caches. * This was killing us for performance. Instead, we found it is much - * faster to allocate the pages without GFP_ZERO, map the entire range, - * memset it, flush the range and then unmap - this results in a factor - * of 4 improvement for speed for large buffers. There is a small - * increase in speed for small buffers, but only on the order of a few - * microseconds at best. The only downside is that there needs to be - * enough temporary space in vmalloc to accomodate the map. This - * shouldn't be a problem, but if it happens, fall back to a much slower - * path + * faster to allocate the pages without GFP_ZERO, map a chunk of the + * range ('step' pages), memset it, flush it and then unmap + * - this results in a factor of 4 improvement for speed for large + * buffers. There is a small decrease in speed for small buffers, + * but only on the order of a few microseconds at best. The 'step' + * size is based on a guess at the amount of free vmalloc space, but + * will scale down if there's not enough free space. */ - - ptr = vmap(pages, pcount, VM_IOREMAP, page_prot); - - if (ptr != NULL) { - memset(ptr, 0, memdesc->size); - dmac_flush_range(ptr, ptr + memdesc->size); - vunmap(ptr); - } else { - /* Very, very, very slow path */ - - for (j = 0; j < pcount; j++) { - ptr = kmap_atomic(pages[j]); - memset(ptr, 0, PAGE_SIZE); - dmac_flush_range(ptr, ptr + PAGE_SIZE); - kunmap_atomic(ptr); + for (j = 0; j < pcount; j += step) { + step = min(step, pcount - j); + + ptr = vmap(&pages[j], step, VM_IOREMAP, page_prot); + + if (ptr != NULL) { + memset(ptr, 0, step * PAGE_SIZE); + dmac_flush_range(ptr, ptr + step * PAGE_SIZE); + vunmap(ptr); + } else { + int k; + /* Very, very, very slow path */ + + for (k = j; k < j + step; k++) { + ptr = kmap_atomic(pages[k]); + memset(ptr, 0, PAGE_SIZE); + dmac_flush_range(ptr, ptr + PAGE_SIZE); + kunmap_atomic(ptr); + } + /* scale down the step size to avoid this path */ + if (step > 1) + step >>= 1; } } outer_cache_range_op_sg(memdesc->sg, memdesc->sglen, KGSL_CACHE_OP_FLUSH); - KGSL_STATS_ADD(size, kgsl_driver.stats.page_alloc, - kgsl_driver.stats.page_alloc_max); - order = get_order(size); if (order < 16) kgsl_driver.stats.histogram[order]++; done: - kfree(pages); + KGSL_STATS_ADD(memdesc->size, kgsl_driver.stats.page_alloc, + kgsl_driver.stats.page_alloc_max); + + if ((memdesc->sglen_alloc * sizeof(struct page *)) > PAGE_SIZE) + vfree(pages); + else + kfree(pages); if (ret) kgsl_sharedmem_free(memdesc); @@ -723,6 +812,8 @@ kgsl_sharedmem_page_alloc(struct kgsl_memdesc *memdesc, BUG_ON(size == 0); size = ALIGN(size, PAGE_SIZE * 2); + if (size == 0) + return -EINVAL; ret = _kgsl_sharedmem_page_alloc(memdesc, pagetable, size); if (!ret) @@ -738,7 +829,11 @@ kgsl_sharedmem_page_alloc_user(struct kgsl_memdesc *memdesc, struct kgsl_pagetable *pagetable, size_t size) { - return _kgsl_sharedmem_page_alloc(memdesc, pagetable, PAGE_ALIGN(size)); + size = PAGE_ALIGN(size); + if (size == 0) + return -EINVAL; + + return _kgsl_sharedmem_page_alloc(memdesc, pagetable, size); } EXPORT_SYMBOL(kgsl_sharedmem_page_alloc_user); @@ -748,6 +843,8 @@ kgsl_sharedmem_alloc_coherent(struct kgsl_memdesc *memdesc, size_t size) int result = 0; size = ALIGN(size, PAGE_SIZE); + if (size == 0) + return -EINVAL; memdesc->size = size; memdesc->ops = &kgsl_coherent_ops; @@ -782,8 +879,10 @@ void kgsl_sharedmem_free(struct kgsl_memdesc *memdesc) if (memdesc == NULL || memdesc->size == 0) return; - if (memdesc->gpuaddr) + if (memdesc->gpuaddr) { kgsl_mmu_unmap(memdesc->pagetable, memdesc); + kgsl_mmu_put_gpuaddr(memdesc->pagetable, memdesc); + } if (memdesc->ops && memdesc->ops->free) memdesc->ops->free(memdesc); @@ -832,6 +931,9 @@ kgsl_sharedmem_ebimem_user(struct kgsl_memdesc *memdesc, size_t size) { size = ALIGN(size, PAGE_SIZE); + if (size == 0) + return -EINVAL; + return _kgsl_sharedmem_ebimem(memdesc, pagetable, size); } EXPORT_SYMBOL(kgsl_sharedmem_ebimem_user); @@ -842,17 +944,20 @@ kgsl_sharedmem_ebimem(struct kgsl_memdesc *memdesc, { int result; size = ALIGN(size, 8192); + if (size == 0) + return -EINVAL; + result = _kgsl_sharedmem_ebimem(memdesc, pagetable, size); if (result) return result; - memdesc->hostptr = ioremap(memdesc->physaddr, size); + result = kgsl_ebimem_map_kernel(memdesc); - if (memdesc->hostptr == NULL) { - KGSL_CORE_ERR("ioremap failed\n"); + if (result) { + KGSL_CORE_ERR("hostptr mapping failed\n"); kgsl_sharedmem_free(memdesc); - return -ENOMEM; + return result; } return 0; @@ -880,7 +985,8 @@ kgsl_sharedmem_readl(const struct kgsl_memdesc *memdesc, EXPORT_SYMBOL(kgsl_sharedmem_readl); int -kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc, +kgsl_sharedmem_writel(struct kgsl_device *device, + const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, uint32_t src) { @@ -893,7 +999,8 @@ kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc, WARN_ON(offsetbytes + sizeof(uint32_t) > memdesc->size); if (offsetbytes + sizeof(uint32_t) > memdesc->size) return -ERANGE; - kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes, + kgsl_cffdump_setmem(device, + memdesc->gpuaddr + offsetbytes, src, sizeof(uint32_t)); dst = (uint32_t *)(memdesc->hostptr + offsetbytes); *dst = src; @@ -902,14 +1009,16 @@ kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc, EXPORT_SYMBOL(kgsl_sharedmem_writel); int -kgsl_sharedmem_set(const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, - unsigned int value, unsigned int sizebytes) +kgsl_sharedmem_set(struct kgsl_device *device, + const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, + unsigned int value, unsigned int sizebytes) { BUG_ON(memdesc == NULL || memdesc->hostptr == NULL); BUG_ON(offsetbytes + sizebytes > memdesc->size); - kgsl_cffdump_setmem(memdesc->gpuaddr + offsetbytes, value, - sizebytes); + kgsl_cffdump_setmem(device, + memdesc->gpuaddr + offsetbytes, value, + sizebytes); memset(memdesc->hostptr + offsetbytes, value, sizebytes); return 0; } diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h index c000cbb6df6..4a43d148097 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.h +++ b/drivers/gpu/msm/kgsl_sharedmem.h @@ -55,17 +55,20 @@ int kgsl_sharedmem_readl(const struct kgsl_memdesc *memdesc, uint32_t *dst, unsigned int offsetbytes); -int kgsl_sharedmem_writel(const struct kgsl_memdesc *memdesc, +int kgsl_sharedmem_writel(struct kgsl_device *device, + const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, uint32_t src); -int kgsl_sharedmem_set(const struct kgsl_memdesc *memdesc, +int kgsl_sharedmem_set(struct kgsl_device *device, + const struct kgsl_memdesc *memdesc, unsigned int offsetbytes, unsigned int value, unsigned int sizebytes); void kgsl_cache_range_op(struct kgsl_memdesc *memdesc, int op); -void kgsl_process_init_sysfs(struct kgsl_process_private *private); +int kgsl_process_init_sysfs(struct kgsl_device *device, + struct kgsl_process_private *private); void kgsl_process_uninit_sysfs(struct kgsl_process_private *private); int kgsl_sharedmem_init_sysfs(void); @@ -138,6 +141,9 @@ kgsl_sharedmem_map_vma(struct vm_area_struct *vma, static inline void *kgsl_sg_alloc(unsigned int sglen) { + if ((sglen == 0) || (sglen >= ULONG_MAX / sizeof(struct scatterlist))) + return NULL; + if ((sglen * sizeof(struct scatterlist)) < PAGE_SIZE) return kzalloc(sglen * sizeof(struct scatterlist), GFP_KERNEL); else { @@ -159,7 +165,7 @@ static inline void kgsl_sg_free(void *ptr, unsigned int sglen) static inline int memdesc_sg_phys(struct kgsl_memdesc *memdesc, - unsigned int physaddr, unsigned int size) + phys_addr_t physaddr, unsigned int size) { memdesc->sg = kgsl_sg_alloc(1); if (!memdesc->sg) @@ -263,6 +269,11 @@ kgsl_allocate(struct kgsl_memdesc *memdesc, ret = kgsl_sharedmem_page_alloc(memdesc, pagetable, size); if (ret) return ret; + ret = kgsl_mmu_get_gpuaddr(pagetable, memdesc); + if (ret) { + kgsl_sharedmem_free(memdesc); + return ret; + } ret = kgsl_mmu_map(pagetable, memdesc); if (ret) kgsl_sharedmem_free(memdesc); diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c index 50ac9c1bd34..a81e19c520a 100644 --- a/drivers/gpu/msm/kgsl_snapshot.c +++ b/drivers/gpu/msm/kgsl_snapshot.c @@ -22,12 +22,13 @@ #include "kgsl_device.h" #include "kgsl_sharedmem.h" #include "kgsl_snapshot.h" +#include "adreno_cp_parser.h" /* Placeholder for the list of memory objects frozen after a hang */ struct kgsl_snapshot_object { unsigned int gpuaddr; - unsigned int ptbase; + phys_addr_t ptbase; unsigned int size; unsigned int offset; int type; @@ -35,6 +36,14 @@ struct kgsl_snapshot_object { struct list_head node; }; +/* Placeholder for list of ib objects that contain all objects in that IB */ + +struct kgsl_snapshot_cp_obj { + struct adreno_ib_object_list *ib_obj_list; + unsigned int ptbase; + struct list_head node; +}; + struct snapshot_obj_itr { void *buf; /* Buffer pointer to write to */ int pos; /* Current position in the sequence */ @@ -140,6 +149,7 @@ static int snapshot_os(struct kgsl_device *device, int hang = (int) priv; int ctxtcount = 0; int size = sizeof(*header); + phys_addr_t temp_ptbase; /* Figure out how many active contexts there are - these will * be appended on the end of the structure */ @@ -183,11 +193,14 @@ static int snapshot_os(struct kgsl_device *device, kgsl_sharedmem_readl(&device->memstore, &header->current_context, KGSL_MEMSTORE_OFFSET(KGSL_MEMSTORE_GLOBAL, current_context)); + /* Get the current PT base */ - header->ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); + temp_ptbase = kgsl_mmu_get_current_ptbase(&device->mmu); + /* Truncate to 32 bits in case LPAE is used */ + header->ptbase = (__u32)temp_ptbase; /* And the PID for the task leader */ pid = header->pid = kgsl_mmu_get_ptname_from_ptbase(&device->mmu, - header->ptbase); + temp_ptbase); task = find_task_by_vpid(pid); @@ -258,6 +271,12 @@ static int kgsl_snapshot_dump_object(struct kgsl_device *device, struct kgsl_snapshot_gpu_object header; int ret; + if (kgsl_memdesc_map(&obj->entry->memdesc) == NULL) { + KGSL_DRV_ERR(device, "Unable to map GPU buffer %X\n", + obj->gpuaddr); + return 0; + } + sect.magic = SNAPSHOT_SECTION_MAGIC; sect.id = KGSL_SNAPSHOT_SECTION_GPU_OBJECT; @@ -270,21 +289,21 @@ static int kgsl_snapshot_dump_object(struct kgsl_device *device, ret = obj_itr_out(itr, §, sizeof(sect)); if (ret == 0) - return 0; + goto done; header.size = ALIGN(obj->size, 4) >> 2; header.gpuaddr = obj->gpuaddr; - header.ptbase = obj->ptbase; + header.ptbase = (__u32)obj->ptbase; header.type = obj->type; ret = obj_itr_out(itr, &header, sizeof(header)); if (ret == 0) - return 0; + goto done; ret = obj_itr_out(itr, obj->entry->memdesc.hostptr + obj->offset, obj->size); if (ret == 0) - return 0; + goto done; /* Pad the end to a dword boundary if we need to */ @@ -292,7 +311,8 @@ static int kgsl_snapshot_dump_object(struct kgsl_device *device, unsigned int dummy = 0; ret = obj_itr_out(itr, &dummy, obj->size % 4); } - +done: + kgsl_memdesc_unmap(&obj->entry->memdesc); return ret; } @@ -307,6 +327,32 @@ static void kgsl_snapshot_put_object(struct kgsl_device *device, kfree(obj); } +/* + * ksgl_snapshot_find_object() - Return the snapshot object pointer + * for given address range + * @device: the device that is being snapshotted + * @ptbase: the pagetable base of the object to search + * @gpuaddr: The gpu address of the object to search + * @size: the size of the object (may not always be the size of the region) + * + * Return the object pointer if found else NULL + */ +struct kgsl_snapshot_object *kgsl_snapshot_find_object( + struct kgsl_device *device, + phys_addr_t ptbase, unsigned int gpuaddr, + unsigned int size) +{ + struct kgsl_snapshot_object *obj = NULL; + list_for_each_entry(obj, &device->snapshot_obj_list, node) { + if (obj->ptbase != ptbase) + continue; + if ((gpuaddr >= obj->gpuaddr) && + ((gpuaddr + size) <= (obj->gpuaddr + obj->size))) + return obj; + } + return NULL; +} + /* ksgl_snapshot_have_object - Return 1 if the object has been processed *@device - the device that is being snapshotted * @ptbase - the pagetable base of the object to freeze @@ -316,7 +362,7 @@ static void kgsl_snapshot_put_object(struct kgsl_device *device, * Return 1 if the object is already in the list - this can save us from * having to parse the sme thing over again. */ -int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase, +int kgsl_snapshot_have_object(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size) { struct kgsl_snapshot_object *obj; @@ -346,13 +392,14 @@ EXPORT_SYMBOL(kgsl_snapshot_have_object); * size of the object being frozen */ -int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase, +int kgsl_snapshot_get_object(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size, unsigned int type) { struct kgsl_mem_entry *entry; struct kgsl_snapshot_object *obj; int offset; int ret = -EINVAL; + unsigned int mem_type; if (!gpuaddr) return 0; @@ -371,6 +418,18 @@ int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase, "Only internal GPU buffers can be frozen\n"); goto err_put; } + /* + * Do not save texture and render targets in snapshot, + * they can be just too big + */ + mem_type = (entry->memdesc.flags & KGSL_MEMTYPE_MASK) >> + KGSL_MEMTYPE_SHIFT; + if (KGSL_MEMTYPE_TEXTURE == mem_type || + KGSL_MEMTYPE_EGL_SURFACE == mem_type || + KGSL_MEMTYPE_EGL_IMAGE == mem_type) { + ret = 0; + goto err_put; + } /* * size indicates the number of bytes in the region to save. This might @@ -397,21 +456,24 @@ int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase, /* If the buffer is already on the list, skip it */ list_for_each_entry(obj, &device->snapshot_obj_list, node) { - if (obj->gpuaddr == gpuaddr && obj->ptbase == ptbase) { - /* If the size is different, use the bigger size */ - if (obj->size < size) - obj->size = size; + /* combine the range with existing object if they overlap */ + if (obj->ptbase == ptbase && obj->type == type && + kgsl_addr_range_overlap(obj->gpuaddr, obj->size, + gpuaddr, size)) { + unsigned int end1 = obj->gpuaddr + obj->size; + unsigned int end2 = gpuaddr + size; + if (obj->gpuaddr > gpuaddr) + obj->gpuaddr = gpuaddr; + if (end1 > end2) + obj->size = end1 - obj->gpuaddr; + else + obj->size = end2 - obj->gpuaddr; + obj->offset = obj->gpuaddr - entry->memdesc.gpuaddr; ret = 0; goto err_put; } } - if (kgsl_memdesc_map(&entry->memdesc) == NULL) { - KGSL_DRV_ERR(device, "Unable to map GPU buffer %X\n", - gpuaddr); - goto err_put; - } - obj = kzalloc(sizeof(*obj), GFP_KERNEL); if (obj == NULL) { @@ -542,6 +604,20 @@ int kgsl_device_snapshot(struct kgsl_device *device, int hang) int remain = device->snapshot_maxsize - sizeof(*header); void *snapshot; struct timespec boot; + int ret = 0; + + /* + * Bail if failed to get active count for GPU, + * try again + */ + if (kgsl_active_count_get(device)) { + KGSL_DRV_ERR(device, "Failed to get GPU active count"); + return -EINVAL; + } + + /* increment the hang count (on hang) for good book keeping */ + if (hang) + device->snapshot_faultcount++; /* * The first hang is always the one we are interested in. To @@ -552,19 +628,23 @@ int kgsl_device_snapshot(struct kgsl_device *device, int hang) * of the state and never frozen. */ - if (hang && device->snapshot_frozen == 1) - return 0; + if (hang && device->snapshot_frozen == 1) { + ret = 0; + goto done; + } if (device->snapshot == NULL) { KGSL_DRV_ERR(device, "snapshot: No snapshot memory available\n"); - return -ENOMEM; + ret = -ENOMEM; + goto done; } if (remain < sizeof(*header)) { KGSL_DRV_ERR(device, "snapshot: Not enough memory for the header\n"); - return -ENOMEM; + ret = -ENOMEM; + goto done; } header->magic = SNAPSHOT_MAGIC; @@ -600,7 +680,10 @@ int kgsl_device_snapshot(struct kgsl_device *device, int hang) __pa(device->snapshot), device->snapshot_size); if (hang) sysfs_notify(&device->snapshot_kobj, NULL, "timestamp"); - return 0; + +done: + kgsl_active_count_put(device); + return ret; } EXPORT_SYMBOL(kgsl_device_snapshot); @@ -612,6 +695,32 @@ struct kgsl_snapshot_attribute { size_t count); }; +/* + * kgsl_snapshot_process_ib_obj_list() - Go through the list of IB's which need + * to be dumped for snapshot and move them to the global snapshot list so + * they will get dumped when the global list is dumped + * @device: device being snapshotted + */ +static void kgsl_snapshot_process_ib_obj_list(struct kgsl_device *device) +{ + struct kgsl_snapshot_cp_obj *obj, *obj_temp; + struct adreno_ib_object *ib_obj; + int i; + + list_for_each_entry_safe(obj, obj_temp, &device->snapshot_cp_list, + node) { + for (i = 0; i < obj->ib_obj_list->num_objs; i++) { + ib_obj = &(obj->ib_obj_list->obj_list[i]); + kgsl_snapshot_get_object(device, obj->ptbase, + ib_obj->gpuaddr, ib_obj->size, + ib_obj->snapshot_obj_type); + } + list_del(&obj->node); + adreno_ib_destroy_obj_list(obj->ib_obj_list); + kfree(obj); + } +} + #define to_snapshot_attr(a) \ container_of(a, struct kgsl_snapshot_attribute, attr) @@ -646,6 +755,13 @@ static ssize_t snapshot_show(struct file *filep, struct kobject *kobj, if (ret == 0) goto done; + kgsl_snapshot_process_ib_obj_list(device); + + if (device->snapshot_cur_ib_objs) { + obj_itr_out(&itr, device->snapshot_cur_ib_objs, + device->snapshot_cur_ib_objs_size); + } + list_for_each_entry(obj, &device->snapshot_obj_list, node) kgsl_snapshot_dump_object(device, obj, &itr); @@ -669,6 +785,12 @@ static ssize_t snapshot_show(struct file *filep, struct kobject *kobj, node) kgsl_snapshot_put_object(device, obj); + if (device->snapshot_cur_ib_objs) { + vfree(device->snapshot_cur_ib_objs); + device->snapshot_cur_ib_objs = NULL; + device->snapshot_cur_ib_objs_size = 0; + } + if (device->snapshot_frozen) KGSL_DRV_ERR(device, "Snapshot objects released\n"); @@ -681,6 +803,22 @@ static ssize_t snapshot_show(struct file *filep, struct kobject *kobj, return itr.write; } +/* Show the total number of hangs since device boot */ +static ssize_t faultcount_show(struct kgsl_device *device, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_faultcount); +} + +/* Reset the total number of hangs since device boot */ +static ssize_t faultcount_store(struct kgsl_device *device, const char *buf, + size_t count) +{ + if (device && count > 0) + device->snapshot_faultcount = 0; + + return count; +} + /* Show the timestamp of the last collected snapshot */ static ssize_t timestamp_show(struct kgsl_device *device, char *buf) { @@ -693,7 +831,10 @@ static ssize_t trigger_store(struct kgsl_device *device, const char *buf, { if (device && count > 0) { mutex_lock(&device->mutex); - kgsl_device_snapshot(device, 0); + if (!kgsl_active_count_get(device)) { + kgsl_device_snapshot(device, 0); + kgsl_active_count_put(device); + } mutex_unlock(&device->mutex); } @@ -716,6 +857,7 @@ struct kgsl_snapshot_attribute attr_##_name = { \ SNAPSHOT_ATTR(trigger, 0600, NULL, trigger_store); SNAPSHOT_ATTR(timestamp, 0444, timestamp_show, NULL); +SNAPSHOT_ATTR(faultcount, 0644, faultcount_show, faultcount_store); static void snapshot_sysfs_release(struct kobject *kobj) { @@ -781,8 +923,12 @@ int kgsl_device_snapshot_init(struct kgsl_device *device) device->snapshot_maxsize = KGSL_SNAPSHOT_MEMSIZE; device->snapshot_timestamp = 0; + device->snapshot_faultcount = 0; INIT_LIST_HEAD(&device->snapshot_obj_list); + INIT_LIST_HEAD(&device->snapshot_cp_list); + device->snapshot_cur_ib_objs = NULL; + device->snapshot_cur_ib_objs_size = 0; ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot, &device->dev->kobj, "snapshot"); @@ -798,6 +944,10 @@ int kgsl_device_snapshot_init(struct kgsl_device *device) goto done; ret = sysfs_create_file(&device->snapshot_kobj, &attr_timestamp.attr); + if (ret) + goto done; + + ret = sysfs_create_file(&device->snapshot_kobj, &attr_faultcount.attr); done: return ret; @@ -824,5 +974,123 @@ void kgsl_device_snapshot_close(struct kgsl_device *device) device->snapshot = NULL; device->snapshot_maxsize = 0; device->snapshot_timestamp = 0; + device->snapshot_faultcount = 0; } EXPORT_SYMBOL(kgsl_device_snapshot_close); + +/* + * kgsl_snapshot_add_ib_obj_list() - Add a IB object list to the snapshot + * object list + * @device: the device that is being snapshotted + * @ib_obj_list: The IB list that has objects required to execute an IB + * @num_objs: Number of IB objects + * @ptbase: The pagetable base in which the IB is mapped + * + * Adds a new IB to the list of IB objects maintained when getting snapshot + * Returns 0 on success else -ENOMEM on error + */ +int kgsl_snapshot_add_ib_obj_list(struct kgsl_device *device, + phys_addr_t ptbase, + struct adreno_ib_object_list *ib_obj_list) +{ + struct kgsl_snapshot_cp_obj *obj; + + obj = kzalloc(sizeof(*obj), GFP_KERNEL); + if (!obj) + return -ENOMEM; + obj->ib_obj_list = ib_obj_list; + obj->ptbase = ptbase; + list_add(&obj->node, &device->snapshot_cp_list); + return 0; +} + +/* + * snapshot_object() - Dump an IB object into memory + * @device - Device being snapshotted + * @snapshot - Snapshot memory + * @remain - Amount of bytes that the snapshot memory can take + * @priv - Pointer to the object being snapshotted + * + * Returns the amount of bytes written + */ +static int snapshot_object(struct kgsl_device *device, void *snapshot, + int remain, void *priv) +{ + int ret = 0; + struct kgsl_snapshot_object *obj = priv; + struct kgsl_snapshot_gpu_object *header = snapshot; + void *dest; + + if (remain < sizeof(*header) + obj->size) { + KGSL_DRV_ERR(device, "Not enough space in snapshot\n"); + return ret; + } + header->size = obj->size >> 2; + header->gpuaddr = obj->gpuaddr; + header->ptbase = (__u32)obj->ptbase; + header->type = obj->type; + dest = snapshot + sizeof(*header); + + if (!kgsl_memdesc_map(&obj->entry->memdesc)) { + KGSL_DRV_ERR(device, "Failed to map memdesc\n"); + return 0; + } + memcpy(dest, obj->entry->memdesc.hostptr + obj->offset, obj->size); + ret += sizeof(*header) + obj->size; + kgsl_memdesc_unmap(&obj->entry->memdesc); + return ret; +} + +/* + * kgsl_snapshot_save_frozen_objs - Save the objects frozen in snapshot into + * memory so that the data reported in these objects is correct when snapshot + * is taken + * @work - The work item that scheduled this work + */ +void kgsl_snapshot_save_frozen_objs(struct work_struct *work) +{ + struct kgsl_device *device = container_of(work, struct kgsl_device, + snapshot_obj_ws); + struct kgsl_snapshot_object *snapshot_obj, *snapshot_obj_temp; + unsigned int remain = 0; + void *snapshot_dest; + + mutex_lock(&device->mutex); + + kgsl_snapshot_process_ib_obj_list(device); + + /* If already exists then wait for it to be released */ + if (device->snapshot_cur_ib_objs) + goto done; + + list_for_each_entry_safe(snapshot_obj, snapshot_obj_temp, + &device->snapshot_obj_list, node) { + snapshot_obj->size = ALIGN(snapshot_obj->size, 4); + remain += (snapshot_obj->size + + sizeof(struct kgsl_snapshot_gpu_object) + + sizeof(struct kgsl_snapshot_section_header)); + } + if (!remain) + goto done; + + device->snapshot_cur_ib_objs = vmalloc(remain); + if (!device->snapshot_cur_ib_objs) + goto done; + + KGSL_DRV_ERR(device, + "Allocated memory for snapshot objects at address %p, size %x\n", + device->snapshot_cur_ib_objs, remain); + snapshot_dest = device->snapshot_cur_ib_objs; + device->snapshot_cur_ib_objs_size = remain; + + list_for_each_entry_safe(snapshot_obj, snapshot_obj_temp, + &device->snapshot_obj_list, node) { + snapshot_dest = kgsl_snapshot_add_section(device, + KGSL_SNAPSHOT_SECTION_GPU_OBJECT, + snapshot_dest, &remain, snapshot_object, + snapshot_obj); + kgsl_snapshot_put_object(device, snapshot_obj); + } +done: + mutex_unlock(&device->mutex); +} diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h index 327d18a136b..00a83ac57e5 100644 --- a/drivers/gpu/msm/kgsl_snapshot.h +++ b/drivers/gpu/msm/kgsl_snapshot.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2013, 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 @@ -52,6 +52,7 @@ struct kgsl_snapshot_section_header { #define KGSL_SNAPSHOT_SECTION_DEBUG 0x0901 #define KGSL_SNAPSHOT_SECTION_DEBUGBUS 0x0A01 #define KGSL_SNAPSHOT_SECTION_GPU_OBJECT 0x0B01 +#define KGSL_SNAPSHOT_SECTION_MEMLIST 0x0E01 #define KGSL_SNAPSHOT_SECTION_END 0xFFFF @@ -103,6 +104,17 @@ struct kgsl_snapshot_rb { int count; /* Number of dwords in the dump */ } __packed; +/* Replay or Memory list section, both sections have same header */ +struct kgsl_snapshot_replay_mem_list { + /* + * Number of IBs to replay for replay section or + * number of memory list entries for mem list section + */ + int num_entries; + /* Pagetable base to which the replay IBs or memory entries belong */ + __u32 ptbase; +} __packed; + /* Indirect buffer sub-section header */ struct kgsl_snapshot_ib { __u32 gpuaddr; /* GPU address of the the IB */ @@ -308,11 +320,17 @@ void *kgsl_snapshot_indexed_registers(struct kgsl_device *device, unsigned int data, unsigned int start, unsigned int count); /* Freeze a GPU buffer so it can be dumped in the snapshot */ -int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase, +int kgsl_snapshot_get_object(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size, unsigned int type); -int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase, +int kgsl_snapshot_have_object(struct kgsl_device *device, phys_addr_t ptbase, unsigned int gpuaddr, unsigned int size); +struct adreno_ib_object_list; + +int kgsl_snapshot_add_ib_obj_list(struct kgsl_device *device, + phys_addr_t ptbase, + struct adreno_ib_object_list *ib_obj_list); + #endif #endif diff --git a/drivers/gpu/msm/kgsl_sync.c b/drivers/gpu/msm/kgsl_sync.c index b74d4604d14..0e7606e842c 100644 --- a/drivers/gpu/msm/kgsl_sync.c +++ b/drivers/gpu/msm/kgsl_sync.c @@ -13,9 +13,12 @@ #include #include +#include #include #include +#include + #include "kgsl_sync.h" struct sync_pt *kgsl_sync_pt_create(struct sync_timeline *timeline, @@ -189,24 +192,77 @@ int kgsl_add_fence_event(struct kgsl_device *device, return ret; } +static unsigned int kgsl_sync_get_timestamp( + struct kgsl_sync_timeline *ktimeline, enum kgsl_timestamp_type type) +{ + struct kgsl_context *context = idr_find(&ktimeline->device->context_idr, + ktimeline->context_id); + if (context == NULL) + return 0; + + return kgsl_readtimestamp(ktimeline->device, context, type); +} + +static void kgsl_sync_timeline_value_str(struct sync_timeline *sync_timeline, + char *str, int size) +{ + struct kgsl_sync_timeline *ktimeline = + (struct kgsl_sync_timeline *) sync_timeline; + unsigned int timestamp_retired = kgsl_sync_get_timestamp(ktimeline, + KGSL_TIMESTAMP_RETIRED); + snprintf(str, size, "%u retired:%u", ktimeline->last_timestamp, + timestamp_retired); +} + +static void kgsl_sync_pt_value_str(struct sync_pt *sync_pt, + char *str, int size) +{ + struct kgsl_sync_pt *kpt = (struct kgsl_sync_pt *) sync_pt; + snprintf(str, size, "%u", kpt->timestamp); +} + +static void kgsl_sync_timeline_release_obj(struct sync_timeline *sync_timeline) +{ + /* + * Make sure to free the timeline only after destroy flag is set. + * This is to avoid further accessing to the timeline from KGSL and + * also to catch any unbalanced kref of timeline. + */ + BUG_ON(sync_timeline && (sync_timeline->destroyed != true)); +} static const struct sync_timeline_ops kgsl_sync_timeline_ops = { .driver_name = "kgsl-timeline", .dup = kgsl_sync_pt_dup, .has_signaled = kgsl_sync_pt_has_signaled, .compare = kgsl_sync_pt_compare, + .timeline_value_str = kgsl_sync_timeline_value_str, + .pt_value_str = kgsl_sync_pt_value_str, + .release_obj = kgsl_sync_timeline_release_obj, }; int kgsl_sync_timeline_create(struct kgsl_context *context) { struct kgsl_sync_timeline *ktimeline; + /* Generate a name which includes the thread name, thread id, process + * name, process id, and context id. This makes it possible to + * identify the context of a timeline in the sync dump. */ + char ktimeline_name[sizeof(context->timeline->name)] = {}; + snprintf(ktimeline_name, sizeof(ktimeline_name), + "%s_%.15s(%d)-%.15s(%d)-%d", + context->device->name, + current->group_leader->comm, current->group_leader->pid, + current->comm, current->pid, context->id); + context->timeline = sync_timeline_create(&kgsl_sync_timeline_ops, - (int) sizeof(struct kgsl_sync_timeline), "kgsl-timeline"); + (int) sizeof(struct kgsl_sync_timeline), ktimeline_name); if (context->timeline == NULL) return -EINVAL; ktimeline = (struct kgsl_sync_timeline *) context->timeline; ktimeline->last_timestamp = 0; + ktimeline->device = context->dev_priv->device; + ktimeline->context_id = context->id; return 0; } diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h index 2f28b21fc6d..275eaf07dfb 100644 --- a/drivers/gpu/msm/kgsl_sync.h +++ b/drivers/gpu/msm/kgsl_sync.h @@ -19,6 +19,8 @@ struct kgsl_sync_timeline { struct sync_timeline timeline; unsigned int last_timestamp; + struct kgsl_device *device; + u32 context_id; }; struct kgsl_sync_pt { diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h index b55075935db..5f39b8bb3ec 100644 --- a/drivers/gpu/msm/kgsl_trace.h +++ b/drivers/gpu/msm/kgsl_trace.h @@ -69,7 +69,7 @@ TRACE_EVENT(kgsl_issueibcmds, ), TP_printk( - "d_name=%s ctx=%u ib=0x%u numibs=%u timestamp=0x%x " + "d_name=%s ctx=%u ib=0x%u numibs=%u ts=%u " "flags=0x%x(%s) result=%d type=%s", __get_str(device_name), __entry->drawctxt_id, @@ -115,7 +115,7 @@ TRACE_EVENT(kgsl_readtimestamp, ), TP_printk( - "d_name=%s context_id=%u type=%u timestamp=0x%x", + "d_name=%s context_id=%u type=%u ts=%u", __get_str(device_name), __entry->context_id, __entry->type, @@ -153,7 +153,7 @@ TRACE_EVENT(kgsl_waittimestamp_entry, ), TP_printk( - "d_name=%s context_id=%u curr_ts=0x%x timestamp=0x%x timeout=%u", + "d_name=%s ctx=%u curr_ts=%u ts=%u timeout=%u", __get_str(device_name), __entry->context_id, __entry->curr_ts, @@ -185,7 +185,7 @@ TRACE_EVENT(kgsl_waittimestamp_exit, ), TP_printk( - "d_name=%s curr_ts=0x%x result=%d", + "d_name=%s curr_ts=%u result=%d", __get_str(device_name), __entry->curr_ts, __entry->result @@ -208,7 +208,7 @@ DECLARE_EVENT_CLASS(kgsl_pwr_template, ), TP_printk( - "d_name=%s %s", + "d_name=%s flag=%s", __get_str(device_name), __entry->on ? "on" : "off" ) @@ -261,26 +261,29 @@ TRACE_EVENT(kgsl_pwrlevel, ) ); -TRACE_EVENT(kgsl_mpdcvs, +TRACE_EVENT(kgsl_gpubusy, + TP_PROTO(struct kgsl_device *device, unsigned int busy, + unsigned int elapsed), - TP_PROTO(struct kgsl_device *device, unsigned int state), - - TP_ARGS(device, state), + TP_ARGS(device, busy, elapsed), TP_STRUCT__entry( __string(device_name, device->name) - __field(unsigned int, state) + __field(unsigned int, busy) + __field(unsigned int, elapsed) ), TP_fast_assign( __assign_str(device_name, device->name); - __entry->state = state; + __entry->busy = busy; + __entry->elapsed = elapsed; ), TP_printk( - "d_name=%s %s", + "d_name=%s busy=%u elapsed=%d", __get_str(device_name), - __entry->state ? "BUSY" : "IDLE" + __entry->busy, + __entry->elapsed ) ); @@ -300,7 +303,7 @@ DECLARE_EVENT_CLASS(kgsl_pwrstate_template, ), TP_printk( - "d_name=%s %s", + "d_name=%s state=%s", __get_str(device_name), kgsl_pwrstate_to_str(__entry->state) ) @@ -342,7 +345,7 @@ TRACE_EVENT(kgsl_mem_alloc, ), TP_printk( - "gpuaddr=0x%08x size=%d tgid=%d usage=%s id=%d flags=0x%08x", + "gpuaddr=0x%08x size=%u tgid=%u usage=%s id=%u flags=0x%08x", __entry->gpuaddr, __entry->size, __entry->tgid, __entry->usage, __entry->id, __entry->flags ) @@ -374,7 +377,7 @@ TRACE_EVENT(kgsl_mem_mmap, ), TP_printk( - "useraddr=%lx gpuaddr=0x%08x size=%d usage=%s id=%d" + "useraddr=0x%lx gpuaddr=0x%08x size=%u usage=%s id=%u" " flags=0x%08x", __entry->useraddr, __entry->gpuaddr, __entry->size, __entry->usage, __entry->id, __entry->flags @@ -405,7 +408,7 @@ TRACE_EVENT(kgsl_mem_unmapped_area_collision, ), TP_printk( - "id=%d hint=0x%lx len=%ld addr=0x%lx", + "id=%u hint=0x%lx len=%lu addr=0x%lx", __entry->id, __entry->hint, __entry->len, __entry->addr ) ); @@ -438,7 +441,7 @@ TRACE_EVENT(kgsl_mem_map, ), TP_printk( - "gpuaddr=0x%08x size=%d type=%d fd=%d tgid=%d usage=%s id=%d", + "gpuaddr=0x%08x size=%u type=%d fd=%d tgid=%u usage=%s id=%u", __entry->gpuaddr, __entry->size, __entry->type, __entry->fd, __entry->tgid, __entry->usage, __entry->id @@ -472,7 +475,7 @@ TRACE_EVENT(kgsl_mem_free, ), TP_printk( - "gpuaddr=0x%08x size=%d type=%d tgid=%d usage=%s id=%d", + "gpuaddr=0x%08x size=%u type=%d tgid=%u usage=%s id=%u", __entry->gpuaddr, __entry->size, __entry->type, __entry->tgid, __entry->usage, __entry->id ) @@ -504,7 +507,7 @@ TRACE_EVENT(kgsl_mem_sync_cache, ), TP_printk( - "gpuaddr=0x%08x size=%d tgid=%d usage=%s id=%d op=%c%c", + "gpuaddr=0x%08x size=%u tgid=%u usage=%s id=%u op=%c%c", __entry->gpuaddr, __entry->size, __entry->tgid, __entry->usage, __entry->id, (__entry->op & KGSL_GPUMEM_CACHE_CLEAN) ? 'c' : '.', @@ -572,8 +575,8 @@ DECLARE_EVENT_CLASS(kgsl_mem_timestamp_template, ), TP_printk( - "d_name=%s gpuaddr=0x%08x size=%d type=%d usage=%s id=%d ctx=%u" - " curr_ts=0x%x free_ts=0x%x", + "d_name=%s gpuaddr=0x%08x size=%u type=%d usage=%s id=%u ctx=%u" + " curr_ts=%u free_ts=%u", __get_str(device_name), __entry->gpuaddr, __entry->size, @@ -695,7 +698,7 @@ TRACE_EVENT(kgsl_mmu_pagefault, ), TP_printk( - "d_name=%s page=0x%08x pt=%d op=%s", + "d_name=%s page=0x%08x pt=%u op=%s", __get_str(device_name), __entry->page, __entry->pt, __get_str(op) ) @@ -721,46 +724,52 @@ TRACE_EVENT(kgsl_regwrite, ), TP_printk( - "d_name=%s reg=%x value=%x", + "d_name=%s reg=0x%x value=0x%x", __get_str(device_name), __entry->offset, __entry->value ) ); TRACE_EVENT(kgsl_register_event, - TP_PROTO(unsigned int id, unsigned int timestamp), - TP_ARGS(id, timestamp), + TP_PROTO(unsigned int id, unsigned int timestamp, void *func), + TP_ARGS(id, timestamp, func), TP_STRUCT__entry( __field(unsigned int, id) __field(unsigned int, timestamp) + __field(void *, func) ), TP_fast_assign( __entry->id = id; __entry->timestamp = timestamp; + __entry->func = func; ), TP_printk( - "ctx=%d ts=%d", - __entry->id, __entry->timestamp) + "ctx=%u ts=%u cb=%pF", + __entry->id, __entry->timestamp, __entry->func) ); TRACE_EVENT(kgsl_fire_event, TP_PROTO(unsigned int id, unsigned int ts, - unsigned int type, unsigned int age), - TP_ARGS(id, ts, type, age), + unsigned int type, unsigned int age, void *func), + TP_ARGS(id, ts, type, age, func), TP_STRUCT__entry( __field(unsigned int, id) __field(unsigned int, ts) __field(unsigned int, type) __field(unsigned int, age) + __field(void *, func) ), TP_fast_assign( __entry->id = id; __entry->ts = ts; __entry->type = type; __entry->age = age; + __entry->func = func; ), TP_printk( - "ctx=%d ts=%d type=%d age=%u", - __entry->id, __entry->ts, __entry->type, __entry->age) + "ctx=%u ts=%u type=%s age=%u cb=%pF", + __entry->id, __entry->ts, + __print_symbolic(__entry->type, KGSL_EVENT_TYPES), + __entry->age, __entry->func) ); TRACE_EVENT(kgsl_active_count, @@ -782,7 +791,7 @@ TRACE_EVENT(kgsl_active_count, ), TP_printk( - "d_name=%s active_cnt=%x func=%pf", + "d_name=%s active_cnt=%u func=%pf", __get_str(device_name), __entry->count, (void *) __entry->ip ) ); diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c index 9cebacec048..a8cbfa714c7 100644 --- a/drivers/gpu/msm/z180.c +++ b/drivers/gpu/msm/z180.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2002,2007-2013, The Linux Foundation. All rights reserved. +/* Copyright (c) 2002,2007-2014, 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 @@ -124,6 +124,8 @@ static void z180_cmdwindow_write(struct kgsl_device *device, | (MMU_CONFIG << MH_MMU_CONFIG__TC_R_CLNT_BEHAVIOR__SHIFT) \ | (MMU_CONFIG << MH_MMU_CONFIG__PA_W_CLNT_BEHAVIOR__SHIFT)) +#define KGSL_LOG_LEVEL_DEFAULT 3 + static const struct kgsl_functable z180_functable; static struct z180_device device_2d0 = { @@ -149,6 +151,12 @@ static struct z180_device device_2d0 = { }, .iomemname = KGSL_2D0_REG_MEMORY, .ftbl = &z180_functable, + .cmd_log = KGSL_LOG_LEVEL_DEFAULT, + .ctxt_log = KGSL_LOG_LEVEL_DEFAULT, + .drv_log = KGSL_LOG_LEVEL_DEFAULT, + .mem_log = KGSL_LOG_LEVEL_DEFAULT, + .pwr_log = KGSL_LOG_LEVEL_DEFAULT, + .pm_dump_enable = 0, }, .cmdwin_lock = __SPIN_LOCK_INITIALIZER(device_2d1.cmdwin_lock), }; @@ -216,8 +224,7 @@ static irqreturn_t z180_irq_handler(struct kgsl_device *device) } } - if ((device->pwrctrl.nap_allowed == true) && - (device->requested_state == KGSL_STATE_NONE)) { + if (device->requested_state == KGSL_STATE_NONE) { kgsl_pwrctrl_request_state(device, KGSL_STATE_NAP); queue_work(device->work_queue, &device->idle_check_ws); } @@ -399,7 +406,9 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, mutex_lock(&device->mutex); - kgsl_active_count_get(device); + result = kgsl_active_count_get(device); + if (result) + goto error_active_count; if (cmdbatch == NULL) { result = EINVAL; @@ -442,7 +451,7 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, "Cannot make kernel mapping for gpuaddr 0x%x\n", cmd); result = -EINVAL; - goto error; + goto error_put; } KGSL_CMD_INFO(device, "ctxt %d ibaddr 0x%08x sizedwords %d\n", @@ -471,7 +480,7 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, if (result < 0) { KGSL_CMD_ERR(device, "wait_event_interruptible_timeout " "failed: %ld\n", result); - goto error; + goto error_put; } result = 0; @@ -488,10 +497,10 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, addmarker(&z180_dev->ringbuffer, z180_dev->current_timestamp); /* monkey patch the IB so that it jumps back to the ringbuffer */ - kgsl_sharedmem_writel(&entry->memdesc, + kgsl_sharedmem_writel(device, &entry->memdesc, ((sizedwords + 1) * sizeof(unsigned int)), rb_gpuaddr(z180_dev, z180_dev->current_timestamp)); - kgsl_sharedmem_writel(&entry->memdesc, + kgsl_sharedmem_writel(device, &entry->memdesc, ((sizedwords + 2) * sizeof(unsigned int)), nextcnt); @@ -503,12 +512,14 @@ z180_cmdstream_issueibcmds(struct kgsl_device_private *dev_priv, z180_cmdwindow_write(device, ADDR_VGV3_CONTROL, cmd); z180_cmdwindow_write(device, ADDR_VGV3_CONTROL, 0); +error_put: + kgsl_mem_entry_put(entry); error: kgsl_trace_issueibcmds(device, context->id, cmdbatch, *timestamp, cmdbatch->flags, result, 0); kgsl_active_count_put(device); - +error_active_count: mutex_unlock(&device->mutex); return (int)result; @@ -621,8 +632,12 @@ static int z180_start(struct kgsl_device *device) static int z180_stop(struct kgsl_device *device) { + int ret; + device->ftbl->irqctrl(device, 0); - z180_idle(device); + ret = z180_idle(device); + if (ret) + return ret; del_timer_sync(&device->idle_timer); @@ -734,7 +749,7 @@ static void _z180_regwrite_simple(struct kgsl_device *device, BUG_ON(offsetwords*sizeof(uint32_t) >= device->reg_len); reg = (unsigned int *)(device->reg_virt + (offsetwords << 2)); - kgsl_cffdump_regwrite(device->id, offsetwords << 2, value); + kgsl_cffdump_regwrite(device, offsetwords << 2, value); /*ensure previous writes post before this one, * i.e. act like normal writel() */ wmb(); @@ -853,9 +868,13 @@ static int z180_waittimestamp(struct kgsl_device *device, if (msecs == -1) msecs = Z180_IDLE_TIMEOUT; - mutex_unlock(&device->mutex); - status = z180_wait(device, context, timestamp, msecs); - mutex_lock(&device->mutex); + status = kgsl_active_count_get(device); + if (!status) { + mutex_unlock(&device->mutex); + status = z180_wait(device, context, timestamp, msecs); + mutex_lock(&device->mutex); + kgsl_active_count_put(device); + } return status; } @@ -904,21 +923,29 @@ z180_drawctxt_create(struct kgsl_device_private *dev_priv, static int z180_drawctxt_detach(struct kgsl_context *context) { + int ret; struct kgsl_device *device; struct z180_device *z180_dev; device = context->device; z180_dev = Z180_DEVICE(device); + ret = kgsl_active_count_get(device); + if (ret) + return ret; + z180_idle(device); if (z180_dev->ringbuffer.prevctx == context->id) { z180_dev->ringbuffer.prevctx = Z180_INVALID_CONTEXT; device->mmu.hwpagetable = device->mmu.defaultpagetable; + + /* Ignore the result - we are going down anyway */ kgsl_setstate(&device->mmu, KGSL_MEMSTORE_GLOBAL, KGSL_MMUFLAGS_PTUPDATE); } + kgsl_active_count_put(device); return 0; } diff --git a/drivers/gpu/msm/z180_postmortem.c b/drivers/gpu/msm/z180_postmortem.c index 03ebdb572d8..bc53c0e9801 100644 --- a/drivers/gpu/msm/z180_postmortem.c +++ b/drivers/gpu/msm/z180_postmortem.c @@ -120,7 +120,7 @@ static void z180_dump_ib(struct kgsl_device *device) int rb_slot_num = -1; struct z180_device *z180_dev = Z180_DEVICE(device); struct kgsl_mem_entry *entry = NULL; - unsigned int pt_base; + phys_addr_t pt_base; unsigned int i; unsigned int j; char linebuf[CHARS_PER_LINE]; diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 2e6d187709d..1432594c4e2 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -278,8 +278,9 @@ static void set_abs(struct input_dev *input, unsigned int code, static void set_last_slot_field(struct hid_usage *usage, struct mt_device *td, struct hid_input *hi) { - if (!test_bit(usage->hid, hi->input->absbit)) - td->last_slot_field = usage->hid; + if ((BIT_WORD(usage->hid)) < (sizeof(hi->input->absbit) / sizeof(int))) + if (!test_bit(usage->hid, hi->input->absbit)) + td->last_slot_field = usage->hid; } static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, diff --git a/drivers/input/input-mt.c b/drivers/input/input-mt.c index f658086fbbe..92f801a7bb8 100644 --- a/drivers/input/input-mt.c +++ b/drivers/input/input-mt.c @@ -41,7 +41,6 @@ int input_mt_init_slots(struct input_dev *dev, unsigned int num_slots) dev->mtsize = num_slots; input_set_abs_params(dev, ABS_MT_SLOT, 0, num_slots - 1, 0, 0); input_set_abs_params(dev, ABS_MT_TRACKING_ID, 0, TRKID_MAX, 0, 0); - input_set_events_per_packet(dev, 6 * num_slots); /* Mark slots as 'unused' */ for (i = 0; i < num_slots; i++) diff --git a/drivers/input/input.c b/drivers/input/input.c index 661e7ae3328..9566a67a2be 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -47,6 +47,8 @@ static DEFINE_MUTEX(input_mutex); static struct input_handler *input_table[8]; +static const struct input_value input_value_sync = { EV_SYN, SYN_REPORT, 1 }; + static inline int is_event_supported(unsigned int code, unsigned long *bm, unsigned int max) { @@ -69,42 +71,102 @@ static int input_defuzz_abs_event(int value, int old_val, int fuzz) return value; } +static void input_start_autorepeat(struct input_dev *dev, int code) +{ + if (test_bit(EV_REP, dev->evbit) && + dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && + dev->timer.data) { + dev->repeat_key = code; + mod_timer(&dev->timer, + jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); + } +} + +static void input_stop_autorepeat(struct input_dev *dev) +{ + del_timer(&dev->timer); +} + /* * Pass event first through all filters and then, if event has not been * filtered out, through all open handles. This function is called with * dev->event_lock held and interrupts disabled. */ -static void input_pass_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) +static unsigned int input_to_handler(struct input_handle *handle, + struct input_value *vals, unsigned int count) +{ + struct input_handler *handler = handle->handler; + struct input_value *end = vals; + struct input_value *v; + + for (v = vals; v != vals + count; v++) { + if (handler->filter && + handler->filter(handle, v->type, v->code, v->value)) + continue; + if (end != v) + *end = *v; + end++; + } + + count = end - vals; + if (!count) + return 0; + + if (handler->events) + handler->events(handle, vals, count); + else if (handler->event) + for (v = vals; v != end; v++) + handler->event(handle, v->type, v->code, v->value); + + return count; +} + +/* + * Pass values first through all filters and then, if event has not been + * filtered out, through all open handles. This function is called with + * dev->event_lock held and interrupts disabled. + */ +static void input_pass_values(struct input_dev *dev, + struct input_value *vals, unsigned int count) { - struct input_handler *handler; struct input_handle *handle; + struct input_value *v; + + if (!count) + return; rcu_read_lock(); handle = rcu_dereference(dev->grab); - if (handle) - handle->handler->event(handle, type, code, value); - else { - bool filtered = false; - - list_for_each_entry_rcu(handle, &dev->h_list, d_node) { - if (!handle->open) - continue; + if (handle) { + count = input_to_handler(handle, vals, count); + } else { + list_for_each_entry_rcu(handle, &dev->h_list, d_node) + if (handle->open) + count = input_to_handler(handle, vals, count); + } - handler = handle->handler; - if (!handler->filter) { - if (filtered) - break; + rcu_read_unlock(); - handler->event(handle, type, code, value); + add_input_randomness(vals->type, vals->code, vals->value); - } else if (handler->filter(handle, type, code, value)) - filtered = true; + /* trigger auto repeat for key events */ + for (v = vals; v != vals + count; v++) { + if (v->type == EV_KEY && v->value != 2) { + if (v->value) + input_start_autorepeat(dev, v->code); + else + input_stop_autorepeat(dev); } } +} - rcu_read_unlock(); +static void input_pass_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) +{ + struct input_value vals[] = { { type, code, value } }; + + input_pass_values(dev, vals, ARRAY_SIZE(vals)); } /* @@ -121,18 +183,12 @@ static void input_repeat_key(unsigned long data) if (test_bit(dev->repeat_key, dev->key) && is_event_supported(dev->repeat_key, dev->keybit, KEY_MAX)) { + struct input_value vals[] = { + { EV_KEY, dev->repeat_key, 2 }, + input_value_sync + }; - input_pass_event(dev, EV_KEY, dev->repeat_key, 2); - - if (dev->sync) { - /* - * Only send SYN_REPORT if we are not in a middle - * of driver parsing a new hardware packet. - * Otherwise assume that the driver will send - * SYN_REPORT once it's done. - */ - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); - } + input_pass_values(dev, vals, ARRAY_SIZE(vals)); if (dev->rep[REP_PERIOD]) mod_timer(&dev->timer, jiffies + @@ -142,25 +198,11 @@ static void input_repeat_key(unsigned long data) spin_unlock_irqrestore(&dev->event_lock, flags); } -static void input_start_autorepeat(struct input_dev *dev, int code) -{ - if (test_bit(EV_REP, dev->evbit) && - dev->rep[REP_PERIOD] && dev->rep[REP_DELAY] && - dev->timer.data) { - dev->repeat_key = code; - mod_timer(&dev->timer, - jiffies + msecs_to_jiffies(dev->rep[REP_DELAY])); - } -} - -static void input_stop_autorepeat(struct input_dev *dev) -{ - del_timer(&dev->timer); -} - #define INPUT_IGNORE_EVENT 0 #define INPUT_PASS_TO_HANDLERS 1 #define INPUT_PASS_TO_DEVICE 2 +#define INPUT_SLOT 4 +#define INPUT_FLUSH 8 #define INPUT_PASS_TO_ALL (INPUT_PASS_TO_HANDLERS | INPUT_PASS_TO_DEVICE) static int input_handle_abs_event(struct input_dev *dev, @@ -207,14 +249,14 @@ static int input_handle_abs_event(struct input_dev *dev, /* Flush pending "slot" event */ if (is_mt_event && dev->slot != input_abs_get_val(dev, ABS_MT_SLOT)) { input_abs_set_val(dev, ABS_MT_SLOT, dev->slot); - input_pass_event(dev, EV_ABS, ABS_MT_SLOT, dev->slot); + return INPUT_PASS_TO_HANDLERS | INPUT_SLOT; } return INPUT_PASS_TO_HANDLERS; } -static void input_handle_event(struct input_dev *dev, - unsigned int type, unsigned int code, int value) +static int input_get_disposition(struct input_dev *dev, + unsigned int type, unsigned int code, int value) { int disposition = INPUT_IGNORE_EVENT; @@ -227,13 +269,9 @@ static void input_handle_event(struct input_dev *dev, break; case SYN_REPORT: - if (!dev->sync) { - dev->sync = true; - disposition = INPUT_PASS_TO_HANDLERS; - } + disposition = INPUT_PASS_TO_HANDLERS | INPUT_FLUSH; break; case SYN_MT_REPORT: - dev->sync = false; disposition = INPUT_PASS_TO_HANDLERS; break; } @@ -317,14 +355,48 @@ static void input_handle_event(struct input_dev *dev, break; } - if (disposition != INPUT_IGNORE_EVENT && type != EV_SYN) - dev->sync = false; + return disposition; +} + +static void input_handle_event(struct input_dev *dev, + unsigned int type, unsigned int code, int value) +{ + int disposition; + + disposition = input_get_disposition(dev, type, code, value); if ((disposition & INPUT_PASS_TO_DEVICE) && dev->event) dev->event(dev, type, code, value); - if (disposition & INPUT_PASS_TO_HANDLERS) - input_pass_event(dev, type, code, value); + if (!dev->vals) + return; + + if (disposition & INPUT_PASS_TO_HANDLERS) { + struct input_value *v; + + if (disposition & INPUT_SLOT) { + v = &dev->vals[dev->num_vals++]; + v->type = EV_ABS; + v->code = ABS_MT_SLOT; + v->value = dev->slot; + } + + v = &dev->vals[dev->num_vals++]; + v->type = type; + v->code = code; + v->value = value; + } + + if (disposition & INPUT_FLUSH) { + if (dev->num_vals >= 2) + input_pass_values(dev, dev->vals, dev->num_vals); + dev->num_vals = 0; + } else if (dev->num_vals >= dev->max_vals - 2) { + dev->vals[dev->num_vals++] = input_value_sync; + input_pass_values(dev, dev->vals, dev->num_vals); + dev->num_vals = 0; + } + } /** @@ -352,7 +424,6 @@ void input_event(struct input_dev *dev, if (is_event_supported(type, dev->evbit, EV_MAX)) { spin_lock_irqsave(&dev->event_lock, flags); - add_input_randomness(type, code, value); input_handle_event(dev, type, code, value); spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -831,10 +902,12 @@ int input_set_keycode(struct input_dev *dev, if (test_bit(EV_KEY, dev->evbit) && !is_event_supported(old_keycode, dev->keybit, KEY_MAX) && __test_and_clear_bit(old_keycode, dev->key)) { + struct input_value vals[] = { + { EV_KEY, old_keycode, 0 }, + input_value_sync + }; - input_pass_event(dev, EV_KEY, old_keycode, 0); - if (dev->sync) - input_pass_event(dev, EV_SYN, SYN_REPORT, 1); + input_pass_values(dev, vals, ARRAY_SIZE(vals)); } out: @@ -1416,6 +1489,7 @@ static void input_dev_release(struct device *device) input_ff_destroy(dev); input_mt_destroy_slots(dev); kfree(dev->absinfo); + kfree(dev->vals); kfree(dev); module_put(THIS_MODULE); @@ -1781,6 +1855,9 @@ static unsigned int input_estimate_events_per_packet(struct input_dev *dev) if (test_bit(i, dev->relbit)) events++; + /* Make room for KEY and MSC events */ + events += 7; + return events; } @@ -1819,6 +1896,7 @@ int input_register_device(struct input_dev *dev) { static atomic_t input_no = ATOMIC_INIT(0); struct input_handler *handler; + unsigned int packet_size; const char *path; int error; @@ -1831,9 +1909,14 @@ int input_register_device(struct input_dev *dev) /* Make sure that bitmasks not mentioned in dev->evbit are clean. */ input_cleanse_bitmasks(dev); - if (!dev->hint_events_per_packet) - dev->hint_events_per_packet = - input_estimate_events_per_packet(dev); + packet_size = input_estimate_events_per_packet(dev); + if (dev->hint_events_per_packet < packet_size) + dev->hint_events_per_packet = packet_size; + + dev->max_vals = max(dev->hint_events_per_packet, packet_size) + 2; + dev->vals = kcalloc(dev->max_vals, sizeof(*dev->vals), GFP_KERNEL); + if (!dev->vals) + return -ENOMEM; /* * If delay and period are pre-set by the driver, then autorepeating diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 9f03500288b..e4f2e8d8e4d 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -30,6 +30,10 @@ #include #include +#include + +int pwr_key_pressed = 0; + struct gpio_button_data { const struct gpio_keys_button *button; struct input_dev *input; @@ -345,6 +349,7 @@ static void gpio_keys_gpio_report_event(struct gpio_button_data *bdata) } else { input_event(input, type, button->code, !!state); } + input_sync(input); } @@ -362,6 +367,12 @@ static void gpio_keys_gpio_work_func(struct work_struct *work) if ((button->code <= KEY_POWER) && (button->code >= KEY_VOLUMEDOWN)) pr_info("gpio_keys: %s %s\n", state ? "Pressed" : "Released", key_descriptions[button->code - KEY_VOLUMEDOWN]); + +/*s2w*/ + if (button->code == 116 && state) { + pwr_key_pressed = 1; + } + #endif gpio_keys_gpio_report_event(bdata); } @@ -754,6 +765,10 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev) } input_sync(input); + sweep2wake_setdev(input); + printk(KERN_INFO "[sweep2wake]: set device %s\n", input->name); + + device_init_wakeup(&pdev->dev, wakeup); return 0; diff --git a/drivers/input/lid.c b/drivers/input/lid.c index 3e55c3f7571..f22f48ce45a 100644 --- a/drivers/input/lid.c +++ b/drivers/input/lid.c @@ -12,6 +12,8 @@ #include #include +#include + #define LID_DEBUG 0 #define CONVERSION_TIME_MS 50 @@ -30,6 +32,27 @@ struct delayed_work lid_hall_sensor_work; +int lid_closed = 0; + +int enable_lid = 1; +module_param( enable_lid, int, 0644 ); + +static int __init get_lid_opt(char *lid) +{ + if (strcmp(lid, "0") == 0) { + enable_lid = 0; + } else if (strcmp(lid, "1") == 0) { + enable_lid = 1; + } else { + enable_lid = 1; + } + return 1; +} + +__setup("lid=", get_lid_opt); + + + /* * functions declaration */ @@ -70,11 +93,14 @@ static ssize_t show_lid_status(struct device *class, static irqreturn_t lid_interrupt_handler(int irq, void *dev_id) { - if (irq == hall_sensor_irq) { - LID_NOTICE("LID interrupt handler...gpio: %d..\n", - gpio_get_value(hall_sensor_gpio)); - queue_delayed_work(lid_wq, &lid_hall_sensor_work, 0); + if (enable_lid) { + if (irq == hall_sensor_irq) { + LID_NOTICE("LID interrupt handler...gpio: %d..\n", + gpio_get_value(hall_sensor_gpio)); + queue_delayed_work(lid_wq, &lid_hall_sensor_work, 0); + } } + return IRQ_HANDLED; } @@ -92,6 +118,9 @@ static void lid_report_function(struct work_struct *dat) input_report_switch(lid_indev, SW_LID, !value); input_sync(lid_indev); + if (value == 0) + lid_closed = 1; + LID_NOTICE("SW_LID report value = %d\n", value); } diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 4fde87938b7..a0f25beb42d 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -972,5 +972,12 @@ config TOUCHSCREEN_ELAN_TF_3K help To compile this driver as a module, choose M here: the module will be called atmel_tsadcc. + +config WAKE_TIMEOUT + tristate "Disable screen wake functions after timeout" + default y + help + Disable screen wake functions after timeout + endif diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 927658704b0..2b0e62812bf 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile @@ -81,3 +81,4 @@ obj-$(CONFIG_TOUCHSCREEN_LGE_COMMON) += lge_touch_core.o obj-$(CONFIG_TOUCHSCREEN_LGE_SYNAPTICS) += touch_synaptics.o obj-$(CONFIG_TOUCHSCREEN_LGE_SYNAPTICS) += touch_synaptics_ds4_fw_upgrade.o obj-$(CONFIG_TOUCHSCREEN_ELAN_TF_3K) += ektf3k.o +obj-$(CONFIG_WAKE_TIMEOUT) += wake_timeout.o diff --git a/drivers/input/touchscreen/ektf3k.c b/drivers/input/touchscreen/ektf3k.c index 4b6a7e7a51d..b8bded3044d 100755 --- a/drivers/input/touchscreen/ektf3k.c +++ b/drivers/input/touchscreen/ektf3k.c @@ -2,6 +2,9 @@ * * Copyright (C) 2011 Elan Microelectronics Corporation. * + * Sweep2wake and Doubletap2wake for Nexus 7 (flo) + * Copyright (C) 2013 Aaron Segaert (flar2) asegaert at gmail.com. All rights reserved. + * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. @@ -28,6 +31,8 @@ #include #include +#include + // for linux 2.6.36.3 #include #include @@ -137,6 +142,8 @@ static atomic_t touch_char_available = ATOMIC_INIT(1); static struct proc_dir_entry *dbgProcFile; #endif +#define ELAN_I2C_RETRY 10 + struct elan_ktf3k_ts_data { struct i2c_client *client; struct input_dev *input_dev; @@ -196,6 +203,393 @@ static int debug = DEBUG_INFO; printk("[ektf3k]:" __VA_ARGS__); \ } while (0) + +/* sweep2wake */ +static struct input_dev *sweep2wake_pwrdev; +static DEFINE_MUTEX(s2w_lock); +static bool scr_suspended = false; + +static int pwrkey_suspend = 1; +static int lid_suspend = 1; +static int s2w_orientation = 0; +static int shortsweep = 0; +static int dt2w_switch = 1; +static int dt2w_switch_temp = 1; +static int dt2w_changed = 0; +static int s2w_switch = 15; +static int s2w_switch_temp = 15; +static int s2w_changed = 0; +static int s2s_switch = 1; + +static int s2w_begin_v = 150; +static int s2w_end_v = 1200; +static int s2w_begin_h = 350; +static int s2w_end_h = 1900; +static int tripoff_vl = 0; +static int tripoff_vr = 0; +static int tripoff_hd = 0; +static int tripoff_hu = 0; +static int tripon_vl = 0; +static int tripon_vr = 0; +static int tripon_hd = 0; +static int tripon_hu = 0; +static unsigned long triptime_vl = 0; +static unsigned long triptime_vr = 0; +static unsigned long triptime_hd = 0; +static unsigned long triptime_hu = 0; + +static unsigned long dt2w_time[2] = {0, 0}; +static unsigned int dt2w_x[2] = {0, 0}; +static unsigned int dt2w_y[2] = {0, 0}; +static unsigned int last_x = 0; +static unsigned int last_y = 0; + +#define S2W_TIMEOUT 50 +#define DT2W_TIMEOUT_MAX 50 +#define DT2W_DELTA 200 + +/* Wake Gestures */ +#define SWEEP_RIGHT 0x01 +#define SWEEP_LEFT 0x02 +#define SWEEP_UP 0x04 +#define SWEEP_DOWN 0x08 +#define WAKE_GESTURE 0x0b +static struct input_dev *gesture_dev; +static int gestures_switch = 1; + +static void report_gesture(int gest) +{ + printk("WG: gesture = %d\n", gest); + input_report_rel(gesture_dev, WAKE_GESTURE, gest); + input_sync(gesture_dev); +} + + +void sweep2wake_setdev(struct input_dev * input_device) { + sweep2wake_pwrdev = input_device; + return; +} + +EXPORT_SYMBOL(sweep2wake_setdev); + +static void reset_sweep2wake(void) +{ + tripoff_vl = 0; + tripoff_vr = 0; + tripoff_hd = 0; + tripoff_hu = 0; + tripon_vl = 0; + tripon_vr = 0; + tripon_hd = 0; + tripon_hu = 0; + triptime_vl = 0; + triptime_vr = 0; + triptime_hd = 0; + triptime_hu = 0; + +} + +static void sweep2wake_presspwr(struct work_struct *sweep2wake_presspwr_work) +{ + reset_sweep2wake(); + + input_event(sweep2wake_pwrdev, EV_KEY, KEY_POWER, 1); + input_event(sweep2wake_pwrdev, EV_SYN, 0, 0); + msleep(20); + input_event(sweep2wake_pwrdev, EV_KEY, KEY_POWER, 0); + input_event(sweep2wake_pwrdev, EV_SYN, 0, 0); + msleep(20); + mutex_unlock(&s2w_lock); +} + +static DECLARE_WORK(sweep2wake_presspwr_work, sweep2wake_presspwr); + +void sweep2wake_pwrtrigger(void) +{ + if (mutex_trylock(&s2w_lock)) + schedule_work(&sweep2wake_presspwr_work); +} + +static void sweep2wake_func(int x, int y, unsigned long time, int i) +{ + if (x < 0 || i > 0) { + reset_sweep2wake(); + return; + } + + if (scr_suspended == true && s2w_switch) { + //left->right + if (y < s2w_begin_v && (s2w_switch & SWEEP_RIGHT)) { + tripon_vr = 1; + triptime_vr = time; + } else if (tripon_vr == 1 && y > 488 && time - triptime_vr < 20) { + tripon_vr = 2; + } else if (tripon_vr == 2 && y > 896 && time - triptime_vr < 40) { + tripon_vr = 3; + } else if (tripon_vr == 3 && (y > s2w_end_v) && time - triptime_vr < S2W_TIMEOUT) { + printk(KERN_INFO "[s2w]: ON"); + if (gestures_switch) { + report_gesture(1); + } else { + sweep2wake_pwrtrigger(); + } + } + //right->left + if (y > s2w_end_v && (s2w_switch & SWEEP_LEFT)) { + tripon_vl = 1; + triptime_vl = time; + } else if (tripon_vl == 1 && y < 896 && time - triptime_vl < 20) { + tripon_vl = 2; + } else if (tripon_vl == 2 && y < 488 && time - triptime_vl < 40) { + tripon_vl = 3; + } else if (tripon_vl == 3 && y < s2w_begin_v && (time - triptime_vl < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: ON"); + if (gestures_switch) { + report_gesture(2); + } else { + sweep2wake_pwrtrigger(); + } + } + //top->bottom + if (x < s2w_begin_h && (s2w_switch & SWEEP_DOWN)) { + tripon_hd = 1; + triptime_hd = time; + } else if (tripon_hd == 1 && x > 748 && time - triptime_hd < 25) { + tripon_hd = 2; + } else if (tripon_hd == 2 && x > 1496 && time - triptime_hd < 45) { + tripon_hd = 3; + } else if (tripon_hd == 3 && x > s2w_end_h && (time - triptime_hd < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: ON"); + if (gestures_switch) { + report_gesture(4); + } else { + sweep2wake_pwrtrigger(); + } + } + //bottom->top + if (x > s2w_end_h && (s2w_switch & SWEEP_UP)) { + tripon_hu = 1; + triptime_hu = time; + } else if (tripon_hu == 1 && x < 1496 && time - triptime_hu < 25) { + tripon_hu = 2; + } else if (tripon_hu == 2 && x < 748 && time - triptime_hu < 45) { + tripon_hu = 3; + } else if (tripon_hu == 3 && x < s2w_begin_h && (time - triptime_hu < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: ON"); + if (gestures_switch) { + report_gesture(3); + } else { + sweep2wake_pwrtrigger(); + } + } + } + + if (scr_suspended == false && s2s_switch) { + //right->left portrait mode normal + if (y > s2w_end_v && x > 2140 && (s2w_orientation == 0 || s2w_orientation == 1)) { + tripoff_vl = 1; + triptime_vl = time; + } else if (tripoff_vl == 1 && y < 896 && time - triptime_vl < 20) { + tripoff_vl = 2; + } else if (tripoff_vl == 2 && y < 488 && time - triptime_vl < 40) { + tripoff_vl = 3; + } else if (tripoff_vl == 3 && y < (s2w_begin_v) && (time - triptime_vl < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: OFF"); + sweep2wake_pwrtrigger(); + } + //left->right portrait mode upside down + if (y < s2w_begin_v && x < 100 && (s2w_orientation == 0 || s2w_orientation == 1)) { + tripoff_vr = 1; + triptime_vr = time; + } else if (tripoff_vr == 1 && y > 488 && time - triptime_vr < 20) { + tripoff_vr = 2; + } else if (tripoff_vr == 2 && y > 896 && time - triptime_vr < 40) { + tripoff_vr = 3; + } else if (tripoff_vr == 3 && y > s2w_end_v && time - triptime_vr < S2W_TIMEOUT) { + printk(KERN_INFO "[s2w]: OFF"); + sweep2wake_pwrtrigger(); + } + //top->bottom + if (x < s2w_begin_h && y > 1244 && (s2w_orientation == 0 || s2w_orientation == 2)) { + tripoff_hd = 1; + triptime_hd = time; + } else if (tripoff_hd == 1 && x > 748 && time - triptime_hd < 25) { + tripoff_hd = 2; + } else if (tripoff_hd == 2 && x > 1496 && time - triptime_hd < 45) { + tripoff_hd = 3; + } else if (tripoff_hd == 3 && x > s2w_end_h && (time - triptime_hd < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: OFF"); + sweep2wake_pwrtrigger(); + } + //bottom->top + if (x > s2w_end_h && y < 100 && (s2w_orientation == 0 || s2w_orientation == 2)) { + tripoff_hu = 1; + triptime_hu = time; + } else if (tripoff_hu == 1 && x < 1496 && time - triptime_hu < 25) { + tripoff_hu = 2; + } else if (tripoff_hu == 2 && x < 748 && time - triptime_hu < 45) { + tripoff_hu = 3; + } else if (tripoff_hu == 3 && x < s2w_begin_h && (time - triptime_hu < S2W_TIMEOUT)) { + printk(KERN_INFO "[s2w]: OFF"); + sweep2wake_pwrtrigger(); + } + } +} + +static void reset_dt2w(void) +{ + dt2w_x[0] = 0; + dt2w_x[1] = 0; + dt2w_y[0] = 0; + dt2w_y[1] = 0; + dt2w_time[0] = 0; + dt2w_time[1] = 0; +} + +static void doubletap2wake_func(int x, int y) +{ + + printk("dt2w x=%d y=%d\n", x, y); + + if (x >= 0) { + + last_x = x; + last_y = y; + } + + if (x < 0) { + dt2w_x[1] = dt2w_x[0]; + dt2w_x[0] = last_x; + dt2w_y[1] = dt2w_y[0]; + dt2w_y[0] = last_y; + + dt2w_time[1] = dt2w_time[0]; + dt2w_time[0] = jiffies; + + //printk("dt2w x0=%d x1=%d time0=%lu time1=%lu\n", dt2w_x[0], dt2w_x[1], dt2w_time[0], dt2w_time[1]); + + if ((dt2w_time[0] - dt2w_time[1]) < DT2W_TIMEOUT_MAX) { + + if ((abs(dt2w_x[0]-dt2w_x[1]) < DT2W_DELTA) && (abs(dt2w_y[0]-dt2w_y[1]) < DT2W_DELTA)) { + //printk("dt2w OFF->ON\n"); + reset_dt2w(); + if (gestures_switch) { + report_gesture(5); + } else { + sweep2wake_pwrtrigger(); + } + } + } + } + + return; +} + +static int __init get_s2w_opt(char *s2w) +{ + if (strcmp(s2w, "0") == 0) { + s2w_switch = 0; + } else if (strcmp(s2w, "1") == 0) { + s2w_switch = 1; + } else if (strcmp(s2w, "2") == 0) { + s2w_switch = 2; + } else { + s2w_switch = 0; + } + return 1; +} + +__setup("s2w=", get_s2w_opt); + +static int __init get_dt2w_opt(char *dt2w) +{ + if (strcmp(dt2w, "0") == 0) { + dt2w_switch = 0; + } else if (strcmp(dt2w, "1") == 0) { + dt2w_switch = 1; + } else { + dt2w_switch = 0; + } + return 1; +} + +__setup("dt2w=", get_dt2w_opt); + +static int __init get_shortsweep_opt(char *shorts) +{ + if (strcmp(shorts, "0") == 0) { + shortsweep = 0; + } else if (strcmp(shorts, "1") == 0) { + shortsweep = 1; + } else { + shortsweep = 0; + } + + if (shortsweep) { + s2w_begin_v = 400 ; + s2w_end_v = 950; + s2w_begin_h = 650; + s2w_end_h = 1600; + } else { + s2w_begin_v = 150; + s2w_end_v = 1200; + s2w_begin_h = 350; + s2w_end_h = 1900; + } + + return 1; +} + +__setup("shorts=", get_shortsweep_opt); + + +static int __init get_orient_opt(char *orient) +{ + if (strcmp(orient, "0") == 0) { + s2w_orientation = 0; + } else if (strcmp(orient, "1") == 0) { + s2w_orientation = 1; + } else if (strcmp(orient, "2") == 0) { + s2w_orientation = 2; + } else { + s2w_orientation = 0; + } + return 1; +} + +__setup("orient=", get_orient_opt); + +static int __init get_pwr_key_opt(char *pwr_key) +{ + if (strcmp(pwr_key, "0") == 0) { + pwrkey_suspend = 0; + } else if (strcmp(pwr_key, "1") == 0) { + pwrkey_suspend = 1; + } else { + pwrkey_suspend = 0; + } + return 1; +} + +__setup("pwr_key=", get_pwr_key_opt); + +static int __init get_lid_suspend_opt(char *lid_sus) +{ + if (strcmp(lid_sus, "0") == 0) { + lid_suspend = 0; + } else if (strcmp(lid_sus, "1") == 0) { + lid_suspend = 1; + } else { + lid_suspend = 0; + } + return 1; +} + +__setup("lid_sus=", get_lid_suspend_opt); + +/* end sweep2wake */ + + int elan_iap_open(struct inode *inode, struct file *filp){ touch_debug(DEBUG_INFO, "[ELAN]into elan_iap_open\n"); if (private_ts == NULL) touch_debug(DEBUG_ERROR, "private_ts is NULL~~~"); @@ -381,6 +775,214 @@ static ssize_t elan_show_status(struct device *dev, struct device_attribute *dev DEVICE_ATTR(elan_touchpanel_status, S_IRUGO, elan_show_status, NULL); + + +/* sweep2wake sysfs */ +static ssize_t elan_ktf3k_sweep2wake_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + + if (s2w_switch == s2w_switch_temp ) + count += sprintf(buf, "%d\n", s2w_switch); + else + count += sprintf(buf, "%d->%d\n", s2w_switch, s2w_switch_temp); + + return count; +} + +static ssize_t elan_ktf3k_sweep2wake_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + sscanf(buf, "%d ", &s2w_switch_temp); + if (s2w_switch_temp < 0 || s2w_switch_temp > 15) + s2w_switch_temp = 15; + + if (!scr_suspended) + s2w_switch = s2w_switch_temp; + else + s2w_changed = 1; + + return count; +} + +static DEVICE_ATTR(sweep2wake, (S_IWUSR|S_IRUGO), + elan_ktf3k_sweep2wake_show, elan_ktf3k_sweep2wake_dump); + +static ssize_t elan_ktf3k_wake_gestures_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + + count += sprintf(buf, "%d\n", gestures_switch); + + return count; +} + +static ssize_t elan_ktf3k_wake_gestures_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '2' && buf[1] == '\n') + if (gestures_switch != buf[0] - '0') + gestures_switch = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(wake_gestures, (S_IWUSR|S_IRUGO), + elan_ktf3k_wake_gestures_show, elan_ktf3k_wake_gestures_dump); + +static ssize_t elan_ktf3k_sweep2sleep_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + + count += sprintf(buf, "%d\n", s2s_switch); + return count; +} + +static ssize_t elan_ktf3k_sweep2sleep_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (s2s_switch != buf[0] - '0') + s2s_switch = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(sweep2sleep, (S_IWUSR|S_IRUGO), + elan_ktf3k_sweep2sleep_show, elan_ktf3k_sweep2sleep_dump); + +static ssize_t elan_ktf3k_pwrkey_suspend_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", pwrkey_suspend); + return count; +} + +static ssize_t elan_ktf3k_pwrkey_suspend_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (pwrkey_suspend != buf[0] - '0') + pwrkey_suspend = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(pwrkey_suspend, (S_IWUSR|S_IRUGO), + elan_ktf3k_pwrkey_suspend_show, elan_ktf3k_pwrkey_suspend_dump); + +static ssize_t elan_ktf3k_lid_suspend_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", lid_suspend); + return count; +} + +static ssize_t elan_ktf3k_lid_suspend_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (lid_suspend != buf[0] - '0') + lid_suspend = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(lid_suspend, (S_IWUSR|S_IRUGO), + elan_ktf3k_lid_suspend_show, elan_ktf3k_lid_suspend_dump); + + +static ssize_t elan_ktf3k_orientation_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", s2w_orientation); + return count; +} + +static ssize_t elan_ktf3k_orientation_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '2' && buf[1] == '\n') + if (s2w_orientation != buf[0] - '0') + s2w_orientation = buf[0] - '0'; + + return count; +} + +static DEVICE_ATTR(orientation, (S_IWUSR|S_IRUGO), + elan_ktf3k_orientation_show, elan_ktf3k_orientation_dump); + +static ssize_t elan_ktf3k_shortsweep_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + size_t count = 0; + count += sprintf(buf, "%d\n", shortsweep); + return count; +} + +static ssize_t elan_ktf3k_shortsweep_dump(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (shortsweep != buf[0] - '0') + shortsweep = buf[0] - '0'; + + if (shortsweep) { + s2w_begin_v = 400 ; + s2w_end_v = 950; + s2w_begin_h = 650; + s2w_end_h = 1750; + } else { + s2w_begin_v = 150; + s2w_end_v = 1200; + s2w_begin_h = 350; + s2w_end_h = 1900; + } + + return count; +} + +static DEVICE_ATTR(shortsweep, (S_IWUSR|S_IRUGO), + elan_ktf3k_shortsweep_show, elan_ktf3k_shortsweep_dump); + +static ssize_t elan_ktf3k_doubletap2wake_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + size_t count = 0; + + if (dt2w_switch == dt2w_switch_temp) + count += sprintf(buf, "%d\n", dt2w_switch); + else + count += sprintf(buf, "%d->%d\n", dt2w_switch, dt2w_switch_temp); + + return count; +} + +static ssize_t elan_ktf3k_doubletap2wake_dump(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + if (buf[0] >= '0' && buf[0] <= '1' && buf[1] == '\n') + if (dt2w_switch != buf[0] - '0') { + dt2w_switch_temp = buf[0] - '0'; + if (!scr_suspended) + dt2w_switch = dt2w_switch_temp; + else + dt2w_changed = 1; + } + + return count; +} + +static DEVICE_ATTR(doubletap2wake, (S_IWUSR|S_IRUGO), + elan_ktf3k_doubletap2wake_show, elan_ktf3k_doubletap2wake_dump); + +/* end sweep2wake sysfs*/ + + static int check_fw_version(const unsigned char*firmware, unsigned int size, int fw_version){ int id, version; @@ -404,12 +1006,11 @@ static int check_fw_version(const unsigned char*firmware, unsigned int size, int } - -/* +/* Reenable forced firmware update through sysfs */ static ssize_t update_firmware(struct device *dev, struct device_attribute *devattr,const char *buf, size_t count) { struct i2c_client *client = to_i2c_client(dev); - struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); + //struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); struct file *firmware_fp; char file_path[100]; unsigned int pos = 0; @@ -438,10 +1039,12 @@ static ssize_t update_firmware(struct device *dev, struct device_attribute *deva } filp_close(firmware_fp, NULL); // check the firmware ID and version - if(RECOVERY || check_fw_version(firmware, pos, ts->fw_ver) > 0){ + // force into firmware updating + if(RECOVERY || 1 /* check_fw_version(firmware, pos, ts->fw_ver ) */ > 0){ touch_debug(DEBUG_INFO, "Firmware update start!\n"); do{ -// ret = firmware_update_header(client, firmware, page_number);//add by mars + // reenable firmware update through sysfs by uncommenting following line + ret = firmware_update_header(client, firmware, page_number);//add by mars touch_debug(DEBUG_INFO, "Firmware update finish ret=%d retry=%d !\n", ret, retry++); }while(ret != 0 && retry < 3); if(ret == 0 && RECOVERY) RECOVERY = 0; @@ -450,21 +1053,35 @@ static ssize_t update_firmware(struct device *dev, struct device_attribute *deva return count; } -*/ -//DEVICE_ATTR(update_fw, S_IWUSR, NULL, update_firmware); +// Reenable forced firmware update through sysfs +DEVICE_ATTR(update_fw, S_IWUSR, NULL, update_firmware); static struct attribute *elan_attr[] = { &dev_attr_elan_touchpanel_status.attr, &dev_attr_vendor.attr, &dev_attr_gpio.attr, - //&dev_attr_update_fw.attr, +// Renable forced firmware update through sysfs + &dev_attr_update_fw.attr, +/* sweep2wake sysfs */ + &dev_attr_sweep2wake.attr, + &dev_attr_sweep2sleep.attr, + &dev_attr_wake_gestures.attr, + &dev_attr_doubletap2wake.attr, + &dev_attr_shortsweep.attr, + &dev_attr_pwrkey_suspend.attr, + &dev_attr_lid_suspend.attr, + &dev_attr_orientation.attr, NULL }; +#ifdef CONFIG_WAKE_TIMEOUT +struct kobject *android_touch_kobj; +#else static struct kobject *android_touch_kobj; +#endif + -/* static int elan_ktf3k_touch_sysfs_init(void) { int ret ; @@ -475,7 +1092,7 @@ static int elan_ktf3k_touch_sysfs_init(void) ret = -ENOMEM; return ret; } - ret = sysfs_create_file(android_touch_kobj, &dev_attr_gpio.attr); +/* ret = sysfs_create_file(android_touch_kobj, &dev_attr_gpio.attr); if (ret) { touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_file failed\n", __func__); return ret; @@ -485,13 +1102,64 @@ static int elan_ktf3k_touch_sysfs_init(void) touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); return ret; } +*/ +/* sweep2wake sysfs */ + ret = sysfs_create_file(android_touch_kobj, &dev_attr_sweep2wake.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_wake_gestures.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_sweep2sleep.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_doubletap2wake.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_shortsweep.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_pwrkey_suspend.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_lid_suspend.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } + ret = sysfs_create_file(android_touch_kobj, &dev_attr_orientation.attr); + if (ret) { + touch_debug(DEBUG_ERROR, "[elan]%s: sysfs_create_group failed\n", __func__); + return ret; + } return 0 ; } -*/ + static void elan_touch_sysfs_deinit(void) { - sysfs_remove_file(android_touch_kobj, &dev_attr_vendor.attr); - sysfs_remove_file(android_touch_kobj, &dev_attr_gpio.attr); +// sysfs_remove_file(android_touch_kobj, &dev_attr_vendor.attr); +// sysfs_remove_file(android_touch_kobj, &dev_attr_gpio.attr); +/* sweep2wake sysfs */ + sysfs_remove_file(android_touch_kobj, &dev_attr_sweep2wake.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_wake_gestures.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_sweep2sleep.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_doubletap2wake.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_shortsweep.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_pwrkey_suspend.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_lid_suspend.attr); + sysfs_remove_file(android_touch_kobj, &dev_attr_orientation.attr); kobject_del(android_touch_kobj); } @@ -549,11 +1217,11 @@ static int elan_ktf3k_ts_get_data(struct i2c_client *client, uint8_t *cmd, static int elan_ktf3k_ts_read_command(struct i2c_client *client, u8* cmd, u16 cmd_length, u8 *value, u16 value_length){ - struct i2c_adapter *adapter = client->adapter; + struct i2c_adapter *adapter = client->adapter; struct i2c_msg msg[2]; //__le16 le_addr; struct elan_ktf3k_ts_data *ts; - int length = 0; + int retry = 0; ts = i2c_get_clientdata(client); @@ -562,23 +1230,28 @@ static int elan_ktf3k_ts_read_command(struct i2c_client *client, msg[0].len = cmd_length; msg[0].buf = cmd; - down(&pSem); - length = i2c_transfer(adapter, msg, 1); - up(&pSem); - - if (length == 1) // only send on packet - return value_length; - else - return -EIO; + for (retry = 0; retry <= ELAN_I2C_RETRY; retry++) { + down(&pSem); + if (i2c_transfer(adapter, msg, 1) == 1) { + up(&pSem); + return value_length; + } + up(&pSem); + if (retry == ELAN_I2C_RETRY) { + return -EIO; + } else + msleep(10); + } + return 0; } static int elan_ktf3k_i2c_read_packet(struct i2c_client *client, u8 *value, u16 value_length){ - struct i2c_adapter *adapter = client->adapter; + struct i2c_adapter *adapter = client->adapter; struct i2c_msg msg[1]; //__le16 le_addr; struct elan_ktf3k_ts_data *ts; - int length = 0; + int retry = 0; ts = i2c_get_clientdata(client); @@ -586,14 +1259,20 @@ static int elan_ktf3k_i2c_read_packet(struct i2c_client *client, msg[0].flags = I2C_M_RD; msg[0].len = value_length; msg[0].buf = (u8 *) value; - down(&pSem); - length = i2c_transfer(adapter, msg, 1); - up(&pSem); - - if (length == 1) // only send on packet - return value_length; - else - return -EIO; + + for (retry = 0; retry <= ELAN_I2C_RETRY; retry++) { + down(&pSem); + if (i2c_transfer(adapter, msg, 1) == 1) { + up(&pSem); + return value_length; + } + up(&pSem); + if (retry == ELAN_I2C_RETRY) { + return -EIO; + } else + msleep(10); + } + return 0; } static int __hello_packet_handler(struct i2c_client *client) @@ -792,6 +1471,13 @@ static int elan_ktf3k_ts_set_power_state(struct i2c_client *client, int state) return 0; } +#ifdef CONFIG_WAKE_TIMEOUT +void ext_elan_ktf3k_ts_set_power_state(void) +{ + elan_ktf3k_ts_set_power_state(private_ts->client, PWR_STATE_DEEP_SLEEP); +} +#endif + static int elan_ktf3k_ts_rough_calibrate(struct i2c_client *client){ uint8_t cmd[] = {CMD_W_PKT, 0x29, 0x00, 0x01}; int length; @@ -909,29 +1595,33 @@ void touch_callback(unsigned cable_status){ static int elan_ktf3k_ts_recv_data(struct i2c_client *client, uint8_t *buf, int size) { - int rc, bytes_to_recv = size; + int retry = 0, bytes_to_recv = size; if (buf == NULL) return -EINVAL; memset(buf, 0, bytes_to_recv); - rc = i2c_master_recv(client, buf, bytes_to_recv); - if (rc != bytes_to_recv) { - dev_err(&client->dev, - "[elan] %s: i2c_master_recv error?! \n", __func__); - rc = i2c_master_recv(client, buf, bytes_to_recv); - return -EINVAL; + for (retry = 0; retry <= ELAN_I2C_RETRY; retry++) { + if (i2c_master_recv(client, buf, bytes_to_recv) == bytes_to_recv) + return bytes_to_recv; + if (retry == ELAN_I2C_RETRY) { + dev_err(&client->dev, + "[elan] %s: i2c_master_recv error?! \n", __func__); + (void) i2c_master_recv(client, buf, bytes_to_recv); + return -EINVAL; + } else + msleep(10); } - return rc; + return -EINVAL; } static void elan_ktf3k_ts_report_data(struct i2c_client *client, uint8_t *buf) { struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); struct input_dev *idev = ts->input_dev; - uint16_t x, y, touch_size, pressure_size; + uint16_t x = 0, y = 0, touch_size, pressure_size; uint16_t fbits=0, checksum=0; uint8_t i, num; static uint8_t size_index[10] = {35, 35, 36, 36, 37, 37, 38, 38, 39, 39}; @@ -961,19 +1651,21 @@ static void elan_ktf3k_ts_report_data(struct i2c_client *client, uint8_t *buf) input_report_abs(idev, ABS_MT_POSITION_X, y); input_report_abs(idev, ABS_MT_POSITION_Y, x); if(unlikely(gPrint_point)) touch_debug(DEBUG_INFO, "[elan] finger id=%d X=%d y=%d size=%d pressure=%d\n", i, x, y, touch_size, pressure_size); - } + + } } mTouchStatus[i] = active; fbits = fbits >> 1; idx += 3; } + input_sync(idev); } // checksum else { checksum_err +=1; touch_debug(DEBUG_ERROR, "[elan] Checksum Error %d byte[2]=%X\n", checksum_err, buf[2]); } - + return; } @@ -987,43 +1679,62 @@ static void elan_ktf3k_ts_report_data2(struct i2c_client *client, uint8_t *buf) uint16_t active = 0; uint8_t idx=IDX_FINGER; - num = buf[2] & 0xf; + num = buf[2] & 0xf; for (i=0; i<34;i++) checksum +=buf[i]; - + if ( (num < 3) || ((checksum & 0x00ff) == buf[34])) { - fbits = buf[2] & 0x30; - fbits = (fbits << 4) | buf[1]; - //input_report_key(idev, BTN_TOUCH, 1); - for(i = 0; i < FINGER_NUM; i++){ - active = fbits & 0x1; - if(active || mTouchStatus[i]){ - input_mt_slot(ts->input_dev, i); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, active); - if(active){ - elan_ktf3k_ts_parse_xy(&buf[idx], &x, &y); - x = x > ts->abs_x_max ? 0 : ts->abs_x_max - x; - y = y > ts->abs_y_max ? ts->abs_y_max : y; - touch_size = buf[35 + i]; - pressure_size = buf[45 + i]; - input_report_abs(idev, ABS_MT_TOUCH_MAJOR, touch_size); - input_report_abs(idev, ABS_MT_PRESSURE, pressure_size); - input_report_abs(idev, ABS_MT_POSITION_X, y); - input_report_abs(idev, ABS_MT_POSITION_Y, x); - if(unlikely(gPrint_point)) touch_debug(DEBUG_INFO, "[elan] finger id=%d X=%d y=%d size=%d pressure=%d\n", i, x, y, touch_size, pressure_size); - } - } - mTouchStatus[i] = active; - fbits = fbits >> 1; - idx += 3; - } - input_sync(idev); + fbits = buf[2] & 0x30; + fbits = (fbits << 4) | buf[1]; + + //input_report_key(idev, BTN_TOUCH, 1); + + for(i = 0; i < FINGER_NUM; i++){ + active = fbits & 0x1; + if(active || mTouchStatus[i]){ + input_mt_slot(ts->input_dev, i); + input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, active); + if(active){ + elan_ktf3k_ts_parse_xy(&buf[idx], &x, &y); + x = x > ts->abs_x_max ? 0 : ts->abs_x_max - x; + y = y > ts->abs_y_max ? ts->abs_y_max : y; + touch_size = buf[35 + i]; + pressure_size = buf[45 + i]; + input_report_abs(idev, ABS_MT_TOUCH_MAJOR, touch_size); + input_report_abs(idev, ABS_MT_PRESSURE, pressure_size); + input_report_abs(idev, ABS_MT_POSITION_X, y); + input_report_abs(idev, ABS_MT_POSITION_Y, x); + if(unlikely(gPrint_point)) + touch_debug(DEBUG_INFO, "[elan] finger id=%d X=%d y=%d size=%d pressure=%d\n", i, x, y, touch_size, pressure_size); + /* sweep2wake */ + if (s2w_switch || s2s_switch) + sweep2wake_func(x, y, jiffies, i); + if (dt2w_switch && scr_suspended) + doubletap2wake_func(x, y); + /* end sweep2wake */ + } + } + mTouchStatus[i] = active; + fbits = fbits >> 1; + idx += 3; + } + input_sync(idev); } // checksum + else { checksum_err +=1; touch_debug(DEBUG_ERROR, "[elan] Checksum Error %d byte[2]=%X\n", checksum_err, buf[2]); } + /* sweep2wake */ + if (checksum == 99) { + if (s2w_switch || s2s_switch) + sweep2wake_func(-1, -1, jiffies, i); + if (dt2w_switch && scr_suspended) + doubletap2wake_func(-1, -1); + } + /* end sweep2wake */ + return; } @@ -1573,6 +2284,22 @@ static int elan_ktf3k_ts_probe(struct i2c_client *client, elan_ktf3k_ts_irq_handler(client->irq, ts); } + +// Wake Gestures + gesture_dev = input_allocate_device(); + if (!gesture_dev) { + pr_err("%s: input_allocate_device error\n", __func__); + } + + gesture_dev->name = "wake_gesture"; + gesture_dev->phys = "wake_gesture/input0"; + input_set_capability(gesture_dev, EV_REL, WAKE_GESTURE); + + err = input_register_device(gesture_dev); + if (err) { + pr_err("%s: input_register_device err=%d\n", __func__, err); + } +// end Wake Gestures #ifdef FIRMWARE_UPDATE_WITH_HEADER if (RECOVERY || check_fw_version(touch_firmware, sizeof(touch_firmware), ts->fw_ver) > 0) @@ -1588,7 +2315,7 @@ static int elan_ktf3k_ts_probe(struct i2c_client *client, private_ts = ts; - //elan_ktf2k_touch_sysfs_init(); + elan_ktf3k_touch_sysfs_init(); ts->attrs.attrs = elan_attr; err = sysfs_create_group(&client->dev.kobj, &ts->attrs); if (err) { @@ -1711,14 +2438,27 @@ static int elan_ktf3k_ts_suspend(struct i2c_client *client, pm_message_t mesg) int rc = 0; touch_debug(DEBUG_INFO, "[elan] %s: enter\n", __func__); - disable_irq(client->irq); + +/*s2w*/ + if ((s2w_switch || dt2w_switch) ) { + enable_irq_wake(client->irq); + } else { + disable_irq(client->irq); + } + force_release_pos(client); rc = cancel_work_sync(&ts->work); if (rc) enable_irq(client->irq); - if(work_lock == 0) - rc = elan_ktf3k_ts_set_power_state(client, PWR_STATE_DEEP_SLEEP); +/*s2w*/ + if(((!s2w_switch && !dt2w_switch) || (lid_suspend && lid_closed) || (pwrkey_suspend && pwr_key_pressed)) && work_lock == 0) { + pwr_key_pressed = 0; + lid_closed = 0; + rc = elan_ktf3k_ts_set_power_state(client, PWR_STATE_DEEP_SLEEP); + } +/*s2w*/ + scr_suspended = true; return 0; } @@ -1727,8 +2467,8 @@ static int elan_ktf3k_ts_resume(struct i2c_client *client) { int rc = 0, retry = 5; - //struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); - //int delay_time; + //struct elan_ktf3k_ts_data *ts = i2c_get_clientdata(client); + //int delay_time; //gpio_direction_output(31, 0); @@ -1745,7 +2485,24 @@ static int elan_ktf3k_ts_resume(struct i2c_client *client) } while (--retry); } //force_release_pos(client); - enable_irq(client->irq); + +/* s2w */ + if (s2w_switch || dt2w_switch) { + disable_irq_wake(client->irq); + } else { + enable_irq(client->irq); + } + + if (s2w_changed) + s2w_switch = s2w_switch_temp; + if (dt2w_changed) + dt2w_switch = dt2w_switch_temp; + + scr_suspended = false; + pwr_key_pressed = 0; + lid_closed = 0; +/* end s2w */ + return 0; } diff --git a/drivers/input/touchscreen/fw_data.b b/drivers/input/touchscreen/fw_data.b index 714c55c4945..d4b4bd6b062 100755 --- a/drivers/input/touchscreen/fw_data.b +++ b/drivers/input/touchscreen/fw_data.b @@ -1,91 +1,91 @@ 0xc0, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x5f, 0x40, 0x02, 0x98, 0x3f, 0x5e, 0x52, 0x98, 0x3f, 0x5f, 0x52, 0x98, 0x3f, 0x60, 0x52, 0x98, 0x3f, 0xc2, 0x52, 0x98, 0x3f, 0xc3, 0x52, 0x98, 0x3f, 0xc4, 0x52, 0x98, 0x3f, 0xc9, 0x52, 0x98, 0x3f, 0xce, 0x52, 0x98, 0x3f, 0xcf, 0x52, 0x98, 0x3f, 0xd0, 0x52, 0x98, 0x3f, 0xd1, 0x52, 0x98, 0x3f, 0xd2, 0x52, 0x98, 0x3f, 0xd3, 0x52, 0x98, 0x3f, 0xd4, 0x52, 0x98, 0x3f, 0xd5, 0x52, 0x98, 0x3f, 0xd6, 0x52, 0x98, 0x3f, 0xd7, 0x52, 0x98, 0x3f, 0xd8, 0x52, 0x98, 0x3f, 0xd9, 0x52, 0x98, 0x3f, 0xda, 0x52, 0x98, 0x3f, 0xdb, 0x52, 0x98, 0x3f, 0xdc, 0x52, 0x98, 0x3f, 0xdd, 0x52, 0x98, 0x3f, 0xde, 0x52, 0x98, 0x3f, 0xdf, 0x52, 0x98, 0x3f, 0xe0, 0x52, 0x98, 0x3f, 0xf4, 0x52, 0x98, 0x3f, 0xf5, 0x52, 0x98, 0x3f, 0x04, 0x53, 0x98, 0x3f, 0x05, 0x53, 0x98, 0x3f, 0x9c, 0x50, 0x98, 0x3f, 0x06, 0x53, 0xf8, 0x4c, 0x80, 0x02, 0x98, 0x3f, 0xdc, 0x53, 0x98, 0x3f, 0xdd, 0x53, 0x1a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xbd, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0xbe, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0xbf, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0xc1, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x1f, 0x00, 0x60, 0xbe, 0x58, 0x1c, 0x1f, 0x7a, 0xad, 0xfe, 0x93, 0x1a, 0x38, 0x02, 0xa9, 0x00, 0xbc, 0xb1, 0x00, 0x48, 0xaa, 0x40, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0xf2, 0x62, 0x72, 0x6a, 0x40, 0xbd, 0xb0, 0x00, 0x02, 0xab, 0x1a, 0x38, 0x02, 0x60, 0x80, 0x68, 0xb2, 0x61, 0x2f, 0x38, 0xae, 0x02, 0x0b, 0x5a, 0x8a, 0xb9, 0x19, 0x01, 0x7a, 0xad, 0xfe, 0x93, 0x04, 0x60, 0x80, 0x68, 0xb4, 0x61, 0x6f, 0x38, 0xb8, 0x02, 0x0b, 0x5a, 0x8a, 0xb9, 0x19, 0x01, 0x1a, 0x38, 0x7f, 0x60, 0x1f, 0x68, 0x91, 0xb0, 0x1f, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0xe2, 0x36, -0xc0, 0x02, 0x16, 0x00, 0x41, 0xa9, 0xff, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0x91, 0x00, 0x80, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0x96, 0x00, 0x41, 0xab, 0x5a, 0xa9, 0x51, 0x60, 0x0b, 0x68, 0x1e, 0x58, 0x5a, 0xab, 0x00, 0x60, 0x82, 0xb0, 0xed, 0xc6, 0xe5, 0xc6, 0x19, 0x38, 0x20, 0x5a, 0xbe, 0xa8, 0xe0, 0xa8, 0xcf, 0xc6, 0xf4, 0xc6, 0x94, 0xef, 0x19, 0x38, 0x24, 0x5a, 0xb9, 0xfc, 0xfa, 0xc7, 0xaf, 0x61, 0x1a, 0x69, 0x78, 0xa9, 0x94, 0xa9, 0x92, 0xaa, 0x82, 0xaa, 0x53, 0xc7, 0x1a, 0xc7, 0x19, 0x38, 0x22, 0x5a, 0xff, 0xf0, 0xa7, 0xaa, 0xd7, 0xc8, 0x64, 0xee, 0x92, 0xac, 0xfe, 0x91, 0x18, 0xc5, 0xde, 0xc5, 0x8a, 0xc7, 0xe5, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0xf5, 0xac, 0x00, 0x92, 0x4f, 0x8e, -0x00, 0x03, 0x8f, 0xa8, 0x97, 0xaa, 0x58, 0xd9, 0xed, 0xac, 0x03, 0x92, 0x19, 0x38, 0x91, 0x4b, 0x02, 0x9e, 0x19, 0x38, 0xde, 0x53, 0x02, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0x01, 0xc9, 0x19, 0x38, 0xd9, 0x54, 0x04, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0x08, 0x60, 0x1e, 0x58, 0x9a, 0xea, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0xbe, 0x58, 0xdd, 0x00, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x9a, 0xea, 0x3e, 0x58, 0x19, 0x00, 0x9c, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0x19, 0x38, 0x32, 0x4e, 0x02, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0x01, 0xc9, 0x19, 0x38, 0x1a, 0x55, 0x04, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0xf5, 0xaa, 0x08, 0x60, 0x1e, 0x58, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x00, 0xce, 0xc7, 0xe7, 0xc1, -0x40, 0x03, 0x18, 0x10, 0xf8, 0x89, 0xe5, 0xc8, 0xc5, 0xfc, 0xe5, 0xa8, 0x26, 0x60, 0x04, 0x68, 0x3e, 0x61, 0x04, 0x69, 0x9e, 0x5a, 0xbb, 0x00, 0x57, 0x38, 0x3d, 0x58, 0x1a, 0x38, 0x34, 0x60, 0x12, 0x68, 0xbe, 0x58, 0xbd, 0x1d, 0x78, 0x60, 0x56, 0x68, 0xbe, 0x58, 0xbe, 0x1d, 0xbc, 0x60, 0x9a, 0x68, 0xbe, 0x58, 0xbf, 0x1d, 0xaa, 0x60, 0x55, 0x68, 0xbe, 0x58, 0x1b, 0x1f, 0x55, 0x60, 0xaa, 0x68, 0xbe, 0x58, 0x1c, 0x1f, 0x1a, 0x38, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xf6, 0xeb, 0xf5, 0xac, 0x07, 0x90, 0x5d, 0xeb, 0x00, 0x60, 0xbe, 0x58, 0x40, 0x1b, 0xbe, 0x58, 0x3c, 0x02, 0x7e, 0x9f, 0xdd, 0xac, 0x5a, 0x90, 0xed, 0xac, 0x3c, 0x92, 0x8d, 0xac, 0x23, 0x92, 0x00, 0x9e, 0x9e, 0x58, 0x50, 0x01, 0xbe, 0x58, 0x00, 0xf8, 0x9e, 0x58, 0x83, 0xa6, +0xc0, 0x02, 0x16, 0x00, 0x41, 0xa9, 0xff, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0x91, 0x00, 0x80, 0x60, 0x1f, 0x68, 0x00, 0xbd, 0x96, 0x00, 0x41, 0xab, 0x5a, 0xa9, 0x4f, 0x60, 0x0b, 0x68, 0x1e, 0x58, 0x5a, 0xab, 0x00, 0x60, 0x82, 0xb0, 0xeb, 0xc6, 0xe3, 0xc6, 0x19, 0x38, 0x20, 0x5a, 0xbe, 0xa8, 0xe0, 0xa8, 0xcd, 0xc6, 0xf2, 0xc6, 0x94, 0xef, 0x19, 0x38, 0x24, 0x5a, 0xb9, 0xfc, 0xf8, 0xc7, 0xaf, 0x61, 0x1a, 0x69, 0x78, 0xa9, 0x94, 0xa9, 0x92, 0xaa, 0x82, 0xaa, 0x51, 0xc7, 0x18, 0xc7, 0x19, 0x38, 0x22, 0x5a, 0xff, 0xf0, 0xa7, 0xaa, 0xd5, 0xc8, 0x77, 0xee, 0x92, 0xac, 0xfe, 0x91, 0x16, 0xc5, 0xdc, 0xc5, 0x88, 0xc7, 0xe5, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0xf5, 0xac, 0x00, 0x92, 0x4a, 0x8e, +0x00, 0x03, 0x8f, 0xa8, 0x97, 0xaa, 0x58, 0xd9, 0xed, 0xac, 0x03, 0x92, 0x19, 0x38, 0x91, 0x4b, 0x02, 0x9e, 0x19, 0x38, 0xde, 0x53, 0x02, 0x60, 0x72, 0x68, 0x05, 0xec, 0xff, 0xc8, 0x19, 0x38, 0xd9, 0x54, 0x02, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0x05, 0xec, 0x08, 0x60, 0x1e, 0x58, 0xbc, 0xea, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0xbe, 0x58, 0xdd, 0x00, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0xbc, 0xea, 0x3e, 0x58, 0x19, 0x00, 0x9a, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0x19, 0x38, 0x32, 0x4e, 0x02, 0x60, 0x72, 0x68, 0x05, 0xec, 0xff, 0xc8, 0x19, 0x38, 0x1a, 0x55, 0x02, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0x05, 0xec, 0xf5, 0xaa, 0x08, 0x60, 0x1e, 0x58, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x00, 0xcc, 0xc7, 0xa7, 0xc2, +0x40, 0x03, 0x18, 0x10, 0xf8, 0x89, 0xe3, 0xc8, 0xc5, 0xfc, 0xe5, 0xa8, 0x26, 0x60, 0x04, 0x68, 0x3e, 0x61, 0x04, 0x69, 0x9e, 0x5a, 0xbb, 0x00, 0x57, 0x38, 0x3d, 0x58, 0x1a, 0x38, 0x34, 0x60, 0x12, 0x68, 0xbe, 0x58, 0xbd, 0x1d, 0x78, 0x60, 0x56, 0x68, 0xbe, 0x58, 0xbe, 0x1d, 0xbc, 0x60, 0x9a, 0x68, 0xbe, 0x58, 0xbf, 0x1d, 0xaa, 0x60, 0x55, 0x68, 0xbe, 0x58, 0x1b, 0x1f, 0x55, 0x60, 0xaa, 0x68, 0xbe, 0x58, 0x1c, 0x1f, 0x1a, 0x38, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x18, 0xec, 0xf5, 0xac, 0x07, 0x90, 0x7f, 0xeb, 0x00, 0x60, 0xbe, 0x58, 0x40, 0x1b, 0xbe, 0x58, 0x3c, 0x02, 0x7e, 0x9f, 0xdd, 0xac, 0x5a, 0x90, 0xed, 0xac, 0x3c, 0x92, 0x8d, 0xac, 0x23, 0x92, 0x00, 0x9e, 0x9e, 0x58, 0x50, 0x01, 0xbe, 0x58, 0x00, 0xf8, 0x9e, 0x58, 0xc5, 0xa6, 0x80, 0x03, 0xd5, 0x1a, 0xbe, 0x58, 0x02, 0xf8, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xd7, 0x1a, 0xbe, 0x58, 0x05, 0xf8, 0x9e, 0x58, 0xd8, 0x1a, 0xbe, 0x58, 0x0a, 0xf8, 0x9e, 0x58, 0x57, 0x01, 0xbe, 0x58, 0x0c, 0xf8, 0x9e, 0x58, 0x5b, 0x01, 0xbe, 0x58, 0x0b, 0xf8, 0x9e, 0x58, 0x07, 0xf8, 0x19, 0x28, 0xbe, 0x58, 0x07, 0xf8, 0x32, 0x9e, 0x9e, 0x58, 0x50, 0x01, 0xbe, 0x58, 0x00, 0xf8, 0x21, 0x60, 0xbe, 0x58, 0x02, 0xf8, 0x48, 0x60, 0xbe, 0x58, 0x04, 0xf8, 0x04, 0x60, 0xbe, 0x58, 0x05, 0xf8, 0x04, 0x60, 0xbe, 0x58, 0x0a, 0xf8, 0x64, 0x60, 0xbe, 0x58, 0x0c, 0xf8, 0x0b, 0x60, 0xbe, 0x58, 0x0b, 0xf8, 0x1b, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x00, 0xf8, 0x21, 0x60, 0xbe, 0x58, 0x02, 0xf8, 0x94, 0x60, 0xbe, 0x58, 0x04, 0xf8, 0x2d, 0x60, 0xbe, 0x58, 0x05, 0xf8, 0x23, 0xab, -0xc0, 0x03, 0x2d, 0x60, 0xbe, 0x58, 0x0a, 0xf8, 0x94, 0x60, 0xbe, 0x58, 0x0c, 0xf8, 0x0f, 0x60, 0xbe, 0x58, 0x0b, 0xf8, 0x9e, 0x58, 0x07, 0xf8, 0x04, 0x38, 0xfe, 0xff, 0xbe, 0x58, 0x07, 0xf8, 0xdd, 0xaa, 0xa5, 0xac, 0x01, 0x90, 0xf5, 0xc8, 0x77, 0xe9, 0x19, 0x38, 0xf2, 0x41, 0xed, 0xac, 0x7a, 0x92, 0xd5, 0xaa, 0xe5, 0xa8, 0x4b, 0xe5, 0x0c, 0xf1, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xf6, 0xeb, 0x9e, 0x58, 0x36, 0x1d, 0x1d, 0x10, 0x21, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0x1d, 0x8a, 0xdb, 0xf1, 0x86, 0xf6, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x1a, 0x9e, 0x58, 0xb8, 0x04, 0x18, 0x10, 0x14, 0x88, 0x9e, 0x58, 0xc6, 0x00, 0x19, 0x10, 0x10, 0x8a, 0x9e, 0x58, 0xea, 0x19, 0x00, 0x58, 0xbe, 0x58, 0xd3, 0x00, 0x9e, 0x58, 0xeb, 0x19, 0x59, 0xe2, -0x00, 0x04, 0x00, 0x58, 0xbe, 0x58, 0xd4, 0x00, 0x9e, 0x58, 0xec, 0x19, 0x00, 0x58, 0xbe, 0x58, 0xd5, 0x00, 0x0c, 0x9e, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd3, 0x00, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd4, 0x00, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd5, 0x00, 0x9e, 0x58, 0xfc, 0x01, 0x78, 0xac, 0x08, 0x90, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd5, 0x00, 0xbe, 0x58, 0xd4, 0x00, 0xbe, 0x58, 0xd3, 0x00, 0x7b, 0xeb, 0xb5, 0xea, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xf6, 0xeb, 0x26, 0x60, 0x04, 0x68, 0x3e, 0x61, 0x04, 0x69, 0x9e, 0x5a, 0xbb, 0x00, 0x57, 0x38, 0x3d, 0x58, 0x06, 0x70, 0x00, 0xac, 0x12, 0x90, 0x9e, 0x58, 0xfc, 0x1c, 0x18, 0x10, 0x0e, 0x88, 0x9e, 0x58, 0x47, 0x1e, 0x78, 0xac, 0x01, 0x90, 0x0d, 0x9e, 0x60, 0xed, 0xc4, 0xb6, -0x40, 0x04, 0x9e, 0x58, 0x1e, 0x1e, 0x18, 0x10, 0x0d, 0x8a, 0xdc, 0xec, 0x3c, 0xed, 0x4e, 0xed, 0x86, 0xed, 0x9e, 0x58, 0x47, 0x1e, 0x78, 0xac, 0x05, 0x90, 0x78, 0xaa, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x02, 0x9e, 0x9d, 0xf7, 0x00, 0x9e, 0x4f, 0xf7, 0x19, 0x38, 0xd7, 0x41, 0xe6, 0xff, 0x5e, 0xca, 0x91, 0xca, 0xc4, 0xca, 0x19, 0x38, 0xa1, 0x51, 0xba, 0xac, 0x0f, 0x92, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x78, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x34, 0xc8, 0xba, 0xac, 0x71, 0x92, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x67, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x95, 0xac, 0x05, 0x90, 0x8e, 0xd2, -0x80, 0x04, 0x9e, 0x5f, 0xfb, 0x04, 0xbe, 0x5f, 0xfb, 0x04, 0x95, 0xaa, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x52, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0xb9, 0xac, 0xd9, 0x91, 0xfd, 0xac, 0x1a, 0x90, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x40, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x80, 0x62, 0x57, 0x6a, 0x48, 0x63, 0x0e, 0x6b, 0x0c, 0x61, 0x24, 0x60, 0x01, 0x40, 0x19, 0x10, 0x07, 0x38, 0xb0, 0x04, 0x45, 0x5c, 0x9d, 0x5b, 0x85, 0xac, 0x1f, 0x90, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x24, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x10, 0x62, -0xc0, 0x04, 0xff, 0xa9, 0x48, 0x62, 0x0e, 0x6a, 0x7a, 0x63, 0x02, 0x6b, 0x9e, 0x5c, 0xbb, 0x00, 0x9e, 0x5d, 0xbc, 0x00, 0xa4, 0x05, 0x19, 0x15, 0xa7, 0x38, 0xd1, 0x04, 0x63, 0x5c, 0x83, 0x5d, 0xbb, 0x5a, 0x19, 0x02, 0x19, 0x03, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x05, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x58, 0xeb, 0x34, 0x61, 0x12, 0x69, 0x9e, 0x58, 0xbd, 0x1d, 0x38, 0x48, 0x02, 0x8a, 0x42, 0xa9, 0x0f, 0x9e, 0x78, 0x61, 0x56, 0x69, 0x9e, 0x58, 0xbe, 0x1d, 0x38, 0x48, 0x02, 0x8a, 0x42, 0xa9, 0x07, 0x9e, 0xbc, 0x61, 0x9a, 0x69, 0x9e, 0x58, 0xbf, 0x1d, 0x38, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x1a, 0x38, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0x4e, 0x4c, -0x00, 0x05, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xf6, 0xeb, 0x9e, 0x58, 0xf8, 0x04, 0x19, 0x00, 0xbe, 0x58, 0xf8, 0x04, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x06, 0x88, 0x9e, 0x58, 0x19, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x19, 0x1f, 0x42, 0xa9, 0x98, 0x3f, 0x62, 0x03, 0x9e, 0x5e, 0x50, 0x01, 0x00, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbc, 0x01, 0x01, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbd, 0x01, 0x1f, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbe, 0x01, 0x20, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbf, 0x01, 0x21, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd5, 0x1a, 0x02, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x51, 0x01, 0xc8, 0x58, 0xc0, 0x06, 0x08, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x52, 0x01, 0x03, 0x60, 0x18, 0x4e, -0x40, 0x05, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd6, 0x1a, 0x04, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd7, 0x1a, 0x05, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x55, 0x01, 0x06, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x56, 0x01, 0x07, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x57, 0x01, 0x0c, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x58, 0x01, 0x0e, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x59, 0x01, 0x12, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xba, 0x01, 0x09, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd8, 0x1a, 0x0a, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x5b, 0x01, 0x0b, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0xb4, 0x60, 0x01, 0x68, 0x22, 0x61, 0xf8, 0x69, 0xb9, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0xb4, 0x01, 0xc7, 0x38, 0x7f, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0xd1, 0xc0, -0x80, 0x05, 0x9e, 0x5e, 0x5c, 0x01, 0x0f, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x5d, 0x01, 0x10, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x5e, 0x60, 0x01, 0x68, 0x28, 0x61, 0xf8, 0x69, 0x63, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x5e, 0x01, 0xc7, 0x38, 0x95, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x9e, 0x5e, 0xbb, 0x01, 0x2e, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x64, 0x60, 0x01, 0x68, 0x2f, 0x61, 0xf8, 0x69, 0x6f, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x64, 0x01, 0xc7, 0x38, 0xa6, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x70, 0x60, 0x01, 0x68, 0x3b, 0x61, 0xf8, 0x69, 0x7b, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x70, 0x01, 0xc7, 0x38, 0xb2, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x7c, 0x60, 0x01, 0x68, 0x47, 0x61, 0xf8, 0x69, 0x52, 0x66, 0xf8, 0x6e, 0xc2, 0x3e, 0x47, 0xf8, 0xc7, 0x38, 0xc1, 0x05, 0x03, 0x5a, 0x05, 0x5b, 0xfe, 0x5b, 0x10, 0x49, -0xc0, 0x05, 0x43, 0x2a, 0x5d, 0x59, 0x94, 0x60, 0x01, 0x68, 0x53, 0x61, 0xf8, 0x69, 0x5e, 0x66, 0xf8, 0x6e, 0xc2, 0x3e, 0x53, 0xf8, 0xc7, 0x38, 0xd0, 0x05, 0x03, 0x5a, 0x05, 0x5b, 0xfe, 0x5b, 0x43, 0x2a, 0x5d, 0x59, 0xac, 0x60, 0x01, 0x68, 0x13, 0x61, 0xf8, 0x69, 0xb2, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0xac, 0x01, 0xc7, 0x38, 0xdc, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x3a, 0x38, 0x9e, 0x5e, 0xc3, 0x01, 0xaa, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xc7, 0x01, 0xaf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xc8, 0x01, 0xb0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd9, 0x1a, 0xb1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xca, 0x01, 0xb2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xcd, 0x01, 0xb5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xce, 0x01, 0xb6, 0x60, 0xf8, 0x68, 0xa3, 0x24, -0x00, 0x06, 0xdb, 0x58, 0x9e, 0x5e, 0xcf, 0x01, 0xb7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd0, 0x01, 0xd8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd1, 0x01, 0xb8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd3, 0x01, 0xba, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd4, 0x01, 0xbb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd5, 0x01, 0xbc, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd6, 0x01, 0xbd, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd7, 0x01, 0xbe, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd8, 0x01, 0xbf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd9, 0x01, 0xc0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xda, 0x01, 0xc1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdb, 0x01, 0xc2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdc, 0x01, 0xc3, 0x60, 0x58, 0x44, -0x40, 0x06, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdd, 0x01, 0xc4, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xde, 0x01, 0xc5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdf, 0x01, 0xc6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe0, 0x01, 0xc7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe1, 0x01, 0xc8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe2, 0x01, 0xc9, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe3, 0x01, 0xca, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe4, 0x01, 0xcb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe5, 0x01, 0xcc, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe6, 0x01, 0xcd, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe7, 0x01, 0xce, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe8, 0x01, 0xcf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe9, 0x01, 0xf6, 0x4d, -0x80, 0x06, 0xd0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xea, 0x01, 0xd1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xeb, 0x01, 0xd2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xec, 0x01, 0xd3, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xed, 0x01, 0xd4, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xee, 0x01, 0xd5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xef, 0x01, 0xd6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf0, 0x01, 0xd7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf1, 0x01, 0xea, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf2, 0x01, 0xeb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf3, 0x01, 0xec, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf4, 0x01, 0xed, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf5, 0x01, 0xee, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xaf, 0xae, -0xc0, 0x06, 0xf6, 0x01, 0xef, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf7, 0x01, 0xf0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf8, 0x01, 0xf1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x3a, 0x38, 0x00, 0xbc, 0xb1, 0x00, 0x18, 0xaa, 0x10, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0x60, 0x80, 0xb0, 0x00, 0x60, 0x81, 0xb0, 0x00, 0x60, 0x82, 0xb0, 0x00, 0x60, 0x83, 0xb0, 0x00, 0x60, 0x9c, 0xb0, 0xc0, 0x60, 0x13, 0x68, 0x9d, 0xb0, 0x00, 0x60, 0xcf, 0xb0, 0x3a, 0x38, 0x41, 0xab, 0x51, 0xb0, 0x78, 0xa8, 0x70, 0xa8, 0x68, 0xaa, 0x60, 0xaa, 0xd1, 0xb0, 0x3a, 0x38, 0x00, 0x60, 0x1f, 0x68, 0x00, 0x61, 0x00, 0x62, 0x17, 0x38, 0x5d, 0x59, 0x3a, 0x38, 0x3e, 0xb0, 0x08, 0xaa, 0x00, 0xaa, 0x18, 0xaa, 0x10, 0xaa, 0xbe, 0xb0, 0x10, 0x60, 0x9e, 0xb0, 0x30, 0xb0, 0x38, 0xa8, 0xb0, 0xb0, 0x3e, 0xb0, 0x53, 0x60, -0x00, 0x07, 0x38, 0xaa, 0xbe, 0xb0, 0x84, 0xb0, 0x3c, 0xa9, 0x3e, 0xb0, 0x78, 0xaa, 0xbe, 0xb0, 0x00, 0x60, 0x00, 0xbd, 0xaa, 0x00, 0x30, 0xb0, 0x08, 0xaa, 0x18, 0xaa, 0x00, 0xbd, 0x30, 0x00, 0x36, 0xb0, 0x08, 0xaa, 0x18, 0xaa, 0x00, 0xbd, 0x36, 0x00, 0x33, 0xb0, 0x08, 0xa8, 0x18, 0xa8, 0x00, 0xbd, 0x33, 0x00, 0x3a, 0x38, 0x04, 0x60, 0x69, 0x78, 0x55, 0x60, 0x6a, 0x78, 0x6b, 0x78, 0x6c, 0x78, 0x6d, 0x78, 0x82, 0xac, 0x28, 0x92, 0x00, 0x60, 0x88, 0x68, 0xae, 0xb0, 0x20, 0x60, 0xc4, 0x68, 0xd0, 0xb0, 0x1e, 0x59, 0x1e, 0x5a, 0x93, 0x60, 0x2f, 0x68, 0x09, 0x58, 0x04, 0x39, 0xff, 0x00, 0x04, 0x3a, 0x00, 0xff, 0xfe, 0x5a, 0x22, 0x32, 0xff, 0x61, 0x04, 0x38, 0xff, 0x00, 0x3a, 0x48, 0x01, 0x8a, 0x10, 0x60, 0xd2, 0xb0, 0x3e, 0x5a, 0x3e, 0x59, 0x00, 0x60, 0x5d, 0x78, 0x19, 0x38, 0xe3, 0xbf, -0x40, 0x07, 0x8c, 0x50, 0x92, 0xaa, 0xaa, 0xac, 0x01, 0x90, 0x92, 0xa8, 0xaa, 0xaa, 0xf9, 0xab, 0xf1, 0xab, 0xfd, 0xa9, 0xf5, 0xa9, 0x01, 0x9e, 0x1a, 0x38, 0xaa, 0xac, 0x04, 0x92, 0xa2, 0xa8, 0x92, 0xc7, 0x82, 0xac, 0x00, 0x90, 0x3a, 0x38, 0x90, 0xaa, 0xa2, 0xaa, 0x81, 0xaa, 0xb9, 0xaa, 0xba, 0xa8, 0xb0, 0xa8, 0xb8, 0xaa, 0x02, 0x60, 0xbe, 0x58, 0x12, 0x00, 0x01, 0x60, 0xbe, 0x58, 0x11, 0x00, 0x01, 0x60, 0xbe, 0x58, 0xfb, 0x1c, 0xff, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x00, 0xbe, 0x58, 0xc6, 0x00, 0x00, 0x60, 0xbe, 0x58, 0xa3, 0x1c, 0xbe, 0x58, 0xa4, 0x1c, 0xbe, 0x58, 0xa5, 0x1c, 0xbe, 0x58, 0xfc, 0x1c, 0xbe, 0x58, 0xfd, 0x1c, 0xe6, 0xa8, 0x88, 0xb0, 0x89, 0xb0, 0x78, 0xa9, 0x3a, 0x38, 0x30, 0x60, 0x80, 0x68, 0xcf, 0xb0, 0xcd, 0xa9, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0x1c, 0x57, -0x80, 0x07, 0x00, 0x60, 0xbe, 0x58, 0xaf, 0x00, 0xbe, 0x58, 0xc2, 0x1d, 0xbe, 0x58, 0xc3, 0x1d, 0xbe, 0x58, 0xc4, 0x1d, 0x3a, 0x38, 0x36, 0x60, 0x80, 0x68, 0x8f, 0xb0, 0xdd, 0xa9, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x3a, 0x38, 0x39, 0xb0, 0x38, 0xaa, 0xb9, 0xb0, 0x30, 0xb0, 0x38, 0xa8, 0xb0, 0xb0, 0x3c, 0xab, 0x3a, 0x38, 0x3c, 0xa9, 0x3a, 0x38, 0x02, 0x3f, 0x01, 0x00, 0x0c, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xa9, 0x07, 0xa5, 0x59, 0x3d, 0x5e, 0x22, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1f, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xb9, 0x07, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x10, 0x88, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xde, 0xa4, -0xc0, 0x07, 0x22, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xcb, 0x07, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0x02, 0x3f, 0x01, 0x00, 0x0a, 0x98, 0x29, 0x66, 0x03, 0x6e, 0xb5, 0x65, 0x02, 0x6d, 0x39, 0x67, 0xe7, 0x38, 0xd9, 0x07, 0xa5, 0x59, 0x3d, 0x5e, 0x1e, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1b, 0x98, 0x29, 0x66, 0x03, 0x6e, 0xb5, 0x65, 0x02, 0x6d, 0x39, 0x67, 0xe7, 0x38, 0xe7, 0x07, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x0e, 0x88, 0x29, 0x66, 0x03, 0x6e, 0x9e, 0x5d, 0x22, 0x00, 0x39, 0x67, 0xe7, 0x38, 0xf7, 0x07, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0xaf, 0x61, 0x1a, 0x69, 0x19, 0x01, 0x00, 0x60, 0x2f, 0x68, 0x93, 0x62, 0x7d, 0xbb, -0x00, 0x08, 0x57, 0x38, 0x0f, 0x59, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x08, 0x60, 0x1e, 0x58, 0x9a, 0xea, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x9a, 0xea, 0x3e, 0x58, 0x19, 0x00, 0x9c, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0x08, 0x60, 0x1e, 0x58, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x00, 0xce, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0xe5, 0xa8, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0xa2, 0x72, 0x07, 0x61, 0x22, 0x23, 0x03, 0x61, 0x17, 0x1e, -0x40, 0x08, 0x23, 0x32, 0x0a, 0x8a, 0x04, 0x61, 0x23, 0x32, 0x0e, 0x8a, 0x00, 0x61, 0x23, 0x32, 0x24, 0x8a, 0x02, 0x61, 0x23, 0x32, 0x2a, 0x8a, 0x2f, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0xb5, 0x66, 0x02, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x28, 0x9e, 0x48, 0x63, 0x0e, 0x6b, 0x48, 0x66, 0x1d, 0x6e, 0x9e, 0x59, 0xbe, 0x00, 0x00, 0x64, 0x3c, 0x48, 0x0d, 0x8a, 0xfa, 0x06, 0x48, 0x67, 0x1d, 0x6f, 0xfa, 0x07, 0x19, 0x11, 0x27, 0x38, 0x66, 0x08, 0xe3, 0x59, 0x3b, 0x5e, 0x19, 0x07, 0x19, 0x06, 0x48, 0x66, 0x1d, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x0f, 0x9e, 0x18, 0xca, 0x48, 0x63, 0x0e, 0x6b, 0x2c, 0xc9, 0x7a, 0x66, 0x02, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x06, 0x9e, 0x30, 0x63, 0x0b, 0x6b, 0x29, 0x66, 0x03, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x60, 0x62, 0x11, 0x6a, 0xc0, 0x61, 0x03, 0x69, 0x24, 0x64, 0x62, 0x8d, -0x80, 0x08, 0x16, 0x65, 0x9e, 0x58, 0x28, 0x1d, 0x05, 0x00, 0x19, 0x05, 0x00, 0x66, 0x00, 0x67, 0xbe, 0x5f, 0x29, 0x1d, 0x27, 0x38, 0xcd, 0x08, 0x19, 0x06, 0xbe, 0x48, 0x09, 0x8a, 0x1e, 0x58, 0x9e, 0x58, 0x29, 0x1d, 0x00, 0xac, 0x02, 0x92, 0x65, 0x58, 0x1d, 0x5a, 0x3e, 0x58, 0x36, 0x9e, 0x05, 0x5e, 0xdd, 0x5a, 0x00, 0x66, 0x19, 0x07, 0xfc, 0x48, 0x01, 0x8a, 0x2f, 0x9e, 0x13, 0xb8, 0x14, 0xb8, 0x15, 0xb8, 0x1e, 0x5e, 0x9e, 0x58, 0x28, 0x1d, 0x9e, 0x5c, 0xb8, 0x00, 0x87, 0x38, 0xa9, 0x08, 0x05, 0x5e, 0xdd, 0x5a, 0x3e, 0x5e, 0x95, 0xb8, 0x94, 0xb8, 0x93, 0xb8, 0x19, 0x12, 0x01, 0x76, 0xdd, 0x5a, 0x9e, 0x58, 0x28, 0x1d, 0xfa, 0x00, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0xbe, 0x22, -0xc0, 0x08, 0x05, 0x5e, 0xdd, 0x5a, 0x9e, 0x5e, 0xe3, 0x19, 0xdd, 0x5a, 0xbb, 0x66, 0xdd, 0x5a, 0xbb, 0x66, 0xdd, 0x5a, 0xff, 0x66, 0xbe, 0x5e, 0x29, 0x1d, 0x1a, 0x38, 0x1a, 0x38, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x67, 0x03, 0x6f, 0xbe, 0x5f, 0xdb, 0x00, 0x7f, 0x67, 0xbe, 0x5f, 0xde, 0x00, 0x00, 0x67, 0xbe, 0x5f, 0xe1, 0x00, 0x40, 0x67, 0xbe, 0x5f, 0xe0, 0x00, 0x3a, 0x38, 0xad, 0xac, 0x0d, 0x90, 0x04, 0x60, 0x69, 0x78, 0x66, 0x60, 0x6a, 0x78, 0x6b, 0x78, 0x6c, 0x78, 0x6d, 0x78, 0xb2, 0xa8, 0x3c, 0xab, 0xad, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xc2, 0x1d, 0x3a, 0x38, 0x02, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0x01, 0xc9, 0x19, 0x38, 0xd9, 0x54, 0x04, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0xe3, 0xeb, 0xa5, 0xaa, 0xac, 0xdf, -0x00, 0x09, 0x3a, 0x38, 0x1e, 0x5c, 0x04, 0xaa, 0x02, 0x9e, 0x1e, 0x5c, 0x04, 0xa8, 0x46, 0x62, 0x31, 0x6a, 0x40, 0xbd, 0xbd, 0x00, 0x02, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x00, 0x61, 0x10, 0x69, 0x07, 0x60, 0xc0, 0x68, 0x3f, 0x38, 0x0f, 0x59, 0x00, 0x61, 0x10, 0x69, 0x23, 0x5a, 0x32, 0xa8, 0x04, 0xac, 0x01, 0x92, 0x32, 0xaa, 0x5b, 0x59, 0x01, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x07, 0x60, 0xc0, 0x68, 0x3f, 0x38, 0x7a, 0x38, 0x02, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x00, 0x62, 0x40, 0xbd, 0xbd, 0x00, 0x40, 0xbd, 0xbe, 0x00, 0x3e, 0x5c, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0xe6, 0xac, 0x05, 0x92, 0xe0, 0x61, 0x1a, 0x69, 0x00, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x40, 0x61, 0x57, 0x69, 0x60, 0x62, 0x57, 0x6a, 0x90, 0x63, 0xd4, 0xfd, -0x40, 0x09, 0x5e, 0x6b, 0xb6, 0x64, 0x5e, 0x6c, 0x39, 0x65, 0x00, 0x66, 0x00, 0x67, 0xa7, 0x38, 0x0e, 0x0a, 0x15, 0x65, 0xfd, 0x48, 0x21, 0x9c, 0xe6, 0xac, 0x05, 0x92, 0xec, 0x61, 0x1a, 0x69, 0x0c, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x4c, 0x61, 0x57, 0x69, 0x6c, 0x62, 0x57, 0x6a, 0x16, 0x65, 0xa0, 0x38, 0x7a, 0x02, 0x5e, 0x17, 0x07, 0x00, 0x5e, 0x07, 0x6b, 0x5d, 0xbe, 0x5d, 0x2e, 0x1d, 0x48, 0x66, 0xbe, 0x48, 0xac, 0x8a, 0x09, 0x66, 0xbe, 0x48, 0x1b, 0x9c, 0x13, 0x66, 0xbe, 0x48, 0x35, 0x9c, 0x1d, 0x66, 0xbe, 0x48, 0x15, 0x9c, 0x31, 0x9e, 0x7a, 0x60, 0x02, 0x68, 0x8b, 0x5d, 0xbe, 0x5d, 0x2e, 0x1d, 0x48, 0x66, 0xdd, 0x48, 0x77, 0x8a, 0x05, 0x66, 0xfe, 0x48, 0x4b, 0x9c, 0x0b, 0x66, 0xfe, 0x48, 0x5d, 0x9c, 0x11, 0x66, 0xfe, 0x48, 0x45, 0x9c, 0x15, 0x66, 0xfe, 0x48, 0x57, 0x9c, 0x5b, 0x68, -0x80, 0x09, 0x9e, 0x5d, 0x2e, 0x1d, 0x0a, 0x66, 0xbe, 0x48, 0x01, 0x96, 0xa6, 0x15, 0x25, 0x01, 0x45, 0x02, 0xff, 0x65, 0xe6, 0xac, 0x02, 0x92, 0x35, 0x26, 0x04, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x3e, 0x58, 0xfe, 0x5e, 0xe6, 0xac, 0x02, 0x92, 0x55, 0x25, 0x04, 0x9e, 0x1e, 0x58, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xc5, 0x2e, 0xdb, 0x58, 0x71, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xec, 0x61, 0x1a, 0x69, 0x0c, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x4c, 0x61, 0x57, 0x69, 0x6c, 0x62, 0x57, 0x6a, 0x9e, 0x5d, 0x2e, 0x1d, 0x0a, 0x66, 0xa6, 0x15, 0xbe, 0x48, 0x01, 0x96, 0xa6, 0x15, 0x25, 0x01, 0x45, 0x02, 0x00, 0x65, 0xff, 0x6d, 0xe6, 0xac, 0x03, 0x92, 0x35, 0x26, 0x55, 0x25, 0x06, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xfe, 0x5d, 0xc5, 0x2e, 0xa9, 0x5c, -0xc0, 0x09, 0xdb, 0x58, 0x4c, 0x9e, 0xff, 0x65, 0xe6, 0xac, 0x04, 0x92, 0x35, 0x26, 0xfe, 0x5e, 0x55, 0x25, 0x07, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0xfe, 0x5e, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xc5, 0x2e, 0x9e, 0x5d, 0x2e, 0x1d, 0x05, 0x00, 0xdb, 0x58, 0x05, 0x10, 0x14, 0x9e, 0x00, 0x65, 0xff, 0x6d, 0xe6, 0xac, 0x03, 0x92, 0x35, 0x26, 0x55, 0x25, 0x06, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xfe, 0x5d, 0xc5, 0x2e, 0x9e, 0x5d, 0x2e, 0x1d, 0x05, 0x00, 0xdb, 0x58, 0x05, 0x10, 0x05, 0x66, 0xdf, 0x48, 0x09, 0x8a, 0x0b, 0x66, 0xdf, 0x48, 0x12, 0x8a, 0x11, 0x66, 0xdf, 0x48, 0x0f, 0x8a, 0x19, 0x01, 0x19, 0x02, 0x17, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xe0, 0x61, 0x1a, 0x69, 0x00, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x40, 0x61, 0x57, 0x69, 0x4f, 0x4c, -0x00, 0x0a, 0x60, 0x62, 0x57, 0x6a, 0x0b, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xe6, 0x61, 0x1a, 0x69, 0x06, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x46, 0x61, 0x57, 0x69, 0x66, 0x62, 0x57, 0x6a, 0x19, 0x07, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x90, 0x60, 0x5e, 0x68, 0x48, 0x64, 0x0e, 0x6c, 0x00, 0x65, 0x00, 0x66, 0x00, 0x67, 0xff, 0x63, 0xff, 0x6b, 0x6f, 0x3c, 0x5c, 0x0a, 0x09, 0x5a, 0x48, 0x65, 0x5d, 0x48, 0x34, 0x8a, 0x1e, 0x58, 0x19, 0x03, 0x0c, 0x65, 0x65, 0x40, 0xe6, 0xac, 0x03, 0x92, 0x00, 0x61, 0x05, 0x69, 0x02, 0x9e, 0x80, 0x61, 0x57, 0x69, 0x20, 0x01, 0xb6, 0x62, 0x5e, 0x6a, 0x13, 0xb8, 0x14, 0xb8, 0x15, 0xb8, 0x6f, 0x39, 0x54, 0x0a, 0xe6, 0xac, 0x02, 0x92, 0x23, 0x5e, 0x01, 0x9e, 0x29, 0x5e, 0xc4, 0x3f, 0xf9, 0x96, -0x40, 0x0a, 0x00, 0xff, 0xfe, 0x5f, 0xc4, 0x3e, 0xff, 0x00, 0x49, 0x5d, 0x48, 0x60, 0x1d, 0x48, 0x03, 0x8a, 0x85, 0x04, 0xdb, 0x5c, 0x85, 0x14, 0x19, 0x02, 0x49, 0x5d, 0x48, 0x60, 0x1d, 0x48, 0x03, 0x8a, 0x85, 0x04, 0xfb, 0x5c, 0x85, 0x14, 0x19, 0x02, 0x19, 0x01, 0x95, 0xb8, 0x94, 0xb8, 0x93, 0xb8, 0x16, 0x65, 0x85, 0x04, 0x3e, 0x58, 0x1a, 0x38, 0x19, 0x00, 0x3a, 0x38, 0x9e, 0x59, 0xf1, 0x1e, 0x1c, 0x11, 0x1e, 0x98, 0x9e, 0x59, 0xf2, 0x1e, 0x22, 0x39, 0x88, 0x00, 0x11, 0x8a, 0x9e, 0x59, 0x58, 0x1a, 0x1a, 0x11, 0x01, 0x94, 0x14, 0x9e, 0x88, 0x61, 0xbe, 0x59, 0xf2, 0x1e, 0x8d, 0x61, 0x9e, 0x58, 0xef, 0x1e, 0x1b, 0x59, 0x97, 0x61, 0x9e, 0x58, 0xee, 0x1e, 0x1b, 0x59, 0x18, 0x9e, 0x9e, 0x59, 0x58, 0x1a, 0x19, 0x11, 0xf0, 0x95, 0x9e, 0x59, 0xf1, 0x1e, 0x1c, 0x11, 0x00, 0x98, 0x40, 0x44, -0x80, 0x0a, 0x00, 0x61, 0xbe, 0x59, 0xf2, 0x1e, 0x9e, 0x59, 0xf0, 0x1e, 0x22, 0x39, 0x66, 0x00, 0x08, 0x88, 0x8d, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xef, 0x1e, 0x97, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xee, 0x1e, 0x3a, 0x38, 0x9e, 0x59, 0xf3, 0x1e, 0x1c, 0x11, 0x1e, 0x98, 0x9e, 0x59, 0xf7, 0x1e, 0x22, 0x39, 0x88, 0x00, 0x11, 0x8a, 0x9e, 0x59, 0x58, 0x1a, 0x1b, 0x11, 0x01, 0x94, 0x14, 0x9e, 0x88, 0x61, 0xbe, 0x59, 0xf7, 0x1e, 0x8e, 0x61, 0x9e, 0x58, 0xf5, 0x1e, 0x1b, 0x59, 0x98, 0x61, 0x9e, 0x58, 0xf6, 0x1e, 0x1b, 0x59, 0x18, 0x9e, 0x9e, 0x59, 0x58, 0x1a, 0x1a, 0x11, 0xf0, 0x95, 0x9e, 0x59, 0xf3, 0x1e, 0x1c, 0x11, 0x00, 0x98, 0x00, 0x61, 0xbe, 0x59, 0xf7, 0x1e, 0x9e, 0x59, 0xf4, 0x1e, 0x22, 0x39, 0x66, 0x00, 0x08, 0x88, 0x8e, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xf5, 0x1e, 0x98, 0x61, 0xe4, 0x8e, -0xc0, 0x0a, 0x23, 0x58, 0xbe, 0x58, 0xf6, 0x1e, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x9e, 0x58, 0xea, 0x04, 0x18, 0x10, 0x0a, 0x88, 0x00, 0x60, 0x01, 0x61, 0x1f, 0x69, 0x06, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xd7, 0x0a, 0x1d, 0x59, 0x1d, 0x5a, 0x1a, 0x38, 0x9e, 0x58, 0x00, 0x1f, 0x19, 0x10, 0x23, 0x8a, 0x00, 0x64, 0x7f, 0x6c, 0x8d, 0x61, 0x01, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xed, 0x0a, 0x23, 0x58, 0x04, 0x15, 0x06, 0x8a, 0x43, 0x5b, 0x18, 0x13, 0x01, 0x88, 0x1b, 0x5a, 0x43, 0x58, 0x1b, 0x59, 0x19, 0x01, 0x19, 0x02, 0x30, 0x64, 0x97, 0x61, 0x06, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xfe, 0x0a, 0x23, 0x58, 0x04, 0x15, 0x06, 0x8a, 0x43, 0x5b, 0x18, 0x13, 0x01, 0x88, 0x1b, 0x5a, 0x43, 0x58, 0x1b, 0x59, 0x19, 0x01, 0x19, 0x02, 0x3e, 0x5d, 0xcf, 0xcb, -0x00, 0x0b, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x08, 0x0c, -0x40, 0x0b, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x9e, 0x58, 0xe7, 0x00, 0x19, 0x10, 0x08, 0x98, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xfd, 0x38, 0x75, 0xcb, 0x01, 0x60, 0xbe, 0x58, 0xea, 0x00, 0xbe, 0x58, 0xe7, 0x00, 0xed, 0x9f, 0x9e, 0x58, 0xe7, 0x00, 0x19, 0x10, 0x08, 0x98, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0xfd, 0x38, 0x94, 0xcc, 0x01, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0xef, 0x9f, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0xf4, 0x8a, 0xf6, 0xcd, 0x02, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x79, 0xe4, 0xb7, 0x8b, -0x80, 0x0b, 0xc7, 0xdd, 0x8a, 0xde, 0xa1, 0xdd, 0xa8, 0xe5, 0x9c, 0xcc, 0xd2, 0xde, 0xd4, 0xdb, 0x37, 0xee, 0xb2, 0xcc, 0xcf, 0xcc, 0x48, 0x66, 0x0e, 0x6e, 0x91, 0xed, 0xf3, 0xcc, 0x7f, 0xe2, 0x80, 0x60, 0xbe, 0x58, 0xfd, 0x1e, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1a, 0x10, 0x13, 0x88, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x00, 0x01, 0x08, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x01, 0x00, 0x02, 0x39, 0x00, 0x02, 0x7d, 0x80, 0x88, 0x60, 0xbe, 0x58, 0xfd, 0x1e, 0x86, 0xe8, 0x0c, 0xe9, 0x77, 0x9e, 0x1a, 0x38, 0x9e, 0x58, 0xe9, 0x1e, 0x18, 0x10, 0x01, 0x8a, 0x71, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x1b, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x06, 0x70, 0x50, 0xac, 0x18, 0x92, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x00, 0x01, 0x0a, 0x98, 0x09, 0x92, -0xc0, 0x0b, 0x9e, 0x58, 0x4d, 0x04, 0x02, 0x38, 0x40, 0x01, 0x0e, 0x80, 0x9e, 0x58, 0x4f, 0x04, 0x02, 0x38, 0x40, 0x01, 0x09, 0x80, 0xe7, 0xe5, 0x9e, 0x58, 0x20, 0x1d, 0x18, 0x10, 0x04, 0x8a, 0x05, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x50, 0x9e, 0x1a, 0x38, 0x06, 0x70, 0x08, 0xac, 0x2f, 0x92, 0x00, 0xac, 0x2d, 0x92, 0x50, 0xac, 0x2b, 0x92, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x04, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1a, 0x10, 0x21, 0x8a, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1b, 0x10, 0x14, 0x9a, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x60, 0x00, 0x15, 0x80, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1b, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xf1, 0x1e, 0x9e, 0x59, 0xf3, 0x1e, 0x01, 0x00, 0x08, 0x58, 0x1d, 0x10, 0x06, 0x98, 0xb2, 0x09, -0x00, 0x0c, 0x1f, 0xdf, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x1d, 0x8a, 0x9e, 0x58, 0x8a, 0x04, 0x1f, 0x10, 0x07, 0x80, 0x9e, 0x58, 0x8b, 0x04, 0x1f, 0x10, 0x03, 0x80, 0x05, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x9e, 0x58, 0x36, 0x1d, 0x1a, 0x10, 0x08, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1c, 0x10, 0x03, 0x8a, 0x98, 0xe2, 0x98, 0xe2, 0x01, 0x9e, 0x98, 0xe2, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x80, 0x01, 0x01, 0x80, 0x69, 0xe2, 0xc6, 0xce, 0x1a, 0xcd, 0x99, 0xce, 0xab, 0xce, 0x25, 0xcf, 0x72, 0xdc, 0x12, 0xd2, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x0a, 0x8a, 0x9e, 0x58, 0xb1, 0x04, 0x19, 0x10, 0x06, 0x8a, 0x9e, 0x58, 0xb8, 0x04, 0x18, 0x10, 0x02, 0x88, 0x28, 0xe4, 0xc3, 0xe1, 0xc1, 0xf8, 0x8a, 0xf8, 0x51, 0xd0, 0x19, 0x38, 0x92, 0x4a, 0x9e, 0x58, 0x43, 0x04, 0x1b, 0x22, -0x40, 0x0c, 0x01, 0x61, 0x19, 0x48, 0x0c, 0x8a, 0x9e, 0x58, 0x20, 0x1d, 0x18, 0x10, 0x08, 0x88, 0x19, 0x38, 0xc6, 0x4a, 0x19, 0x38, 0xc5, 0x48, 0x19, 0x38, 0x94, 0x49, 0x19, 0x38, 0xd6, 0x4a, 0x03, 0xda, 0x4d, 0xda, 0xe3, 0xed, 0x66, 0xd3, 0xdc, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0x9e, 0x58, 0x58, 0x1a, 0x19, 0x10, 0x12, 0x88, 0x9e, 0x58, 0x8a, 0x04, 0x9e, 0x59, 0x8b, 0x04, 0x01, 0x00, 0x02, 0x39, 0x05, 0x00, 0x0a, 0x98, 0xaa, 0x61, 0x15, 0x69, 0x23, 0x58, 0x02, 0x39, 0x0d, 0x00, 0x04, 0x80, 0xaa, 0x61, 0x15, 0x69, 0x0d, 0x60, 0x1b, 0x59, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0xf6, 0xcd, 0x9c, 0xcc, 0xd4, 0xdb, 0xc3, 0xcc, 0xcf, 0xcc, 0xf3, 0xcc, 0x7f, 0xe2, 0xc6, 0xce, 0x1a, 0xcd, 0x99, 0xce, 0xab, 0xce, 0x25, 0xcf, 0x12, 0xd2, 0x51, 0xd0, 0x03, 0xda, 0x4d, 0xda, 0x66, 0xd3, 0x27, 0x2c, -0x80, 0x0c, 0xdc, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0xf6, 0xcd, 0x9c, 0xcc, 0xcf, 0xcc, 0xf3, 0xcc, 0x75, 0xce, 0xc6, 0xce, 0x1a, 0xcd, 0x99, 0xce, 0xab, 0xce, 0x25, 0xcf, 0x12, 0xd2, 0x51, 0xd0, 0x03, 0xda, 0x3a, 0x38, 0x4d, 0xda, 0x66, 0xd3, 0xdc, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0x30, 0x67, 0x0b, 0x6f, 0x9e, 0x5e, 0xe9, 0x00, 0x48, 0x65, 0x0e, 0x6d, 0x9e, 0x5c, 0xda, 0x00, 0x19, 0x14, 0x87, 0x38, 0xb0, 0x0c, 0xc5, 0x5c, 0xf4, 0x14, 0x7c, 0xac, 0x04, 0x92, 0x00, 0x61, 0x02, 0x62, 0x82, 0x40, 0x01, 0x5c, 0x9d, 0x5d, 0x19, 0x07, 0x3a, 0x38, 0x30, 0x60, 0x1c, 0x78, 0x06, 0x70, 0x50, 0xac, 0x08, 0x92, 0x08, 0xac, 0x04, 0x92, 0x00, 0xac, 0x02, 0x92, 0x10, 0x60, 0x03, 0x9e, 0x30, 0x60, 0x01, 0x9e, 0x68, 0x60, 0x61, 0x34, -0xc0, 0x0c, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x30, 0x60, 0x1c, 0x78, 0x30, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x40, 0x60, 0x1c, 0x78, 0x30, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x48, 0x67, 0x0e, 0x6f, 0x9e, 0x5d, 0xfd, 0x1b, 0x19, 0x15, 0x9e, 0x5e, 0xfe, 0x1b, 0xff, 0x64, 0x7f, 0x6c, 0xa7, 0x38, 0xdd, 0x0c, 0x9f, 0x49, 0x01, 0x9a, 0xe3, 0x5c, 0x19, 0x07, 0x18, 0x14, 0x01, 0x94, 0x00, 0x64, 0x90, 0x3c, 0x26, 0x00, 0x90, 0x3c, 0x05, 0x1c, 0xf2, 0x3f, 0xfd, 0x1b, 0x00, 0x62, 0xa7, 0x38, 0xef, 0x0c, 0xf2, 0x13, 0x03, 0x96, 0xf4, 0x13, 0x01, 0x94, 0x00, 0x63, 0x7d, 0x5f, 0x19, 0x16, 0xe4, 0x89, 0x3a, 0x38, 0x48, 0x67, 0x0e, 0x6f, 0x9e, 0x5d, 0xfd, 0x1b, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0xff, 0x64, 0x7f, 0x6c, 0xc7, 0x38, 0x03, 0x0d, 0x9f, 0x49, 0x01, 0x9a, 0xb0, 0xa2, -0x00, 0x0d, 0xe3, 0x5c, 0xf0, 0x3f, 0xfd, 0x1b, 0x1a, 0x38, 0x18, 0x14, 0x01, 0x94, 0x00, 0x64, 0x90, 0x3c, 0x25, 0x00, 0x90, 0x3c, 0x05, 0x1c, 0x00, 0x62, 0xc7, 0x38, 0x15, 0x0d, 0xf2, 0x3f, 0xfd, 0x1b, 0xf2, 0x13, 0x03, 0x96, 0xf4, 0x13, 0x01, 0x94, 0x00, 0x63, 0x7b, 0x5f, 0x19, 0x07, 0x19, 0x15, 0xe1, 0x89, 0x3a, 0x38, 0x05, 0x71, 0x49, 0xaa, 0x05, 0x79, 0x00, 0x66, 0x60, 0x65, 0x11, 0x6d, 0x48, 0x64, 0x0e, 0x6c, 0x9e, 0x5b, 0xfd, 0x1b, 0x1a, 0x05, 0xa3, 0x05, 0x00, 0x67, 0x9e, 0x58, 0xfd, 0x1b, 0x19, 0x10, 0x07, 0x38, 0xb6, 0x0d, 0x1d, 0x70, 0x1c, 0x49, 0x85, 0x94, 0x05, 0x71, 0x49, 0xa8, 0x05, 0x79, 0x00, 0x60, 0xa2, 0x3b, 0x01, 0x00, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x29, 0x88, 0xb2, 0x3b, 0xfd, 0x1b, 0x19, 0x13, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x77, 0xc4, -0x40, 0x0d, 0x19, 0x48, 0x21, 0x88, 0xa3, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x6d, 0x88, 0x9e, 0x5b, 0xf0, 0x04, 0x4b, 0x62, 0x1a, 0x6a, 0x7a, 0x49, 0x06, 0x98, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x08, 0x9e, 0x43, 0x5b, 0x19, 0x03, 0x7b, 0x5a, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x19, 0x13, 0x60, 0x3a, 0xaa, 0x15, 0x43, 0x59, 0x19, 0x01, 0x3b, 0x5a, 0xda, 0xce, 0x51, 0x9e, 0xa3, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x4c, 0x88, 0xa2, 0x3b, 0x01, 0x00, 0xb2, 0x3a, 0xfd, 0x1b, 0x19, 0x12, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x1f, 0x8a, 0x43, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x1a, 0x8a, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x43, 0x58, 0x04, 0x38, 0xff, 0x00, 0x38, 0x48, 0x12, 0x8a, 0x20, 0x39, 0x6a, 0x62, -0x80, 0x0d, 0xbd, 0x15, 0x43, 0x58, 0x00, 0x38, 0xbd, 0x15, 0x03, 0x58, 0x19, 0x49, 0x01, 0x94, 0x1b, 0x59, 0x00, 0x39, 0xbd, 0x15, 0x63, 0x58, 0x00, 0x38, 0xbd, 0x15, 0x03, 0x58, 0x19, 0x49, 0x01, 0x94, 0x1b, 0x59, 0x00, 0x60, 0x43, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x09, 0x8a, 0x43, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x0d, 0x9e, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x08, 0x8a, 0x63, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x19, 0x13, 0x60, 0x3a, 0xaa, 0x15, 0x43, 0x59, 0x19, 0x01, 0x3b, 0x5a, 0xe7, 0xce, 0x19, 0x04, 0x19, 0x05, 0x19, 0x07, 0x19, 0x05, 0x19, 0x06, 0x9e, 0x5a, 0xfe, 0x1b, 0x5e, 0x48, 0x69, 0x99, 0x3a, 0x38, 0xe8, 0x67, 0x03, 0x6f, 0x22, 0x6f, -0xc0, 0x0d, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x5c, 0x58, 0x1a, 0x82, 0x39, 0x00, 0x00, 0x20, 0x8a, 0x00, 0x67, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x5a, 0xfd, 0x1b, 0x72, 0x65, 0x19, 0x6d, 0x86, 0x66, 0x19, 0x6e, 0x19, 0x14, 0xff, 0x61, 0x7f, 0x69, 0x00, 0x63, 0x87, 0x38, 0xe0, 0x0d, 0xa5, 0x58, 0x46, 0x4a, 0x00, 0x38, 0x48, 0x0e, 0x38, 0x49, 0x01, 0x9a, 0x03, 0x59, 0x78, 0x49, 0x01, 0x94, 0x03, 0x5b, 0x17, 0x07, 0x19, 0x04, 0xe1, 0x58, 0x00, 0x61, 0x1c, 0x5c, 0xbe, 0x58, 0x54, 0x1a, 0x3a, 0x38, 0x9e, 0x58, 0xe3, 0x19, 0x00, 0x67, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0xf2, 0x0d, 0x04, 0x39, 0x01, 0x00, 0xe1, 0x07, 0x08, 0x58, 0xbe, 0x5f, 0xea, 0x04, 0x3a, 0x38, 0x9e, 0x58, 0x00, 0x1f, 0x9e, 0x5f, 0x20, 0x1d, 0x18, 0x17, 0x01, 0x8a, 0x1b, 0x00, 0xbe, 0x58, 0x11, 0x00, 0x7a, 0x67, 0xc6, 0xac, -0x00, 0x0e, 0x02, 0x6f, 0x00, 0x66, 0x9e, 0x58, 0x5d, 0x1a, 0x19, 0x10, 0x07, 0x38, 0x09, 0x0e, 0xdd, 0x5f, 0x1a, 0x38, 0x1a, 0x38, 0xe8, 0xcd, 0xbe, 0xcd, 0x9e, 0x5f, 0xea, 0x04, 0x0a, 0x67, 0xbe, 0x5f, 0xe4, 0x19, 0x9e, 0x58, 0x54, 0x1a, 0x9e, 0x59, 0x48, 0x1a, 0x24, 0x3a, 0x00, 0xe0, 0x07, 0x8a, 0x22, 0x39, 0x00, 0x20, 0xbe, 0x59, 0x48, 0x1a, 0x24, 0x38, 0xff, 0x1f, 0x17, 0x9e, 0x18, 0x10, 0x0b, 0x8a, 0x9e, 0x59, 0x48, 0x1a, 0x18, 0x11, 0x05, 0x8a, 0x26, 0x5a, 0x41, 0x02, 0x02, 0x00, 0x08, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x48, 0x1a, 0x9e, 0x59, 0xe2, 0x19, 0x3f, 0x48, 0x07, 0x8a, 0x9e, 0x58, 0x48, 0x1a, 0x05, 0x39, 0x00, 0x80, 0xbe, 0x59, 0x48, 0x1a, 0x06, 0x58, 0x24, 0x3a, 0x00, 0xe0, 0x00, 0x8a, 0x32, 0x62, 0x0b, 0x6a, 0x50, 0x3a, 0x4b, 0x1a, 0x49, 0x5a, 0x02, 0x40, 0x1f, 0x71, -0x40, 0x0e, 0x00, 0x61, 0x02, 0x69, 0x01, 0x40, 0xbe, 0x59, 0x05, 0x1c, 0x9e, 0x59, 0x4b, 0x1a, 0xbe, 0x59, 0x03, 0x1c, 0x00, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x58, 0x1a, 0x60, 0x66, 0x11, 0x6e, 0x00, 0x61, 0x80, 0x69, 0x9e, 0x5f, 0xff, 0x1b, 0x19, 0x17, 0xe7, 0x38, 0x57, 0x0e, 0xd1, 0x22, 0x5d, 0x5e, 0xaa, 0x63, 0x15, 0x6b, 0xbe, 0x62, 0x15, 0x6a, 0x00, 0x61, 0x9e, 0x5f, 0xf0, 0x04, 0x19, 0x17, 0xe7, 0x38, 0x64, 0x0e, 0x1d, 0x5b, 0x19, 0x01, 0x3d, 0x5a, 0xbe, 0x58, 0x4b, 0x1a, 0xc8, 0x63, 0x1b, 0x6b, 0x00, 0x60, 0x13, 0x67, 0xe7, 0x38, 0x6f, 0x0e, 0x1d, 0x5b, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x58, 0x06, 0x1c, 0xbe, 0x58, 0x1c, 0x00, 0x3a, 0x38, 0x60, 0x67, 0x11, 0x6f, 0x48, 0x66, 0x0e, 0x6e, 0x00, 0x64, 0x01, 0x63, 0x24, 0x72, 0x9e, 0x58, 0x05, 0x1c, 0x08, 0x58, 0x40, 0x02, 0x05, 0x2d, -0x80, 0x0e, 0x00, 0x61, 0x80, 0x69, 0x20, 0x58, 0x9e, 0x5d, 0xda, 0x00, 0x19, 0x15, 0xa7, 0x38, 0x97, 0x0e, 0xf1, 0x25, 0x08, 0x8a, 0xd3, 0x15, 0x0a, 0x98, 0xf0, 0x25, 0xbb, 0x5f, 0x9e, 0x49, 0x06, 0x98, 0x9b, 0x5e, 0x04, 0x9e, 0xd2, 0x15, 0xfa, 0x9b, 0xf1, 0x2d, 0xbb, 0x5f, 0x19, 0x07, 0x19, 0x06, 0x3a, 0x38, 0xbe, 0x63, 0x15, 0x6b, 0x00, 0x65, 0x9e, 0x5c, 0x4b, 0x1a, 0x18, 0x14, 0x0a, 0x8a, 0x19, 0x14, 0x87, 0x38, 0xa9, 0x0e, 0x65, 0x04, 0x83, 0x5e, 0x19, 0x16, 0x66, 0x07, 0xe3, 0x5e, 0xdb, 0x5c, 0x19, 0x05, 0x3a, 0x38, 0x9e, 0x5e, 0x4b, 0x1a, 0x0f, 0x9a, 0x0e, 0x8a, 0x19, 0x16, 0xc7, 0x38, 0xbc, 0x0e, 0xc0, 0x3d, 0xbe, 0x15, 0xa3, 0x5f, 0x19, 0x17, 0xdf, 0x48, 0x04, 0x8a, 0xaa, 0x62, 0x15, 0x6a, 0xbe, 0xce, 0xfc, 0xce, 0x19, 0x16, 0x3a, 0x38, 0xe2, 0x04, 0x83, 0x58, 0x26, 0xfe, -0xc0, 0x0e, 0xc2, 0x02, 0x50, 0x00, 0x1b, 0x5c, 0xde, 0x5a, 0x00, 0x00, 0x3a, 0x38, 0x00, 0x60, 0xff, 0x61, 0xde, 0x66, 0x15, 0x6e, 0xf2, 0x65, 0x15, 0x6d, 0x06, 0x64, 0x16, 0x6c, 0x1a, 0x63, 0x16, 0x6b, 0x9e, 0x5f, 0xf0, 0x04, 0x19, 0x17, 0xe7, 0x38, 0xd8, 0x0e, 0x3d, 0x5e, 0x1d, 0x5d, 0x1d, 0x5c, 0x3d, 0x5b, 0x3a, 0x38, 0x60, 0x38, 0xde, 0x15, 0xfb, 0x58, 0x60, 0x38, 0xf2, 0x15, 0xfb, 0x58, 0x60, 0x38, 0x06, 0x16, 0xdb, 0x58, 0x60, 0x38, 0x1a, 0x16, 0xdb, 0x58, 0x3a, 0x38, 0x60, 0x38, 0xde, 0x15, 0xf8, 0x49, 0x01, 0x94, 0xfb, 0x58, 0x60, 0x38, 0xf2, 0x15, 0xf8, 0x49, 0x01, 0x9a, 0xfb, 0x58, 0x60, 0x38, 0x06, 0x16, 0xd8, 0x49, 0x01, 0x9a, 0xdb, 0x58, 0x60, 0x38, 0x1a, 0x16, 0xd8, 0x49, 0x01, 0x94, 0xdb, 0x58, 0x3a, 0x38, 0xc0, 0x38, 0xde, 0x15, 0x03, 0x59, 0xe0, 0x3a, 0x6f, 0x88, -0x00, 0x0f, 0xde, 0x15, 0x3a, 0x49, 0x01, 0x94, 0x3b, 0x5a, 0xde, 0x58, 0xff, 0x00, 0xc0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0xe0, 0x3a, 0xf2, 0x15, 0x3a, 0x49, 0x01, 0x9a, 0x3b, 0x5a, 0xde, 0x58, 0x00, 0x00, 0xc0, 0x38, 0x06, 0x16, 0x03, 0x59, 0xe0, 0x3a, 0x06, 0x16, 0x3a, 0x49, 0x01, 0x9a, 0x3b, 0x5a, 0xde, 0x58, 0x00, 0x00, 0xc0, 0x38, 0x1a, 0x16, 0x03, 0x59, 0xe0, 0x3a, 0x1a, 0x16, 0x3a, 0x49, 0x01, 0x94, 0x3b, 0x5a, 0xde, 0x58, 0xff, 0x00, 0x3a, 0x38, 0x00, 0x61, 0xbe, 0x59, 0x58, 0x1a, 0x00, 0x67, 0x23, 0x70, 0xe0, 0x39, 0xaa, 0x15, 0x19, 0x49, 0x32, 0x98, 0x02, 0xdc, 0x9e, 0x58, 0xe9, 0x1e, 0x18, 0x10, 0x0e, 0x8a, 0x06, 0x70, 0x08, 0xac, 0x08, 0x92, 0x00, 0xac, 0x06, 0x92, 0x50, 0xac, 0x04, 0x92, 0x20, 0x60, 0x01, 0x68, 0x1c, 0x78, 0x03, 0x9e, 0x00, 0x60, 0x02, 0x68, 0xe2, 0x31, -0x40, 0x0f, 0x1c, 0x78, 0x9e, 0x58, 0x20, 0x1d, 0x02, 0x38, 0x80, 0x01, 0x03, 0x88, 0x40, 0x60, 0xbe, 0x58, 0x1c, 0x00, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5e, 0xe0, 0x3b, 0xde, 0x15, 0x63, 0x5d, 0x14, 0x60, 0x58, 0x62, 0x1a, 0x6a, 0x1a, 0x49, 0x12, 0x9a, 0x68, 0xcf, 0x19, 0x05, 0xe0, 0x3b, 0xf2, 0x15, 0xbb, 0x49, 0xf5, 0x9b, 0x19, 0x06, 0xe0, 0x38, 0x06, 0x16, 0xd8, 0x49, 0xed, 0x9b, 0x66, 0xdc, 0x19, 0x07, 0x9e, 0x58, 0x4b, 0x1a, 0xf8, 0x48, 0xc4, 0x97, 0x01, 0x9e, 0x66, 0xdc, 0x3a, 0x38, 0x9e, 0x5a, 0xfd, 0x1b, 0xa0, 0x38, 0x48, 0x0e, 0x46, 0x48, 0x03, 0x5c, 0xe0, 0x3b, 0xc8, 0x1b, 0x63, 0x58, 0x04, 0x00, 0x1b, 0x5b, 0x1c, 0x73, 0x9b, 0x48, 0x31, 0x96, 0x1e, 0x5f, 0x01, 0x67, 0xe0, 0x39, 0x07, 0x10, 0x29, 0x59, 0x25, 0x03, 0x62, 0x39, 0x00, 0x00, 0x14, 0x96, 0x72, 0x39, 0x8f, 0x4b, -0x80, 0x0f, 0xfd, 0x1b, 0x11, 0x94, 0xe0, 0x39, 0x10, 0x10, 0x29, 0x59, 0x26, 0x02, 0x42, 0x39, 0x00, 0x00, 0x0a, 0x96, 0x52, 0x39, 0xfe, 0x1b, 0x07, 0x94, 0x9e, 0x59, 0xfd, 0x1b, 0x60, 0x38, 0x48, 0x0e, 0x22, 0x48, 0x98, 0x49, 0x13, 0x96, 0x19, 0x07, 0xe2, 0x38, 0x09, 0x00, 0xe1, 0x97, 0x3e, 0x5f, 0x58, 0x61, 0x1a, 0x69, 0x23, 0x58, 0x00, 0x3a, 0x72, 0x19, 0xfe, 0x5f, 0xaf, 0x2a, 0xfe, 0x5f, 0x00, 0x3a, 0x86, 0x19, 0xdb, 0x5a, 0x08, 0x39, 0x01, 0x00, 0x01, 0x9e, 0x3e, 0x5f, 0x3a, 0x38, 0x1e, 0x5f, 0x00, 0x67, 0xe0, 0x3c, 0x07, 0x10, 0x89, 0x5c, 0x85, 0x03, 0x62, 0x39, 0x00, 0x00, 0x50, 0x96, 0x72, 0x39, 0xfd, 0x1b, 0x4d, 0x94, 0xe0, 0x3c, 0x10, 0x10, 0x89, 0x5c, 0x86, 0x02, 0x42, 0x39, 0x00, 0x00, 0x46, 0x96, 0x52, 0x39, 0xfe, 0x1b, 0x43, 0x94, 0x9e, 0x59, 0xfd, 0x1b, 0x6e, 0xbd, -0xc0, 0x0f, 0x60, 0x38, 0x32, 0x16, 0x22, 0x48, 0x03, 0x5c, 0x82, 0x39, 0x00, 0x00, 0x3a, 0x9a, 0x1e, 0x5f, 0x1e, 0x5c, 0x19, 0xd0, 0x81, 0x58, 0x3e, 0x5c, 0x19, 0x17, 0x20, 0x98, 0x19, 0x11, 0x1e, 0x98, 0x1e, 0x5c, 0x00, 0x3f, 0x72, 0x19, 0xe3, 0x5f, 0x00, 0x39, 0x86, 0x19, 0x23, 0x59, 0x9e, 0x5c, 0xfd, 0x1b, 0xe0, 0x38, 0x32, 0x16, 0x81, 0x48, 0x03, 0x5f, 0xa0, 0x38, 0x32, 0x16, 0x86, 0x48, 0x3e, 0x5c, 0x17, 0x07, 0x80, 0x41, 0x1c, 0x5f, 0x01, 0x5c, 0x3e, 0x5f, 0xe2, 0x38, 0x05, 0x00, 0x04, 0x96, 0xfd, 0x61, 0xb4, 0x69, 0x81, 0x40, 0x21, 0x5c, 0x1e, 0x5f, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x83, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x82, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x90, 0x38, 0x54, 0x1a, 0xbe, 0x58, 0x54, 0x1a, 0xfd, 0x70, -0x00, 0x10, 0x3e, 0x5f, 0x19, 0x07, 0xe2, 0x38, 0x09, 0x00, 0xa5, 0x97, 0x3e, 0x5f, 0x3a, 0x38, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x9e, 0x5c, 0x58, 0x1a, 0x18, 0x14, 0x29, 0x9a, 0x19, 0x14, 0xff, 0x67, 0x7f, 0x6f, 0x87, 0x38, 0x38, 0x10, 0x80, 0x38, 0x72, 0x19, 0x80, 0x39, 0x86, 0x19, 0xb8, 0x49, 0x02, 0x88, 0xd9, 0x49, 0x0e, 0x8a, 0x13, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x32, 0x11, 0x01, 0x8c, 0x22, 0x59, 0x01, 0x00, 0xe4, 0x39, 0xff, 0x00, 0x19, 0x48, 0x03, 0x94, 0xfe, 0x5c, 0x04, 0x2f, 0xfe, 0x5c, 0x19, 0x14, 0xe4, 0x3c, 0x00, 0xff, 0xfe, 0x5c, 0x80, 0x38, 0x72, 0x19, 0x13, 0x11, 0x01, 0x8c, 0xf1, 0x08, -0x40, 0x10, 0x22, 0x59, 0x80, 0x38, 0x86, 0x19, 0x12, 0x17, 0x01, 0x8c, 0xe2, 0x5f, 0x3a, 0x38, 0x21, 0x72, 0x43, 0x43, 0x01, 0x5c, 0x43, 0x41, 0x24, 0x01, 0x9e, 0x5c, 0x54, 0x1a, 0x1c, 0x5c, 0x18, 0x00, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0xd2, 0x60, 0x15, 0x68, 0x03, 0x59, 0x22, 0x38, 0x01, 0x00, 0x03, 0x8a, 0x22, 0x38, 0x02, 0x00, 0x06, 0x8a, 0x00, 0x60, 0xbe, 0x58, 0x0b, 0x1f, 0xbe, 0x58, 0x0c, 0x1f, 0x0a, 0x9e, 0xb2, 0x60, 0x19, 0x68, 0x03, 0x59, 0xbe, 0x59, 0x0c, 0x1f, 0xbe, 0x60, 0x19, 0x68, 0x03, 0x59, 0xbe, 0x59, 0x0b, 0x1f, 0x3e, 0x59, 0x3e, 0x58, 0x00, 0x60, 0xbe, 0x58, 0xe2, 0x19, 0x58, 0x60, 0x1a, 0x68, 0x00, 0x61, 0x38, 0x49, 0x58, 0x8a, 0x00, 0x67, 0xe0, 0x38, 0x72, 0x19, 0x03, 0x5d, 0xe0, 0x38, 0x86, 0x19, 0x03, 0x5e, 0xcf, 0xd0, 0xef, 0xd1, 0x9e, 0x58, 0x49, 0x13, -0x80, 0x10, 0x59, 0x1a, 0x19, 0x10, 0x05, 0x8a, 0xdb, 0xd0, 0x9e, 0x58, 0x59, 0x1a, 0x1a, 0x10, 0x01, 0x8a, 0xa8, 0xcf, 0x51, 0x63, 0x1a, 0x6b, 0x47, 0xd0, 0x9e, 0x5d, 0xe2, 0x19, 0xa0, 0x3b, 0xb2, 0x19, 0x1b, 0x5b, 0x53, 0x63, 0x1a, 0x6b, 0x47, 0xd0, 0xa0, 0x3b, 0xbe, 0x19, 0x1b, 0x5b, 0x1e, 0x58, 0x1e, 0x59, 0xa2, 0x38, 0x00, 0x00, 0x13, 0x88, 0x9e, 0x58, 0x0b, 0x1f, 0x18, 0x10, 0x05, 0x88, 0x9e, 0x58, 0x0c, 0x1f, 0x18, 0x10, 0x01, 0x88, 0x0a, 0x9e, 0x9e, 0x58, 0x0b, 0x1f, 0xb2, 0x61, 0x19, 0x69, 0x1b, 0x59, 0x9e, 0x58, 0x0c, 0x1f, 0xbe, 0x61, 0x19, 0x69, 0x1b, 0x59, 0x3e, 0x59, 0x3e, 0x58, 0xe2, 0x62, 0x19, 0x6a, 0xca, 0x63, 0x19, 0x6b, 0x53, 0x03, 0xde, 0x5b, 0xff, 0xff, 0xd6, 0x63, 0x19, 0x6b, 0x53, 0x03, 0xde, 0x5b, 0xff, 0x7f, 0x43, 0x5b, 0x68, 0x3a, 0x01, 0x00, 0x5c, 0xdf, -0xc0, 0x10, 0x59, 0x60, 0x1a, 0x68, 0xde, 0x58, 0x00, 0x00, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0x27, 0x00, 0x05, 0x94, 0x19, 0x07, 0x58, 0x60, 0x1a, 0x68, 0xf8, 0x49, 0xa9, 0x81, 0x3a, 0x38, 0x50, 0x60, 0x1a, 0x68, 0x00, 0x61, 0x04, 0x62, 0x47, 0x38, 0xd6, 0x10, 0x3d, 0x58, 0x1a, 0x38, 0x59, 0x60, 0x1a, 0x68, 0x3b, 0x58, 0x3a, 0x38, 0xbe, 0x5d, 0xe1, 0x1b, 0xbe, 0x5e, 0xe2, 0x1b, 0x1e, 0x5f, 0x00, 0x67, 0xe0, 0x39, 0xde, 0x15, 0x23, 0x59, 0xe0, 0x3a, 0xf2, 0x15, 0x43, 0x5a, 0xe0, 0x3b, 0x06, 0x16, 0x63, 0x5b, 0xe0, 0x3c, 0x1a, 0x16, 0x83, 0x5c, 0xb9, 0x48, 0x07, 0x96, 0xba, 0x48, 0x05, 0x98, 0xdb, 0x48, 0x03, 0x98, 0xdc, 0x48, 0x01, 0x96, 0x05, 0x9e, 0x19, 0x07, 0xf2, 0x39, 0x4b, 0x1a, 0xe7, 0x97, 0xa9, 0x9e, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x67, 0x00, 0x60, 0x97, 0xfd, -0x00, 0x11, 0xe0, 0x3d, 0x72, 0x19, 0xa3, 0x5d, 0xe0, 0x3e, 0x86, 0x19, 0xc3, 0x5e, 0xb9, 0x48, 0x0a, 0x96, 0xba, 0x48, 0x08, 0x98, 0xdb, 0x48, 0x06, 0x98, 0xdc, 0x48, 0x04, 0x96, 0x19, 0x00, 0xfe, 0x5f, 0x07, 0x28, 0xfe, 0x5f, 0x19, 0x07, 0xf2, 0x3d, 0x58, 0x1a, 0xea, 0x97, 0x3e, 0x5f, 0x04, 0x3d, 0xff, 0x00, 0x19, 0x15, 0x01, 0x8a, 0x86, 0x9e, 0x41, 0x16, 0xc1, 0x5f, 0x64, 0x15, 0xdd, 0x48, 0x01, 0x94, 0xa1, 0x5f, 0x1d, 0x17, 0x7b, 0x98, 0x04, 0x3f, 0x00, 0xff, 0xfe, 0x5f, 0x1a, 0x16, 0x0d, 0x94, 0xe0, 0x38, 0x72, 0x19, 0x03, 0x58, 0x18, 0x10, 0x02, 0x9a, 0x02, 0x39, 0x01, 0x00, 0x12, 0x3e, 0xfd, 0x1b, 0x19, 0x06, 0x02, 0x94, 0x00, 0x3a, 0x01, 0x00, 0x1a, 0x15, 0x0d, 0x94, 0xe0, 0x38, 0x86, 0x19, 0x03, 0x58, 0x18, 0x10, 0x02, 0x9a, 0x02, 0x3c, 0x01, 0x00, 0x12, 0x3e, 0xb0, 0xa9, -0x40, 0x11, 0xfe, 0x1b, 0x19, 0x06, 0x02, 0x94, 0x00, 0x3b, 0x01, 0x00, 0x1e, 0x59, 0x21, 0x5d, 0x9e, 0x5e, 0xfd, 0x1b, 0xa0, 0x38, 0x32, 0x16, 0xc4, 0x48, 0x03, 0x5e, 0x9e, 0x58, 0xe6, 0x1b, 0x00, 0x61, 0x01, 0x69, 0x19, 0x48, 0x12, 0x98, 0xb2, 0x38, 0xe1, 0x1b, 0x03, 0x88, 0x92, 0x38, 0xe2, 0x1b, 0x0c, 0x8a, 0x18, 0x16, 0x07, 0x9a, 0x08, 0x60, 0xc0, 0x40, 0x08, 0x5e, 0xc0, 0x06, 0xc8, 0x5e, 0xc8, 0x5e, 0xc8, 0x5e, 0x9e, 0x58, 0xe4, 0x1b, 0xc0, 0x06, 0x18, 0x16, 0x2b, 0x9a, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0xc5, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0xc4, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0xd0, 0x3f, 0x54, 0x1a, 0xbe, 0x5f, 0x54, 0x1a, 0x7f, 0xac, 0x17, 0x90, 0xe8, 0x5f, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x58, 0x50, 0x1a, 0x76, 0x7e, -0x80, 0x11, 0x9e, 0x59, 0x51, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x51, 0x1a, 0xbe, 0x58, 0x50, 0x1a, 0x9e, 0x58, 0x52, 0x1a, 0x9e, 0x59, 0x53, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x53, 0x1a, 0xbe, 0x58, 0x52, 0x1a, 0xa2, 0x37, 0x02, 0x8a, 0x19, 0x05, 0xb1, 0x9f, 0x3e, 0x59, 0x83, 0x37, 0x02, 0x8a, 0x19, 0x04, 0xaa, 0x9f, 0x02, 0x65, 0xbe, 0x5d, 0x59, 0x1a, 0x03, 0x9e, 0x03, 0x65, 0xbe, 0x5d, 0x59, 0x1a, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5f, 0x3a, 0x38, 0x1e, 0x5c, 0x9e, 0x5d, 0xe1, 0x1b, 0x9e, 0x5e, 0xe2, 0x1b, 0xa0, 0x38, 0x32, 0x16, 0x16, 0x67, 0x1e, 0x59, 0x00, 0x61, 0xc7, 0x48, 0x3e, 0x59, 0x03, 0x5f, 0x18, 0x17, 0x35, 0x9a, 0x1e, 0x59, 0x1e, 0x5a, 0x00, 0x61, 0xe1, 0x58, 0xbe, 0x5f, 0xe6, 0x1b, 0x06, 0x58, 0x2a, 0x59, 0x06, 0x58, 0x2a, 0x59, 0x0c, 0x62, 0xb9, 0x8c, -0xc0, 0x11, 0x1c, 0x5a, 0xbe, 0x58, 0xe3, 0x1b, 0x00, 0x61, 0xe1, 0x58, 0xa8, 0x62, 0x1c, 0x5a, 0xbe, 0x58, 0xe4, 0x1b, 0x3e, 0x5a, 0x3e, 0x59, 0x41, 0x10, 0x21, 0x5f, 0x07, 0x38, 0xe5, 0x11, 0xfd, 0x48, 0x02, 0x88, 0x9e, 0x48, 0x12, 0x8a, 0x20, 0x38, 0x32, 0x16, 0x1e, 0x59, 0x1e, 0x5a, 0x16, 0x62, 0x00, 0x61, 0x82, 0x48, 0x3e, 0x5a, 0x3e, 0x59, 0x03, 0x58, 0x18, 0x10, 0x06, 0x9a, 0x1e, 0x59, 0x9e, 0x59, 0xe3, 0x1b, 0x19, 0x48, 0x3e, 0x59, 0x05, 0x94, 0x19, 0x07, 0x19, 0x04, 0x9b, 0x48, 0xe2, 0x9b, 0x03, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0xe4, 0x1b, 0x3e, 0x5c, 0x3a, 0x38, 0x9e, 0x58, 0x58, 0x1a, 0x02, 0x39, 0x01, 0x00, 0x1d, 0x9a, 0x00, 0x62, 0x5f, 0x48, 0x16, 0x8a, 0x40, 0x38, 0x72, 0x19, 0x03, 0x5b, 0x40, 0x38, 0x86, 0x19, 0x03, 0x5c, 0xa3, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x76, 0x63, -0x00, 0x12, 0x02, 0x39, 0x01, 0x00, 0x0a, 0x88, 0xc4, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x02, 0x39, 0x01, 0x00, 0x04, 0x88, 0x01, 0x61, 0xbe, 0x59, 0x59, 0x1a, 0x04, 0x9e, 0x19, 0x02, 0x52, 0x39, 0x58, 0x1a, 0xe4, 0x89, 0x3a, 0x38, 0x9e, 0x58, 0x58, 0x1a, 0x02, 0x39, 0x01, 0x00, 0x66, 0x9a, 0x00, 0x67, 0xe0, 0x3e, 0x86, 0x19, 0xe0, 0x3a, 0x01, 0x00, 0x40, 0x3b, 0x72, 0x19, 0x40, 0x3c, 0x86, 0x19, 0xe0, 0x3d, 0x72, 0x19, 0xa3, 0x5d, 0xa4, 0x38, 0x00, 0xff, 0x63, 0x5b, 0x64, 0x39, 0x00, 0xff, 0x19, 0x48, 0x4a, 0x88, 0xa4, 0x3d, 0xff, 0x00, 0x64, 0x3b, 0xff, 0x00, 0x1e, 0x5f, 0x1e, 0x5a, 0x9e, 0x5f, 0xfd, 0x1b, 0x60, 0x38, 0x48, 0x0e, 0xe4, 0x49, 0x03, 0x5a, 0xa0, 0x38, 0x48, 0x0e, 0xe6, 0x49, 0x00, 0x61, 0x58, 0x49, 0x02, 0x9a, 0x01, 0x61, 0x03, 0x5a, 0x1e, 0x59, 0x9e, 0x58, 0x0d, 0x2c, -0x40, 0x12, 0x44, 0x1a, 0x40, 0x40, 0x9f, 0x38, 0x08, 0x58, 0xbe, 0x58, 0x83, 0x1a, 0x8a, 0xd2, 0x19, 0x10, 0x28, 0x8a, 0x9e, 0x58, 0x58, 0x1a, 0x19, 0x10, 0xbe, 0x58, 0x58, 0x1a, 0x3e, 0x59, 0x3e, 0x5a, 0x3e, 0x5f, 0x40, 0x3b, 0x72, 0x19, 0xe0, 0x3d, 0x72, 0x19, 0x18, 0x11, 0x04, 0x8a, 0x63, 0x59, 0x3b, 0x5d, 0x83, 0x59, 0x3b, 0x5e, 0x72, 0x61, 0x19, 0x69, 0x30, 0x39, 0x58, 0x1a, 0x23, 0x59, 0x3b, 0x5b, 0x86, 0x61, 0x19, 0x69, 0x30, 0x39, 0x58, 0x1a, 0x23, 0x59, 0x3b, 0x5c, 0x19, 0x10, 0x14, 0x8a, 0x52, 0x38, 0x58, 0x1a, 0x0c, 0x94, 0xf2, 0x38, 0x58, 0x1a, 0x19, 0x00, 0x0d, 0x94, 0xab, 0x9f, 0x3e, 0x59, 0x3e, 0x5a, 0x3e, 0x5f, 0x19, 0x02, 0x52, 0x39, 0x58, 0x1a, 0xa4, 0x97, 0x19, 0x07, 0xf2, 0x39, 0x58, 0x1a, 0x19, 0x01, 0x9b, 0x97, 0x9e, 0x58, 0x58, 0x1a, 0x18, 0x10, 0x0c, 0xc1, -0x80, 0x12, 0x08, 0x8a, 0x72, 0x66, 0x19, 0x6e, 0xff, 0x61, 0x19, 0x10, 0x07, 0x38, 0x88, 0x12, 0xd1, 0x25, 0xbd, 0x5e, 0x3a, 0x38, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5b, 0x1e, 0x5c, 0x83, 0x5a, 0x7d, 0x48, 0x03, 0x9a, 0x5e, 0x49, 0x23, 0x9a, 0x32, 0x9e, 0x5e, 0x49, 0x10, 0x9a, 0x61, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0xa1, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x02, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x2f, 0x9e, 0x61, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0xa1, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x00, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x1f, 0x9e, 0xa1, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0x61, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0xc3, 0x5a, 0xf9, 0x02, -0xc0, 0x12, 0xbe, 0x5a, 0x31, 0x16, 0x06, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x0f, 0x9e, 0xa1, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0x61, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x04, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0xc3, 0x5e, 0xa1, 0x58, 0xc1, 0x59, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5b, 0x1e, 0x5c, 0x00, 0x67, 0x9e, 0x5a, 0x82, 0x1a, 0x40, 0x3c, 0x25, 0x13, 0x89, 0x5c, 0x85, 0x04, 0x92, 0x39, 0x2e, 0x16, 0x23, 0x96, 0x92, 0x39, 0x2f, 0x16, 0x20, 0x98, 0x40, 0x3b, 0x2d, 0x13, 0x69, 0x5b, 0x66, 0x03, 0x72, 0x39, 0x30, 0x16, 0x19, 0x96, 0x72, 0x39, 0x31, 0x16, 0x16, 0x98, 0x9e, 0x59, 0xfd, 0x1b, 0x80, 0x38, 0x48, 0x0e, 0x23, 0x48, 0x9e, 0x59, 0x83, 0x1a, 0x38, 0x49, 0x0d, 0x98, 0x81, 0x5d, 0x61, 0x5e, 0x9e, 0x59, 0x82, 0x1a, 0xd8, 0xd6, -0x00, 0x13, 0x01, 0xac, 0x02, 0x90, 0x1e, 0x01, 0x01, 0x9e, 0x1f, 0x01, 0x1f, 0x21, 0xbe, 0x59, 0x82, 0x1a, 0x08, 0x9e, 0x19, 0x02, 0x1f, 0x22, 0xbe, 0x5a, 0x82, 0x1a, 0x19, 0x07, 0xe2, 0x39, 0x08, 0x00, 0xce, 0x97, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x59, 0x3e, 0x58, 0xd9, 0x48, 0x04, 0x88, 0xb8, 0x48, 0x02, 0x88, 0x01, 0x60, 0x05, 0x9e, 0xdc, 0x49, 0xbb, 0x89, 0xbb, 0x48, 0xb9, 0x89, 0x00, 0x60, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5e, 0x3e, 0x5d, 0x3a, 0x38, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0x3f, 0x01, 0x00, 0x0c, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x0b, 0x09, -0x40, 0x13, 0x42, 0x13, 0xa5, 0x59, 0x3d, 0x5e, 0x21, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1e, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x52, 0x13, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x0f, 0x88, 0x30, 0x66, 0x0b, 0x6e, 0x22, 0x75, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x63, 0x13, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0x27, 0x76, 0x19, 0x16, 0x39, 0x60, 0x15, 0x68, 0x9a, 0x61, 0x19, 0x69, 0x45, 0x62, 0x15, 0x6a, 0xa6, 0x63, 0x19, 0x6b, 0x00, 0x64, 0x80, 0x6c, 0x00, 0x67, 0xc7, 0x38, 0x7e, 0x13, 0xf8, 0x49, 0x04, 0x98, 0x03, 0x5d, 0xbb, 0x59, 0x43, 0x5d, 0xbb, 0x5b, 0x19, 0x01, 0x19, 0x03, 0x9d, 0x58, 0x9d, 0x5a, 0x21, 0x60, 0x24, 0x0a, -0x80, 0x13, 0x15, 0x68, 0x2b, 0x61, 0x1c, 0x69, 0x2d, 0x62, 0x15, 0x6a, 0x37, 0x63, 0x1c, 0x6b, 0x00, 0x65, 0xc7, 0x38, 0x9d, 0x13, 0xa0, 0x3c, 0x63, 0x29, 0x89, 0x5c, 0x94, 0x3c, 0xe3, 0x19, 0x05, 0x8a, 0x03, 0x5c, 0x9b, 0x59, 0x43, 0x5c, 0x9b, 0x5b, 0x04, 0x9e, 0xde, 0x59, 0x00, 0x80, 0xde, 0x5b, 0x00, 0x80, 0x19, 0x01, 0x19, 0x03, 0x19, 0x00, 0x19, 0x02, 0x19, 0x05, 0x00, 0x67, 0x80, 0x6f, 0x51, 0x60, 0x15, 0x68, 0x21, 0x61, 0x15, 0x69, 0x5d, 0x62, 0x15, 0x6a, 0x2d, 0x63, 0x15, 0x6b, 0xc7, 0x38, 0xb3, 0x13, 0xf8, 0x49, 0x04, 0x8a, 0x03, 0x5c, 0x9b, 0x59, 0x43, 0x5c, 0x9b, 0x5b, 0x19, 0x01, 0x19, 0x03, 0x19, 0x00, 0x19, 0x02, 0xca, 0x60, 0x19, 0x68, 0xd6, 0x61, 0x19, 0x69, 0xc7, 0x38, 0xbf, 0x13, 0xde, 0x58, 0xff, 0xff, 0xde, 0x59, 0xff, 0x7f, 0x19, 0x00, 0x19, 0x01, 0x00, 0xae, -0xc0, 0x13, 0x9e, 0x58, 0xfa, 0x1b, 0x12, 0x38, 0xe2, 0x19, 0x16, 0x9a, 0x00, 0x67, 0x01, 0x65, 0xc7, 0x38, 0xda, 0x13, 0xb4, 0x38, 0x4c, 0x1a, 0x0d, 0x88, 0xe0, 0x38, 0x9a, 0x19, 0xde, 0x58, 0x00, 0x80, 0xe0, 0x38, 0xa6, 0x19, 0xde, 0x58, 0x00, 0x80, 0xa0, 0x5c, 0x94, 0x3c, 0x00, 0x1c, 0xbe, 0x5c, 0x00, 0x1c, 0xa6, 0x5d, 0x19, 0x07, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x24, 0x8a, 0x21, 0x72, 0x23, 0x61, 0x22, 0x40, 0x00, 0x3b, 0x00, 0x00, 0x15, 0x61, 0x22, 0x40, 0x00, 0x3c, 0x00, 0x00, 0xe1, 0x5e, 0x00, 0x67, 0xe0, 0x39, 0xb2, 0x19, 0xe0, 0x3a, 0xbe, 0x19, 0x79, 0x49, 0x02, 0x80, 0x9a, 0x49, 0x0c, 0x82, 0x19, 0x16, 0xdf, 0x48, 0x0c, 0x8a, 0xc0, 0x38, 0xb2, 0x19, 0x03, 0x58, 0x1b, 0x59, 0xc0, 0x38, 0xbe, 0x19, 0x03, 0x58, 0x1b, 0x5a, 0xec, 0x9f, 0x19, 0x07, 0x78, 0x6b, -0x00, 0x14, 0xe6, 0x15, 0xe9, 0x97, 0xbe, 0x5e, 0xe2, 0x19, 0x01, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x00, 0x67, 0xe2, 0x60, 0x19, 0x68, 0xf8, 0x49, 0x31, 0x94, 0xe0, 0x38, 0xca, 0x19, 0x00, 0x61, 0x38, 0x49, 0x2a, 0x9a, 0x00, 0x66, 0x27, 0x70, 0x19, 0x10, 0x07, 0x38, 0x3a, 0x14, 0xc0, 0x38, 0x39, 0x15, 0x00, 0x61, 0x38, 0x49, 0x1f, 0x9a, 0xc0, 0x38, 0x9a, 0x19, 0x00, 0x61, 0x38, 0x49, 0x03, 0x9a, 0xfe, 0x65, 0x7f, 0x6d, 0x0f, 0x9e, 0xe0, 0x38, 0xb2, 0x19, 0xc0, 0x39, 0x9a, 0x19, 0x23, 0x59, 0x11, 0x12, 0xe0, 0x38, 0xbe, 0x19, 0xc0, 0x39, 0xa6, 0x19, 0x23, 0x59, 0x11, 0x13, 0x5a, 0x40, 0x63, 0x48, 0x46, 0xd9, 0xe0, 0x38, 0xd6, 0x19, 0xb8, 0x49, 0x04, 0x94, 0xbb, 0x58, 0xe0, 0x38, 0xca, 0x19, 0xdb, 0x58, 0x19, 0x06, 0x19, 0x07, 0xcb, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x1c, 0xba, -0x40, 0x14, 0x00, 0x67, 0x9e, 0x5d, 0xe2, 0x19, 0xfd, 0x48, 0x25, 0x94, 0xe0, 0x3e, 0x01, 0x00, 0xa2, 0x38, 0x01, 0x00, 0x07, 0x38, 0x67, 0x14, 0xdd, 0x48, 0x1b, 0x94, 0xe0, 0x3c, 0xca, 0x19, 0x83, 0x58, 0xc0, 0x3b, 0xca, 0x19, 0x1b, 0x49, 0x13, 0x88, 0xe0, 0x3a, 0xd6, 0x19, 0x43, 0x58, 0xc0, 0x39, 0xd6, 0x19, 0x19, 0x49, 0x05, 0x9a, 0xde, 0x5c, 0xff, 0xff, 0xde, 0x5a, 0xff, 0x7f, 0x04, 0x9e, 0xde, 0x5b, 0xff, 0xff, 0xde, 0x59, 0xff, 0x7f, 0x01, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x19, 0x06, 0x19, 0x07, 0xd9, 0x9f, 0x00, 0x67, 0xe2, 0x60, 0x19, 0x68, 0xf8, 0x49, 0x15, 0x94, 0xe0, 0x38, 0xca, 0x19, 0x00, 0x61, 0x38, 0x49, 0x0e, 0x98, 0x39, 0x61, 0x15, 0x69, 0x11, 0x01, 0xe0, 0x3a, 0xb2, 0x19, 0x43, 0x5a, 0x5b, 0x59, 0x45, 0x61, 0x15, 0x69, 0x11, 0x01, 0xe0, 0x3a, 0xbe, 0x19, 0xb2, 0x4c, -0x80, 0x14, 0x43, 0x5a, 0x5b, 0x59, 0x19, 0x07, 0xe7, 0x9f, 0x82, 0x60, 0x1a, 0x68, 0x01, 0x61, 0x38, 0x49, 0x7e, 0x8b, 0x9e, 0x58, 0xe2, 0x19, 0x19, 0x10, 0x01, 0x9a, 0x25, 0xdb, 0x92, 0x60, 0x15, 0x68, 0xff, 0x61, 0xff, 0x69, 0x27, 0x76, 0x19, 0x16, 0xd7, 0x38, 0x3d, 0x58, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x10, 0x8a, 0x92, 0x66, 0x15, 0x6e, 0x19, 0x17, 0xe7, 0x38, 0xa9, 0x14, 0xe0, 0x3b, 0xca, 0x19, 0x76, 0x03, 0xe0, 0x3c, 0xd6, 0x19, 0x83, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x21, 0x74, 0x9b, 0x5b, 0x19, 0x17, 0x01, 0x67, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0xb0, 0x14, 0xe6, 0x5f, 0x1a, 0x38, 0x19, 0x17, 0xbe, 0x5f, 0x84, 0x1a, 0xf1, 0xd5, 0x9e, 0x58, 0xe2, 0x19, 0xbe, 0x58, 0xfa, 0x1b, 0x00, 0x67, 0x27, 0x70, 0x19, 0x10, 0x07, 0x38, 0x51, 0x15, 0x9e, 0x58, 0xea, 0x04, 0xc4, 0xb3, -0xc0, 0x14, 0x18, 0x10, 0x03, 0x8a, 0x02, 0x60, 0x20, 0x78, 0x02, 0x9e, 0x02, 0x60, 0x20, 0x78, 0xe0, 0x38, 0x39, 0x15, 0xe0, 0x3c, 0xd2, 0x15, 0x00, 0x61, 0x38, 0x49, 0x50, 0x98, 0xd0, 0x73, 0x7c, 0x49, 0x02, 0x9a, 0x7b, 0x5c, 0x7e, 0x9e, 0x70, 0x3b, 0x20, 0x00, 0x7c, 0x49, 0x14, 0x98, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0xe3, 0x61, 0x19, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x4c, 0x61, 0x1a, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x70, 0x3b, 0xcf, 0x00, 0x7c, 0x49, 0x34, 0x98, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x66, 0x9e, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x14, 0x3a, 0xe3, 0x19, 0x02, 0x8a, 0x7b, 0x5c, 0x27, 0x9e, 0xe0, 0x38, 0x92, 0x15, 0x0a, 0x61, 0x38, 0x49, 0x09, 0x9c, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x00, 0x5a, 0x32, 0x22, 0x5b, 0x59, 0x7f, 0x32, -0x00, 0x15, 0x19, 0x9e, 0xd0, 0x70, 0x19, 0x00, 0x1c, 0x49, 0x15, 0x88, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x30, 0x22, 0x0e, 0x88, 0x30, 0x2a, 0x5b, 0x59, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x13, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x1f, 0x1c, 0x1b, 0x59, 0x83, 0x58, 0x08, 0x3c, 0x01, 0x00, 0x33, 0x9e, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0xd0, 0x73, 0x14, 0x39, 0x4c, 0x1a, 0x04, 0x8a, 0x00, 0x61, 0x91, 0x11, 0x09, 0x98, 0x0b, 0x9e, 0x7c, 0x49, 0x09, 0x94, 0x7b, 0x5c, 0x00, 0x61, 0x1c, 0x69, 0x00, 0x5a, 0x32, 0x22, 0x5b, 0x59, 0x83, 0x59, 0x2a, 0x3c, 0x01, 0x00, 0x00, 0x58, 0x70, 0x3b, 0x1f, 0x00, 0x7c, 0x49, 0x10, 0x96, 0xe3, 0x61, 0x19, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x44, 0x4e, -0x40, 0x15, 0x5b, 0x59, 0x83, 0x5b, 0x72, 0x3b, 0xd0, 0x00, 0x0c, 0x9a, 0xd0, 0x73, 0x19, 0x13, 0x7b, 0x5c, 0x08, 0x9e, 0x54, 0xd5, 0x19, 0x03, 0x7c, 0x49, 0x04, 0x96, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x19, 0x07, 0x99, 0xd6, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x5b, 0x21, 0x72, 0x23, 0x65, 0xa2, 0x40, 0x00, 0x3d, 0x00, 0x00, 0xe0, 0x38, 0x5b, 0x1c, 0x03, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x0b, 0x9e, 0x1d, 0x48, 0x02, 0x9a, 0xa1, 0x58, 0x07, 0x9e, 0x40, 0x3b, 0x00, 0x00, 0x1b, 0x48, 0x03, 0x96, 0xa2, 0x13, 0x1b, 0x48, 0x03, 0x9a, 0xe0, 0x39, 0x9a, 0x19, 0x1b, 0x59, 0x15, 0x65, 0xa2, 0x40, 0x00, 0x3d, 0x00, 0x00, 0xe0, 0x38, 0x67, 0x1c, 0x03, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x0b, 0x9e, 0x1d, 0x48, 0x02, 0x9a, 0xa1, 0x58, 0x07, 0x9e, 0x40, 0x3b, 0xcf, 0x67, -0x80, 0x15, 0x00, 0x00, 0x1b, 0x48, 0x03, 0x96, 0xa2, 0x13, 0x1b, 0x48, 0x03, 0x9a, 0xe0, 0x39, 0xa6, 0x19, 0x1b, 0x59, 0x3e, 0x5b, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x04, 0x1c, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0xea, 0x04, 0x31, 0x94, 0x01, 0x60, 0xbe, 0x58, 0x04, 0x1c, 0x27, 0x76, 0x19, 0x16, 0x00, 0x65, 0x00, 0x67, 0xc7, 0x38, 0xc4, 0x15, 0xe0, 0x38, 0x9a, 0x19, 0xb8, 0x49, 0x23, 0x98, 0xe0, 0x3e, 0x63, 0x29, 0xc9, 0x5e, 0xd4, 0x3e, 0xe3, 0x19, 0x0b, 0x88, 0x03, 0x58, 0xe0, 0x39, 0x5b, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0xa6, 0x19, 0x03, 0x58, 0xe0, 0x39, 0x67, 0x1c, 0x1b, 0x59, 0x12, 0x9e, 0xe0, 0x39, 0x43, 0x1c, 0x23, 0x59, 0xe0, 0x3a, 0x4f, 0x1c, 0x43, 0x5a, 0xe0, 0x38, 0x9a, 0x19, 0x11, 0x00, 0xe0, 0x39, 0x5b, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0xa6, 0x19, 0x4a, 0xa6, -0xc0, 0x15, 0x12, 0x00, 0xe0, 0x39, 0x67, 0x1c, 0x1b, 0x59, 0x19, 0x07, 0x3a, 0x38, 0x27, 0x76, 0x19, 0x16, 0x00, 0x67, 0xc7, 0x38, 0xef, 0x15, 0x00, 0x62, 0xe0, 0x38, 0x39, 0x15, 0x58, 0x49, 0x1f, 0x98, 0xe0, 0x39, 0x9a, 0x19, 0x59, 0x49, 0x1b, 0x98, 0x23, 0x5a, 0x12, 0x12, 0xe0, 0x3c, 0x43, 0x1c, 0x5b, 0x5c, 0xe0, 0x38, 0x45, 0x15, 0xe0, 0x39, 0xa6, 0x19, 0x23, 0x5b, 0x13, 0x13, 0xe0, 0x3c, 0x4f, 0x1c, 0x7b, 0x5c, 0x9e, 0x58, 0x04, 0x1c, 0x18, 0x10, 0x09, 0x8a, 0x5a, 0x40, 0x63, 0x48, 0x46, 0xd9, 0x18, 0x15, 0x01, 0x88, 0x21, 0x75, 0xe0, 0x38, 0x92, 0x15, 0xbb, 0x58, 0x19, 0x07, 0x3a, 0x38, 0x27, 0x75, 0x19, 0x15, 0xa7, 0x38, 0x73, 0x16, 0xa0, 0x3f, 0x63, 0x29, 0xe9, 0x5f, 0x9e, 0x5c, 0x86, 0x1a, 0xe0, 0x5b, 0x83, 0x24, 0xa0, 0x3b, 0xa0, 0x1a, 0x63, 0x5b, 0xbd, 0x13, 0xe6, 0xbc, -0x00, 0x16, 0x01, 0x96, 0x87, 0x2c, 0xbe, 0x5c, 0x86, 0x1a, 0xa0, 0x3c, 0x92, 0x15, 0x83, 0x5c, 0x82, 0x38, 0xff, 0xff, 0x69, 0x8a, 0x21, 0x73, 0x66, 0x5b, 0x83, 0x11, 0x65, 0x9a, 0x81, 0x58, 0xa0, 0x3a, 0x9e, 0x15, 0x43, 0x5a, 0x21, 0x73, 0x68, 0x5b, 0x42, 0x39, 0xfe, 0x7f, 0x05, 0x88, 0xf4, 0x39, 0x87, 0x1a, 0x02, 0x8a, 0x61, 0x5a, 0x16, 0x9e, 0x5b, 0x48, 0x14, 0x98, 0xa0, 0x39, 0x88, 0x1a, 0x23, 0x59, 0x18, 0x11, 0x02, 0x8a, 0x04, 0x62, 0x0d, 0x9e, 0x02, 0xa8, 0xa0, 0x39, 0xa0, 0x1a, 0x23, 0x59, 0xbd, 0x11, 0x07, 0x96, 0xa0, 0x39, 0x94, 0x1a, 0x23, 0x59, 0x24, 0x39, 0xff, 0x00, 0x01, 0x8a, 0x61, 0x5a, 0x04, 0x61, 0x01, 0x40, 0x1c, 0x5a, 0x00, 0x39, 0x01, 0x00, 0x28, 0x59, 0x1a, 0x00, 0x08, 0x58, 0x08, 0x58, 0x1a, 0x11, 0x03, 0x88, 0xf4, 0x39, 0x4a, 0x1a, 0x28, 0x88, 0x7f, 0xca, -0x40, 0x16, 0x04, 0x62, 0xf4, 0x3e, 0x86, 0x1a, 0x01, 0x8a, 0x19, 0x62, 0x00, 0x61, 0xbe, 0x59, 0x17, 0x1f, 0x9e, 0x59, 0x20, 0x1d, 0x18, 0x11, 0x13, 0x8a, 0x22, 0x39, 0x68, 0x01, 0x14, 0x8a, 0x9e, 0x5e, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0xc1, 0x06, 0x1b, 0x16, 0x09, 0x88, 0x9e, 0x5e, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0xc1, 0x06, 0x1b, 0x16, 0x02, 0x88, 0x3a, 0x02, 0x05, 0x9e, 0x9e, 0x59, 0xb5, 0x00, 0x1a, 0x11, 0x01, 0x88, 0x3a, 0x02, 0xbe, 0x5a, 0x17, 0x1f, 0x02, 0x11, 0x0b, 0x96, 0xa0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x14, 0x3a, 0x00, 0x1c, 0x05, 0x88, 0x00, 0x58, 0x84, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x19, 0x15, 0x21, 0x74, 0x88, 0x5c, 0x92, 0x60, 0x15, 0x68, 0x9e, 0x61, 0x15, 0x69, 0x00, 0x65, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0x97, 0x16, 0xa0, 0x3f, 0x7a, 0x56, -0x80, 0x16, 0x63, 0x29, 0xe9, 0x5f, 0xff, 0x66, 0xff, 0x6e, 0xd8, 0x49, 0x03, 0x8a, 0x03, 0x5a, 0x5b, 0x59, 0x0c, 0x9e, 0xf4, 0x3b, 0xe3, 0x19, 0x09, 0x8a, 0xa0, 0x3b, 0xa0, 0x1a, 0x63, 0x5b, 0xbd, 0x13, 0x04, 0x82, 0x99, 0x49, 0x02, 0x82, 0x8a, 0x39, 0x01, 0x00, 0x19, 0x00, 0x19, 0x01, 0x19, 0x05, 0x3a, 0x38, 0x9e, 0x58, 0xe3, 0x19, 0x9e, 0x59, 0x84, 0x1a, 0x20, 0x59, 0x20, 0x21, 0xbe, 0x59, 0x4a, 0x1a, 0x14, 0x3a, 0x84, 0x1a, 0xbe, 0x5a, 0xe3, 0x19, 0x16, 0x39, 0x85, 0x1a, 0x20, 0x21, 0xbe, 0x59, 0x87, 0x1a, 0xbe, 0x58, 0x85, 0x1a, 0x01, 0x65, 0x00, 0x66, 0x27, 0x77, 0x19, 0x17, 0xe7, 0x38, 0xea, 0x16, 0x05, 0x27, 0x09, 0x8a, 0xc0, 0x39, 0x88, 0x1a, 0x23, 0x5b, 0x66, 0x5b, 0xb4, 0x3f, 0x4a, 0x1a, 0x01, 0x8a, 0x03, 0xa8, 0x7b, 0x59, 0xc0, 0x39, 0xa0, 0x1a, 0x23, 0x5b, 0x56, 0xfa, -0xc0, 0x16, 0xa2, 0x27, 0x0e, 0x8a, 0xd0, 0x77, 0xf0, 0x3f, 0x20, 0x00, 0xf0, 0x3f, 0xcf, 0x00, 0xc0, 0x3c, 0xd2, 0x15, 0xfc, 0x49, 0x05, 0x98, 0x62, 0x3f, 0x64, 0x00, 0x03, 0x82, 0x19, 0x03, 0x01, 0x9e, 0x00, 0x63, 0x7b, 0x59, 0x05, 0x27, 0x0f, 0x8a, 0xc0, 0x39, 0x94, 0x1a, 0x23, 0x5b, 0x66, 0x5b, 0xc0, 0x3c, 0x92, 0x15, 0x83, 0x5c, 0x92, 0x3f, 0x21, 0x00, 0x04, 0x80, 0x82, 0x3f, 0x00, 0x10, 0x01, 0x82, 0x03, 0xa8, 0x7b, 0x59, 0xa0, 0x27, 0x04, 0x88, 0xc0, 0x39, 0x9e, 0x15, 0xde, 0x59, 0xaa, 0x55, 0xa6, 0x5d, 0x19, 0x06, 0x3a, 0x38, 0x00, 0x67, 0xbe, 0x5f, 0xf1, 0x1e, 0xbe, 0x5f, 0xf3, 0x1e, 0x00, 0x67, 0x01, 0x66, 0xd0, 0x3e, 0xd0, 0x00, 0xd0, 0x3e, 0x1f, 0x00, 0xe3, 0x60, 0x19, 0x68, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x5c, 0x14, 0x20, 0x87, 0x88, 0xe0, 0x38, 0x39, 0x15, 0x0d, 0x8c, -0x00, 0x17, 0x00, 0x61, 0x38, 0x49, 0x45, 0x98, 0x37, 0x9e, 0x95, 0x38, 0x4d, 0x1a, 0xbe, 0x58, 0x4d, 0x1a, 0xe0, 0x38, 0x63, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x30, 0x22, 0x2c, 0x8a, 0x00, 0x58, 0x30, 0x22, 0x5b, 0x59, 0xe0, 0x3b, 0x13, 0x1c, 0xe0, 0x39, 0x43, 0x1c, 0x23, 0x59, 0x71, 0x13, 0x18, 0x13, 0x02, 0x94, 0x00, 0x63, 0x07, 0x9e, 0x21, 0x72, 0x23, 0x65, 0xa2, 0x40, 0x18, 0x00, 0x78, 0x48, 0x01, 0x9a, 0x01, 0x5b, 0xe0, 0x39, 0x51, 0x15, 0x7b, 0x59, 0xe0, 0x3b, 0x1f, 0x1c, 0xe0, 0x39, 0x4f, 0x1c, 0x23, 0x59, 0x71, 0x13, 0x18, 0x13, 0x02, 0x94, 0x00, 0x63, 0x07, 0x9e, 0x21, 0x72, 0x15, 0x65, 0xa2, 0x40, 0x18, 0x00, 0x78, 0x48, 0x01, 0x9a, 0x01, 0x5b, 0xe0, 0x39, 0x5d, 0x15, 0x7b, 0x59, 0xee, 0x9e, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x51, 0x15, 0x1f, 0xd8, +0xc0, 0x03, 0x2d, 0x60, 0xbe, 0x58, 0x0a, 0xf8, 0x94, 0x60, 0xbe, 0x58, 0x0c, 0xf8, 0x0f, 0x60, 0xbe, 0x58, 0x0b, 0xf8, 0x9e, 0x58, 0x07, 0xf8, 0x04, 0x38, 0xfe, 0xff, 0xbe, 0x58, 0x07, 0xf8, 0xdd, 0xaa, 0xa5, 0xac, 0x01, 0x90, 0xf3, 0xc8, 0x99, 0xe9, 0x19, 0x38, 0xf2, 0x41, 0xed, 0xac, 0x7a, 0x92, 0xd5, 0xaa, 0xe5, 0xa8, 0x4f, 0xe5, 0x0c, 0xf1, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x18, 0xec, 0x9e, 0x58, 0x36, 0x1d, 0x1d, 0x10, 0x21, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0x1d, 0x8a, 0xdb, 0xf1, 0x86, 0xf6, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x1a, 0x9e, 0x58, 0xb8, 0x04, 0x18, 0x10, 0x14, 0x88, 0x9e, 0x58, 0xc6, 0x00, 0x19, 0x10, 0x10, 0x8a, 0x9e, 0x58, 0xea, 0x19, 0x00, 0x58, 0xbe, 0x58, 0xd3, 0x00, 0x9e, 0x58, 0xeb, 0x19, 0x9f, 0xe2, +0x00, 0x04, 0x00, 0x58, 0xbe, 0x58, 0xd4, 0x00, 0x9e, 0x58, 0xec, 0x19, 0x00, 0x58, 0xbe, 0x58, 0xd5, 0x00, 0x0c, 0x9e, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd3, 0x00, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd4, 0x00, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd5, 0x00, 0x9e, 0x58, 0xfc, 0x01, 0x78, 0xac, 0x08, 0x90, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0xd5, 0x00, 0xbe, 0x58, 0xd4, 0x00, 0xbe, 0x58, 0xd3, 0x00, 0x9d, 0xeb, 0xd7, 0xea, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x18, 0xec, 0x26, 0x60, 0x04, 0x68, 0x3e, 0x61, 0x04, 0x69, 0x9e, 0x5a, 0xbb, 0x00, 0x57, 0x38, 0x3d, 0x58, 0x06, 0x70, 0x00, 0xac, 0x12, 0x90, 0x9e, 0x58, 0xfc, 0x1c, 0x18, 0x10, 0x0e, 0x88, 0x9e, 0x58, 0x47, 0x1e, 0x78, 0xac, 0x01, 0x90, 0x0d, 0x9e, 0x73, 0xed, 0x3d, 0xb7, +0x40, 0x04, 0x9e, 0x58, 0x1e, 0x1e, 0x18, 0x10, 0x0d, 0x8a, 0xef, 0xec, 0x4f, 0xed, 0x61, 0xed, 0x99, 0xed, 0x9e, 0x58, 0x47, 0x1e, 0x78, 0xac, 0x05, 0x90, 0x78, 0xaa, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x02, 0x9e, 0x9d, 0xf7, 0x00, 0x9e, 0x4f, 0xf7, 0x19, 0x38, 0xd7, 0x41, 0xe6, 0xff, 0x5c, 0xca, 0x8f, 0xca, 0xc2, 0xca, 0x19, 0x38, 0xa1, 0x51, 0xba, 0xac, 0x0f, 0x92, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x78, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x32, 0xc8, 0xba, 0xac, 0x71, 0x92, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x67, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x95, 0xac, 0x05, 0x90, 0xd2, 0xd2, +0x80, 0x04, 0x9e, 0x5f, 0xfb, 0x04, 0xbe, 0x5f, 0xfb, 0x04, 0x95, 0xaa, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x52, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0xb9, 0xac, 0xd9, 0x91, 0xfd, 0xac, 0x1a, 0x90, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x40, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x80, 0x62, 0x57, 0x6a, 0x48, 0x63, 0x0e, 0x6b, 0x0c, 0x61, 0x24, 0x60, 0x01, 0x40, 0x19, 0x10, 0x07, 0x38, 0xb0, 0x04, 0x4b, 0x5c, 0x9d, 0x5b, 0x85, 0xac, 0x1f, 0x90, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x24, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x16, 0x62, +0xc0, 0x04, 0xff, 0xa9, 0x48, 0x62, 0x0e, 0x6a, 0x7a, 0x63, 0x02, 0x6b, 0x9e, 0x5c, 0xbb, 0x00, 0x9e, 0x5d, 0xbc, 0x00, 0xa4, 0x05, 0x19, 0x15, 0xa7, 0x38, 0xd1, 0x04, 0x63, 0x5c, 0x83, 0x5d, 0xbb, 0x5a, 0x19, 0x02, 0x19, 0x03, 0x9e, 0x58, 0xc1, 0x1d, 0x06, 0x39, 0x55, 0x00, 0x05, 0x8a, 0x06, 0x39, 0xa5, 0x00, 0x02, 0x8a, 0x42, 0xa9, 0x05, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x7a, 0xeb, 0x34, 0x61, 0x12, 0x69, 0x9e, 0x58, 0xbd, 0x1d, 0x38, 0x48, 0x02, 0x8a, 0x42, 0xa9, 0x0f, 0x9e, 0x78, 0x61, 0x56, 0x69, 0x9e, 0x58, 0xbe, 0x1d, 0x38, 0x48, 0x02, 0x8a, 0x42, 0xa9, 0x07, 0x9e, 0xbc, 0x61, 0x9a, 0x69, 0x9e, 0x58, 0xbf, 0x1d, 0x38, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x1a, 0x38, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0x70, 0x4c, +0x00, 0x05, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x18, 0xec, 0x9e, 0x58, 0xf8, 0x04, 0x19, 0x00, 0xbe, 0x58, 0xf8, 0x04, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x04, 0x88, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x42, 0xa9, 0x98, 0x3f, 0x62, 0x03, 0x9e, 0x5e, 0x50, 0x01, 0x00, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbc, 0x01, 0x01, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbd, 0x01, 0x1f, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbe, 0x01, 0x20, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xbf, 0x01, 0x21, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd5, 0x1a, 0x02, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x51, 0x01, 0xc8, 0x58, 0xc0, 0x06, 0x08, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x52, 0x01, 0x03, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0xb2, 0xc8, +0x40, 0x05, 0x9e, 0x5e, 0xd6, 0x1a, 0x04, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd7, 0x1a, 0x05, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x55, 0x01, 0x06, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x56, 0x01, 0x07, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x57, 0x01, 0x0c, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x58, 0x01, 0x0e, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x59, 0x01, 0x12, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xba, 0x01, 0x09, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd8, 0x1a, 0x0a, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x5b, 0x01, 0x0b, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0xb4, 0x60, 0x01, 0x68, 0x22, 0x61, 0xf8, 0x69, 0xb9, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0xb4, 0x01, 0xc7, 0x38, 0x7d, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x9e, 0x5e, 0x5c, 0x01, 0xf6, 0x5e, +0x80, 0x05, 0x0f, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x5d, 0x01, 0x10, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x5e, 0x60, 0x01, 0x68, 0x28, 0x61, 0xf8, 0x69, 0x63, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x5e, 0x01, 0xc7, 0x38, 0x93, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x9e, 0x5e, 0xbb, 0x01, 0x2e, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x64, 0x60, 0x01, 0x68, 0x2f, 0x61, 0xf8, 0x69, 0x6f, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x64, 0x01, 0xc7, 0x38, 0xa4, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x70, 0x60, 0x01, 0x68, 0x3b, 0x61, 0xf8, 0x69, 0x7b, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0x70, 0x01, 0xc7, 0x38, 0xb0, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x7c, 0x60, 0x01, 0x68, 0x47, 0x61, 0xf8, 0x69, 0x52, 0x66, 0xf8, 0x6e, 0xc2, 0x3e, 0x47, 0xf8, 0xc7, 0x38, 0xbf, 0x05, 0x03, 0x5a, 0x05, 0x5b, 0xfe, 0x5b, 0x43, 0x2a, 0x5d, 0x59, 0xae, 0x6c, +0xc0, 0x05, 0x94, 0x60, 0x01, 0x68, 0x53, 0x61, 0xf8, 0x69, 0x5e, 0x66, 0xf8, 0x6e, 0xc2, 0x3e, 0x53, 0xf8, 0xc7, 0x38, 0xce, 0x05, 0x03, 0x5a, 0x05, 0x5b, 0xfe, 0x5b, 0x43, 0x2a, 0x5d, 0x59, 0xac, 0x60, 0x01, 0x68, 0x13, 0x61, 0xf8, 0x69, 0xb2, 0x66, 0x01, 0x6e, 0xc2, 0x3e, 0xac, 0x01, 0xc7, 0x38, 0xda, 0x05, 0x05, 0x5a, 0x5d, 0x59, 0x3a, 0x38, 0x9e, 0x5e, 0xc3, 0x01, 0xaa, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xc7, 0x01, 0xaf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xc8, 0x01, 0xb0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd9, 0x1a, 0xb1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xca, 0x01, 0xb2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xcd, 0x01, 0xb5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xce, 0x01, 0xb6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0x78, 0x58, +0x00, 0x06, 0xcf, 0x01, 0xb7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd0, 0x01, 0xd8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd1, 0x01, 0xb8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd3, 0x01, 0xba, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd4, 0x01, 0xbb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd5, 0x01, 0xbc, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd6, 0x01, 0xbd, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd7, 0x01, 0xbe, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd8, 0x01, 0xbf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xd9, 0x01, 0xc0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xda, 0x01, 0xc1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdb, 0x01, 0xc2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdc, 0x01, 0xc3, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0xb2, 0x4e, +0x40, 0x06, 0x9e, 0x5e, 0xdd, 0x01, 0xc4, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xde, 0x01, 0xc5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xdf, 0x01, 0xc6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe0, 0x01, 0xc7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe1, 0x01, 0xc8, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe2, 0x01, 0xc9, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe3, 0x01, 0xca, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe4, 0x01, 0xcb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe5, 0x01, 0xcc, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe6, 0x01, 0xcd, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe7, 0x01, 0xce, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe8, 0x01, 0xcf, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xe9, 0x01, 0xd0, 0x60, 0xf8, 0x68, 0xeb, 0x55, +0x80, 0x06, 0xdb, 0x58, 0x9e, 0x5e, 0xea, 0x01, 0xd1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xeb, 0x01, 0xd2, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xec, 0x01, 0xd3, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xed, 0x01, 0xd4, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xee, 0x01, 0xd5, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xef, 0x01, 0xd6, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf0, 0x01, 0xd7, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf1, 0x01, 0xea, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf2, 0x01, 0xeb, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf3, 0x01, 0xec, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf4, 0x01, 0xed, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf5, 0x01, 0xee, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf6, 0x01, 0xef, 0x60, 0xcc, 0x47, +0xc0, 0x06, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf7, 0x01, 0xf0, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x9e, 0x5e, 0xf8, 0x01, 0xf1, 0x60, 0xf8, 0x68, 0xdb, 0x58, 0x3a, 0x38, 0x00, 0xbc, 0xb1, 0x00, 0x18, 0xaa, 0x10, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0x60, 0x80, 0xb0, 0x00, 0x60, 0x81, 0xb0, 0x00, 0x60, 0x82, 0xb0, 0x00, 0x60, 0x83, 0xb0, 0x00, 0x60, 0x9c, 0xb0, 0xc0, 0x60, 0x13, 0x68, 0x9d, 0xb0, 0x00, 0x60, 0xcf, 0xb0, 0x3a, 0x38, 0x41, 0xab, 0x51, 0xb0, 0x78, 0xa8, 0x70, 0xa8, 0x68, 0xaa, 0x60, 0xaa, 0xd1, 0xb0, 0x3a, 0x38, 0x00, 0x60, 0x1f, 0x68, 0x00, 0x61, 0x00, 0x62, 0x17, 0x38, 0x5d, 0x59, 0x3a, 0x38, 0x3e, 0xb0, 0x08, 0xaa, 0x00, 0xaa, 0x18, 0xaa, 0x10, 0xaa, 0xbe, 0xb0, 0x10, 0x60, 0x9e, 0xb0, 0x30, 0xb0, 0x38, 0xa8, 0xb0, 0xb0, 0x3e, 0xb0, 0x38, 0xaa, 0xbe, 0xb0, 0x64, 0x58, +0x00, 0x07, 0x84, 0xb0, 0x3c, 0xa9, 0x3e, 0xb0, 0x78, 0xaa, 0xbe, 0xb0, 0x00, 0x60, 0x00, 0xbd, 0xaa, 0x00, 0x30, 0xb0, 0x08, 0xaa, 0x18, 0xaa, 0x00, 0xbd, 0x30, 0x00, 0x36, 0xb0, 0x08, 0xaa, 0x18, 0xaa, 0x00, 0xbd, 0x36, 0x00, 0x33, 0xb0, 0x08, 0xa8, 0x18, 0xa8, 0x00, 0xbd, 0x33, 0x00, 0x3a, 0x38, 0x04, 0x60, 0x69, 0x78, 0x55, 0x60, 0x6a, 0x78, 0x6b, 0x78, 0x6c, 0x78, 0x6d, 0x78, 0x82, 0xac, 0x28, 0x92, 0x00, 0x60, 0x88, 0x68, 0xae, 0xb0, 0x20, 0x60, 0xc4, 0x68, 0xd0, 0xb0, 0x1e, 0x59, 0x1e, 0x5a, 0x93, 0x60, 0x2f, 0x68, 0x09, 0x58, 0x04, 0x39, 0xff, 0x00, 0x04, 0x3a, 0x00, 0xff, 0xfe, 0x5a, 0x22, 0x32, 0xff, 0x61, 0x04, 0x38, 0xff, 0x00, 0x3a, 0x48, 0x01, 0x8a, 0x10, 0x60, 0xd2, 0xb0, 0x3e, 0x5a, 0x3e, 0x59, 0x00, 0x60, 0x5d, 0x78, 0x19, 0x38, 0x8c, 0x50, 0x92, 0xaa, 0x0b, 0x60, +0x40, 0x07, 0xaa, 0xac, 0x01, 0x90, 0x92, 0xa8, 0xaa, 0xaa, 0xf9, 0xab, 0xf1, 0xab, 0xfd, 0xa9, 0xf5, 0xa9, 0x01, 0x9e, 0x1a, 0x38, 0xaa, 0xac, 0x04, 0x92, 0xa2, 0xa8, 0x90, 0xc7, 0x82, 0xac, 0x00, 0x90, 0x3a, 0x38, 0x90, 0xaa, 0xa2, 0xaa, 0x81, 0xaa, 0xb9, 0xaa, 0xba, 0xa8, 0xb0, 0xa8, 0xb8, 0xaa, 0x02, 0x60, 0xbe, 0x58, 0x12, 0x00, 0x01, 0x60, 0xbe, 0x58, 0x11, 0x00, 0x01, 0x60, 0xbe, 0x58, 0xfb, 0x1c, 0xff, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x00, 0xbe, 0x58, 0xc6, 0x00, 0x00, 0x60, 0xbe, 0x58, 0xa3, 0x1c, 0xbe, 0x58, 0xa4, 0x1c, 0xbe, 0x58, 0xa5, 0x1c, 0xbe, 0x58, 0xfc, 0x1c, 0xbe, 0x58, 0xfd, 0x1c, 0xe6, 0xa8, 0x88, 0xb0, 0x89, 0xb0, 0x78, 0xa9, 0x3a, 0x38, 0x30, 0x60, 0x80, 0x68, 0xcf, 0xb0, 0xcd, 0xa9, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0x00, 0x60, 0xbe, 0x58, 0xba, 0x14, +0x80, 0x07, 0xaf, 0x00, 0xbe, 0x58, 0xc2, 0x1d, 0xbe, 0x58, 0xc3, 0x1d, 0xbe, 0x58, 0xc4, 0x1d, 0x3a, 0x38, 0x36, 0x60, 0x80, 0x68, 0x8f, 0xb0, 0xdd, 0xa9, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x3a, 0x38, 0x39, 0xb0, 0x38, 0xaa, 0xb9, 0xb0, 0x30, 0xb0, 0x38, 0xa8, 0xb0, 0xb0, 0x3c, 0xab, 0x3a, 0x38, 0x3c, 0xa9, 0x3a, 0x38, 0x02, 0x3f, 0x01, 0x00, 0x0c, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xa7, 0x07, 0xa5, 0x59, 0x3d, 0x5e, 0x22, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1f, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xb7, 0x07, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x10, 0x88, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0x22, 0x00, 0x9e, 0x5f, 0xdc, 0x4b, +0xc0, 0x07, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xc9, 0x07, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0x02, 0x3f, 0x01, 0x00, 0x0a, 0x98, 0x29, 0x66, 0x03, 0x6e, 0xb5, 0x65, 0x02, 0x6d, 0x39, 0x67, 0xe7, 0x38, 0xd7, 0x07, 0xa5, 0x59, 0x3d, 0x5e, 0x1e, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1b, 0x98, 0x29, 0x66, 0x03, 0x6e, 0xb5, 0x65, 0x02, 0x6d, 0x39, 0x67, 0xe7, 0x38, 0xe5, 0x07, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x0e, 0x88, 0x29, 0x66, 0x03, 0x6e, 0x9e, 0x5d, 0x22, 0x00, 0x39, 0x67, 0xe7, 0x38, 0xf5, 0x07, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0xaf, 0x61, 0x1a, 0x69, 0x19, 0x01, 0x00, 0x60, 0x2f, 0x68, 0x93, 0x62, 0x57, 0x38, 0x0f, 0x59, 0x1b, 0xed, +0x00, 0x08, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x08, 0x60, 0x1e, 0x58, 0xbc, 0xea, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0xbc, 0xea, 0x3e, 0x58, 0x19, 0x00, 0x9a, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0x08, 0x60, 0x1e, 0x58, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x10, 0xfb, 0x89, 0x00, 0x60, 0x1e, 0x58, 0x78, 0xa9, 0x0c, 0xf1, 0x3e, 0x58, 0x19, 0x00, 0xcc, 0xc7, 0x18, 0x10, 0xf8, 0x89, 0xe5, 0xa8, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0xa2, 0x72, 0x07, 0x61, 0x22, 0x23, 0x03, 0x61, 0x23, 0x32, 0x0a, 0x8a, 0x1e, 0x49, +0x40, 0x08, 0x04, 0x61, 0x23, 0x32, 0x0e, 0x8a, 0x00, 0x61, 0x23, 0x32, 0x24, 0x8a, 0x02, 0x61, 0x23, 0x32, 0x2a, 0x8a, 0x2f, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0xb5, 0x66, 0x02, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x28, 0x9e, 0x48, 0x63, 0x0e, 0x6b, 0x48, 0x66, 0x1d, 0x6e, 0x9e, 0x59, 0xbe, 0x00, 0x00, 0x64, 0x3c, 0x48, 0x0d, 0x8a, 0xfa, 0x06, 0x48, 0x67, 0x1d, 0x6f, 0xfa, 0x07, 0x19, 0x11, 0x27, 0x38, 0x64, 0x08, 0xe3, 0x59, 0x3b, 0x5e, 0x19, 0x07, 0x19, 0x06, 0x48, 0x66, 0x1d, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x0f, 0x9e, 0x16, 0xca, 0x48, 0x63, 0x0e, 0x6b, 0x2a, 0xc9, 0x7a, 0x66, 0x02, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x06, 0x9e, 0x30, 0x63, 0x0b, 0x6b, 0x29, 0x66, 0x03, 0x6e, 0xbe, 0x5e, 0x28, 0x1d, 0x60, 0x62, 0x11, 0x6a, 0xc0, 0x61, 0x03, 0x69, 0x24, 0x64, 0x16, 0x65, 0x9e, 0x58, 0xe3, 0x8e, +0x80, 0x08, 0x28, 0x1d, 0x05, 0x00, 0x19, 0x05, 0x00, 0x66, 0x00, 0x67, 0xbe, 0x5f, 0x29, 0x1d, 0x27, 0x38, 0xcb, 0x08, 0x19, 0x06, 0xbe, 0x48, 0x09, 0x8a, 0x1e, 0x58, 0x9e, 0x58, 0x29, 0x1d, 0x00, 0xac, 0x02, 0x92, 0x65, 0x58, 0x1d, 0x5a, 0x3e, 0x58, 0x36, 0x9e, 0x05, 0x5e, 0xdd, 0x5a, 0x00, 0x66, 0x19, 0x07, 0xfc, 0x48, 0x01, 0x8a, 0x2f, 0x9e, 0x13, 0xb8, 0x14, 0xb8, 0x15, 0xb8, 0x1e, 0x5e, 0x9e, 0x58, 0x28, 0x1d, 0x9e, 0x5c, 0xb8, 0x00, 0x87, 0x38, 0xa7, 0x08, 0x05, 0x5e, 0xdd, 0x5a, 0x3e, 0x5e, 0x95, 0xb8, 0x94, 0xb8, 0x93, 0xb8, 0x19, 0x12, 0x01, 0x76, 0xdd, 0x5a, 0x9e, 0x58, 0x28, 0x1d, 0xfa, 0x00, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0x05, 0x5e, 0xdd, 0x5a, 0xe8, 0x1d, +0xc0, 0x08, 0x9e, 0x5e, 0xe3, 0x19, 0xdd, 0x5a, 0xbb, 0x66, 0xdd, 0x5a, 0xbb, 0x66, 0xdd, 0x5a, 0xff, 0x66, 0xbe, 0x5e, 0x29, 0x1d, 0x1a, 0x38, 0x1a, 0x38, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x67, 0x03, 0x6f, 0xbe, 0x5f, 0xdb, 0x00, 0x7f, 0x67, 0xbe, 0x5f, 0xde, 0x00, 0x00, 0x67, 0xbe, 0x5f, 0xe1, 0x00, 0x40, 0x67, 0xbe, 0x5f, 0xe0, 0x00, 0x3a, 0x38, 0xad, 0xac, 0x0d, 0x90, 0x04, 0x60, 0x69, 0x78, 0x66, 0x60, 0x6a, 0x78, 0x6b, 0x78, 0x6c, 0x78, 0x6d, 0x78, 0xb2, 0xa8, 0x3c, 0xab, 0xad, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xc2, 0x1d, 0x3a, 0x38, 0x02, 0x60, 0x72, 0x68, 0x05, 0xec, 0xff, 0xc8, 0x19, 0x38, 0xd9, 0x54, 0x02, 0xc9, 0xf2, 0x60, 0x72, 0x68, 0x05, 0xec, 0xa5, 0xaa, 0x3a, 0x38, 0x1e, 0x5c, 0x62, 0xbb, +0x00, 0x09, 0x04, 0xaa, 0x02, 0x9e, 0x1e, 0x5c, 0x04, 0xa8, 0x46, 0x62, 0x31, 0x6a, 0x40, 0xbd, 0xbd, 0x00, 0x02, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x00, 0x61, 0x10, 0x69, 0x07, 0x60, 0xc0, 0x68, 0x3f, 0x38, 0x0f, 0x59, 0x00, 0x61, 0x10, 0x69, 0x23, 0x5a, 0x32, 0xa8, 0x04, 0xac, 0x01, 0x92, 0x32, 0xaa, 0x5b, 0x59, 0x01, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x07, 0x60, 0xc0, 0x68, 0x3f, 0x38, 0x7a, 0x38, 0x02, 0x62, 0x40, 0xbd, 0xbe, 0x00, 0x00, 0x62, 0x40, 0xbd, 0xbd, 0x00, 0x40, 0xbd, 0xbe, 0x00, 0x3e, 0x5c, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0xe6, 0xac, 0x05, 0x92, 0xe0, 0x61, 0x1a, 0x69, 0x00, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x40, 0x61, 0x57, 0x69, 0x60, 0x62, 0x57, 0x6a, 0x90, 0x63, 0x5e, 0x6b, 0xb6, 0x64, 0x90, 0x39, +0x40, 0x09, 0x5e, 0x6c, 0x39, 0x65, 0x00, 0x66, 0x00, 0x67, 0xa7, 0x38, 0x0c, 0x0a, 0x15, 0x65, 0xfd, 0x48, 0x21, 0x9c, 0xe6, 0xac, 0x05, 0x92, 0xec, 0x61, 0x1a, 0x69, 0x0c, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x4c, 0x61, 0x57, 0x69, 0x6c, 0x62, 0x57, 0x6a, 0x16, 0x65, 0xa0, 0x38, 0x7a, 0x02, 0x5e, 0x17, 0x07, 0x00, 0x5e, 0x07, 0x6b, 0x5d, 0xbe, 0x5d, 0x2e, 0x1d, 0x48, 0x66, 0xbe, 0x48, 0xac, 0x8a, 0x09, 0x66, 0xbe, 0x48, 0x1b, 0x9c, 0x13, 0x66, 0xbe, 0x48, 0x35, 0x9c, 0x1d, 0x66, 0xbe, 0x48, 0x15, 0x9c, 0x31, 0x9e, 0x7a, 0x60, 0x02, 0x68, 0x8b, 0x5d, 0xbe, 0x5d, 0x2e, 0x1d, 0x48, 0x66, 0xdd, 0x48, 0x77, 0x8a, 0x05, 0x66, 0xfe, 0x48, 0x4b, 0x9c, 0x0b, 0x66, 0xfe, 0x48, 0x5d, 0x9c, 0x11, 0x66, 0xfe, 0x48, 0x45, 0x9c, 0x15, 0x66, 0xfe, 0x48, 0x57, 0x9c, 0x9e, 0x5d, 0x2e, 0x1d, 0x11, 0x13, +0x80, 0x09, 0x0a, 0x66, 0xbe, 0x48, 0x01, 0x96, 0xa6, 0x15, 0x25, 0x01, 0x45, 0x02, 0xff, 0x65, 0xe6, 0xac, 0x02, 0x92, 0x35, 0x26, 0x04, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x3e, 0x58, 0xfe, 0x5e, 0xe6, 0xac, 0x02, 0x92, 0x55, 0x25, 0x04, 0x9e, 0x1e, 0x58, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xc5, 0x2e, 0xdb, 0x58, 0x71, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xec, 0x61, 0x1a, 0x69, 0x0c, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x4c, 0x61, 0x57, 0x69, 0x6c, 0x62, 0x57, 0x6a, 0x9e, 0x5d, 0x2e, 0x1d, 0x0a, 0x66, 0xa6, 0x15, 0xbe, 0x48, 0x01, 0x96, 0xa6, 0x15, 0x25, 0x01, 0x45, 0x02, 0x00, 0x65, 0xff, 0x6d, 0xe6, 0xac, 0x03, 0x92, 0x35, 0x26, 0x55, 0x25, 0x06, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xfe, 0x5d, 0xc5, 0x2e, 0xdb, 0x58, 0x4c, 0x9e, 0x04, 0xd9, +0xc0, 0x09, 0xff, 0x65, 0xe6, 0xac, 0x04, 0x92, 0x35, 0x26, 0xfe, 0x5e, 0x55, 0x25, 0x07, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0xfe, 0x5e, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xc5, 0x2e, 0x9e, 0x5d, 0x2e, 0x1d, 0x05, 0x00, 0xdb, 0x58, 0x05, 0x10, 0x14, 0x9e, 0x00, 0x65, 0xff, 0x6d, 0xe6, 0xac, 0x03, 0x92, 0x35, 0x26, 0x55, 0x25, 0x06, 0x9e, 0x1e, 0x58, 0x29, 0x58, 0x05, 0x26, 0x49, 0x58, 0x05, 0x25, 0x3e, 0x58, 0xfe, 0x5d, 0xc5, 0x2e, 0x9e, 0x5d, 0x2e, 0x1d, 0x05, 0x00, 0xdb, 0x58, 0x05, 0x10, 0x05, 0x66, 0xdf, 0x48, 0x09, 0x8a, 0x0b, 0x66, 0xdf, 0x48, 0x12, 0x8a, 0x11, 0x66, 0xdf, 0x48, 0x0f, 0x8a, 0x19, 0x01, 0x19, 0x02, 0x17, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xe0, 0x61, 0x1a, 0x69, 0x00, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x40, 0x61, 0x57, 0x69, 0x60, 0x62, 0x57, 0x6a, 0xdf, 0x21, +0x00, 0x0a, 0x0b, 0x9e, 0xe6, 0xac, 0x05, 0x92, 0xe6, 0x61, 0x1a, 0x69, 0x06, 0x62, 0x1b, 0x6a, 0x04, 0x9e, 0x46, 0x61, 0x57, 0x69, 0x66, 0x62, 0x57, 0x6a, 0x19, 0x07, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x90, 0x60, 0x5e, 0x68, 0x48, 0x64, 0x0e, 0x6c, 0x00, 0x65, 0x00, 0x66, 0x00, 0x67, 0xff, 0x63, 0xff, 0x6b, 0x6f, 0x3c, 0x5a, 0x0a, 0x09, 0x5a, 0x48, 0x65, 0x5d, 0x48, 0x34, 0x8a, 0x1e, 0x58, 0x19, 0x03, 0x0c, 0x65, 0x65, 0x40, 0xe6, 0xac, 0x03, 0x92, 0x00, 0x61, 0x05, 0x69, 0x02, 0x9e, 0x80, 0x61, 0x57, 0x69, 0x20, 0x01, 0xb6, 0x62, 0x5e, 0x6a, 0x13, 0xb8, 0x14, 0xb8, 0x15, 0xb8, 0x6f, 0x39, 0x52, 0x0a, 0xe6, 0xac, 0x02, 0x92, 0x23, 0x5e, 0x01, 0x9e, 0x29, 0x5e, 0xc4, 0x3f, 0x00, 0xff, 0xfe, 0x5f, 0x3c, 0x29, +0x40, 0x0a, 0xc4, 0x3e, 0xff, 0x00, 0x49, 0x5d, 0x48, 0x60, 0x1d, 0x48, 0x03, 0x8a, 0x85, 0x04, 0xdb, 0x5c, 0x85, 0x14, 0x19, 0x02, 0x49, 0x5d, 0x48, 0x60, 0x1d, 0x48, 0x03, 0x8a, 0x85, 0x04, 0xfb, 0x5c, 0x85, 0x14, 0x19, 0x02, 0x19, 0x01, 0x95, 0xb8, 0x94, 0xb8, 0x93, 0xb8, 0x16, 0x65, 0x85, 0x04, 0x3e, 0x58, 0x1a, 0x38, 0x19, 0x00, 0x3a, 0x38, 0x9e, 0x59, 0xf1, 0x1e, 0x1c, 0x11, 0x1e, 0x98, 0x9e, 0x59, 0xf2, 0x1e, 0x22, 0x39, 0x88, 0x00, 0x11, 0x8a, 0x9e, 0x59, 0x58, 0x1a, 0x1a, 0x11, 0x01, 0x94, 0x14, 0x9e, 0x88, 0x61, 0xbe, 0x59, 0xf2, 0x1e, 0x8d, 0x61, 0x9e, 0x58, 0xef, 0x1e, 0x1b, 0x59, 0x97, 0x61, 0x9e, 0x58, 0xee, 0x1e, 0x1b, 0x59, 0x18, 0x9e, 0x9e, 0x59, 0x58, 0x1a, 0x19, 0x11, 0xf0, 0x95, 0x9e, 0x59, 0xf1, 0x1e, 0x1c, 0x11, 0x00, 0x98, 0x00, 0x61, 0xbe, 0x59, 0x00, 0xa0, +0x80, 0x0a, 0xf2, 0x1e, 0x9e, 0x59, 0xf0, 0x1e, 0x22, 0x39, 0x66, 0x00, 0x08, 0x88, 0x8d, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xef, 0x1e, 0x97, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xee, 0x1e, 0x3a, 0x38, 0x9e, 0x59, 0xf3, 0x1e, 0x1c, 0x11, 0x1e, 0x98, 0x9e, 0x59, 0xf7, 0x1e, 0x22, 0x39, 0x88, 0x00, 0x11, 0x8a, 0x9e, 0x59, 0x58, 0x1a, 0x1b, 0x11, 0x01, 0x94, 0x14, 0x9e, 0x88, 0x61, 0xbe, 0x59, 0xf7, 0x1e, 0x8e, 0x61, 0x9e, 0x58, 0xf5, 0x1e, 0x1b, 0x59, 0x98, 0x61, 0x9e, 0x58, 0xf6, 0x1e, 0x1b, 0x59, 0x18, 0x9e, 0x9e, 0x59, 0x58, 0x1a, 0x1a, 0x11, 0xf0, 0x95, 0x9e, 0x59, 0xf3, 0x1e, 0x1c, 0x11, 0x00, 0x98, 0x00, 0x61, 0xbe, 0x59, 0xf7, 0x1e, 0x9e, 0x59, 0xf4, 0x1e, 0x22, 0x39, 0x66, 0x00, 0x08, 0x88, 0x8e, 0x61, 0x23, 0x58, 0xbe, 0x58, 0xf5, 0x1e, 0x98, 0x61, 0x23, 0x58, 0xbe, 0x58, 0x07, 0x85, +0xc0, 0x0a, 0xf6, 0x1e, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x9e, 0x58, 0xea, 0x04, 0x18, 0x10, 0x0a, 0x88, 0x00, 0x60, 0x01, 0x61, 0x1f, 0x69, 0x06, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xd5, 0x0a, 0x1d, 0x59, 0x1d, 0x5a, 0x1a, 0x38, 0x9e, 0x58, 0x00, 0x1f, 0x19, 0x10, 0x23, 0x8a, 0x00, 0x64, 0x7f, 0x6c, 0x8d, 0x61, 0x01, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xeb, 0x0a, 0x23, 0x58, 0x04, 0x15, 0x06, 0x8a, 0x43, 0x5b, 0x18, 0x13, 0x01, 0x88, 0x1b, 0x5a, 0x43, 0x58, 0x1b, 0x59, 0x19, 0x01, 0x19, 0x02, 0x30, 0x64, 0x97, 0x61, 0x06, 0x62, 0x1f, 0x6a, 0x8f, 0x38, 0xfc, 0x0a, 0x23, 0x58, 0x04, 0x15, 0x06, 0x8a, 0x43, 0x5b, 0x18, 0x13, 0x01, 0x88, 0x1b, 0x5a, 0x43, 0x58, 0x1b, 0x59, 0x19, 0x01, 0x19, 0x02, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x64, 0xd2, +0x00, 0x0b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x0e, 0x00, 0x0c, 0x00, 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x06, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0xff, 0x01, 0xff, 0x00, 0x7f, 0x00, 0x3f, 0x00, 0x1f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x05, 0x00, 0x05, 0x00, 0x05, 0x00, 0x96, 0x54, +0x40, 0x0b, 0x05, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x9e, 0x58, 0xe7, 0x00, 0x19, 0x10, 0x01, 0x98, 0xfd, 0x38, 0x6c, 0xcb, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x01, 0x60, 0xbe, 0x58, 0xea, 0x00, 0xbe, 0x58, 0xe7, 0x00, 0xed, 0x9f, 0x9e, 0x58, 0xe7, 0x00, 0x19, 0x10, 0x01, 0x98, 0xfd, 0x38, 0x99, 0xcc, 0x01, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0xf6, 0x9f, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0x98, 0x3a, 0x74, 0x0c, 0xfb, 0xcd, 0x02, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x7d, 0xe4, 0xc7, 0xdd, 0x8a, 0xde, 0xa1, 0xdd, 0xac, 0xe5, 0xa1, 0xcc, 0xd4, 0xdb, 0x4a, 0xee, 0xb7, 0xcc, 0x6e, 0xfd, +0x80, 0x0b, 0xd4, 0xcc, 0x48, 0x66, 0x0e, 0x6e, 0xa4, 0xed, 0xf8, 0xcc, 0xd2, 0xde, 0x7f, 0xe2, 0x80, 0x60, 0xbe, 0x58, 0xfd, 0x1e, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1a, 0x10, 0x13, 0x88, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x00, 0x01, 0x08, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x01, 0x00, 0x02, 0x39, 0x00, 0x02, 0x8a, 0x80, 0x88, 0x60, 0xbe, 0x58, 0xfd, 0x1e, 0xa8, 0xe8, 0x2e, 0xe9, 0x84, 0x9e, 0x1a, 0x38, 0x9e, 0x58, 0xe9, 0x1e, 0x18, 0x10, 0x01, 0x8a, 0x7e, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x1b, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x9e, 0x58, 0xcd, 0x04, 0xfc, 0x10, 0x1b, 0x98, 0x06, 0x70, 0x50, 0xac, 0x18, 0x92, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x00, 0x01, 0x0a, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x02, 0x38, 0x40, 0x01, 0x4d, 0x4c, +0xc0, 0x0b, 0x0e, 0x80, 0x9e, 0x58, 0x4f, 0x04, 0x02, 0x38, 0x40, 0x01, 0x09, 0x80, 0xeb, 0xe5, 0x9e, 0x58, 0x20, 0x1d, 0x18, 0x10, 0x04, 0x8a, 0x05, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x59, 0x9e, 0x1a, 0x38, 0x06, 0x70, 0x08, 0xac, 0x38, 0x92, 0x00, 0xac, 0x36, 0x92, 0x50, 0xac, 0x34, 0x92, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x04, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1a, 0x10, 0x2a, 0x8a, 0x9e, 0x58, 0xf1, 0x04, 0x1a, 0x10, 0x01, 0x8a, 0x04, 0x9e, 0x9e, 0x58, 0xf2, 0x04, 0x1a, 0x10, 0x21, 0x8a, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1b, 0x10, 0x14, 0x9a, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x60, 0x00, 0x15, 0x80, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1b, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xf1, 0x1e, 0x9e, 0x59, 0x10, 0xe2, +0x00, 0x0c, 0xf3, 0x1e, 0x01, 0x00, 0x08, 0x58, 0x1d, 0x10, 0x06, 0x98, 0x1f, 0xdf, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x1d, 0x8a, 0x9e, 0x58, 0x8a, 0x04, 0x1f, 0x10, 0x07, 0x80, 0x9e, 0x58, 0x8b, 0x04, 0x1f, 0x10, 0x03, 0x80, 0x05, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x9e, 0x58, 0x36, 0x1d, 0x1a, 0x10, 0x08, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1c, 0x10, 0x03, 0x8a, 0x98, 0xe2, 0x98, 0xe2, 0x01, 0x9e, 0x98, 0xe2, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x80, 0x01, 0x01, 0x80, 0x69, 0xe2, 0xcb, 0xce, 0x1f, 0xcd, 0x9e, 0xce, 0xb0, 0xce, 0x2a, 0xcf, 0x72, 0xdc, 0x17, 0xd2, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x0a, 0x8a, 0x9e, 0x58, 0xb1, 0x04, 0x19, 0x10, 0x06, 0x8a, 0x9e, 0x58, 0xb8, 0x04, 0x18, 0x10, 0x02, 0x88, 0x2c, 0xe4, 0xc3, 0xe1, 0xc1, 0xf8, 0x8a, 0xf8, 0x7f, 0x91, +0x40, 0x0c, 0x56, 0xd0, 0x19, 0x38, 0x92, 0x4a, 0x9e, 0x58, 0x43, 0x04, 0x01, 0x61, 0x19, 0x48, 0x0c, 0x8a, 0x9e, 0x58, 0x20, 0x1d, 0x18, 0x10, 0x08, 0x88, 0x19, 0x38, 0xc6, 0x4a, 0x19, 0x38, 0xc5, 0x48, 0x19, 0x38, 0x94, 0x49, 0x19, 0x38, 0xd6, 0x4a, 0x03, 0xda, 0x4d, 0xda, 0xf6, 0xed, 0x6b, 0xd3, 0xe1, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0x9e, 0x58, 0x58, 0x1a, 0x19, 0x10, 0x12, 0x88, 0x9e, 0x58, 0x8a, 0x04, 0x9e, 0x59, 0x8b, 0x04, 0x01, 0x00, 0x02, 0x39, 0x05, 0x00, 0x0a, 0x98, 0xaa, 0x61, 0x15, 0x69, 0x23, 0x58, 0x02, 0x39, 0x0d, 0x00, 0x04, 0x80, 0xaa, 0x61, 0x15, 0x69, 0x0d, 0x60, 0x1b, 0x59, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0xfb, 0xcd, 0xa1, 0xcc, 0xd4, 0xdb, 0xc8, 0xcc, 0xd4, 0xcc, 0xf8, 0xcc, 0x7f, 0xe2, 0xcb, 0xce, 0x1f, 0xcd, 0x9e, 0xce, 0xb0, 0xce, 0x2a, 0xcf, 0x3f, 0xb2, +0x80, 0x0c, 0x17, 0xd2, 0x56, 0xd0, 0x03, 0xda, 0x4d, 0xda, 0x6b, 0xd3, 0xe1, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0xfb, 0xcd, 0xa1, 0xcc, 0xd4, 0xcc, 0xf8, 0xcc, 0x7a, 0xce, 0xcb, 0xce, 0x1f, 0xcd, 0x9e, 0xce, 0xb0, 0xce, 0x2a, 0xcf, 0x17, 0xd2, 0x56, 0xd0, 0x03, 0xda, 0x3a, 0x38, 0x4d, 0xda, 0x6b, 0xd3, 0xe1, 0xd3, 0xec, 0xd6, 0x8a, 0xda, 0xbf, 0xdc, 0x7a, 0xdd, 0x3a, 0x38, 0x30, 0x67, 0x0b, 0x6f, 0x9e, 0x5e, 0xe9, 0x00, 0x48, 0x65, 0x0e, 0x6d, 0x9e, 0x5c, 0xda, 0x00, 0x19, 0x14, 0x87, 0x38, 0xb5, 0x0c, 0xc5, 0x5c, 0xf4, 0x14, 0x7c, 0xac, 0x04, 0x92, 0x00, 0x61, 0x02, 0x62, 0x82, 0x40, 0x01, 0x5c, 0x9d, 0x5d, 0x19, 0x07, 0x3a, 0x38, 0x30, 0x60, 0x1c, 0x78, 0x06, 0x70, 0x50, 0xac, 0x08, 0x92, 0x08, 0xac, 0x04, 0x92, 0x00, 0xac, 0x02, 0x92, 0x2d, 0x02, +0xc0, 0x0c, 0x10, 0x60, 0x03, 0x9e, 0x30, 0x60, 0x01, 0x9e, 0x68, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x30, 0x60, 0x1c, 0x78, 0x30, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x40, 0x60, 0x1c, 0x78, 0x30, 0x60, 0x25, 0x78, 0x26, 0x78, 0x3a, 0x38, 0x48, 0x67, 0x0e, 0x6f, 0x9e, 0x5d, 0xfd, 0x1b, 0x19, 0x15, 0x9e, 0x5e, 0xfe, 0x1b, 0xff, 0x64, 0x7f, 0x6c, 0xa7, 0x38, 0xe2, 0x0c, 0x9f, 0x49, 0x01, 0x9a, 0xe3, 0x5c, 0x19, 0x07, 0x18, 0x14, 0x01, 0x94, 0x00, 0x64, 0x90, 0x3c, 0x26, 0x00, 0x90, 0x3c, 0x05, 0x1c, 0xf2, 0x3f, 0xfd, 0x1b, 0x00, 0x62, 0xa7, 0x38, 0xf4, 0x0c, 0xf2, 0x13, 0x03, 0x96, 0xf4, 0x13, 0x01, 0x94, 0x00, 0x63, 0x7d, 0x5f, 0x19, 0x16, 0xe4, 0x89, 0x3a, 0x38, 0x48, 0x67, 0x0e, 0x6f, 0x9e, 0x5d, 0xfd, 0x1b, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0xff, 0x64, 0x7d, 0x69, +0x00, 0x0d, 0x7f, 0x6c, 0xc7, 0x38, 0x08, 0x0d, 0x9f, 0x49, 0x01, 0x9a, 0xe3, 0x5c, 0xf0, 0x3f, 0xfd, 0x1b, 0x1a, 0x38, 0x18, 0x14, 0x01, 0x94, 0x00, 0x64, 0x90, 0x3c, 0x25, 0x00, 0x90, 0x3c, 0x05, 0x1c, 0x00, 0x62, 0xc7, 0x38, 0x1a, 0x0d, 0xf2, 0x3f, 0xfd, 0x1b, 0xf2, 0x13, 0x03, 0x96, 0xf4, 0x13, 0x01, 0x94, 0x00, 0x63, 0x7b, 0x5f, 0x19, 0x07, 0x19, 0x15, 0xe1, 0x89, 0x3a, 0x38, 0x05, 0x71, 0x49, 0xaa, 0x05, 0x79, 0x00, 0x66, 0x60, 0x65, 0x11, 0x6d, 0x48, 0x64, 0x0e, 0x6c, 0x9e, 0x5b, 0xfd, 0x1b, 0x1a, 0x05, 0xa3, 0x05, 0x00, 0x67, 0x9e, 0x58, 0xfd, 0x1b, 0x19, 0x10, 0x07, 0x38, 0xbb, 0x0d, 0x1d, 0x70, 0x1c, 0x49, 0x85, 0x94, 0x05, 0x71, 0x49, 0xa8, 0x05, 0x79, 0x00, 0x60, 0xa2, 0x3b, 0x01, 0x00, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x29, 0x88, 0xb2, 0x3b, 0xd3, 0x97, +0x40, 0x0d, 0xfd, 0x1b, 0x19, 0x13, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x21, 0x88, 0xa3, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x6d, 0x88, 0x9e, 0x5b, 0xf0, 0x04, 0x4b, 0x62, 0x1a, 0x6a, 0x7a, 0x49, 0x06, 0x98, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x08, 0x9e, 0x43, 0x5b, 0x19, 0x03, 0x7b, 0x5a, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x19, 0x13, 0x60, 0x3a, 0xaa, 0x15, 0x43, 0x59, 0x19, 0x01, 0x3b, 0x5a, 0xdf, 0xce, 0x51, 0x9e, 0xa3, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x4c, 0x88, 0xa2, 0x3b, 0x01, 0x00, 0xb2, 0x3a, 0xfd, 0x1b, 0x19, 0x12, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x1f, 0x8a, 0x43, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x1a, 0x8a, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x43, 0x58, 0x9e, 0xe0, +0x80, 0x0d, 0x04, 0x38, 0xff, 0x00, 0x38, 0x48, 0x12, 0x8a, 0x20, 0x39, 0xbd, 0x15, 0x43, 0x58, 0x00, 0x38, 0xbd, 0x15, 0x03, 0x58, 0x19, 0x49, 0x01, 0x94, 0x1b, 0x59, 0x00, 0x39, 0xbd, 0x15, 0x63, 0x58, 0x00, 0x38, 0xbd, 0x15, 0x03, 0x58, 0x19, 0x49, 0x01, 0x94, 0x1b, 0x59, 0x00, 0x60, 0x43, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x09, 0x8a, 0x43, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x0d, 0x9e, 0x63, 0x59, 0x24, 0x39, 0xff, 0x00, 0x19, 0x48, 0x08, 0x8a, 0x63, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0xa3, 0x59, 0x24, 0x39, 0x00, 0x80, 0x23, 0x29, 0x3b, 0x5d, 0x19, 0x13, 0x60, 0x3a, 0xaa, 0x15, 0x43, 0x59, 0x19, 0x01, 0x3b, 0x5a, 0xec, 0xce, 0x19, 0x04, 0x19, 0x05, 0x19, 0x07, 0x19, 0x05, 0x19, 0x06, 0x9e, 0x5a, 0xfe, 0x1b, 0xa8, 0xc2, +0xc0, 0x0d, 0x5e, 0x48, 0x69, 0x99, 0x3a, 0x38, 0xe8, 0x67, 0x03, 0x6f, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x5c, 0x58, 0x1a, 0x82, 0x39, 0x00, 0x00, 0x20, 0x8a, 0x00, 0x67, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x5a, 0xfd, 0x1b, 0x72, 0x65, 0x19, 0x6d, 0x86, 0x66, 0x19, 0x6e, 0x19, 0x14, 0xff, 0x61, 0x7f, 0x69, 0x00, 0x63, 0x87, 0x38, 0xe5, 0x0d, 0xa5, 0x58, 0x46, 0x4a, 0x00, 0x38, 0x48, 0x0e, 0x38, 0x49, 0x01, 0x9a, 0x03, 0x59, 0x78, 0x49, 0x01, 0x94, 0x03, 0x5b, 0x17, 0x07, 0x19, 0x04, 0xe1, 0x58, 0x00, 0x61, 0x1c, 0x5c, 0xbe, 0x58, 0x54, 0x1a, 0x3a, 0x38, 0x9e, 0x58, 0xe3, 0x19, 0x00, 0x67, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0xf7, 0x0d, 0x04, 0x39, 0x01, 0x00, 0xe1, 0x07, 0x08, 0x58, 0xbe, 0x5f, 0xea, 0x04, 0x3a, 0x38, 0x9e, 0x58, 0x00, 0x1f, 0x9e, 0x5f, 0x20, 0x1d, 0x18, 0x17, 0x57, 0x53, +0x00, 0x0e, 0x01, 0x8a, 0x1b, 0x00, 0xbe, 0x58, 0x11, 0x00, 0x7a, 0x67, 0x02, 0x6f, 0x00, 0x66, 0x9e, 0x58, 0x5d, 0x1a, 0x19, 0x10, 0x07, 0x38, 0x0e, 0x0e, 0xdd, 0x5f, 0x1a, 0x38, 0x1a, 0x38, 0xed, 0xcd, 0xc3, 0xcd, 0x9e, 0x5f, 0xea, 0x04, 0x0a, 0x67, 0xbe, 0x5f, 0xe4, 0x19, 0x9e, 0x58, 0x54, 0x1a, 0x9e, 0x59, 0x48, 0x1a, 0x24, 0x3a, 0x00, 0xe0, 0x07, 0x8a, 0x22, 0x39, 0x00, 0x20, 0xbe, 0x59, 0x48, 0x1a, 0x24, 0x38, 0xff, 0x1f, 0x17, 0x9e, 0x18, 0x10, 0x0b, 0x8a, 0x9e, 0x59, 0x48, 0x1a, 0x18, 0x11, 0x05, 0x8a, 0x26, 0x5a, 0x41, 0x02, 0x02, 0x00, 0x08, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x48, 0x1a, 0x9e, 0x59, 0xe2, 0x19, 0x3f, 0x48, 0x07, 0x8a, 0x9e, 0x58, 0x48, 0x1a, 0x05, 0x39, 0x00, 0x80, 0xbe, 0x59, 0x48, 0x1a, 0x06, 0x58, 0x24, 0x3a, 0x00, 0xe0, 0x00, 0x8a, 0x30, 0x62, 0xa0, 0x62, +0x40, 0x0e, 0x0b, 0x6a, 0x50, 0x3a, 0x4b, 0x1a, 0x49, 0x5a, 0x02, 0x40, 0x00, 0x61, 0x02, 0x69, 0x01, 0x40, 0xbe, 0x59, 0x05, 0x1c, 0x9e, 0x59, 0x4b, 0x1a, 0xbe, 0x59, 0x03, 0x1c, 0x00, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0x58, 0x1a, 0x60, 0x66, 0x11, 0x6e, 0x00, 0x61, 0x80, 0x69, 0x9e, 0x5f, 0xff, 0x1b, 0x19, 0x17, 0xe7, 0x38, 0x5c, 0x0e, 0xd1, 0x22, 0x5d, 0x5e, 0xaa, 0x63, 0x15, 0x6b, 0xbe, 0x62, 0x15, 0x6a, 0x00, 0x61, 0x9e, 0x5f, 0xf0, 0x04, 0x19, 0x17, 0xe7, 0x38, 0x69, 0x0e, 0x1d, 0x5b, 0x19, 0x01, 0x3d, 0x5a, 0xbe, 0x58, 0x4b, 0x1a, 0xc8, 0x63, 0x1b, 0x6b, 0x00, 0x60, 0x13, 0x67, 0xe7, 0x38, 0x74, 0x0e, 0x1d, 0x5b, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x58, 0x06, 0x1c, 0xbe, 0x58, 0x1c, 0x00, 0x3a, 0x38, 0x60, 0x67, 0x11, 0x6f, 0x48, 0x66, 0x0e, 0x6e, 0x00, 0x64, 0x01, 0x63, 0xf6, 0x44, +0x80, 0x0e, 0x24, 0x72, 0x9e, 0x58, 0x05, 0x1c, 0x08, 0x58, 0x40, 0x02, 0x00, 0x61, 0x80, 0x69, 0x20, 0x58, 0x9e, 0x5d, 0xda, 0x00, 0x19, 0x15, 0xa7, 0x38, 0x9c, 0x0e, 0xf1, 0x25, 0x08, 0x8a, 0xd3, 0x15, 0x0a, 0x98, 0xf0, 0x25, 0xbb, 0x5f, 0x9e, 0x49, 0x06, 0x98, 0x9b, 0x5e, 0x04, 0x9e, 0xd2, 0x15, 0xfa, 0x9b, 0xf1, 0x2d, 0xbb, 0x5f, 0x19, 0x07, 0x19, 0x06, 0x3a, 0x38, 0xbe, 0x63, 0x15, 0x6b, 0x00, 0x65, 0x9e, 0x5c, 0x4b, 0x1a, 0x18, 0x14, 0x0a, 0x8a, 0x19, 0x14, 0x87, 0x38, 0xae, 0x0e, 0x65, 0x04, 0x83, 0x5e, 0x19, 0x16, 0x66, 0x07, 0xe3, 0x5e, 0xdb, 0x5c, 0x19, 0x05, 0x3a, 0x38, 0x9e, 0x5e, 0x4b, 0x1a, 0x0f, 0x9a, 0x0e, 0x8a, 0x19, 0x16, 0xc7, 0x38, 0xc1, 0x0e, 0xc0, 0x3d, 0xbe, 0x15, 0xa3, 0x5f, 0x19, 0x17, 0xdf, 0x48, 0x04, 0x8a, 0xaa, 0x62, 0x15, 0x6a, 0xc3, 0xce, 0x95, 0xc4, +0xc0, 0x0e, 0x01, 0xcf, 0x19, 0x16, 0x3a, 0x38, 0xe2, 0x04, 0x83, 0x58, 0xc2, 0x02, 0x50, 0x00, 0x1b, 0x5c, 0xde, 0x5a, 0x00, 0x00, 0x3a, 0x38, 0x00, 0x60, 0xff, 0x61, 0xde, 0x66, 0x15, 0x6e, 0xf2, 0x65, 0x15, 0x6d, 0x06, 0x64, 0x16, 0x6c, 0x1a, 0x63, 0x16, 0x6b, 0x9e, 0x5f, 0xf0, 0x04, 0x19, 0x17, 0xe7, 0x38, 0xdd, 0x0e, 0x3d, 0x5e, 0x1d, 0x5d, 0x1d, 0x5c, 0x3d, 0x5b, 0x3a, 0x38, 0x60, 0x38, 0xde, 0x15, 0xfb, 0x58, 0x60, 0x38, 0xf2, 0x15, 0xfb, 0x58, 0x60, 0x38, 0x06, 0x16, 0xdb, 0x58, 0x60, 0x38, 0x1a, 0x16, 0xdb, 0x58, 0x3a, 0x38, 0x60, 0x38, 0xde, 0x15, 0xf8, 0x49, 0x01, 0x94, 0xfb, 0x58, 0x60, 0x38, 0xf2, 0x15, 0xf8, 0x49, 0x01, 0x9a, 0xfb, 0x58, 0x60, 0x38, 0x06, 0x16, 0xd8, 0x49, 0x01, 0x9a, 0xdb, 0x58, 0x60, 0x38, 0x1a, 0x16, 0xd8, 0x49, 0x01, 0x94, 0xdb, 0x58, 0x72, 0xe8, +0x00, 0x0f, 0x3a, 0x38, 0xc0, 0x38, 0xde, 0x15, 0x03, 0x59, 0xe0, 0x3a, 0xde, 0x15, 0x3a, 0x49, 0x01, 0x94, 0x3b, 0x5a, 0xde, 0x58, 0xff, 0x00, 0xc0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0xe0, 0x3a, 0xf2, 0x15, 0x3a, 0x49, 0x01, 0x9a, 0x3b, 0x5a, 0xde, 0x58, 0x00, 0x00, 0xc0, 0x38, 0x06, 0x16, 0x03, 0x59, 0xe0, 0x3a, 0x06, 0x16, 0x3a, 0x49, 0x01, 0x9a, 0x3b, 0x5a, 0xde, 0x58, 0x00, 0x00, 0xc0, 0x38, 0x1a, 0x16, 0x03, 0x59, 0xe0, 0x3a, 0x1a, 0x16, 0x3a, 0x49, 0x01, 0x94, 0x3b, 0x5a, 0xde, 0x58, 0xff, 0x00, 0x3a, 0x38, 0x00, 0x61, 0xbe, 0x59, 0x58, 0x1a, 0x00, 0x67, 0x23, 0x70, 0xe0, 0x39, 0xaa, 0x15, 0x19, 0x49, 0x32, 0x98, 0x02, 0xdc, 0x9e, 0x58, 0xe9, 0x1e, 0x18, 0x10, 0x0e, 0x8a, 0x06, 0x70, 0x08, 0xac, 0x08, 0x92, 0x00, 0xac, 0x06, 0x92, 0x50, 0xac, 0x04, 0x92, 0x20, 0x60, 0x7b, 0x06, +0x40, 0x0f, 0x01, 0x68, 0x1c, 0x78, 0x03, 0x9e, 0x00, 0x60, 0x02, 0x68, 0x1c, 0x78, 0x9e, 0x58, 0x20, 0x1d, 0x02, 0x38, 0x80, 0x01, 0x03, 0x88, 0x40, 0x60, 0xbe, 0x58, 0x1c, 0x00, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5e, 0xe0, 0x3b, 0xde, 0x15, 0x63, 0x5d, 0x14, 0x60, 0x58, 0x62, 0x1a, 0x6a, 0x1a, 0x49, 0x12, 0x9a, 0x6d, 0xcf, 0x19, 0x05, 0xe0, 0x3b, 0xf2, 0x15, 0xbb, 0x49, 0xf5, 0x9b, 0x19, 0x06, 0xe0, 0x38, 0x06, 0x16, 0xd8, 0x49, 0xed, 0x9b, 0x66, 0xdc, 0x19, 0x07, 0x9e, 0x58, 0x4b, 0x1a, 0xf8, 0x48, 0xc4, 0x97, 0x01, 0x9e, 0x66, 0xdc, 0x3a, 0x38, 0x9e, 0x5a, 0xfd, 0x1b, 0xa0, 0x38, 0x48, 0x0e, 0x46, 0x48, 0x03, 0x5c, 0xe0, 0x3b, 0xc8, 0x1b, 0x63, 0x58, 0x04, 0x00, 0x1b, 0x5b, 0x1c, 0x73, 0x9b, 0x48, 0x31, 0x96, 0x1e, 0x5f, 0x01, 0x67, 0xe0, 0x39, 0x0c, 0x10, 0x29, 0x59, 0xae, 0x85, +0x80, 0x0f, 0x25, 0x03, 0x62, 0x39, 0x00, 0x00, 0x14, 0x96, 0x72, 0x39, 0xfd, 0x1b, 0x11, 0x94, 0xe0, 0x39, 0x15, 0x10, 0x29, 0x59, 0x26, 0x02, 0x42, 0x39, 0x00, 0x00, 0x0a, 0x96, 0x52, 0x39, 0xfe, 0x1b, 0x07, 0x94, 0x9e, 0x59, 0xfd, 0x1b, 0x60, 0x38, 0x48, 0x0e, 0x22, 0x48, 0x98, 0x49, 0x13, 0x96, 0x19, 0x07, 0xe2, 0x38, 0x09, 0x00, 0xe1, 0x97, 0x3e, 0x5f, 0x58, 0x61, 0x1a, 0x69, 0x23, 0x58, 0x00, 0x3a, 0x72, 0x19, 0xfe, 0x5f, 0xaf, 0x2a, 0xfe, 0x5f, 0x00, 0x3a, 0x86, 0x19, 0xdb, 0x5a, 0x08, 0x39, 0x01, 0x00, 0x01, 0x9e, 0x3e, 0x5f, 0x3a, 0x38, 0x1e, 0x5f, 0x00, 0x67, 0xe0, 0x3c, 0x0c, 0x10, 0x89, 0x5c, 0x85, 0x03, 0x62, 0x39, 0x00, 0x00, 0x50, 0x96, 0x72, 0x39, 0xfd, 0x1b, 0x4d, 0x94, 0xe0, 0x3c, 0x15, 0x10, 0x89, 0x5c, 0x86, 0x02, 0x42, 0x39, 0x00, 0x00, 0x46, 0x96, 0x5c, 0x6a, +0xc0, 0x0f, 0x52, 0x39, 0xfe, 0x1b, 0x43, 0x94, 0x9e, 0x59, 0xfd, 0x1b, 0x60, 0x38, 0x32, 0x16, 0x22, 0x48, 0x03, 0x5c, 0x82, 0x39, 0x00, 0x00, 0x3a, 0x9a, 0x1e, 0x5f, 0x1e, 0x5c, 0x1e, 0xd0, 0x81, 0x58, 0x3e, 0x5c, 0x19, 0x17, 0x20, 0x98, 0x19, 0x11, 0x1e, 0x98, 0x1e, 0x5c, 0x00, 0x3f, 0x72, 0x19, 0xe3, 0x5f, 0x00, 0x39, 0x86, 0x19, 0x23, 0x59, 0x9e, 0x5c, 0xfd, 0x1b, 0xe0, 0x38, 0x32, 0x16, 0x81, 0x48, 0x03, 0x5f, 0xa0, 0x38, 0x32, 0x16, 0x86, 0x48, 0x3e, 0x5c, 0x17, 0x07, 0x80, 0x41, 0x1c, 0x5f, 0x01, 0x5c, 0x3e, 0x5f, 0xe2, 0x38, 0x05, 0x00, 0x04, 0x96, 0xfd, 0x61, 0xb4, 0x69, 0x81, 0x40, 0x21, 0x5c, 0x1e, 0x5f, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x83, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x82, 0x48, 0x3f, 0x5f, 0x1f, 0xab, +0x00, 0x10, 0x1b, 0x5f, 0x90, 0x38, 0x54, 0x1a, 0xbe, 0x58, 0x54, 0x1a, 0x3e, 0x5f, 0x19, 0x07, 0xe2, 0x38, 0x09, 0x00, 0xa5, 0x97, 0x3e, 0x5f, 0x3a, 0x38, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x01, 0x00, 0x9e, 0x5c, 0x58, 0x1a, 0x18, 0x14, 0x29, 0x9a, 0x19, 0x14, 0xff, 0x67, 0x7f, 0x6f, 0x87, 0x38, 0x3d, 0x10, 0x80, 0x38, 0x72, 0x19, 0x80, 0x39, 0x86, 0x19, 0xb8, 0x49, 0x02, 0x88, 0xd9, 0x49, 0x0e, 0x8a, 0x13, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x32, 0x11, 0x01, 0x8c, 0x22, 0x59, 0x01, 0x00, 0xe4, 0x39, 0xff, 0x00, 0x19, 0x48, 0x03, 0x94, 0xfe, 0x5c, 0x04, 0x2f, 0xfe, 0x5c, 0x19, 0x14, 0xe4, 0x3c, 0x00, 0xff, 0x03, 0xe2, +0x40, 0x10, 0xfe, 0x5c, 0x80, 0x38, 0x72, 0x19, 0x13, 0x11, 0x01, 0x8c, 0x22, 0x59, 0x80, 0x38, 0x86, 0x19, 0x12, 0x17, 0x01, 0x8c, 0xe2, 0x5f, 0x3a, 0x38, 0x21, 0x72, 0x43, 0x43, 0x01, 0x5c, 0x43, 0x41, 0x24, 0x01, 0x9e, 0x5c, 0x54, 0x1a, 0x1c, 0x5c, 0x18, 0x00, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0xd2, 0x60, 0x15, 0x68, 0x03, 0x59, 0x22, 0x38, 0x01, 0x00, 0x03, 0x8a, 0x22, 0x38, 0x02, 0x00, 0x06, 0x8a, 0x00, 0x60, 0xbe, 0x58, 0x0b, 0x1f, 0xbe, 0x58, 0x0c, 0x1f, 0x0a, 0x9e, 0xb2, 0x60, 0x19, 0x68, 0x03, 0x59, 0xbe, 0x59, 0x0c, 0x1f, 0xbe, 0x60, 0x19, 0x68, 0x03, 0x59, 0xbe, 0x59, 0x0b, 0x1f, 0x3e, 0x59, 0x3e, 0x58, 0x00, 0x60, 0xbe, 0x58, 0xe2, 0x19, 0x58, 0x60, 0x1a, 0x68, 0x00, 0x61, 0x38, 0x49, 0x58, 0x8a, 0x00, 0x67, 0xe0, 0x38, 0x72, 0x19, 0x03, 0x5d, 0xe0, 0x38, 0x68, 0xec, +0x80, 0x10, 0x86, 0x19, 0x03, 0x5e, 0xd4, 0xd0, 0xf4, 0xd1, 0x9e, 0x58, 0x59, 0x1a, 0x19, 0x10, 0x05, 0x8a, 0xe0, 0xd0, 0x9e, 0x58, 0x59, 0x1a, 0x1a, 0x10, 0x01, 0x8a, 0xad, 0xcf, 0x51, 0x63, 0x1a, 0x6b, 0x4c, 0xd0, 0x9e, 0x5d, 0xe2, 0x19, 0xa0, 0x3b, 0xb2, 0x19, 0x1b, 0x5b, 0x53, 0x63, 0x1a, 0x6b, 0x4c, 0xd0, 0xa0, 0x3b, 0xbe, 0x19, 0x1b, 0x5b, 0x1e, 0x58, 0x1e, 0x59, 0xa2, 0x38, 0x00, 0x00, 0x13, 0x88, 0x9e, 0x58, 0x0b, 0x1f, 0x18, 0x10, 0x05, 0x88, 0x9e, 0x58, 0x0c, 0x1f, 0x18, 0x10, 0x01, 0x88, 0x0a, 0x9e, 0x9e, 0x58, 0x0b, 0x1f, 0xb2, 0x61, 0x19, 0x69, 0x1b, 0x59, 0x9e, 0x58, 0x0c, 0x1f, 0xbe, 0x61, 0x19, 0x69, 0x1b, 0x59, 0x3e, 0x59, 0x3e, 0x58, 0xe2, 0x62, 0x19, 0x6a, 0xca, 0x63, 0x19, 0x6b, 0x53, 0x03, 0xde, 0x5b, 0xff, 0xff, 0xd6, 0x63, 0x19, 0x6b, 0x53, 0x03, 0xd6, 0xe0, +0xc0, 0x10, 0xde, 0x5b, 0xff, 0x7f, 0x43, 0x5b, 0x68, 0x3a, 0x01, 0x00, 0x59, 0x60, 0x1a, 0x68, 0xde, 0x58, 0x00, 0x00, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0x27, 0x00, 0x05, 0x94, 0x19, 0x07, 0x58, 0x60, 0x1a, 0x68, 0xf8, 0x49, 0xa9, 0x81, 0x3a, 0x38, 0x50, 0x60, 0x1a, 0x68, 0x00, 0x61, 0x04, 0x62, 0x47, 0x38, 0xdb, 0x10, 0x3d, 0x58, 0x1a, 0x38, 0x59, 0x60, 0x1a, 0x68, 0x3b, 0x58, 0x3a, 0x38, 0xbe, 0x5d, 0xe1, 0x1b, 0xbe, 0x5e, 0xe2, 0x1b, 0x1e, 0x5f, 0x00, 0x67, 0xe0, 0x39, 0xde, 0x15, 0x23, 0x59, 0xe0, 0x3a, 0xf2, 0x15, 0x43, 0x5a, 0xe0, 0x3b, 0x06, 0x16, 0x63, 0x5b, 0xe0, 0x3c, 0x1a, 0x16, 0x83, 0x5c, 0xb9, 0x48, 0x07, 0x96, 0xba, 0x48, 0x05, 0x98, 0xdb, 0x48, 0x03, 0x98, 0xdc, 0x48, 0x01, 0x96, 0x05, 0x9e, 0x19, 0x07, 0xf2, 0x39, 0x4b, 0x1a, 0xe7, 0x97, 0xa9, 0x9e, 0xcb, 0x8d, +0x00, 0x11, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x67, 0x00, 0x60, 0xe0, 0x3d, 0x72, 0x19, 0xa3, 0x5d, 0xe0, 0x3e, 0x86, 0x19, 0xc3, 0x5e, 0xb9, 0x48, 0x0a, 0x96, 0xba, 0x48, 0x08, 0x98, 0xdb, 0x48, 0x06, 0x98, 0xdc, 0x48, 0x04, 0x96, 0x19, 0x00, 0xfe, 0x5f, 0x07, 0x28, 0xfe, 0x5f, 0x19, 0x07, 0xf2, 0x3d, 0x58, 0x1a, 0xea, 0x97, 0x3e, 0x5f, 0x04, 0x3d, 0xff, 0x00, 0x19, 0x15, 0x01, 0x8a, 0x86, 0x9e, 0x41, 0x16, 0xc1, 0x5f, 0x64, 0x15, 0xdd, 0x48, 0x01, 0x94, 0xa1, 0x5f, 0x1d, 0x17, 0x7b, 0x98, 0x04, 0x3f, 0x00, 0xff, 0xfe, 0x5f, 0x1a, 0x16, 0x0d, 0x94, 0xe0, 0x38, 0x72, 0x19, 0x03, 0x58, 0x18, 0x10, 0x02, 0x9a, 0x02, 0x39, 0x01, 0x00, 0x12, 0x3e, 0xfd, 0x1b, 0x19, 0x06, 0x02, 0x94, 0x00, 0x3a, 0x01, 0x00, 0x1a, 0x15, 0x0d, 0x94, 0xe0, 0x38, 0x86, 0x19, 0x03, 0x58, 0xdb, 0x66, +0x40, 0x11, 0x18, 0x10, 0x02, 0x9a, 0x02, 0x3c, 0x01, 0x00, 0x12, 0x3e, 0xfe, 0x1b, 0x19, 0x06, 0x02, 0x94, 0x00, 0x3b, 0x01, 0x00, 0x1e, 0x59, 0x21, 0x5d, 0x9e, 0x5e, 0xfd, 0x1b, 0xa0, 0x38, 0x32, 0x16, 0xc4, 0x48, 0x03, 0x5e, 0x9e, 0x58, 0xe6, 0x1b, 0x00, 0x61, 0x01, 0x69, 0x19, 0x48, 0x12, 0x98, 0xb2, 0x38, 0xe1, 0x1b, 0x03, 0x88, 0x92, 0x38, 0xe2, 0x1b, 0x0c, 0x8a, 0x18, 0x16, 0x07, 0x9a, 0x08, 0x60, 0xc0, 0x40, 0x08, 0x5e, 0xc0, 0x06, 0xc8, 0x5e, 0xc8, 0x5e, 0xc8, 0x5e, 0x9e, 0x58, 0xe4, 0x1b, 0xc0, 0x06, 0x18, 0x16, 0x2b, 0x9a, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0xc5, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0xc4, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0xd0, 0x3f, 0x54, 0x1a, 0xbe, 0x5f, 0x54, 0x1a, 0x7f, 0xac, 0x17, 0x90, 0xbd, 0x55, +0x80, 0x11, 0xe8, 0x5f, 0xbe, 0x5f, 0x54, 0x1a, 0x9e, 0x58, 0x50, 0x1a, 0x9e, 0x59, 0x51, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x51, 0x1a, 0xbe, 0x58, 0x50, 0x1a, 0x9e, 0x58, 0x52, 0x1a, 0x9e, 0x59, 0x53, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x53, 0x1a, 0xbe, 0x58, 0x52, 0x1a, 0xa2, 0x37, 0x02, 0x8a, 0x19, 0x05, 0xb1, 0x9f, 0x3e, 0x59, 0x83, 0x37, 0x02, 0x8a, 0x19, 0x04, 0xaa, 0x9f, 0x02, 0x65, 0xbe, 0x5d, 0x59, 0x1a, 0x03, 0x9e, 0x03, 0x65, 0xbe, 0x5d, 0x59, 0x1a, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5f, 0x3a, 0x38, 0x1e, 0x5c, 0x9e, 0x5d, 0xe1, 0x1b, 0x9e, 0x5e, 0xe2, 0x1b, 0xa0, 0x38, 0x32, 0x16, 0x16, 0x67, 0x1e, 0x59, 0x00, 0x61, 0xc7, 0x48, 0x3e, 0x59, 0x03, 0x5f, 0x18, 0x17, 0x35, 0x9a, 0x1e, 0x59, 0x1e, 0x5a, 0x00, 0x61, 0xe1, 0x58, 0xbe, 0x5f, 0xe6, 0x1b, 0x35, 0x15, +0xc0, 0x11, 0x06, 0x58, 0x2a, 0x59, 0x06, 0x58, 0x2a, 0x59, 0x0c, 0x62, 0x1c, 0x5a, 0xbe, 0x58, 0xe3, 0x1b, 0x00, 0x61, 0xe1, 0x58, 0xa8, 0x62, 0x1c, 0x5a, 0xbe, 0x58, 0xe4, 0x1b, 0x3e, 0x5a, 0x3e, 0x59, 0x41, 0x10, 0x21, 0x5f, 0x07, 0x38, 0xea, 0x11, 0xfd, 0x48, 0x02, 0x88, 0x9e, 0x48, 0x12, 0x8a, 0x20, 0x38, 0x32, 0x16, 0x1e, 0x59, 0x1e, 0x5a, 0x16, 0x62, 0x00, 0x61, 0x82, 0x48, 0x3e, 0x5a, 0x3e, 0x59, 0x03, 0x58, 0x18, 0x10, 0x06, 0x9a, 0x1e, 0x59, 0x9e, 0x59, 0xe3, 0x1b, 0x19, 0x48, 0x3e, 0x59, 0x05, 0x94, 0x19, 0x07, 0x19, 0x04, 0x9b, 0x48, 0xe2, 0x9b, 0x03, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0xe4, 0x1b, 0x3e, 0x5c, 0x3a, 0x38, 0x9e, 0x58, 0x58, 0x1a, 0x02, 0x39, 0x01, 0x00, 0x1d, 0x9a, 0x00, 0x62, 0x5f, 0x48, 0x16, 0x8a, 0x40, 0x38, 0x72, 0x19, 0x03, 0x5b, 0x40, 0x38, 0xb8, 0xbd, +0x00, 0x12, 0x86, 0x19, 0x03, 0x5c, 0xa3, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x02, 0x39, 0x01, 0x00, 0x0a, 0x88, 0xc4, 0x10, 0x01, 0x8c, 0x02, 0x58, 0x02, 0x39, 0x01, 0x00, 0x04, 0x88, 0x01, 0x61, 0xbe, 0x59, 0x59, 0x1a, 0x04, 0x9e, 0x19, 0x02, 0x52, 0x39, 0x58, 0x1a, 0xe4, 0x89, 0x3a, 0x38, 0x9e, 0x58, 0x58, 0x1a, 0x02, 0x39, 0x01, 0x00, 0x66, 0x9a, 0x00, 0x67, 0xe0, 0x3e, 0x86, 0x19, 0xe0, 0x3a, 0x01, 0x00, 0x40, 0x3b, 0x72, 0x19, 0x40, 0x3c, 0x86, 0x19, 0xe0, 0x3d, 0x72, 0x19, 0xa3, 0x5d, 0xa4, 0x38, 0x00, 0xff, 0x63, 0x5b, 0x64, 0x39, 0x00, 0xff, 0x19, 0x48, 0x4a, 0x88, 0xa4, 0x3d, 0xff, 0x00, 0x64, 0x3b, 0xff, 0x00, 0x1e, 0x5f, 0x1e, 0x5a, 0x9e, 0x5f, 0xfd, 0x1b, 0x60, 0x38, 0x48, 0x0e, 0xe4, 0x49, 0x03, 0x5a, 0xa0, 0x38, 0x48, 0x0e, 0xe6, 0x49, 0x00, 0x61, 0x58, 0x49, 0x7a, 0x8f, +0x40, 0x12, 0x02, 0x9a, 0x01, 0x61, 0x03, 0x5a, 0x1e, 0x59, 0x9e, 0x58, 0x44, 0x1a, 0x40, 0x40, 0x9f, 0x38, 0x08, 0x58, 0xbe, 0x58, 0x83, 0x1a, 0x8f, 0xd2, 0x19, 0x10, 0x28, 0x8a, 0x9e, 0x58, 0x58, 0x1a, 0x19, 0x10, 0xbe, 0x58, 0x58, 0x1a, 0x3e, 0x59, 0x3e, 0x5a, 0x3e, 0x5f, 0x40, 0x3b, 0x72, 0x19, 0xe0, 0x3d, 0x72, 0x19, 0x18, 0x11, 0x04, 0x8a, 0x63, 0x59, 0x3b, 0x5d, 0x83, 0x59, 0x3b, 0x5e, 0x72, 0x61, 0x19, 0x69, 0x30, 0x39, 0x58, 0x1a, 0x23, 0x59, 0x3b, 0x5b, 0x86, 0x61, 0x19, 0x69, 0x30, 0x39, 0x58, 0x1a, 0x23, 0x59, 0x3b, 0x5c, 0x19, 0x10, 0x14, 0x8a, 0x52, 0x38, 0x58, 0x1a, 0x0c, 0x94, 0xf2, 0x38, 0x58, 0x1a, 0x19, 0x00, 0x0d, 0x94, 0xab, 0x9f, 0x3e, 0x59, 0x3e, 0x5a, 0x3e, 0x5f, 0x19, 0x02, 0x52, 0x39, 0x58, 0x1a, 0xa4, 0x97, 0x19, 0x07, 0xf2, 0x39, 0x58, 0x1a, 0x11, 0xac, +0x80, 0x12, 0x19, 0x01, 0x9b, 0x97, 0x9e, 0x58, 0x58, 0x1a, 0x18, 0x10, 0x08, 0x8a, 0x72, 0x66, 0x19, 0x6e, 0xff, 0x61, 0x19, 0x10, 0x07, 0x38, 0x8d, 0x12, 0xd1, 0x25, 0xbd, 0x5e, 0x3a, 0x38, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5b, 0x1e, 0x5c, 0x83, 0x5a, 0x7d, 0x48, 0x03, 0x9a, 0x5e, 0x49, 0x23, 0x9a, 0x32, 0x9e, 0x5e, 0x49, 0x10, 0x9a, 0x61, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0xa1, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x02, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x2f, 0x9e, 0x61, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0xa1, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x00, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x1f, 0x9e, 0xa1, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0x61, 0x5a, 0xbe, 0x5a, 0x5d, 0xe2, +0xc0, 0x12, 0x2f, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x06, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0x0f, 0x9e, 0xa1, 0x5a, 0xbe, 0x5a, 0x2e, 0x16, 0x61, 0x5a, 0xbe, 0x5a, 0x2f, 0x16, 0xc3, 0x5a, 0xbe, 0x5a, 0x30, 0x16, 0x83, 0x5a, 0xbe, 0x5a, 0x31, 0x16, 0x04, 0x62, 0xbe, 0x5a, 0x82, 0x1a, 0xc3, 0x5e, 0xa1, 0x58, 0xc1, 0x59, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5b, 0x1e, 0x5c, 0x00, 0x67, 0x9e, 0x5a, 0x82, 0x1a, 0x40, 0x3c, 0x2a, 0x13, 0x89, 0x5c, 0x85, 0x04, 0x92, 0x39, 0x2e, 0x16, 0x23, 0x96, 0x92, 0x39, 0x2f, 0x16, 0x20, 0x98, 0x40, 0x3b, 0x32, 0x13, 0x69, 0x5b, 0x66, 0x03, 0x72, 0x39, 0x30, 0x16, 0x19, 0x96, 0x72, 0x39, 0x31, 0x16, 0x16, 0x98, 0x9e, 0x59, 0xfd, 0x1b, 0x80, 0x38, 0x48, 0x0e, 0x23, 0x48, 0x9e, 0x59, 0x83, 0x1a, 0x38, 0x49, 0x36, 0x4b, +0x00, 0x13, 0x0d, 0x98, 0x81, 0x5d, 0x61, 0x5e, 0x9e, 0x59, 0x82, 0x1a, 0x01, 0xac, 0x02, 0x90, 0x1e, 0x01, 0x01, 0x9e, 0x1f, 0x01, 0x1f, 0x21, 0xbe, 0x59, 0x82, 0x1a, 0x08, 0x9e, 0x19, 0x02, 0x1f, 0x22, 0xbe, 0x5a, 0x82, 0x1a, 0x19, 0x07, 0xe2, 0x39, 0x08, 0x00, 0xce, 0x97, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x59, 0x3e, 0x58, 0xd9, 0x48, 0x04, 0x88, 0xb8, 0x48, 0x02, 0x88, 0x01, 0x60, 0x05, 0x9e, 0xdc, 0x49, 0xbb, 0x89, 0xbb, 0x48, 0xb9, 0x89, 0x00, 0x60, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5e, 0x3e, 0x5d, 0x3a, 0x38, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0x02, 0x3f, 0x01, 0x00, 0x0c, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xba, 0x1f, +0x40, 0x13, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x47, 0x13, 0xa5, 0x59, 0x3d, 0x5e, 0x21, 0x9e, 0x12, 0x3f, 0x22, 0x00, 0x1e, 0x98, 0x30, 0x66, 0x0b, 0x6e, 0x9e, 0x5d, 0xe8, 0x00, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x57, 0x13, 0xa5, 0x5f, 0xd7, 0x07, 0xfd, 0x5e, 0x12, 0x3f, 0x22, 0x00, 0x0f, 0x88, 0x30, 0x66, 0x0b, 0x6e, 0x22, 0x75, 0x9e, 0x5f, 0xda, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x68, 0x13, 0x00, 0x61, 0xc3, 0x58, 0x1c, 0x5d, 0x1d, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0x3a, 0x38, 0x27, 0x76, 0x19, 0x16, 0x39, 0x60, 0x15, 0x68, 0x9a, 0x61, 0x19, 0x69, 0x45, 0x62, 0x15, 0x6a, 0xa6, 0x63, 0x19, 0x6b, 0x00, 0x64, 0x80, 0x6c, 0x00, 0x67, 0xc7, 0x38, 0x83, 0x13, 0xf8, 0x49, 0x04, 0x98, 0x03, 0x5d, 0xbb, 0x59, 0x43, 0x5d, 0xbb, 0x5b, 0x0b, 0xa4, +0x80, 0x13, 0x19, 0x01, 0x19, 0x03, 0x9d, 0x58, 0x9d, 0x5a, 0x21, 0x60, 0x15, 0x68, 0x2b, 0x61, 0x1c, 0x69, 0x2d, 0x62, 0x15, 0x6a, 0x37, 0x63, 0x1c, 0x6b, 0x00, 0x65, 0xc7, 0x38, 0xa2, 0x13, 0xa0, 0x3c, 0x85, 0x29, 0x89, 0x5c, 0x94, 0x3c, 0xe3, 0x19, 0x05, 0x8a, 0x03, 0x5c, 0x9b, 0x59, 0x43, 0x5c, 0x9b, 0x5b, 0x04, 0x9e, 0xde, 0x59, 0x00, 0x80, 0xde, 0x5b, 0x00, 0x80, 0x19, 0x01, 0x19, 0x03, 0x19, 0x00, 0x19, 0x02, 0x19, 0x05, 0x00, 0x67, 0x80, 0x6f, 0x51, 0x60, 0x15, 0x68, 0x21, 0x61, 0x15, 0x69, 0x5d, 0x62, 0x15, 0x6a, 0x2d, 0x63, 0x15, 0x6b, 0xc7, 0x38, 0xb8, 0x13, 0xf8, 0x49, 0x04, 0x8a, 0x03, 0x5c, 0x9b, 0x59, 0x43, 0x5c, 0x9b, 0x5b, 0x19, 0x01, 0x19, 0x03, 0x19, 0x00, 0x19, 0x02, 0xca, 0x60, 0x19, 0x68, 0xd6, 0x61, 0x19, 0x69, 0xc7, 0x38, 0xc4, 0x13, 0xde, 0x58, 0xb0, 0xea, +0xc0, 0x13, 0xff, 0xff, 0xde, 0x59, 0xff, 0x7f, 0x19, 0x00, 0x19, 0x01, 0x9e, 0x58, 0xfa, 0x1b, 0x12, 0x38, 0xe2, 0x19, 0x16, 0x9a, 0x00, 0x67, 0x01, 0x65, 0xc7, 0x38, 0xdf, 0x13, 0xb4, 0x38, 0x4c, 0x1a, 0x0d, 0x88, 0xe0, 0x38, 0x9a, 0x19, 0xde, 0x58, 0x00, 0x80, 0xe0, 0x38, 0xa6, 0x19, 0xde, 0x58, 0x00, 0x80, 0xa0, 0x5c, 0x94, 0x3c, 0x00, 0x1c, 0xbe, 0x5c, 0x00, 0x1c, 0xa6, 0x5d, 0x19, 0x07, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x24, 0x8a, 0x21, 0x72, 0x23, 0x61, 0x22, 0x40, 0x00, 0x3b, 0x00, 0x00, 0x15, 0x61, 0x22, 0x40, 0x00, 0x3c, 0x00, 0x00, 0xe1, 0x5e, 0x00, 0x67, 0xe0, 0x39, 0xb2, 0x19, 0xe0, 0x3a, 0xbe, 0x19, 0x79, 0x49, 0x02, 0x80, 0x9a, 0x49, 0x0c, 0x82, 0x19, 0x16, 0xdf, 0x48, 0x0c, 0x8a, 0xc0, 0x38, 0xb2, 0x19, 0x03, 0x58, 0x1b, 0x59, 0xc0, 0x38, 0xaa, 0xd3, +0x00, 0x14, 0xbe, 0x19, 0x03, 0x58, 0x1b, 0x5a, 0xec, 0x9f, 0x19, 0x07, 0xe6, 0x15, 0xe9, 0x97, 0xbe, 0x5e, 0xe2, 0x19, 0x01, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x00, 0x67, 0xe2, 0x60, 0x19, 0x68, 0xf8, 0x49, 0x31, 0x94, 0xe0, 0x38, 0xca, 0x19, 0x00, 0x61, 0x38, 0x49, 0x2a, 0x9a, 0x00, 0x66, 0x27, 0x70, 0x19, 0x10, 0x07, 0x38, 0x3f, 0x14, 0xc0, 0x38, 0x39, 0x15, 0x00, 0x61, 0x38, 0x49, 0x1f, 0x9a, 0xc0, 0x38, 0x9a, 0x19, 0x00, 0x61, 0x38, 0x49, 0x03, 0x9a, 0xfe, 0x65, 0x7f, 0x6d, 0x0f, 0x9e, 0xe0, 0x38, 0xb2, 0x19, 0xc0, 0x39, 0x9a, 0x19, 0x23, 0x59, 0x11, 0x12, 0xe0, 0x38, 0xbe, 0x19, 0xc0, 0x39, 0xa6, 0x19, 0x23, 0x59, 0x11, 0x13, 0x5a, 0x40, 0x63, 0x48, 0x46, 0xd9, 0xe0, 0x38, 0xd6, 0x19, 0xb8, 0x49, 0x04, 0x94, 0xbb, 0x58, 0xe0, 0x38, 0xca, 0x19, 0xdb, 0x58, 0x19, 0x06, 0xde, 0xb2, +0x40, 0x14, 0x19, 0x07, 0xcb, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x00, 0x67, 0x9e, 0x5d, 0xe2, 0x19, 0xfd, 0x48, 0x25, 0x94, 0xe0, 0x3e, 0x01, 0x00, 0xa2, 0x38, 0x01, 0x00, 0x07, 0x38, 0x6c, 0x14, 0xdd, 0x48, 0x1b, 0x94, 0xe0, 0x3c, 0xca, 0x19, 0x83, 0x58, 0xc0, 0x3b, 0xca, 0x19, 0x1b, 0x49, 0x13, 0x88, 0xe0, 0x3a, 0xd6, 0x19, 0x43, 0x58, 0xc0, 0x39, 0xd6, 0x19, 0x19, 0x49, 0x05, 0x9a, 0xde, 0x5c, 0xff, 0xff, 0xde, 0x5a, 0xff, 0x7f, 0x04, 0x9e, 0xde, 0x5b, 0xff, 0xff, 0xde, 0x59, 0xff, 0x7f, 0x01, 0x60, 0xbe, 0x58, 0x82, 0x1a, 0x19, 0x06, 0x19, 0x07, 0xd9, 0x9f, 0x00, 0x67, 0xe2, 0x60, 0x19, 0x68, 0xf8, 0x49, 0x15, 0x94, 0xe0, 0x38, 0xca, 0x19, 0x00, 0x61, 0x38, 0x49, 0x0e, 0x98, 0x39, 0x61, 0x15, 0x69, 0x11, 0x01, 0xe0, 0x3a, 0xb2, 0x19, 0x43, 0x5a, 0x5b, 0x59, 0xd2, 0xa6, +0x80, 0x14, 0x45, 0x61, 0x15, 0x69, 0x11, 0x01, 0xe0, 0x3a, 0xbe, 0x19, 0x43, 0x5a, 0x5b, 0x59, 0x19, 0x07, 0xe7, 0x9f, 0x82, 0x60, 0x1a, 0x68, 0x01, 0x61, 0x38, 0x49, 0x7e, 0x8b, 0x9e, 0x58, 0xe2, 0x19, 0x19, 0x10, 0x01, 0x9a, 0x25, 0xdb, 0x92, 0x60, 0x15, 0x68, 0xff, 0x61, 0xff, 0x69, 0x27, 0x76, 0x19, 0x16, 0xd7, 0x38, 0x3d, 0x58, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x10, 0x8a, 0x92, 0x66, 0x15, 0x6e, 0x19, 0x17, 0xe7, 0x38, 0xae, 0x14, 0xe0, 0x3b, 0xca, 0x19, 0x76, 0x03, 0xe0, 0x3c, 0xd6, 0x19, 0x83, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x21, 0x74, 0x9b, 0x5b, 0x19, 0x17, 0x01, 0x67, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0xb5, 0x14, 0xe6, 0x5f, 0x1a, 0x38, 0x19, 0x17, 0xbe, 0x5f, 0x84, 0x1a, 0xf6, 0xd5, 0x9e, 0x58, 0xe2, 0x19, 0xbe, 0x58, 0xfa, 0x1b, 0x00, 0x67, 0x27, 0x70, 0xe3, 0x18, +0xc0, 0x14, 0x19, 0x10, 0x07, 0x38, 0x56, 0x15, 0x9e, 0x58, 0xea, 0x04, 0x18, 0x10, 0x03, 0x8a, 0x02, 0x60, 0x20, 0x78, 0x02, 0x9e, 0x02, 0x60, 0x20, 0x78, 0xe0, 0x38, 0x39, 0x15, 0xe0, 0x3c, 0xd2, 0x15, 0x00, 0x61, 0x38, 0x49, 0x50, 0x98, 0xd0, 0x73, 0x7c, 0x49, 0x02, 0x9a, 0x7b, 0x5c, 0x7e, 0x9e, 0x70, 0x3b, 0x20, 0x00, 0x7c, 0x49, 0x14, 0x98, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0xe3, 0x61, 0x19, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x4c, 0x61, 0x1a, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x70, 0x3b, 0xcf, 0x00, 0x7c, 0x49, 0x34, 0x98, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x2a, 0x5b, 0x59, 0x66, 0x9e, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x14, 0x3a, 0xe3, 0x19, 0x02, 0x8a, 0x7b, 0x5c, 0x27, 0x9e, 0xe0, 0x38, 0x92, 0x15, 0x0a, 0x61, 0x38, 0x49, 0x09, 0x9c, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x3a, 0x4e, +0x00, 0x15, 0x00, 0x61, 0x1c, 0x69, 0x00, 0x5a, 0x32, 0x22, 0x5b, 0x59, 0x19, 0x9e, 0xd0, 0x70, 0x19, 0x00, 0x1c, 0x49, 0x15, 0x88, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x30, 0x22, 0x0e, 0x88, 0x30, 0x2a, 0x5b, 0x59, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x13, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x1f, 0x1c, 0x1b, 0x59, 0x83, 0x58, 0x08, 0x3c, 0x01, 0x00, 0x33, 0x9e, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0xd0, 0x73, 0x14, 0x39, 0x4c, 0x1a, 0x04, 0x8a, 0x00, 0x61, 0x91, 0x11, 0x09, 0x98, 0x0b, 0x9e, 0x7c, 0x49, 0x09, 0x94, 0x7b, 0x5c, 0x00, 0x61, 0x1c, 0x69, 0x00, 0x5a, 0x32, 0x22, 0x5b, 0x59, 0x83, 0x59, 0x2a, 0x3c, 0x01, 0x00, 0x00, 0x58, 0x70, 0x3b, 0x1f, 0x00, 0x7c, 0x49, 0x10, 0x96, 0xe3, 0x61, 0x19, 0x69, 0x0f, 0x86, +0x40, 0x15, 0x30, 0x22, 0x5b, 0x59, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x83, 0x5b, 0x72, 0x3b, 0xd0, 0x00, 0x0c, 0x9a, 0xd0, 0x73, 0x19, 0x13, 0x7b, 0x5c, 0x08, 0x9e, 0x59, 0xd5, 0x19, 0x03, 0x7c, 0x49, 0x04, 0x96, 0x4d, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x19, 0x07, 0x99, 0xd6, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x5b, 0x21, 0x72, 0x23, 0x65, 0xa2, 0x40, 0x00, 0x3d, 0x00, 0x00, 0xe0, 0x38, 0x5b, 0x1c, 0x03, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x0b, 0x9e, 0x1d, 0x48, 0x02, 0x9a, 0xa1, 0x58, 0x07, 0x9e, 0x40, 0x3b, 0x00, 0x00, 0x1b, 0x48, 0x03, 0x96, 0xa2, 0x13, 0x1b, 0x48, 0x03, 0x9a, 0xe0, 0x39, 0x9a, 0x19, 0x1b, 0x59, 0x15, 0x65, 0xa2, 0x40, 0x00, 0x3d, 0x00, 0x00, 0xe0, 0x38, 0x67, 0x1c, 0x03, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x0b, 0x9e, 0xef, 0xbb, +0x80, 0x15, 0x1d, 0x48, 0x02, 0x9a, 0xa1, 0x58, 0x07, 0x9e, 0x40, 0x3b, 0x00, 0x00, 0x1b, 0x48, 0x03, 0x96, 0xa2, 0x13, 0x1b, 0x48, 0x03, 0x9a, 0xe0, 0x39, 0xa6, 0x19, 0x1b, 0x59, 0x3e, 0x5b, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x04, 0x1c, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0xea, 0x04, 0x31, 0x94, 0x01, 0x60, 0xbe, 0x58, 0x04, 0x1c, 0x27, 0x76, 0x19, 0x16, 0x00, 0x65, 0x00, 0x67, 0xc7, 0x38, 0xc9, 0x15, 0xe0, 0x38, 0x9a, 0x19, 0xb8, 0x49, 0x23, 0x98, 0xe0, 0x3e, 0x85, 0x29, 0xc9, 0x5e, 0xd4, 0x3e, 0xe3, 0x19, 0x0b, 0x88, 0x03, 0x58, 0xe0, 0x39, 0x5b, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0xa6, 0x19, 0x03, 0x58, 0xe0, 0x39, 0x67, 0x1c, 0x1b, 0x59, 0x12, 0x9e, 0xe0, 0x39, 0x43, 0x1c, 0x23, 0x59, 0xe0, 0x3a, 0x4f, 0x1c, 0x43, 0x5a, 0xe0, 0x38, 0x9a, 0x19, 0x11, 0x00, 0x9c, 0xb8, +0xc0, 0x15, 0xe0, 0x39, 0x5b, 0x1c, 0x1b, 0x59, 0xe0, 0x38, 0xa6, 0x19, 0x12, 0x00, 0xe0, 0x39, 0x67, 0x1c, 0x1b, 0x59, 0x19, 0x07, 0x3a, 0x38, 0x27, 0x76, 0x19, 0x16, 0x00, 0x67, 0xc7, 0x38, 0xf4, 0x15, 0x00, 0x62, 0xe0, 0x38, 0x39, 0x15, 0x58, 0x49, 0x1f, 0x98, 0xe0, 0x39, 0x9a, 0x19, 0x59, 0x49, 0x1b, 0x98, 0x23, 0x5a, 0x12, 0x12, 0xe0, 0x3c, 0x43, 0x1c, 0x5b, 0x5c, 0xe0, 0x38, 0x45, 0x15, 0xe0, 0x39, 0xa6, 0x19, 0x23, 0x5b, 0x13, 0x13, 0xe0, 0x3c, 0x4f, 0x1c, 0x7b, 0x5c, 0x9e, 0x58, 0x04, 0x1c, 0x18, 0x10, 0x09, 0x8a, 0x5a, 0x40, 0x63, 0x48, 0x46, 0xd9, 0x18, 0x15, 0x01, 0x88, 0x21, 0x75, 0xe0, 0x38, 0x92, 0x15, 0xbb, 0x58, 0x19, 0x07, 0x3a, 0x38, 0x27, 0x75, 0x19, 0x15, 0xa7, 0x38, 0x73, 0x16, 0xa0, 0x3f, 0x85, 0x29, 0xe9, 0x5f, 0x9e, 0x5c, 0x86, 0x1a, 0xe0, 0x5b, 0x06, 0xd5, +0x00, 0x16, 0x83, 0x24, 0xa0, 0x3b, 0xa0, 0x1a, 0x63, 0x5b, 0xbd, 0x13, 0x01, 0x96, 0x87, 0x2c, 0xbe, 0x5c, 0x86, 0x1a, 0xa0, 0x3c, 0x92, 0x15, 0x83, 0x5c, 0x82, 0x38, 0xff, 0xff, 0x64, 0x8a, 0x21, 0x73, 0x66, 0x5b, 0x83, 0x11, 0x60, 0x9a, 0x81, 0x58, 0xa0, 0x3a, 0x9e, 0x15, 0x43, 0x5a, 0x21, 0x73, 0x68, 0x5b, 0x42, 0x39, 0xfe, 0x7f, 0x05, 0x88, 0xf4, 0x39, 0x87, 0x1a, 0x02, 0x8a, 0x61, 0x5a, 0x16, 0x9e, 0x5b, 0x48, 0x14, 0x98, 0xa0, 0x39, 0x88, 0x1a, 0x23, 0x59, 0x18, 0x11, 0x02, 0x8a, 0x04, 0x62, 0x0d, 0x9e, 0x02, 0xa8, 0xa0, 0x39, 0xa0, 0x1a, 0x23, 0x59, 0xbd, 0x11, 0x07, 0x96, 0xa0, 0x39, 0x94, 0x1a, 0x23, 0x59, 0x24, 0x39, 0xff, 0x00, 0x01, 0x8a, 0x61, 0x5a, 0x04, 0x61, 0x01, 0x40, 0x1c, 0x5a, 0x00, 0x39, 0x01, 0x00, 0x28, 0x59, 0x1a, 0x00, 0x08, 0x58, 0x08, 0x58, 0xd5, 0x3e, +0x40, 0x16, 0x1a, 0x11, 0x03, 0x88, 0xf4, 0x39, 0x4a, 0x1a, 0x23, 0x88, 0x04, 0x62, 0xf4, 0x3e, 0x86, 0x1a, 0x01, 0x8a, 0x19, 0x62, 0x9e, 0x59, 0x20, 0x1d, 0x18, 0x11, 0x13, 0x8a, 0x22, 0x39, 0x68, 0x01, 0x14, 0x8a, 0x9e, 0x5e, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0xc1, 0x06, 0x1b, 0x16, 0x09, 0x88, 0x9e, 0x5e, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0xc1, 0x06, 0x1b, 0x16, 0x02, 0x88, 0x3a, 0x02, 0x05, 0x9e, 0x9e, 0x59, 0xb5, 0x00, 0x1a, 0x11, 0x01, 0x88, 0x3a, 0x02, 0x02, 0x11, 0x0b, 0x96, 0xa0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x14, 0x3a, 0x00, 0x1c, 0x05, 0x88, 0x00, 0x58, 0x84, 0x61, 0x1a, 0x69, 0x30, 0x22, 0x5b, 0x59, 0x19, 0x15, 0x21, 0x74, 0x88, 0x5c, 0x92, 0x60, 0x15, 0x68, 0x9e, 0x61, 0x15, 0x69, 0x00, 0x65, 0x27, 0x76, 0x19, 0x16, 0xc7, 0x38, 0x97, 0x16, 0xa0, 0x3f, 0x70, 0x78, +0x80, 0x16, 0x85, 0x29, 0xe9, 0x5f, 0xff, 0x66, 0xff, 0x6e, 0xd8, 0x49, 0x03, 0x8a, 0x03, 0x5a, 0x5b, 0x59, 0x0c, 0x9e, 0xf4, 0x3b, 0xe3, 0x19, 0x09, 0x8a, 0xa0, 0x3b, 0xa0, 0x1a, 0x63, 0x5b, 0xbd, 0x13, 0x04, 0x82, 0x99, 0x49, 0x02, 0x82, 0x8a, 0x39, 0x01, 0x00, 0x19, 0x00, 0x19, 0x01, 0x19, 0x05, 0x3a, 0x38, 0x9e, 0x58, 0xe3, 0x19, 0x9e, 0x59, 0x84, 0x1a, 0x20, 0x59, 0x20, 0x21, 0xbe, 0x59, 0x4a, 0x1a, 0x14, 0x3a, 0x84, 0x1a, 0xbe, 0x5a, 0xe3, 0x19, 0x16, 0x39, 0x85, 0x1a, 0x20, 0x21, 0xbe, 0x59, 0x87, 0x1a, 0xbe, 0x58, 0x85, 0x1a, 0x01, 0x65, 0x00, 0x66, 0x27, 0x77, 0x19, 0x17, 0xe7, 0x38, 0xea, 0x16, 0x05, 0x27, 0x09, 0x8a, 0xc0, 0x39, 0x88, 0x1a, 0x23, 0x5b, 0x66, 0x5b, 0xb4, 0x3f, 0x4a, 0x1a, 0x01, 0x8a, 0x03, 0xa8, 0x7b, 0x59, 0xc0, 0x39, 0xa0, 0x1a, 0x23, 0x5b, 0x78, 0xfa, +0xc0, 0x16, 0xa2, 0x27, 0x0e, 0x8a, 0xd0, 0x77, 0xf0, 0x3f, 0x20, 0x00, 0xf0, 0x3f, 0xcf, 0x00, 0xc0, 0x3c, 0xd2, 0x15, 0xfc, 0x49, 0x05, 0x98, 0x62, 0x3f, 0x64, 0x00, 0x03, 0x82, 0x19, 0x03, 0x01, 0x9e, 0x00, 0x63, 0x7b, 0x59, 0x05, 0x27, 0x0f, 0x8a, 0xc0, 0x39, 0x94, 0x1a, 0x23, 0x5b, 0x66, 0x5b, 0xc0, 0x3c, 0x92, 0x15, 0x83, 0x5c, 0x92, 0x3f, 0x21, 0x00, 0x04, 0x80, 0x82, 0x3f, 0x00, 0x10, 0x01, 0x82, 0x03, 0xa8, 0x7b, 0x59, 0xa0, 0x27, 0x04, 0x88, 0xc0, 0x39, 0x9e, 0x15, 0xde, 0x59, 0xaa, 0x55, 0xa6, 0x5d, 0x19, 0x06, 0x3a, 0x38, 0x00, 0x67, 0xbe, 0x5f, 0xf1, 0x1e, 0xbe, 0x5f, 0xf3, 0x1e, 0x00, 0x67, 0x01, 0x66, 0xd0, 0x3e, 0xd0, 0x00, 0xd0, 0x3e, 0x1f, 0x00, 0xe3, 0x60, 0x19, 0x68, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x5c, 0x14, 0x20, 0x87, 0x88, 0xe0, 0x38, 0x39, 0x15, 0x2f, 0x8c, +0x00, 0x17, 0x00, 0x61, 0x38, 0x49, 0x45, 0x98, 0x37, 0x9e, 0x95, 0x38, 0x4d, 0x1a, 0xbe, 0x58, 0x4d, 0x1a, 0xe0, 0x38, 0x85, 0x29, 0x09, 0x58, 0x00, 0x61, 0x1c, 0x69, 0x30, 0x22, 0x2c, 0x8a, 0x00, 0x58, 0x30, 0x22, 0x5b, 0x59, 0xe0, 0x3b, 0x13, 0x1c, 0xe0, 0x39, 0x43, 0x1c, 0x23, 0x59, 0x71, 0x13, 0x18, 0x13, 0x02, 0x94, 0x00, 0x63, 0x07, 0x9e, 0x21, 0x72, 0x23, 0x65, 0xa2, 0x40, 0x18, 0x00, 0x78, 0x48, 0x01, 0x9a, 0x01, 0x5b, 0xe0, 0x39, 0x51, 0x15, 0x7b, 0x59, 0xe0, 0x3b, 0x1f, 0x1c, 0xe0, 0x39, 0x4f, 0x1c, 0x23, 0x59, 0x71, 0x13, 0x18, 0x13, 0x02, 0x94, 0x00, 0x63, 0x07, 0x9e, 0x21, 0x72, 0x15, 0x65, 0xa2, 0x40, 0x18, 0x00, 0x78, 0x48, 0x01, 0x9a, 0x01, 0x5b, 0xe0, 0x39, 0x5d, 0x15, 0x7b, 0x59, 0xee, 0x9e, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x51, 0x15, 0x41, 0xd8, 0x40, 0x17, 0x1b, 0x59, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x5d, 0x15, 0x1b, 0x59, 0xe1, 0x9e, 0xe0, 0x38, 0xd2, 0x15, 0x38, 0x49, 0x22, 0x88, 0xd0, 0x71, 0x3b, 0x58, 0x80, 0x5c, 0x4c, 0x61, 0x1a, 0x69, 0x34, 0x20, 0x1b, 0x59, 0x00, 0x62, 0x80, 0x6a, 0xe0, 0x38, 0x51, 0x15, 0xe0, 0x39, 0x5d, 0x15, 0x5b, 0x58, 0x5b, 0x59, 0xe0, 0x38, 0x21, 0x15, 0xe0, 0x39, 0x2d, 0x15, 0xe0, 0x3b, 0x9a, 0x19, 0xe0, 0x3c, 0xa6, 0x19, 0x5b, 0x58, 0x5b, 0x59, 0x5b, 0x5b, 0x5b, 0x5c, 0xe0, 0x38, 0x2b, 0x1c, 0xe0, 0x39, 0x37, 0x1c, 0x5b, 0x58, 0x5b, 0x59, 0xbb, 0x9e, 0xe0, 0x38, 0x73, 0x1c, 0x03, 0x58, 0x39, 0x10, 0x05, 0x94, 0xe0, 0x38, 0x7f, 0x1c, 0x03, 0x58, 0x39, 0x10, 0x19, 0x96, 0xe0, 0x38, 0x9a, 0x19, 0x03, 0x58, 0xe0, 0x3b, 0xa6, 0x19, 0x63, 0x5b, 0xe0, 0x39, 0x51, 0x15, 0x98, 0x01, 0x80, 0x17, 0x1b, 0x59, 0xe0, 0x3d, 0x5d, 0x15, 0x7b, 0x5d, 0xa4, 0x9e, 0x94, 0x38, 0x4d, 0x1a, 0x16, 0x88, 0xe0, 0x38, 0x39, 0x15, 0x00, 0x61, 0x38, 0x49, 0x77, 0x9b, 0xe0, 0x38, 0xd2, 0x15, 0xd8, 0x49, 0xdd, 0x9b, 0xe0, 0x38, 0x21, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x51, 0x15, 0x1b, 0x59, 0xe0, 0x38, 0x2d, 0x15, 0x03, 0x58, 0xe0, 0x39, 0x5d, 0x15, 0x1b, 0x59, 0x8b, 0x9e, 0x94, 0x3d, 0x84, 0x1a, 0x01, 0x88, 0x99, 0x9f, 0x00, 0x60, 0xe0, 0x39, 0x39, 0x15, 0x19, 0x49, 0x36, 0x9a, 0xe0, 0x38, 0x2b, 0x1c, 0x03, 0x58, 0xe0, 0x39, 0x21, 0x15, 0x30, 0x12, 0x01, 0x8c, 0x42, 0x5a, 0xe0, 0x38, 0x37, 0x1c, 0x03, 0x58, 0xe0, 0x39, 0x2d, 0x15, 0x30, 0x13, 0x01, 0x8c, 0x62, 0x5b, 0xd0, 0x75, 0xb0, 0x3d, 0x20, 0x00, 0xb0, 0x3d, 0xcf, 0x00, 0x19, 0x15, 0xe0, 0x38, 0xd2, 0x15, 0xb8, 0x49, 0x58, 0x3b, -0xc0, 0x17, 0x06, 0x88, 0xe0, 0x38, 0x73, 0x1c, 0x5b, 0x58, 0xe0, 0x38, 0x7f, 0x1c, 0x7b, 0x58, 0xe0, 0x38, 0x73, 0x1c, 0x03, 0x5a, 0xe0, 0x38, 0x7f, 0x1c, 0x03, 0x5b, 0x39, 0x12, 0x02, 0x94, 0x39, 0x13, 0xc0, 0x97, 0xe0, 0x39, 0x39, 0x15, 0xe0, 0x38, 0x9a, 0x19, 0x03, 0x58, 0x1b, 0x59, 0xe0, 0x3b, 0xa6, 0x19, 0x63, 0x5b, 0xe0, 0x39, 0x45, 0x15, 0x7b, 0x59, 0x32, 0xd9, 0x19, 0x00, 0x00, 0x61, 0x21, 0x75, 0x5f, 0x38, 0xa8, 0x5d, 0x1c, 0x5d, 0xe2, 0x39, 0x00, 0x00, 0x02, 0x88, 0xbe, 0x58, 0xf1, 0x1e, 0xe2, 0x39, 0x01, 0x00, 0x02, 0x88, 0xbe, 0x58, 0xf3, 0x1e, 0x16, 0x61, 0x01, 0x11, 0x0c, 0x94, 0x01, 0x61, 0x19, 0x48, 0x05, 0x9a, 0x01, 0x11, 0x20, 0x39, 0x07, 0x0b, 0x29, 0x5d, 0x07, 0x9e, 0x07, 0x65, 0x0b, 0x6d, 0xa9, 0x5d, 0x03, 0x9e, 0x1c, 0x65, 0x0b, 0x6d, 0xa9, 0x5d, 0x54, 0x05, +0xc0, 0x17, 0x06, 0x88, 0xe0, 0x38, 0x73, 0x1c, 0x5b, 0x58, 0xe0, 0x38, 0x7f, 0x1c, 0x7b, 0x58, 0xe0, 0x38, 0x73, 0x1c, 0x03, 0x5a, 0xe0, 0x38, 0x7f, 0x1c, 0x03, 0x5b, 0x39, 0x12, 0x02, 0x94, 0x39, 0x13, 0xc0, 0x97, 0xe0, 0x39, 0x39, 0x15, 0xe0, 0x38, 0x9a, 0x19, 0x03, 0x58, 0x1b, 0x59, 0xe0, 0x3b, 0xa6, 0x19, 0x63, 0x5b, 0xe0, 0x39, 0x45, 0x15, 0x7b, 0x59, 0x32, 0xd9, 0x19, 0x00, 0x00, 0x61, 0x21, 0x75, 0x5f, 0x38, 0xa8, 0x5d, 0x1c, 0x5d, 0xe2, 0x39, 0x00, 0x00, 0x02, 0x88, 0xbe, 0x58, 0xf1, 0x1e, 0xe2, 0x39, 0x01, 0x00, 0x02, 0x88, 0xbe, 0x58, 0xf3, 0x1e, 0x16, 0x61, 0x01, 0x11, 0x0c, 0x94, 0x01, 0x61, 0x19, 0x48, 0x05, 0x9a, 0x01, 0x11, 0x20, 0x39, 0x05, 0x0b, 0x29, 0x5d, 0x07, 0x9e, 0x05, 0x65, 0x0b, 0x6d, 0xa9, 0x5d, 0x03, 0x9e, 0x1a, 0x65, 0x0b, 0x6d, 0xa9, 0x5d, 0x4e, 0x05, 0x00, 0x18, 0x9e, 0x5a, 0xcd, 0x04, 0x42, 0x3a, 0x50, 0x00, 0x01, 0x96, 0x1a, 0x05, 0x9e, 0x5a, 0x20, 0x1d, 0x18, 0x12, 0x01, 0x8a, 0x1b, 0x05, 0xa2, 0x3a, 0x01, 0x00, 0x0d, 0x8a, 0xe0, 0x3a, 0x21, 0x15, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0x2f, 0xd8, 0xe0, 0x3a, 0x2d, 0x15, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0x58, 0xd8, 0x0e, 0x9e, 0x00, 0x61, 0x1e, 0x5e, 0x81, 0xd8, 0x3e, 0x5e, 0xe0, 0x39, 0x51, 0x15, 0x1b, 0x59, 0x01, 0x61, 0x1e, 0x5e, 0x81, 0xd8, 0x3e, 0x5e, 0xe0, 0x39, 0x5d, 0x15, 0x1b, 0x59, 0x19, 0x07, 0xf2, 0x39, 0x27, 0x00, 0x98, 0x3d, 0xf7, 0x16, 0x3a, 0x38, 0x1e, 0x5e, 0x1e, 0x58, 0x21, 0x71, 0x23, 0x63, 0x23, 0x40, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x58, 0xa2, 0x3b, 0x01, 0x00, 0x00, 0x61, 0x62, 0x49, 0x01, 0x5b, 0x1c, 0x5d, 0x01, 0x5c, 0x05, 0x40, 0x60, 0x10, 0x64, 0x1b, 0x40, 0x18, 0x0a, 0x8a, 0xd2, 0x39, 0x21, 0x00, 0xe0, 0x38, 0x39, 0x15, 0x03, 0x58, 0x19, 0x48, 0x03, 0x9a, 0x80, 0x10, 0x01, 0x98, 0x19, 0x04, 0x81, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x03, 0x9e, 0x1e, 0x48, 0x01, 0x9a, 0xc1, 0x58, 0xe0, 0x39, 0x51, 0x15, 0x1b, 0x59, 0x3e, 0x5e, 0x3a, 0x38, 0x1e, 0x5e, 0x1e, 0x58, 0x21, 0x71, 0x15, 0x63, 0x23, 0x40, 0x00, 0x3e, 0x00, 0x00, 0x3e, 0x58, 0xa2, 0x3b, 0x01, 0x00, 0x00, 0x61, 0x62, 0x49, 0x01, 0x5b, 0x1c, 0x5d, 0x01, 0x5c, 0x05, 0x40, 0x60, 0x10, 0x0a, 0x8a, 0xd2, 0x39, 0x21, 0x00, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0x19, 0x48, 0x03, 0x9a, 0x80, 0x10, 0x01, 0x98, 0x19, 0x04, 0x81, 0x58, 0x18, 0x10, 0x02, 0x94, 0x00, 0x60, 0x03, 0x9e, 0x1e, 0x48, 0x01, 0x9a, 0xc1, 0x58, 0xe0, 0x39, 0x5d, 0x15, 0x1b, 0x59, 0x3e, 0x5e, 0x9b, 0x65, 0x80, 0x18, 0x3a, 0x38, 0x1e, 0x59, 0x14, 0x60, 0x1e, 0x58, 0xb0, 0xd8, 0x3e, 0x5b, 0xa3, 0x14, 0x10, 0x9a, 0x3e, 0x59, 0x01, 0xac, 0x05, 0x92, 0xe0, 0x3a, 0x21, 0x15, 0xe0, 0x38, 0x39, 0x15, 0x04, 0x9e, 0xe0, 0x3a, 0x2d, 0x15, 0xe0, 0x38, 0x45, 0x15, 0x80, 0x41, 0x62, 0x49, 0x1c, 0x5d, 0x17, 0x9e, 0x1e, 0x75, 0x3e, 0x59, 0x01, 0xac, 0x05, 0x92, 0xe0, 0x3a, 0x21, 0x15, 0xe0, 0x38, 0x39, 0x15, 0x04, 0x9e, 0xe0, 0x3a, 0x2d, 0x15, 0xe0, 0x38, 0x45, 0x15, 0xa2, 0x3b, 0x01, 0x00, 0x00, 0x61, 0x03, 0x58, 0x62, 0x49, 0x06, 0x58, 0x2a, 0x59, 0x1c, 0x5d, 0x19, 0x00, 0x08, 0x58, 0x3a, 0x38, 0xe0, 0x39, 0x21, 0x15, 0x00, 0x65, 0xb9, 0x49, 0x0d, 0x98, 0xe0, 0x38, 0x39, 0x15, 0x23, 0x59, 0x11, 0x12, 0xe0, 0x38, 0x45, 0x15, 0xe0, 0x39, 0x2d, 0x15, 0x23, 0x59, 0x11, 0x13, 0x5a, 0x40, 0x89, 0x98, @@ -96,7 +96,7 @@ 0xc0, 0x19, 0xff, 0x3a, 0x9d, 0x5b, 0x00, 0x64, 0x80, 0x6c, 0x8b, 0x63, 0x1c, 0x6b, 0xff, 0x3a, 0x9d, 0x5b, 0x00, 0x64, 0x80, 0x6c, 0x21, 0x63, 0x15, 0x6b, 0xff, 0x3a, 0x9d, 0x5b, 0x2b, 0x63, 0x1c, 0x6b, 0xff, 0x3a, 0x9d, 0x5b, 0x9e, 0x60, 0x15, 0x68, 0xff, 0x61, 0x7f, 0x69, 0x7f, 0x39, 0x3d, 0x58, 0xbe, 0x58, 0x85, 0x1a, 0x88, 0x61, 0x1a, 0x69, 0x7f, 0x39, 0x1d, 0x59, 0x94, 0x61, 0x1a, 0x69, 0x7f, 0x39, 0x1d, 0x59, 0x13, 0x67, 0x1c, 0x6f, 0x1f, 0x66, 0x1c, 0x6e, 0x00, 0x60, 0x80, 0x68, 0x6f, 0x39, 0xeb, 0x19, 0x1d, 0x5f, 0x1d, 0x5e, 0x00, 0x61, 0xbe, 0x59, 0x00, 0x1c, 0x00, 0x61, 0x7f, 0x69, 0xe6, 0x66, 0x1b, 0x6e, 0x3f, 0x39, 0x3d, 0x5e, 0x00, 0x61, 0xf0, 0x66, 0x1b, 0x6e, 0x3f, 0x39, 0x3d, 0x5e, 0x00, 0x61, 0x30, 0x60, 0x1d, 0x68, 0x04, 0x62, 0x57, 0x38, 0x3d, 0x58, 0xb0, 0x4e, 0x00, 0x1a, 0xa2, 0xf8, 0xf2, 0xdb, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x19, 0x19, 0x17, 0x45, 0x9a, 0x00, 0x67, 0xe0, 0x3d, 0xb2, 0x19, 0xa3, 0x5d, 0xe0, 0x3c, 0xbe, 0x19, 0x83, 0x5c, 0xe0, 0x3e, 0x01, 0x00, 0xc0, 0x3b, 0xb2, 0x19, 0x63, 0x5b, 0xa3, 0x13, 0x01, 0x8c, 0x62, 0x5b, 0x62, 0x3b, 0x40, 0x00, 0x2a, 0x98, 0xc0, 0x3b, 0xbe, 0x19, 0x63, 0x5b, 0x83, 0x13, 0x01, 0x8c, 0x62, 0x5b, 0x62, 0x3b, 0x40, 0x00, 0x21, 0x98, 0xe0, 0x3c, 0xbe, 0x19, 0xc0, 0x3d, 0xbe, 0x19, 0xa3, 0x59, 0x91, 0x01, 0x28, 0x5b, 0x7b, 0x5c, 0xe0, 0x3c, 0xb2, 0x19, 0xc0, 0x3a, 0xb2, 0x19, 0x43, 0x59, 0x91, 0x01, 0x28, 0x5b, 0x7b, 0x5c, 0x9e, 0x59, 0xe2, 0x19, 0x19, 0x11, 0x20, 0x3c, 0xbe, 0x19, 0x83, 0x5c, 0x9b, 0x5d, 0x20, 0x3c, 0xb2, 0x19, 0x83, 0x5c, 0x9b, 0x5a, 0xbe, 0x59, 0xe2, 0x19, 0x22, 0x38, 0xc9, 0x2a, 0x40, 0x1a, 0x01, 0x00, 0x0a, 0x9a, 0xcd, 0x9f, 0x19, 0x06, 0xd2, 0x39, 0xe2, 0x19, 0xc9, 0x97, 0x19, 0x07, 0xf2, 0x38, 0xe2, 0x19, 0x19, 0x00, 0xbc, 0x97, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x19, 0x8a, 0x23, 0x66, 0x21, 0x75, 0xa6, 0x40, 0x00, 0x3e, 0x00, 0x00, 0x15, 0x64, 0xa4, 0x40, 0x00, 0x3d, 0x00, 0x00, 0x19, 0x17, 0xe7, 0x38, 0x69, 0x1a, 0xe0, 0x38, 0xbe, 0x19, 0x03, 0x5a, 0xe0, 0x39, 0xb2, 0x19, 0x23, 0x5b, 0xe0, 0x38, 0xb2, 0x19, 0x5b, 0x58, 0xe0, 0x39, 0xbe, 0x19, 0x7b, 0x59, 0x19, 0x17, 0x3a, 0x38, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5e, 0xe0, 0x3b, 0xde, 0x15, 0x63, 0x5d, 0x00, 0x64, 0x1e, 0x5d, 0xa0, 0x38, 0x48, 0x0e, 0x9e, 0x5b, 0xfd, 0x1b, 0x66, 0x48, 0x98, 0x49, 0x01, 0x94, 0x03, 0x5c, 0xe0, 0x3b, 0xf2, 0x15, 0x75, 0x33, 0x03, 0x8a, 0x19, 0x00, 0x9a, 0xa3, -0x80, 0x1a, 0x19, 0x05, 0xf6, 0x9f, 0x3e, 0x5d, 0xe0, 0x3b, 0x06, 0x16, 0x76, 0x33, 0x02, 0x8a, 0x19, 0x06, 0xe9, 0x9f, 0x3a, 0x38, 0x9e, 0x5f, 0xe4, 0x19, 0xf2, 0x38, 0x27, 0x00, 0x90, 0x94, 0x00, 0x65, 0xe0, 0x3e, 0x63, 0x29, 0xc9, 0x5e, 0xd4, 0x3b, 0xe3, 0x19, 0x85, 0x8a, 0xc0, 0x5e, 0xd4, 0x3b, 0xe3, 0x19, 0xbe, 0x5b, 0xe3, 0x19, 0xb2, 0x38, 0xe4, 0x19, 0x7d, 0x94, 0xa0, 0x3e, 0x63, 0x29, 0xc9, 0x5e, 0xd4, 0x3e, 0xe3, 0x19, 0x75, 0x88, 0xe0, 0x3e, 0x39, 0x15, 0xa0, 0x3c, 0x39, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x45, 0x15, 0xa0, 0x3c, 0x45, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x9a, 0x19, 0xa0, 0x3c, 0x9a, 0x19, 0x20, 0xdb, 0xe0, 0x3e, 0xa6, 0x19, 0xa0, 0x3c, 0xa6, 0x19, 0x20, 0xdb, 0xe0, 0x3e, 0x51, 0x15, 0xa0, 0x3c, 0x51, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x5d, 0x15, 0xa0, 0x3c, 0x18, 0x3f, +0x80, 0x1a, 0x19, 0x05, 0xf6, 0x9f, 0x3e, 0x5d, 0xe0, 0x3b, 0x06, 0x16, 0x76, 0x33, 0x02, 0x8a, 0x19, 0x06, 0xe9, 0x9f, 0x3a, 0x38, 0x9e, 0x5f, 0xe4, 0x19, 0xf2, 0x38, 0x27, 0x00, 0x90, 0x94, 0x00, 0x65, 0xe0, 0x3e, 0x85, 0x29, 0xc9, 0x5e, 0xd4, 0x3b, 0xe3, 0x19, 0x85, 0x8a, 0xc0, 0x5e, 0xd4, 0x3b, 0xe3, 0x19, 0xbe, 0x5b, 0xe3, 0x19, 0xb2, 0x38, 0xe4, 0x19, 0x7d, 0x94, 0xa0, 0x3e, 0x85, 0x29, 0xc9, 0x5e, 0xd4, 0x3e, 0xe3, 0x19, 0x75, 0x88, 0xe0, 0x3e, 0x39, 0x15, 0xa0, 0x3c, 0x39, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x45, 0x15, 0xa0, 0x3c, 0x45, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x9a, 0x19, 0xa0, 0x3c, 0x9a, 0x19, 0x20, 0xdb, 0xe0, 0x3e, 0xa6, 0x19, 0xa0, 0x3c, 0xa6, 0x19, 0x20, 0xdb, 0xe0, 0x3e, 0x51, 0x15, 0xa0, 0x3c, 0x51, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x5d, 0x15, 0xa0, 0x3c, 0x5c, 0x3f, 0xc0, 0x1a, 0x5d, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x21, 0x15, 0xa0, 0x3c, 0x21, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x2d, 0x15, 0xa0, 0x3c, 0x2d, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0xd2, 0x15, 0xa0, 0x3c, 0xd2, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x2b, 0x1c, 0xa0, 0x3c, 0x2b, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x37, 0x1c, 0xa0, 0x3c, 0x37, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x43, 0x1c, 0xa0, 0x3c, 0x43, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x4f, 0x1c, 0xa0, 0x3c, 0x4f, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x5b, 0x1c, 0xa0, 0x3c, 0x5b, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x67, 0x1c, 0xa0, 0x3c, 0x67, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x07, 0x1c, 0xa0, 0x3c, 0x07, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x73, 0x1c, 0xa0, 0x3c, 0x73, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x7f, 0x1c, 0xa0, 0x3c, 0x7f, 0x1c, 0x20, 0xdb, 0xe0, 0x3e, 0x88, 0x1a, 0xc3, 0xf1, 0x00, 0x1b, 0xa0, 0x3c, 0x88, 0x1a, 0x20, 0xdb, 0xe0, 0x3e, 0x94, 0x1a, 0xa0, 0x3c, 0x94, 0x1a, 0x20, 0xdb, 0xe0, 0x3e, 0xa0, 0x1a, 0xa0, 0x3c, 0xa0, 0x1a, 0x20, 0xdb, 0xe0, 0x3e, 0x92, 0x15, 0xa0, 0x3c, 0x92, 0x15, 0x20, 0xdb, 0xe0, 0x3e, 0x9e, 0x15, 0xa0, 0x3c, 0x9e, 0x15, 0x20, 0xdb, 0x19, 0x05, 0x02, 0x9e, 0x19, 0x05, 0x80, 0x9f, 0x19, 0x07, 0xf2, 0x38, 0x27, 0x00, 0x71, 0x97, 0x3a, 0x38, 0xc3, 0x5b, 0x83, 0x5a, 0x7b, 0x5c, 0x5b, 0x5e, 0x3a, 0x38, 0x00, 0x67, 0x00, 0x61, 0xe0, 0x38, 0x9a, 0x19, 0x38, 0x49, 0xa4, 0x98, 0xe0, 0x38, 0x39, 0x15, 0x38, 0x49, 0xa0, 0x98, 0x27, 0x76, 0x19, 0x16, 0xdf, 0x48, 0x9a, 0x8a, 0x00, 0x61, 0xc0, 0x38, 0x9a, 0x19, 0x38, 0x49, 0x95, 0x98, 0xc0, 0x38, 0x39, 0x15, 0x38, 0x49, 0x91, 0x98, 0xe0, 0x3a, 0x9a, 0x19, 0xe0, 0x3b, 0x39, 0x15, 0xf3, 0x5f, 0x40, 0x1b, 0x63, 0x5b, 0x53, 0x12, 0xe0, 0x3b, 0xa6, 0x19, 0xe0, 0x3c, 0x45, 0x15, 0x83, 0x5c, 0x74, 0x13, 0xc0, 0x3c, 0x9a, 0x19, 0xe0, 0x3d, 0x39, 0x15, 0xa3, 0x5d, 0x95, 0x14, 0xc0, 0x3d, 0xa6, 0x19, 0xe0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xb0, 0x15, 0x5d, 0x40, 0x6c, 0x48, 0x21, 0x5c, 0xc0, 0x3d, 0x39, 0x15, 0xe0, 0x39, 0x39, 0x15, 0x23, 0x59, 0xb1, 0x15, 0xc0, 0x38, 0x45, 0x15, 0xe0, 0x39, 0x45, 0x15, 0x23, 0x59, 0x11, 0x10, 0x58, 0x40, 0x6d, 0x48, 0x81, 0x31, 0x79, 0xac, 0x65, 0x90, 0xc0, 0x3a, 0x9a, 0x19, 0xc0, 0x3b, 0x39, 0x15, 0x63, 0x5b, 0x53, 0x12, 0xc0, 0x3b, 0xa6, 0x19, 0xc0, 0x3c, 0x45, 0x15, 0x83, 0x5c, 0x74, 0x13, 0xe0, 0x3c, 0x9a, 0x19, 0xc0, 0x3d, 0x39, 0x15, 0xa3, 0x5d, 0x95, 0x14, 0xe0, 0x3d, 0xa6, 0x19, 0xc0, 0x38, 0x45, 0x15, 0x03, 0x58, 0xb0, 0x15, 0x27, 0x1c, @@ -134,50 +134,50 @@ 0x40, 0x23, 0x60, 0x11, 0x83, 0x5a, 0xff, 0x63, 0xff, 0x6b, 0xbe, 0x5b, 0x60, 0x1a, 0x00, 0x63, 0x5b, 0x48, 0x14, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0x7f, 0xbe, 0x5d, 0x60, 0x1a, 0x41, 0x59, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x22, 0x01, 0x00, 0x62, 0x10, 0x6a, 0x3a, 0x48, 0x02, 0x9c, 0x00, 0x61, 0x10, 0x69, 0x5e, 0x14, 0x19, 0x14, 0x83, 0x5a, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0x7f, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xbf, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x14, 0x83, 0x5a, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0xfe, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x04, 0xd3, 0xe2, 0x80, 0x23, 0x19, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xdf, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xf7, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x04, 0x83, 0x5a, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0xf7, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x14, 0x1a, 0x14, 0x83, 0x5a, 0x22, 0x01, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xef, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x14, 0x83, 0x5a, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0xfb, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x04, 0x5e, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0x78, 0xcd, 0xc0, 0x23, 0xa4, 0x3d, 0xfb, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x19, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xfd, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x04, 0x83, 0x5a, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xff, 0xfd, 0xbe, 0x5d, 0x60, 0x1a, 0x5e, 0x14, 0x19, 0x04, 0x83, 0x5a, 0x22, 0x01, 0x5b, 0x48, 0x06, 0x88, 0x9e, 0x5d, 0x60, 0x1a, 0xa4, 0x3d, 0xfe, 0xff, 0xbe, 0x5d, 0x60, 0x1a, 0x1e, 0x58, 0x08, 0x65, 0x21, 0x58, 0x00, 0x61, 0x1c, 0x5d, 0x01, 0x59, 0x3e, 0x58, 0x00, 0x65, 0xbe, 0x5d, 0x61, 0x1a, 0x9e, 0x5d, 0x60, 0x1a, 0x35, 0xac, 0x02, 0x92, 0x45, 0xac, 0x0d, 0x90, 0x0d, 0xac, 0x02, 0x92, 0x4d, 0xac, 0x09, 0x90, 0x25, 0xac, 0x02, 0x92, 0x55, 0xac, 0x05, 0x90, 0x1d, 0xac, 0x06, 0x92, 0x08, 0x8d, -0x00, 0x24, 0x5d, 0xac, 0x01, 0x90, 0x03, 0x9e, 0x01, 0x65, 0xbe, 0x5d, 0x61, 0x1a, 0x9e, 0x5c, 0x02, 0x1d, 0x19, 0x04, 0xbe, 0x5c, 0x02, 0x1d, 0x00, 0x3c, 0x48, 0x0e, 0x83, 0x5b, 0x9e, 0x5d, 0x61, 0x1a, 0x05, 0xac, 0x0c, 0x92, 0x61, 0x12, 0x7a, 0xac, 0x09, 0x90, 0x3b, 0x5c, 0x01, 0x62, 0xbe, 0x5a, 0x62, 0x1a, 0x9e, 0x5a, 0x03, 0x1d, 0x19, 0x02, 0xbe, 0x5a, 0x03, 0x1d, 0x3e, 0x5b, 0x19, 0x13, 0x00, 0x62, 0x62, 0x14, 0x0e, 0x89, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x72, 0x62, 0x19, 0x6a, 0x86, 0x63, 0x19, 0x6b, 0x00, 0x60, 0xbe, 0x58, 0x71, 0x1a, 0x00, 0x67, 0x00, 0x60, 0x9e, 0x59, 0x58, 0x1a, 0x38, 0x48, 0x33, 0x8a, 0x19, 0x11, 0x27, 0x38, 0x6f, 0x24, 0xe2, 0x85, -0x40, 0x24, 0x40, 0x04, 0x83, 0x5d, 0x48, 0x64, 0x1d, 0x6c, 0x85, 0x04, 0x83, 0x5d, 0x15, 0x66, 0xbe, 0x48, 0x09, 0x82, 0x19, 0x04, 0x83, 0x5d, 0xbe, 0x48, 0x05, 0x82, 0x1a, 0x14, 0x83, 0x5d, 0xbe, 0x48, 0x01, 0x82, 0x13, 0x9e, 0x60, 0x04, 0x83, 0x5d, 0x48, 0x64, 0x1d, 0x6c, 0x85, 0x04, 0x90, 0x3c, 0xb8, 0x00, 0x83, 0x5d, 0x15, 0x66, 0xbe, 0x48, 0x10, 0x82, 0x19, 0x04, 0x83, 0x5d, 0xbe, 0x48, 0x0c, 0x82, 0x1a, 0x14, 0x83, 0x5d, 0xbe, 0x48, 0x08, 0x82, 0x19, 0x07, 0xbe, 0x5f, 0x71, 0x1a, 0x72, 0x65, 0x1a, 0x6d, 0xa7, 0x06, 0x19, 0x16, 0x1b, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x19, 0x00, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x67, 0xdf, 0x60, 0x1e, 0x68, 0x2f, 0x39, 0x80, 0x24, 0xfd, 0x58, 0x1a, 0x38, 0x47, 0xcf, -0x80, 0x24, 0x1a, 0x38, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x9e, 0x5c, 0xb8, 0x00, 0x9e, 0x5e, 0xb9, 0x00, 0x86, 0x04, 0x19, 0x14, 0x87, 0x38, 0x8e, 0x24, 0xfd, 0x5d, 0x1a, 0x38, 0x1a, 0x38, 0xbe, 0x5f, 0xdb, 0x1e, 0xbe, 0x5f, 0xdc, 0x1e, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x01, 0x00, 0x02, 0x3a, 0xb0, 0x00, 0x01, 0x98, 0x3a, 0x38, 0x00, 0x61, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x5a, 0xdd, 0x1e, 0x1c, 0x5a, 0x02, 0x39, 0x20, 0x00, 0x01, 0x98, 0x20, 0x60, 0x00, 0x61, 0x01, 0x62, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x48, 0x63, 0x1d, 0x6b, 0x9e, 0x5c, 0xb8, 0x00, 0x19, 0x14, 0x87, 0x38, 0xc9, 0x24, 0x65, 0x5c, 0x98, 0x48, 0x06, 0x80, 0x5b, 0x5d, 0xbe, 0x5a, 0xdb, 0x1e, 0x19, 0x01, 0x01, 0x67, 0x0e, 0x9e, 0x07, 0xac, 0x0c, 0x90, 0x1e, 0x5d, 0x40, 0x3d, 0xdf, 0x1e, 0x26, 0xad, -0xc0, 0x24, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x01, 0x8a, 0x3b, 0x5d, 0x3e, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x19, 0x02, 0x19, 0x05, 0x1e, 0x5d, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x01, 0x8a, 0x3b, 0x5d, 0x3e, 0x5d, 0x00, 0x61, 0x9e, 0x58, 0x4f, 0x04, 0x9e, 0x5a, 0xdd, 0x1e, 0x1c, 0x5a, 0x02, 0x39, 0x20, 0x00, 0x01, 0x98, 0x20, 0x60, 0x00, 0x61, 0x01, 0x62, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x48, 0x63, 0x1d, 0x6b, 0x9e, 0x5c, 0xb8, 0x00, 0xa4, 0x05, 0x64, 0x03, 0x9e, 0x5c, 0xb9, 0x00, 0x19, 0x14, 0x87, 0x38, 0x09, 0x25, 0x65, 0x5c, 0x98, 0x48, 0x06, 0x80, 0x5b, 0x5d, 0xbe, 0x5a, 0xdc, 0x1e, 0x19, 0x01, 0x01, 0x67, 0x13, 0x9e, 0x07, 0xac, 0x11, 0x90, 0x1e, 0x5d, 0x1e, 0x5e, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x04, 0x8a, 0xf1, 0xf0, -0x00, 0x25, 0xa3, 0x5e, 0xfe, 0x59, 0xc1, 0x06, 0xdb, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x19, 0x02, 0x19, 0x05, 0x1e, 0x5d, 0x1e, 0x5e, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x04, 0x8a, 0xa3, 0x5e, 0xfe, 0x59, 0xc1, 0x06, 0xdb, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x00, 0x60, 0xbe, 0x58, 0xe8, 0x1e, 0xbe, 0x58, 0xe7, 0x1e, 0xdf, 0x62, 0x1e, 0x6a, 0x01, 0x67, 0xef, 0x38, 0x2a, 0x25, 0x45, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0x78, 0x48, 0x02, 0x96, 0x61, 0x58, 0xe1, 0x5c, 0x19, 0x07, 0x1a, 0x38, 0xbe, 0x5c, 0xe7, 0x1e, 0xdf, 0x62, 0x1e, 0x6a, 0x01, 0x67, 0x00, 0x60, 0xef, 0x38, 0x3c, 0x25, 0x45, 0x5b, 0xfe, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0x78, 0x48, 0x02, 0x96, 0x61, 0x58, 0xe1, 0x5d, 0x19, 0x07, 0x1a, 0x38, 0xbe, 0x5d, 0xe8, 0x1e, 0x7a, 0x60, 0xf0, 0x02, -0x40, 0x25, 0x02, 0x68, 0x50, 0x61, 0x04, 0x69, 0x39, 0x62, 0x47, 0x38, 0x49, 0x25, 0x23, 0x5b, 0x7b, 0x58, 0x19, 0x01, 0x19, 0x00, 0x3a, 0x38, 0x92, 0x62, 0xf8, 0x6a, 0x00, 0x64, 0x17, 0x63, 0x67, 0x38, 0x53, 0x25, 0x45, 0x5b, 0x83, 0x04, 0x1a, 0x38, 0xfe, 0x5c, 0x84, 0x3c, 0x00, 0xff, 0x9e, 0x5f, 0x34, 0x1d, 0xe0, 0x3b, 0x30, 0x1d, 0x9e, 0x59, 0xb5, 0x00, 0x24, 0x29, 0x3b, 0x5b, 0x30, 0x63, 0x1d, 0x6b, 0x00, 0x60, 0xbe, 0x58, 0x36, 0x1d, 0x04, 0x65, 0x19, 0x15, 0xa7, 0x38, 0x6c, 0x25, 0x63, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0x06, 0x00, 0x19, 0x03, 0x19, 0x05, 0x00, 0x61, 0x1c, 0x5d, 0xbe, 0x58, 0x35, 0x1d, 0x30, 0x63, 0x1d, 0x6b, 0x04, 0x65, 0x19, 0x15, 0xa7, 0x38, 0x7d, 0x25, 0x63, 0x5e, 0xc4, 0x3e, 0x00, 0xff, 0xfe, 0x5e, 0x06, 0x00, 0x19, 0x03, 0x19, 0x05, 0x00, 0x61, 0x85, 0x3d, -0x80, 0x25, 0x1c, 0x5d, 0x01, 0x5b, 0xbe, 0x58, 0xbc, 0x1d, 0x9e, 0x58, 0x35, 0x1d, 0x19, 0x07, 0xe2, 0x3a, 0x04, 0x00, 0x01, 0x88, 0x00, 0x67, 0xbe, 0x5f, 0x34, 0x1d, 0x01, 0x61, 0x9e, 0x5a, 0xb1, 0x04, 0x42, 0x3f, 0x01, 0x00, 0x11, 0x8a, 0x01, 0x61, 0x02, 0x3f, 0x04, 0x00, 0x0d, 0x9a, 0x04, 0x61, 0x02, 0x3f, 0x06, 0x00, 0x09, 0x9a, 0x02, 0x61, 0x02, 0x3f, 0x08, 0x00, 0x05, 0x9a, 0x03, 0x61, 0x02, 0x3f, 0x0a, 0x00, 0x01, 0x9a, 0x01, 0x61, 0xbe, 0x59, 0x36, 0x1d, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x63, 0x00, 0x65, 0x9c, 0x60, 0x1e, 0x68, 0x9e, 0x59, 0xb8, 0x00, 0x19, 0x11, 0x27, 0x38, 0xbd, 0x25, 0x03, 0x5a, 0x5b, 0x48, 0x01, 0x96, 0x41, 0x5b, 0x19, 0x00, 0x1a, 0x38, 0xbe, 0x5b, 0x60, 0x1e, 0xe3, 0x52, -0xc0, 0x25, 0x9e, 0x59, 0xb9, 0x00, 0x19, 0x11, 0x27, 0x38, 0xca, 0x25, 0x03, 0x5a, 0x5d, 0x48, 0x01, 0x96, 0x41, 0x5d, 0x19, 0x00, 0x1a, 0x38, 0xbe, 0x5d, 0x5f, 0x1e, 0x10, 0x64, 0x65, 0x02, 0x50, 0x48, 0x00, 0x01, 0x0b, 0x80, 0x61, 0x58, 0x7d, 0x48, 0x01, 0x98, 0xa1, 0x58, 0x01, 0x5c, 0x00, 0x61, 0x07, 0x62, 0x82, 0x40, 0x0a, 0x62, 0x1c, 0x5a, 0x01, 0x5c, 0xbe, 0x5c, 0x61, 0x1e, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x10, 0x48, 0x05, 0x00, 0x18, 0x3e, 0x34, 0x27, 0x9e, 0x58, 0xdb, 0x1e, 0x10, 0x48, 0x02, 0x00, 0x18, 0x3e, 0x34, 0x27, 0x9e, 0x59, 0xdc, 0x1e, 0x30, 0x48, 0x02, 0x00, 0x18, 0x3e, 0x34, 0x27, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x50, 0x01, 0xa4, 0xf1, -0x00, 0x26, 0x3d, 0x98, 0xdf, 0x60, 0x1e, 0x68, 0x05, 0x59, 0x24, 0x3a, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3b, 0xff, 0x00, 0x43, 0x06, 0x03, 0x59, 0x24, 0x3c, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3d, 0xff, 0x00, 0x85, 0x07, 0xc7, 0x00, 0x38, 0x10, 0x2a, 0x98, 0xd0, 0x48, 0x06, 0x00, 0x27, 0x98, 0xf0, 0x48, 0x06, 0x00, 0x24, 0x98, 0x45, 0x00, 0x10, 0x48, 0x06, 0x00, 0x20, 0x98, 0x64, 0x00, 0x10, 0x48, 0x06, 0x00, 0x1c, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x98, 0x21, 0x58, 0x9e, 0x59, 0x44, 0x04, 0x19, 0x48, 0x10, 0x80, 0x9e, 0x58, 0xf1, 0x04, 0x19, 0x10, 0x04, 0x88, 0x9e, 0x58, 0x8a, 0x04, 0x1a, 0x10, 0x09, 0x98, 0x9e, 0x58, 0xf2, 0x04, 0x19, 0x10, 0x04, 0x88, 0x9e, 0x58, 0x8b, 0x04, 0x1a, 0x10, 0x01, 0x98, 0xf5, 0x9e, 0x9e, 0x59, 0x4e, 0x04, 0xca, 0x25, -0x40, 0x26, 0x30, 0x48, 0x00, 0x00, 0x84, 0x8a, 0x9e, 0x59, 0x4e, 0x04, 0x30, 0x48, 0x23, 0x00, 0x7f, 0x8a, 0x9e, 0x59, 0x4c, 0x04, 0x30, 0x48, 0x00, 0x00, 0x7a, 0x8a, 0x9e, 0x59, 0x4c, 0x04, 0x30, 0x48, 0x15, 0x00, 0x75, 0x8a, 0x9e, 0x58, 0x46, 0x04, 0x9e, 0x59, 0x47, 0x04, 0x01, 0x00, 0x02, 0x38, 0x40, 0x00, 0x08, 0x98, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x02, 0x39, 0x02, 0x00, 0x12, 0x8a, 0x9e, 0x58, 0x46, 0x04, 0x38, 0x10, 0x61, 0x98, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1b, 0x10, 0x5a, 0x88, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x10, 0x54, 0x8a, 0x22, 0x9e, 0x80, 0x60, 0x01, 0x68, 0xbe, 0x58, 0x20, 0x1d, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x9a, 0x21, 0x58, 0xbe, 0x58, 0xb4, 0xd7, -0x80, 0x26, 0x14, 0x1f, 0x36, 0xe7, 0x00, 0x63, 0xbe, 0x5b, 0x0e, 0x1f, 0xbe, 0x5b, 0x10, 0x1f, 0x9e, 0x5b, 0xb8, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xb9, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x11, 0x1f, 0x01, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x98, 0xe2, 0x9d, 0x9e, 0x9e, 0x58, 0x46, 0x04, 0x9e, 0x59, 0x47, 0x04, 0x19, 0x48, 0x97, 0x98, 0x68, 0x60, 0x01, 0x68, 0xbe, 0x58, 0x20, 0x1d, 0x76, 0xde, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x9a, 0x21, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0e, 0x1f, 0xbe, 0x5b, 0x10, 0x1f, 0x9e, 0x5b, 0xb8, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xb9, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x11, 0x1f, 0x01, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x01, 0x60, 0x02, 0x61, 0x5c, 0xe7, 0x67, 0x7e, -0xc0, 0x26, 0x02, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x02, 0x60, 0x02, 0x61, 0x5c, 0xe7, 0x6c, 0x9e, 0x0c, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x79, 0xe4, 0xdf, 0x60, 0x1e, 0x68, 0x05, 0x59, 0x24, 0x3a, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3b, 0xff, 0x00, 0x43, 0x06, 0x03, 0x59, 0x24, 0x3c, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3d, 0xff, 0x00, 0x85, 0x07, 0xd0, 0x48, 0x0f, 0x00, 0x04, 0x98, 0xf0, 0x48, 0x0f, 0x00, 0x01, 0x98, 0x04, 0x9e, 0x04, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x79, 0xe4, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1a, 0x10, 0x0b, 0x88, 0x60, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1c, 0x10, 0x3d, 0x88, 0x3b, 0x9e, 0x66, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x4e, 0xe8, 0x01, 0x60, 0x01, 0x61, 0x9d, 0xe7, 0x9e, 0x58, 0x39, 0x2e, -0x00, 0x27, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x01, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x01, 0x60, 0x02, 0x61, 0x9d, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x01, 0x60, 0x02, 0x61, 0x5c, 0xe7, 0x02, 0x60, 0x01, 0x61, 0x9d, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x02, 0x60, 0x01, 0x61, 0x5c, 0xe7, 0x02, 0x60, 0x02, 0x61, 0x9d, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x02, 0x60, 0x02, 0x61, 0x5c, 0xe7, 0x06, 0x71, 0x09, 0xac, 0x0c, 0x92, 0x01, 0xac, 0x0a, 0x92, 0x51, 0xac, 0x08, 0x92, 0x9e, 0x58, 0x20, 0x1d, 0x00, 0x61, 0x19, 0x48, 0x03, 0x8a, 0x01, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x98, 0xe2, 0x1a, 0x38, 0x3a, 0x38, 0x9e, 0x58, 0xb8, 0x00, 0x1b, 0x10, 0x7a, 0x61, 0x02, 0x69, 0x45, 0xe7, 0x9e, 0x58, 0xb9, 0x00, 0x1b, 0x10, 0x7a, 0x61, 0x55, 0x69, -0x40, 0x27, 0x02, 0x69, 0x30, 0x39, 0xb8, 0x00, 0x45, 0xe7, 0x3a, 0x38, 0x19, 0x01, 0x00, 0x66, 0x07, 0x38, 0x5a, 0x27, 0x23, 0x5a, 0x18, 0x12, 0x08, 0x8a, 0x18, 0x16, 0x04, 0x88, 0x21, 0x5b, 0x19, 0x13, 0x01, 0x64, 0x9b, 0x5b, 0x01, 0x66, 0x06, 0x9e, 0x18, 0x16, 0x04, 0x8a, 0x21, 0x5b, 0x01, 0x64, 0x9b, 0x5b, 0x00, 0x66, 0x19, 0x01, 0x3a, 0x38, 0xbe, 0x58, 0x82, 0x1d, 0xbe, 0x59, 0x83, 0x1d, 0x9e, 0x5e, 0x10, 0x1f, 0x9e, 0x5f, 0x0e, 0x1f, 0x7a, 0x63, 0x02, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x9e, 0x59, 0x82, 0x1d, 0x79, 0x48, 0x26, 0x88, 0x48, 0x63, 0x1d, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x18, 0x13, 0x20, 0x8a, 0x7a, 0x62, 0x02, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x83, 0x1d, 0x59, 0x48, 0x16, 0x88, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0xdc, 0xac, -0x80, 0x27, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x61, 0x58, 0x43, 0x40, 0x9e, 0x5d, 0x14, 0x1f, 0x1c, 0x5d, 0x01, 0x5d, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x48, 0x64, 0x0e, 0x6c, 0x80, 0x04, 0xbb, 0x5c, 0x19, 0x07, 0x9e, 0x5a, 0x0f, 0x1f, 0xfa, 0x48, 0xcd, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0x11, 0x1f, 0xda, 0x48, 0xc6, 0x9d, 0x3a, 0x38, 0x9e, 0x5b, 0xb8, 0x00, 0xbe, 0x5b, 0x0e, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xb9, 0x00, 0xbe, 0x5b, 0x10, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x11, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0d, 0x1f, 0x01, 0x63, 0xbe, 0x5b, 0x12, 0x1f, 0xbe, 0x5b, 0x13, 0x1f, 0x00, 0x63, 0x00, 0x65, 0xbe, 0x58, 0x00, 0x1d, 0xbe, 0x59, 0x04, 0x1d, 0x00, 0x66, 0x00, 0x67, 0x7a, 0x62, 0x02, 0x6a, 0x47, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x6d, 0xf0, -0xc0, 0x27, 0x00, 0x1d, 0x59, 0x48, 0x5a, 0x88, 0x7a, 0x62, 0x02, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x04, 0x1d, 0x59, 0x48, 0x50, 0x88, 0x48, 0x62, 0x1d, 0x6a, 0x47, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x12, 0x1f, 0x59, 0x48, 0x02, 0x9a, 0xbe, 0x5a, 0x12, 0x1f, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x13, 0x1f, 0x59, 0x48, 0x02, 0x9a, 0xbe, 0x5a, 0x13, 0x1f, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x48, 0x64, 0x0e, 0x6c, 0x80, 0x04, 0x83, 0x59, 0x79, 0xac, 0x2f, 0x92, 0x10, 0x60, 0x38, 0x48, 0x2c, 0x9a, 0x9e, 0x58, 0x0e, 0x1f, 0xf8, 0x48, 0x07, 0x98, 0xbe, 0x5f, 0x0e, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x0f, 0x1f, 0xf8, 0x48, 0x07, 0x80, 0x4c, 0x0e, -0x00, 0x28, 0xbe, 0x5f, 0x0f, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x10, 0x1f, 0xd8, 0x48, 0x07, 0x98, 0xbe, 0x5e, 0x10, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x11, 0x1f, 0xd8, 0x48, 0x07, 0x80, 0xbe, 0x5e, 0x11, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x19, 0x07, 0x9e, 0x5a, 0xb8, 0x00, 0x19, 0x12, 0xfa, 0x48, 0x98, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0xb9, 0x00, 0x19, 0x12, 0xda, 0x48, 0x91, 0x9d, 0x9e, 0x58, 0x12, 0x1f, 0x9e, 0x59, 0x13, 0x1f, 0x38, 0x48, 0x01, 0x98, 0x21, 0x58, 0x9e, 0x5e, 0x4d, 0x04, 0x9e, 0x5f, 0x4f, 0x04, 0xc7, 0x06, 0xc2, 0x3e, 0x00, 0x06, 0x04, 0x80, 0x02, 0x39, 0x40, 0x01, 0x01, 0x98, 0x10, 0x60, 0x02, 0x39, 0x80, 0x03, 0x02, 0x80, 0x08, 0x59, 0x3f, 0xc2, -0x40, 0x28, 0x01, 0x00, 0x9e, 0x5e, 0x12, 0x1f, 0x9e, 0x5f, 0x13, 0x1f, 0xc7, 0x06, 0xc2, 0x3e, 0x00, 0x02, 0x02, 0x98, 0x08, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x3a, 0x38, 0x00, 0x62, 0x7a, 0x67, 0x02, 0x6f, 0x16, 0x60, 0xe5, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x69, 0xe8, 0x19, 0x02, 0x19, 0x10, 0x18, 0x10, 0xf8, 0x89, 0x00, 0x62, 0x7a, 0x67, 0x02, 0x6f, 0x16, 0x66, 0xe6, 0x07, 0x24, 0x66, 0xe5, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x76, 0xe8, 0x19, 0x02, 0x19, 0x16, 0x18, 0x16, 0xf8, 0x89, 0x3a, 0x38, 0x00, 0x64, 0x48, 0x63, 0x0e, 0x6b, 0x62, 0x03, 0x16, 0x65, 0x24, 0x66, 0x19, 0x16, 0xc7, 0x38, 0x74, 0x28, 0x9b, 0x5b, 0x65, 0x03, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x64, 0x16, 0x65, 0x48, 0x63, 0x0e, 0x6b, 0x00, 0x61, 0x00, 0x60, 0x45, 0x40, 0x03, 0x03, 0x16, 0x65, 0x19, 0x15, 0x8d, 0xc6, -0x80, 0x28, 0xa7, 0x38, 0x84, 0x28, 0x9d, 0x5b, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x48, 0x60, 0x1d, 0x68, 0x9c, 0x61, 0x1e, 0x69, 0x9e, 0x5b, 0x4c, 0x04, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x8a, 0x9e, 0x5b, 0x4c, 0x04, 0x70, 0x48, 0x01, 0x00, 0x0f, 0x8a, 0x70, 0x48, 0x14, 0x00, 0x15, 0x8a, 0x70, 0x48, 0x15, 0x00, 0x1b, 0x8a, 0x23, 0x9e, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xa1, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x23, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xaa, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xb3, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x11, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xbc, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x08, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x7e, 0xc4, -0xc0, 0x28, 0x23, 0x01, 0x8f, 0x38, 0xc5, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x48, 0x60, 0x1d, 0x68, 0x10, 0x38, 0xb8, 0x00, 0x9c, 0x61, 0x1e, 0x69, 0x30, 0x39, 0xb8, 0x00, 0x9e, 0x5b, 0x4e, 0x04, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x8a, 0x9e, 0x5b, 0x4e, 0x04, 0x70, 0x48, 0x01, 0x00, 0x0f, 0x8a, 0x70, 0x48, 0x22, 0x00, 0x15, 0x8a, 0x70, 0x48, 0x23, 0x00, 0x1b, 0x8a, 0x23, 0x9e, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xe5, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x23, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xee, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xf7, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x11, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x00, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1c, 0x38, -0x00, 0x29, 0x1a, 0x38, 0x08, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x8f, 0x38, 0x09, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x66, 0x00, 0x67, 0x9c, 0x63, 0x1e, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x18, 0x13, 0x24, 0x8a, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x59, 0x48, 0x1b, 0x8a, 0x9c, 0x62, 0x1e, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x61, 0x58, 0x43, 0x40, 0x9e, 0x5d, 0x61, 0x1e, 0x1c, 0x5d, 0x01, 0x5d, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x80, 0x04, 0x48, 0x63, 0x0e, 0x6b, 0x60, 0x03, 0xbb, 0x5c, 0xbb, 0x5b, 0x0e, 0x9e, 0xae, 0xcd, -0x40, 0x29, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x80, 0x04, 0x48, 0x63, 0x0e, 0x6b, 0x60, 0x03, 0x00, 0x65, 0xbb, 0x5c, 0xbb, 0x5b, 0x19, 0x07, 0x9e, 0x5a, 0xb8, 0x00, 0x19, 0x12, 0xfa, 0x48, 0xc2, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0xb9, 0x00, 0x19, 0x12, 0xda, 0x48, 0xbb, 0x9d, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0xe0, 0xac, 0x98, 0x3c, 0x99, 0x2a, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xfe, 0x97, -0x80, 0x29, 0x00, 0xbc, 0xbc, 0x00, 0x78, 0xa8, 0x70, 0xa8, 0x00, 0xbd, 0xbc, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x38, 0xa8, 0x70, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0xbc, 0x1c, 0x00, 0x78, 0xaa, 0x00, 0xbd, 0x1c, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xaa, 0x00, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x1d, 0xb0, 0x38, 0xa8, 0x40, 0xa8, 0x48, 0xa8, 0x9d, 0xb0, 0x9a, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0x5e, 0x00, 0xbe, 0x58, 0x5f, 0x00, 0xbe, 0x58, 0x60, 0x00, 0xbe, 0x58, 0x61, 0x00, 0x3e, 0xb0, 0x70, 0xaa, 0x78, 0xaa, 0xbe, 0xb0, 0x30, 0xb0, 0xbe, 0x58, 0x2a, 0x1d, 0x31, 0xb0, 0xbe, 0x58, 0x2b, 0x1d, 0x33, 0xb0, 0xbe, 0x58, 0x2c, 0x1d, 0x34, 0xb0, 0xbe, 0x58, 0x2d, 0x1d, 0xff, 0x13, -0xc0, 0x29, 0x00, 0x60, 0x00, 0xbd, 0x31, 0x00, 0x00, 0x60, 0x00, 0xbd, 0x05, 0x00, 0x00, 0xbc, 0x34, 0x00, 0x00, 0x60, 0x00, 0xbd, 0x34, 0x00, 0x00, 0xbc, 0x30, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x30, 0x00, 0x00, 0xbc, 0x04, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x04, 0x00, 0x00, 0xbc, 0x33, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x31, 0x83, -0x00, 0x2a, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x33, 0x00, 0x9e, 0x58, 0xc3, 0x1d, 0x06, 0x38, 0xaa, 0x55, 0x02, 0x8a, 0x42, 0xa9, 0x8b, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xab, 0x62, 0x60, 0xb1, 0x68, 0xef, 0xb0, 0x12, 0xa9, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0xbc, 0x04, 0x00, 0x38, 0xa8, 0x00, 0xbd, 0x04, 0x00, 0x9e, 0x58, 0x2a, 0x1d, 0xb0, 0xb0, 0x9e, 0x58, 0x2b, 0x1d, 0xb1, 0xb0, 0x9e, 0x58, 0x2c, 0x1d, 0xb3, 0xb0, 0x9e, 0x58, 0x2d, 0x1d, 0xb4, 0xb0, 0x9a, 0xac, 0xfe, 0x91, 0x9e, 0x58, 0x5e, 0x00, 0x02, 0x38, 0x54, 0x00, 0x03, 0x8a, 0xb2, 0xac, 0xfe, 0x93, 0x81, 0x9f, 0xe0, 0xac, 0x7f, 0x91, 0x9a, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x1d, 0xd5, -0x40, 0x2a, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0xbc, 0xbc, 0x00, 0x78, 0xaa, 0x70, 0xaa, 0x00, 0xbd, 0xbc, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x38, 0xaa, 0x70, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0xbc, 0x1c, 0x00, 0x78, 0xa8, 0x00, 0xbd, 0x1c, 0x00, 0x3e, 0xb0, 0x70, 0xa8, 0x78, 0xa8, 0xbe, 0xb0, 0x19, 0x38, 0x8c, 0x50, 0x00, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0xea, 0x60, 0x2f, 0x68, 0x07, 0x38, 0x6b, 0x2a, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0xe5, 0xaa, 0x00, 0x61, 0xff, 0x65, 0xff, 0x6d, 0x0c, 0x62, 0x47, 0x63, 0xf8, 0x6b, 0x53, 0x64, 0xf8, 0x6c, 0x19, 0x12, 0x47, 0x38, 0x7b, 0x2a, 0x3d, 0x5b, 0xbd, 0x5c, 0x1a, 0x38, 0xc5, 0xfc, 0x1e, 0x59, 0x96, 0x61, 0xbe, 0x59, 0x4a, 0x81, -0x80, 0x2a, 0xfc, 0x1c, 0x3e, 0x59, 0x04, 0xc8, 0x9e, 0x58, 0xc4, 0x1d, 0x06, 0x38, 0x55, 0xaa, 0x02, 0x8a, 0x42, 0xa9, 0x0f, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xda, 0x1a, 0xbe, 0x58, 0xb3, 0xf8, 0x79, 0xed, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb1, 0x00, 0xb5, 0xef, 0x9e, 0x59, 0xbc, 0x00, 0x9e, 0x58, 0xb1, 0x00, 0x19, 0x00, 0xbe, 0x58, 0xb1, 0x00, 0x19, 0x48, 0xf6, 0x81, 0xd5, 0xf0, 0x9e, 0x58, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb1, 0x00, 0xbe, 0x58, 0xb0, 0x00, 0x9e, 0x58, 0x36, 0x1d, 0x1d, 0x10, 0x04, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0xc4, 0x76, -0xc0, 0x2a, 0x1b, 0x10, 0x20, 0x88, 0xe5, 0xac, 0x1e, 0x90, 0x9e, 0x58, 0xe8, 0x00, 0x02, 0x38, 0x00, 0x05, 0x09, 0x8a, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x08, 0x9e, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x9e, 0x58, 0xe7, 0x00, 0x02, 0x39, 0x01, 0x00, 0x03, 0x98, 0x19, 0x00, 0xbe, 0x58, 0xe7, 0x00, 0x9e, 0x5d, 0xd5, 0x00, 0x9e, 0x5b, 0xd4, 0x00, 0x9e, 0x5c, 0xd3, 0x00, 0x04, 0xac, 0x07, 0x90, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0xb5, 0xef, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x9e, 0x59, 0xbc, 0x00, 0x9e, 0x58, 0xb1, 0x00, 0x19, 0x00, 0x01, 0x31, 0x06, 0x8a, 0xbe, 0x58, 0xb1, 0x00, 0xa8, 0x5d, 0x6c, 0x5b, 0x8c, 0x5c, 0xea, 0x9f, 0xd5, 0xf0, 0x9e, 0x58, 0x23, 0xfe, -0x00, 0x2b, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x3a, 0x38, 0x3a, 0x38, 0x9e, 0x58, 0xe2, 0x19, 0x00, 0x61, 0x01, 0x30, 0x01, 0x88, 0x05, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0xd0, 0xaa, 0x3f, 0x9e, 0x9e, 0x58, 0xae, 0x00, 0x9e, 0x59, 0xc0, 0x00, 0x19, 0x48, 0x01, 0x82, 0x38, 0x9e, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xd0, 0xa8, 0x74, 0xb0, 0x78, 0xaa, 0xf4, 0xb0, 0x00, 0xbc, 0xb1, 0x00, 0x00, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x4f, 0xb0, 0x50, 0xa8, 0xcf, 0xb0, 0x9e, 0x58, 0xaf, 0x00, 0x9e, 0x59, 0xc5, 0x00, 0x19, 0x48, 0x03, 0x82, 0x74, 0x60, 0x82, 0xb0, 0xc2, 0x8e, -0x40, 0x2b, 0xf7, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0xaf, 0x00, 0x4f, 0xb0, 0x50, 0xaa, 0xcf, 0xb0, 0x00, 0xbc, 0xb1, 0x00, 0x00, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x20, 0x60, 0x07, 0x38, 0x56, 0x2b, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x19, 0x38, 0x02, 0x48, 0xb9, 0xaa, 0x00, 0x9e, 0x3a, 0x38, 0x3a, 0x38, 0x52, 0xb2, 0x3a, 0xac, 0xfd, 0x93, 0x78, 0xab, 0x5a, 0x62, 0xe1, 0x6a, 0xac, 0xb2, 0x00, 0x62, 0xff, 0x3f, 0x7a, 0x38, 0xac, 0xb2, 0x78, 0xa9, 0x3a, 0x38, 0x00, 0x62, 0xac, 0xb2, 0xff, 0x3f, 0x0f, 0x59, 0x3a, 0x38, 0x01, 0x62, 0xef, 0x3f, 0x77, 0x2b, 0x05, 0x5d, 0x25, 0x5c, 0xbc, 0x48, 0x02, 0x88, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x62, 0x3a, 0x38, 0x9e, 0x58, 0xbf, 0x00, 0x19, 0x10, 0x0f, 0x61, 0x27, 0x69, 0x59, 0xe5, -0x80, 0x2b, 0x9e, 0x5b, 0xe8, 0x00, 0x9e, 0x58, 0xd5, 0x00, 0x9e, 0x5a, 0xd4, 0x00, 0x9e, 0x5c, 0xd3, 0x00, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0x65, 0x9e, 0x5e, 0xe9, 0x19, 0xa0, 0xac, 0x26, 0x90, 0x9e, 0x5b, 0xe8, 0x00, 0x30, 0x67, 0x0b, 0x6f, 0xa6, 0x40, 0x60, 0x03, 0xe0, 0x07, 0x00, 0xa9, 0x9e, 0x58, 0xed, 0x19, 0x9e, 0x5a, 0xee, 0x19, 0x9e, 0x5c, 0xef, 0x19, 0x0c, 0x58, 0x4c, 0x5a, 0x8c, 0x5c, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0xad, 0x07, 0x92, 0xc2, 0x38, 0x01, 0x00, 0x07, 0x38, 0xb2, 0x2b, 0xe5, 0x59, 0x3d, 0x5b, 0x1a, 0x38, 0x19, 0x05, 0x9e, 0x58, 0xe8, 0x19, 0xb8, 0x48, 0xdb, 0x81, 0x29, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0x30, 0x67, 0x0b, 0x6f, 0x65, 0x03, 0xe5, 0x07, 0x00, 0xa9, 0x05, 0x95, -0xc0, 0x2b, 0x9e, 0x58, 0xed, 0x19, 0x9e, 0x5a, 0xee, 0x19, 0x9e, 0x5c, 0xef, 0x19, 0x0c, 0x58, 0x4c, 0x5a, 0x8c, 0x5c, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0xad, 0x0b, 0x92, 0xc2, 0x38, 0x01, 0x00, 0x07, 0x38, 0xdb, 0x2b, 0xe3, 0x59, 0x3b, 0x5b, 0x70, 0x3b, 0xe8, 0x19, 0xf0, 0x3f, 0xe8, 0x19, 0x1a, 0x38, 0x19, 0x05, 0x9e, 0x58, 0xe8, 0x19, 0xb8, 0x48, 0xd8, 0x81, 0x00, 0x9e, 0x3a, 0x38, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xfd, 0xab, 0xf5, 0xab, 0x1a, 0x38, 0x1a, 0x38, 0x02, 0xa9, 0x00, 0xbd, 0xb0, 0x00, 0x1a, 0x38, 0x1a, 0x38, 0x02, 0xab, 0x1a, 0x38, 0x7a, 0xad, 0xfe, 0x93, 0xfd, 0xa9, 0xf5, 0xa9, 0x3a, 0x38, 0x00, 0xbc, 0xaa, 0x00, 0x10, 0x48, 0x00, 0x00, 0x01, 0x8a, 0x42, 0xa9, 0x40, 0x60, 0x21, 0x71, 0x19, 0x48, 0x01, 0x8a, 0x99, 0xa3, -0x00, 0x2c, 0x42, 0xa9, 0x0c, 0x60, 0x27, 0x71, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0a, 0x60, 0x9e, 0x59, 0xe4, 0x19, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x14, 0x60, 0x9e, 0x59, 0xf0, 0x04, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x16, 0x60, 0x9e, 0x59, 0xba, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x18, 0x60, 0x03, 0x68, 0x9e, 0x59, 0xbf, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x16, 0x60, 0x9e, 0x59, 0xbb, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x24, 0x60, 0x9e, 0x59, 0xbc, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0xe7, 0x00, 0x10, 0x48, 0x02, 0x00, 0x01, 0x9a, 0x42, 0xa9, 0x9e, 0x58, 0x1b, 0x1f, 0x10, 0x48, 0xaa, 0x55, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x1c, 0x1f, 0x10, 0x48, 0x55, 0xaa, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x1b, 0x1f, 0x9e, 0x59, 0x43, 0x86, -0x40, 0x2c, 0x1c, 0x1f, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1a, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1b, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1c, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x17, 0x1f, 0x9e, 0x59, 0x1a, 0x1f, 0x19, 0x48, 0x09, 0x88, 0xcc, 0x60, 0x33, 0x68, 0xbe, 0x58, 0x17, 0x1f, 0x33, 0x60, 0xcc, 0x68, 0xbe, 0x58, 0x1a, 0x1f, 0x42, 0xa9, 0xff, 0xad, 0x01, 0x92, 0x42, 0xa9, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x9e, 0x58, 0x1f, 0x00, 0x10, 0x48, 0x01, 0x00, 0x01, 0x8a, 0x42, 0xa9, 0xed, 0xac, 0x5f, 0x92, 0x2c, 0x60, 0x1b, 0x68, 0x1f, 0x61, 0x1f, 0x69, 0x14, 0x62, 0x19, 0x12, 0x44, 0xd9, -0x80, 0x2c, 0x47, 0x38, 0x87, 0x2c, 0x05, 0x5b, 0x70, 0x48, 0x1f, 0x1f, 0x01, 0x8a, 0x42, 0xa9, 0x1a, 0x38, 0x02, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd5, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0a, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd8, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x05, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd7, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0e, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0x58, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0c, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0x57, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x09, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xba, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xaf, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xc7, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x89, 0xd0, -0xc0, 0x2c, 0xb0, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xc8, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb7, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xcf, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb8, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd1, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0xe0, 0xec, 0xf0, 0xec, 0x1a, 0xed, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x1f, 0x1e, 0xbe, 0x58, 0x20, 0x1e, 0xbe, 0x58, 0x21, 0x1e, 0x22, 0x61, 0x1e, 0x69, 0x23, 0x62, 0x47, 0x38, 0xee, 0x2c, 0x1d, 0x59, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x30, 0x60, 0x0b, 0x68, 0x9e, 0x59, 0xe8, 0x00, 0x9e, 0x5a, 0xe9, 0x00, 0x9e, 0x5f, 0xfe, 0x1b, 0x9e, 0x5e, 0xfd, 0x1b, 0x19, 0x16, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0xc7, 0x38, 0x0a, 0x2d, 0xf8, 0x69, -0x00, 0x2d, 0x68, 0x5b, 0x8c, 0x5c, 0xac, 0x5d, 0x25, 0x5e, 0x16, 0x16, 0xdd, 0x5a, 0xd2, 0x3e, 0x19, 0x1e, 0x01, 0x96, 0x7b, 0xa8, 0x19, 0x00, 0x75, 0x3b, 0x1f, 0x1e, 0x95, 0x3c, 0x20, 0x1e, 0xb5, 0x3d, 0x21, 0x1e, 0xbe, 0x5b, 0x1f, 0x1e, 0xbe, 0x5c, 0x20, 0x1e, 0xbe, 0x5d, 0x21, 0x1e, 0x19, 0x17, 0xdf, 0x99, 0x3a, 0x38, 0x9e, 0x5b, 0x1f, 0x1e, 0x9e, 0x5c, 0x20, 0x1e, 0x9e, 0x5a, 0x21, 0x1e, 0x00, 0x65, 0x9e, 0x5f, 0xfd, 0x1b, 0x19, 0x17, 0x7b, 0xac, 0x0e, 0x92, 0xf0, 0x38, 0xe9, 0x00, 0x22, 0x61, 0x1e, 0x69, 0x23, 0x66, 0xc7, 0x38, 0x32, 0x2d, 0x03, 0x5e, 0x36, 0x06, 0xdd, 0x59, 0x10, 0x38, 0xfd, 0x1b, 0x1a, 0x38, 0x19, 0x05, 0x46, 0x5a, 0x8a, 0x5c, 0x6a, 0x5b, 0x19, 0x17, 0xeb, 0x95, 0xbe, 0x5d, 0x46, 0x1e, 0x3a, 0x38, 0x9e, 0x5b, 0x46, 0x1e, 0x18, 0x13, 0x0d, 0x8a, 0xaa, 0x64, -0x40, 0x2d, 0x24, 0x62, 0x22, 0x64, 0x1e, 0x6c, 0x47, 0x38, 0x4c, 0x2d, 0x00, 0x61, 0x83, 0x58, 0x78, 0xac, 0x02, 0x90, 0xff, 0x61, 0xff, 0x69, 0x3c, 0x5b, 0x1d, 0x5c, 0x3a, 0x38, 0x9e, 0x5b, 0xe9, 0x00, 0x22, 0x64, 0x1e, 0x6c, 0x85, 0x5d, 0x24, 0x67, 0x9e, 0x5e, 0xfd, 0x1b, 0x19, 0x16, 0xc7, 0x38, 0x5b, 0x2d, 0x75, 0x16, 0xdd, 0x5b, 0x1a, 0x38, 0x85, 0x5d, 0x19, 0x17, 0xf5, 0x99, 0x3a, 0x38, 0x9e, 0x58, 0x15, 0x1e, 0x00, 0xac, 0x21, 0x90, 0xff, 0x61, 0x07, 0x69, 0x34, 0x38, 0xe3, 0x19, 0x18, 0x10, 0x1b, 0x88, 0x9e, 0x58, 0x1a, 0x1e, 0x02, 0x61, 0x19, 0x48, 0x16, 0x88, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xda, 0x1a, 0xbe, 0x58, 0xb3, 0xf8, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0x1a, 0x1e, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x1e, 0x24, 0x78, -0x80, 0x2d, 0xbe, 0x58, 0x1c, 0x1e, 0xff, 0x60, 0xbe, 0x58, 0x1d, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x1a, 0x10, 0x04, 0x8a, 0x8f, 0xed, 0xc5, 0xed, 0xf5, 0xed, 0x1c, 0xee, 0x3a, 0x38, 0x9e, 0x5e, 0xe9, 0x00, 0x00, 0x65, 0xbe, 0x5d, 0x48, 0x1e, 0x9e, 0x5f, 0xfd, 0x1b, 0xbe, 0x5f, 0x49, 0x1e, 0x19, 0x17, 0xe6, 0x00, 0x03, 0x5b, 0x10, 0x38, 0xfd, 0x1b, 0x9e, 0x59, 0xfe, 0x1b, 0x1a, 0x11, 0x27, 0x38, 0xb4, 0x2d, 0x03, 0x5a, 0x10, 0x39, 0xfd, 0x1b, 0x23, 0x5c, 0x43, 0x13, 0x09, 0x9a, 0x44, 0x14, 0x07, 0x9a, 0x72, 0x39, 0x16, 0x1e, 0x03, 0x98, 0x92, 0x39, 0x16, 0x1e, 0x01, 0x9a, 0x19, 0x05, 0x41, 0x5b, 0x10, 0x38, 0xfd, 0x1b, 0x1a, 0x38, 0x9e, 0x5b, 0x48, 0x1e, 0x7d, 0x48, 0x02, 0x94, 0xbe, 0x5d, 0x48, 0x1e, 0x9e, 0x5b, 0x49, 0x1e, 0x7d, 0x48, 0x02, 0x9a, 0xbe, 0x5d, 0xc0, 0x63, -0xc0, 0x2d, 0x49, 0x1e, 0x00, 0x65, 0x19, 0x17, 0xd5, 0x95, 0x3a, 0x38, 0x9e, 0x5f, 0x1a, 0x1e, 0x19, 0x07, 0x18, 0x17, 0x01, 0x9a, 0x00, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x58, 0x48, 0x1e, 0x12, 0x39, 0x49, 0x1e, 0x06, 0x62, 0xd6, 0xac, 0x01, 0x90, 0x02, 0x62, 0xbe, 0x5a, 0x17, 0x1e, 0x12, 0x3a, 0x17, 0x1e, 0x08, 0x9a, 0x01, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x5f, 0x1b, 0x1e, 0x19, 0x07, 0xbe, 0x5f, 0x1b, 0x1e, 0x3a, 0x38, 0x00, 0x63, 0x9e, 0x58, 0x48, 0x1e, 0x12, 0x39, 0x49, 0x1e, 0x06, 0x62, 0xd6, 0xac, 0x01, 0x90, 0x02, 0x62, 0xbe, 0x5a, 0x17, 0x1e, 0x12, 0x3a, 0x17, 0x1e, 0x01, 0x9a, 0x01, 0x63, 0xbe, 0x5b, 0x1e, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x18, 0x10, 0x1f, 0x8a, 0x9e, 0x58, 0x1b, 0x1e, 0x02, 0x39, 0x05, 0x00, 0x0a, 0x8a, 0x9e, 0x59, 0x48, 0x1e, 0xac, 0x7f, -0x00, 0x2e, 0x32, 0x3a, 0x1d, 0x1e, 0x18, 0x98, 0xbe, 0x59, 0x1d, 0x1e, 0xbe, 0x58, 0x1c, 0x1e, 0x13, 0x9e, 0x9e, 0x59, 0x15, 0x1e, 0x09, 0xac, 0x08, 0x92, 0x02, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x5f, 0x1c, 0x1e, 0xbe, 0x5f, 0x1b, 0x1e, 0x07, 0x9e, 0x00, 0x67, 0xbe, 0x5f, 0x1b, 0x1e, 0x03, 0x9e, 0x00, 0x63, 0xbe, 0x5b, 0x1e, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x18, 0x10, 0x16, 0x8a, 0x9e, 0x58, 0x1b, 0x1e, 0x9e, 0x59, 0x15, 0x1e, 0x11, 0xac, 0x02, 0x90, 0x08, 0x58, 0x08, 0x58, 0xd6, 0xac, 0x03, 0x90, 0x00, 0x38, 0x77, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x7c, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xd6, 0x1a, 0x01, 0x00, 0x78, 0xa8, 0xbe, 0x58, 0x47, 0x1e, 0x3a, 0x38, 0x48, 0x62, 0x0e, 0x6a, 0x9e, 0x5b, 0xfd, 0x1b, 0x9e, 0x5c, 0xfd, 0x1b, 0x41, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x9e, 0x10, -0x40, 0x2e, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0xc7, 0x38, 0x4a, 0x2e, 0xa3, 0x58, 0x18, 0x10, 0x02, 0x94, 0x19, 0x07, 0x20, 0x01, 0xa3, 0x05, 0x21, 0x58, 0x00, 0x61, 0x02, 0x58, 0x1c, 0x5f, 0x01, 0x59, 0x32, 0x39, 0x18, 0x1e, 0x0d, 0x9a, 0x41, 0x5d, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0x08, 0x58, 0xc7, 0x38, 0x5f, 0x2e, 0xa3, 0x5e, 0x18, 0x06, 0x02, 0x9a, 0xc0, 0x06, 0xdb, 0x5d, 0xa3, 0x05, 0x19, 0x02, 0x19, 0x14, 0xda, 0x89, 0x3a, 0x38, 0x01, 0x60, 0xbe, 0x58, 0x15, 0x1e, 0x40, 0x60, 0xbe, 0x58, 0x16, 0x1e, 0xff, 0x60, 0x1f, 0x68, 0xbe, 0x58, 0x18, 0x1e, 0x80, 0x60, 0xbe, 0x58, 0x19, 0x1e, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0x79, 0xed, 0x3a, 0x38, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8b, 0xaf, -0x80, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x30, 0x00, 0x38, 0x00, 0x3c, 0xab, 0x3a, 0x38, 0xfa, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x01, 0xd6, 0x1a, 0xd7, 0x1a, 0xd8, 0x1a, 0x57, 0x01, 0x5b, 0x01, 0x2d, 0x62, 0x01, 0x6a, 0x26, 0x63, 0x04, 0x6b, 0xeb, 0x64, 0x00, 0x67, 0x10, 0x6f, 0xef, 0x3a, 0xa3, 0x2e, 0x45, 0x5d, 0x65, 0x5e, 0x85, 0x58, 0xbb, 0x5e, 0x3a, 0x38, 0x9e, 0x5e, 0x20, 0x04, 0xc6, 0x5e, 0x7c, 0x62, 0x01, 0x6a, 0x94, 0x63, 0x01, 0x6b, 0x17, 0x64, 0x01, 0x6c, 0x01, 0x65, 0x01, 0x6d, 0xef, 0x3a, 0xb7, 0x2e, 0x45, 0x58, 0xc0, 0x40, 0x1d, 0x5c, 0x65, 0x58, 0xc0, 0x40, 0x1d, 0x5d, 0x3a, 0x38, 0xef, 0xa8, 0x9e, 0x58, 0x17, 0x04, 0x9e, 0x59, 0x1f, 0x04, 0x01, 0x10, 0x19, 0x48, 0x3d, 0x9e, -0xc0, 0x2e, 0x03, 0x9a, 0xbe, 0x58, 0x18, 0x04, 0x02, 0x9e, 0xbe, 0x59, 0x18, 0x04, 0x9e, 0x58, 0xb5, 0x00, 0x18, 0x10, 0x03, 0x8a, 0x19, 0x10, 0x01, 0x8a, 0x09, 0x9e, 0x9e, 0x58, 0x1d, 0x04, 0x18, 0x10, 0x04, 0x8a, 0x19, 0x10, 0xbe, 0x58, 0x1d, 0x04, 0x01, 0x9e, 0xef, 0xaa, 0x3a, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0x31, +0x00, 0x24, 0x5d, 0xac, 0x01, 0x90, 0x03, 0x9e, 0x01, 0x65, 0xbe, 0x5d, 0x61, 0x1a, 0x9e, 0x5c, 0x02, 0x1d, 0x19, 0x04, 0xbe, 0x5c, 0x02, 0x1d, 0x00, 0x3c, 0x48, 0x0e, 0x83, 0x5b, 0x9e, 0x5a, 0x1d, 0x1f, 0x18, 0x12, 0x07, 0x88, 0x9e, 0x5d, 0x61, 0x1a, 0x05, 0xac, 0x0c, 0x92, 0x61, 0x12, 0x7a, 0xac, 0x09, 0x90, 0x3b, 0x5c, 0x01, 0x62, 0xbe, 0x5a, 0x62, 0x1a, 0x9e, 0x5a, 0x03, 0x1d, 0x19, 0x02, 0xbe, 0x5a, 0x03, 0x1d, 0x3e, 0x5b, 0x19, 0x13, 0x00, 0x62, 0x62, 0x14, 0x0a, 0x89, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x72, 0x62, 0x19, 0x6a, 0x86, 0x63, 0x19, 0x6b, 0x00, 0x60, 0xbe, 0x58, 0x71, 0x1a, 0x00, 0x67, 0x00, 0x60, 0x9e, 0x59, 0x58, 0x1a, 0x38, 0x48, 0xd6, 0xa1, +0x40, 0x24, 0x33, 0x8a, 0x19, 0x11, 0x27, 0x38, 0x73, 0x24, 0x40, 0x04, 0x83, 0x5d, 0x48, 0x64, 0x1d, 0x6c, 0x85, 0x04, 0x83, 0x5d, 0x15, 0x66, 0xbe, 0x48, 0x09, 0x82, 0x19, 0x04, 0x83, 0x5d, 0xbe, 0x48, 0x05, 0x82, 0x1a, 0x14, 0x83, 0x5d, 0xbe, 0x48, 0x01, 0x82, 0x13, 0x9e, 0x60, 0x04, 0x83, 0x5d, 0x48, 0x64, 0x1d, 0x6c, 0x85, 0x04, 0x90, 0x3c, 0xb8, 0x00, 0x83, 0x5d, 0x15, 0x66, 0xbe, 0x48, 0x10, 0x82, 0x19, 0x04, 0x83, 0x5d, 0xbe, 0x48, 0x0c, 0x82, 0x1a, 0x14, 0x83, 0x5d, 0xbe, 0x48, 0x08, 0x82, 0x19, 0x07, 0xbe, 0x5f, 0x71, 0x1a, 0x72, 0x65, 0x1a, 0x6d, 0xa7, 0x06, 0x19, 0x16, 0x1b, 0x5e, 0x1a, 0x38, 0x1a, 0x38, 0x19, 0x00, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x00, 0x67, 0xdf, 0x60, 0x1e, 0x68, 0x67, 0xd8, +0x80, 0x24, 0x2f, 0x39, 0x84, 0x24, 0xfd, 0x58, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x9e, 0x5c, 0xb8, 0x00, 0x9e, 0x5e, 0xb9, 0x00, 0x86, 0x04, 0x19, 0x14, 0x87, 0x38, 0x92, 0x24, 0xfd, 0x5d, 0x1a, 0x38, 0x1a, 0x38, 0xbe, 0x5f, 0xdb, 0x1e, 0xbe, 0x5f, 0xdc, 0x1e, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x01, 0x00, 0x02, 0x3a, 0xb0, 0x00, 0x01, 0x98, 0x3a, 0x38, 0x00, 0x61, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x5a, 0xdd, 0x1e, 0x1c, 0x5a, 0x02, 0x39, 0x20, 0x00, 0x01, 0x98, 0x20, 0x60, 0x00, 0x61, 0x01, 0x62, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x48, 0x63, 0x1d, 0x6b, 0x9e, 0x5c, 0xb8, 0x00, 0x19, 0x14, 0x87, 0x38, 0xcd, 0x24, 0x65, 0x5c, 0x98, 0x48, 0x06, 0x80, 0x5b, 0x5d, 0xbe, 0x5a, 0xdb, 0x1e, 0x19, 0x01, 0x01, 0x67, 0x0e, 0x9e, 0x07, 0xac, 0xaf, 0x52, +0xc0, 0x24, 0x0c, 0x90, 0x1e, 0x5d, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x01, 0x8a, 0x3b, 0x5d, 0x3e, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x19, 0x02, 0x19, 0x05, 0x1e, 0x5d, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x01, 0x8a, 0x3b, 0x5d, 0x3e, 0x5d, 0x00, 0x61, 0x9e, 0x58, 0x4f, 0x04, 0x9e, 0x5a, 0xdd, 0x1e, 0x1c, 0x5a, 0x02, 0x39, 0x20, 0x00, 0x01, 0x98, 0x20, 0x60, 0x00, 0x61, 0x01, 0x62, 0x00, 0x67, 0x50, 0x65, 0x04, 0x6d, 0x48, 0x63, 0x1d, 0x6b, 0x9e, 0x5c, 0xb8, 0x00, 0xa4, 0x05, 0x64, 0x03, 0x9e, 0x5c, 0xb9, 0x00, 0x19, 0x14, 0x87, 0x38, 0x0d, 0x25, 0x65, 0x5c, 0x98, 0x48, 0x06, 0x80, 0x5b, 0x5d, 0xbe, 0x5a, 0xdc, 0x1e, 0x19, 0x01, 0x01, 0x67, 0x13, 0x9e, 0x07, 0xac, 0x11, 0x90, 0x1e, 0x5d, 0x1e, 0x5e, 0x40, 0x3d, 0xdf, 0x1e, 0xc9, 0x52, +0x00, 0x25, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x04, 0x8a, 0xa3, 0x5e, 0xfe, 0x59, 0xc1, 0x06, 0xdb, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x19, 0x02, 0x19, 0x05, 0x1e, 0x5d, 0x1e, 0x5e, 0x40, 0x3d, 0xdf, 0x1e, 0x19, 0x15, 0x50, 0x48, 0x08, 0x00, 0x04, 0x8a, 0xa3, 0x5e, 0xfe, 0x59, 0xc1, 0x06, 0xdb, 0x5d, 0x3e, 0x5e, 0x3e, 0x5d, 0x00, 0x60, 0xbe, 0x58, 0xe8, 0x1e, 0xbe, 0x58, 0xe7, 0x1e, 0xdf, 0x62, 0x1e, 0x6a, 0x01, 0x67, 0xef, 0x38, 0x2e, 0x25, 0x45, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0x78, 0x48, 0x02, 0x96, 0x61, 0x58, 0xe1, 0x5c, 0x19, 0x07, 0x1a, 0x38, 0xbe, 0x5c, 0xe7, 0x1e, 0xdf, 0x62, 0x1e, 0x6a, 0x01, 0x67, 0x00, 0x60, 0xef, 0x38, 0x40, 0x25, 0x45, 0x5b, 0xfe, 0x5b, 0x64, 0x3b, 0xff, 0x00, 0x78, 0x48, 0x02, 0x96, 0x61, 0x58, 0xe1, 0x5d, 0x19, 0x07, 0x33, 0xd5, +0x40, 0x25, 0x1a, 0x38, 0xbe, 0x5d, 0xe8, 0x1e, 0x7a, 0x60, 0x02, 0x68, 0x50, 0x61, 0x04, 0x69, 0x39, 0x62, 0x47, 0x38, 0x4d, 0x25, 0x23, 0x5b, 0x7b, 0x58, 0x19, 0x01, 0x19, 0x00, 0x3a, 0x38, 0x92, 0x62, 0xf8, 0x6a, 0x00, 0x64, 0x17, 0x63, 0x67, 0x38, 0x57, 0x25, 0x45, 0x5b, 0x83, 0x04, 0x1a, 0x38, 0xfe, 0x5c, 0x84, 0x3c, 0x00, 0xff, 0x9e, 0x5f, 0x34, 0x1d, 0xe0, 0x3b, 0x30, 0x1d, 0x9e, 0x59, 0xb5, 0x00, 0x24, 0x29, 0x3b, 0x5b, 0x30, 0x63, 0x1d, 0x6b, 0x00, 0x60, 0xbe, 0x58, 0x36, 0x1d, 0x04, 0x65, 0x19, 0x15, 0xa7, 0x38, 0x70, 0x25, 0x63, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0x06, 0x00, 0x19, 0x03, 0x19, 0x05, 0x00, 0x61, 0x1c, 0x5d, 0xbe, 0x58, 0x35, 0x1d, 0x30, 0x63, 0x1d, 0x6b, 0x04, 0x65, 0x19, 0x15, 0xa7, 0x38, 0x81, 0x25, 0x63, 0x5e, 0xc4, 0x3e, 0x00, 0xff, 0xfe, 0x5e, 0x97, 0xe9, +0x80, 0x25, 0x06, 0x00, 0x19, 0x03, 0x19, 0x05, 0x00, 0x61, 0x1c, 0x5d, 0x01, 0x5b, 0xbe, 0x58, 0xbc, 0x1d, 0x9e, 0x58, 0x35, 0x1d, 0x19, 0x07, 0xe2, 0x3a, 0x04, 0x00, 0x01, 0x88, 0x00, 0x67, 0xbe, 0x5f, 0x34, 0x1d, 0x01, 0x61, 0x9e, 0x5a, 0xb1, 0x04, 0x42, 0x3f, 0x01, 0x00, 0x11, 0x8a, 0x01, 0x61, 0x02, 0x3f, 0x04, 0x00, 0x0d, 0x9a, 0x04, 0x61, 0x02, 0x3f, 0x06, 0x00, 0x09, 0x9a, 0x02, 0x61, 0x02, 0x3f, 0x08, 0x00, 0x05, 0x9a, 0x03, 0x61, 0x02, 0x3f, 0x0a, 0x00, 0x01, 0x9a, 0x01, 0x61, 0xbe, 0x59, 0x36, 0x1d, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x63, 0x00, 0x65, 0x9c, 0x60, 0x1e, 0x68, 0x9e, 0x59, 0xb8, 0x00, 0x19, 0x11, 0x27, 0x38, 0xc1, 0x25, 0x03, 0x5a, 0x5b, 0x48, 0x01, 0x96, 0x41, 0x5b, 0xce, 0x09, +0xc0, 0x25, 0x19, 0x00, 0x1a, 0x38, 0xbe, 0x5b, 0x60, 0x1e, 0x9e, 0x59, 0xb9, 0x00, 0x19, 0x11, 0x27, 0x38, 0xce, 0x25, 0x03, 0x5a, 0x5d, 0x48, 0x01, 0x96, 0x41, 0x5d, 0x19, 0x00, 0x1a, 0x38, 0xbe, 0x5d, 0x5f, 0x1e, 0x10, 0x64, 0x65, 0x02, 0x50, 0x48, 0x00, 0x01, 0x0b, 0x80, 0x61, 0x58, 0x7d, 0x48, 0x01, 0x98, 0xa1, 0x58, 0x01, 0x5c, 0x00, 0x61, 0x07, 0x62, 0x82, 0x40, 0x0a, 0x62, 0x1c, 0x5a, 0x01, 0x5c, 0xbe, 0x5c, 0x61, 0x1e, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x10, 0x48, 0x05, 0x00, 0x18, 0x3e, 0x4f, 0x27, 0x9e, 0x58, 0xdb, 0x1e, 0x10, 0x48, 0x02, 0x00, 0x18, 0x3e, 0x4f, 0x27, 0x9e, 0x59, 0xdc, 0x1e, 0x30, 0x48, 0x02, 0x00, 0x18, 0x3e, 0x4f, 0x27, 0x15, 0x0e, +0x00, 0x26, 0x9e, 0x58, 0x45, 0x04, 0x02, 0x38, 0x50, 0x01, 0x3d, 0x98, 0xdf, 0x60, 0x1e, 0x68, 0x05, 0x59, 0x24, 0x3a, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3b, 0xff, 0x00, 0x43, 0x06, 0x03, 0x59, 0x24, 0x3c, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3d, 0xff, 0x00, 0x85, 0x07, 0xc7, 0x00, 0x38, 0x10, 0x2a, 0x98, 0xd0, 0x48, 0x06, 0x00, 0x27, 0x98, 0xf0, 0x48, 0x06, 0x00, 0x24, 0x98, 0x45, 0x00, 0x10, 0x48, 0x06, 0x00, 0x20, 0x98, 0x64, 0x00, 0x10, 0x48, 0x06, 0x00, 0x1c, 0x98, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x98, 0x21, 0x58, 0x9e, 0x59, 0x44, 0x04, 0x19, 0x48, 0x10, 0x80, 0x9e, 0x58, 0xf1, 0x04, 0x19, 0x10, 0x04, 0x88, 0x9e, 0x58, 0x8a, 0x04, 0x1a, 0x10, 0x09, 0x98, 0x9e, 0x58, 0xf2, 0x04, 0x19, 0x10, 0x04, 0x88, 0x9e, 0x58, 0x8b, 0x04, 0x1a, 0x10, 0x1d, 0x27, +0x40, 0x26, 0x01, 0x98, 0xfc, 0x9e, 0x9e, 0x59, 0x4e, 0x04, 0x30, 0x48, 0x00, 0x00, 0x8a, 0x8a, 0x9e, 0x59, 0x4e, 0x04, 0x30, 0x48, 0x23, 0x00, 0x85, 0x8a, 0x9e, 0x59, 0x4c, 0x04, 0x30, 0x48, 0x00, 0x00, 0x80, 0x8a, 0x9e, 0x59, 0x4c, 0x04, 0x30, 0x48, 0x15, 0x00, 0x7b, 0x8a, 0x9e, 0x58, 0x46, 0x04, 0x9e, 0x59, 0x47, 0x04, 0x01, 0x00, 0x02, 0x38, 0x40, 0x00, 0x08, 0x98, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x02, 0x39, 0x02, 0x00, 0x12, 0x8a, 0x9e, 0x58, 0x46, 0x04, 0x38, 0x10, 0x67, 0x98, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1b, 0x10, 0x60, 0x88, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x10, 0x5a, 0x8a, 0x28, 0x9e, 0x80, 0x60, 0x01, 0x68, 0xbe, 0x58, 0x20, 0x1d, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0xd4, 0xd9, +0x80, 0x26, 0x19, 0x48, 0x01, 0x9a, 0x21, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x51, 0xe7, 0x01, 0x60, 0x01, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x18, 0x10, 0xb1, 0x8a, 0x00, 0x63, 0xbe, 0x5b, 0x0e, 0x1f, 0xbe, 0x5b, 0x10, 0x1f, 0x9e, 0x5b, 0xb8, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xb9, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x11, 0x1f, 0x01, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x9e, 0x9e, 0x9e, 0x58, 0x46, 0x04, 0x9e, 0x59, 0x47, 0x04, 0x19, 0x48, 0x98, 0x98, 0x68, 0x60, 0x01, 0x68, 0xbe, 0x58, 0x20, 0x1d, 0x76, 0xde, 0x9e, 0x58, 0x4d, 0x04, 0x9e, 0x59, 0x4f, 0x04, 0x19, 0x48, 0x01, 0x9a, 0x21, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0e, 0x1f, 0xbe, 0x5b, 0x10, 0x1f, 0x9e, 0x5b, 0xb8, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0xd0, 0x0a, +0xc0, 0x26, 0xb9, 0x00, 0x19, 0x13, 0xbe, 0x5b, 0x11, 0x1f, 0x01, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x01, 0x60, 0x02, 0x61, 0x77, 0xe7, 0x02, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x02, 0x60, 0x02, 0x61, 0x77, 0xe7, 0x6d, 0x9e, 0x0c, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x7d, 0xe4, 0xdf, 0x60, 0x1e, 0x68, 0x05, 0x59, 0x24, 0x3a, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3b, 0xff, 0x00, 0x43, 0x06, 0x03, 0x59, 0x24, 0x3c, 0xff, 0x00, 0xfe, 0x59, 0x24, 0x3d, 0xff, 0x00, 0x85, 0x07, 0xd0, 0x48, 0x0f, 0x00, 0x04, 0x98, 0xf0, 0x48, 0x0f, 0x00, 0x01, 0x98, 0x04, 0x9e, 0x04, 0x60, 0xbe, 0x58, 0xdd, 0x1e, 0x7d, 0xe4, 0x9e, 0x58, 0xdb, 0x1e, 0x9e, 0x59, 0xdc, 0x1e, 0x01, 0x00, 0x1a, 0x10, 0x0b, 0x88, 0x60, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x9e, 0x58, 0xf1, 0x04, 0x9e, 0x59, 0xf2, 0x04, 0x01, 0x00, 0x1c, 0x10, 0xc5, 0x27, +0x00, 0x27, 0x4e, 0x88, 0x3c, 0x9e, 0x66, 0x60, 0xbe, 0x58, 0x20, 0x1d, 0x70, 0xe8, 0x01, 0x60, 0x01, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x01, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x01, 0x60, 0x02, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x01, 0x60, 0x02, 0x61, 0x77, 0xe7, 0x02, 0x60, 0x01, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x02, 0x60, 0x01, 0x61, 0x77, 0xe7, 0x02, 0x60, 0x02, 0x61, 0xb8, 0xe7, 0x9e, 0x58, 0x0d, 0x1f, 0x1e, 0x10, 0x03, 0x80, 0x02, 0x60, 0x02, 0x61, 0x77, 0xe7, 0x98, 0xe2, 0x06, 0x71, 0x09, 0xac, 0x0c, 0x92, 0x01, 0xac, 0x0a, 0x92, 0x51, 0xac, 0x08, 0x92, 0x9e, 0x58, 0x20, 0x1d, 0x00, 0x61, 0x19, 0x48, 0x03, 0x8a, 0x01, 0x60, 0xbe, 0x58, 0x44, 0x1a, 0x9e, 0x58, 0x8a, 0x04, 0x5e, 0x57, +0x40, 0x27, 0x10, 0x48, 0x0a, 0x00, 0x05, 0x98, 0x9e, 0x58, 0x8b, 0x04, 0x10, 0x48, 0x0a, 0x00, 0x03, 0x9c, 0x01, 0x60, 0xbe, 0x58, 0x1d, 0x1f, 0x98, 0xe2, 0x00, 0x60, 0xbe, 0x58, 0x1d, 0x1f, 0x1a, 0x38, 0x3a, 0x38, 0x9e, 0x58, 0xb8, 0x00, 0x1b, 0x10, 0x7a, 0x61, 0x02, 0x69, 0x60, 0xe7, 0x9e, 0x58, 0xb9, 0x00, 0x1b, 0x10, 0x7a, 0x61, 0x02, 0x69, 0x30, 0x39, 0xb8, 0x00, 0x60, 0xe7, 0x3a, 0x38, 0x19, 0x01, 0x00, 0x66, 0x07, 0x38, 0x75, 0x27, 0x23, 0x5a, 0x18, 0x12, 0x08, 0x8a, 0x18, 0x16, 0x04, 0x88, 0x21, 0x5b, 0x19, 0x13, 0x01, 0x64, 0x9b, 0x5b, 0x01, 0x66, 0x06, 0x9e, 0x18, 0x16, 0x04, 0x8a, 0x21, 0x5b, 0x01, 0x64, 0x9b, 0x5b, 0x00, 0x66, 0x19, 0x01, 0x3a, 0x38, 0xbe, 0x58, 0x82, 0x1d, 0xbe, 0x59, 0x83, 0x1d, 0x9e, 0x5e, 0x10, 0x1f, 0x9e, 0x5f, 0x0e, 0x1f, 0x7a, 0x63, 0x57, 0x28, +0x80, 0x27, 0x02, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x9e, 0x59, 0x82, 0x1d, 0x79, 0x48, 0x26, 0x88, 0x48, 0x63, 0x1d, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x18, 0x13, 0x20, 0x8a, 0x7a, 0x62, 0x02, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x83, 0x1d, 0x59, 0x48, 0x16, 0x88, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x61, 0x58, 0x43, 0x40, 0x9e, 0x5d, 0x14, 0x1f, 0x1c, 0x5d, 0x01, 0x5d, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x48, 0x64, 0x0e, 0x6c, 0x80, 0x04, 0xbb, 0x5c, 0x19, 0x07, 0x9e, 0x5a, 0x0f, 0x1f, 0xfa, 0x48, 0xcd, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0x11, 0x1f, 0xda, 0x48, 0xc6, 0x9d, 0x3a, 0x38, 0x9e, 0x5b, 0xb8, 0x00, 0xbe, 0x5b, 0x0e, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0f, 0x1f, 0x9e, 0x5b, 0x82, 0xeb, +0xc0, 0x27, 0xb9, 0x00, 0xbe, 0x5b, 0x10, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x11, 0x1f, 0x00, 0x63, 0xbe, 0x5b, 0x0d, 0x1f, 0x01, 0x63, 0xbe, 0x5b, 0x12, 0x1f, 0xbe, 0x5b, 0x13, 0x1f, 0x00, 0x63, 0x00, 0x65, 0xbe, 0x58, 0x00, 0x1d, 0xbe, 0x59, 0x04, 0x1d, 0x00, 0x66, 0x00, 0x67, 0x7a, 0x62, 0x02, 0x6a, 0x47, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x00, 0x1d, 0x59, 0x48, 0x61, 0x88, 0x7a, 0x62, 0x02, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x04, 0x1d, 0x59, 0x48, 0x57, 0x88, 0x48, 0x62, 0x1d, 0x6a, 0x47, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x12, 0x1f, 0x59, 0x48, 0x02, 0x9a, 0xbe, 0x5a, 0x12, 0x1f, 0x48, 0x62, 0x1d, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x9e, 0x59, 0x13, 0x1f, 0x59, 0x48, 0x02, 0x9a, 0xbe, 0x5a, 0x13, 0x1f, 0x9e, 0x5c, 0xb8, 0x00, 0xb3, 0xe8, +0x00, 0x28, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x9e, 0x5d, 0x20, 0x1d, 0xb0, 0x48, 0x66, 0x00, 0x02, 0x88, 0x48, 0x64, 0x0e, 0x6c, 0x80, 0x04, 0x83, 0x59, 0x79, 0xac, 0x2f, 0x92, 0x10, 0x60, 0x38, 0x48, 0x2c, 0x9a, 0x9e, 0x58, 0x0e, 0x1f, 0xf8, 0x48, 0x07, 0x98, 0xbe, 0x5f, 0x0e, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x0f, 0x1f, 0xf8, 0x48, 0x07, 0x80, 0xbe, 0x5f, 0x0f, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x10, 0x1f, 0xd8, 0x48, 0x07, 0x98, 0xbe, 0x5e, 0x10, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x9e, 0x58, 0x11, 0x1f, 0xd8, 0x48, 0x07, 0x80, 0xbe, 0x5e, 0x11, 0x1f, 0x9e, 0x58, 0x0d, 0x1f, 0x19, 0x00, 0xbe, 0x58, 0x0d, 0x1f, 0x19, 0x07, 0xf7, 0xe6, +0x40, 0x28, 0x9e, 0x5a, 0xb8, 0x00, 0x19, 0x12, 0xfa, 0x48, 0x91, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0xb9, 0x00, 0x19, 0x12, 0xda, 0x48, 0x8a, 0x9d, 0x9e, 0x58, 0x12, 0x1f, 0x9e, 0x59, 0x13, 0x1f, 0x38, 0x48, 0x01, 0x98, 0x21, 0x58, 0x9e, 0x5e, 0x4d, 0x04, 0x9e, 0x5f, 0x4f, 0x04, 0xc7, 0x06, 0xc2, 0x3e, 0x00, 0x06, 0x04, 0x80, 0x02, 0x39, 0x40, 0x01, 0x01, 0x98, 0x10, 0x60, 0x02, 0x39, 0x80, 0x03, 0x02, 0x80, 0x08, 0x59, 0x01, 0x00, 0x9e, 0x5e, 0x12, 0x1f, 0x9e, 0x5f, 0x13, 0x1f, 0xc7, 0x06, 0xc2, 0x3e, 0x00, 0x02, 0x02, 0x98, 0x08, 0x58, 0x08, 0x58, 0xbe, 0x58, 0x14, 0x1f, 0x3a, 0x38, 0x00, 0x62, 0x7a, 0x67, 0x02, 0x6f, 0x16, 0x60, 0xe5, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x8b, 0xe8, 0x19, 0x02, 0x19, 0x10, 0x18, 0x10, 0xf8, 0x89, 0x00, 0x62, 0x7a, 0x67, 0x02, 0x6f, 0x16, 0x66, 0x1e, 0xda, +0x80, 0x28, 0xe6, 0x07, 0x24, 0x66, 0xe5, 0x5c, 0x18, 0x14, 0x01, 0x88, 0x98, 0xe8, 0x19, 0x02, 0x19, 0x16, 0x18, 0x16, 0xf8, 0x89, 0x3a, 0x38, 0x00, 0x64, 0x48, 0x63, 0x0e, 0x6b, 0x62, 0x03, 0x16, 0x65, 0x24, 0x66, 0x19, 0x16, 0xc7, 0x38, 0x96, 0x28, 0x9b, 0x5b, 0x65, 0x03, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x64, 0x16, 0x65, 0x48, 0x63, 0x0e, 0x6b, 0x00, 0x61, 0x00, 0x60, 0x45, 0x40, 0x03, 0x03, 0x16, 0x65, 0x19, 0x15, 0xa7, 0x38, 0xa6, 0x28, 0x9d, 0x5b, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x48, 0x60, 0x1d, 0x68, 0x9c, 0x61, 0x1e, 0x69, 0x9e, 0x5b, 0x4c, 0x04, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x8a, 0x9e, 0x5b, 0x4c, 0x04, 0x70, 0x48, 0x01, 0x00, 0x0f, 0x8a, 0x70, 0x48, 0x14, 0x00, 0x15, 0x8a, 0x70, 0x48, 0x15, 0x00, 0x1b, 0x8a, 0x23, 0x9e, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x53, 0xa0, +0xc0, 0x28, 0xc3, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x23, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0xcc, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xd5, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x11, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0xde, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x08, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x8f, 0x38, 0xe7, 0x28, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x48, 0x60, 0x1d, 0x68, 0x10, 0x38, 0xb8, 0x00, 0x9c, 0x61, 0x1e, 0x69, 0x30, 0x39, 0xb8, 0x00, 0x9e, 0x5b, 0x4e, 0x04, 0x70, 0x48, 0x00, 0x00, 0x0c, 0x8a, 0x9e, 0x5b, 0x4e, 0x04, 0x70, 0x48, 0x01, 0x00, 0x0f, 0x8a, 0x70, 0x48, 0x22, 0x00, 0x15, 0x8a, 0x70, 0x48, 0x23, 0x00, 0x1b, 0x8a, 0x3d, 0x49, +0x00, 0x29, 0x23, 0x9e, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x07, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x23, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x6f, 0x38, 0x10, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x9e, 0x19, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x19, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x11, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x4f, 0x38, 0x22, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x08, 0x9e, 0x1a, 0x13, 0x03, 0x00, 0x23, 0x01, 0x8f, 0x38, 0x2b, 0x29, 0x05, 0x5a, 0x5d, 0x59, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0x1e, 0x5e, 0x1e, 0x5f, 0x00, 0x66, 0x00, 0x67, 0x9c, 0x63, 0x1e, 0x6b, 0x67, 0x03, 0x63, 0x5b, 0x18, 0x13, 0x24, 0x8a, 0x48, 0x62, 0x1d, 0x6a, 0xda, 0xc3, +0x40, 0x29, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x59, 0x48, 0x1b, 0x8a, 0x9c, 0x62, 0x1e, 0x6a, 0x50, 0x3a, 0xb8, 0x00, 0x46, 0x02, 0x43, 0x5a, 0x00, 0x61, 0x61, 0x58, 0x43, 0x40, 0x9e, 0x5d, 0x61, 0x1e, 0x1c, 0x5d, 0x01, 0x5d, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x80, 0x04, 0x48, 0x63, 0x0e, 0x6b, 0x60, 0x03, 0xbb, 0x5c, 0xbb, 0x5b, 0x0e, 0x9e, 0x9e, 0x5c, 0xb8, 0x00, 0x00, 0x61, 0xe1, 0x58, 0x86, 0x48, 0x32, 0x64, 0x16, 0x6c, 0x80, 0x04, 0x48, 0x63, 0x0e, 0x6b, 0x60, 0x03, 0x00, 0x65, 0xbb, 0x5c, 0xbb, 0x5b, 0x19, 0x07, 0x9e, 0x5a, 0xb8, 0x00, 0x19, 0x12, 0xfa, 0x48, 0xc2, 0x9d, 0x19, 0x06, 0x9e, 0x5a, 0xb9, 0x00, 0x19, 0x12, 0xda, 0x48, 0xbb, 0x9d, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x1a, 0x35, +0x80, 0x29, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00, 0xe0, 0xac, 0x98, 0x3c, 0xbb, 0x2a, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0x00, 0xbc, 0xbc, 0x00, 0x78, 0xa8, 0x70, 0xa8, 0x00, 0xbd, 0xbc, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x38, 0xa8, 0x70, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0xbc, 0x1c, 0x00, 0x78, 0xaa, 0x00, 0xbd, 0x1c, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xaa, 0x47, 0xb4, +0xc0, 0x29, 0x00, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x1d, 0xb0, 0x38, 0xa8, 0x40, 0xa8, 0x48, 0xa8, 0x9d, 0xb0, 0x9a, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0x5e, 0x00, 0xbe, 0x58, 0x5f, 0x00, 0xbe, 0x58, 0x60, 0x00, 0xbe, 0x58, 0x61, 0x00, 0x3e, 0xb0, 0x70, 0xaa, 0x78, 0xaa, 0xbe, 0xb0, 0x30, 0xb0, 0xbe, 0x58, 0x2a, 0x1d, 0x31, 0xb0, 0xbe, 0x58, 0x2b, 0x1d, 0x33, 0xb0, 0xbe, 0x58, 0x2c, 0x1d, 0x34, 0xb0, 0xbe, 0x58, 0x2d, 0x1d, 0x00, 0x60, 0x00, 0xbd, 0x31, 0x00, 0x00, 0x60, 0x00, 0xbd, 0x05, 0x00, 0x00, 0xbc, 0x34, 0x00, 0x00, 0x60, 0x00, 0xbd, 0x34, 0x00, 0x00, 0xbc, 0x30, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0xdb, 0xd8, +0x00, 0x2a, 0x30, 0x00, 0x00, 0xbc, 0x04, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x04, 0x00, 0x00, 0xbc, 0x33, 0x00, 0x00, 0xaa, 0x08, 0xaa, 0x10, 0xaa, 0x18, 0xaa, 0x20, 0xaa, 0x28, 0xaa, 0x30, 0xaa, 0x38, 0xaa, 0x40, 0xaa, 0x48, 0xaa, 0x50, 0xaa, 0x58, 0xaa, 0x60, 0xaa, 0x68, 0xaa, 0x70, 0xaa, 0x78, 0xaa, 0x00, 0xbd, 0x33, 0x00, 0x9e, 0x58, 0xc3, 0x1d, 0x06, 0x38, 0xaa, 0x55, 0x02, 0x8a, 0x42, 0xa9, 0x8b, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xab, 0x62, 0x60, 0xb1, 0x68, 0xef, 0xb0, 0x12, 0xa9, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0xbc, 0x04, 0x00, 0x38, 0xa8, 0x00, 0xbd, 0x04, 0x00, 0x9e, 0x58, 0xfd, 0x6c, +0x40, 0x2a, 0x2a, 0x1d, 0xb0, 0xb0, 0x9e, 0x58, 0x2b, 0x1d, 0xb1, 0xb0, 0x9e, 0x58, 0x2c, 0x1d, 0xb3, 0xb0, 0x9e, 0x58, 0x2d, 0x1d, 0xb4, 0xb0, 0x9a, 0xac, 0xfe, 0x91, 0x9e, 0x58, 0x5e, 0x00, 0x02, 0x38, 0x54, 0x00, 0x03, 0x8a, 0xb2, 0xac, 0xfe, 0x93, 0x81, 0x9f, 0xe0, 0xac, 0x7f, 0x91, 0x9a, 0xaa, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0xbc, 0xbc, 0x00, 0x78, 0xaa, 0x70, 0xaa, 0x00, 0xbd, 0xbc, 0x00, 0x00, 0xbc, 0xb1, 0x00, 0x38, 0xaa, 0x70, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x00, 0xbc, 0x1c, 0x00, 0x78, 0xa8, 0x00, 0xbd, 0x1c, 0x00, 0x3e, 0xb0, 0x70, 0xa8, 0x78, 0xa8, 0xbe, 0xb0, 0x19, 0x38, 0x8c, 0x50, 0x00, 0x60, 0xbe, 0x58, 0xe7, 0x00, 0x00, 0x60, 0x49, 0xca, +0x80, 0x2a, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0xea, 0x60, 0x2f, 0x68, 0x07, 0x38, 0x8d, 0x2a, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0xe5, 0xaa, 0x00, 0x61, 0xff, 0x65, 0xff, 0x6d, 0x0c, 0x62, 0x47, 0x63, 0xf8, 0x6b, 0x53, 0x64, 0xf8, 0x6c, 0x19, 0x12, 0x47, 0x38, 0x9d, 0x2a, 0x3d, 0x5b, 0xbd, 0x5c, 0x1a, 0x38, 0xc5, 0xfc, 0x1e, 0x59, 0x96, 0x61, 0xbe, 0x59, 0xfc, 0x1c, 0x3e, 0x59, 0x02, 0xc8, 0x9e, 0x58, 0xc4, 0x1d, 0x06, 0x38, 0x55, 0xaa, 0x02, 0x8a, 0x42, 0xa9, 0x0f, 0x9e, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xff, 0xa9, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xda, 0x1a, 0xbe, 0x58, 0xb3, 0xf8, 0x8c, 0xed, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb1, 0x00, 0xb5, 0xef, 0xfb, 0xcd, +0xc0, 0x2a, 0x9e, 0x59, 0xbc, 0x00, 0x9e, 0x58, 0xb1, 0x00, 0x19, 0x00, 0xbe, 0x58, 0xb1, 0x00, 0x19, 0x48, 0xf6, 0x81, 0xd5, 0xf0, 0x9e, 0x58, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb1, 0x00, 0xbe, 0x58, 0xb0, 0x00, 0x9e, 0x58, 0x36, 0x1d, 0x1d, 0x10, 0x04, 0x8a, 0x9e, 0x58, 0x36, 0x1d, 0x1b, 0x10, 0x20, 0x88, 0xe5, 0xac, 0x1e, 0x90, 0x9e, 0x58, 0xe8, 0x00, 0x02, 0x38, 0x00, 0x05, 0x09, 0x8a, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x08, 0x9e, 0x18, 0x60, 0x08, 0x68, 0xbe, 0x58, 0xe8, 0x00, 0x00, 0x60, 0x05, 0x68, 0xbe, 0x58, 0xe9, 0x00, 0x9e, 0x58, 0xe7, 0x00, 0x02, 0x39, 0x01, 0x00, 0x25, 0xc9, +0x00, 0x2b, 0x03, 0x98, 0x19, 0x00, 0xbe, 0x58, 0xe7, 0x00, 0x9e, 0x5d, 0xd5, 0x00, 0x9e, 0x5b, 0xd4, 0x00, 0x9e, 0x5c, 0xd3, 0x00, 0x04, 0xac, 0x07, 0x90, 0x1e, 0x5b, 0x1e, 0x5c, 0x1e, 0x5d, 0xb5, 0xef, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x9e, 0x59, 0xbc, 0x00, 0x9e, 0x58, 0xb1, 0x00, 0x19, 0x00, 0x01, 0x31, 0x06, 0x8a, 0xbe, 0x58, 0xb1, 0x00, 0xa8, 0x5d, 0x6c, 0x5b, 0x8c, 0x5c, 0xea, 0x9f, 0xd5, 0xf0, 0x9e, 0x58, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x3a, 0x38, 0x3a, 0x38, 0x9e, 0x58, 0xe2, 0x19, 0x00, 0x61, 0x01, 0x30, 0x01, 0x88, 0x05, 0x9e, 0x00, 0x60, 0xbe, 0x58, 0xae, 0x00, 0xd0, 0xaa, 0x3f, 0x9e, 0x9e, 0x58, 0xae, 0x00, 0x9e, 0x59, 0xc0, 0x00, 0x19, 0x48, 0x01, 0x82, 0xe9, 0x6a, +0x40, 0x2b, 0x38, 0x9e, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xd0, 0xa8, 0x74, 0xb0, 0x78, 0xaa, 0xf4, 0xb0, 0x00, 0xbc, 0xb1, 0x00, 0x00, 0xa8, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x4f, 0xb0, 0x50, 0xa8, 0xcf, 0xb0, 0x9e, 0x58, 0xaf, 0x00, 0x9e, 0x59, 0xc5, 0x00, 0x19, 0x48, 0x03, 0x82, 0x74, 0x60, 0x82, 0xb0, 0xf7, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0xaf, 0x00, 0x4f, 0xb0, 0x50, 0xaa, 0xcf, 0xb0, 0x00, 0xbc, 0xb1, 0x00, 0x00, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x20, 0x60, 0x07, 0x38, 0x78, 0x2b, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x19, 0x38, 0x02, 0x48, 0xb9, 0xaa, 0x00, 0x9e, 0x3a, 0x38, 0x3a, 0x38, 0x38, 0x27, +0x80, 0x2b, 0x52, 0xb2, 0x3a, 0xac, 0xfd, 0x93, 0x78, 0xab, 0x5a, 0x62, 0xe1, 0x6a, 0xac, 0xb2, 0x00, 0x62, 0xff, 0x3f, 0x7a, 0x38, 0xac, 0xb2, 0x78, 0xa9, 0x3a, 0x38, 0x00, 0x62, 0xac, 0xb2, 0xff, 0x3f, 0x0f, 0x59, 0x3a, 0x38, 0x01, 0x62, 0xef, 0x3f, 0x99, 0x2b, 0x05, 0x5d, 0x25, 0x5c, 0xbc, 0x48, 0x02, 0x88, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x62, 0x3a, 0x38, 0x9e, 0x58, 0xbf, 0x00, 0x19, 0x10, 0x0f, 0x61, 0x27, 0x69, 0x9e, 0x5b, 0xe8, 0x00, 0x9e, 0x58, 0xd5, 0x00, 0x9e, 0x5a, 0xd4, 0x00, 0x9e, 0x5c, 0xd3, 0x00, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0x65, 0x9e, 0x5e, 0xe9, 0x19, 0xa0, 0xac, 0x26, 0x90, 0x9e, 0x5b, 0xe8, 0x00, 0x30, 0x67, 0x0b, 0x6f, 0xa6, 0x40, 0x60, 0x03, 0xe0, 0x07, 0x00, 0xa9, 0x9e, 0x58, 0xed, 0x19, 0x9e, 0x5a, 0xdb, 0x0f, +0xc0, 0x2b, 0xee, 0x19, 0x9e, 0x5c, 0xef, 0x19, 0x0c, 0x58, 0x4c, 0x5a, 0x8c, 0x5c, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0xad, 0x07, 0x92, 0xc2, 0x38, 0x01, 0x00, 0x07, 0x38, 0xd4, 0x2b, 0xe5, 0x59, 0x3d, 0x5b, 0x1a, 0x38, 0x19, 0x05, 0x9e, 0x58, 0xe8, 0x19, 0xb8, 0x48, 0xdb, 0x81, 0x29, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0x30, 0x67, 0x0b, 0x6f, 0x65, 0x03, 0xe5, 0x07, 0x00, 0xa9, 0x9e, 0x58, 0xed, 0x19, 0x9e, 0x5a, 0xee, 0x19, 0x9e, 0x5c, 0xef, 0x19, 0x0c, 0x58, 0x4c, 0x5a, 0x8c, 0x5c, 0xbe, 0x58, 0xed, 0x19, 0xbe, 0x5a, 0xee, 0x19, 0xbe, 0x5c, 0xef, 0x19, 0x00, 0xad, 0x0b, 0x92, 0xc2, 0x38, 0x01, 0x00, 0x07, 0x38, 0xfd, 0x2b, 0xe3, 0x59, 0x3b, 0x5b, 0x70, 0x3b, 0xe8, 0x19, 0xf0, 0x3f, 0xe8, 0x19, 0x1a, 0x38, 0x19, 0x05, 0x9e, 0x58, 0xe7, 0x59, +0x00, 0x2c, 0xe8, 0x19, 0xb8, 0x48, 0xd8, 0x81, 0x00, 0x9e, 0x3a, 0x38, 0x52, 0xb1, 0x39, 0xac, 0xfd, 0x93, 0xfd, 0xab, 0xf5, 0xab, 0x1a, 0x38, 0x1a, 0x38, 0x02, 0xa9, 0x00, 0xbd, 0xb0, 0x00, 0x1a, 0x38, 0x1a, 0x38, 0x02, 0xab, 0x1a, 0x38, 0x7a, 0xad, 0xfe, 0x93, 0xfd, 0xa9, 0xf5, 0xa9, 0x3a, 0x38, 0x00, 0xbc, 0xaa, 0x00, 0x10, 0x48, 0x00, 0x00, 0x01, 0x8a, 0x42, 0xa9, 0x40, 0x60, 0x21, 0x71, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0c, 0x60, 0x27, 0x71, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0a, 0x60, 0x9e, 0x59, 0xe4, 0x19, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x14, 0x60, 0x9e, 0x59, 0xf0, 0x04, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x16, 0x60, 0x9e, 0x59, 0xba, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x18, 0x60, 0x03, 0x68, 0x9e, 0x59, 0xbf, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x91, 0xac, +0x40, 0x2c, 0x42, 0xa9, 0x16, 0x60, 0x9e, 0x59, 0xbb, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x24, 0x60, 0x9e, 0x59, 0xbc, 0x00, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0xe7, 0x00, 0x10, 0x48, 0x02, 0x00, 0x01, 0x9a, 0x42, 0xa9, 0x9e, 0x58, 0x1b, 0x1f, 0x10, 0x48, 0xaa, 0x55, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x1c, 0x1f, 0x10, 0x48, 0x55, 0xaa, 0x01, 0x8a, 0x42, 0xa9, 0x9e, 0x58, 0x1b, 0x1f, 0x9e, 0x59, 0x1c, 0x1f, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1a, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1b, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1c, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x00, 0x61, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xff, 0xad, 0x01, 0x92, 0x42, 0xa9, 0x9e, 0x58, 0xe8, 0x00, 0x06, 0xb1, +0x80, 0x2c, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x9e, 0x58, 0x1f, 0x00, 0x10, 0x48, 0x01, 0x00, 0x01, 0x8a, 0x42, 0xa9, 0xed, 0xac, 0x5f, 0x92, 0x2c, 0x60, 0x1b, 0x68, 0x1f, 0x61, 0x1f, 0x69, 0x14, 0x62, 0x19, 0x12, 0x47, 0x38, 0x9a, 0x2c, 0x05, 0x5b, 0x70, 0x48, 0x1f, 0x1f, 0x01, 0x8a, 0x42, 0xa9, 0x1a, 0x38, 0x02, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd5, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0a, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd8, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x05, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd7, 0x1a, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0e, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0x58, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x0c, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0x57, 0x01, 0x0f, 0x53, +0xc0, 0x2c, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x09, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xba, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xaf, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xc7, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb0, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xc8, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb7, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xcf, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0xb8, 0x60, 0xf8, 0x68, 0x03, 0x58, 0x9e, 0x59, 0xd1, 0x01, 0x19, 0x48, 0x01, 0x8a, 0x42, 0xa9, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0xf3, 0xec, 0x03, 0xed, 0x2d, 0xed, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x1f, 0x1e, 0xbe, 0x58, 0x20, 0x1e, 0xbe, 0x58, 0x21, 0x1e, 0x22, 0x61, 0x1e, 0x69, 0x23, 0x62, 0x47, 0x38, 0x01, 0x2d, 0x1d, 0x59, 0xec, 0x10, +0x00, 0x2d, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x30, 0x60, 0x0b, 0x68, 0x9e, 0x59, 0xe8, 0x00, 0x9e, 0x5a, 0xe9, 0x00, 0x9e, 0x5f, 0xfe, 0x1b, 0x9e, 0x5e, 0xfd, 0x1b, 0x19, 0x16, 0x00, 0x63, 0x00, 0x64, 0x00, 0x65, 0xc7, 0x38, 0x1d, 0x2d, 0x68, 0x5b, 0x8c, 0x5c, 0xac, 0x5d, 0x25, 0x5e, 0x16, 0x16, 0xdd, 0x5a, 0xd2, 0x3e, 0x19, 0x1e, 0x01, 0x96, 0x7b, 0xa8, 0x19, 0x00, 0x75, 0x3b, 0x1f, 0x1e, 0x95, 0x3c, 0x20, 0x1e, 0xb5, 0x3d, 0x21, 0x1e, 0xbe, 0x5b, 0x1f, 0x1e, 0xbe, 0x5c, 0x20, 0x1e, 0xbe, 0x5d, 0x21, 0x1e, 0x19, 0x17, 0xdf, 0x99, 0x3a, 0x38, 0x9e, 0x5b, 0x1f, 0x1e, 0x9e, 0x5c, 0x20, 0x1e, 0x9e, 0x5a, 0x21, 0x1e, 0x00, 0x65, 0x9e, 0x5f, 0xfd, 0x1b, 0x19, 0x17, 0x7b, 0xac, 0x0e, 0x92, 0xf0, 0x38, 0xe9, 0x00, 0x22, 0x61, 0x1e, 0x69, 0x23, 0x66, 0xc7, 0x38, 0x45, 0x2d, 0xcc, 0x4f, +0x40, 0x2d, 0x03, 0x5e, 0x36, 0x06, 0xdd, 0x59, 0x10, 0x38, 0xfd, 0x1b, 0x1a, 0x38, 0x19, 0x05, 0x46, 0x5a, 0x8a, 0x5c, 0x6a, 0x5b, 0x19, 0x17, 0xeb, 0x95, 0xbe, 0x5d, 0x46, 0x1e, 0x3a, 0x38, 0x9e, 0x5b, 0x46, 0x1e, 0x18, 0x13, 0x0d, 0x8a, 0x24, 0x62, 0x22, 0x64, 0x1e, 0x6c, 0x47, 0x38, 0x5f, 0x2d, 0x00, 0x61, 0x83, 0x58, 0x78, 0xac, 0x02, 0x90, 0xff, 0x61, 0xff, 0x69, 0x3c, 0x5b, 0x1d, 0x5c, 0x3a, 0x38, 0x9e, 0x5b, 0xe9, 0x00, 0x22, 0x64, 0x1e, 0x6c, 0x85, 0x5d, 0x24, 0x67, 0x9e, 0x5e, 0xfd, 0x1b, 0x19, 0x16, 0xc7, 0x38, 0x6e, 0x2d, 0x75, 0x16, 0xdd, 0x5b, 0x1a, 0x38, 0x85, 0x5d, 0x19, 0x17, 0xf5, 0x99, 0x3a, 0x38, 0x9e, 0x58, 0x15, 0x1e, 0x00, 0xac, 0x21, 0x90, 0xff, 0x61, 0x07, 0x69, 0x34, 0x38, 0xe3, 0x19, 0x18, 0x10, 0x1b, 0x88, 0x9e, 0x58, 0x1a, 0x1e, 0x02, 0x61, 0x23, 0x6a, +0x80, 0x2d, 0x19, 0x48, 0x16, 0x88, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x9e, 0x58, 0xda, 0x1a, 0xbe, 0x58, 0xb3, 0xf8, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0x1a, 0x1e, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x1e, 0xbe, 0x58, 0x1c, 0x1e, 0xff, 0x60, 0xbe, 0x58, 0x1d, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x1a, 0x10, 0x04, 0x8a, 0xa2, 0xed, 0xd8, 0xed, 0x08, 0xee, 0x2f, 0xee, 0x3a, 0x38, 0x9e, 0x5e, 0xe9, 0x00, 0x00, 0x65, 0xbe, 0x5d, 0x48, 0x1e, 0x9e, 0x5f, 0xfd, 0x1b, 0xbe, 0x5f, 0x49, 0x1e, 0x19, 0x17, 0xe6, 0x00, 0x03, 0x5b, 0x10, 0x38, 0xfd, 0x1b, 0x9e, 0x59, 0xfe, 0x1b, 0x1a, 0x11, 0x27, 0x38, 0xc7, 0x2d, 0x03, 0x5a, 0x10, 0x39, 0xfd, 0x1b, 0x23, 0x5c, 0x43, 0x13, 0x09, 0x9a, 0x44, 0x14, 0x07, 0x9a, 0x72, 0x39, 0x16, 0x1e, 0x03, 0x98, 0x68, 0xe1, +0xc0, 0x2d, 0x92, 0x39, 0x16, 0x1e, 0x01, 0x9a, 0x19, 0x05, 0x41, 0x5b, 0x10, 0x38, 0xfd, 0x1b, 0x1a, 0x38, 0x9e, 0x5b, 0x48, 0x1e, 0x7d, 0x48, 0x02, 0x94, 0xbe, 0x5d, 0x48, 0x1e, 0x9e, 0x5b, 0x49, 0x1e, 0x7d, 0x48, 0x02, 0x9a, 0xbe, 0x5d, 0x49, 0x1e, 0x00, 0x65, 0x19, 0x17, 0xd5, 0x95, 0x3a, 0x38, 0x9e, 0x5f, 0x1a, 0x1e, 0x19, 0x07, 0x18, 0x17, 0x01, 0x9a, 0x00, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x58, 0x48, 0x1e, 0x12, 0x39, 0x49, 0x1e, 0x06, 0x62, 0xd6, 0xac, 0x01, 0x90, 0x02, 0x62, 0xbe, 0x5a, 0x17, 0x1e, 0x12, 0x3a, 0x17, 0x1e, 0x08, 0x9a, 0x01, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x5f, 0x1b, 0x1e, 0x19, 0x07, 0xbe, 0x5f, 0x1b, 0x1e, 0x3a, 0x38, 0x00, 0x63, 0x9e, 0x58, 0x48, 0x1e, 0x12, 0x39, 0x49, 0x1e, 0x06, 0x62, 0xd6, 0xac, 0x01, 0x90, 0x02, 0x62, 0xbe, 0x5a, 0x6e, 0x02, +0x00, 0x2e, 0x17, 0x1e, 0x12, 0x3a, 0x17, 0x1e, 0x01, 0x9a, 0x01, 0x63, 0xbe, 0x5b, 0x1e, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x18, 0x10, 0x1f, 0x8a, 0x9e, 0x58, 0x1b, 0x1e, 0x02, 0x39, 0x05, 0x00, 0x0a, 0x8a, 0x9e, 0x59, 0x48, 0x1e, 0x32, 0x3a, 0x1d, 0x1e, 0x18, 0x98, 0xbe, 0x59, 0x1d, 0x1e, 0xbe, 0x58, 0x1c, 0x1e, 0x13, 0x9e, 0x9e, 0x59, 0x15, 0x1e, 0x09, 0xac, 0x08, 0x92, 0x02, 0x67, 0xbe, 0x5f, 0x1a, 0x1e, 0x9e, 0x5f, 0x1c, 0x1e, 0xbe, 0x5f, 0x1b, 0x1e, 0x07, 0x9e, 0x00, 0x67, 0xbe, 0x5f, 0x1b, 0x1e, 0x03, 0x9e, 0x00, 0x63, 0xbe, 0x5b, 0x1e, 0x1e, 0x3a, 0x38, 0x9e, 0x58, 0x1a, 0x1e, 0x18, 0x10, 0x16, 0x8a, 0x9e, 0x58, 0x1b, 0x1e, 0x9e, 0x59, 0x15, 0x1e, 0x11, 0xac, 0x02, 0x90, 0x08, 0x58, 0x08, 0x58, 0xd6, 0xac, 0x03, 0x90, 0x00, 0x38, 0x8a, 0x2e, 0x02, 0x9e, 0x2a, 0x8c, +0x40, 0x2e, 0x00, 0x38, 0x8f, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xd6, 0x1a, 0x01, 0x00, 0x78, 0xa8, 0xbe, 0x58, 0x47, 0x1e, 0x3a, 0x38, 0x48, 0x62, 0x0e, 0x6a, 0x9e, 0x5b, 0xfd, 0x1b, 0x9e, 0x5c, 0xfd, 0x1b, 0x41, 0x5d, 0x00, 0x61, 0x00, 0x67, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0xc7, 0x38, 0x5d, 0x2e, 0xa3, 0x58, 0x18, 0x10, 0x02, 0x94, 0x19, 0x07, 0x20, 0x01, 0xa3, 0x05, 0x21, 0x58, 0x00, 0x61, 0x02, 0x58, 0x1c, 0x5f, 0x01, 0x59, 0x32, 0x39, 0x18, 0x1e, 0x0d, 0x9a, 0x41, 0x5d, 0x9e, 0x5e, 0xfe, 0x1b, 0x19, 0x16, 0x08, 0x58, 0xc7, 0x38, 0x72, 0x2e, 0xa3, 0x5e, 0x18, 0x06, 0x02, 0x9a, 0xc0, 0x06, 0xdb, 0x5d, 0xa3, 0x05, 0x19, 0x02, 0x19, 0x14, 0xda, 0x89, 0x3a, 0x38, 0x01, 0x60, 0xbe, 0x58, 0x15, 0x1e, 0x40, 0x60, 0xbe, 0x58, 0x16, 0x1e, 0xff, 0x60, 0x1f, 0x68, 0xbe, 0x58, 0x16, 0x16, +0x80, 0x2e, 0x18, 0x1e, 0x80, 0x60, 0xbe, 0x58, 0x19, 0x1e, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0x8c, 0xed, 0x3a, 0x38, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x18, 0x00, 0x30, 0x00, 0x38, 0x00, 0x3c, 0xab, 0x3a, 0x38, 0xfa, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x56, 0x01, 0xd6, 0x1a, 0xd7, 0x1a, 0xd8, 0x1a, 0x57, 0x01, 0x5b, 0x01, 0x2d, 0x62, 0x01, 0x6a, 0x26, 0x63, 0x04, 0x6b, 0xeb, 0x64, 0x00, 0x67, 0x10, 0x6f, 0xef, 0x3a, 0xb6, 0x2e, 0x45, 0x5d, 0x65, 0x5e, 0x85, 0x58, 0xbb, 0x5e, 0x3a, 0x38, 0x9e, 0x5e, 0x20, 0x04, 0xc6, 0x5e, 0x7c, 0x62, 0x01, 0x6a, 0x94, 0x63, 0x01, 0x6b, 0x17, 0x64, 0xcd, 0x1d, +0xc0, 0x2e, 0x01, 0x6c, 0x01, 0x65, 0x01, 0x6d, 0xef, 0x3a, 0xca, 0x2e, 0x45, 0x58, 0xc0, 0x40, 0x1d, 0x5c, 0x65, 0x58, 0xc0, 0x40, 0x1d, 0x5d, 0x3a, 0x38, 0xef, 0xa8, 0x9e, 0x58, 0x17, 0x04, 0x9e, 0x59, 0x1f, 0x04, 0x01, 0x10, 0x19, 0x48, 0x03, 0x9a, 0xbe, 0x58, 0x18, 0x04, 0x02, 0x9e, 0xbe, 0x59, 0x18, 0x04, 0x9e, 0x58, 0xb5, 0x00, 0x18, 0x10, 0x03, 0x8a, 0x19, 0x10, 0x01, 0x8a, 0x09, 0x9e, 0x9e, 0x58, 0x1d, 0x04, 0x18, 0x10, 0x04, 0x8a, 0x19, 0x10, 0xbe, 0x58, 0x1d, 0x04, 0x01, 0x9e, 0xef, 0xaa, 0x3a, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb6, 0xb8, 0x00, 0x2f, 0x25, 0x00, 0x25, 0x00, 0x04, 0x00, 0x08, 0x00, 0x30, 0x00, 0x01, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x02, 0x00, 0x10, 0x00, 0x0a, 0x00, 0x03, 0x00, 0x12, 0x00, 0x0e, 0x00, 0x08, 0x00, 0x08, 0x00, 0x40, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x04, 0x00, 0x01, 0x00, 0x05, 0x00, 0x05, 0x00, 0x13, 0x00, 0x50, 0x00, 0x38, 0x00, 0x18, 0x00, 0x1a, 0x00, 0x24, 0x00, 0x30, 0x00, 0x20, 0x00, 0x24, 0x00, 0x30, 0x00, 0x14, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x55, 0x2a, 0x40, 0x2f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x27, 0x80, 0x2f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00, 0x10, 0xef, 0x00, 0xbc, 0xb1, 0x00, 0x30, 0xa8, 0x28, 0xa8, 0x20, 0xa8, 0x68, 0xa8, 0x60, 0xaa, 0x00, 0xbd, 0xb1, 0x00, 0x9e, 0x58, 0x01, 0xf8, 0x08, 0xaa, 0xbe, 0x58, 0x01, 0xf8, 0x3e, 0xb0, 0x60, 0xaa, 0xbe, 0xb0, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x1f, 0x60, 0x4e, 0x68, 0x07, 0x38, 0xb0, 0x2f, 0x1a, 0x38, 0x1a, 0x38, 0x1a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0x01, 0x00, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xb0, 0x00, 0xdb, 0xef, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0xff, 0x60, 0xff, 0x68, 0x62, 0x0c, @@ -190,9 +190,9 @@ 0x40, 0x31, 0x7d, 0x5a, 0x1a, 0x38, 0x8e, 0x61, 0x1b, 0x69, 0x62, 0x62, 0x1e, 0x6a, 0x9e, 0x58, 0x5d, 0x1a, 0x19, 0x10, 0x07, 0x38, 0x4d, 0x31, 0x25, 0x5b, 0x7d, 0x5a, 0x1a, 0x38, 0x09, 0x61, 0x1a, 0x69, 0x9c, 0x62, 0x1e, 0x6a, 0x9e, 0x58, 0x5d, 0x1a, 0x19, 0x10, 0x07, 0x38, 0x59, 0x31, 0x25, 0x5b, 0x7d, 0x5a, 0x1a, 0x38, 0x9e, 0x5a, 0xec, 0x19, 0x9e, 0x59, 0xeb, 0x19, 0x9e, 0x58, 0xea, 0x19, 0xbe, 0x5a, 0x5b, 0x1a, 0xbe, 0x59, 0xaf, 0x1a, 0xbe, 0x58, 0x5a, 0x1a, 0x9e, 0x58, 0xea, 0x1e, 0xbe, 0x58, 0x4c, 0x04, 0x9e, 0x58, 0xeb, 0x1e, 0xbe, 0x58, 0x4d, 0x04, 0x9e, 0x58, 0xec, 0x1e, 0xbe, 0x58, 0x4e, 0x04, 0x9e, 0x58, 0xed, 0x1e, 0xbe, 0x58, 0x4f, 0x04, 0x00, 0x60, 0xbe, 0x58, 0x43, 0x1a, 0x2c, 0xf2, 0x1a, 0x38, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xaa, 0xbe, 0x58, 0x00, 0xf8, 0x61, 0xf8, 0x80, 0x31, 0xff, 0x60, 0xff, 0x68, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x9e, 0x58, 0x00, 0xf8, 0x10, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x9f, 0xf0, 0x1a, 0x38, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0xbe, 0x58, 0x10, 0xf8, 0x3d, 0xf3, 0x1a, 0x38, 0xf9, 0x60, 0x01, 0x68, 0x03, 0x59, 0x05, 0x62, 0x0f, 0x63, 0x1a, 0x38, 0x3a, 0x48, 0x98, 0x3a, 0x31, 0x33, 0x1a, 0x38, 0x3b, 0x48, 0x18, 0x3a, 0x2a, 0x33, 0x1a, 0x38, 0xf9, 0x60, 0x01, 0x68, 0xfa, 0x61, 0x01, 0x69, 0x00, 0x62, 0x5b, 0x58, 0x5b, 0x59, 0x1a, 0x38, 0xe1, 0xf1, 0x65, 0xf3, 0x9e, 0x58, 0xe7, 0x00, 0x1a, 0x10, 0x08, 0x88, 0x9e, 0x58, 0xe8, 0x00, 0x9e, 0x59, 0xe9, 0x00, 0x19, 0x48, 0x01, 0x88, 0x42, 0xa9, 0x1d, 0x39, 0x1a, 0x38, 0x1a, 0x38, 0x3a, 0x38, 0x11, 0x46, 0xc0, 0x31, 0x1e, 0x58, 0x1e, 0x59, 0x1e, 0x5a, 0xb5, 0x61, 0x02, 0x69, 0x29, 0x62, 0x03, 0x6a, 0x2f, 0x3f, 0xcc, 0x31, 0x23, 0x58, 0x1b, 0x5a, 0x19, 0x01, 0x19, 0x02, 0x02, 0x61, 0x02, 0x69, 0x3d, 0x62, 0x02, 0x6a, 0x0f, 0x3f, 0xd6, 0x31, 0x23, 0x58, 0x1b, 0x5a, 0x19, 0x01, 0x19, 0x02, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x3a, 0x38, 0x34, 0xf8, 0x82, 0xf3, 0xbe, 0xf3, 0x02, 0xf4, 0x9d, 0xf4, 0x3a, 0x38, 0x02, 0x62, 0x02, 0x6a, 0xb5, 0x64, 0x02, 0x6c, 0xf1, 0x61, 0x31, 0x69, 0x2f, 0x3f, 0xee, 0x31, 0x29, 0x5b, 0x43, 0x03, 0x63, 0x5d, 0xbb, 0x5c, 0x19, 0x01, 0x19, 0x04, 0x1a, 0x38, 0x3a, 0x38, 0x00, 0x00, 0x04, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x10, 0x00, 0x14, 0x00, 0x01, 0x00, 0x05, 0x00, 0x09, 0x00, 0x0d, 0x00, 0x11, 0x00, 0x15, 0x00, 0x02, 0x00, 0x06, 0x00, 0x0a, 0x00, 0xdb, 0x62, -0x00, 0x32, 0x0e, 0x00, 0x12, 0x00, 0x16, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x25, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x3d, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3a, 0x00, 0x3e, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x3a, 0x38, 0xfa, 0x60, 0x01, 0x68, 0x03, 0x58, 0x00, 0xac, 0x02, 0x90, 0x77, 0x9e, 0x3a, 0x38, 0x9e, 0x58, 0x1b, 0x1e, 0xd6, 0xac, 0x03, 0x92, 0x00, 0x38, 0x86, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x81, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xda, 0x1a, 0x20, 0x01, 0x69, 0x92, +0x00, 0x32, 0x0e, 0x00, 0x12, 0x00, 0x16, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0b, 0x00, 0x0f, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x20, 0x00, 0x24, 0x00, 0x28, 0x00, 0x2c, 0x00, 0x30, 0x00, 0x34, 0x00, 0x38, 0x00, 0x3c, 0x00, 0x19, 0x00, 0x1d, 0x00, 0x21, 0x00, 0x25, 0x00, 0x29, 0x00, 0x2d, 0x00, 0x31, 0x00, 0x35, 0x00, 0x39, 0x00, 0x3d, 0x00, 0x1a, 0x00, 0x1e, 0x00, 0x22, 0x00, 0x26, 0x00, 0x2a, 0x00, 0x2e, 0x00, 0x32, 0x00, 0x36, 0x00, 0x3a, 0x00, 0x3e, 0x00, 0x1b, 0x00, 0x1f, 0x00, 0x23, 0x00, 0x27, 0x00, 0x2b, 0x00, 0x2f, 0x00, 0x3a, 0x38, 0xfa, 0x60, 0x01, 0x68, 0x03, 0x58, 0x00, 0xac, 0x02, 0x90, 0x77, 0x9e, 0x3a, 0x38, 0x9e, 0x58, 0x1b, 0x1e, 0xd6, 0xac, 0x03, 0x92, 0x00, 0x38, 0x99, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x94, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xda, 0x1a, 0x20, 0x01, 0x8f, 0x92, 0x40, 0x32, 0xb3, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xdb, 0x1a, 0xb4, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xdc, 0x1a, 0xb9, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x20, 0x61, 0xb1, 0x60, 0xf8, 0x68, 0x9e, 0x5a, 0xc9, 0x00, 0x18, 0x12, 0x01, 0x8a, 0x20, 0x61, 0x3b, 0x58, 0xaa, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xa8, 0x21, 0xa8, 0x29, 0xa8, 0x31, 0xa8, 0x39, 0xa8, 0x41, 0xaa, 0x49, 0xaa, 0x51, 0xaa, 0x59, 0xaa, 0x79, 0xa8, 0x3b, 0x58, 0xab, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xa8, 0x09, 0xa8, 0x11, 0xa8, 0x19, 0xa8, 0x21, 0xa8, 0x29, 0xaa, 0x31, 0xaa, 0x39, 0xaa, 0x41, 0xaa, 0x3b, 0x58, 0xe0, 0x61, 0x1a, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xac, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xe6, 0x61, 0x1a, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xad, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x12, 0x8a, -0x80, 0x32, 0x5b, 0x58, 0x20, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd4, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x26, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd5, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x00, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd0, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x06, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd1, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xf9, 0x62, 0x01, 0x6a, 0x43, 0x5a, 0xae, 0x64, 0xf8, 0x6c, 0x5b, 0x5c, 0x1a, 0x38, 0x89, 0x9f, 0x9e, 0x58, 0x1b, 0x1e, 0xd6, 0xac, 0x03, 0x92, 0x00, 0x38, 0x86, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x81, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xdd, 0x1a, 0x20, 0x01, 0xb3, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xde, 0x1a, 0xb4, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xdf, 0x1a, 0x3f, 0xd9, +0x80, 0x32, 0x5b, 0x58, 0x20, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd4, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x26, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd5, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x00, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd0, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x06, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0xd1, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xf9, 0x62, 0x01, 0x6a, 0x43, 0x5a, 0xae, 0x64, 0xf8, 0x6c, 0x5b, 0x5c, 0x1a, 0x38, 0x89, 0x9f, 0x9e, 0x58, 0x1b, 0x1e, 0xd6, 0xac, 0x03, 0x92, 0x00, 0x38, 0x99, 0x2e, 0x02, 0x9e, 0x00, 0x38, 0x94, 0x2e, 0x09, 0x58, 0x9e, 0x59, 0xdd, 0x1a, 0x20, 0x01, 0xb3, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xde, 0x1a, 0xb4, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x9e, 0x59, 0xdf, 0x1a, 0x65, 0xd9, 0xc0, 0x32, 0xb9, 0x60, 0xf8, 0x68, 0x3b, 0x58, 0x20, 0x61, 0xb1, 0x60, 0xf8, 0x68, 0x9e, 0x5a, 0xc9, 0x00, 0x18, 0x12, 0x01, 0x8a, 0x20, 0x61, 0x3b, 0x58, 0xaa, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xa8, 0x21, 0xaa, 0x29, 0xaa, 0x31, 0xaa, 0x39, 0xaa, 0x41, 0xa8, 0x49, 0xa8, 0x51, 0xa8, 0x59, 0xa8, 0x79, 0xa8, 0x3b, 0x58, 0xab, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xa8, 0x09, 0xaa, 0x11, 0xaa, 0x19, 0xaa, 0x21, 0xaa, 0x29, 0xa8, 0x31, 0xa8, 0x39, 0xa8, 0x41, 0xa8, 0x3b, 0x58, 0xec, 0x61, 0x1a, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xac, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xf6, 0x61, 0x1a, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xad, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x2c, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xd6, 0x60, 0xf8, 0x68, 0xe1, 0xb8, 0x00, 0x33, 0x23, 0x5a, 0x5b, 0x58, 0x36, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xd7, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x0c, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xd2, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0x16, 0x61, 0x1b, 0x69, 0x30, 0x39, 0xf9, 0x01, 0x1e, 0x11, 0xd3, 0x60, 0xf8, 0x68, 0x23, 0x5a, 0x5b, 0x58, 0xf9, 0x62, 0x01, 0x6a, 0x43, 0x5a, 0x06, 0x63, 0x43, 0x12, 0x44, 0x3a, 0xff, 0x00, 0xfe, 0x5a, 0xae, 0x64, 0xf8, 0x6c, 0x5b, 0x5c, 0x1a, 0x38, 0x08, 0x9f, 0xf9, 0x60, 0x01, 0x68, 0x03, 0x59, 0x19, 0x01, 0x3b, 0x58, 0x98, 0x3f, 0x79, 0x31, 0xf9, 0x60, 0x01, 0x68, 0x03, 0x59, 0x19, 0x01, 0x3b, 0x58, 0xfa, 0x61, 0x01, 0x69, 0x23, 0x58, 0x00, 0xa8, 0x1b, 0x59, 0x98, 0x3f, 0x79, 0x31, 0xfa, 0x60, 0x01, 0x68, 0x03, 0x59, 0xbf, 0xf4, 0x40, 0x33, 0x01, 0xac, 0x01, 0x90, 0x11, 0x9e, 0xda, 0x65, 0xf8, 0x6d, 0xf9, 0x63, 0x01, 0x6b, 0x63, 0x5b, 0x04, 0x60, 0x03, 0x40, 0x02, 0x63, 0x02, 0x6b, 0x03, 0x04, 0x6f, 0x38, 0x51, 0x33, 0xa5, 0x5e, 0xdd, 0x5c, 0x1a, 0x38, 0xdb, 0x5c, 0x10, 0x9e, 0xde, 0x65, 0xf8, 0x6d, 0xf9, 0x63, 0x01, 0x6b, 0x63, 0x5b, 0x04, 0x60, 0x03, 0x40, 0x02, 0x63, 0x02, 0x6b, 0x03, 0x04, 0x6f, 0x38, 0x62, 0x33, 0xa5, 0x5e, 0xdd, 0x5c, 0x1a, 0x38, 0x00, 0x9e, 0x3a, 0x38, 0xaa, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x21, 0xaa, 0x29, 0xaa, 0x31, 0xaa, 0x39, 0xaa, 0x41, 0xaa, 0x49, 0xaa, 0x51, 0xaa, 0x59, 0xaa, 0x3b, 0x58, 0xab, 0x60, 0xf8, 0x68, 0x03, 0x59, 0x01, 0xaa, 0x09, 0xaa, 0x11, 0xaa, 0x19, 0xaa, 0x21, 0xaa, 0x29, 0xaa, 0x31, 0xaa, 0x39, 0xaa, 0x41, 0xaa, 0xae, 0x60, 0xf8, 0x68, 0x00, 0x61, 0xfc, 0x92, @@ -217,21 +217,21 @@ 0x00, 0x38, 0x00, 0x61, 0x9e, 0x5b, 0xbb, 0x00, 0xb1, 0x70, 0x03, 0x40, 0x04, 0x04, 0x40, 0x3e, 0xb6, 0x5e, 0xc9, 0x5e, 0xd0, 0x48, 0x48, 0x00, 0x03, 0x8a, 0x86, 0x04, 0xbb, 0x5c, 0x03, 0x9e, 0x0f, 0x77, 0x19, 0x07, 0x0f, 0x7f, 0xb0, 0x72, 0x19, 0x02, 0xb0, 0x7a, 0x19, 0x07, 0x9d, 0x9f, 0xb1, 0x70, 0x19, 0x00, 0xb1, 0x78, 0x8b, 0x9f, 0x00, 0x60, 0xbe, 0x58, 0x0f, 0xf8, 0x00, 0x60, 0xbe, 0x58, 0x10, 0xf8, 0x44, 0xab, 0x9e, 0x58, 0x00, 0xf8, 0x00, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x3a, 0x38, 0x40, 0x60, 0x57, 0x68, 0xe0, 0x63, 0x1a, 0x6b, 0x40, 0x61, 0x19, 0x11, 0x27, 0x38, 0x32, 0x38, 0x0b, 0x5a, 0x5d, 0x5b, 0x1a, 0x38, 0x3a, 0x38, 0x06, 0x71, 0x51, 0xac, 0x1c, 0x92, 0x09, 0xac, 0x36, 0x92, 0x01, 0xac, 0x34, 0x92, 0x0a, 0x60, 0xbe, 0x58, 0xc1, 0x1a, 0x03, 0x60, 0xbe, 0x58, 0x40, 0x7b, 0x40, 0x38, 0xc2, 0x1a, 0x12, 0x60, 0xbe, 0x58, 0xc3, 0x1a, 0x0e, 0x60, 0xbe, 0x58, 0xc4, 0x1a, 0x9e, 0x58, 0xd6, 0x1a, 0xbe, 0x58, 0x47, 0x1e, 0xbe, 0x58, 0x04, 0xf8, 0x01, 0x60, 0x23, 0x78, 0x00, 0x60, 0xbe, 0x58, 0x1b, 0x1e, 0x36, 0x9e, 0x48, 0x60, 0xbe, 0x58, 0xc1, 0x1a, 0x48, 0x60, 0xbe, 0x58, 0xc2, 0x1a, 0x60, 0x60, 0xbe, 0x58, 0xc3, 0x1a, 0x60, 0x60, 0xbe, 0x58, 0xc4, 0x1a, 0x50, 0x60, 0x02, 0x68, 0x1c, 0x78, 0x02, 0x60, 0x23, 0x78, 0x9e, 0x59, 0x47, 0x1e, 0x9e, 0x58, 0xd6, 0x1a, 0x19, 0x48, 0x1f, 0x88, 0x9e, 0x59, 0xd6, 0x1a, 0xbe, 0x59, 0x04, 0xf8, 0x1a, 0x9e, 0x20, 0x60, 0xbe, 0x58, 0xc1, 0x1a, 0x20, 0x60, 0xbe, 0x58, 0xc2, 0x1a, 0x30, 0x60, 0xbe, 0x58, 0xc3, 0x1a, 0x30, 0x60, 0xbe, 0x58, 0xc4, 0x1a, 0x80, 0x60, 0x1c, 0x78, 0x01, 0x60, 0x23, 0x78, 0x9e, 0x59, 0x59, 0x63, 0x80, 0x38, 0x47, 0x1e, 0x9e, 0x58, 0xd6, 0x1a, 0x19, 0x48, 0x04, 0x88, 0x9e, 0x59, 0xd6, 0x1a, 0xbe, 0x59, 0x04, 0xf8, 0x3a, 0x38, 0xaa, 0x66, 0x15, 0x6e, 0xc3, 0x5d, 0xa4, 0x3d, 0xff, 0x0f, 0xbb, 0x5e, 0x9e, 0x5f, 0x4b, 0x1a, 0xe2, 0x38, 0x01, 0x00, 0x0b, 0x9a, 0xe2, 0x3e, 0x01, 0x00, 0xc7, 0x38, 0x9f, 0x38, 0xe0, 0x3e, 0xaa, 0x15, 0xc3, 0x5d, 0xa4, 0x3d, 0xff, 0x00, 0xbb, 0x5e, 0x19, 0x17, 0x1a, 0x38, 0x3a, 0x38, 0x3c, 0x60, 0xbe, 0x58, 0xce, 0x04, 0x0f, 0x60, 0xbe, 0x58, 0xd0, 0x04, 0x06, 0x60, 0xbe, 0x58, 0xd1, 0x04, 0x04, 0x60, 0xbe, 0x58, 0xd2, 0x04, 0x07, 0x60, 0xbe, 0x58, 0xd3, 0x04, 0x01, 0x60, 0xbe, 0x58, 0xd4, 0x04, 0x14, 0x60, 0xbe, 0x58, 0xd5, 0x04, 0x05, 0x60, 0xbe, 0x58, 0xd6, 0x04, 0x3c, 0x60, 0xbe, 0x58, 0xcd, 0x04, 0x00, 0x60, 0xbe, 0x58, 0xc7, 0x04, 0x25, 0xb4, -0xc0, 0x38, 0x3a, 0x38, 0x8a, 0xf8, 0xce, 0x60, 0x04, 0x68, 0xd0, 0x61, 0x04, 0x69, 0xd1, 0x62, 0x04, 0x6a, 0xd2, 0x63, 0x04, 0x6b, 0xd3, 0x64, 0x04, 0x6c, 0xd4, 0x65, 0x04, 0x6d, 0xd5, 0x66, 0x04, 0x6e, 0xd6, 0x67, 0x04, 0x6f, 0x9e, 0x58, 0xe2, 0x19, 0x1a, 0x10, 0x04, 0x8a, 0x9e, 0x58, 0xea, 0x04, 0x1a, 0x10, 0x61, 0x88, 0x9e, 0x58, 0x58, 0x1a, 0x18, 0x10, 0x5d, 0x9a, 0x1a, 0x10, 0x5b, 0x98, 0x9e, 0x58, 0x58, 0x1a, 0x1a, 0x10, 0x19, 0x8a, 0x9e, 0x58, 0xcd, 0x04, 0x9e, 0x59, 0xce, 0x04, 0x30, 0x39, 0xd5, 0x04, 0x01, 0x10, 0x05, 0x98, 0x9e, 0x58, 0xc7, 0x04, 0x12, 0x38, 0xd4, 0x04, 0x3e, 0x96, 0xc7, 0x60, 0x04, 0x68, 0x9e, 0x59, 0xd4, 0x04, 0x3b, 0x58, 0xae, 0xfc, 0x46, 0xf9, 0x00, 0xfc, 0x8a, 0xf8, 0x3e, 0x58, 0x98, 0x3f, 0x3c, 0x0c, 0x9e, 0x58, 0x72, 0x19, 0x73, 0x61, 0xd7, 0x71, +0xc0, 0x38, 0x3a, 0x38, 0x8a, 0xf8, 0xce, 0x60, 0x04, 0x68, 0xd0, 0x61, 0x04, 0x69, 0xd1, 0x62, 0x04, 0x6a, 0xd2, 0x63, 0x04, 0x6b, 0xd3, 0x64, 0x04, 0x6c, 0xd4, 0x65, 0x04, 0x6d, 0xd5, 0x66, 0x04, 0x6e, 0xd6, 0x67, 0x04, 0x6f, 0x9e, 0x58, 0xe2, 0x19, 0x1a, 0x10, 0x04, 0x8a, 0x9e, 0x58, 0xea, 0x04, 0x1a, 0x10, 0x61, 0x88, 0x9e, 0x58, 0x58, 0x1a, 0x18, 0x10, 0x5d, 0x9a, 0x1a, 0x10, 0x5b, 0x98, 0x9e, 0x58, 0x58, 0x1a, 0x1a, 0x10, 0x19, 0x8a, 0x9e, 0x58, 0xcd, 0x04, 0x9e, 0x59, 0xce, 0x04, 0x30, 0x39, 0xd5, 0x04, 0x01, 0x10, 0x05, 0x98, 0x9e, 0x58, 0xc7, 0x04, 0x12, 0x38, 0xd4, 0x04, 0x3e, 0x96, 0xc7, 0x60, 0x04, 0x68, 0x9e, 0x59, 0xd4, 0x04, 0x3b, 0x58, 0xae, 0xfc, 0x46, 0xf9, 0x00, 0xfc, 0x8a, 0xf8, 0x3e, 0x58, 0x98, 0x3f, 0x41, 0x0c, 0x9e, 0x58, 0x72, 0x19, 0x73, 0x61, 0xdc, 0x71, 0x00, 0x39, 0x19, 0x69, 0x23, 0x59, 0x20, 0x10, 0x04, 0x58, 0x9e, 0x59, 0x86, 0x19, 0x87, 0x62, 0x19, 0x6a, 0x43, 0x5a, 0x41, 0x11, 0x04, 0x59, 0x01, 0x00, 0xbe, 0x58, 0xee, 0x04, 0x9e, 0x59, 0xd3, 0x04, 0x01, 0x11, 0x22, 0x98, 0xc7, 0x60, 0x04, 0x68, 0x03, 0x59, 0x19, 0x01, 0x32, 0x3a, 0xd4, 0x04, 0x02, 0x94, 0x3b, 0x58, 0x2a, 0x9e, 0x9e, 0x59, 0xd4, 0x04, 0x3b, 0x58, 0xcd, 0x60, 0x04, 0x68, 0x5a, 0x61, 0x03, 0x5a, 0x19, 0x02, 0x41, 0x13, 0x02, 0x94, 0x3b, 0x58, 0x1e, 0x9e, 0x9e, 0x59, 0xce, 0x04, 0x26, 0x59, 0x41, 0x13, 0x01, 0x9a, 0x21, 0x5a, 0x5b, 0x58, 0x16, 0x9e, 0x0b, 0x9e, 0x3c, 0x60, 0xbe, 0x58, 0xcd, 0x04, 0x11, 0x9e, 0xc7, 0x60, 0x04, 0x68, 0x03, 0x59, 0x19, 0x11, 0x22, 0x3a, 0x00, 0x00, 0x09, 0x98, 0xc7, 0x60, 0x04, 0x68, 0xde, 0x58, 0x00, 0x00, 0x9e, 0x58, 0x73, 0xc2, 0x40, 0x39, 0xce, 0x04, 0xbe, 0x58, 0xcd, 0x04, 0x01, 0x9e, 0x3b, 0x58, 0x3a, 0x38, 0xc8, 0x67, 0x04, 0x6f, 0x00, 0x65, 0xbd, 0x5f, 0xbb, 0x5f, 0xbe, 0x5d, 0xcb, 0x04, 0xbe, 0x5d, 0xcc, 0x04, 0x9e, 0x5f, 0x4b, 0x1a, 0x18, 0x17, 0xa5, 0x8a, 0xe2, 0x38, 0x14, 0x00, 0x1a, 0x00, 0xa5, 0x94, 0x00, 0x67, 0xe0, 0x38, 0xaa, 0x15, 0x03, 0x58, 0x12, 0x38, 0x23, 0x00, 0x93, 0x96, 0xe0, 0x3e, 0xde, 0x15, 0xc3, 0x5e, 0xe0, 0x3d, 0xf2, 0x15, 0xa3, 0x5d, 0xa6, 0x16, 0x19, 0x06, 0xe0, 0x3d, 0x1a, 0x16, 0xa3, 0x5d, 0xe0, 0x3c, 0x06, 0x16, 0x83, 0x5c, 0x85, 0x15, 0x19, 0x05, 0xe0, 0x3c, 0xaa, 0x15, 0x83, 0x5c, 0xc5, 0x00, 0xbe, 0x58, 0xec, 0x04, 0x12, 0x38, 0xd1, 0x04, 0x7a, 0x96, 0xc5, 0x00, 0x12, 0x38, 0xd0, 0x04, 0x76, 0x98, 0xe0, 0x38, 0xaa, 0x15, 0x7c, 0xa8, 0x9b, 0x58, 0x06, 0xac, 0x0c, 0x00, 0x80, 0x39, 0x3b, 0x92, 0x05, 0xac, 0x20, 0x92, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc8, 0x5a, 0x19, 0x12, 0x82, 0x04, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa8, 0x59, 0x19, 0x11, 0x61, 0x03, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x5a, 0xb8, 0x00, 0x43, 0x48, 0x03, 0x59, 0x01, 0xa8, 0x3d, 0x58, 0x03, 0x59, 0x01, 0xa8, 0x3f, 0x58, 0x10, 0x38, 0xb8, 0x00, 0x03, 0x59, 0x01, 0xa8, 0x3d, 0x58, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x4c, 0x9e, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc8, 0x5a, 0x19, 0x12, 0x82, 0x04, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa2, 0x39, 0x01, 0x00, 0x28, 0x59, 0x61, 0x03, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x5a, 0xb8, 0x00, 0x43, 0x48, 0x03, 0x59, 0x01, 0xa8, 0x3d, 0x58, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x33, 0x9e, 0x05, 0xac, 0x1b, 0x92, 0xe0, 0x3c, 0xde, 0x15, 0x9b, 0x9c, 0xc0, 0x39, 0x83, 0x5c, 0xc2, 0x3a, 0x01, 0x00, 0x48, 0x5a, 0x82, 0x04, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa8, 0x59, 0x19, 0x11, 0x61, 0x03, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x5a, 0xb8, 0x00, 0x43, 0x48, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x10, 0x38, 0xb8, 0x00, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x16, 0x9e, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc2, 0x3a, 0x01, 0x00, 0x48, 0x5a, 0x82, 0x04, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa2, 0x39, 0x01, 0x00, 0x28, 0x59, 0x61, 0x03, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x5a, 0xb8, 0x00, 0x43, 0x48, 0x03, 0x59, 0x01, 0xa8, 0x3b, 0x58, 0x3e, 0xfa, 0xfd, 0xf9, 0x19, 0x07, 0xf2, 0x38, 0x4b, 0x1a, 0x63, 0x97, 0xa0, 0xfa, 0xcb, 0xfa, 0x04, 0x9e, 0x9e, 0x58, 0xce, 0x04, 0xbe, 0x58, 0xcd, 0x04, 0x3a, 0x38, 0x9e, 0x5e, 0xca, 0x04, 0xc2, 0x38, 0xc1, 0x97, -0x00, 0x3a, 0x01, 0x00, 0x23, 0x9a, 0x00, 0x66, 0xc0, 0x3d, 0x01, 0x00, 0xc0, 0x3c, 0xe0, 0x04, 0x83, 0x5c, 0xa0, 0x3b, 0xe0, 0x04, 0x74, 0x10, 0x04, 0x58, 0xc0, 0x3c, 0xe5, 0x04, 0x83, 0x5c, 0xa0, 0x3b, 0xe5, 0x04, 0x74, 0x11, 0x04, 0x59, 0x01, 0x00, 0x19, 0x10, 0x0f, 0x9a, 0x01, 0x61, 0xbe, 0x59, 0xcb, 0x04, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x59, 0x11, 0x29, 0x3b, 0x58, 0x0b, 0x9e, 0x9e, 0x58, 0xcd, 0x04, 0x9e, 0x59, 0xce, 0x04, 0x30, 0x39, 0xd5, 0x04, 0x01, 0x10, 0xec, 0x99, 0x02, 0x60, 0xbe, 0x58, 0xcc, 0x04, 0x19, 0x05, 0xb2, 0x38, 0xca, 0x04, 0xd1, 0x97, 0x19, 0x06, 0xd2, 0x38, 0xca, 0x04, 0x19, 0x00, 0xca, 0x97, 0x03, 0x9e, 0x02, 0x60, 0xbe, 0x58, 0xcc, 0x04, 0x3a, 0x38, 0xe0, 0x3b, 0x1a, 0x16, 0x89, 0xe3, +0x00, 0x3a, 0x01, 0x00, 0x23, 0x9a, 0x00, 0x66, 0xc0, 0x3d, 0x01, 0x00, 0xc0, 0x3c, 0xe0, 0x04, 0x83, 0x5c, 0xa0, 0x3b, 0xe0, 0x04, 0x74, 0x10, 0x04, 0x58, 0xc0, 0x3c, 0xe5, 0x04, 0x83, 0x5c, 0xa0, 0x3b, 0xe5, 0x04, 0x74, 0x11, 0x04, 0x59, 0x01, 0x00, 0x19, 0x10, 0x0f, 0x9a, 0x01, 0x61, 0xbe, 0x59, 0xcb, 0x04, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x59, 0x11, 0x29, 0x3b, 0x58, 0x0b, 0x9e, 0x9e, 0x58, 0xcd, 0x04, 0x9e, 0x59, 0xce, 0x04, 0x30, 0x39, 0xd5, 0x04, 0x01, 0x10, 0xec, 0x99, 0x02, 0x60, 0xbe, 0x58, 0xcc, 0x04, 0x19, 0x05, 0xb2, 0x38, 0xca, 0x04, 0xd1, 0x97, 0x19, 0x06, 0xd2, 0x38, 0xca, 0x04, 0x19, 0x00, 0xca, 0x97, 0x03, 0x9e, 0x02, 0x60, 0xbe, 0x58, 0xcc, 0x04, 0x3a, 0x38, 0xe0, 0x3b, 0x1a, 0x16, 0xab, 0xe3, 0x40, 0x3a, 0x63, 0x5e, 0xe0, 0x3b, 0xde, 0x15, 0x63, 0x5d, 0x00, 0x60, 0xbe, 0x58, 0xca, 0x04, 0x1e, 0x5d, 0x6d, 0xfa, 0x9c, 0xfc, 0x59, 0x48, 0x15, 0x96, 0x5b, 0x48, 0x13, 0x96, 0x88, 0xfc, 0x59, 0x48, 0x10, 0x96, 0x5b, 0x48, 0x0e, 0x96, 0x9e, 0x58, 0xca, 0x04, 0x02, 0x3c, 0x05, 0x00, 0x09, 0x94, 0x00, 0x3c, 0xe0, 0x04, 0xbb, 0x5c, 0x00, 0x3c, 0xe5, 0x04, 0xdb, 0x5c, 0x19, 0x00, 0xbe, 0x58, 0xca, 0x04, 0x19, 0x05, 0xe0, 0x3b, 0xf2, 0x15, 0xbb, 0x49, 0xe2, 0x9b, 0x3e, 0x5d, 0x19, 0x06, 0xe0, 0x3b, 0x06, 0x16, 0xdb, 0x49, 0xdb, 0x9b, 0x3a, 0x38, 0x1e, 0x5e, 0xc0, 0x3c, 0x01, 0x00, 0xa0, 0x3b, 0x01, 0x00, 0x19, 0x16, 0x19, 0x15, 0xd7, 0x62, 0x04, 0x6a, 0x1e, 0x5d, 0xc2, 0x39, 0x00, 0x00, 0x1b, 0x96, 0xd2, 0x39, 0xb9, 0x00, 0x18, 0x94, 0xa0, 0x38, 0x48, 0x0e, 0x9e, 0x59, 0x83, 0x10, 0x80, 0x3a, 0xb8, 0x00, 0x26, 0x48, 0xa2, 0x39, 0x00, 0x00, 0x09, 0x96, 0xb2, 0x39, 0xb8, 0x00, 0x06, 0x94, 0x03, 0x59, 0x01, 0xac, 0x01, 0x90, 0x28, 0x59, 0x3d, 0x5a, 0x02, 0x9e, 0x00, 0x61, 0x3d, 0x5a, 0x19, 0x00, 0x19, 0x05, 0xbb, 0x48, 0xee, 0x9b, 0x04, 0x9e, 0x00, 0x61, 0x3d, 0x5a, 0x3d, 0x5a, 0x3d, 0x5a, 0x3e, 0x5d, 0x19, 0x06, 0xdc, 0x48, 0xd9, 0x9b, 0x19, 0x05, 0x3e, 0x5e, 0x3a, 0x38, 0x9e, 0x5f, 0xcb, 0x04, 0xf0, 0x3f, 0xcc, 0x04, 0xe2, 0x38, 0x01, 0x00, 0x17, 0x8a, 0xe2, 0x38, 0x02, 0x00, 0x08, 0x8a, 0xe2, 0x38, 0x03, 0x00, 0x1b, 0x8a, 0x9e, 0x58, 0xce, 0x04, 0xbe, 0x58, 0xcd, 0x04, 0x16, 0x9e, 0x9e, 0x58, 0xcd, 0x04, 0x12, 0x38, 0xd6, 0x04, 0x9e, 0x59, 0xce, 0x04, 0xb8, 0x11, 0x01, 0x11, 0x0d, 0x96, 0xbe, 0x58, 0xcd, 0x04, 0x0a, 0x9e, 0x9e, 0x58, 0xcd, 0x04, 0xf2, 0xf3, -0xc0, 0x3a, 0x19, 0x00, 0x9e, 0x59, 0xce, 0x04, 0xb8, 0x01, 0x01, 0x11, 0x02, 0x98, 0xbe, 0x58, 0xcd, 0x04, 0x9e, 0x58, 0xcd, 0x04, 0x3a, 0x38, 0x9e, 0x5f, 0x4b, 0x1a, 0xbe, 0x5f, 0x82, 0x1a, 0x00, 0x67, 0x9e, 0x5e, 0xcd, 0x04, 0x9e, 0x5a, 0xce, 0x04, 0x9e, 0x59, 0xd5, 0x04, 0x41, 0x10, 0xc0, 0x10, 0x19, 0x96, 0x41, 0x00, 0xc0, 0x10, 0x23, 0x9a, 0xe0, 0x38, 0xaa, 0x15, 0x03, 0x58, 0x04, 0x38, 0xff, 0x00, 0xbe, 0x58, 0xed, 0x04, 0x12, 0x39, 0xd2, 0x04, 0x19, 0x9a, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x59, 0x11, 0x29, 0x3b, 0x58, 0x18, 0x9e, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x59, 0x20, 0x59, 0x11, 0x21, 0x3b, 0x58, 0xe2, 0x9e, 0xc8, 0x60, 0x1b, 0xc7, -0x00, 0x3b, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x63, 0x29, 0x29, 0x59, 0x11, 0x21, 0xd7, 0x8a, 0xe0, 0x3e, 0xde, 0x15, 0xc3, 0x5e, 0xe0, 0x3d, 0xf2, 0x15, 0xb6, 0x16, 0x19, 0x06, 0xe0, 0x3d, 0x1a, 0x16, 0xa3, 0x5d, 0xe0, 0x3c, 0x06, 0x16, 0x95, 0x15, 0x19, 0x05, 0xdd, 0x48, 0x04, 0x98, 0x62, 0x96, 0x06, 0xac, 0x32, 0x92, 0x02, 0x9e, 0x06, 0xac, 0x2f, 0x92, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc8, 0x5e, 0x19, 0x16, 0xc4, 0x06, 0xe0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0x1e, 0x59, 0xdb, 0x58, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa3, 0x05, 0x19, 0x15, 0xe7, 0xfb, 0xe0, 0x38, 0xaa, 0x15, 0x5b, 0x58, 0xc0, 0x3c, 0x01, 0x00, 0x3e, 0x5e, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x30, 0x38, +0xc0, 0x3a, 0x19, 0x00, 0x9e, 0x59, 0xce, 0x04, 0xb8, 0x01, 0x01, 0x11, 0x02, 0x98, 0xbe, 0x58, 0xcd, 0x04, 0x9e, 0x58, 0xcd, 0x04, 0x3a, 0x38, 0x9e, 0x5f, 0x4b, 0x1a, 0xbe, 0x5f, 0x82, 0x1a, 0x00, 0x67, 0x9e, 0x5e, 0xcd, 0x04, 0x9e, 0x5a, 0xce, 0x04, 0x9e, 0x59, 0xd5, 0x04, 0x41, 0x10, 0xc0, 0x10, 0x19, 0x96, 0x41, 0x00, 0xc0, 0x10, 0x23, 0x9a, 0xe0, 0x38, 0xaa, 0x15, 0x03, 0x58, 0x04, 0x38, 0xff, 0x00, 0xbe, 0x58, 0xed, 0x04, 0x12, 0x39, 0xd2, 0x04, 0x19, 0x9a, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x59, 0x11, 0x29, 0x3b, 0x58, 0x18, 0x9e, 0xc8, 0x60, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x59, 0x20, 0x59, 0x11, 0x21, 0x3b, 0x58, 0xe2, 0x9e, 0xc8, 0x60, 0x5f, 0xc7, +0x00, 0x3b, 0x04, 0x68, 0xe2, 0x39, 0x10, 0x00, 0x01, 0x96, 0x19, 0x00, 0xe0, 0x39, 0x85, 0x29, 0x29, 0x59, 0x11, 0x21, 0xd7, 0x8a, 0xe0, 0x3e, 0xde, 0x15, 0xc3, 0x5e, 0xe0, 0x3d, 0xf2, 0x15, 0xb6, 0x16, 0x19, 0x06, 0xe0, 0x3d, 0x1a, 0x16, 0xa3, 0x5d, 0xe0, 0x3c, 0x06, 0x16, 0x95, 0x15, 0x19, 0x05, 0xdd, 0x48, 0x04, 0x98, 0x62, 0x96, 0x06, 0xac, 0x32, 0x92, 0x02, 0x9e, 0x06, 0xac, 0x2f, 0x92, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0xc8, 0x5e, 0x19, 0x16, 0xc4, 0x06, 0xe0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0x1e, 0x59, 0xdb, 0x58, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa3, 0x05, 0x19, 0x15, 0xe7, 0xfb, 0xe0, 0x38, 0xaa, 0x15, 0x5b, 0x58, 0xc0, 0x3c, 0x01, 0x00, 0x3e, 0x5e, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x52, 0x38, 0x40, 0x3b, 0x06, 0x16, 0xbb, 0x59, 0x00, 0x39, 0x1a, 0x16, 0x7b, 0x59, 0xe7, 0xfb, 0x9e, 0x5c, 0x4b, 0x1a, 0x80, 0x39, 0xaa, 0x15, 0xe1, 0x58, 0xfe, 0x58, 0x68, 0xa8, 0x48, 0x29, 0x8c, 0x9e, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0x19, 0x16, 0xc8, 0x5e, 0xc4, 0x06, 0xe0, 0x38, 0xf2, 0x15, 0x03, 0x59, 0x1e, 0x59, 0xdb, 0x58, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa3, 0x05, 0x19, 0x15, 0xe7, 0xfb, 0xe0, 0x38, 0xaa, 0x15, 0x5b, 0x58, 0xc1, 0x5c, 0x3e, 0x5e, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x06, 0x16, 0xbb, 0x59, 0x00, 0x39, 0x1a, 0x16, 0x7b, 0x59, 0xe7, 0xfb, 0x9e, 0x5c, 0x4b, 0x1a, 0x80, 0x39, 0xaa, 0x15, 0xe1, 0x58, 0xfe, 0x58, 0x68, 0xa8, 0x48, 0x29, 0x5e, 0x9e, 0x05, 0xac, 0x2f, 0x92, 0xe0, 0x3c, 0xc3, 0x56, 0x80, 0x3b, 0xde, 0x15, 0x83, 0x5c, 0x86, 0x06, 0x19, 0x16, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0xa8, 0x5d, 0x19, 0x15, 0xa3, 0x05, 0xe0, 0x38, 0x06, 0x16, 0x03, 0x59, 0x1e, 0x59, 0xbb, 0x58, 0xe7, 0xfb, 0xe0, 0x38, 0xaa, 0x15, 0x5b, 0x58, 0xa0, 0x3b, 0x01, 0x00, 0x3e, 0x5d, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x06, 0x16, 0xbb, 0x59, 0x00, 0x39, 0x1a, 0x16, 0x7b, 0x59, 0xe7, 0xfb, 0x9e, 0x5c, 0x4b, 0x1a, 0x80, 0x39, 0xaa, 0x15, 0xe1, 0x58, 0xfe, 0x58, 0x70, 0xa8, 0x48, 0x29, 0x2d, 0x9e, 0xe0, 0x3c, 0xde, 0x15, 0x83, 0x5c, 0x86, 0x06, 0x19, 0x16, 0xe0, 0x3b, 0x1a, 0x16, 0x63, 0x5b, 0x19, 0x15, 0xa8, 0x5d, 0xa3, 0x05, 0xe0, 0x38, 0x06, 0x16, 0x03, 0x59, 0x1e, 0x59, 0xbb, 0x58, 0xe7, 0xfb, 0xe0, 0x38, 0x1b, 0xff, 0xc0, 0x3b, 0xaa, 0x15, 0x5b, 0x58, 0xa1, 0x5b, 0x3e, 0x5d, 0x9e, 0x58, 0x4b, 0x1a, 0x00, 0x39, 0xde, 0x15, 0x9b, 0x59, 0x00, 0x39, 0xf2, 0x15, 0xdb, 0x59, 0x00, 0x39, 0x06, 0x16, 0xbb, 0x59, 0x00, 0x39, 0x1a, 0x16, 0x7b, 0x59, 0xe7, 0xfb, 0x9e, 0x5c, 0x4b, 0x1a, 0x80, 0x39, 0xaa, 0x15, 0xe1, 0x58, 0xfe, 0x58, 0x70, 0xa8, 0x48, 0x29, 0x19, 0x04, 0xbe, 0x5c, 0x4b, 0x1a, 0x82, 0x38, 0x14, 0x00, 0x05, 0x94, 0x19, 0x07, 0xf2, 0x38, 0x82, 0x1a, 0x98, 0x3d, 0xd0, 0x3a, 0x3a, 0x38, 0x1e, 0x5e, 0x1e, 0x5b, 0x00, 0x62, 0xc4, 0x16, 0x80, 0x38, 0x48, 0x0e, 0x9e, 0x59, 0xb8, 0x00, 0x23, 0x48, 0xc7, 0x38, 0xf9, 0x3b, 0x05, 0x59, 0x01, 0xac, 0x01, 0x90, 0x28, 0x59, 0x32, 0x39, 0x1d, 0x00, 0x00, 0x9a, 0x19, 0x02, 0x19, 0x03, 0x7d, 0x48, 0xee, 0x9b, 0x3e, 0x5b, 0x3e, 0x5e, 0x3a, 0x38, 0x78, 0x3d, -0x00, 0x3c, 0x00, 0x60, 0xbe, 0x58, 0xe2, 0x19, 0x9e, 0x5f, 0x4b, 0x1a, 0x18, 0x17, 0x5f, 0x9a, 0x00, 0x67, 0xe0, 0x3e, 0xaa, 0x15, 0xc3, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0xd2, 0x38, 0x23, 0x00, 0x52, 0x96, 0xff, 0x62, 0xe0, 0x3e, 0x1a, 0x16, 0xd2, 0x26, 0xe0, 0x3d, 0xde, 0x15, 0xb2, 0x25, 0xe0, 0x3c, 0x06, 0x16, 0x92, 0x24, 0xe0, 0x3b, 0xf2, 0x15, 0x72, 0x23, 0x1e, 0x5f, 0xcf, 0xd0, 0x1e, 0x5d, 0x9e, 0x5a, 0xb8, 0x00, 0xa0, 0x38, 0x48, 0x0e, 0x46, 0x48, 0x03, 0x5a, 0x42, 0x38, 0x01, 0x00, 0x2b, 0x9a, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x45, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x46, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x50, 0x3f, 0x54, 0x1a, 0xbe, 0x5f, 0x54, 0x1a, 0x7f, 0xac, 0x17, 0x90, 0xe8, 0x5f, 0xbe, 0x5f, 0x54, 0x1a, 0x39, 0x56, -0x40, 0x3c, 0x9e, 0x58, 0x50, 0x1a, 0x9e, 0x59, 0x51, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x51, 0x1a, 0xbe, 0x58, 0x50, 0x1a, 0x9e, 0x58, 0x52, 0x1a, 0x9e, 0x59, 0x53, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x53, 0x1a, 0xbe, 0x58, 0x52, 0x1a, 0x19, 0x05, 0xbb, 0x48, 0xc9, 0x9b, 0x3e, 0x5d, 0x19, 0x06, 0xdc, 0x48, 0xc4, 0x9b, 0x3e, 0x5f, 0x67, 0xfc, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0x27, 0x00, 0x04, 0x94, 0x19, 0x07, 0xf2, 0x38, 0x4b, 0x1a, 0xa2, 0x97, 0x3a, 0x38, 0x9e, 0x58, 0x54, 0x1a, 0xbe, 0x58, 0x55, 0x1a, 0x00, 0x60, 0xbe, 0x58, 0x56, 0x1a, 0x9e, 0x5d, 0xe2, 0x19, 0x51, 0x63, 0x1a, 0x6b, 0x47, 0xd0, 0xa0, 0x3b, 0xb2, 0x19, 0x1b, 0x5b, 0x53, 0x63, 0x1a, 0x6b, 0x47, 0xd0, 0xa0, 0x3b, 0xbe, 0x19, 0x1b, 0x5b, 0xa0, 0x3b, 0xca, 0x19, 0xde, 0x5b, 0xff, 0xff, 0xf8, 0xb0, +0x00, 0x3c, 0x00, 0x60, 0xbe, 0x58, 0xe2, 0x19, 0x9e, 0x5f, 0x4b, 0x1a, 0x18, 0x17, 0x5f, 0x9a, 0x00, 0x67, 0xe0, 0x3e, 0xaa, 0x15, 0xc3, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0xd2, 0x38, 0x23, 0x00, 0x52, 0x96, 0xff, 0x62, 0xe0, 0x3e, 0x1a, 0x16, 0xd2, 0x26, 0xe0, 0x3d, 0xde, 0x15, 0xb2, 0x25, 0xe0, 0x3c, 0x06, 0x16, 0x92, 0x24, 0xe0, 0x3b, 0xf2, 0x15, 0x72, 0x23, 0x1e, 0x5f, 0xd4, 0xd0, 0x1e, 0x5d, 0x9e, 0x5a, 0xb8, 0x00, 0xa0, 0x38, 0x48, 0x0e, 0x46, 0x48, 0x03, 0x5a, 0x42, 0x38, 0x01, 0x00, 0x2b, 0x9a, 0x50, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x45, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x52, 0x67, 0x1a, 0x6f, 0xe5, 0x58, 0xe3, 0x59, 0x46, 0x48, 0x3f, 0x5f, 0x1b, 0x5f, 0x50, 0x3f, 0x54, 0x1a, 0xbe, 0x5f, 0x54, 0x1a, 0x7f, 0xac, 0x17, 0x90, 0xe8, 0x5f, 0xbe, 0x5f, 0x54, 0x1a, 0x3e, 0x56, +0x40, 0x3c, 0x9e, 0x58, 0x50, 0x1a, 0x9e, 0x59, 0x51, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x51, 0x1a, 0xbe, 0x58, 0x50, 0x1a, 0x9e, 0x58, 0x52, 0x1a, 0x9e, 0x59, 0x53, 0x1a, 0x28, 0x59, 0x0c, 0x58, 0xbe, 0x59, 0x53, 0x1a, 0xbe, 0x58, 0x52, 0x1a, 0x19, 0x05, 0xbb, 0x48, 0xc9, 0x9b, 0x3e, 0x5d, 0x19, 0x06, 0xdc, 0x48, 0xc4, 0x9b, 0x3e, 0x5f, 0x67, 0xfc, 0x9e, 0x58, 0xe2, 0x19, 0x12, 0x38, 0x27, 0x00, 0x04, 0x94, 0x19, 0x07, 0xf2, 0x38, 0x4b, 0x1a, 0xa2, 0x97, 0x3a, 0x38, 0x9e, 0x58, 0x54, 0x1a, 0xbe, 0x58, 0x55, 0x1a, 0x00, 0x60, 0xbe, 0x58, 0x56, 0x1a, 0x9e, 0x5d, 0xe2, 0x19, 0x51, 0x63, 0x1a, 0x6b, 0x4c, 0xd0, 0xa0, 0x3b, 0xb2, 0x19, 0x1b, 0x5b, 0x53, 0x63, 0x1a, 0x6b, 0x4c, 0xd0, 0xa0, 0x3b, 0xbe, 0x19, 0x1b, 0x5b, 0xa0, 0x3b, 0xca, 0x19, 0xde, 0x5b, 0xff, 0xff, 0x02, 0xb1, 0x80, 0x3c, 0xa0, 0x3b, 0xd6, 0x19, 0xde, 0x5b, 0xff, 0x7f, 0x19, 0x05, 0xbe, 0x5d, 0xe2, 0x19, 0x3a, 0x38, 0xd7, 0x64, 0x04, 0x6c, 0x00, 0x63, 0x4f, 0x38, 0x8e, 0x3c, 0x93, 0x03, 0x1b, 0x04, 0x38, 0x14, 0x00, 0x62, 0x4f, 0x38, 0x94, 0x3c, 0x92, 0x02, 0x1b, 0x04, 0x38, 0x14, 0x00, 0x61, 0x4f, 0x38, 0x9a, 0x3c, 0x91, 0x01, 0x1b, 0x04, 0x3a, 0x38, 0xd7, 0x64, 0x04, 0x6c, 0x00, 0x63, 0x4f, 0x38, 0xa2, 0x3c, 0x93, 0x03, 0x19, 0x04, 0x00, 0x62, 0x4f, 0x38, 0xa7, 0x3c, 0x92, 0x02, 0x19, 0x04, 0x00, 0x61, 0x4f, 0x38, 0xac, 0x3c, 0x91, 0x01, 0x19, 0x04, 0x3a, 0x38, 0x48, 0x60, 0x0e, 0x68, 0x9e, 0x5f, 0xbf, 0x00, 0x19, 0x17, 0xe7, 0x38, 0xb7, 0x3c, 0x03, 0x59, 0x01, 0xaa, 0x3d, 0x58, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xdd, 0x00, 0xbe, 0x58, 0xe3, 0x00, 0xbe, 0x58, 0xe2, 0x00, 0xb4, 0x44, 0xc0, 0x3c, 0xbe, 0x58, 0xe5, 0x00, 0xbe, 0x58, 0x16, 0x1f, 0x3a, 0x38, 0x00, 0x60, 0xbe, 0x58, 0xe3, 0x00, 0xbe, 0x58, 0xe2, 0x00, 0xbe, 0x58, 0xe5, 0x00, 0xbe, 0x58, 0x1e, 0x1d, 0xbe, 0x58, 0x16, 0x1f, 0x4d, 0xfe, 0xbe, 0x58, 0xdc, 0x00, 0xbe, 0x58, 0xe6, 0x00, 0x00, 0x60, 0x79, 0xfe, 0xbe, 0x58, 0x45, 0x01, 0x00, 0x60, 0x98, 0xfe, 0xbe, 0x58, 0x46, 0x01, 0x3a, 0x38, 0x9e, 0x5f, 0xe2, 0x00, 0x27, 0xaa, 0xbe, 0x5f, 0xe2, 0x00, 0x1f, 0xac, 0x0e, 0x92, 0x9e, 0x5f, 0xe5, 0x00, 0x19, 0x07, 0xbe, 0x5f, 0xe5, 0x00, 0xb8, 0x66, 0x0b, 0x6e, 0xfe, 0x48, 0x05, 0x9c, 0x9e, 0x5f, 0xe2, 0x00, 0x1f, 0xa8, 0xbe, 0x5f, 0xe2, 0x00, 0x9e, 0x5f, 0xdf, 0x00, 0x19, 0x07, 0xbe, 0x5f, 0xdf, 0x00, 0x9e, 0x5e, 0xe1, 0x00, 0xdf, 0x48, 0x98, 0x38, 0x4b, 0x3e, 0x00, 0x67, 0xbe, 0x5f, 0xdf, 0x00, 0xab, 0x3f, 0x00, 0x3d, 0x4d, 0xfe, 0xbe, 0x58, 0xdb, 0x00, 0x9e, 0x59, 0xdc, 0x00, 0x19, 0x48, 0x2c, 0x82, 0x20, 0x10, 0x1e, 0x61, 0x38, 0x48, 0x20, 0x82, 0x9e, 0x5f, 0xe2, 0x00, 0x47, 0xa8, 0xbe, 0x5f, 0xe2, 0x00, 0x9e, 0x5a, 0x1e, 0x1d, 0x19, 0x02, 0xbe, 0x5a, 0x1e, 0x1d, 0x03, 0x63, 0x5b, 0x48, 0x1b, 0x96, 0x00, 0x62, 0xbe, 0x5a, 0x1e, 0x1d, 0x9e, 0x5f, 0xe2, 0x00, 0x47, 0xaa, 0xbe, 0x5f, 0xe2, 0x00, 0x9e, 0x58, 0xdb, 0x00, 0x9e, 0x59, 0xdc, 0x00, 0x20, 0x11, 0xbe, 0x58, 0xdc, 0x00, 0x10, 0x60, 0x19, 0x48, 0xd4, 0x82, 0xec, 0x9e, 0x00, 0x62, 0xbe, 0x5a, 0x1e, 0x1d, 0x9e, 0x5f, 0xe2, 0x00, 0x47, 0xaa, 0xbe, 0x5f, 0xe2, 0x00, 0x9e, 0x5f, 0xea, 0x04, 0x18, 0x17, 0x06, 0x8a, 0x00, 0x67, 0xbe, 0x5f, 0xdf, 0x00, 0xbe, 0x5f, 0xe3, 0x00, 0x09, 0x9e, 0x9e, 0x5f, 0xe2, 0x19, 0x18, 0x17, 0x6d, 0x61, @@ -260,12 +260,12 @@ 0xc0, 0x42, 0xff, 0x00, 0x7f, 0x38, 0x06, 0x58, 0x64, 0x3b, 0xff, 0x00, 0x7f, 0x38, 0x66, 0x5b, 0x60, 0x33, 0x0b, 0x8a, 0xd1, 0xa8, 0x09, 0x9e, 0x04, 0x38, 0x00, 0xff, 0xfe, 0x58, 0x64, 0x3b, 0x00, 0xff, 0xfe, 0x5b, 0x60, 0x33, 0x01, 0x8a, 0xd1, 0xa8, 0xe1, 0x01, 0x30, 0x28, 0x1b, 0x59, 0xc8, 0x5e, 0x19, 0x05, 0x19, 0x14, 0xd9, 0x89, 0x9e, 0x5a, 0x90, 0x19, 0xbe, 0x5a, 0xc0, 0x01, 0x9e, 0x5a, 0x91, 0x19, 0xbe, 0x5a, 0xc1, 0x01, 0x9e, 0x5a, 0x92, 0x19, 0xbe, 0x5a, 0xc2, 0x01, 0x3a, 0x38, 0x53, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x82, 0x8a, 0x54, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x98, 0x3a, 0x11, 0x45, 0x57, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x98, 0x3a, 0x00, 0x48, 0x58, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x98, 0x3a, 0x5f, 0x48, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x66, 0x00, 0x98, 0x3a, 0x2d, 0xca, 0x00, 0x43, 0x5b, 0x48, 0x9f, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x0d, 0x88, 0x00, 0x60, 0x16, 0x39, 0x5f, 0x00, 0x36, 0x38, 0x60, 0x00, 0x06, 0x88, 0x01, 0x60, 0x16, 0x39, 0x61, 0x00, 0x02, 0x88, 0xb9, 0xaa, 0xf7, 0xaa, 0x3a, 0x38, 0x96, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x02, 0x88, 0x98, 0x3f, 0x8a, 0x47, 0x97, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x02, 0x88, 0x98, 0x3f, 0xf6, 0x47, 0x98, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x02, 0x88, 0x98, 0x3f, 0xaf, 0x47, 0x5b, 0x60, 0x16, 0x39, 0x5e, 0x00, 0x02, 0x88, 0x98, 0x3f, 0xcf, 0x47, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x56, 0x00, 0x02, 0x88, 0x84, 0xaa, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0xa6, 0x00, 0x02, 0x88, 0x84, 0xa8, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x57, 0x00, 0x02, 0x88, 0xa8, 0xa8, 0x3a, 0x38, 0x19, 0x38, 0x05, 0xed, 0x40, 0x43, 0x66, 0x43, 0x26, 0x38, 0xa7, 0x00, 0x02, 0x88, 0xa8, 0xaa, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x55, 0x00, 0x05, 0x88, 0xba, 0xaa, 0x5e, 0x71, 0xbe, 0x59, 0xc1, 0x1d, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0xa5, 0x00, 0x09, 0x88, 0xba, 0xa8, 0x81, 0xaa, 0x5e, 0x71, 0xbe, 0x59, 0xc1, 0x1d, 0x00, 0x60, 0xbe, 0x58, 0x27, 0x1d, 0x3a, 0x38, 0x19, 0x38, 0x66, 0x43, 0x26, 0x38, 0x77, 0x00, 0x02, 0x88, 0x42, 0xa9, 0x3a, 0x38, 0x3a, 0x38, 0x5e, 0x70, 0x14, 0x39, 0x5f, 0x00, 0x34, 0x38, 0x60, 0x00, 0x14, 0x39, 0x61, 0x00, 0x3a, 0x38, 0xa2, 0xa8, 0x04, 0x60, 0x69, 0x78, 0x52, 0x60, 0x6a, 0x78, 0x5f, 0x70, 0x6b, 0x78, 0x00, 0x60, 0x6c, 0x78, 0x01, 0x60, 0x6d, 0x78, 0x5f, 0x70, 0x7f, 0x38, 0x08, 0x58, 0x3f, 0x20, 0x00, 0x39, 0x81, 0x43, 0x29, 0x58, 0xd7, 0x4b, -0x80, 0x43, 0x5e, 0x58, 0x91, 0x43, 0x95, 0x43, 0x9a, 0x43, 0xbb, 0x43, 0xc5, 0x43, 0xe7, 0x43, 0x02, 0x44, 0x56, 0x44, 0x57, 0x44, 0x9c, 0x44, 0xa4, 0x44, 0xb0, 0x44, 0xdf, 0x44, 0xf3, 0x44, 0xf5, 0x44, 0xf7, 0x44, 0x42, 0x60, 0xa0, 0x68, 0x98, 0x3f, 0xfc, 0x44, 0x1c, 0x61, 0x02, 0x69, 0x29, 0x58, 0x98, 0x3f, 0xfc, 0x44, 0x5f, 0x70, 0x06, 0x39, 0x20, 0x00, 0x0a, 0x8a, 0x06, 0x39, 0x27, 0x00, 0x0e, 0x8a, 0x06, 0x39, 0x28, 0x00, 0x0e, 0x8a, 0x06, 0x39, 0x29, 0x00, 0x0c, 0x8a, 0x3a, 0x38, 0xf5, 0xac, 0x01, 0x90, 0x01, 0x61, 0x6c, 0x79, 0x01, 0x61, 0x6d, 0x79, 0x3a, 0x38, 0xfd, 0xac, 0x09, 0x90, 0x06, 0x9e, 0x02, 0x9e, 0xfa, 0x60, 0x5f, 0x68, 0x09, 0x58, 0x18, 0x10, 0x02, 0x88, 0x01, 0x60, 0x6c, 0x78, 0x3a, 0x38, 0x6b, 0x71, 0x24, 0x39, 0xf0, 0x00, 0x00, 0x60, 0xd8, 0xac, 0xc1, 0xaf, +0x80, 0x43, 0x5e, 0x58, 0x91, 0x43, 0x95, 0x43, 0x9a, 0x43, 0xbb, 0x43, 0xc5, 0x43, 0xe7, 0x43, 0x02, 0x44, 0x56, 0x44, 0x57, 0x44, 0x9c, 0x44, 0xa4, 0x44, 0xb0, 0x44, 0xdf, 0x44, 0xf3, 0x44, 0xf5, 0x44, 0xf7, 0x44, 0x44, 0x60, 0xa0, 0x68, 0x98, 0x3f, 0xfc, 0x44, 0x1c, 0x61, 0x02, 0x69, 0x29, 0x58, 0x98, 0x3f, 0xfc, 0x44, 0x5f, 0x70, 0x06, 0x39, 0x20, 0x00, 0x0a, 0x8a, 0x06, 0x39, 0x27, 0x00, 0x0e, 0x8a, 0x06, 0x39, 0x28, 0x00, 0x0e, 0x8a, 0x06, 0x39, 0x29, 0x00, 0x0c, 0x8a, 0x3a, 0x38, 0xf5, 0xac, 0x01, 0x90, 0x01, 0x61, 0x6c, 0x79, 0x01, 0x61, 0x6d, 0x79, 0x3a, 0x38, 0xfd, 0xac, 0x09, 0x90, 0x06, 0x9e, 0x02, 0x9e, 0xfa, 0x60, 0x5f, 0x68, 0x09, 0x58, 0x18, 0x10, 0x02, 0x88, 0x01, 0x60, 0x6c, 0x78, 0x3a, 0x38, 0x6b, 0x71, 0x24, 0x39, 0xf0, 0x00, 0x00, 0x60, 0xd8, 0xac, 0xc3, 0xaf, 0xc0, 0x43, 0x01, 0x90, 0x18, 0xa8, 0x20, 0x29, 0x6b, 0x79, 0x3a, 0x38, 0x6b, 0x71, 0x24, 0x39, 0xf3, 0x00, 0x03, 0x60, 0x01, 0x20, 0x00, 0x62, 0x1a, 0x48, 0x04, 0x8a, 0x00, 0x60, 0x24, 0x39, 0xf0, 0x00, 0x13, 0x9e, 0x03, 0x60, 0xd6, 0xac, 0x10, 0x92, 0x00, 0x60, 0x86, 0xac, 0x02, 0x90, 0x00, 0xa8, 0x04, 0x9e, 0x00, 0xaa, 0x8e, 0xac, 0x04, 0x90, 0x05, 0x9e, 0x8e, 0xac, 0x01, 0x90, 0x02, 0x9e, 0x08, 0xaa, 0x02, 0x9e, 0x08, 0xa8, 0x00, 0x9e, 0x20, 0x29, 0x6b, 0x79, 0x3a, 0x38, 0x6b, 0x71, 0x26, 0x38, 0x5a, 0x00, 0x0d, 0x8a, 0x24, 0x39, 0xf0, 0x00, 0x00, 0x60, 0xe0, 0xac, 0x05, 0x90, 0xd0, 0xac, 0x02, 0x90, 0x00, 0xa8, 0x01, 0x9e, 0x18, 0xa8, 0x20, 0x29, 0x6b, 0x79, 0x3a, 0x38, 0x9e, 0x59, 0xbd, 0x1d, 0x6b, 0x79, 0x9e, 0x59, 0xbe, 0x1d, 0x6c, 0x79, 0x9e, 0x59, 0xbf, 0x1d, 0x69, 0xa1, 0x00, 0x44, 0x6d, 0x79, 0x3a, 0x38, 0xb0, 0xac, 0x06, 0x90, 0xb8, 0xac, 0x02, 0x92, 0x06, 0x60, 0x03, 0x9e, 0x07, 0x60, 0x01, 0x9e, 0x08, 0x60, 0xb3, 0x78, 0x5f, 0x70, 0x3f, 0x20, 0x00, 0x38, 0x12, 0x44, 0x09, 0x59, 0x5e, 0x59, 0x22, 0x44, 0x35, 0x44, 0x36, 0x44, 0x37, 0x44, 0x4a, 0x44, 0x4b, 0x44, 0x4c, 0x44, 0x4d, 0x44, 0x4e, 0x44, 0x4f, 0x44, 0x50, 0x44, 0x51, 0x44, 0x52, 0x44, 0x53, 0x44, 0x54, 0x44, 0x55, 0x44, 0x00, 0x60, 0x00, 0x61, 0x9e, 0x5a, 0xb8, 0x00, 0xb3, 0x73, 0x19, 0x12, 0x43, 0x48, 0x04, 0x3a, 0xff, 0x00, 0x6c, 0x7a, 0x04, 0x3a, 0x00, 0x0f, 0xfe, 0x5a, 0x7f, 0x38, 0x46, 0x5a, 0x55, 0x3a, 0x6d, 0x00, 0x6d, 0x7a, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x00, 0x60, 0x00, 0x61, 0x9e, 0x5a, 0xb9, 0x00, 0xb3, 0x73, 0x19, 0x12, 0x43, 0x48, 0x04, 0x3a, 0xff, 0x00, 0x59, 0xa3, 0x40, 0x44, 0x6c, 0x7a, 0x04, 0x3a, 0x00, 0x0f, 0xfe, 0x5a, 0x7f, 0x38, 0x46, 0x5a, 0x55, 0x3a, 0x6d, 0x00, 0x6d, 0x7a, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x3f, 0x20, 0x00, 0x38, 0x5e, 0x44, 0x09, 0x59, 0x01, 0x60, 0x5e, 0x59, 0x6e, 0x44, 0x72, 0x44, 0x74, 0x44, 0x75, 0x44, 0x79, 0x44, 0x7d, 0x44, 0x7e, 0x44, 0x7f, 0x44, 0x83, 0x44, 0x87, 0x44, 0x88, 0x44, 0x89, 0x44, 0x8a, 0x44, 0x8c, 0x44, 0x8d, 0x44, 0x8e, 0x44, 0xa1, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x28, 0x9e, 0x12, 0x70, 0x26, 0x9e, 0x25, 0x9e, 0xf8, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x21, 0x9e, 0xca, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x1d, 0x9e, 0x1c, 0x9e, 0x1b, 0x9e, 0xf2, 0xac, 0x8c, 0x4f, 0x80, 0x44, 0x01, 0x92, 0x00, 0xaa, 0x17, 0x9e, 0xf0, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x13, 0x9e, 0x12, 0x9e, 0x11, 0x9e, 0x10, 0x9e, 0x11, 0x70, 0x0e, 0x9e, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x38, 0x8f, 0x00, 0x02, 0x8a, 0x1a, 0x38, 0x3a, 0x38, 0x01, 0x60, 0xe6, 0xac, 0x01, 0x92, 0x00, 0x60, 0x6c, 0x78, 0x3a, 0x38, 0x6c, 0x78, 0x3a, 0x38, 0x9e, 0x58, 0xfb, 0x04, 0x04, 0x38, 0x00, 0x0f, 0xfe, 0x58, 0x19, 0x00, 0x6c, 0x78, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x38, 0xa0, 0x00, 0x02, 0x8a, 0xa2, 0xaa, 0x3a, 0x38, 0x01, 0x60, 0xe8, 0xac, 0x01, 0x92, 0x00, 0xaa, 0x6c, 0x78, 0x3a, 0x38, 0x5f, 0x70, 0x3f, 0x20, 0x00, 0x38, 0xb6, 0x44, 0x09, 0x59, 0x5e, 0x59, 0xc6, 0x44, 0xcc, 0x44, 0xd1, 0x44, 0xd2, 0x44, 0xd3, 0x44, 0xd4, 0x44, 0xd5, 0x44, 0xd6, 0x44, 0xd7, 0x44, 0xd8, 0x44, 0x9e, 0x2f, -0xc0, 0x44, 0xd9, 0x44, 0xda, 0x44, 0xdb, 0x44, 0xdc, 0x44, 0xdd, 0x44, 0xde, 0x44, 0x01, 0x60, 0x90, 0xac, 0x01, 0x8a, 0x00, 0xaa, 0x6c, 0x78, 0x3a, 0x38, 0x03, 0x60, 0x14, 0x38, 0x00, 0x00, 0x6c, 0x78, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x71, 0x24, 0x38, 0x0f, 0x00, 0x00, 0x38, 0x8d, 0x2e, 0x09, 0x58, 0x02, 0x39, 0x00, 0x00, 0x02, 0x88, 0x6c, 0x78, 0x3a, 0x38, 0x03, 0x58, 0x04, 0x39, 0xff, 0x00, 0x6d, 0x79, 0xfe, 0x58, 0x04, 0x39, 0xff, 0x00, 0x6c, 0x79, 0x3a, 0x38, 0x00, 0x60, 0x07, 0x9e, 0x88, 0x60, 0x05, 0x9e, 0xfc, 0x61, 0x3f, 0x69, 0x29, 0x58, 0x29, 0x60, 0x30, 0x68, 0x04, 0x39, 0x00, 0xf0, 0xfe, 0x59, 0x7f, 0x38, 0xc4, 0xfc, +0xc0, 0x44, 0xd9, 0x44, 0xda, 0x44, 0xdb, 0x44, 0xdc, 0x44, 0xdd, 0x44, 0xde, 0x44, 0x01, 0x60, 0x90, 0xac, 0x01, 0x8a, 0x00, 0xaa, 0x6c, 0x78, 0x3a, 0x38, 0x03, 0x60, 0x14, 0x38, 0x00, 0x00, 0x6c, 0x78, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x71, 0x24, 0x38, 0x0f, 0x00, 0x00, 0x38, 0xa0, 0x2e, 0x09, 0x58, 0x02, 0x39, 0x00, 0x00, 0x02, 0x88, 0x6c, 0x78, 0x3a, 0x38, 0x03, 0x58, 0x04, 0x39, 0xff, 0x00, 0x6d, 0x79, 0xfe, 0x58, 0x04, 0x39, 0xff, 0x00, 0x6c, 0x79, 0x3a, 0x38, 0x00, 0x60, 0x07, 0x9e, 0x88, 0x60, 0x05, 0x9e, 0xfc, 0x61, 0x3f, 0x69, 0x29, 0x58, 0x29, 0x60, 0x30, 0x68, 0x04, 0x39, 0x00, 0xf0, 0xfe, 0x59, 0x7f, 0x38, 0xd7, 0xfc, 0x00, 0x45, 0x28, 0x59, 0x35, 0x39, 0x6b, 0x00, 0x6b, 0x79, 0x04, 0x39, 0xf0, 0x0f, 0x7f, 0x38, 0x28, 0x59, 0x6c, 0x79, 0x04, 0x39, 0x0f, 0x00, 0x7f, 0x38, 0x26, 0x59, 0x35, 0x39, 0x6d, 0x00, 0x6d, 0x79, 0x3a, 0x38, 0x5f, 0x70, 0x7f, 0x38, 0x08, 0x58, 0x3f, 0x20, 0x00, 0x39, 0x19, 0x45, 0x29, 0x58, 0x5e, 0x58, 0x29, 0x45, 0x35, 0x45, 0x36, 0x45, 0x0c, 0x46, 0x18, 0x46, 0x34, 0x46, 0x54, 0x46, 0x68, 0x46, 0x69, 0x46, 0xfc, 0x46, 0x45, 0x47, 0x56, 0x47, 0x78, 0x47, 0x87, 0x47, 0x88, 0x47, 0x89, 0x47, 0x60, 0x70, 0x12, 0x61, 0x19, 0x48, 0x07, 0x88, 0x61, 0x70, 0x34, 0x61, 0x19, 0x48, 0x03, 0x88, 0xff, 0x60, 0xff, 0x68, 0x60, 0xc0, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0x25, 0x00, 0x38, 0x8a, 0x06, 0x39, 0x26, 0x00, 0x37, 0x8a, 0x06, 0x39, 0x27, 0x00, 0x1c, 0x8a, 0x3b, 0x0c, 0x40, 0x45, 0x06, 0x39, 0x28, 0x00, 0x10, 0x8a, 0x06, 0x39, 0x29, 0x00, 0x0f, 0x8a, 0x06, 0x39, 0x2a, 0x00, 0x1e, 0x8a, 0x06, 0x39, 0x2d, 0x00, 0x37, 0x8a, 0x06, 0x39, 0x2e, 0x00, 0x36, 0x8a, 0x06, 0x39, 0x2f, 0x00, 0x3d, 0x8a, 0x3a, 0x38, 0x97, 0xa8, 0x3a, 0x38, 0x5a, 0x60, 0x5a, 0x68, 0xbe, 0x58, 0xc2, 0x1d, 0xad, 0xa8, 0xf5, 0xa8, 0x3a, 0x38, 0x60, 0x70, 0x00, 0x61, 0x20, 0x31, 0x03, 0x8a, 0x01, 0x61, 0x20, 0x31, 0x02, 0x8a, 0xfd, 0xaa, 0x3a, 0x38, 0xfd, 0xa8, 0x3a, 0x38, 0x60, 0x70, 0x00, 0x61, 0x20, 0x31, 0x03, 0x8a, 0x01, 0x61, 0x20, 0x31, 0x02, 0x8a, 0xb6, 0xaa, 0x3a, 0x38, 0xb6, 0xa8, 0x3a, 0x38, 0x42, 0xa9, 0x3a, 0x38, 0x60, 0x70, 0x00, 0x61, 0x20, 0x31, 0x03, 0x8a, 0x01, 0x61, 0x20, 0x31, 0x04, 0x8a, 0x00, 0x60, 0xbe, 0x58, 0xc6, 0x00, 0x3a, 0x38, 0x01, 0x60, 0xe8, 0x70, 0x80, 0x45, 0xbe, 0x58, 0xc6, 0x00, 0x3a, 0x38, 0xdd, 0xa8, 0x3a, 0x38, 0x60, 0x70, 0x1f, 0x61, 0x20, 0x21, 0x21, 0x5a, 0xfe, 0x5a, 0x41, 0x2a, 0xbe, 0x5a, 0xf9, 0x04, 0xa5, 0xa8, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x00, 0x00, 0x10, 0x8a, 0x06, 0x39, 0x01, 0x00, 0x1c, 0x8a, 0x06, 0x39, 0x02, 0x00, 0x2b, 0x8a, 0x06, 0x39, 0x03, 0x00, 0x3a, 0x8a, 0x06, 0x39, 0x04, 0x00, 0x49, 0x8a, 0x06, 0x39, 0x05, 0x00, 0x58, 0x8a, 0x3a, 0x38, 0x85, 0xaa, 0x80, 0x62, 0x57, 0x6a, 0x48, 0x63, 0x0e, 0x6b, 0x0c, 0x61, 0x24, 0x60, 0x01, 0x40, 0x19, 0x10, 0x07, 0x38, 0xaf, 0x45, 0x4b, 0x5c, 0x9d, 0x5b, 0x1a, 0x38, 0x3a, 0x38, 0x7a, 0x62, 0x02, 0x6a, 0xb5, 0x63, 0x02, 0x6b, 0x9e, 0x5c, 0xbb, 0x00, 0x9e, 0x5d, 0xbc, 0x00, 0xa4, 0x05, 0x19, 0x15, 0xa7, 0x38, 0xc0, 0x45, 0x7d, 0x5a, 0x19, 0x03, 0x77, 0x51, @@ -275,11 +275,11 @@ 0x80, 0x46, 0xa1, 0xa8, 0x00, 0xac, 0x01, 0x92, 0xa1, 0xaa, 0xa1, 0xac, 0x01, 0x92, 0xf9, 0xaa, 0x3a, 0x38, 0x1b, 0x20, 0x12, 0x78, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x02, 0x8a, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xf8, 0xa8, 0x3a, 0x38, 0xf8, 0xaa, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xca, 0xa8, 0x3a, 0x38, 0xca, 0xaa, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x07, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x01, 0x8a, 0x3a, 0x38, 0xf2, 0xaa, 0x64, 0x61, 0x3a, 0x38, 0xf2, 0xa8, 0x69, 0x61, 0x3a, 0x38, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xfe, 0x71, 0xc0, 0x46, 0xf0, 0xa8, 0x3a, 0x38, 0xf0, 0xaa, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x11, 0x78, 0xee, 0xa8, 0x3a, 0x38, 0x61, 0x71, 0x01, 0x60, 0x19, 0x48, 0x0b, 0x88, 0x60, 0x71, 0x00, 0x60, 0x19, 0x48, 0x05, 0x8a, 0x01, 0x60, 0x19, 0x48, 0x04, 0x88, 0xed, 0xa8, 0x02, 0x9e, 0xed, 0xaa, 0x00, 0x9e, 0xdd, 0xa8, 0x3a, 0x38, 0x61, 0x71, 0x01, 0x60, 0x19, 0x48, 0x0b, 0x88, 0x60, 0x71, 0x00, 0x60, 0x19, 0x48, 0x05, 0x8a, 0x01, 0x60, 0x19, 0x48, 0x04, 0x88, 0x8d, 0xa8, 0x02, 0x9e, 0x8d, 0xaa, 0x00, 0x9e, 0xdd, 0xa8, 0x3a, 0x38, 0x61, 0x71, 0x01, 0x60, 0x19, 0x48, 0x0b, 0x88, 0x60, 0x71, 0x00, 0x60, 0x19, 0x48, 0x05, 0x8a, 0x01, 0x60, 0x19, 0x48, 0x04, 0x88, 0xe6, 0xa8, 0x02, 0x9e, 0xe6, 0xaa, 0xef, 0x9f, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0x90, 0x00, 0x01, 0x8a, 0x74, 0x4b, 0x00, 0x47, 0x3a, 0x38, 0x60, 0x70, 0x95, 0xa8, 0x06, 0x39, 0x01, 0x00, 0x17, 0x8a, 0x06, 0x39, 0x02, 0x00, 0x18, 0x8a, 0x06, 0x39, 0x03, 0x00, 0x1a, 0x8a, 0x06, 0x39, 0x04, 0x00, 0x1c, 0x8a, 0x06, 0x39, 0x05, 0x00, 0x1e, 0x8a, 0x06, 0x39, 0x06, 0x00, 0x20, 0x8a, 0x06, 0x39, 0x07, 0x00, 0x22, 0x8a, 0x06, 0x39, 0x08, 0x00, 0x24, 0x8a, 0x95, 0xaa, 0x3a, 0x38, 0x52, 0x60, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x01, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x02, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x03, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x04, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x06, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x07, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x52, 0x60, 0x87, 0x20, -0x40, 0x47, 0x08, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0xa0, 0x00, 0x01, 0x8a, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xe8, 0xa8, 0x3a, 0x38, 0xe8, 0xa8, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0xb0, 0x00, 0x04, 0x8a, 0x06, 0x39, 0xb1, 0x00, 0x0d, 0x8a, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0x93, 0xa8, 0x3a, 0x38, 0x93, 0xa8, 0x3a, 0x38, 0x83, 0xaa, 0x8b, 0xaa, 0x60, 0x70, 0x1b, 0x20, 0x15, 0x38, 0x03, 0x00, 0x83, 0xac, 0x03, 0x90, 0x83, 0xaa, 0xc8, 0xa8, 0x3a, 0x38, 0x83, 0xa8, 0xc8, 0xa8, 0x3a, 0x38, 0x5f, 0x71, 0x24, 0x38, 0x0f, 0x00, 0x00, 0x38, 0x8d, 0x2e, 0x09, 0x58, 0x02, 0x39, 0x00, 0x00, 0x61, 0x0b, +0x40, 0x47, 0x08, 0x68, 0xbe, 0x58, 0xfb, 0x04, 0x3a, 0x38, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0xa0, 0x00, 0x01, 0x8a, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0xe8, 0xa8, 0x3a, 0x38, 0xe8, 0xa8, 0x3a, 0x38, 0x5f, 0x70, 0x06, 0x39, 0xb0, 0x00, 0x04, 0x8a, 0x06, 0x39, 0xb1, 0x00, 0x0d, 0x8a, 0x3a, 0x38, 0x60, 0x70, 0x06, 0x39, 0x01, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x00, 0x00, 0x03, 0x8a, 0x3a, 0x38, 0x93, 0xa8, 0x3a, 0x38, 0x93, 0xa8, 0x3a, 0x38, 0x83, 0xaa, 0x8b, 0xaa, 0x60, 0x70, 0x1b, 0x20, 0x15, 0x38, 0x03, 0x00, 0x83, 0xac, 0x03, 0x90, 0x83, 0xaa, 0xc8, 0xa8, 0x3a, 0x38, 0x83, 0xa8, 0xc8, 0xa8, 0x3a, 0x38, 0x5f, 0x71, 0x24, 0x38, 0x0f, 0x00, 0x00, 0x38, 0xa0, 0x2e, 0x09, 0x58, 0x02, 0x39, 0x00, 0x00, 0x74, 0x0b, 0x80, 0x47, 0x05, 0x8a, 0x60, 0x71, 0xfe, 0x59, 0x35, 0x39, 0x61, 0x00, 0x3b, 0x58, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0x3a, 0x38, 0xa2, 0xa8, 0x06, 0x60, 0x69, 0x78, 0x95, 0x60, 0x6a, 0x78, 0x60, 0x70, 0x6c, 0x78, 0x5f, 0x70, 0x6b, 0x78, 0xfe, 0x58, 0x15, 0x38, 0x60, 0x00, 0x03, 0x59, 0x24, 0x38, 0x00, 0xff, 0xfe, 0x58, 0x6d, 0x78, 0x24, 0x38, 0xff, 0x00, 0x6e, 0x78, 0xf1, 0x60, 0x6f, 0x78, 0xbe, 0xac, 0x0c, 0x90, 0x6b, 0x71, 0x24, 0x39, 0xff, 0x00, 0x18, 0x31, 0x07, 0x88, 0x6c, 0x71, 0x24, 0x39, 0xff, 0x00, 0x26, 0x39, 0x4e, 0x00, 0x01, 0x88, 0x82, 0xa8, 0x3a, 0x38, 0xa2, 0xa8, 0x12, 0x60, 0x69, 0x78, 0x94, 0x60, 0x6a, 0x78, 0x60, 0x70, 0x5f, 0x71, 0xfe, 0x59, 0x01, 0x28, 0x80, 0x61, 0x59, 0x69, 0x01, 0x00, 0x60, 0x71, 0x6c, 0x79, 0x5f, 0x71, 0x6b, 0x79, 0x01, 0x5b, 0xb9, 0x61, 0xc0, 0x47, 0x6d, 0x64, 0xef, 0x38, 0xcb, 0x47, 0x69, 0x59, 0x24, 0x38, 0x00, 0xff, 0xfe, 0x58, 0x1d, 0x5c, 0x24, 0x38, 0xff, 0x00, 0x1d, 0x5c, 0x19, 0x03, 0xf1, 0x60, 0x7b, 0x78, 0x3a, 0x38, 0xa2, 0xa8, 0x11, 0x60, 0x69, 0x78, 0x9b, 0x60, 0x6a, 0x78, 0x10, 0x60, 0x06, 0x58, 0x6b, 0x78, 0x9e, 0x58, 0xba, 0x00, 0xe2, 0xac, 0x01, 0x90, 0x19, 0x00, 0x6c, 0x78, 0x24, 0x60, 0xe2, 0xac, 0x01, 0x90, 0x19, 0x00, 0x6d, 0x78, 0x00, 0x60, 0x6e, 0x78, 0x00, 0x60, 0x6f, 0x78, 0x00, 0x60, 0x70, 0x78, 0x00, 0x60, 0x71, 0x78, 0x00, 0x60, 0x72, 0x78, 0x73, 0x78, 0x74, 0x78, 0x75, 0x78, 0x76, 0x78, 0x77, 0x78, 0x78, 0x78, 0x79, 0x78, 0x7a, 0x78, 0xe2, 0xaa, 0x3a, 0x38, 0x5f, 0x70, 0xfe, 0x58, 0x15, 0x38, 0x60, 0x00, 0x61, 0x71, 0xfe, 0x59, 0x35, 0x39, 0x62, 0x00, 0x3b, 0x58, 0x3a, 0x38, 0xba, 0x43, -0x00, 0x48, 0x98, 0x3f, 0x65, 0x43, 0x00, 0x62, 0xa9, 0x7a, 0xad, 0x72, 0x57, 0x7a, 0xa9, 0x70, 0xa8, 0x71, 0x19, 0x48, 0x28, 0x82, 0x19, 0x11, 0x19, 0x48, 0x03, 0x88, 0xaa, 0x72, 0x46, 0x5a, 0x01, 0x9e, 0x3c, 0x62, 0x1b, 0x02, 0x69, 0x7a, 0x1b, 0x12, 0x4e, 0x5a, 0x6c, 0x7a, 0x98, 0x62, 0x6a, 0x7a, 0xa9, 0x72, 0xbe, 0xac, 0x02, 0x92, 0x45, 0x3a, 0x40, 0x00, 0x6b, 0x7a, 0x81, 0xa8, 0xa2, 0xa8, 0x8b, 0xee, 0xb9, 0xac, 0x17, 0x90, 0xa2, 0xac, 0xfc, 0x93, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xbe, 0xac, 0x01, 0x92, 0x24, 0xa9, 0xa9, 0x70, 0x19, 0x00, 0xa9, 0x78, 0x57, 0x70, 0x7e, 0x00, 0x57, 0x78, 0xd4, 0x9f, 0x81, 0xaa, 0xa2, 0xaa, 0xbe, 0xac, 0x02, 0x90, 0x3c, 0xa9, 0x01, 0x9e, 0x24, 0xa9, 0x3a, 0x38, 0x81, 0xaa, 0xa2, 0xaa, 0xbe, 0xac, 0x02, 0x90, 0x3c, 0xa9, 0x01, 0x9e, 0x34, 0xbb, -0x40, 0x48, 0x24, 0xa9, 0x3a, 0x38, 0xb2, 0xa8, 0xa2, 0xa8, 0xaa, 0xaa, 0x00, 0x60, 0x5d, 0x78, 0x50, 0xb2, 0x3a, 0xaa, 0xd0, 0xb2, 0xf9, 0xab, 0x5e, 0x70, 0x06, 0x39, 0x83, 0x00, 0x01, 0x8a, 0x8b, 0xee, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x80, 0xb8, 0x81, 0xb8, 0x5a, 0x38, 0xe2, 0xa8, 0x66, 0x61, 0xbe, 0x59, 0x27, 0x1d, 0xba, 0xac, 0x98, 0x3c, 0x65, 0x43, 0x81, 0xaa, 0xb9, 0xaa, 0x5f, 0x70, 0xa2, 0x78, 0x60, 0x70, 0xa4, 0x78, 0x61, 0x70, 0xa5, 0x78, 0x62, 0x70, 0x01, 0x59, 0xa6, 0x78, 0x63, 0x70, 0xa7, 0x78, 0x24, 0x39, 0xff, 0x00, 0xfe, 0x59, 0x04, 0x38, 0xff, 0x00, 0x20, 0x28, 0x08, 0x58, 0x01, 0x5b, 0x00, 0x61, 0x1e, 0x62, 0x1c, 0x5a, 0x01, 0x5c, 0x02, 0x40, 0x78, 0x48, 0x06, 0x8a, 0x19, 0x04, 0xa8, 0x7c, 0x0f, 0x01, +0x00, 0x48, 0x98, 0x3f, 0x65, 0x43, 0x00, 0x62, 0xa9, 0x7a, 0xad, 0x72, 0x57, 0x7a, 0xa9, 0x70, 0xa8, 0x71, 0x19, 0x48, 0x28, 0x82, 0x19, 0x11, 0x19, 0x48, 0x03, 0x88, 0xaa, 0x72, 0x46, 0x5a, 0x01, 0x9e, 0x3c, 0x62, 0x1b, 0x02, 0x69, 0x7a, 0x1b, 0x12, 0x4e, 0x5a, 0x6c, 0x7a, 0x98, 0x62, 0x6a, 0x7a, 0xa9, 0x72, 0xbe, 0xac, 0x02, 0x92, 0x45, 0x3a, 0x40, 0x00, 0x6b, 0x7a, 0x81, 0xa8, 0xa2, 0xa8, 0x9e, 0xee, 0xb9, 0xac, 0x17, 0x90, 0xa2, 0xac, 0xfc, 0x93, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0xbe, 0xac, 0x01, 0x92, 0x24, 0xa9, 0xa9, 0x70, 0x19, 0x00, 0xa9, 0x78, 0x57, 0x70, 0x7e, 0x00, 0x57, 0x78, 0xd4, 0x9f, 0x81, 0xaa, 0xa2, 0xaa, 0xbe, 0xac, 0x02, 0x90, 0x3c, 0xa9, 0x01, 0x9e, 0x24, 0xa9, 0x3a, 0x38, 0x81, 0xaa, 0xa2, 0xaa, 0xbe, 0xac, 0x02, 0x90, 0x3c, 0xa9, 0x01, 0x9e, 0x47, 0xbb, +0x40, 0x48, 0x24, 0xa9, 0x3a, 0x38, 0xb2, 0xa8, 0xa2, 0xa8, 0xaa, 0xaa, 0x00, 0x60, 0x5d, 0x78, 0x50, 0xb2, 0x3a, 0xaa, 0xd0, 0xb2, 0xf9, 0xab, 0x5e, 0x70, 0x06, 0x39, 0x83, 0x00, 0x01, 0x8a, 0x9e, 0xee, 0x3e, 0x5f, 0x3e, 0x5e, 0x3e, 0x5d, 0x3e, 0x5c, 0x3e, 0x5b, 0x3e, 0x5a, 0x3e, 0x59, 0x3e, 0x58, 0x80, 0xb8, 0x81, 0xb8, 0x5a, 0x38, 0xe2, 0xa8, 0x66, 0x61, 0xbe, 0x59, 0x27, 0x1d, 0xba, 0xac, 0x98, 0x3c, 0x65, 0x43, 0x81, 0xaa, 0xb9, 0xaa, 0x5f, 0x70, 0xa2, 0x78, 0x60, 0x70, 0xa4, 0x78, 0x61, 0x70, 0xa5, 0x78, 0x62, 0x70, 0x01, 0x59, 0xa6, 0x78, 0x63, 0x70, 0xa7, 0x78, 0x24, 0x39, 0xff, 0x00, 0xfe, 0x59, 0x04, 0x38, 0xff, 0x00, 0x20, 0x28, 0x08, 0x58, 0x01, 0x5b, 0x00, 0x61, 0x1e, 0x62, 0x1c, 0x5a, 0x01, 0x5c, 0x02, 0x40, 0x78, 0x48, 0x06, 0x8a, 0x19, 0x04, 0xa8, 0x7c, 0x22, 0x01, 0x80, 0x48, 0xa3, 0x7c, 0x60, 0x13, 0xaa, 0x7b, 0x04, 0x9e, 0xa8, 0x7c, 0xa3, 0x7c, 0x1e, 0x63, 0xaa, 0x7b, 0x60, 0x71, 0x24, 0x39, 0xff, 0x00, 0xfe, 0x59, 0x61, 0x70, 0x04, 0x38, 0xff, 0x00, 0x20, 0x28, 0xab, 0x78, 0xa2, 0x70, 0x04, 0x38, 0xc0, 0x00, 0xbf, 0x38, 0x08, 0x58, 0x00, 0x61, 0x20, 0x31, 0x01, 0x8a, 0x2a, 0x9e, 0xa2, 0x70, 0x04, 0x39, 0x07, 0x00, 0x20, 0x3a, 0xa1, 0x48, 0x49, 0x5b, 0x5e, 0x5b, 0xa9, 0x48, 0xa6, 0x48, 0xa9, 0x48, 0xb0, 0x48, 0xb0, 0x48, 0x60, 0x63, 0x11, 0x6b, 0x0d, 0x9e, 0x00, 0x63, 0x05, 0x6b, 0x08, 0xac, 0x09, 0x90, 0x30, 0x63, 0x0b, 0x6b, 0x06, 0x9e, 0x9e, 0x5b, 0xe8, 0x00, 0x10, 0xac, 0x02, 0x90, 0x48, 0x63, 0x0e, 0x6b, 0x1e, 0x59, 0x1e, 0x58, 0x9e, 0x59, 0x27, 0x1d, 0x26, 0x38, 0x66, 0x00, 0x02, 0x88, 0x60, 0x63, 0x11, 0x6b, 0x3e, 0x58, 0xda, 0xb5, 0xc0, 0x48, 0x3e, 0x59, 0xad, 0x7b, 0xf7, 0xa8, 0xb9, 0xa8, 0x3a, 0x38, 0x9e, 0x58, 0xc6, 0x04, 0x18, 0x10, 0x2f, 0x8a, 0xff, 0x60, 0xff, 0x68, 0x8c, 0x61, 0x04, 0x69, 0x14, 0x62, 0x19, 0x12, 0x57, 0x38, 0x1d, 0x59, 0x00, 0x60, 0xbe, 0x58, 0xa0, 0x04, 0xbe, 0x58, 0xa1, 0x04, 0x19, 0x38, 0xf9, 0x48, 0x18, 0x60, 0x58, 0x48, 0x1d, 0x9c, 0x60, 0x38, 0x06, 0x16, 0x03, 0x59, 0x24, 0x3a, 0xff, 0x00, 0x4d, 0x38, 0x00, 0x71, 0x01, 0x60, 0xbe, 0x58, 0xa0, 0x04, 0xbe, 0x58, 0xa1, 0x04, 0x00, 0x39, 0x8c, 0x04, 0x7b, 0x59, 0x19, 0x38, 0x18, 0x49, 0x9e, 0x58, 0xa0, 0x04, 0x19, 0x00, 0xbe, 0x58, 0xa0, 0x04, 0x00, 0x39, 0x8c, 0x04, 0x23, 0x5b, 0xff, 0x62, 0xff, 0x6a, 0x59, 0x49, 0xf2, 0x89, 0x3a, 0x38, 0x00, 0x67, 0x9e, 0x58, 0xc6, 0x04, 0x00, 0x62, 0x00, 0x63, 0x23, 0x74, 0xe0, 0x39, 0xe8, 0x3c, 0x00, 0x49, 0xaa, 0x15, 0x23, 0x5e, 0xc4, 0x3e, 0xff, 0x00, 0x9e, 0x48, 0x04, 0x98, 0x5e, 0x48, 0x02, 0x94, 0xc1, 0x5a, 0xe1, 0x5b, 0x19, 0x07, 0xf8, 0x48, 0xf2, 0x97, 0xbe, 0x5a, 0xbc, 0x04, 0x00, 0x60, 0x9e, 0x59, 0xad, 0x04, 0x59, 0x48, 0x01, 0x9a, 0x01, 0x60, 0xbe, 0x58, 0xb2, 0x04, 0x3a, 0x38, 0x61, 0x5e, 0x00, 0x67, 0x19, 0x38, 0x44, 0x49, 0xe0, 0x39, 0xaa, 0x15, 0x23, 0x74, 0x99, 0x49, 0x1d, 0x98, 0xfe, 0x48, 0x1b, 0x8a, 0xe0, 0x38, 0x06, 0x16, 0x03, 0x59, 0x24, 0x39, 0x00, 0xff, 0x22, 0x39, 0x00, 0x71, 0x13, 0x8a, 0x19, 0x38, 0x5a, 0x49, 0x18, 0x10, 0x0f, 0x8a, 0xe0, 0x38, 0x06, 0x16, 0x03, 0x59, 0x24, 0x3a, 0xff, 0x00, 0x4d, 0x38, 0x00, 0x71, 0x9e, 0x58, 0xa1, 0x04, 0x19, 0x00, 0xbe, 0x58, 0xa1, 0x04, 0x00, 0x39, 0x8c, 0x04, 0xfb, 0x59, 0x19, 0x07, 0x9e, 0x58, 0x65, 0x7b, @@ -330,7 +330,7 @@ 0x40, 0x54, 0xbe, 0x58, 0x07, 0xf8, 0x5b, 0x38, 0x3e, 0x5b, 0x3a, 0x38, 0x3b, 0x61, 0xf8, 0x69, 0x81, 0x5a, 0xff, 0x38, 0x86, 0x5c, 0x44, 0x2a, 0x6f, 0x39, 0x4e, 0x54, 0x5b, 0x59, 0x19, 0x01, 0x3a, 0x38, 0x9d, 0x60, 0x4e, 0x68, 0xef, 0xb0, 0x9e, 0x58, 0x00, 0xf8, 0x10, 0xa8, 0xbe, 0x58, 0x00, 0xf8, 0x19, 0x38, 0x64, 0x54, 0x1a, 0x38, 0x1a, 0x38, 0x9e, 0x5e, 0xb2, 0x00, 0x1e, 0xac, 0xfa, 0x91, 0x00, 0x66, 0xbe, 0x5e, 0xb2, 0x00, 0x3a, 0x38, 0x94, 0xab, 0x26, 0x66, 0x04, 0x6e, 0xef, 0x3a, 0x6a, 0x54, 0xdd, 0x5e, 0x1a, 0x38, 0x94, 0xa9, 0x3a, 0x38, 0x30, 0x65, 0xa4, 0x15, 0x18, 0x61, 0x25, 0x40, 0x00, 0x3d, 0x18, 0x08, 0x26, 0x66, 0x04, 0x6e, 0x42, 0x38, 0x10, 0x00, 0x05, 0x88, 0xef, 0x3a, 0x7b, 0x54, 0xc5, 0x58, 0x1d, 0x5d, 0x3a, 0x38, 0xef, 0x3a, 0x82, 0x54, 0xc5, 0x58, 0x0b, 0xb5, 0x80, 0x54, 0xa3, 0x59, 0x20, 0x00, 0x1d, 0x5d, 0x3a, 0x38, 0x9e, 0x58, 0x04, 0xf8, 0x9e, 0x5a, 0x05, 0xf8, 0x9e, 0x5c, 0x00, 0xf8, 0x02, 0x00, 0x24, 0xac, 0x01, 0x90, 0x06, 0x58, 0x55, 0x61, 0x01, 0x40, 0x64, 0x62, 0x1c, 0x5a, 0xbe, 0x58, 0x08, 0x00, 0x3a, 0x38, 0x1e, 0x5b, 0x18, 0x61, 0x21, 0x5c, 0x00, 0x66, 0x0b, 0x7e, 0xc0, 0x3d, 0x18, 0x08, 0x30, 0x67, 0x00, 0x73, 0xff, 0x61, 0x7f, 0x69, 0xa3, 0x5a, 0x6f, 0x38, 0xa4, 0x54, 0x48, 0x5a, 0x1a, 0x38, 0x52, 0x3a, 0x08, 0x00, 0x04, 0x5a, 0x59, 0x48, 0x02, 0x98, 0x41, 0x59, 0xe1, 0x5b, 0xa4, 0x05, 0x19, 0x17, 0x10, 0x60, 0xf8, 0x48, 0xef, 0x95, 0x9e, 0x58, 0xb1, 0x00, 0x0c, 0x61, 0x01, 0x40, 0x00, 0x3a, 0x00, 0x05, 0x0a, 0x7a, 0x02, 0x62, 0x00, 0x61, 0xc1, 0x58, 0x1c, 0x5a, 0x0a, 0x72, 0x02, 0x02, 0x0b, 0x70, 0x00, 0xab, 0x6b, 0x5e, 0xc0, 0x54, 0x06, 0x39, 0x00, 0x00, 0x04, 0x8a, 0x06, 0x39, 0x01, 0x00, 0x06, 0x8a, 0x0d, 0x9e, 0x7b, 0x5a, 0x0b, 0x71, 0x19, 0x01, 0x0b, 0x79, 0x08, 0x9e, 0x43, 0x58, 0x10, 0x58, 0x60, 0x83, 0x03, 0x28, 0x1b, 0x5a, 0x00, 0x61, 0x0b, 0x79, 0x00, 0x9e, 0x19, 0x06, 0xdc, 0x48, 0xc3, 0x89, 0x3e, 0x5b, 0x3a, 0x38, 0xa5, 0xac, 0x0a, 0x90, 0x00, 0x61, 0x05, 0x69, 0xff, 0x60, 0x01, 0x68, 0x07, 0x38, 0xe4, 0x54, 0x9e, 0x58, 0xf9, 0x04, 0x1b, 0x59, 0x19, 0x01, 0x00, 0x60, 0xac, 0xb0, 0xfa, 0x61, 0x5f, 0x69, 0x29, 0x58, 0x02, 0x38, 0xff, 0xff, 0x02, 0x8a, 0xf5, 0xac, 0x47, 0x90, 0x40, 0x66, 0x9e, 0x5f, 0xbc, 0x00, 0x0c, 0x61, 0x9e, 0x58, 0xbd, 0x00, 0x01, 0x40, 0x07, 0x40, 0x00, 0x61, 0x05, 0x69, 0x20, 0x01, 0xff, 0x62, 0x01, 0x6a, 0x40, 0x12, 0xff, 0x60, 0xff, 0x68, 0x57, 0x38, 0x3c, 0xec, -0x00, 0x55, 0x1d, 0x59, 0x00, 0x67, 0xe6, 0x40, 0x00, 0x3d, 0x80, 0x57, 0x00, 0x3c, 0x00, 0x05, 0x00, 0x3b, 0x18, 0x08, 0xe2, 0x38, 0x08, 0x00, 0x01, 0x96, 0x3d, 0x94, 0xa1, 0x58, 0x81, 0x59, 0x5e, 0xeb, 0xa1, 0x58, 0x61, 0x59, 0x6b, 0xeb, 0x61, 0x58, 0x81, 0x59, 0x70, 0xeb, 0x18, 0x12, 0xf5, 0x8b, 0x19, 0x07, 0xe8, 0x9f, 0x00, 0x60, 0xac, 0xb0, 0xfa, 0x61, 0x5f, 0x69, 0x29, 0x58, 0x02, 0x38, 0xff, 0xff, 0x03, 0x8a, 0xf5, 0xac, 0x12, 0x90, 0x00, 0x60, 0x00, 0x3d, 0x40, 0x57, 0x00, 0x3c, 0xe0, 0x1a, 0x00, 0x3b, 0x18, 0x08, 0xa1, 0x58, 0x81, 0x59, 0x5e, 0xeb, 0xa1, 0x58, 0x61, 0x59, 0x6b, 0xeb, 0x61, 0x58, 0x81, 0x59, 0x70, 0xeb, 0x18, 0x12, 0xf5, 0x8b, 0x00, 0x63, 0xbe, 0x5b, 0x0b, 0x00, 0x0b, 0x61, 0x78, 0xab, 0x5a, 0x62, 0xe1, 0x6a, 0xac, 0xb2, 0xfa, 0x60, 0x5f, 0x68, 0x59, 0x3b, +0x00, 0x55, 0x1d, 0x59, 0x00, 0x67, 0xe6, 0x40, 0x00, 0x3d, 0x80, 0x57, 0x00, 0x3c, 0x00, 0x05, 0x00, 0x3b, 0x18, 0x08, 0xe2, 0x38, 0x08, 0x00, 0x01, 0x96, 0x3d, 0x94, 0xa1, 0x58, 0x81, 0x59, 0x80, 0xeb, 0xa1, 0x58, 0x61, 0x59, 0x8d, 0xeb, 0x61, 0x58, 0x81, 0x59, 0x92, 0xeb, 0x18, 0x12, 0xf5, 0x8b, 0x19, 0x07, 0xe8, 0x9f, 0x00, 0x60, 0xac, 0xb0, 0xfa, 0x61, 0x5f, 0x69, 0x29, 0x58, 0x02, 0x38, 0xff, 0xff, 0x03, 0x8a, 0xf5, 0xac, 0x12, 0x90, 0x00, 0x60, 0x00, 0x3d, 0x40, 0x57, 0x00, 0x3c, 0xe0, 0x1a, 0x00, 0x3b, 0x18, 0x08, 0xa1, 0x58, 0x81, 0x59, 0x80, 0xeb, 0xa1, 0x58, 0x61, 0x59, 0x8d, 0xeb, 0x61, 0x58, 0x81, 0x59, 0x92, 0xeb, 0x18, 0x12, 0xf5, 0x8b, 0x00, 0x63, 0xbe, 0x5b, 0x0b, 0x00, 0x0b, 0x61, 0x78, 0xab, 0x5a, 0x62, 0xe1, 0x6a, 0xac, 0xb2, 0xfa, 0x60, 0x5f, 0x68, 0x25, 0x3c, 0x40, 0x55, 0x00, 0x62, 0x57, 0x38, 0x7a, 0x38, 0x19, 0x10, 0x19, 0x11, 0xac, 0xb2, 0x09, 0x5a, 0x5b, 0x48, 0xf2, 0x89, 0x78, 0xa9, 0x1a, 0x38, 0x3a, 0x38, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdd, 0x41, 0x80, 0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x55, 0xc0, 0x55, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x55, @@ -363,6 +363,6 @@ 0x00, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x5e, 0x40, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5f, 0x80, 0x5f, 0xff, 0xff, 0x00, 0x80, 0x55, 0x55, 0x00, 0x40, 0x33, 0x33, 0xaa, 0x2a, 0x92, 0x24, 0x00, 0x20, 0x71, 0x1c, 0x99, 0x19, 0x45, 0x17, 0x55, 0x15, 0xb1, 0x13, 0x49, 0x12, 0x11, 0x11, 0x00, 0x10, 0x0f, 0x0f, 0x38, 0x0e, 0x79, 0x0d, 0xcc, 0x0c, 0x30, 0x0c, 0xa2, 0x0b, 0x21, 0x0b, 0xaa, 0x0a, 0x3d, 0x0a, 0xd8, 0x09, 0x7b, 0x09, 0x24, 0x09, 0xd3, 0x08, 0x88, 0x08, 0x42, 0x08, 0x00, 0x08, 0xc1, 0x07, 0x87, 0x07, 0x50, 0x07, 0x1c, 0x07, 0xeb, 0x06, 0xbc, 0x06, 0x90, 0x06, 0x66, 0x06, 0x3e, 0x06, 0x18, 0x06, 0xf4, 0x05, 0xd1, 0x05, 0xb0, 0x05, 0x90, 0x05, 0x72, 0x05, 0x55, 0x05, 0x39, 0x05, 0x1e, 0x05, 0x05, 0x05, 0xec, 0x04, 0xd4, 0x04, 0xbd, 0x04, 0xa7, 0x04, 0x92, 0x04, 0x7d, 0x04, 0x69, 0x04, 0x56, 0x04, 0x44, 0x04, 0x32, 0x04, 0x21, 0x04, 0x10, 0x04, 0x00, 0x04, 0xd4, 0x1d, -0xc0, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x88, 0x00, 0xff, 0xff, 0x00, 0x00, 0x42, 0xa0, 0x29, 0x30, 0xaa, 0x55, 0xcc, 0x33, 0xff, 0xff, 0xef, 0xb9, +0xc0, 0x5f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x88, 0x00, 0xff, 0xff, 0x00, 0x00, 0x44, 0xa0, 0x29, 0x30, 0xaa, 0x55, 0xcc, 0x33, 0xff, 0xff, 0xf1, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, diff --git a/drivers/input/touchscreen/wake_timeout.c b/drivers/input/touchscreen/wake_timeout.c new file mode 100644 index 00000000000..d4de44d2a80 --- /dev/null +++ b/drivers/input/touchscreen/wake_timeout.c @@ -0,0 +1,178 @@ +/* + * Screen wake timeout + * Copyright (C) 2014 flar2 + * + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 +#include +#include +#include + +#define WAKE_TIMEOUT_MAJOR_VERSION 2 +#define WAKE_TIMEOUT_MINOR_VERSION 0 +#define WAKEFUNC "wakefunc" + +static unsigned int wake_timeout = 0; +static struct alarm wakefunc_rtc; +static bool wakefunc_triggered = false; +void ext_elan_ktf3k_ts_set_power_state(void); + +static void wake_presspwr(struct work_struct * wake_presspwr_work) { + wakefunc_triggered = true; + ext_elan_ktf3k_ts_set_power_state(); + return; +} +static DECLARE_WORK(wake_presspwr_work, wake_presspwr); + +static void wake_pwrtrigger(void) { + schedule_work(&wake_presspwr_work); + return; +} + +static void wakefunc_rtc_start(void) +{ + ktime_t wakeup_time; + ktime_t curr_time; + + wakefunc_triggered = false; + curr_time = alarm_get_elapsed_realtime(); + wakeup_time = ktime_add_us(curr_time, + (wake_timeout * USEC_PER_MSEC * 60000)); + alarm_start_range(&wakefunc_rtc, wakeup_time, + wakeup_time); + pr_debug("%s: Current Time: %ld, Alarm set to: %ld\n", + WAKEFUNC, + ktime_to_timeval(curr_time).tv_sec, + ktime_to_timeval(wakeup_time).tv_sec); + + pr_info("%s: Timeout started for %u minutes\n", WAKEFUNC, + wake_timeout); +} + +static void wakefunc_rtc_cancel(void) +{ + int ret; + + wakefunc_triggered = false; + ret = alarm_cancel(&wakefunc_rtc); + if (ret) + pr_info("%s: Timeout canceled\n", WAKEFUNC); + else + pr_info("%s: Nothing to cancel\n", + WAKEFUNC); +} + + +static void wakefunc_rtc_callback(struct alarm *al) +{ + struct timeval ts; + ts = ktime_to_timeval(alarm_get_elapsed_realtime()); + + wake_pwrtrigger(); + + pr_debug("%s: Time of alarm expiry: %ld\n", WAKEFUNC, + ts.tv_sec); +} + + +//sysfs +static ssize_t show_wake_timeout(struct device *dev, + struct device_attribute *attr, char *buf) +{ + return snprintf(buf, PAGE_SIZE, "%d\n", wake_timeout); +} + +static ssize_t store_wake_timeout(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + unsigned int input; + int ret; + + ret = sscanf(buf, "%u", &input); + + if (ret != 1) { + return -EINVAL; + } + + wake_timeout = input; + + return count; +} + +static DEVICE_ATTR(wake_timeout, (S_IWUSR|S_IRUGO), + show_wake_timeout, store_wake_timeout); + +extern struct kobject *android_touch_kobj; + +static void wake_timeout_early_suspend(struct early_suspend *h) +{ + if (!pwr_key_pressed && !lid_closed && !wakefunc_triggered && wake_timeout > 0) + wakefunc_rtc_start(); + + return; +} + +static void wake_timeout_late_resume(struct early_suspend *h) +{ + wakefunc_rtc_cancel(); + return; +} + +static struct early_suspend wake_timeout_early_suspend_driver = { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 10, + .suspend = wake_timeout_early_suspend, + .resume = wake_timeout_late_resume, +}; + +static int __init wake_timeout_init(void) +{ + int rc; + + pr_info("wake_timeout version %d.%d\n", + WAKE_TIMEOUT_MAJOR_VERSION, + WAKE_TIMEOUT_MINOR_VERSION); + + alarm_init(&wakefunc_rtc, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP, + wakefunc_rtc_callback); + + rc = sysfs_create_file(android_touch_kobj, &dev_attr_wake_timeout.attr); + if (rc) { + pr_warn("%s: sysfs_create_file failed for wake_timeout\n", __func__); + } + + register_early_suspend(&wake_timeout_early_suspend_driver); + + return 0; +} + + +static void __exit wake_timeout_exit(void) +{ + + alarm_cancel(&wakefunc_rtc); + + return; +} + +MODULE_AUTHOR("flar2 "); +MODULE_DESCRIPTION("'wake_timeout' - Disable screen wake functions after timeout"); +MODULE_LICENSE("GPL v2"); + +module_init(wake_timeout_init); +module_exit(wake_timeout_exit); diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ef69d91516d..88e44ddf525 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -120,6 +120,7 @@ EXPORT_SYMBOL_GPL(iommu_present); * iommu_set_fault_handler() - set a fault handler for an iommu domain * @domain: iommu domain * @handler: fault handler + * @token: user data, will be passed back to the fault handler * * This function should be used by IOMMU users which want to be notified * whenever an IOMMU fault happens. @@ -128,11 +129,13 @@ EXPORT_SYMBOL_GPL(iommu_present); * error code otherwise. */ void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler) + iommu_fault_handler_t handler, + void *token) { BUG_ON(!domain); domain->handler = handler; + domain->handler_token = token; } EXPORT_SYMBOL_GPL(iommu_set_fault_handler); diff --git a/drivers/media/common/tuners/xc4000.c b/drivers/media/common/tuners/xc4000.c index 98a057f1318..075f54ab81d 100644 --- a/drivers/media/common/tuners/xc4000.c +++ b/drivers/media/common/tuners/xc4000.c @@ -933,7 +933,7 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, struct xc4000_priv *priv = fe->tuner_priv; struct firmware_properties new_fw; int rc = 0, is_retry = 0; - u16 hwmodel; + u16 hwmodel = 0; v4l2_std_id std0; u8 hw_major = 0, hw_minor = 0, fw_major = 0, fw_minor = 0; @@ -1095,12 +1095,12 @@ static int check_firmware(struct dvb_frontend *fe, unsigned int type, static void xc_debug_dump(struct xc4000_priv *priv) { - u16 adc_envelope; + u16 adc_envelope = 0; u32 freq_error_hz = 0; - u16 lock_status; + u16 lock_status = 0; u32 hsync_freq_hz = 0; - u16 frame_lines; - u16 quality; + u16 frame_lines = 0; + u16 quality = 0; u16 signal = 0; u16 noise = 0; u8 hw_majorversion = 0, hw_minorversion = 0; diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index eab2ea42420..e6c8ecee5ec 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -641,12 +641,12 @@ static int xc5000_fwupload(struct dvb_frontend *fe) static void xc_debug_dump(struct xc5000_priv *priv) { - u16 adc_envelope; + u16 adc_envelope = 0; u32 freq_error_hz = 0; - u16 lock_status; + u16 lock_status = 0; u32 hsync_freq_hz = 0; - u16 frame_lines; - u16 quality; + u16 frame_lines = 0; + u16 quality = 0; u8 hw_majorversion = 0, hw_minorversion = 0; u8 fw_majorversion = 0, fw_minorversion = 0; u16 fw_buildversion = 0; diff --git a/drivers/media/platform/msm/camera_v2/camera/camera.c b/drivers/media/platform/msm/camera_v2/camera/camera.c index e6e6cfeffb7..125dd5aa8b8 100644 --- a/drivers/media/platform/msm/camera_v2/camera/camera.c +++ b/drivers/media/platform/msm/camera_v2/camera/camera.c @@ -540,7 +540,6 @@ static int camera_v4l2_open(struct file *filep) rc = msm_create_session(pvdev->vdev->num, pvdev->vdev); if (rc < 0) goto session_fail; - rc = msm_create_command_ack_q(pvdev->vdev->num, 0); if (rc < 0) goto command_ack_q_fail; @@ -604,14 +603,12 @@ static int camera_v4l2_close(struct file *filep) camera_pack_event(filep, MSM_CAMERA_SET_PARM, MSM_CAMERA_PRIV_DEL_STREAM, -1, &event); - - /* Donot wait, imaging server may have crashed */ msm_post_event(&event, MSM_POST_EVT_TIMEOUT); camera_pack_event(filep, MSM_CAMERA_DEL_SESSION, 0, -1, &event); + msm_post_event(&event, MSM_POST_EVT_TIMEOUT); - /* Donot wait, imaging server may have crashed */ - msm_post_event(&event, -1); + msm_delete_command_ack_q(pvdev->vdev->num, 0); /* This should take care of both normal close * and application crashes */ @@ -620,8 +617,6 @@ static int camera_v4l2_close(struct file *filep) } else { camera_pack_event(filep, MSM_CAMERA_SET_PARM, MSM_CAMERA_PRIV_DEL_STREAM, -1, &event); - - /* Donot wait, imaging server may have crashed */ msm_post_event(&event, MSM_POST_EVT_TIMEOUT); msm_delete_command_ack_q(pvdev->vdev->num, diff --git a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.c b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.c index 96470fdb31b..da6f69f9705 100644 --- a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.c +++ b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.c @@ -426,7 +426,7 @@ void msm_gemini_hw_delay(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us) } } -int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, int m_cmds) +int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, uint32_t m_cmds) { int is_copy_to_user = -1; uint32_t data; diff --git a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.h b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.h index 84eed720f44..4a55565528c 100644 --- a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.h +++ b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_hw.h @@ -94,7 +94,7 @@ uint32_t msm_gemini_hw_read(struct msm_gemini_hw_cmd *hw_cmd_p); void msm_gemini_hw_write(struct msm_gemini_hw_cmd *hw_cmd_p); int msm_gemini_hw_wait(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us); void msm_gemini_hw_delay(struct msm_gemini_hw_cmd *hw_cmd_p, int m_us); -int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, int m_cmds); +int msm_gemini_hw_exec_cmds(struct msm_gemini_hw_cmd *hw_cmd_p, uint32_t m_cmds); void msm_gemini_io_dump(int size); #define MSM_GEMINI_PIPELINE_CLK_128MHZ 128 /* 8MP 128MHz */ diff --git a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_sync.c b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_sync.c index 010f7a2c016..15a540520f1 100644 --- a/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_sync.c +++ b/drivers/media/platform/msm/camera_v2/gemini/msm_gemini_sync.c @@ -23,6 +23,7 @@ #include "msm_gemini_platform.h" #include "msm_gemini_common.h" +# define UINT32_MAX (4294967295U) static int release_buf; /* size is based on 4k page size */ @@ -811,7 +812,7 @@ static int msm_gemini_ioctl_hw_cmds(struct msm_gemini_device *pgmn_dev, void * __user arg) { int is_copy_to_user; - int len; + uint32_t len; uint32_t m; struct msm_gemini_hw_cmds *hw_cmds_p; struct msm_gemini_hw_cmd *hw_cmd_p; @@ -820,6 +821,14 @@ static int msm_gemini_ioctl_hw_cmds(struct msm_gemini_device *pgmn_dev, GMN_PR_ERR("%s:%d] failed\n", __func__, __LINE__); return -EFAULT; } + + if ((m == 0) || (m > ((UINT32_MAX-sizeof(struct msm_gemini_hw_cmds))/ + sizeof(struct msm_gemini_hw_cmd)))) { + GMN_PR_ERR("%s:%d] outof range of hwcmds\n", + __func__, __LINE__); + return -EINVAL; + } + if (m > g_max_hw_cmds_cnt) { GMN_PR_ERR("%s:%d] hw_cmds_cnt of %d exceeds limit of %d\n", __func__, __LINE__, m, g_max_hw_cmds_cnt); diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c index 8cc15f6fb21..20178cffc65 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp32.c @@ -24,7 +24,7 @@ #define VFE32_BURST_LEN 3 #define VFE32_UB_SIZE 1024 -#define VFE32_EQUAL_SLICE_UB 204 +#define VFE32_EQUAL_SLICE_UB 198 #define VFE32_WM_BASE(idx) (0x4C + 0x18 * idx) #define VFE32_RDI_BASE(idx) (idx ? 0x734 + 0x4 * (idx - 1) : 0x06FC) #define VFE32_XBAR_BASE(idx) (0x40 + 0x4 * (idx / 4)) @@ -119,7 +119,6 @@ static void msm_vfe32_init_hardware_reg(struct vfe_device *vfe_dev) msm_camera_io_w(0xFFFFFFFF, vfe_dev->vfe_base + 0x24); msm_camera_io_w_mb(0x1FFFFFFF, vfe_dev->vfe_base + 0x28); msm_camera_io_w(0x80000000, vfe_dev->vfe_base + 0x600); - } static void msm_vfe32_process_reset_irq(struct vfe_device *vfe_dev, @@ -813,13 +812,13 @@ static void msm_vfe32_stats_cfg_ub(struct vfe_device *vfe_dev) int i; uint32_t ub_offset = VFE32_UB_SIZE; uint32_t ub_size[VFE32_NUM_STATS_TYPE] = { - 64, /*MSM_ISP_STATS_BG*/ - 64, /*MSM_ISP_STATS_BF*/ - 16, /*MSM_ISP_STATS_AWB*/ - 8, /*MSM_ISP_STATS_RS*/ + 107, /*MSM_ISP_STATS_BG*/ + 92, /*MSM_ISP_STATS_BF*/ + 2, /*MSM_ISP_STATS_AWB*/ + 7, /*MSM_ISP_STATS_RS*/ 16, /*MSM_ISP_STATS_CS*/ - 16, /*MSM_ISP_STATS_IHIST*/ - 16, /*MSM_ISP_STATS_BHIST*/ + 2, /*MSM_ISP_STATS_IHIST*/ + 7, /*MSM_ISP_STATS_BHIST*/ }; for (i = 0; i < VFE32_NUM_STATS_TYPE; i++) { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 34445067040..2061c69db7f 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -883,10 +883,12 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) rc = vfe_dev->hw_info->vfe_ops.core_ops.reset_hw(vfe_dev); if (rc <= 0) { - pr_err("%s: reset timeout\n", __func__); + pr_err("%s: reset timeout, rc = %ld\n", __func__, rc); mutex_unlock(&vfe_dev->core_mutex); mutex_unlock(&vfe_dev->realtime_mutex); - return -EINVAL; + if (rc != -ERESTARTSYS) + rc = -EINVAL; + return rc; } vfe_dev->vfe_hw_version = msm_camera_io_r(vfe_dev->vfe_base); ISP_DBG("%s: HW Version: 0x%x\n", __func__, vfe_dev->vfe_hw_version); diff --git a/drivers/media/platform/msm/camera_v2/ispif/Makefile b/drivers/media/platform/msm/camera_v2/ispif/Makefile index 443911f3bcc..c015f488281 100644 --- a/drivers/media/platform/msm/camera_v2/ispif/Makefile +++ b/drivers/media/platform/msm/camera_v2/ispif/Makefile @@ -1,3 +1,4 @@ +ccflags-y := -Wno-maybe-uninitialized ccflags-y += -Idrivers/media/platform/msm/camera_v2 ccflags-y += -Idrivers/media/platform/msm/camera_v2/sensor/io obj-$(CONFIG_MSM_CSID) += msm_ispif.o diff --git a/drivers/media/platform/msm/camera_v2/msm.c b/drivers/media/platform/msm/camera_v2/msm.c index 8a691c5f310..d8ad1d5fd09 100644 --- a/drivers/media/platform/msm/camera_v2/msm.c +++ b/drivers/media/platform/msm/camera_v2/msm.c @@ -402,19 +402,24 @@ void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id) list, __msm_queue_find_session, &session_id); if (!session) return; + mutex_lock(&session->lock); cmd_ack = msm_queue_find(&session->command_ack_q, struct msm_command_ack, list, __msm_queue_find_command_ack_q, &stream_id); - if (!cmd_ack) + if (!cmd_ack) { + mutex_unlock(&session->lock); return; + } msm_queue_drain(&cmd_ack->command_q, struct msm_command, list); spin_lock_irqsave(&(session->command_ack_q.lock), flags); list_del_init(&cmd_ack->list); + kzfree(cmd_ack); session->command_ack_q.len--; spin_unlock_irqrestore(&(session->command_ack_q.lock), flags); + mutex_unlock(&session->lock); } static inline int __msm_sd_close_subdevs(struct msm_sd_subdev *msm_sd, @@ -464,6 +469,7 @@ static void msm_remove_session_cmd_ack_q(struct msm_session *session) if (!session) return; + mutex_lock(&session->lock); /* to ensure error handling purpose, it needs to detach all subdevs * which are being connected to streams */ msm_queue_traverse_action(&session->command_ack_q, @@ -471,6 +477,8 @@ static void msm_remove_session_cmd_ack_q(struct msm_session *session) __msm_remove_session_cmd_ack_q, NULL); msm_queue_drain(&session->command_ack_q, struct msm_command_ack, list); + + mutex_unlock(&session->lock); } int msm_destroy_session(unsigned int session_id) @@ -646,7 +654,8 @@ int msm_post_event(struct v4l2_event *event, int timeout) msecs_to_jiffies(timeout)); if (list_empty_careful(&cmd_ack->command_q.list)) { if (!rc) { - pr_err("%s: Timed out\n", __func__); + pr_err("%s: Timed out for event type %d\n", + __func__, event->type); rc = -ETIMEDOUT; } if (rc < 0) { diff --git a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c index 451d81b8a61..d84ffe75141 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c +++ b/drivers/media/platform/msm/camera_v2/sensor/cci/msm_cci.c @@ -150,17 +150,20 @@ static int32_t msm_cci_validate_queue(struct cci_device *cci_dev, __func__, __LINE__); rc = wait_for_completion_interruptible_timeout(&cci_dev-> cci_master_info[master].reset_complete, CCI_TIMEOUT); - if (rc <= 0) { + if (rc == -ERESTARTSYS) { + pr_err("%s:%d failed: rc %d", __func__, __LINE__, rc); + } else if (rc <= 0) { pr_err("%s: wait_for_completion_interruptible_timeout %d\n", __func__, __LINE__); if (rc == 0) rc = -ETIMEDOUT; msm_cci_flush_queue(cci_dev, master); return rc; + } else { + rc = cci_dev->cci_master_info[master].status; + if (rc < 0) + pr_err("%s failed rc %d\n", __func__, rc); } - rc = cci_dev->cci_master_info[master].status; - if (rc < 0) - pr_err("%s failed rc %d\n", __func__, rc); } return rc; } @@ -330,7 +333,10 @@ static int32_t msm_cci_i2c_read(struct v4l2_subdev *sd, __LINE__); rc = wait_for_completion_interruptible_timeout(&cci_dev-> cci_master_info[master].reset_complete, CCI_TIMEOUT); - if (rc <= 0) { + if (rc == -ERESTARTSYS) { + pr_err("%s:%d failed: rc %d", __func__, __LINE__, rc); + goto ERROR; + } else if (rc <= 0) { pr_err("%s: wait_for_completion_interruptible_timeout %d\n", __func__, __LINE__); if (rc == 0) @@ -500,7 +506,9 @@ static int32_t msm_cci_i2c_write(struct v4l2_subdev *sd, __func__, __LINE__); rc = wait_for_completion_interruptible_timeout(&cci_dev-> cci_master_info[master].reset_complete, CCI_TIMEOUT); - if (rc <= 0) { + if (rc == -ERESTARTSYS) { + pr_err("%s:%d failed: rc %d", __func__, __LINE__, rc); + } else if (rc <= 0) { pr_err("%s: wait_for_completion_interruptible_timeout %d\n", __func__, __LINE__); if (rc == 0) diff --git a/drivers/media/platform/msm/camera_v2/sensor/mi1040.c b/drivers/media/platform/msm/camera_v2/sensor/mi1040.c old mode 100644 new mode 100755 index 806c650dd71..9e357ee8890 --- a/drivers/media/platform/msm/camera_v2/sensor/mi1040.c +++ b/drivers/media/platform/msm/camera_v2/sensor/mi1040.c @@ -779,6 +779,7 @@ int32_t mi1040_sensor_set_fps(struct msm_sensor_ctrl_t *s_ctrl, int fps) CDBG("--CAMERA--CAMERA_FPS_FIX_15\n"); rc = sensor_write_table(s_ctrl, Fix_15_fps, ARRAY_SIZE(Fix_15_fps)); + break; case CAMERA_FPS_AUTO_30: CDBG("--CAMERA--ERROR CAMERA_FPS_AUTO_30\n"); rc = sensor_write_table(s_ctrl, auto_30_fps, diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 1efad20fb17..1287645b984 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -409,8 +409,6 @@ static irqreturn_t ab3100_irq_handler(int irq, void *data) u32 fatevent; int err; - add_interrupt_randomness(irq); - err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1, event_regs, 3); if (err) @@ -933,9 +931,6 @@ static int __devinit ab3100_probe(struct i2c_client *client, err = request_threaded_irq(client->irq, NULL, ab3100_irq_handler, IRQF_ONESHOT, "ab3100-core", ab3100); - /* This real unpredictable IRQ is of course sampled for entropy */ - rand_initialize_irq(client->irq); - if (err) goto exit_no_irq; diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c index 6152bc2ef54..f2c24ba5df0 100644 --- a/drivers/mfd/wcd9xxx-core.c +++ b/drivers/mfd/wcd9xxx-core.c @@ -82,6 +82,22 @@ int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg) } EXPORT_SYMBOL_GPL(wcd9xxx_reg_read); +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +int wcd9xxx_reg_read_safe(struct wcd9xxx *wcd9xxx, unsigned short reg) +{ + u8 val; + int ret; + + ret = wcd9xxx_read(wcd9xxx, reg, 1, &val, false); + + if (ret < 0) + return ret; + else + return val; +} +EXPORT_SYMBOL_GPL(wcd9xxx_reg_read_safe); +#endif + static int wcd9xxx_write(struct wcd9xxx *wcd9xxx, unsigned short reg, int bytes, void *src, bool interface_reg) { diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index 613ddd502ad..a18527cd997 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -551,6 +551,8 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, unsigned long flags; struct qseecom_client_listener_data_irsp send_data_rsp; struct qseecom_registered_listener_list *ptr_svc = NULL; + sigset_t new_sigset; + sigset_t old_sigset; while (resp->result == QSEOS_RESULT_INCOMPLETE) { @@ -576,17 +578,28 @@ static int __qseecom_process_incomplete_cmd(struct qseecom_dev_handle *data, } pr_debug("waking up rcv_req_wq and " "waiting for send_resp_wq\n"); - if (wait_event_freezable(qseecom.send_resp_wq, - __qseecom_listener_has_sent_rsp(data))) { - pr_warning("Interrupted: exiting send_cmd loop\n"); - return -ERESTARTSYS; - } + /* initialize the new signal mask with all signals*/ + sigfillset(&new_sigset); + /* block all signals */ + sigprocmask(SIG_SETMASK, &new_sigset, &old_sigset); + + do { + if (!wait_event_freezable(qseecom.send_resp_wq, + __qseecom_listener_has_sent_rsp(data))) + break; + } while (1); + + /* restore signal mask */ + sigprocmask(SIG_SETMASK, &old_sigset, NULL); if (data->abort) { - pr_err("Aborting listener service %d\n", - data->listener.id); + pr_err("Abort clnt %d waiting on lstnr svc %d, ret %d", + data->client.app_id, lstnr, ret); return -ENODEV; + } + + qseecom.send_resp_flag = 0; send_data_rsp.qsee_cmd_id = QSEOS_LISTENER_DATA_RSP_COMMAND; send_data_rsp.listener_id = lstnr ; diff --git a/drivers/misc/slimport_anx7808/slimport_tx_drv.c b/drivers/misc/slimport_anx7808/slimport_tx_drv.c index 06cac2b7d5f..14879094b8b 100644 --- a/drivers/misc/slimport_anx7808/slimport_tx_drv.c +++ b/drivers/misc/slimport_anx7808/slimport_tx_drv.c @@ -1187,7 +1187,6 @@ static void sp_tx_enable_audio_output(unchar benable) sp_read_reg(TX_P0, SP_TX_AUD_CTRL, &c); if (benable) { - sp_read_reg(TX_P0, SP_TX_AUD_CTRL, &c); if (c&AUD_EN) { c &= ~AUD_EN; sp_write_reg(TX_P0, SP_TX_AUD_CTRL, c); @@ -2307,7 +2306,7 @@ void sp_tx_edid_read(void) bedid_break = 0; sp_tx_addronly_set(1); sp_write_reg(TX_P0, SP_TX_AUX_CTRL_REG, 0x04); - sp_write_reg(TX_P0, SP_TX_AUX_CTRL_REG2, 0x01); + sp_write_reg(TX_P0, SP_TX_AUX_CTRL_REG2, 0x03); sp_tx_wait_aux_finished(); edid_block = sp_tx_get_edid_block(); @@ -3189,7 +3188,7 @@ static void hdmi_rx_restart_audio_chk(void) SP_DEV_DBG("WAIT_AUDIO: hdmi_rx_restart_audio_chk.\n"); g_cts_got = 0; g_audio_got = 0; - if (hdmi_system_state == HDMI_AUDIO_CONFIG) + if (hdmi_system_state > HDMI_AUDIO_CONFIG) hdmi_rx_set_sys_state(HDMI_AUDIO_CONFIG); } @@ -3670,7 +3669,7 @@ static void hdmi_rx_hdmi_dvi_int(void) SP_DEV_NOTICE("hdmi_rx_hdmi_dvi_int: HDMI MODE."); if (hdmi_system_state == HDMI_PLAYBACK) - hdmi_rx_set_sys_state(HDMI_AUDIO_CONFIG); + hdmi_rx_restart_audio_chk(); } else { hdmi_rx_unmute_audio(); } diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index 27a127c9e8d..15bebc861ac 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c @@ -796,7 +796,7 @@ static int mmc_blk_cmd_error(struct request *req, const char *name, int error, * Otherwise we don't understand what happened, so abort. */ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, - struct mmc_blk_request *brq, int *ecc_err) + struct mmc_blk_request *brq, int *ecc_err, int *gen_err) { bool prev_cmd_status_valid = true; u32 status, stop_status = 0; @@ -834,6 +834,16 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, (brq->cmd.resp[0] & R1_CARD_ECC_FAILED)) *ecc_err = 1; + /* Flag General errors */ + if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) + if ((status & R1_ERROR) || + (brq->stop.resp[0] & R1_ERROR)) { + pr_err("%s: %s: general error sending stop or status command, stop cmd response %#x, card status %#x\n", + req->rq_disk->disk_name, __func__, + brq->stop.resp[0], status); + *gen_err = 1; + } + /* * Check the current card state. If it is in some data transfer * mode, tell it to stop (and hopefully transition back to TRAN.) @@ -853,6 +863,13 @@ static int mmc_blk_cmd_recovery(struct mmc_card *card, struct request *req, return ERR_ABORT; if (stop_status & R1_CARD_ECC_FAILED) *ecc_err = 1; + if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) + if (stop_status & R1_ERROR) { + pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", + req->rq_disk->disk_name, __func__, + stop_status); + *gen_err = 1; + } } /* Check for set block count errors */ @@ -1123,7 +1140,7 @@ static int mmc_blk_err_check(struct mmc_card *card, mmc_active); struct mmc_blk_request *brq = &mq_mrq->brq; struct request *req = mq_mrq->req; - int ecc_err = 0; + int ecc_err = 0, gen_err = 0; /* * sbc.error indicates a problem with the set block count @@ -1137,7 +1154,7 @@ static int mmc_blk_err_check(struct mmc_card *card, */ if (brq->sbc.error || brq->cmd.error || brq->stop.error || brq->data.error) { - switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err)) { + switch (mmc_blk_cmd_recovery(card, req, brq, &ecc_err, &gen_err)) { case ERR_RETRY: return MMC_BLK_RETRY; case ERR_ABORT: @@ -1167,6 +1184,15 @@ static int mmc_blk_err_check(struct mmc_card *card, */ if (!mmc_host_is_spi(card->host) && rq_data_dir(req) != READ) { u32 status; + + /* Check stop command response */ + if (brq->stop.resp[0] & R1_ERROR) { + pr_err("%s: %s: general error sending stop command, stop cmd response %#x\n", + req->rq_disk->disk_name, __func__, + brq->stop.resp[0]); + gen_err = 1; + } + do { int err = get_card_status(card, &status, 5); if (err) { @@ -1174,6 +1200,14 @@ static int mmc_blk_err_check(struct mmc_card *card, req->rq_disk->disk_name, err); return MMC_BLK_CMD_ERR; } + + if (status & R1_ERROR) { + pr_err("%s: %s: general error sending status command, card status %#x\n", + req->rq_disk->disk_name, __func__, + status); + gen_err = 1; + } + /* * Some cards mishandle the status bits, * so make sure to check both the busy @@ -1183,6 +1217,13 @@ static int mmc_blk_err_check(struct mmc_card *card, (R1_CURRENT_STATE(status) == R1_STATE_PRG)); } + /* if general error occurs, retry the write operation. */ + if (gen_err) { + pr_warn("%s: retrying write for general error\n", + req->rq_disk->disk_name); + return MMC_BLK_RETRY; + } + if (brq->data.error) { pr_err("%s: error %d transferring data, sector %u, nr %u, cmd response %#x, card status %#x\n", req->rq_disk->disk_name, brq->data.error, diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index d40f6c85272..5afcb73d0d7 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c @@ -57,7 +57,7 @@ static struct workqueue_struct *workqueue; * performance cost, and for other reasons may not always be desired. * So we allow it it to be disabled. */ -bool use_spi_crc = 1; +bool use_spi_crc = 0; module_param(use_spi_crc, bool, 0); /* diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 3cbda0851f8..cd7228ee9df 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -192,7 +192,7 @@ static inline int phy_find_setting(int speed, int duplex) * the mask in features. Returns the index of the last setting * if nothing else matches. */ -static inline int phy_find_valid(int idx, u32 features) +static inline int phy_find_valid(unsigned int idx, u32 features) { while (idx < MAX_NUM_SETTINGS && !(settings[idx].setting & features)) idx++; diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index 21d7151fb0a..2de3ec5f163 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -741,7 +741,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) #ifdef CONFIG_PPP_FILTER case PPPIOCSPASS: { - struct sock_filter *code; + struct sock_filter *code = NULL; err = get_filter(argp, &code); if (err >= 0) { ppp_lock(ppp); @@ -755,7 +755,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg) } case PPPIOCSACTIVE: { - struct sock_filter *code; + struct sock_filter *code = NULL; err = get_filter(argp, &code); if (err >= 0) { ppp_lock(ppp); diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 62963040351..411cd204149 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -1,7 +1,7 @@ # # Makefile for USB Network drivers # - +ccflags-y := -Wno-uninitialized obj-$(CONFIG_USB_CATC) += catc.o obj-$(CONFIG_USB_KAWETH) += kaweth.o obj-$(CONFIG_USB_PEGASUS) += pegasus.o diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c deleted file mode 100644 index 200f165c0c6..00000000000 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ /dev/null @@ -1,1402 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Luis Rodriguez - * Copyright (c) 2007-2008 Pavel Roskin - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/****************************\ - Reset function and helpers -\****************************/ - -#include - -#include /* To determine if a card is pci-e */ -#include -#include -#include "ath5k.h" -#include "reg.h" -#include "debug.h" - - -/** - * DOC: Reset function and helpers - * - * Here we implement the main reset routine, used to bring the card - * to a working state and ready to receive. We also handle routines - * that don't fit on other places such as clock, sleep and power control - */ - - -/******************\ -* Helper functions * -\******************/ - -/** - * ath5k_hw_register_timeout() - Poll a register for a flag/field change - * @ah: The &struct ath5k_hw - * @reg: The register to read - * @flag: The flag/field to check on the register - * @val: The field value we expect (if we check a field) - * @is_set: Instead of checking if the flag got cleared, check if it got set - * - * Some registers contain flags that indicate that an operation is - * running. We use this function to poll these registers and check - * if these flags get cleared. We also use it to poll a register - * field (containing multiple flags) until it gets a specific value. - * - * Returns -EAGAIN if we exceeded AR5K_TUNE_REGISTER_TIMEOUT * 15us or 0 - */ -int -ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, u32 val, - bool is_set) -{ - int i; - u32 data; - - for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { - data = ath5k_hw_reg_read(ah, reg); - if (is_set && (data & flag)) - break; - else if ((data & flag) == val) - break; - udelay(15); - } - - return (i <= 0) ? -EAGAIN : 0; -} - - -/*************************\ -* Clock related functions * -\*************************/ - -/** - * ath5k_hw_htoclock() - Translate usec to hw clock units - * @ah: The &struct ath5k_hw - * @usec: value in microseconds - * - * Translate usecs to hw clock units based on the current - * hw clock rate. - * - * Returns number of clock units - */ -unsigned int -ath5k_hw_htoclock(struct ath5k_hw *ah, unsigned int usec) -{ - struct ath_common *common = ath5k_hw_common(ah); - return usec * common->clockrate; -} - -/** - * ath5k_hw_clocktoh() - Translate hw clock units to usec - * @ah: The &struct ath5k_hw - * @clock: value in hw clock units - * - * Translate hw clock units to usecs based on the current - * hw clock rate. - * - * Returns number of usecs - */ -unsigned int -ath5k_hw_clocktoh(struct ath5k_hw *ah, unsigned int clock) -{ - struct ath_common *common = ath5k_hw_common(ah); - return clock / common->clockrate; -} - -/** - * ath5k_hw_init_core_clock() - Initialize core clock - * @ah: The &struct ath5k_hw - * - * Initialize core clock parameters (usec, usec32, latencies etc), - * based on current bwmode and chipset properties. - */ -static void -ath5k_hw_init_core_clock(struct ath5k_hw *ah) -{ - struct ieee80211_channel *channel = ah->ah_current_channel; - struct ath_common *common = ath5k_hw_common(ah); - u32 usec_reg, txlat, rxlat, usec, clock, sclock, txf2txs; - - /* - * Set core clock frequency - */ - switch (channel->hw_value) { - case AR5K_MODE_11A: - clock = 40; - break; - case AR5K_MODE_11B: - clock = 22; - break; - case AR5K_MODE_11G: - default: - clock = 44; - break; - } - - /* Use clock multiplier for non-default - * bwmode */ - switch (ah->ah_bwmode) { - case AR5K_BWMODE_40MHZ: - clock *= 2; - break; - case AR5K_BWMODE_10MHZ: - clock /= 2; - break; - case AR5K_BWMODE_5MHZ: - clock /= 4; - break; - default: - break; - } - - common->clockrate = clock; - - /* - * Set USEC parameters - */ - /* Set USEC counter on PCU*/ - usec = clock - 1; - usec = AR5K_REG_SM(usec, AR5K_USEC_1); - - /* Set usec duration on DCU */ - if (ah->ah_version != AR5K_AR5210) - AR5K_REG_WRITE_BITS(ah, AR5K_DCU_GBL_IFS_MISC, - AR5K_DCU_GBL_IFS_MISC_USEC_DUR, - clock); - - /* Set 32MHz USEC counter */ - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF2413) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_radio == AR5K_RF2316) || - (ah->ah_radio == AR5K_RF2317)) - /* Remain on 40MHz clock ? */ - sclock = 40 - 1; - else - sclock = 32 - 1; - sclock = AR5K_REG_SM(sclock, AR5K_USEC_32); - - /* - * Set tx/rx latencies - */ - usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); - txlat = AR5K_REG_MS(usec_reg, AR5K_USEC_TX_LATENCY_5211); - rxlat = AR5K_REG_MS(usec_reg, AR5K_USEC_RX_LATENCY_5211); - - /* - * Set default Tx frame to Tx data start delay - */ - txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; - - /* - * 5210 initvals don't include usec settings - * so we need to use magic values here for - * tx/rx latencies - */ - if (ah->ah_version == AR5K_AR5210) { - /* same for turbo */ - txlat = AR5K_INIT_TX_LATENCY_5210; - rxlat = AR5K_INIT_RX_LATENCY_5210; - } - - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - /* 5311 has different tx/rx latency masks - * from 5211, since we deal 5311 the same - * as 5211 when setting initvals, shift - * values here to their proper locations - * - * Note: Initvals indicate tx/rx/ latencies - * are the same for turbo mode */ - txlat = AR5K_REG_SM(txlat, AR5K_USEC_TX_LATENCY_5210); - rxlat = AR5K_REG_SM(rxlat, AR5K_USEC_RX_LATENCY_5210); - } else - switch (ah->ah_bwmode) { - case AR5K_BWMODE_10MHZ: - txlat = AR5K_REG_SM(txlat * 2, - AR5K_USEC_TX_LATENCY_5211); - rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX, - AR5K_USEC_RX_LATENCY_5211); - txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_10MHZ; - break; - case AR5K_BWMODE_5MHZ: - txlat = AR5K_REG_SM(txlat * 4, - AR5K_USEC_TX_LATENCY_5211); - rxlat = AR5K_REG_SM(AR5K_INIT_RX_LAT_MAX, - AR5K_USEC_RX_LATENCY_5211); - txf2txs = AR5K_INIT_TXF2TXD_START_DELAY_5MHZ; - break; - case AR5K_BWMODE_40MHZ: - txlat = AR5K_INIT_TX_LAT_MIN; - rxlat = AR5K_REG_SM(rxlat / 2, - AR5K_USEC_RX_LATENCY_5211); - txf2txs = AR5K_INIT_TXF2TXD_START_DEFAULT; - break; - default: - break; - } - - usec_reg = (usec | sclock | txlat | rxlat); - ath5k_hw_reg_write(ah, usec_reg, AR5K_USEC); - - /* On 5112 set tx frame to tx data start delay */ - if (ah->ah_radio == AR5K_RF5112) { - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL2, - AR5K_PHY_RF_CTL2_TXF2TXD_START, - txf2txs); - } -} - -/** - * ath5k_hw_set_sleep_clock() - Setup sleep clock operation - * @ah: The &struct ath5k_hw - * @enable: Enable sleep clock operation (false to disable) - * - * If there is an external 32KHz crystal available, use it - * as ref. clock instead of 32/40MHz clock and baseband clocks - * to save power during sleep or restore normal 32/40MHz - * operation. - * - * NOTE: When operating on 32KHz certain PHY registers (27 - 31, - * 123 - 127) require delay on access. - */ -static void -ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 scal, spending, sclock; - - /* Only set 32KHz settings if we have an external - * 32KHz crystal present */ - if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || - AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && - enable) { - - /* 1 usec/cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); - /* Set up tsf increment on each cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); - - /* Set baseband sleep control registers - * and sleep control rate */ - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_radio == AR5K_RF2316) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { - ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); - } else { - ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); - } - - /* Enable sleep clock operation */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - } else { - - /* Disable sleep clock operation and - * restore default parameters */ - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); - - /* Set DAC/ADC delays */ - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); - - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ee->ee_is_hb63) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - - ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_radio == AR5K_RF2316) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - /* Set up tsf increment on each cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_radio == AR5K_RF2316) || - (ah->ah_radio == AR5K_RF2317)) - sclock = 40 - 1; - else - sclock = 32 - 1; - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, sclock); - } -} - - -/*********************\ -* Reset/Sleep control * -\*********************/ - -/** - * ath5k_hw_nic_reset() - Reset the various chipset units - * @ah: The &struct ath5k_hw - * @val: Mask to indicate what units to reset - * - * To reset the various chipset units we need to write - * the mask to AR5K_RESET_CTL and poll the register until - * all flags are cleared. - * - * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) - */ -static int -ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) -{ - int ret; - u32 mask = val ? val : ~0U; - - /* Read-and-clear RX Descriptor Pointer*/ - ath5k_hw_reg_read(ah, AR5K_RXDP); - - /* - * Reset the device and wait until success - */ - ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); - - /* Wait at least 128 PCI clocks */ - usleep_range(15, 20); - - if (ah->ah_version == AR5K_AR5210) { - val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA - | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; - mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA - | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; - } else { - val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; - mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; - } - - ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false); - - /* - * Reset configuration register (for hw byte-swap). Note that this - * is only set for big endian. We do the necessary magic in - * AR5K_INIT_CFG. - */ - if ((val & AR5K_RESET_CTL_PCU) == 0) - ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); - - return ret; -} - -/** - * ath5k_hw_wisoc_reset() - Reset AHB chipset - * @ah: The &struct ath5k_hw - * @flags: Mask to indicate what units to reset - * - * Same as ath5k_hw_nic_reset but for AHB based devices - * - * Returns 0 if we are O.K. or -EAGAIN (from athk5_hw_register_timeout) - */ -static int -ath5k_hw_wisoc_reset(struct ath5k_hw *ah, u32 flags) -{ - u32 mask = flags ? flags : ~0U; - u32 __iomem *reg; - u32 regval; - u32 val = 0; - - /* ah->ah_mac_srev is not available at this point yet */ - if (ah->devid >= AR5K_SREV_AR2315_R6) { - reg = (u32 __iomem *) AR5K_AR2315_RESET; - if (mask & AR5K_RESET_CTL_PCU) - val |= AR5K_AR2315_RESET_WMAC; - if (mask & AR5K_RESET_CTL_BASEBAND) - val |= AR5K_AR2315_RESET_BB_WARM; - } else { - reg = (u32 __iomem *) AR5K_AR5312_RESET; - if (to_platform_device(ah->dev)->id == 0) { - if (mask & AR5K_RESET_CTL_PCU) - val |= AR5K_AR5312_RESET_WMAC0; - if (mask & AR5K_RESET_CTL_BASEBAND) - val |= AR5K_AR5312_RESET_BB0_COLD | - AR5K_AR5312_RESET_BB0_WARM; - } else { - if (mask & AR5K_RESET_CTL_PCU) - val |= AR5K_AR5312_RESET_WMAC1; - if (mask & AR5K_RESET_CTL_BASEBAND) - val |= AR5K_AR5312_RESET_BB1_COLD | - AR5K_AR5312_RESET_BB1_WARM; - } - } - - /* Put BB/MAC into reset */ - regval = ioread32(reg); - iowrite32(regval | val, reg); - regval = ioread32(reg); - usleep_range(100, 150); - - /* Bring BB/MAC out of reset */ - iowrite32(regval & ~val, reg); - regval = ioread32(reg); - - /* - * Reset configuration register (for hw byte-swap). Note that this - * is only set for big endian. We do the necessary magic in - * AR5K_INIT_CFG. - */ - if ((flags & AR5K_RESET_CTL_PCU) == 0) - ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); - - return 0; -} - -/** - * ath5k_hw_set_power_mode() - Set power mode - * @ah: The &struct ath5k_hw - * @mode: One of enum ath5k_power_mode - * @set_chip: Set to true to write sleep control register - * @sleep_duration: How much time the device is allowed to sleep - * when sleep logic is enabled (in 128 microsecond increments). - * - * This function is used to configure sleep policy and allowed - * sleep modes. For more information check out the sleep control - * register on reg.h and STA_ID1. - * - * Returns 0 on success, -EIO if chip didn't wake up or -EINVAL if an invalid - * mode is requested. - */ -static int -ath5k_hw_set_power_mode(struct ath5k_hw *ah, enum ath5k_power_mode mode, - bool set_chip, u16 sleep_duration) -{ - unsigned int i; - u32 staid, data; - - staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); - - switch (mode) { - case AR5K_PM_AUTO: - staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; - /* fallthrough */ - case AR5K_PM_NETWORK_SLEEP: - if (set_chip) - ath5k_hw_reg_write(ah, - AR5K_SLEEP_CTL_SLE_ALLOW | - sleep_duration, - AR5K_SLEEP_CTL); - - staid |= AR5K_STA_ID1_PWR_SV; - break; - - case AR5K_PM_FULL_SLEEP: - if (set_chip) - ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, - AR5K_SLEEP_CTL); - - staid |= AR5K_STA_ID1_PWR_SV; - break; - - case AR5K_PM_AWAKE: - - staid &= ~AR5K_STA_ID1_PWR_SV; - - if (!set_chip) - goto commit; - - data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); - - /* If card is down we 'll get 0xffff... so we - * need to clean this up before we write the register - */ - if (data & 0xffc00000) - data = 0; - else - /* Preserve sleep duration etc */ - data = data & ~AR5K_SLEEP_CTL_SLE; - - ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, - AR5K_SLEEP_CTL); - usleep_range(15, 20); - - for (i = 200; i > 0; i--) { - /* Check if the chip did wake up */ - if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & - AR5K_PCICFG_SPWR_DN) == 0) - break; - - /* Wait a bit and retry */ - usleep_range(50, 75); - ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, - AR5K_SLEEP_CTL); - } - - /* Fail if the chip didn't wake up */ - if (i == 0) - return -EIO; - - break; - - default: - return -EINVAL; - } - -commit: - ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); - - return 0; -} - -/** - * ath5k_hw_on_hold() - Put device on hold - * @ah: The &struct ath5k_hw - * - * Put MAC and Baseband on warm reset and keep that state - * (don't clean sleep control register). After this MAC - * and Baseband are disabled and a full reset is needed - * to come back. This way we save as much power as possible - * without putting the card on full sleep. - * - * Returns 0 on success or -EIO on error - */ -int -ath5k_hw_on_hold(struct ath5k_hw *ah) -{ - struct pci_dev *pdev = ah->pdev; - u32 bus_flags; - int ret; - - if (ath5k_get_bus_type(ah) == ATH_AHB) - return 0; - - /* Make sure device is awake */ - ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); - return ret; - } - - /* - * Put chipset on warm reset... - * - * Note: putting PCI core on warm reset on PCI-E cards - * results card to hang and always return 0xffff... so - * we ignore that flag for PCI-E cards. On PCI cards - * this flag gets cleared after 64 PCI clocks. - */ - bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI; - - if (ah->ah_version == AR5K_AR5210) { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | - AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - usleep_range(2000, 2500); - } else { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); - } - - if (ret) { - ATH5K_ERR(ah, "failed to put device on warm reset\n"); - return -EIO; - } - - /* ...wakeup again!*/ - ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah, "failed to put device on hold\n"); - return ret; - } - - return ret; -} - -/** - * ath5k_hw_nic_wakeup() - Force card out of sleep - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * Bring up MAC + PHY Chips and program PLL - * NOTE: Channel is NULL for the initial wakeup. - * - * Returns 0 on success, -EIO on hw failure or -EINVAL for false channel infos - */ -int -ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel) -{ - struct pci_dev *pdev = ah->pdev; - u32 turbo, mode, clock, bus_flags; - int ret; - - turbo = 0; - mode = 0; - clock = 0; - - if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) { - /* Wakeup the device */ - ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah, "failed to wakeup the MAC Chip\n"); - return ret; - } - } - - /* - * Put chipset on warm reset... - * - * Note: putting PCI core on warm reset on PCI-E cards - * results card to hang and always return 0xffff... so - * we ignore that flag for PCI-E cards. On PCI cards - * this flag gets cleared after 64 PCI clocks. - */ - bus_flags = (pdev && pci_is_pcie(pdev)) ? 0 : AR5K_RESET_CTL_PCI; - - if (ah->ah_version == AR5K_AR5210) { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | - AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - usleep_range(2000, 2500); - } else { - if (ath5k_get_bus_type(ah) == ATH_AHB) - ret = ath5k_hw_wisoc_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND); - else - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); - } - - if (ret) { - ATH5K_ERR(ah, "failed to reset the MAC Chip\n"); - return -EIO; - } - - /* ...wakeup again!...*/ - ret = ath5k_hw_set_power_mode(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah, "failed to resume the MAC Chip\n"); - return ret; - } - - /* ...reset configuration register on Wisoc ... - * ...clear reset control register and pull device out of - * warm reset on others */ - if (ath5k_get_bus_type(ah) == ATH_AHB) - ret = ath5k_hw_wisoc_reset(ah, 0); - else - ret = ath5k_hw_nic_reset(ah, 0); - - if (ret) { - ATH5K_ERR(ah, "failed to warm reset the MAC Chip\n"); - return -EIO; - } - - /* On initialization skip PLL programming since we don't have - * a channel / mode set yet */ - if (!channel) - return 0; - - if (ah->ah_version != AR5K_AR5210) { - /* - * Get channel mode flags - */ - - if (ah->ah_radio >= AR5K_RF5112) { - mode = AR5K_PHY_MODE_RAD_RF5112; - clock = AR5K_PHY_PLL_RF5112; - } else { - mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/ - clock = AR5K_PHY_PLL_RF5111; /*Zero*/ - } - - if (channel->band == IEEE80211_BAND_2GHZ) { - mode |= AR5K_PHY_MODE_FREQ_2GHZ; - clock |= AR5K_PHY_PLL_44MHZ; - - if (channel->hw_value == AR5K_MODE_11B) { - mode |= AR5K_PHY_MODE_MOD_CCK; - } else { - /* XXX Dynamic OFDM/CCK is not supported by the - * AR5211 so we set MOD_OFDM for plain g (no - * CCK headers) operation. We need to test - * this, 5211 might support ofdm-only g after - * all, there are also initial register values - * in the code for g mode (see initvals.c). - */ - if (ah->ah_version == AR5K_AR5211) - mode |= AR5K_PHY_MODE_MOD_OFDM; - else - mode |= AR5K_PHY_MODE_MOD_DYN; - } - } else if (channel->band == IEEE80211_BAND_5GHZ) { - mode |= (AR5K_PHY_MODE_FREQ_5GHZ | - AR5K_PHY_MODE_MOD_OFDM); - - /* Different PLL setting for 5413 */ - if (ah->ah_radio == AR5K_RF5413) - clock = AR5K_PHY_PLL_40MHZ_5413; - else - clock |= AR5K_PHY_PLL_40MHZ; - } else { - ATH5K_ERR(ah, "invalid radio frequency mode\n"); - return -EINVAL; - } - - /*XXX: Can bwmode be used with dynamic mode ? - * (I don't think it supports 44MHz) */ - /* On 2425 initvals TURBO_SHORT is not present */ - if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) { - turbo = AR5K_PHY_TURBO_MODE | - (ah->ah_radio == AR5K_RF2425) ? 0 : - AR5K_PHY_TURBO_SHORT; - } else if (ah->ah_bwmode != AR5K_BWMODE_DEFAULT) { - if (ah->ah_radio == AR5K_RF5413) { - mode |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ? - AR5K_PHY_MODE_HALF_RATE : - AR5K_PHY_MODE_QUARTER_RATE; - } else if (ah->ah_version == AR5K_AR5212) { - clock |= (ah->ah_bwmode == AR5K_BWMODE_10MHZ) ? - AR5K_PHY_PLL_HALF_RATE : - AR5K_PHY_PLL_QUARTER_RATE; - } - } - - } else { /* Reset the device */ - - /* ...enable Atheros turbo mode if requested */ - if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) - ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, - AR5K_PHY_TURBO); - } - - if (ah->ah_version != AR5K_AR5210) { - - /* ...update PLL if needed */ - if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) { - ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); - usleep_range(300, 350); - } - - /* ...set the PHY operating mode */ - ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); - ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); - } - - return 0; -} - - -/**************************************\ -* Post-initvals register modifications * -\**************************************/ - -/** - * ath5k_hw_tweak_initval_settings() - Tweak initial settings - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * Some settings are not handled on initvals, e.g. bwmode - * settings, some phy settings, workarounds etc that in general - * don't fit anywhere else or are too small to introduce a separate - * function for each one. So we have this function to handle - * them all during reset and complete card's initialization. - */ -static void -ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - if (ah->ah_version == AR5K_AR5212 && - ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - - /* Setup ADC control */ - ath5k_hw_reg_write(ah, - (AR5K_REG_SM(2, - AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) | - AR5K_REG_SM(2, - AR5K_PHY_ADC_CTL_INBUFGAIN_ON) | - AR5K_PHY_ADC_CTL_PWD_DAC_OFF | - AR5K_PHY_ADC_CTL_PWD_ADC_OFF), - AR5K_PHY_ADC_CTL); - - - - /* Disable barker RSSI threshold */ - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, - AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, - AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2); - - /* Set the mute mask */ - ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); - } - - /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B) - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH); - - /* Enable DCU double buffering */ - if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B) - AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_DCU_DBL_BUF_DIS); - - /* Set fast ADC */ - if ((ah->ah_radio == AR5K_RF5413) || - (ah->ah_radio == AR5K_RF2317) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { - u32 fast_adc = true; - - if (channel->center_freq == 2462 || - channel->center_freq == 2467) - fast_adc = 0; - - /* Only update if needed */ - if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc) - ath5k_hw_reg_write(ah, fast_adc, - AR5K_PHY_FAST_ADC); - } - - /* Fix for first revision of the RF5112 RF chipset */ - if (ah->ah_radio == AR5K_RF5112 && - ah->ah_radio_5ghz_revision < - AR5K_SREV_RAD_5112A) { - u32 data; - ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, - AR5K_PHY_CCKTXCTL); - if (channel->band == IEEE80211_BAND_5GHZ) - data = 0xffb81020; - else - data = 0xffb80d20; - ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); - } - - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - /* Clear QCU/DCU clock gating register */ - ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); - /* Set DAC/ADC delays */ - ath5k_hw_reg_write(ah, AR5K_PHY_SCAL_32MHZ_5311, - AR5K_PHY_SCAL); - /* Enable PCU FIFO corruption ECO */ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_ECO_ENABLE); - } - - if (ah->ah_bwmode) { - /* Increase PHY switch and AGC settling time - * on turbo mode (ath5k_hw_commit_eeprom_settings - * will override settling time if available) */ - if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) { - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, - AR5K_PHY_SETTLING_AGC, - AR5K_AGC_SETTLING_TURBO); - - /* XXX: Initvals indicate we only increase - * switch time on AR5212, 5211 and 5210 - * only change agc time (bug?) */ - if (ah->ah_version == AR5K_AR5212) - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, - AR5K_PHY_SETTLING_SWITCH, - AR5K_SWITCH_SETTLING_TURBO); - - if (ah->ah_version == AR5K_AR5210) { - /* Set Frame Control Register */ - ath5k_hw_reg_write(ah, - (AR5K_PHY_FRAME_CTL_INI | - AR5K_PHY_TURBO_MODE | - AR5K_PHY_TURBO_SHORT | 0x2020), - AR5K_PHY_FRAME_CTL_5210); - } - /* On 5413 PHY force window length for half/quarter rate*/ - } else if ((ah->ah_mac_srev >= AR5K_SREV_AR5424) && - (ah->ah_mac_srev <= AR5K_SREV_AR5414)) { - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL_5211, - AR5K_PHY_FRAME_CTL_WIN_LEN, - 3); - } - } else if (ah->ah_version == AR5K_AR5210) { - /* Set Frame Control Register for normal operation */ - ath5k_hw_reg_write(ah, (AR5K_PHY_FRAME_CTL_INI | 0x1020), - AR5K_PHY_FRAME_CTL_5210); - } -} - -/** - * ath5k_hw_commit_eeprom_settings() - Commit settings from EEPROM - * @ah: The &struct ath5k_hw - * @channel: The &struct ieee80211_channel - * - * Use settings stored on EEPROM to properly initialize the card - * based on various infos and per-mode calibration data. - */ -static void -ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - s16 cck_ofdm_pwr_delta; - u8 ee_mode; - - /* TODO: Add support for AR5210 EEPROM */ - if (ah->ah_version == AR5K_AR5210) - return; - - ee_mode = ath5k_eeprom_mode_from_channel(channel); - - /* Adjust power delta for channel 14 */ - if (channel->center_freq == 2484) - cck_ofdm_pwr_delta = - ((ee->ee_cck_ofdm_power_delta - - ee->ee_scaled_cck_delta) * 2) / 10; - else - cck_ofdm_pwr_delta = - (ee->ee_cck_ofdm_power_delta * 2) / 10; - - /* Set CCK to OFDM power delta on tx power - * adjustment register */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - if (channel->hw_value == AR5K_MODE_11G) - ath5k_hw_reg_write(ah, - AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1), - AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) | - AR5K_REG_SM((cck_ofdm_pwr_delta * -1), - AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX), - AR5K_PHY_TX_PWR_ADJ); - else - ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ); - } else { - /* For older revs we scale power on sw during tx power - * setup */ - ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta; - ah->ah_txpower.txp_cck_ofdm_gainf_delta = - ee->ee_cck_ofdm_gain_delta; - } - - /* XXX: necessary here? is called from ath5k_hw_set_antenna_mode() - * too */ - ath5k_hw_set_antenna_switch(ah, ee_mode); - - /* Noise floor threshold */ - ath5k_hw_reg_write(ah, - AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), - AR5K_PHY_NFTHRES); - - if ((ah->ah_bwmode == AR5K_BWMODE_40MHZ) && - (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { - /* Switch settling time (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, - AR5K_PHY_SETTLING_SWITCH, - ee->ee_switch_settling_turbo[ee_mode]); - - /* Tx/Rx attenuation (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, - AR5K_PHY_GAIN_TXRX_ATTEN, - ee->ee_atn_tx_rx_turbo[ee_mode]); - - /* ADC/PGA desired size (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_ADC, - ee->ee_adc_desired_size_turbo[ee_mode]); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_PGA, - ee->ee_pga_desired_size_turbo[ee_mode]); - - /* Tx/Rx margin (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, - AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, - ee->ee_margin_tx_rx_turbo[ee_mode]); - - } else { - /* Switch settling time */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, - AR5K_PHY_SETTLING_SWITCH, - ee->ee_switch_settling[ee_mode]); - - /* Tx/Rx attenuation */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, - AR5K_PHY_GAIN_TXRX_ATTEN, - ee->ee_atn_tx_rx[ee_mode]); - - /* ADC/PGA desired size */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_ADC, - ee->ee_adc_desired_size[ee_mode]); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_PGA, - ee->ee_pga_desired_size[ee_mode]); - - /* Tx/Rx margin */ - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, - AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, - ee->ee_margin_tx_rx[ee_mode]); - } - - /* XPA delays */ - ath5k_hw_reg_write(ah, - (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | - (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | - (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | - (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); - - /* XLNA delay */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3, - AR5K_PHY_RF_CTL3_TXE2XLNA_ON, - ee->ee_tx_end2xlna_enable[ee_mode]); - - /* Thresh64 (ANI) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF, - AR5K_PHY_NF_THRESH62, - ee->ee_thr_62[ee_mode]); - - /* False detect backoff for channels - * that have spur noise. Write the new - * cyclic power RSSI threshold. */ - if (ath5k_hw_chan_has_spur_noise(ah, channel)) - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, - AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, - AR5K_INIT_CYCRSSI_THR1 + - ee->ee_false_detect[ee_mode]); - else - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, - AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, - AR5K_INIT_CYCRSSI_THR1); - - /* I/Q correction (set enable bit last to match HAL sources) */ - /* TODO: Per channel i/q infos ? */ - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, - ee->ee_i_cal[ee_mode]); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, - ee->ee_q_cal[ee_mode]); - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); - } - - /* Heavy clipping -disable for now */ - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) - ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); -} - - -/*********************\ -* Main reset function * -\*********************/ - -/** - * ath5k_hw_reset() - The main reset function - * @ah: The &struct ath5k_hw - * @op_mode: One of enum nl80211_iftype - * @channel: The &struct ieee80211_channel - * @fast: Enable fast channel switching - * @skip_pcu: Skip pcu initialization - * - * This is the function we call each time we want to (re)initialize the - * card and pass new settings to hw. We also call it when hw runs into - * trouble to make it come back to a working state. - * - * Returns 0 on success, -EINVAL on false op_mode or channel infos, or -EIO - * on failure. - */ -int -ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool fast, bool skip_pcu) -{ - u32 s_seq[10], s_led[3], tsf_up, tsf_lo; - u8 mode; - int i, ret; - - tsf_up = 0; - tsf_lo = 0; - mode = 0; - - /* - * Sanity check for fast flag - * Fast channel change only available - * on AR2413/AR5413. - */ - if (fast && (ah->ah_radio != AR5K_RF2413) && - (ah->ah_radio != AR5K_RF5413)) - fast = false; - - /* Disable sleep clock operation - * to avoid register access delay on certain - * PHY registers */ - if (ah->ah_version == AR5K_AR5212) - ath5k_hw_set_sleep_clock(ah, false); - - /* - * Stop PCU - */ - ath5k_hw_stop_rx_pcu(ah); - - /* - * Stop DMA - * - * Note: If DMA didn't stop continue - * since only a reset will fix it. - */ - ret = ath5k_hw_dma_stop(ah); - - /* RF Bus grant won't work if we have pending - * frames */ - if (ret && fast) { - ATH5K_DBG(ah, ATH5K_DEBUG_RESET, - "DMA didn't stop, falling back to normal reset\n"); - fast = false; - /* Non fatal, just continue with - * normal reset */ - ret = 0; - } - - mode = channel->hw_value; - switch (mode) { - case AR5K_MODE_11A: - break; - case AR5K_MODE_11G: - if (ah->ah_version <= AR5K_AR5211) { - ATH5K_ERR(ah, - "G mode not available on 5210/5211"); - return -EINVAL; - } - break; - case AR5K_MODE_11B: - if (ah->ah_version < AR5K_AR5211) { - ATH5K_ERR(ah, - "B mode not available on 5210"); - return -EINVAL; - } - break; - default: - ATH5K_ERR(ah, - "invalid channel: %d\n", channel->center_freq); - return -EINVAL; - } - - /* - * If driver requested fast channel change and DMA has stopped - * go on. If it fails continue with a normal reset. - */ - if (fast) { - ret = ath5k_hw_phy_init(ah, channel, mode, true); - if (ret) { - ATH5K_DBG(ah, ATH5K_DEBUG_RESET, - "fast chan change failed, falling back to normal reset\n"); - /* Non fatal, can happen eg. - * on mode change */ - ret = 0; - } else { - ATH5K_DBG(ah, ATH5K_DEBUG_RESET, - "fast chan change successful\n"); - return 0; - } - } - - /* - * Save some registers before a reset - */ - if (ah->ah_version != AR5K_AR5210) { - /* - * Save frame sequence count - * For revs. after Oahu, only save - * seq num for DCU 0 (Global seq num) - */ - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - - for (i = 0; i < 10; i++) - s_seq[i] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(i)); - - } else { - s_seq[0] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(0)); - } - - /* TSF accelerates on AR5211 during reset - * As a workaround save it here and restore - * it later so that it's back in time after - * reset. This way it'll get re-synced on the - * next beacon without breaking ad-hoc. - * - * On AR5212 TSF is almost preserved across a - * reset so it stays back in time anyway and - * we don't have to save/restore it. - * - * XXX: Since this breaks power saving we have - * to disable power saving until we receive the - * next beacon, so we can resync beacon timers */ - if (ah->ah_version == AR5K_AR5211) { - tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); - tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); - } - } - - - /*GPIOs*/ - s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & - AR5K_PCICFG_LEDSTATE; - s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); - s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); - - - /* - * Since we are going to write rf buffer - * check if we have any pending gain_F - * optimization settings - */ - if (ah->ah_version == AR5K_AR5212 && - (ah->ah_radio <= AR5K_RF5112)) { - if (!fast && ah->ah_rf_banks != NULL) - ath5k_hw_gainf_calibrate(ah); - } - - /* Wakeup the device */ - ret = ath5k_hw_nic_wakeup(ah, channel); - if (ret) - return ret; - - /* PHY access enable */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5211) - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - else - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40, - AR5K_PHY(0)); - - /* Write initial settings */ - ret = ath5k_hw_write_initvals(ah, mode, skip_pcu); - if (ret) - return ret; - - /* Initialize core clock settings */ - ath5k_hw_init_core_clock(ah); - - /* - * Tweak initval settings for revised - * chipsets and add some more config - * bits - */ - ath5k_hw_tweak_initval_settings(ah, channel); - - /* Commit values from EEPROM */ - ath5k_hw_commit_eeprom_settings(ah, channel); - - - /* - * Restore saved values - */ - - /* Seqnum, TSF */ - if (ah->ah_version != AR5K_AR5210) { - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - for (i = 0; i < 10; i++) - ath5k_hw_reg_write(ah, s_seq[i], - AR5K_QUEUE_DCU_SEQNUM(i)); - } else { - ath5k_hw_reg_write(ah, s_seq[0], - AR5K_QUEUE_DCU_SEQNUM(0)); - } - - if (ah->ah_version == AR5K_AR5211) { - ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); - ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); - } - } - - /* Ledstate */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); - - /* Gpio settings */ - ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); - ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); - - /* - * Initialize PCU - */ - ath5k_hw_pcu_init(ah, op_mode); - - /* - * Initialize PHY - */ - ret = ath5k_hw_phy_init(ah, channel, mode, false); - if (ret) { - ATH5K_ERR(ah, - "failed to initialize PHY (%i) !\n", ret); - return ret; - } - - /* - * Configure QCUs/DCUs - */ - ret = ath5k_hw_init_queues(ah); - if (ret) - return ret; - - - /* - * Initialize DMA/Interrupts - */ - ath5k_hw_dma_init(ah); - - - /* - * Enable 32KHz clock function for AR5212+ chips - * Set clocks to 32KHz operation and use an - * external 32KHz crystal when sleeping if one - * exists. - * Disabled by default because it is also disabled in - * other drivers and it is known to cause stability - * issues on some devices - */ - if (ah->ah_use_32khz_clock && ah->ah_version == AR5K_AR5212 && - op_mode != NL80211_IFTYPE_AP) - ath5k_hw_set_sleep_clock(ah, true); - - /* - * Disable beacons and reset the TSF - */ - AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); - ath5k_hw_reset_tsf(ah); - return 0; -} diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 10dea37431b..bd4ecf34eca 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c @@ -520,6 +520,7 @@ ath_regd_init_wiphy(struct ath_regulatory *reg, */ regd = ath_world_regdomain(reg); wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; + wiphy->country_ie_pref = NL80211_COUNTRY_IE_FOLLOW_POWER; } else { /* * This gets applied in the case of the absence of CRDA, diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c index 65984011ab9..e5d5b4b282f 100644 --- a/drivers/net/wireless/wcnss/wcnss_wlan.c +++ b/drivers/net/wireless/wcnss/wcnss_wlan.c @@ -548,6 +548,19 @@ static int enable_wcnss_suspend_notify_set(const char *val, module_param_call(enable_wcnss_suspend_notify, enable_wcnss_suspend_notify_set, param_get_int, &enable_wcnss_suspend_notify, S_IRUGO | S_IWUSR); +int wcnss_wlan_iris_xo_mode(void) +{ + if (!penv || !penv->pdev || !penv->smd_channel_ready) + return -ENODEV; + + if (penv->wlan_config.use_48mhz_xo) + return WCNSS_XO_48MHZ; + else + return WCNSS_XO_19MHZ; +} +EXPORT_SYMBOL(wcnss_wlan_iris_xo_mode); + + static void wcnss_suspend_notify(void) { void __iomem *pmu_spare_reg; diff --git a/drivers/power/bq27541_battery.c b/drivers/power/bq27541_battery.c index c3e63910bd8..7e81921963c 100644 --- a/drivers/power/bq27541_battery.c +++ b/drivers/power/bq27541_battery.c @@ -16,6 +16,7 @@ * more details. */ + #include #include #include @@ -28,10 +29,13 @@ #include #include #include +#include #include #include #include +#include + #define SMBUS_RETRY (0) #define GPIOPIN_LOW_BATTERY_DETECT 29 #define BATTERY_POLLING_RATE (60) @@ -57,7 +61,6 @@ #define THERMAL_RULE1 1 #define THERMAL_RULE2 2 - /* Debug Message */ #define BAT_NOTICE(format, arg...) \ printk(KERN_NOTICE "%s " format , __FUNCTION__ , ## arg) @@ -84,6 +87,7 @@ static int bq27541_get_property(struct power_supply *psy, enum power_supply_property psp, union power_supply_propval *val); extern unsigned get_usb_cable_status(void); extern int smb345_config_thermal_charging(int temp, int volt, int rule); +extern void reconfig_AICL(void); module_param(battery_current, uint, 0644); module_param(battery_remaining_capacity, uint, 0644); @@ -106,7 +110,16 @@ enum { REG_TIME_TO_FULL, REG_STATUS, REG_CAPACITY, - REG_SERIAL_NUMBER, + //REG_SERIAL_NUMBER, + REG_CHARGE_NOW, + REG_CHARGE_UCOMP, + REG_CHARGE_FULL, + REG_CHARGE_DESIGN, + REG_ENERGY, + REG_CHARGE_COUNTER, + REG_POWER, + REG_CYCLE, + REG_MAX }; @@ -134,6 +147,14 @@ static struct bq27541_device_data { [REG_TIME_TO_FULL] = BQ27541_DATA(TIME_TO_FULL_AVG, 0x18, 0, 65535), [REG_STATUS] = BQ27541_DATA(STATUS, 0x0a, 0, 65535), [REG_CAPACITY] = BQ27541_DATA(CAPACITY, 0x2c, 0, 100), + [REG_CHARGE_NOW] = BQ27541_DATA(CHARGE_NOW, 0x10, 0, 65535), + [REG_CHARGE_UCOMP] = BQ27541_DATA(CHARGE_AVG, 0x0c, 0, 65535), + [REG_CHARGE_FULL] = BQ27541_DATA(CHARGE_FULL, 0x12, 0, 65535), + [REG_CHARGE_DESIGN] = BQ27541_DATA(CHARGE_FULL_DESIGN, 0x3c, 0, 65535), + [REG_ENERGY] = BQ27541_DATA(ENERGY_NOW, 0x22, 0, 65535), + [REG_CHARGE_COUNTER] = BQ27541_DATA(CHARGE_COUNTER, 0x34, -32768, 32767), + [REG_POWER] = BQ27541_DATA(POWER_NOW, 0x24, -32768, 32767), + [REG_CYCLE] = BQ27541_DATA(CYCLE_COUNT, 0x2a, 0, 65535), }; static enum power_supply_property bq27541_properties[] = { @@ -145,6 +166,14 @@ static enum power_supply_property bq27541_properties[] = { POWER_SUPPLY_PROP_CAPACITY, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_CURRENT_NOW, + POWER_SUPPLY_PROP_CHARGE_NOW, + POWER_SUPPLY_PROP_CHARGE_AVG, + POWER_SUPPLY_PROP_CHARGE_FULL, + POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, + POWER_SUPPLY_PROP_ENERGY_NOW, + POWER_SUPPLY_PROP_CHARGE_COUNTER, + POWER_SUPPLY_PROP_POWER_NOW, + POWER_SUPPLY_PROP_CYCLE_COUNT }; unsigned get_cable_status(void) @@ -159,8 +188,13 @@ void bq27541_check_cabe_type(void) usb_on = 0; } else if(bq27541_battery_cable_status == USB_Cable) { - usb_on = 1; - ac_on = 0; + if (force_fast_charge == 1) { + ac_on = 1; + usb_on = 0; + } else { + usb_on = 1; + ac_on = 0; + } } else { ac_on = 0; @@ -268,7 +302,7 @@ static struct bq27541_device_info { int old_temperature; bool temp_err; unsigned int prj_id; - spinlock_t lock; + struct mutex lock; } *bq27541_device; static int bq27541_read_i2c(u8 reg, int *rt_value, int b_single) @@ -353,26 +387,6 @@ static const struct attribute_group battery_smbus_group = { .attrs = battery_smbus_attributes, }; -static int bq27541_battery_current(void) -{ - int ret; - int curr = 0; - - ret = bq27541_read_i2c(bq27541_data[REG_CURRENT].addr, &curr, 0); - if (ret) { - BAT_ERR("error reading current ret = %x\n", ret); - return 0; - } - - curr = (s16)curr; - - if (curr >= bq27541_data[REG_CURRENT].min_value && - curr <= bq27541_data[REG_CURRENT].max_value) { - return curr; - } else - return 0; -} - static void battery_status_poll(struct work_struct *work) { struct bq27541_device_info *batt_dev = container_of(work, struct bq27541_device_info, status_poll_work.work); @@ -380,6 +394,7 @@ static void battery_status_poll(struct work_struct *work) if(!bq27541_battery_driver_ready) BAT_NOTICE("battery driver not ready\n"); + reconfig_AICL(); power_supply_changed(&bq27541_supply[Charger_Type_Battery]); if (!bq27541_device->temp_err) { @@ -474,6 +489,9 @@ int bq27541_battery_callback(unsigned usb_cable_state) bq27541_check_cabe_type(); + if(!cancel_delayed_work(&bq27541_device->status_poll_work)) + flush_workqueue(bq27541_battery_work_queue); + if(!bq27541_battery_cable_status) { if (old_cable_status == USB_AC_Adapter) { power_supply_changed(&bq27541_supply[Charger_Type_AC]); @@ -505,6 +523,9 @@ int bq27541_wireless_callback(unsigned wireless_state) printk(KERN_NOTICE "bq27541_wireless_callback wireless_state = %x\n", wireless_state) ; printk(KERN_NOTICE "========================================================\n"); + if(!cancel_delayed_work(&bq27541_device->status_poll_work)) + flush_workqueue(bq27541_battery_work_queue); + power_supply_changed(&bq27541_supply[Charger_Type_WIRELESS]); cancel_delayed_work(&bq27541_device->status_poll_work); @@ -540,6 +561,42 @@ static int bq27541_get_psp(int reg_offset, enum power_supply_property psp, return -EINVAL; } + if (psp == POWER_SUPPLY_PROP_CHARGE_NOW) { + val->intval = rt_value * 1000; + BAT_NOTICE("charge_now (compensated) = %u uAh\n", val->intval); + } + if (psp == POWER_SUPPLY_PROP_CHARGE_AVG) { + val->intval = rt_value * 1000; + BAT_NOTICE("charge_avg (uncompensated) = %u uAh\n", val->intval); + } + if (psp == POWER_SUPPLY_PROP_CHARGE_FULL) { + val->intval = rt_value * 1000; + BAT_NOTICE("charge_full = %u uAh\n", val->intval); + } + if (psp == POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN) { + val->intval = rt_value * 1000; + BAT_NOTICE("charge_design = %u uAh\n", val->intval); + } + if (psp == POWER_SUPPLY_PROP_ENERGY_NOW) { + val->intval = rt_value * 1000; + BAT_NOTICE("energy_now = %u uWh\n", val->intval); + } + if (psp == POWER_SUPPLY_PROP_CHARGE_COUNTER) { + val->intval = ((s16) rt_value) * 1000; + BAT_NOTICE("charge_counter = %d uWh\n", val->intval); + } + if (psp == POWER_SUPPLY_PROP_POWER_NOW) { + val->intval = ((s16) rt_value) * 1000; + BAT_NOTICE("power_now = %d uW\n", val->intval); + } + if (psp == POWER_SUPPLY_PROP_CYCLE_COUNT) { + val->intval = rt_value; + BAT_NOTICE("cycle count = %u\n", val->intval); + } + if (psp == POWER_SUPPLY_PROP_CURRENT_NOW) { + val->intval = (s16)rt_value; + BAT_NOTICE("current_now = %d mA\n", val->intval); + } if (psp == POWER_SUPPLY_PROP_VOLTAGE_NOW) { if (rt_value >= bq27541_data[REG_VOLTAGE].min_value && rt_value <= bq27541_data[REG_VOLTAGE].max_value) { @@ -598,11 +655,6 @@ static int bq27541_get_psp(int reg_offset, enum power_supply_property psp, bq27541_device->old_temperature = val->intval = ret; BAT_NOTICE("temperature= %d (0.1¢XC)\n", val->intval); } - if (psp == POWER_SUPPLY_PROP_CURRENT_NOW) { - val->intval = bq27541_device->bat_current - = bq27541_battery_current(); - BAT_NOTICE("current = %d mA\n", val->intval); - } return 0; } @@ -614,10 +666,14 @@ static int bq27541_get_capacity(union power_supply_propval *val) bool check_cap = false; int smb_retry_max = (SMBUS_RETRY + 2); + bq27541_device->bat_capacity = 0; do { bq27541_device->smbus_status = bq27541_smbus_read_data(REG_CAPACITY, 0 ,&bq27541_device->bat_capacity); - if ((bq27541_device->bat_capacity <= 0) || (bq27541_device->bat_capacity > 100)) + if ((bq27541_device->bat_capacity <= 0) || (bq27541_device->bat_capacity > 100)) { check_cap = true; + BAT_NOTICE("check capacity, cap = %d, smb_retry = %d\n", bq27541_device->bat_capacity, smb_retry); + } else + check_cap = false; } while(((bq27541_device->smbus_status < 0) || check_cap) && ( ++smb_retry <= smb_retry_max)); if (bq27541_device->smbus_status < 0) { @@ -634,9 +690,14 @@ static int bq27541_get_capacity(union power_supply_propval *val) } } - ret = bq27541_device->bat_capacity; + temp_capacity = ret = bq27541_device->bat_capacity; - temp_capacity = ((ret >= 100) ? 100 : ret); + if (!(bq27541_device->bat_capacity >= bq27541_data[REG_CAPACITY].min_value && + bq27541_device->bat_capacity <= bq27541_data[REG_CAPACITY].max_value)) { + val->intval = bq27541_device->old_capacity; + BAT_NOTICE("use old capacity=%u\n", bq27541_device->old_capacity); + return 0; + } /* start: for mapping %99 to 100%. Lose 84%*/ if(temp_capacity==99) @@ -699,6 +760,9 @@ static int bq27541_get_property(struct power_supply *psy, union power_supply_propval *val) { u8 count; + + mutex_lock(&bq27541_device->lock); + switch (psp) { case POWER_SUPPLY_PROP_PRESENT: case POWER_SUPPLY_PROP_HEALTH: @@ -719,28 +783,36 @@ static int bq27541_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_VOLTAGE_NOW: case POWER_SUPPLY_PROP_CURRENT_NOW: case POWER_SUPPLY_PROP_TEMP: - case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG: - case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG: case POWER_SUPPLY_PROP_SERIAL_NUMBER: + case POWER_SUPPLY_PROP_CHARGE_NOW: + case POWER_SUPPLY_PROP_CHARGE_AVG: + case POWER_SUPPLY_PROP_CHARGE_FULL: + case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: + case POWER_SUPPLY_PROP_ENERGY_NOW: + case POWER_SUPPLY_PROP_CHARGE_COUNTER: + case POWER_SUPPLY_PROP_POWER_NOW: + case POWER_SUPPLY_PROP_CYCLE_COUNT: for (count = 0; count < REG_MAX; count++) { if (psp == bq27541_data[count].psp) break; } if (bq27541_get_psp(count, psp, val)) - return -EINVAL; + goto error; break; default: dev_err(&bq27541_device->client->dev, "%s: INVALID property psp=%u\n", __func__,psp); - return -EINVAL; + goto error; } + mutex_unlock(&bq27541_device->lock); return 0; error: + mutex_unlock(&bq27541_device->lock); return -EINVAL; } @@ -764,6 +836,7 @@ static int bq27541_probe(struct i2c_client *client, bq27541_device->old_temperature = 0xFF; bq27541_device->gpio_low_battery_detect = GPIOPIN_LOW_BATTERY_DETECT; bq27541_device->bat_capacity_zero_count = 0; + mutex_init(&bq27541_device->lock); for (i = 0; i < ARRAY_SIZE(bq27541_supply); i++) { ret = power_supply_register(&client->dev, &bq27541_supply[i]); @@ -781,7 +854,6 @@ static int bq27541_probe(struct i2c_client *client, INIT_DELAYED_WORK(&bq27541_device->low_low_bat_work, low_low_battery_check); cancel_delayed_work(&bq27541_device->status_poll_work); - spin_lock_init(&bq27541_device->lock); wake_lock_init(&bq27541_device->low_battery_wake_lock, WAKE_LOCK_SUSPEND, "low_battery_detection"); wake_lock_init(&bq27541_device->cable_wake_lock, WAKE_LOCK_SUSPEND, "cable_state_changed"); diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c index d1b0ba0fee8..d25306edf0f 100644 --- a/drivers/power/pm8921-bms.c +++ b/drivers/power/pm8921-bms.c @@ -1223,6 +1223,22 @@ static void calculate_cc_uah(struct pm8921_bms_chip *chip, int cc, int *val) *val = cc_uah; } +int pm8921_bms_cc_uah(int *cc_uah) +{ + int cc; + + *cc_uah = 0; + + if (!the_chip) + return -EINVAL; + + read_cc(the_chip, &cc); + calculate_cc_uah(the_chip, cc, cc_uah); + + return 0; +} +EXPORT_SYMBOL(pm8921_bms_cc_uah); + static int calculate_termination_uuc(struct pm8921_bms_chip *chip, int batt_temp, int chargecycles, int fcc_uah, int i_ma, diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c index 16142861142..d550bacafff 100644 --- a/drivers/power/pm8921-charger.c +++ b/drivers/power/pm8921-charger.c @@ -1401,6 +1401,7 @@ static enum power_supply_property msm_batt_power_props[] = { POWER_SUPPLY_PROP_CURRENT_NOW, POWER_SUPPLY_PROP_TEMP, POWER_SUPPLY_PROP_ENERGY_FULL, + POWER_SUPPLY_PROP_CHARGE_NOW, }; static int get_prop_battery_uvolts(struct pm8921_chg_chip *chip) @@ -1486,6 +1487,20 @@ static int get_prop_batt_fcc(struct pm8921_chg_chip *chip) return rc; } +static int get_prop_batt_charge_now(struct pm8921_chg_chip *chip) +{ + int rc; + int cc_uah; + + rc = pm8921_bms_cc_uah(&cc_uah); + + if (rc == 0) + return cc_uah; + + pr_err("unable to get batt fcc rc = %d\n", rc); + return rc; +} + static int get_prop_batt_health(struct pm8921_chg_chip *chip) { int temp; @@ -1643,6 +1658,9 @@ static int pm_batt_power_get_property(struct power_supply *psy, case POWER_SUPPLY_PROP_ENERGY_FULL: val->intval = get_prop_batt_fcc(chip) * 1000; break; + case POWER_SUPPLY_PROP_CHARGE_NOW: + val->intval = get_prop_batt_charge_now(chip); + break; default: return -EINVAL; } diff --git a/drivers/power/smb345-charger.c b/drivers/power/smb345-charger.c index 60f330a7b88..8c3f9405f74 100644 --- a/drivers/power/smb345-charger.c +++ b/drivers/power/smb345-charger.c @@ -104,8 +104,8 @@ #define WPC_INIT_DET_INTERVAL (22 * HZ) #define WPC_SET_CURT_LIMIT_CNT 6 #define BAT_Cold_Limit 0 -#define BAT_Hot_Limit 55 -#define BAT_Mid_Temp_Wired 50 +#define BAT_Hot_Limit 45 +#define BAT_Mid_Temp_Wired 45 #define BAT_Mid_Temp_Wireless 40 #define FLOAT_VOLT 0x2A #define FLOAT_VOLT_LOW 0x1E @@ -119,6 +119,9 @@ extern int bq27541_battery_callback(unsigned usb_cable_state); extern int bq27541_wireless_callback(unsigned wireless_state); extern void touch_callback(unsigned cable_status); static ssize_t smb345_reg_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t smb345_float_voltage_show(struct device *dev, struct device_attribute *attr, char *buf); +static ssize_t smb345_float_voltage_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count); /* Global variables */ static struct smb345_charger *charger; @@ -132,12 +135,16 @@ extern int ac_on; extern int usb_on; static bool wpc_en; static bool disable_DCIN; +static int float_volt_setting = 4300; /* Sysfs interface */ static DEVICE_ATTR(reg_status, S_IWUSR | S_IRUGO, smb345_reg_show, NULL); +static DEVICE_ATTR(float_voltage, 0644, smb345_float_voltage_show, + smb345_float_voltage_store); static struct attribute *smb345_attributes[] = { &dev_attr_reg_status.attr, + &dev_attr_float_voltage.attr, NULL }; @@ -453,17 +460,7 @@ smb345_set_InputCurrentlimit(struct i2c_client *client, u32 current_setting) static irqreturn_t smb345_inok_isr(int irq, void *dev_id) { - struct smb345_charger *smb = dev_id; - int status = gpio_get_value(GPIO_AC_OK); - - SMB_NOTICE("VBUS_DET = %s\n", status ? "H" : "L"); - - if (ac_on && !status) - queue_delayed_work(smb345_wq, &smb->cable_det_work, 0); - else { - if (delayed_work_pending(&charger->cable_det_work)) - cancel_delayed_work(&charger->cable_det_work); - } + SMB_NOTICE("VBUS_DET = %s\n", gpio_get_value(GPIO_AC_OK) ? "H" : "L"); return IRQ_HANDLED; } @@ -627,6 +624,11 @@ static void wireless_isr_work_function(struct work_struct *dat) SMB_NOTICE("wireless state = %d\n", wireless_is_plugged()); + if (otg_on) { + SMB_NOTICE("bypass wireless isr due to otg_on\n"); + return; + } + if (wireless_is_plugged()) wireless_set(); else @@ -635,6 +637,10 @@ static void wireless_isr_work_function(struct work_struct *dat) static void wireless_det_work_function(struct work_struct *dat) { + if (otg_on) { + SMB_NOTICE("bypass wireless isr due to otg_on\n"); + return; + } if (wireless_is_plugged()) wireless_set(); } @@ -654,13 +660,10 @@ static void wireless_set_current_function(struct work_struct *dat) queue_delayed_work(smb345_wq, &charger->wireless_set_current_work, WPC_SET_CURT_INTERVAL); } -static void cable_det_work_function(struct work_struct *dat) +void reconfig_AICL(void) { struct i2c_client *client = charger->client; - if (delayed_work_pending(&charger->cable_det_work)) - cancel_delayed_work(&charger->cable_det_work); - if (ac_on && !gpio_get_value(GPIO_AC_OK)) { int retval; retval = smb345_read(client, smb345_STS_REG_E); @@ -668,7 +671,7 @@ static void cable_det_work_function(struct work_struct *dat) dev_err(&client->dev, "%s(): Failed in reading 0x%02x", __func__, smb345_STS_REG_E); else { - SMB_NOTICE("Status Reg E=0x02%x\n", retval); + SMB_NOTICE("Status Reg E=0x%02x\n", retval); if ((retval & 0xF) <= 0x1) { SMB_NOTICE("reconfig input current limit\n"); @@ -677,6 +680,7 @@ static void cable_det_work_function(struct work_struct *dat) } } } +EXPORT_SYMBOL(reconfig_AICL); static int smb345_inok_irq(struct smb345_charger *smb) { @@ -781,6 +785,9 @@ void smb345_otg_status(bool on) "otg..\n", __func__); return; } + if (wireless_is_plugged()) + wireless_reset(); + return; } else otg_on = false; @@ -942,6 +949,30 @@ static ssize_t smb345_reg_show(struct device *dev, struct device_attribute *attr return strlen(buf); } +static ssize_t smb345_float_voltage_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", float_volt_setting); +} + +/* Set charger float voltage; desired value in mV. */ +static ssize_t smb345_float_voltage_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + int val = 0; + + if(kstrtoint(buf, 0, &val) != 0) + goto error; + val = (val / 20) * 20; /* the charger can only do 20mV increments */ + if(val < 3800 || val > 4300) + goto error; + + float_volt_setting = val; + + return count; +error: + return -EINVAL; +} + static int smb345_otg_setting(struct i2c_client *client) { int ret; @@ -1101,12 +1132,25 @@ int smb345_config_thermal_charging(int temp, int volt, int rule) struct i2c_client *client = charger->client; int ret = 0, retval, setting = 0; int BAT_Mid_Temp = BAT_Mid_Temp_Wired; + /*Charger float voltage for normal temperature conditions. Default 4.3V.*/ + int flt_volt_43 = FLOAT_VOLT_43V; + /*Charger float voltage for high temperature conditions. Default 4.1V.*/ + int flt_volt_low = FLOAT_VOLT_LOW; + + flt_volt_43 = (float_volt_setting - 3500) / 20; + + if(flt_volt_43 < 0 || flt_volt_43 > FLOAT_VOLT_43V) { + SMB_NOTICE("BUG: Invalid float voltage setting calculated: %d\n", flt_volt_43); + flt_volt_43 = FLOAT_VOLT_43V; + } + if(flt_volt_low > flt_volt_43) flt_volt_low = flt_volt_43; if (rule == THERMAL_RULE1) BAT_Mid_Temp = BAT_Mid_Temp_Wired; else if (rule == THERMAL_RULE2) BAT_Mid_Temp = BAT_Mid_Temp_Wireless; + mdelay(100); smb345_config_thermal_limit(); SMB_NOTICE("temp=%d, volt=%d\n", temp, volt); @@ -1129,10 +1173,10 @@ int smb345_config_thermal_charging(int temp, int volt, int rule) if (temp <= BAT_Mid_Temp || (temp > BAT_Mid_Temp && volt > FLOAT_VOLT_LOW_DECIMAL) || temp > BAT_Hot_Limit) { - if (setting != FLOAT_VOLT_43V) { + if (setting != flt_volt_43) { setting = retval & (~FLOAT_VOLT_MASK); - setting |= FLOAT_VOLT_43V; - SMB_NOTICE("Set Float Volt, retval=%x setting=%x\n", retval, setting); + setting |= flt_volt_43; + SMB_NOTICE("Set Float Volt, retval=%x setting=%x V=%dmV\n", retval, setting, float_volt_setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { dev_err(&client->dev, "%s(): Failed in writing 0x%02x to register" @@ -1140,11 +1184,11 @@ int smb345_config_thermal_charging(int temp, int volt, int rule) goto error; } } else - SMB_NOTICE("Bypass set Float Volt=%x\n", retval); + SMB_NOTICE("Bypass set Float Volt setting=%x V=%dmV\n", retval, float_volt_setting); } else { - if (setting != FLOAT_VOLT_LOW) { + if (setting != flt_volt_low) { setting = retval & (~FLOAT_VOLT_MASK); - setting |= FLOAT_VOLT_LOW; + setting |= flt_volt_low; SMB_NOTICE("Set Float Volt, retval=%x setting=%x\n", retval, setting); ret = smb345_write(client, smb345_FLOAT_VLTG, setting); if (ret < 0) { @@ -1242,8 +1286,6 @@ static int __devinit smb345_probe(struct i2c_client *client, wireless_det_work_function); INIT_DELAYED_WORK_DEFERRABLE(&charger->wireless_set_current_work, wireless_set_current_function); - INIT_DELAYED_WORK_DEFERRABLE(&charger->cable_det_work, - cable_det_work_function); wake_lock_init(&charger_wakelock, WAKE_LOCK_SUSPEND, "charger_configuration"); diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index e756a0df366..289293a5cbb 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -78,7 +78,7 @@ typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); * the recovery of the remote processor. */ static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev, - unsigned long iova, int flags) + unsigned long iova, int flags, void *token) { dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags); @@ -117,7 +117,7 @@ static int rproc_enable_iommu(struct rproc *rproc) return -ENOMEM; } - iommu_set_fault_handler(domain, rproc_iommu_fault); + iommu_set_fault_handler(domain, rproc_iommu_fault, rproc); ret = iommu_attach_device(domain, dev); if (ret) { diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 29684c8142b..362baecfcd4 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -265,7 +265,7 @@ config SCSI_SCAN_ASYNC config SCSI_WAIT_SCAN tristate # No prompt here, this is an invisible symbol. - default m + default n depends on SCSI depends on MODULES # scsi_wait_scan is a loadable module which waits until all the async scans are diff --git a/drivers/slimbus/slim-msm-ctrl.c b/drivers/slimbus/slim-msm-ctrl.c index b7081333e07..b2b3ddc7fb0 100644 --- a/drivers/slimbus/slim-msm-ctrl.c +++ b/drivers/slimbus/slim-msm-ctrl.c @@ -232,8 +232,8 @@ enum mgr_intr { enum frm_cfg { FRM_ACTIVE = 1, - CLK_GEAR = 7, - ROOT_FREQ = 11, + CLK_GEAR = 10, + ROOT_FREQ = 22, REF_CLK_GEAR = 15, INTR_WAKE = 19, }; diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c index 4ab803b67f6..28a1cf2537a 100644 --- a/drivers/slimbus/slimbus.c +++ b/drivers/slimbus/slimbus.c @@ -878,7 +878,7 @@ int slim_xfer_msg(struct slim_controller *ctrl, struct slim_device *sbdev, int ret; u16 sl, cur; u16 ec; - u8 tid, mlen = 6; + u8 tid = 0, mlen = 6; if (sbdev->laddr != SLIM_LA_MANAGER && sbdev->laddr >= ctrl->num_dev) return -ENXIO; diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ce8276f5df2..9e7605bdb76 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -136,4 +136,8 @@ source "drivers/staging/ozwpan/Kconfig" source "drivers/staging/prima/Kconfig" +source "drivers/staging/media/Kconfig" + +source "drivers/staging/cpupower/Kconfig" + endif # STAGING diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 993786ccb63..266da6b3d53 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ obj-$(CONFIG_INTEL_MEI) += mei/ obj-$(CONFIG_MFD_NVEC) += nvec/ +obj-$(CONFIG_CPUPOWER) +=cpupower/ obj-$(CONFIG_DRM_OMAP) += omapdrm/ obj-$(CONFIG_ANDROID) += android/ obj-$(CONFIG_PHONE) += telephony/ diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig index 43d17c27695..815cd7ab2e0 100644 --- a/drivers/staging/android/Kconfig +++ b/drivers/staging/android/Kconfig @@ -43,6 +43,7 @@ config PERSISTENT_TRACER depends on HAVE_FUNCTION_TRACER select FUNCTION_TRACER select ANDROID_PERSISTENT_RAM + default n help persistent_trace traces function calls into a persistent ram buffer that can be decoded and dumped after reboot through diff --git a/drivers/staging/android/ashmem.c b/drivers/staging/android/ashmem.c index 16c411cbe5b..4f13907543e 100644 --- a/drivers/staging/android/ashmem.c +++ b/drivers/staging/android/ashmem.c @@ -365,7 +365,9 @@ static int ashmem_shrink(struct shrinker *s, struct shrink_control *sc) if (!sc->nr_to_scan) return lru_count; - mutex_lock(&ashmem_mutex); + if (!mutex_trylock(&ashmem_mutex)) + return -1; + list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) { struct inode *inode = range->asma->file->f_dentry->d_inode; loff_t start = range->pgstart * PAGE_SIZE; diff --git a/drivers/staging/android/binder.c b/drivers/staging/android/binder.c index f1364a860ac..80793e84ae0 100644 --- a/drivers/staging/android/binder.c +++ b/drivers/staging/android/binder.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -2308,13 +2309,13 @@ static int binder_thread_read(struct binder_proc *proc, if (!binder_has_proc_work(proc, thread)) ret = -EAGAIN; } else - ret = wait_event_interruptible_exclusive(proc->wait, binder_has_proc_work(proc, thread)); + ret = wait_event_freezable_exclusive(proc->wait, binder_has_proc_work(proc, thread)); } else { if (non_block) { if (!binder_has_thread_work(thread)) ret = -EAGAIN; } else - ret = wait_event_interruptible(thread->wait, binder_has_thread_work(thread)); + ret = wait_event_freezable(thread->wait, binder_has_thread_work(thread)); } binder_lock(__func__); diff --git a/drivers/staging/cpupower/Kconfig b/drivers/staging/cpupower/Kconfig new file mode 100644 index 00000000000..e07dd983fda --- /dev/null +++ b/drivers/staging/cpupower/Kconfig @@ -0,0 +1,5 @@ +config CPUPOWER + tristate "cpupower driver" + depends on SCHED_MC && ARM_CPU_TOPOLOGY + help + Say Y here if you have dual cortex-A9 diff --git a/drivers/staging/cpupower/Makefile b/drivers/staging/cpupower/Makefile new file mode 100644 index 00000000000..b16bad10226 --- /dev/null +++ b/drivers/staging/cpupower/Makefile @@ -0,0 +1,4 @@ +# +# Makefile for ARM cpupower driver +# +obj-y += cpu_power.o diff --git a/drivers/staging/cpupower/cpu_power.c b/drivers/staging/cpupower/cpu_power.c new file mode 100644 index 00000000000..9f971a7a508 --- /dev/null +++ b/drivers/staging/cpupower/cpu_power.c @@ -0,0 +1,179 @@ +/* + * arch/arm/kernel/topology.c + * + * Copyright (C) 2011 Linaro Limited. + * Written by: Vincent Guittot + * + * based on arch/sh/kernel/topology.c + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static struct cputopo_power **table_config = NULL; + +struct cputopo_scale { + int id; + int freq; + struct cputopo_power *power; +}; + +/* + * The table will be mostly used by one cpu which will update the + * configuration for all cpu on a cpufreq notification + * or a sched_mc level change + */ +static struct cputopo_scale cpu_power[NR_CPUS]; + +static void set_cpufreq_scale(unsigned int cpuid, unsigned int freq) +{ + unsigned int idx; + + cpu_power[cpuid].freq = freq; + + idx = freq / cpu_power[cpuid].power->step; + if (idx >= cpu_power[cpuid].power->max) + idx = cpu_power[cpuid].power->max - 1; + + set_power_scale(cpuid, cpu_power[cpuid].power->table[idx]); + smp_wmb(); +} + +static void update_power_scale(unsigned int cpu, unsigned int idx) +{ + cpu_power[cpu].id = idx; + cpu_power[cpu].power = table_config[idx]; + + set_cpufreq_scale(cpu, cpu_power[cpu].freq); +} + +static int topo_cpufreq_transition(struct notifier_block *nb, + unsigned long state, void *data) +{ + struct cpufreq_freqs *freqs = data; + + if (state == CPUFREQ_POSTCHANGE || state == CPUFREQ_RESUMECHANGE) + set_cpufreq_scale(freqs->cpu, freqs->new); + + return NOTIFY_OK; +} + +static struct notifier_block topo_cpufreq_nb = { + .notifier_call = topo_cpufreq_transition, +}; + +static int topo_cpufreq_init(struct platform_device *pdev) +{ + unsigned int cpu; + + /* get cpu_power table */ + table_config = dev_get_platdata(&pdev->dev); + + /* init core mask */ + for_each_possible_cpu(cpu) { + cpu_power[cpu].freq = 0; + update_power_scale(cpu, ARM_DEFAULT_SCALE); + } + + /* register cpufreq notification */ + return cpufreq_register_notifier(&topo_cpufreq_nb, + CPUFREQ_TRANSITION_NOTIFIER); +} + +static int topo_cpufreq_exit(struct platform_device *pdev) +{ + unsigned int cpu; + + /* unregister cpufreq notification */ + cpufreq_unregister_notifier(&topo_cpufreq_nb, + CPUFREQ_TRANSITION_NOTIFIER); + + /* cleay core mask */ + for_each_possible_cpu(cpu) { + cpu_power[cpu].freq = 0; + cpu_power[cpu].power = NULL; + } + + /* clear cpu_power table */ + table_config = NULL; + + return 0; +} + +static int topo_policy_transition(struct notifier_block *nb, + unsigned long state, void *data) +{ + int cpu, idx, level = (int)data; + + if (level == POWERSAVINGS_BALANCE_NONE) + idx = ARM_DEFAULT_SCALE; + else + idx = ARM_POWER_SCALE; + + for_each_possible_cpu(cpu) + update_power_scale(cpu, cpu ? ARM_DEFAULT_SCALE : idx ); + + return NOTIFY_OK; +} + +static struct notifier_block topo_policy_nb = { + .notifier_call = topo_policy_transition, +}; + +static int __devinit cpupower_probe(struct platform_device *pdev) +{ + topo_cpufreq_init(pdev); + + /* register cpufreq notifer */ + topology_register_notifier(&topo_policy_nb); + + return 0; +} + +static int __devexit cpupower_remove(struct platform_device *pdev) +{ + /* unregister cpufreq notifer */ + topology_unregister_notifier(&topo_policy_nb); + + topo_cpufreq_exit(pdev); + + return 0; +} + + +static struct platform_driver cpupower_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "cpupower", + }, + .probe = cpupower_probe, + .remove = __devexit_p(cpupower_remove), +}; + +static int __init cpupower_init(void) +{ + return platform_driver_register(&cpupower_driver); +} + +static void __exit cpupower_exit(void) +{ + platform_driver_unregister(&cpupower_driver); +} + +core_initcall(cpupower_init); +module_exit(cpupower_exit); + +MODULE_AUTHOR("vincent Guittot"); +MODULE_DESCRIPTION("update cpu_power according to current cpu load driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); diff --git a/drivers/staging/prima/Android.mk b/drivers/staging/prima/Android.mk index beefec4efd0..e046954a2eb 100644 --- a/drivers/staging/prima/Android.mk +++ b/drivers/staging/prima/Android.mk @@ -80,10 +80,14 @@ KBUILD_OPTIONS += MODNAME=wlan KBUILD_OPTIONS += BOARD_PLATFORM=$(TARGET_BOARD_PLATFORM) KBUILD_OPTIONS += $(WLAN_SELECT) + +VERSION=$(shell grep -w "VERSION =" $(TOP)/kernel/Makefile | sed 's/^VERSION = //' ) +PATCHLEVEL=$(shell grep -w "PATCHLEVEL =" $(TOP)/kernel/Makefile | sed 's/^PATCHLEVEL = //' ) + include $(CLEAR_VARS) LOCAL_MODULE := $(WLAN_CHIPSET)_wlan.ko LOCAL_MODULE_KBUILD_NAME := wlan.ko -LOCAL_MODULE_TAGS := debug +LOCAL_MODULE_TAGS := optional LOCAL_MODULE_DEBUG_ENABLE := true LOCAL_MODULE_PATH := $(TARGET_OUT)/lib/modules/$(WLAN_CHIPSET) include $(DLKM_DIR)/AndroidKernelModule.mk diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiHCBB.c b/drivers/staging/prima/CORE/BAP/src/bapApiHCBB.c index fbe7cf43839..1f3b1275834 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiHCBB.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiHCBB.c @@ -161,7 +161,7 @@ WLAN_BAPReset tHalHandle hHal = NULL; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if (btampHandle == NULL) @@ -308,7 +308,7 @@ WLAN_BAPFlush ptBtampContext btampContext = (ptBtampContext) btampHandle; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if (btampHandle == NULL) { @@ -381,7 +381,7 @@ WLAN_EnhancedBAPFlush ptBtampContext btampContext; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ /* Validate params */ @@ -461,7 +461,7 @@ WLAN_BAPReadConnectionAcceptTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -530,7 +530,7 @@ WLAN_BAPWriteConnectionAcceptTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIWriteConnectionAcceptTimeout) @@ -621,7 +621,7 @@ WLAN_BAPReadLinkSupervisionTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIReadLinkSupervisionTimeout) || @@ -713,7 +713,7 @@ WLAN_BAPWriteLinkSupervisionTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIWriteLinkSupervisionTimeout) || @@ -805,7 +805,7 @@ WLAN_BAPReadLogicalLinkAcceptTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -874,7 +874,7 @@ WLAN_BAPWriteLogicalLinkAcceptTimeout /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIWriteLogicalLinkAcceptTimeout) @@ -962,7 +962,7 @@ WLAN_BAPSetEventMaskPage2 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCISetEventMaskPage2) @@ -1037,7 +1037,7 @@ WLAN_BAPReadLocationData /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -1119,7 +1119,7 @@ WLAN_BAPWriteLocationData /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIWriteLocationData) @@ -1200,7 +1200,7 @@ WLAN_BAPReadFlowControlMode /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -1405,7 +1405,7 @@ WLAN_BAPSetShortRangeMode /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -1546,7 +1546,7 @@ WLAN_BAPVendorSpecificCmd0 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) @@ -1646,7 +1646,7 @@ WLAN_BAPVendorSpecificCmd1 /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIEvent)) diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiInfo.c b/drivers/staging/prima/CORE/BAP/src/bapApiInfo.c index 63356f9eab0..df2583e04fe 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiInfo.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiInfo.c @@ -170,7 +170,7 @@ WLAN_BAPReadLocalVersionInfo } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -246,7 +246,7 @@ WLAN_BAPReadLocalSupportedCmds } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -312,7 +312,7 @@ WLAN_BAPReadBufferSize } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -382,7 +382,7 @@ WLAN_BAPReadDataBlockSize } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -543,7 +543,7 @@ WLAN_BAPDisconnect VOS_STATUS vosStatus; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_FATAL, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_FATAL, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if (btampHandle == NULL) @@ -609,7 +609,7 @@ v_BOOL_t WLAN_BAPSessionOn ptBtampContext btampContext = (ptBtampContext) btampHandle; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if (btampHandle == NULL) diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiLinkCntl.c b/drivers/staging/prima/CORE/BAP/src/bapApiLinkCntl.c index 5a484c8aebf..b8ae3c5120f 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiLinkCntl.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiLinkCntl.c @@ -882,12 +882,12 @@ WLAN_BAPPhysicalLinkCreate /* Validate params */ if ((pBapHCIPhysLinkCreate == NULL) || (NULL == btampContext)) { - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: btampHandle value: %x, pBapHCIPhysLinkCreate is %x", + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: btampHandle value: %p, pBapHCIPhysLinkCreate is %p", __func__, btampHandle, pBapHCIPhysLinkCreate); return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); if(DISCONNECTED != instanceVar->stateVar) { @@ -913,7 +913,7 @@ WLAN_BAPPhysicalLinkCreate &btampContext, /* Handle to return per assoc btampContext value in */ BT_INITIATOR); /* BT_INITIATOR */ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Handle event */ vosStatus = btampFsm(btampContext, &bapEvent, &status); @@ -985,12 +985,12 @@ WLAN_BAPPhysicalLinkAccept /* Validate params */ if ((pBapHCIPhysLinkAccept == NULL) || (NULL == btampContext)) { - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: btampHandle value: %x, pBapHCIPhysLinkAccept is %x", + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "%s: btampHandle value: %p, pBapHCIPhysLinkAccept is %p", __func__, btampHandle, pBapHCIPhysLinkAccept); return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); instanceVar = &(btampContext->bapPhysLinkMachine); if(DISCONNECTED != instanceVar->stateVar) @@ -1017,7 +1017,7 @@ WLAN_BAPPhysicalLinkAccept &btampContext, /* Handle to return per assoc btampContext value in */ BT_RESPONDER); /* BT_RESPONDER */ - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Handle event */ vosStatus = btampFsm(btampContext, &bapEvent, &status); @@ -1087,7 +1087,7 @@ WLAN_BAPPhysicalLinkDisconnect return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate the Physical link handle */ if (pBapHCIPhysLinkDisconnect->phy_link_handle != btampContext->phy_link_handle) @@ -1106,7 +1106,7 @@ WLAN_BAPPhysicalLinkDisconnect bapEvent.event = eWLAN_BAP_HCI_PHYSICAL_LINK_DISCONNECT; bapEvent.params = pBapHCIPhysLinkDisconnect; - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Handle event */ vosStatus = btampFsm(btampContext, &bapEvent, &status); @@ -1192,7 +1192,7 @@ WLAN_BAPLogicalLinkCreate } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate the BAP state to accept the logical link request Logical Link create/accept requests are allowed only in @@ -1382,7 +1382,7 @@ WLAN_BAPLogicalLinkAccept } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Validate the BAP state to accept the logical link request Logical Link create/accept requests are allowed only in @@ -1590,7 +1590,7 @@ WLAN_BAPLogicalLinkDisconnect #ifdef BAP_DEBUG /* Trace the tBtampCtx being passed in. */ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN BAP Context Monitor: btampContext value = %x in %s:%d", btampContext, __func__, __LINE__ ); + "WLAN BAP Context Monitor: btampContext value = %p in %s:%d", btampContext, __func__, __LINE__ ); #endif //BAP_DEBUG bapHCIEvent.bapHCIEventCode = BTAMP_TLV_HCI_COMMAND_STATUS_EVENT; diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiLinkSupervision.c b/drivers/staging/prima/CORE/BAP/src/bapApiLinkSupervision.c index 426f00e6ad3..62a1d4e2752 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiLinkSupervision.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiLinkSupervision.c @@ -537,7 +537,7 @@ static VOS_STATUS WLANBAP_TxLinkSupervisionCB } } VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO, - "%s:Returned Vos Packet:%x\n",__func__, pPacket ); + "%s:Returned Vos Packet:%p\n", __func__, pPacket ); vos_pkt_return_packet( pPacket ); diff --git a/drivers/staging/prima/CORE/BAP/src/bapApiStatus.c b/drivers/staging/prima/CORE/BAP/src/bapApiStatus.c index b1c26b4087c..00b11e662ba 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapApiStatus.c +++ b/drivers/staging/prima/CORE/BAP/src/bapApiStatus.c @@ -263,7 +263,7 @@ WLAN_BAPReadLinkQuality /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIReadLinkQuality) || @@ -360,7 +360,7 @@ WLAN_BAPReadRSSI /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "%s: btampHandle value: %x", __func__, btampHandle); + "%s: btampHandle value: %p", __func__, btampHandle); /* Validate params */ if ((NULL == btampHandle) || (NULL == pBapHCIReadRSSI) || @@ -469,7 +469,7 @@ WLAN_BAPReadLocalAMPInfo return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Format the command complete event to return... */ @@ -581,7 +581,7 @@ WLAN_BAPReadLocalAMPAssoc return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, phy_link_handle = %d", __func__, @@ -818,13 +818,13 @@ WLAN_BAPWriteRemoteAMPAssoc return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %x", __func__, btampHandle); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampHandle value: %p", __func__, btampHandle); /* Fill in the event structure */ bapEvent.event = eWLAN_BAP_HCI_WRITE_REMOTE_AMP_ASSOC; bapEvent.params = pBapHCIWriteRemoteAMPAssoc; - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Handle event */ vosStatus = btampFsm(btampContext, &bapEvent, &status); diff --git a/drivers/staging/prima/CORE/BAP/src/bapModule.c b/drivers/staging/prima/CORE/BAP/src/bapModule.c index a0eab5cc696..504ae9b7501 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapModule.c +++ b/drivers/staging/prima/CORE/BAP/src/bapModule.c @@ -977,7 +977,7 @@ WLANBAP_CreateNewPhyLinkCtx *hBtampContext = pBtampCtx; VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, - "Btamp Ctxt = %x", pBtampCtx); + "Btamp Ctxt = %p", pBtampCtx); return VOS_STATUS_SUCCESS; #else // defined(BTAMP_MULTIPLE_PHY_LINKS) @@ -1112,7 +1112,7 @@ WLANBAP_CreateNewLogLinkCtx #ifdef BAP_DEBUG /* Trace the tBtampCtx being passed in. */ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN BAP Context Monitor: pBtampContext value = %x in %s:%d", pBtampContext, __func__, __LINE__ ); + "WLAN BAP Context Monitor: pBtampContext value = %p in %s:%d", pBtampContext, __func__, __LINE__ ); #endif //BAP_DEBUG /*------------------------------------------------------------------------ diff --git a/drivers/staging/prima/CORE/BAP/src/bapRsn8021xSuppRsnFsm.c b/drivers/staging/prima/CORE/BAP/src/bapRsn8021xSuppRsnFsm.c index abaa50a7ba4..4e4724597ab 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapRsn8021xSuppRsnFsm.c +++ b/drivers/staging/prima/CORE/BAP/src/bapRsn8021xSuppRsnFsm.c @@ -797,7 +797,7 @@ int checkPeerReplayCounter(tSuppRsnFsm *fsm, if (cmp > 0) { VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, - "BP radio %d got old EAPOL replay counter from AP\n" ); + "BP got old EAPOL replay counter from AP" ); retVal = ANI_E_REPLAY_CHECK_FAILED; } @@ -875,7 +875,7 @@ int checkTransition(tSuppRsnFsm *fsm, void *arg) VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_ERROR, "Resending EAPOL-Key Msg2 from " - "supplicant radio %d to AP\n" ); + "supplicant to AP" ); retVal = gotoStateStaKeyStart(fsm, data, eANI_BOOLEAN_TRUE); } diff --git a/drivers/staging/prima/CORE/BAP/src/bapRsnTxRx.c b/drivers/staging/prima/CORE/BAP/src/bapRsnTxRx.c index efe8ec3c55b..390d61abac7 100644 --- a/drivers/staging/prima/CORE/BAP/src/bapRsnTxRx.c +++ b/drivers/staging/prima/CORE/BAP/src/bapRsnTxRx.c @@ -223,7 +223,7 @@ static VOS_STATUS bapRsnTxFrame( v_PVOID_t pvosGCtx, vos_pkt_t *pPacket ) VOS_STATUS bapRsnSendEapolFrame( v_PVOID_t pvosGCtx, tAniPacket *pAniPkt ) { VOS_STATUS status; - vos_pkt_t *pPacket; + vos_pkt_t *pPacket = NULL; v_U8_t *pData, *pSrc; int pktLen = aniAsfPacketGetBytes( pAniPkt, &pSrc ); @@ -232,7 +232,7 @@ VOS_STATUS bapRsnSendEapolFrame( v_PVOID_t pvosGCtx, tAniPacket *pAniPkt ) return VOS_STATUS_E_EMPTY; } status = bapRsnAcquirePacket( &pPacket, &pData, pktLen ); - if( VOS_IS_STATUS_SUCCESS( status ) ) + if( VOS_IS_STATUS_SUCCESS( status ) && ( NULL != pPacket )) { vos_mem_copy( pData, pSrc, pktLen ); //Send the packet, need to check whether we have an outstanding packet first. diff --git a/drivers/staging/prima/CORE/BAP/src/btampFsm.c b/drivers/staging/prima/CORE/BAP/src/btampFsm.c index 0b4b97b1e93..d049067f7aa 100644 --- a/drivers/staging/prima/CORE/BAP/src/btampFsm.c +++ b/drivers/staging/prima/CORE/BAP/src/btampFsm.c @@ -208,7 +208,7 @@ bapSetKey( v_PVOID_t pvosGCtx, tCsrRoamSetKey *pSetKeyInfo ) return VOS_STATUS_E_FAULT; } - VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %x", __func__, btampContext); + VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: btampContext value: %p", __func__, btampContext); /* Fill in the event structure */ bapEvent.event = eWLAN_BAP_RSN_SUCCESS; @@ -1415,7 +1415,7 @@ signalHCIPhysLinkDiscEvent #ifdef BAP_DEBUG /* Trace the tBtampCtx being passed in. */ VOS_TRACE( VOS_MODULE_ID_BAP, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN BAP Context Monitor: btampContext value = %x in %s:%d", btampContext, __func__, __LINE__ ); + "WLAN BAP Context Monitor: btampContext value = %p in %s:%d", btampContext, __func__, __LINE__ ); #endif //BAP_DEBUG /* Loop disconnecting all Logical Links on this Physical Link */ diff --git a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c index cdeed3540b3..d62d460e6c0 100644 --- a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c +++ b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe.c @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + /**========================================================================= @file wlan_qct_dxe.c @@ -46,9 +47,8 @@ @brief This file contains the external API exposed by the wlan data transfer abstraction layer module. - Copyright (c) 2010-2011 QUALCOMM Incorporated. + Copyright (c) 2010-2011 Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary ========================================================================*/ /*=========================================================================== @@ -97,7 +97,7 @@ when who what, where, why #define T_WLANDXE_TX_INT_ENABLE_FCOUNT 1 #define T_WLANDXE_MEMDUMP_BYTE_PER_LINE 16 #define T_WLANDXE_MAX_RX_PACKET_WAIT 6000 -#define T_WLANDXE_PERIODIC_HEALTH_M_TIME 1500 +#define T_WLANDXE_PERIODIC_HEALTH_M_TIME 2500 #define T_WLANDXE_MAX_HW_ACCESS_WAIT 2000 #define WLANDXE_MAX_REAPED_RX_FRAMES 512 @@ -585,6 +585,7 @@ void dxeRXHealthMonitor /* Make wake up HW */ dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); for(hwWakeLoop = 0; hwWakeLoop < T_WLANDXE_MAX_HW_ACCESS_WAIT; hwWakeLoop++) { @@ -711,6 +712,7 @@ void dxeTXHealthMonitor * This will fix if there is any problem with SMSM state */ dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); /* Wait till RIVA up */ for(hwWakeLoop = 0; hwWakeLoop < T_WLANDXE_MAX_HW_ACCESS_WAIT; hwWakeLoop++) @@ -2214,10 +2216,13 @@ static wpt_status dxeRXFrameReady * Do not try reload driver at here*/ if(!(chStat & WLANDXE_CH_CTRL_EN_MASK)) { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN, "dxeRXFrameReady %s RING Wrapped, RX Free Low 0x%x", channelType[channelEntry->channelType], chStat); - channelEntry->numFragmentCurrentChain = 0; + /* This is not empty interrupt case + * If handle this as empty interrupt, false SSR might be issued + * Frame count '1' is dummy frame count to avoid SSR */ + channelEntry->numFragmentCurrentChain = 1; return eWLAN_PAL_STATUS_SUCCESS; } @@ -2248,11 +2253,11 @@ static wpt_status dxeRXFrameReady { if(!(WLANDXE_U32_SWAP_ENDIAN(descCtrl) & WLANDXE_DESC_CTRL_VALID)) { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN, "Found Invalidated Descriptor %d", (int)descLoop); if(eWLAN_PAL_STATUS_SUCCESS == wpalIsPacketLocked(currentCtrlBlk->xfrFrame)) { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN, "Packet locked, Resync Host and HW"); channelEntry->headCtrlBlk = currentCtrlBlk; invalidatedFound = 1; @@ -2260,7 +2265,7 @@ static wpt_status dxeRXFrameReady } else { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_WARN, "Packet Not Locked, cannot transfer frame"); } } @@ -2675,16 +2680,6 @@ void dxeRXEventHandler return; } - /* Enable system level ISR */ - /* Enable RX ready Interrupt at here */ - status = wpalEnableInterrupt(DXE_INTERRUPT_RX_READY); - if(eWLAN_PAL_STATUS_SUCCESS != status) - { - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, - "dxeRXEventHandler Enable RX Ready interrupt fail"); - return; - } - /* Prepare Control Register EN Channel */ if(!(dxeCtxt->dxeChannel[WDTS_CHANNEL_RX_HIGH_PRI].extraConfig.chan_mask & WLANDXE_CH_CTRL_EN_MASK)) { @@ -2708,6 +2703,16 @@ void dxeRXEventHandler regValue &= WLANDXE_RX_INTERRUPT_PRO_UNMASK; wpalWriteRegister(WLANDXE_INT_MASK_REG_ADDRESS, regValue); + /* Enable system level ISR */ + /* Enable RX ready Interrupt at here */ + status = wpalEnableInterrupt(DXE_INTERRUPT_RX_READY); + if(eWLAN_PAL_STATUS_SUCCESS != status) + { + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, + "dxeRXEventHandler Enable RX Ready interrupt fail"); + return; + } + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "%s Exit", __func__); return; @@ -2899,14 +2904,16 @@ static wpt_status dxeTXPushFrame #else wpt_iterator iterator; #endif /* FEATURE_R33D */ + wpt_uint32 isEmpty = 0; HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "%s Enter", __func__); - if(WLANDXE_POWER_STATE_BMPS == tempDxeCtrlBlk->hostPowerState) + tempDxeCtrlBlk->smsmToggled = eWLAN_PAL_FALSE; + if((0 == tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc) && + (0 == tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc)) { - tempDxeCtrlBlk->rivaPowerState = WLANDXE_RIVA_POWER_STATE_BMPS_UNKNOWN; - dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); + isEmpty = 1; } channelEntry->numFragmentCurrentChain = 0; @@ -3049,10 +3056,16 @@ static wpt_status dxeTXPushFrame { /* Update channel head as next avaliable linked slot */ channelEntry->headCtrlBlk = currentCtrlBlk; - tempDxeCtrlBlk->ringNotEmpty = eWLAN_PAL_TRUE; - HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, "SMSM_ret LO=%d HI=%d", tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc, - tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc ); - dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + if(isEmpty) + { + tempDxeCtrlBlk->ringNotEmpty = eWLAN_PAL_TRUE; + HDXE_MSG(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_INFO_LOW, + "SMSM_ret LO=%d HI=%d", + tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc, + tempDxeCtrlBlk->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc ); + dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + tempDxeCtrlBlk->smsmToggled = eWLAN_PAL_TRUE; + } return status; } @@ -3732,6 +3745,18 @@ void dxeTXCompleteProcessing dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_HIGH_PRI].numRsvdDesc, channelType[dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].channelType], dxeCtxt->dxeChannel[WDTS_CHANNEL_TX_LOW_PRI].numRsvdDesc); + + if((WLANDXE_POWER_STATE_FULL != dxeCtxt->hostPowerState) && + (eWLAN_PAL_FALSE == tempDxeCtrlBlk->smsmToggled)) + { + /* After TX Comp processing, still remaining frame on the DXE TX ring + * And when push frame, RING was not empty marked + * Then when push frame, no SMSM toggle happen + * To avoid permanent TX stall, SMSM toggle is needed at here + * With this toggle, host should gaurantee SMSM state should be changed */ + dxeNotifySmsm(eWLAN_PAL_FALSE, eWLAN_PAL_TRUE); + dxeNotifySmsm(eWLAN_PAL_TRUE, eWLAN_PAL_FALSE); + } } /*Kicking the DXE after the TX Complete interrupt was enabled - to avoid @@ -4184,6 +4209,7 @@ void *WLANDXE_Open tempDxeCtrlBlk->rxIntDisabledByIMPS = eWLAN_PAL_FALSE; tempDxeCtrlBlk->txIntDisabledByIMPS = eWLAN_PAL_FALSE; tempDxeCtrlBlk->driverReloadInProcessing = eWLAN_PAL_FALSE; + tempDxeCtrlBlk->smsmToggled = eWLAN_PAL_FALSE; /* Initialize SMSM state * Init State is @@ -4697,6 +4723,11 @@ wpt_status WLANDXE_Stop dxeCtxt = (WLANDXE_CtrlBlkType *)pDXEContext; for(idx = 0; idx < WDTS_CHANNEL_MAX; idx++) { + if(VOS_TIMER_STATE_RUNNING == wpalTimerGetCurStatus(&dxeCtxt->dxeChannel[idx].healthMonitorTimer)) + { + wpalTimerStop(&dxeCtxt->dxeChannel[idx].healthMonitorTimer); + } + status = dxeChannelStop(dxeCtxt, &dxeCtxt->dxeChannel[idx]); if(eWLAN_PAL_STATUS_SUCCESS != status) { diff --git a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c index 24bd93ccba9..6c782f30e52 100644 --- a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c +++ b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_cfg_i.c @@ -386,7 +386,7 @@ wpt_status dxeCommonDefaultConfig All the channels must have it's own configurations @ Parameters - WLANDXE_CtrlBlkType *dxeCtrlBlk, + WLANDXE_CtrlBlkType: *dxeCtrlBlk, DXE host driver main control block WLANDXE_ChannelCBType *channelEntry Channel specific control block @@ -409,6 +409,7 @@ wpt_status dxeChannelDefaultConfig wpt_uint32 dxeControlWriteEop = 0; wpt_uint32 dxeControlWriteEopInt = 0; wpt_uint32 idx; + wpt_uint32 rxResourceCount = 0; WLANDXE_ChannelMappingType *mappedChannel = NULL; /* Sanity Check */ @@ -621,7 +622,16 @@ wpt_status dxeChannelDefaultConfig channelEntry->extraConfig.intMask = channelInterruptMask[mappedChannel->DMAChannel]; - channelEntry->numDesc = mappedChannel->channelConfig->nDescs; + wpalGetNumRxRawPacket(&rxResourceCount); + if((WDTS_CHANNEL_TX_LOW_PRI == channelEntry->channelType) || + (0 == rxResourceCount)) + { + channelEntry->numDesc = mappedChannel->channelConfig->nDescs; + } + else + { + channelEntry->numDesc = rxResourceCount / 4; + } channelEntry->assignedDMAChannel = mappedChannel->DMAChannel; channelEntry->numFreeDesc = 0; channelEntry->numRsvdDesc = 0; diff --git a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_i.h b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_i.h index 77d3987d95d..5f95b33dc82 100644 --- a/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_i.h +++ b/drivers/staging/prima/CORE/DXE/src/wlan_qct_dxe_i.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + #ifndef WLAN_QCT_DXE_I_H #define WLAN_QCT_DXE_I_H @@ -49,9 +50,9 @@ @brief This file contains the external API exposed by the wlan data transfer abstraction layer module. - Copyright (c) 2011 QUALCOMM Incorporated. + Copyright (c) 2011 Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary + Qualcomm Technologies Confidential and Proprietary ========================================================================*/ /*=========================================================================== @@ -642,6 +643,7 @@ typedef struct wpt_packet *freeRXPacket; wpt_boolean rxPalPacketUnavailable; wpt_boolean driverReloadInProcessing; + wpt_boolean smsmToggled; } WLANDXE_CtrlBlkType; /*========================================================================== diff --git a/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h b/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h index b4b27ef73f4..15520ae2e02 100644 --- a/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h +++ b/drivers/staging/prima/CORE/HDD/inc/qc_sap_ioctl.h @@ -256,6 +256,7 @@ typedef struct #define QCSAP_IOCTL_SET_TX_POWER (SIOCIWFIRSTPRIV+20) #define QCSAP_IOCTL_GET_STA_INFO (SIOCIWFIRSTPRIV+21) #define QCSAP_IOCTL_SET_MAX_TX_POWER (SIOCIWFIRSTPRIV+22) +#define QCSAP_IOCTL_DATAPATH_SNAP_SHOT (SIOCIWFIRSTPRIV+23) #define MAX_VAR_ARGS 7 #define QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED (SIOCIWFIRSTPRIV + 31) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h index c1d1b6d58c9..55d8caeefb5 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_assoc.h @@ -44,13 +44,15 @@ #include #define HDD_MAX_NUM_IBSS_STA ( 9 ) #ifdef FEATURE_WLAN_TDLS -#define HDD_MAX_NUM_TDLS_STA ( HDD_MAX_NUM_IBSS_STA - 1 ) // up to 3 as 1 is assigned to AP +#define HDD_MAX_NUM_TDLS_STA ( 8 ) +#define TDLS_STA_INDEX_VALID(staId) \ + (((staId) >= 4) && ((staId) < 0xFF)) #endif #define TKIP_COUNTER_MEASURE_STARTED 1 #define TKIP_COUNTER_MEASURE_STOPED 0 /* Timeout (in ms) for Link to Up before Registering Station */ #define ASSOC_LINKUP_TIMEOUT 60 -typedef enum +typedef enum { /** Not associated in Infra or participating in an IBSS / Ad-hoc network.*/ eConnectionState_NotConnected, @@ -110,6 +112,9 @@ typedef struct connection_info_s /** Remembers authenticated state */ v_U8_t uIsAuthenticated; + + /** Dot11Mode */ + tANI_U32 dot11Mode; }connection_info_t; /*Forward declaration of Adapter*/ @@ -134,5 +139,5 @@ int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType ); int hdd_set_csr_auth_type( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType ); VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, tANI_U8 *peerMac, tANI_U16 staId, tANI_U8 ucastSig); - +void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter); #endif diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h index 2e900906f83..ea8505b5841 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg.h @@ -591,6 +591,11 @@ typedef enum #define CFG_RETRY_LIMIT_TWO_MAX ( 15 ) #define CFG_RETRY_LIMIT_TWO_DEFAULT ( 15 ) +#define CFG_DISABLE_AGG_WITH_BTC_NAME "gDisableAggWithBTC" +#define CFG_DISABLE_AGG_WITH_BTC_MIN ( 0 ) +#define CFG_DISABLE_AGG_WITH_BTC_MAX ( 1 ) +#define CFG_DISABLE_AGG_WITH_BTC_DEFAULT ( 1 ) + #ifdef WLAN_AP_STA_CONCURRENCY #define CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_NAME "gPassiveMaxChannelTimeConc" @@ -618,10 +623,15 @@ typedef enum #define CFG_REST_TIME_CONC_MAX ( 10000 ) #define CFG_REST_TIME_CONC_DEFAULT ( 100 ) -#define CFG_NUM_CHAN_COMBINED_CONC_NAME "gNumChanCombinedConc" -#define CFG_NUM_CHAN_COMBINED_CONC_MIN ( 1 ) -#define CFG_NUM_CHAN_COMBINED_CONC_MAX ( 255 ) -#define CFG_NUM_CHAN_COMBINED_CONC_DEFAULT ( 1 ) +#define CFG_NUM_STA_CHAN_COMBINED_CONC_NAME "gNumStaChanCombinedConc" +#define CFG_NUM_STA_CHAN_COMBINED_CONC_MIN ( 1 ) +#define CFG_NUM_STA_CHAN_COMBINED_CONC_MAX ( 255 ) +#define CFG_NUM_STA_CHAN_COMBINED_CONC_DEFAULT ( 3 ) + +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_NAME "gNumP2PChanCombinedConc" +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_MIN ( 1 ) +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_MAX ( 255 ) +#define CFG_NUM_P2P_CHAN_COMBINED_CONC_DEFAULT ( 1 ) #endif @@ -655,6 +665,11 @@ typedef enum #define CFG_IGNORE_DTIM_MAX WNI_CFG_IGNORE_DTIM_STAMAX #define CFG_IGNORE_DTIM_DEFAULT WNI_CFG_IGNORE_DTIM_STADEF +#define CFG_MAX_LI_MODULATED_DTIM_NAME "gMaxLIModulatedDTIM" +#define CFG_MAX_LI_MODULATED_DTIM_MIN ( 1 ) +#define CFG_MAX_LI_MODULATED_DTIM_MAX ( 10 ) +#define CFG_MAX_LI_MODULATED_DTIM_DEFAULT ( 10 ) + #define CFG_RX_ANT_CONFIGURATION_NAME "gNumRxAnt" #define CFG_RX_ANT_CONFIGURATION_NAME_MIN ( 1 ) #define CFG_RX_ANT_CONFIGURATION_NAME_MAX ( 2 ) @@ -811,6 +826,21 @@ typedef enum #define CFG_IMMEDIATE_ROAM_RSSI_DIFF_MAX (125) #define CFG_IMMEDIATE_ROAM_RSSI_DIFF_DEFAULT (3) +/*This parameter is used to set Wireless Extended Security Mode.*/ +#define CFG_ENABLE_WES_MODE_NAME "gWESModeEnabled" +#define CFG_ENABLE_WES_MODE_NAME_MIN (0) +#define CFG_ENABLE_WES_MODE_NAME_MAX (1) +#define CFG_ENABLE_WES_MODE_NAME_DEFAULT (0) + +#define CFG_ROAM_SCAN_N_PROBES "gRoamScanNProbes" +#define CFG_ROAM_SCAN_N_PROBES_MIN (1) +#define CFG_ROAM_SCAN_N_PROBES_MAX (10) +#define CFG_ROAM_SCAN_N_PROBES_DEFAULT (2) + +#define CFG_ROAM_SCAN_HOME_AWAY_TIME "gRoamScanHomeAwayTime" +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN (3) +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX (300) +#define CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT (CFG_NEIGHBOR_SCAN_MAX_CHAN_TIME_DEFAULT) #endif /* (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) */ #ifdef FEATURE_WLAN_OKC @@ -820,6 +850,13 @@ typedef enum #define CFG_OKC_FEATURE_ENABLED_DEFAULT (1) #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED "gRoamScanOffloadEnabled" +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN (0) +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX (1) +#define CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT (1) +#endif + #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME "PktClassificationBasis" // DSCP or 802.1Q #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN (0) #define CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX (1) @@ -1148,9 +1185,8 @@ typedef enum #define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN (1000) #define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX (60000) #define CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT (20000) - #define CFG_EMPTY_SCAN_REFRESH_PERIOD_NAME "gEmptyScanRefreshPeriod" -#define CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN (0) +#define CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN (1000) #define CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX (60000) #define CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT (0) #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ @@ -1210,6 +1246,12 @@ typedef enum #define CFG_ENABLE_HOST_ARPOFFLOAD_MAX ( 1 ) #define CFG_ENABLE_HOST_ARPOFFLOAD_DEFAULT ( 0 ) +#define CFG_ENABLE_HOST_NSOFFLOAD_NAME "hostNSOffload" +#define CFG_ENABLE_HOST_NSOFFLOAD_MIN ( 0 ) +#define CFG_ENABLE_HOST_NSOFFLOAD_MAX ( 1 ) +#define CFG_ENABLE_HOST_NSOFFLOAD_DEFAULT ( 0 ) + + #define CFG_ENABLE_BTAMP_NAME "gEnableBtAmp" #define CFG_ENABLE_BTAMP_MIN ( 0 ) #define CFG_ENABLE_BTAMP_MAX ( 1 ) @@ -1247,11 +1289,6 @@ typedef enum #define CFG_ENABLE_DFS_CHNL_SCAN_MAX ( 1 ) #define CFG_ENABLE_DFS_CHNL_SCAN_DEFAULT ( 1 ) -#define CFG_ENABLE_IGNORE_CHAN165 "gIgnore_Chan165" -#define CFG_ENABLE_IGNORE_CHAN165_MIN ( 0 ) -#define CFG_ENABLE_IGNORE_CHAN165_MAX ( 1 ) -#define CFG_ENABLE_IGNORE_CHAN165_DEFAULT ( 0 ) - typedef enum { eHDD_LINK_SPEED_REPORT_ACTUAL = 0, @@ -1305,12 +1342,10 @@ typedef enum #define CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_MAX ( 1 ) #define CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_DEFAULT ( 0 ) -#ifdef WLAN_FEATURE_PACKET_FILTERING -#define CFG_MC_ADDR_LIST_FILTER_NAME "isMcAddrListFilter" -#define CFG_MC_ADDR_LIST_FILTER_MIN ( 0 ) -#define CFG_MC_ADDR_LIST_FILTER_MAX ( 1 ) -#define CFG_MC_ADDR_LIST_FILTER_DEFAULT ( 0 ) -#endif +#define CFG_ENABLE_SSR "gEnableSSR" +#define CFG_ENABLE_SSR_MIN ( 0 ) +#define CFG_ENABLE_SSR_MAX ( 1 ) +#define CFG_ENABLE_SSR_DEFAULT ( 1 ) /* * VOS Trace Enable Control @@ -1470,27 +1505,32 @@ typedef enum * Enable / Disable MCC feature * Default: Enable */ -#define CFG_ENABLE_MCC_ENABLED_NAME "gEnableMCCMode" +#define CFG_ENABLE_MCC_ENABLED_NAME "gEnableMCCMode" #define CFG_ENABLE_MCC_ENABLED_MIN ( 0 ) #define CFG_ENABLE_MCC_ENABLED_MAX ( 1 ) -#define CFG_ENABLE_MCC_ENABLED_DEFAULT ( 1 ) +#define CFG_ENABLE_MCC_ENABLED_DEFAULT ( 1 ) /* * Allow GO in MCC mode to accept different beacon interval than STA's. * Added for Wi-Fi Cert. 5.1.12 - * Default: Disable - * If gAllowMCCGODiffBI = 1 // Set to 1 for WFA certification. GO Beacon interval is not changed. MCC GO -* doesn't work well in optimized way. In worst scenario, it may invite STA -* disconnection. - * gAllowMCCGODiffBI = 2 //If set to 2 workaround 1 disassoc all the clients + * Default: gAllowMCCGODiffBI = 2 + * If gAllowMCCGODiffBI = 1 // Set to 1 for WFA certification. GO Beacon + * interval is not changed. MCC GO + * doesn't work well in optimized way. + * In worst scenario, it may invite STA + * disconnection. + * gAllowMCCGODiffBI = 2 //If set to 2 workaround 1 disassoc all the clients * and update beacon Interval * gAllowMCCGODiffBI = 3 //If set to 3 tear down the P2P link in auto/ * Non-autonomous -GO case + * gAllowMCCGODiffBI = 4 //If set to 4 don't disconnect the P2P client + * in autonomous/Non-autonomous -GO case update + * the BI dynamically */ #define CFG_ALLOW_MCC_GO_DIFF_BI_NAME "gAllowMCCGODiffBI" #define CFG_ALLOW_MCC_GO_DIFF_BI_MIN ( 0 ) -#define CFG_ALLOW_MCC_GO_DIFF_BI_MAX ( 3 ) -#define CFG_ALLOW_MCC_GO_DIFF_BI_DEFAULT ( 2 ) +#define CFG_ALLOW_MCC_GO_DIFF_BI_MAX ( 4 ) +#define CFG_ALLOW_MCC_GO_DIFF_BI_DEFAULT ( 4 ) /* * Enable/Disable Thermal Mitigation feature @@ -1561,7 +1601,7 @@ typedef enum #define CFG_TDLS_IMPLICIT_TRIGGER_DEFAULT ( 0 ) #define CFG_TDLS_TX_STATS_PERIOD "gTDLSTxStatsPeriod" -#define CFG_TDLS_TX_STATS_PERIOD_MIN ( 2000 ) +#define CFG_TDLS_TX_STATS_PERIOD_MIN ( 10 ) #define CFG_TDLS_TX_STATS_PERIOD_MAX ( 4294967295UL ) #define CFG_TDLS_TX_STATS_PERIOD_DEFAULT ( 5000 ) @@ -1586,7 +1626,7 @@ typedef enum #define CFG_TDLS_IDLE_TIMEOUT_DEFAULT ( 5000 ) #define CFG_TDLS_IDLE_PACKET_THRESHOLD "gTDLSIdlePacketThreshold" -#define CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ( 1 ) +#define CFG_TDLS_IDLE_PACKET_THRESHOLD_MIN ( 0 ) #define CFG_TDLS_IDLE_PACKET_THRESHOLD_MAX ( 40000 ) #define CFG_TDLS_IDLE_PACKET_THRESHOLD_DEFAULT ( 5 ) @@ -1604,6 +1644,11 @@ typedef enum #define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN ( -120 ) #define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX ( 0 ) #define CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_DEFAULT ( -75 ) + +#define CFG_TDLS_EXTERNAL_CONTROL "gTDLSExternalControl" +#define CFG_TDLS_EXTERNAL_CONTROL_MIN (0) +#define CFG_TDLS_EXTERNAL_CONTROL_MAX (1) +#define CFG_TDLS_EXTERNAL_CONTROL_DEFAULT (0) #endif #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE @@ -1674,8 +1719,73 @@ typedef enum #define CFG_DISABLE_LDPC_WITH_TXBF_AP "gDisableLDPCWithTxbfAP" #define CFG_DISABLE_LDPC_WITH_TXBF_AP_MIN ( 0 ) #define CFG_DISABLE_LDPC_WITH_TXBF_AP_MAX ( 1 ) -#define CFG_DISABLE_LDPC_WITH_TXBF_AP_DEFAULT ( 1 ) +#define CFG_DISABLE_LDPC_WITH_TXBF_AP_DEFAULT ( 0 ) #endif + +#define CFG_LIST_OF_NON_DFS_COUNTRY_CODE "gListOfNonDfsCountryCode" +#define CFG_LIST_OF_NON_DFS_COUNTRY_CODE_DEFAULT "JO,MA" + +/* + * IBSS Operating Channels for 2.4G and 5GHz channels + */ +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_NAME "gAdHocChannel5G" +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_MIN ( 36 ) +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_MAX ( 165 ) +#define CFG_IBSS_ADHOC_CHANNEL_5GHZ_DEFAULT ( 44 ) + +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_NAME "gAdHocChannel24G" +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_MIN ( 1 ) +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_MAX ( 14 ) +#define CFG_IBSS_ADHOC_CHANNEL_24GHZ_DEFAULT ( 6 ) + +#define CFG_LIST_OF_NON_11AC_COUNTRY_CODE "gListOfNon11acCountryCode" +#define CFG_LIST_OF_NON_11AC_COUNTRY_CODE_DEFAULT "RU,UA,ZA" + +#define CFG_MAX_MEDIUM_TIME "gMaxMediumTime" +#define CFG_MAX_MEDIUM_TIME_STAMIN WNI_CFG_MAX_MEDIUM_TIME_STAMIN +#define CFG_MAX_MEDIUM_TIME_STAMAX WNI_CFG_MAX_MEDIUM_TIME_STAMAX +#define CFG_MAX_MEDIUM_TIME_STADEFAULT WNI_CFG_MAX_MEDIUM_TIME_STADEF + +/* + * SAP/P2P-GO mode traffic monitor + */ +#define CFG_ENABLE_TRAFFIC_MONITOR "gEnableTrafficMonitor" +#define CFG_ENABLE_TRAFFIC_MONITOR_MIN ( 0 ) +#define CFG_ENABLE_TRAFFIC_MONITOR_MAX ( 1 ) +#define CFG_ENABLE_TRAFFIC_MONITOR_DEFAULT ( 0 ) + +#define CFG_TRAFFIC_IDLE_TIMEOUT "gTrafficIdleTimeout" +#define CFG_TRAFFIC_IDLE_TIMEOUT_MIN ( 3000 ) +#define CFG_TRAFFIC_IDLE_TIMEOUT_MAX ( 10000 ) +#define CFG_TRAFFIC_IDLE_TIMEOUT_DEFAULT ( 5000 ) + +//Macro to enable/disable dynamic timer +#define CFG_DYNAMIC_SPLIT_SCAN_NAME "gEnableDynSplitScan" +#define CFG_DYNAMIC_SPLIT_SCAN_MIN ( 0 ) +#define CFG_DYNAMIC_SPLIT_SCAN_MAX ( 1 ) +#define CFG_DYNAMIC_SPLIT_SCAN_DEFAULT ( 1 ) + +//Macro to monitor the packet count +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_NAME "gSplitScanTxRxThreshold" +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_MIN ( 10 ) +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_MAX ( 100 ) +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_DEFAULT ( 50 ) +//Macro to handle the monitor timer value in milliseconds +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_NAME "gSplitScanTxRxTimer" +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_MIN ( 1000 ) +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_MAX ( 10000 ) +#define CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_DEFAULT ( 5000 ) + +#define CFG_RA_FILTER_ENABLE_NAME "gRAFilterEnable" +#define CFG_RA_FILTER_ENABLE_DEFAULT (1) +#define CFG_RA_FILTER_ENABLE_MIN (0) +#define CFG_RA_FILTER_ENABLE_MAX (1) + +#define CFG_RA_RATE_LIMIT_INTERVAL_NAME "gRARateLimitInterval" +#define CFG_RA_RATE_LIMIT_INTERVAL_DEFAULT (60) +#define CFG_RA_RATE_LIMIT_INTERVAL_MIN (0) +#define CFG_RA_RATE_LIMIT_INTERVAL_MAX (60) + /*--------------------------------------------------------------------------- Type declarations -------------------------------------------------------------------------*/ @@ -1833,14 +1943,17 @@ typedef struct v_U32_t nActiveMinChnTimeConc; //in units of milliseconds v_U32_t nActiveMaxChnTimeConc; //in units of milliseconds v_U32_t nRestTimeConc; //in units of milliseconds - v_U8_t nNumChanCombinedConc; //number of channels combined - //in each split scan operation + v_U8_t nNumStaChanCombinedConc; //number of channels combined for + //STA in each split scan operation + v_U8_t nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation #endif v_U8_t nMaxPsPoll; v_U8_t nRssiFilterPeriod; v_BOOL_t fIgnoreDtim; + v_U8_t fMaxLIModulatedDTIM; v_U8_t nRxAnt; v_U8_t fEnableFwHeartBeatMonitoring; @@ -1873,10 +1986,20 @@ typedef struct v_BOOL_t isFastTransitionEnabled; v_U8_t RoamRssiDiff; v_U8_t nImmediateRoamRssiDiff; + v_BOOL_t isWESModeEnabled; #endif #ifdef FEATURE_WLAN_OKC v_BOOL_t isOkcIniFeatureEnabled; #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + v_BOOL_t isRoamOffloadScanEnabled; +#endif + //TX and RX traffic threshold for split scan + v_U8_t txRxThresholdForSplitScan; + v_U8_t dynSplitscan; //Enable/Disable dynamic + //splitscan + //Traffic monitor timer for split scan + v_U32_t trafficMntrTmrForSplitScan; hdd_wmm_classification_t PktClassificationBasis; // DSCP or 802.1Q v_BOOL_t bImplicitQosEnabled; @@ -1924,6 +2047,7 @@ typedef struct v_BOOL_t bSingleTidRc; v_U8_t mcastBcastFilterSetting; v_BOOL_t fhostArpOffload; + v_BOOL_t fhostNSOffload; v_BOOL_t burstSizeDefinition; v_U8_t tsInfoAckPolicy; @@ -1980,6 +2104,8 @@ typedef struct #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) v_BOOL_t nRoamPrefer5GHz; v_BOOL_t nRoamIntraBand; + v_U8_t nProbes; + v_U16_t nRoamScanHomeAwayTime; #endif v_S31_t linkSpeedRssiMid; v_S31_t linkSpeedRssiLow; @@ -1987,9 +2113,6 @@ typedef struct v_U8_t allowMCCGODiffBI; v_BOOL_t isP2pDeviceAddrAdministrated; v_U8_t thermalMitigationEnable; -#ifdef WLAN_FEATURE_PACKET_FILTERING - v_BOOL_t isMcAddrListFilter; -#endif #ifdef WLAN_FEATURE_11AC v_U8_t vhtChannelWidth; v_U8_t vhtRxMCS; @@ -2004,7 +2127,6 @@ typedef struct v_BOOL_t ignoreDynamicDtimInP2pMode; v_U16_t configMccParam; v_U32_t numBuffAdvert; - v_U8_t ignore_chan165; v_BOOL_t enableRxSTBC; #ifdef FEATURE_WLAN_TDLS v_BOOL_t fEnableTDLSSupport; @@ -2018,6 +2140,7 @@ typedef struct v_U32_t fTDLSRSSIHysteresis; v_S31_t fTDLSRSSITriggerThreshold; v_S31_t fTDLSRSSITeardownThreshold; + v_BOOL_t fTDLSExternalControl; #endif v_U32_t enableLpwrImgTransition; #ifdef WLAN_SOFTAP_VSTA_FEATURE @@ -2035,6 +2158,15 @@ typedef struct v_U8_t retryLimitZero; v_U8_t retryLimitOne; v_U8_t retryLimitTwo; + v_U8_t disableAggWithBtc; + char listOfNonDfsCountryCode[128]; + v_BOOL_t enableSSR; + char listOfNon11acCountryCode[128]; + v_U32_t cfgMaxMediumTime; + v_U8_t enableTrafficMonitor; + v_U32_t trafficIdleTimeout; + v_BOOL_t cfgRAFilterEnable; + v_U16_t cfgRARateLimitInterval; } hdd_config_t; /*--------------------------------------------------------------------------- Function declarations and documenation diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h index 2468a5bb28b..638ef073ca5 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_cfg80211.h @@ -77,12 +77,6 @@ #define P2P_ACTION_FRAME "\x7f\x50\x6f\x9a\x09" #define P2P_ACTION_FRAME_SIZE 5 -#define SA_QUERY_FRAME_REQ "\x08\x00" -#define SA_QUERY_FRAME_REQ_SIZE 2 - -#define SA_QUERY_FRAME_RSP "\x08\x01" -#define SA_QUERY_FRAME_RSP_SIZE 2 - #define HDD_P2P_WILDCARD_SSID "DIRECT-" //TODO Put it in proper place; #define HDD_P2P_WILDCARD_SSID_LEN 7 @@ -156,6 +150,7 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, struct regulatory_request *r int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg); extern v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx, eConnectionState connState ); +VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel); #ifdef FEATURE_WLAN_TDLS int wlan_hdd_cfg80211_send_tdls_discover_req(struct wiphy *wiphy, struct net_device *dev, u8 *peer); diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h old mode 100644 new mode 100755 index afdf2638d3c..4c8c3075131 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_main.h @@ -101,14 +101,15 @@ #endif /** Hdd Default MTU */ #define HDD_DEFAULT_MTU (1500) + /**event flags registered net device*/ -#define NET_DEVICE_REGISTERED (1<<0) -#define SME_SESSION_OPENED (1<<1) -#define INIT_TX_RX_SUCCESS (1<<2) -#define WMM_INIT_DONE (1<<3) -#define SOFTAP_BSS_STARTED (1<<4) -#define DEVICE_IFACE_OPENED (1<<5) -#define TDLS_INIT_DONE (1<<6) +#define NET_DEVICE_REGISTERED (0) +#define SME_SESSION_OPENED (1) +#define INIT_TX_RX_SUCCESS (2) +#define WMM_INIT_DONE (3) +#define SOFTAP_BSS_STARTED (4) +#define DEVICE_IFACE_OPENED (5) +#define TDLS_INIT_DONE (6) /** Maximum time(ms)to wait for disconnect to complete **/ #define WLAN_WAIT_TIME_DISCONNECT 500 @@ -129,6 +130,8 @@ /** Maximum time(ms) to wait for tdls mgmt to complete **/ #define WAIT_TIME_TDLS_MGMT 11000 +/** Maximum time(ms) to wait for tdls initiator to start direct communication **/ +#define WAIT_TIME_TDLS_INITIATOR 600 /* Maximum time to get crda entry settings */ #define CRDA_WAIT_TIME 300 @@ -162,17 +165,22 @@ #define WLAN_HDD_P2P_SOCIAL_CHANNELS 3 #define WLAN_HDD_P2P_SINGLE_CHANNEL_SCAN 1 -#ifdef WLAN_FEATURE_11W -#define WLAN_HDD_SA_QUERY_ACTION_FRAME 8 -#endif +#define WLAN_HDD_IS_SOCIAL_CHANNEL(center_freq) \ +(((center_freq) == 2412) || ((center_freq) == 2437) || ((center_freq) == 2462)) + +#define WLAN_HDD_CHANNEL_IN_UNII_1_BAND(center_freq) \ +(((center_freq) == 5180 ) || ((center_freq) == 5200) \ +|| ((center_freq) == 5220) || ((center_freq) == 5240)) #define WLAN_HDD_PUBLIC_ACTION_TDLS_DISC_RESP 14 #define WLAN_HDD_TDLS_ACTION_FRAME 12 #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK -#define HDD_WAKE_LOCK_DURATION msecs_to_jiffies(50) +#define HDD_WAKE_LOCK_DURATION 50 //in msecs #endif -#define HDD_SAP_WAKE_LOCK_DURATION 10000 //10 sec +#define HDD_SAP_WAKE_LOCK_DURATION 10000 //in msecs + +#define HDD_MOD_EXIT_SSR_MAX_RETRIES 30 /* Maximum number of interfaces allowed(STA, P2P Device, P2P Interface) */ #define WLAN_MAX_INTERFACES 3 @@ -182,6 +190,9 @@ #define GTK_OFFLOAD_DISABLE 1 #endif +#define HDD_MAC_ADDR_LEN 6 +typedef v_U8_t tWlanHddMacAddr[HDD_MAC_ADDR_LEN]; + typedef struct hdd_tx_rx_stats_s { // start_xmit stats @@ -214,6 +225,8 @@ typedef struct hdd_tx_rx_stats_s __u32 rxDropped; __u32 rxDelivered; __u32 rxRefused; + __u32 pkt_tx_count; //TX pkt Counter used for dynamic splitscan + __u32 pkt_rx_count; //RX pkt Counter used for dynamic splitscan } hdd_tx_rx_stats_t; typedef struct hdd_chip_reset_stats_s @@ -226,14 +239,6 @@ typedef struct hdd_chip_reset_stats_s __u32 totalUnknownExceptions; } hdd_chip_reset_stats_t; -#ifdef WLAN_FEATURE_11W -typedef struct hdd_pmf_stats_s -{ - uint8 numUnprotDeauthRx; - uint8 numUnprotDisassocRx; -} hdd_pmf_stats_t; -#endif - typedef struct hdd_stats_s { tCsrSummaryStatsInfo summary_stat; @@ -244,9 +249,6 @@ typedef struct hdd_stats_s tCsrPerStaStatsInfo perStaStats; hdd_tx_rx_stats_t hddTxRxStats; hdd_chip_reset_stats_t hddChipResetStats; -#ifdef WLAN_FEATURE_11W - hdd_pmf_stats_t hddPmfStats; -#endif } hdd_stats_t; typedef enum @@ -273,6 +275,12 @@ typedef struct roaming_info_s { HDD_ROAM_STATE roamingState; vos_event_t roamingEvent; + + tWlanHddMacAddr bssid; + tWlanHddMacAddr peerMac; + tANI_U32 roamId; + eRoamCmdStatus roamStatus; + v_BOOL_t deferKeyComplete; } roaming_info_t; @@ -522,8 +530,6 @@ struct hdd_station_ctx roaming_info_t roam_info; - v_BOOL_t bSendDisconnect; - #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) int ft_carrier_on; #endif @@ -676,6 +682,13 @@ struct hdd_adapter_s /** Handle to the network device */ struct net_device *dev; + +#ifdef WLAN_NS_OFFLOAD + /** IPv6 notifier callback for handling NS offload on change in IP */ + struct notifier_block ipv6_notifier; + bool ipv6_notifier_registered; + struct work_struct ipv6NotifierWorkQueue; +#endif //TODO Move this to sta Ctx struct wireless_dev wdev ; @@ -800,14 +813,6 @@ struct hdd_adapter_s v_BOOL_t higherDtimTransition; }; -typedef struct hdd_dynamic_mcbcfilter_s -{ - v_BOOL_t enableCfg; - v_U8_t mcastBcastFilterSetting; - v_BOOL_t enableSuspend; - v_U8_t mcBcFilterSuspend; -}hdd_dynamic_mcbcfilter_t; - #define WLAN_HDD_GET_STATION_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.station) #define WLAN_HDD_GET_AP_CTX_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap) #define WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter) (&(pAdapter)->sessionCtx.station.WextState) @@ -816,7 +821,12 @@ typedef struct hdd_dynamic_mcbcfilter_s #define WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter) (&(pAdapter)->sessionCtx.ap.HostapdState) #define WLAN_HDD_GET_CFG_STATE_PTR(pAdapter) (&(pAdapter)->cfg80211State) #ifdef FEATURE_WLAN_TDLS -#define WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter) ((tdlsCtx_t*)(pAdapter)->sessionCtx.station.pHddTdlsCtx) +#define WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter) \ + (((WLAN_HDD_INFRA_STATION != pAdapter->device_mode) && \ + (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode)) ? 0 : 1) +#define WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter) \ + ((WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter)) ? \ + (tdlsCtx_t*)(pAdapter)->sessionCtx.station.pHddTdlsCtx : NULL) #endif typedef struct hdd_adapter_list_node @@ -832,6 +842,15 @@ typedef struct hdd_priv_data_s int total_len; }hdd_priv_data_t; +typedef struct +{ + vos_timer_t trafficTimer; + atomic_t isActiveMode; + v_U8_t isInitialized; + vos_lock_t trafficLock; + v_TIME_t lastFrameTs; +}hdd_traffic_monitor_t; + /** Adapter stucture definition */ struct hdd_context_s @@ -932,8 +951,6 @@ struct hdd_context_s /* Number of times riva restarted */ v_U32_t hddRivaResetStats; - hdd_dynamic_mcbcfilter_t dynamic_mcbc_filter; - /* Can we allow AMP connection right now*/ v_BOOL_t isAmpAllowed; @@ -978,6 +995,37 @@ struct hdd_context_s tANI_U16 connected_peer_count; tdls_scan_context_t tdls_scan_ctxt; #endif + + hdd_traffic_monitor_t traffic_monitor; + + /* MC/BC Filter state variable + * This always contains the value that is currently + * configured + * */ + v_U8_t configuredMcastBcastFilter; + + v_U8_t sus_res_mcastbcast_filter; + + v_BOOL_t sus_res_mcastbcast_filter_valid; + + /* Use below lock to protect access to isSchedScanUpdatePending + * since it will be accessed in two different contexts. + */ + spinlock_t schedScan_lock; + + // Flag keeps track of wiphy suspend/resume + v_BOOL_t isWiphySuspended; + + // Indicates about pending sched_scan results + v_BOOL_t isSchedScanUpdatePending; + + /* + * TX_rx_pkt_count_timer + */ + vos_timer_t tx_rx_trafficTmr; + v_U8_t drvr_miracast; + v_U8_t issplitscan_enabled; + }; @@ -1036,6 +1084,7 @@ void hdd_abort_mac_scan(hdd_context_t *pHddCtx); void wlan_hdd_set_monitor_tx_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ); void hdd_cleanup_actionframe( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ); v_BOOL_t is_crda_regulatory_entry_valid(void); +void crda_regulatory_entry_default(v_U8_t *countryCode, int domain_id); void wlan_hdd_set_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode); void wlan_hdd_clear_concurrency_mode(hdd_context_t *pHddCtx, tVOS_CON_MODE mode); void wlan_hdd_reset_prob_rspies(hdd_adapter_t* pHostapdAdapter); @@ -1048,10 +1097,17 @@ void hdd_set_ssr_required(e_hdd_ssr_required value); VOS_STATUS hdd_enable_bmps_imps(hdd_context_t *pHddCtx); VOS_STATUS hdd_disable_bmps_imps(hdd_context_t *pHddCtx, tANI_U8 session_type); -eHalStatus hdd_smeCloseSessionCallback(void *pContext); void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy); VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx); void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx); void hdd_set_pwrparams(hdd_context_t *pHddCtx); void hdd_reset_pwrparams(hdd_context_t *pHddCtx); +int wlan_hdd_validate_context(hdd_context_t *pHddCtx); +#ifdef WLAN_FEATURE_PACKET_FILTERING +int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, tANI_U8 sessionId); +#endif +VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx); +#ifdef WLAN_NS_OFFLOAD +void hdd_ipv6_notifier_work_queue(struct work_struct *work); +#endif #endif // end #if !defined( WLAN_HDD_MAIN_H ) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h index 8bc873de978..ff4463a4b5d 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_p2p.h @@ -64,10 +64,6 @@ #define P2P_WILDCARD_SSID_LEN 7 #define P2P_WILDCARD_SSID "DIRECT-" -#ifdef WLAN_FEATURE_11W -#define WLAN_HDD_SET_WEP_FRM_FC(__fc__) ( (__fc__) = ((__fc__) | 0x40)) -#endif //WLAN_FEATURE_11W - enum hdd_rx_flags { HDD_RX_FLAG_DECRYPTED = 1 << 0, HDD_RX_FLAG_MMIC_STRIPPED = 1 << 1, diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_packet_filtering.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_packet_filtering.h index 70896530929..c2b36b66838 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_packet_filtering.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_packet_filtering.h @@ -36,10 +36,20 @@ #ifdef WLAN_FEATURE_PACKET_FILTERING + #define HDD_MAX_CMP_PER_PACKET_FILTER 5 +#define HDD_FILTER_IPV6_MC_UC 1 +#define HDD_FILTER_IPV6_MC 0 +#define HDD_FILTER_ID_IPV6_MC 10 +#define HDD_FILTER_ID_IPV6_UC 11 + +#define HDD_IPV6_MC_CMP_DATA 0x33 +#define HDD_IPV6_UC_CMP_DATA 0x01 +#define HDD_IPV6_CMP_DATA_0 0x86 +#define HDD_IPV6_CMP_DATA_1 0xDD -#define HDD_WLAN_MAC_ADDR_LEN 6 -#define HDD_MAX_NUM_MULTICAST_ADDRESS 10 +#define HDD_WLAN_MAC_ADDR_LEN 6 +#define HDD_MAX_NUM_MULTICAST_ADDRESS 10 typedef enum { diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h index 5b24ae8dd66..0810397b29b 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_power.h @@ -1,43 +1,28 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ +* Copyright (c) 2012 Qualcomm Atheros, Inc. +* All Rights Reserved. +* Qualcomm Atheros Confidential and Proprietary. +*/ #ifndef __WLAN_HDD_POWER_H #define __WLAN_HDD_POWER_H @@ -47,9 +32,9 @@ \file wlan_hdd_power.h \brief Linux HDD Power - Copyright 2008 (c) Qualcomm, Incorporated. + Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary. + Qualcomm Technologies Confidential and Proprietary. ==========================================================================*/ @@ -106,5 +91,17 @@ VOS_STATUS hdd_wlan_re_init(void); void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter); -VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t* pAdapter, v_BOOL_t fenable); +VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t* pAdapter, v_BOOL_t fenable); +/* + * Function: hdd_conf_hostoffload + * Central function to configure the supported offloads, + * either enable or disable them. + */ +void hdd_conf_hostoffload(hdd_adapter_t * pAdapter, v_BOOL_t fenable); +#ifdef WLAN_FEATURE_GTK_OFFLOAD +void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable); +#endif +#ifdef WLAN_NS_OFFLOAD +void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable); +#endif #endif // if !defined __WLAN_QCT_DRIVER_H diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h index ac3ca9611cb..bd470ac3883 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tdls.h @@ -51,6 +51,7 @@ should not be more than 2000 */ #define TDLS_CTX_MAGIC 0x54444c53 // "TDLS" #define TDLS_MAX_SCAN_SCHEDULE 10 +#define TDLS_MAX_SCAN_REJECT 5 #define TDLS_DELAY_SCAN_PER_CONNECTION 100 #define TDLS_IS_CONNECTED(peer) \ @@ -79,6 +80,7 @@ typedef struct struct cfg80211_scan_request *scan_request; int magic; int attempt; + int reject; struct delayed_work tdls_scan_work; } tdls_scan_context_t; @@ -122,19 +124,32 @@ typedef struct { tANI_U16 rssi_thres; } tdls_rssi_config_t; +struct _hddTdlsPeer_t; + +typedef struct { + tSirMacAddr macAddr; +} hddTdlsForcePeer_t; + typedef struct { struct list_head peer_list[256]; hdd_adapter_t *pAdapter; +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER vos_timer_t peerDiscoverTimer; +#endif vos_timer_t peerUpdateTimer; vos_timer_t peerDiscoveryTimeoutTimer; tdls_config_params_t threshold_config; tANI_S32 discovery_peer_cnt; tANI_U32 discovery_sent_cnt; tANI_S8 ap_rssi; + struct _hddTdlsPeer_t *curr_candidate; + struct work_struct implicit_setup; + v_U32_t magic; + hddTdlsForcePeer_t forcePeer[HDD_MAX_NUM_TDLS_STA]; + tANI_U8 forcePeerCnt; } tdlsCtx_t; -typedef struct { +typedef struct _hddTdlsPeer_t { struct list_head node; tdlsCtx_t *pHddTdlsCtx; tSirMacAddr peerMac; @@ -149,6 +164,7 @@ typedef struct { tANI_U16 tx_pkt; tANI_U16 rx_pkt; vos_timer_t peerIdleTimer; + vos_timer_t initiatorWaitTimeoutTimer; } hddTdlsPeer_t; typedef struct { @@ -174,6 +190,8 @@ int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId); hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac); +hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, u8 *mac); + hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac); int wlan_hdd_tdls_set_cap(hdd_adapter_t *pAdapter, u8* mac, tTDLSCapType cap); @@ -214,14 +232,12 @@ void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter); u8 wlan_hdd_tdls_is_peer_progress(hdd_adapter_t *pAdapter, u8 *mac); -u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8* mac, u8 skip_self); +hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8* mac, u8 skip_self, tANI_BOOLEAN mutexLock); void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, eTDLSSupportMode tdls_mode, v_BOOL_t bUpdateLast); -void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, hddTdlsPeer_t *curr_peer); - tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx); void wlan_hdd_tdls_check_power_save_prohibited(hdd_adapter_t *pAdapter); @@ -251,5 +267,8 @@ void wlan_hdd_tdls_indicate_teardown(hdd_adapter_t *pAdapter, hddTdlsPeer_t *curr_peer, tANI_U16 reason); +int wlan_hdd_tdls_add_force_peer(hdd_adapter_t *pAdapter, u8 *mac); + +int wlan_hdd_tdls_remove_force_peer(hdd_adapter_t *pAdapter, u8 *mac); #endif // __HDD_TDSL_H diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h index efd8e22e983..13d17f17886 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_tx_rx.h @@ -254,4 +254,12 @@ void hdd_mon_tx_mgmt_pkt(hdd_adapter_t* pAdapter); ===========================================================================*/ void hdd_mon_tx_work_queue(struct work_struct *work); +/**============================================================================ + @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() - + Timer handler to check enable/disable split scan + @param pHddStaCtx : Hdd adapter + @return : VOS_STATUS_SUCCESS/VOS_STATUS_E_FAILURE + ===========================================================================*/ +void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *pAdapter); + #endif // end #if !defined( WLAN_HDD_TX_RX_H ) diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h index fbd2c145387..07135f8454b 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wext.h @@ -412,6 +412,9 @@ VOS_STATUS wlan_hdd_get_classAstats(hdd_adapter_t *pAdapter); VOS_STATUS wlan_hdd_get_station_stats(hdd_adapter_t *pAdapter); VOS_STATUS wlan_hdd_get_rssi(hdd_adapter_t *pAdapter, v_S7_t *rssi_value); + +void hdd_wmm_tx_snapshot(hdd_adapter_t *pAdapter); + #ifdef FEATURE_WLAN_TDLS VOS_STATUS iw_set_tdls_params(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra, int nOffset); #endif diff --git a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wowl.h b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wowl.h index 1725c59642f..d2d672d3ecb 100644 --- a/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wowl.h +++ b/drivers/staging/prima/CORE/HDD/inc/wlan_hdd_wowl.h @@ -180,4 +180,11 @@ v_BOOL_t hdd_exit_wowl (hdd_adapter_t*pAdapter); ===========================================================================*/ v_BOOL_t hdd_init_wowl (hdd_adapter_t* pAdapter); +/**============================================================================ + @brief hdd_parse_hex() - function returns integer equivalent of hexa decimal + + @return : integer equivalent of hexa decimal + ===========================================================================*/ +int hdd_parse_hex(unsigned char c); + #endif /* #ifndef _WLAN_HDD_WOWL_H */ diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c old mode 100644 new mode 100755 index 6f5798738fa..e235595251e --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_assoc.c @@ -109,9 +109,6 @@ v_U8_t ccpRSNOui05[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x05 }; // WEP-104 #ifdef FEATURE_WLAN_CCX v_U8_t ccpRSNOui06[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x40, 0x96, 0x00 }; // CCKM #endif /* FEATURE_WLAN_CCX */ -#ifdef WLAN_FEATURE_11W -v_U8_t ccpRSNOui07[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x06 }; // RSN-PSK-SHA256 -#endif #if defined(WLAN_FEATURE_VOWIFI_11R) // Offset where the EID-Len-IE, start. @@ -121,12 +118,11 @@ v_U8_t ccpRSNOui07[ HDD_RSN_OUI_SIZE ] = { 0x00, 0x0F, 0xAC, 0x06 }; // RSN-PSK- #define BEACON_FRAME_IES_OFFSET 12 -#ifdef WLAN_FEATURE_11W -void hdd_indicateUnprotMgmtFrame(hdd_adapter_t *pAdapter, - tANI_U32 nFrameLength, - tANI_U8* pbFrames, - tANI_U8 frameType ); -#endif +static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, + tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, + eRoamCmdStatus roamStatus, + eCsrRoamResult roamResult ); v_VOID_t hdd_connSetConnectionState( hdd_station_ctx_t *pHddStaCtx, eConnectionState connState ) @@ -299,6 +295,9 @@ void hdd_connSaveConnectInfo( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, // Save the ssid for the connection vos_mem_copy( &pHddStaCtx->conn_info.SSID.SSID, &pRoamInfo->u.pConnectedProfile->SSID, sizeof( tSirMacSSid ) ); + + // Save dot11mode in which STA associated to AP + pHddStaCtx->conn_info.dot11Mode = pRoamInfo->u.pConnectedProfile->dot11Mode; } } @@ -392,7 +391,6 @@ void hdd_SendFTEvent(hdd_adapter_t *pAdapter) struct cfg80211_ft_event_params ftEvent; v_U8_t ftIe[DOT11F_IE_FTINFO_MAX_LEN]; v_U8_t ricIe[DOT11F_IE_RICDESCRIPTOR_MAX_LEN]; - v_U8_t target_ap[SIR_MAC_ADDR_LENGTH]; struct net_device *dev = pAdapter->dev; #else char *buff; @@ -426,9 +424,9 @@ void hdd_SendFTEvent(hdd_adapter_t *pAdapter) return; } - vos_mem_copy(target_ap, ftIe, SIR_MAC_ADDR_LENGTH); + sme_SetFTPreAuthState(pHddCtx->hHal, TRUE); - ftEvent.target_ap = target_ap; + ftEvent.target_ap = ftIe; ftEvent.ies = (u8 *)(ftIe + SIR_MAC_ADDR_LENGTH); ftEvent.ies_len = auth_resp_len - SIR_MAC_ADDR_LENGTH; @@ -807,10 +805,8 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * //Enable BMPS // In case of JB, as Change-Iface may or maynot be called for p2p0 - // Enable BMPS/IMPS in case P2P_CLIENT disconnected - if(((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) && - (vos_concurrent_sessions_running())) + // Enable BMPS/IMPS in case P2P_CLIENT disconnected + if(VOS_STATUS_SUCCESS == hdd_issta_p2p_clientconnected(pHddCtx)) { //Enable BMPS only of other Session is P2P Client hdd_context_t *pHddCtx = NULL; @@ -826,20 +822,12 @@ static eHalStatus hdd_DisConnectHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo * if((0 == pHddCtx->no_of_sessions[VOS_STA_SAP_MODE]) && (0 == pHddCtx->no_of_sessions[VOS_P2P_GO_MODE])) { - if (pHddCtx->hdd_wlan_suspended) - { - if(WLAN_HDD_INFRA_STATION == pAdapter->device_mode) - { - hdd_reset_pwrparams(pHddCtx); - } - else - { - hdd_set_pwrparams(pHddCtx); - } - } - + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } hdd_enable_bmps_imps(pHddCtx); - } + } } } } @@ -892,7 +880,8 @@ static VOS_STATUS hdd_roamRegisterSTA( hdd_adapter_t *pAdapter, v_BOOL_t fConnected; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - + hdd_config_t *cfg_param = pHddCtx->cfg_ini; + // Get the Station ID from the one saved during the assocation. staDesc.ucSTAId = staId; @@ -1008,35 +997,39 @@ static VOS_STATUS hdd_roamRegisterSTA( hdd_adapter_t *pAdapter, return vosStatus; } - // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver, - // then go to 'authenticated'. For all other authentication types (those that do - // not require upper layer authentication) we can put TL directly into 'authenticated' - // state. - + if ( cfg_param->dynSplitscan && + ( VOS_TIMER_STATE_RUNNING != + vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))) + { + vos_timer_start(&pHddCtx->tx_rx_trafficTmr, + cfg_param->trafficMntrTmrForSplitScan); + } + // if (WPA), tell TL to go to 'connected' and after keys come to the driver, + // then go to 'authenticated'. For all other authentication types + // (those that donot require upper layer authentication) we can put + // TL directly into 'authenticated' state. + VOS_ASSERT( fConnected ); - + if ( !pRoamInfo->fAuthRequired ) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, - "open/shared auth StaId= %d. Changing TL state to AUTHENTICATED at Join time", pHddStaCtx->conn_info.staId[ 0 ] ); - // Connections that do not need Upper layer auth, transition TL directly - // to 'Authenticated' state. - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId, + // to 'Authenticated' state. + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId, WLANTL_STA_AUTHENTICATED ); - + pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE; - } + } else { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, - "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", pHddStaCtx->conn_info.staId[ 0 ] ); - - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId, + "ULA auth StaId= %d. Changing TL state to CONNECTED at Join time", + pHddStaCtx->conn_info.staId[0] ); + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, staDesc.ucSTAId, WLANTL_STA_CONNECTED ); - pHddStaCtx->conn_info.uIsAuthenticated = VOS_FALSE; - } + } + return( vosStatus ); } @@ -1093,8 +1086,33 @@ static void hdd_SendReAssocEvent(struct net_device *dev, hdd_adapter_t *pAdapter kfree(rspRsnIe); } -static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, - tANI_U32 roamId, eRoamCmdStatus roamStatus, +void hdd_PerformRoamSetKeyComplete(hdd_adapter_t *pAdapter) +{ + eHalStatus halStatus = eHAL_STATUS_SUCCESS; + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + tCsrRoamInfo roamInfo; + roamInfo.fAuthRequired = FALSE; + vos_mem_copy(roamInfo.bssid, + pHddStaCtx->roam_info.bssid, + WNI_CFG_BSSID_LEN); + vos_mem_copy(roamInfo.peerMac, + pHddStaCtx->roam_info.peerMac, + WNI_CFG_BSSID_LEN); + + halStatus = hdd_RoamSetKeyCompleteHandler(pAdapter, + &roamInfo, + pHddStaCtx->roam_info.roamId, + pHddStaCtx->roam_info.roamStatus, + eCSR_ROAM_RESULT_AUTHENTICATED); + if (halStatus != eHAL_STATUS_SUCCESS) + { + hddLog(LOGE, "%s: Set Key complete failure", __func__); + } + pHddStaCtx->roam_info.deferKeyComplete = FALSE; +} + +static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + tANI_U32 roamId, eRoamCmdStatus roamStatus, eCsrRoamResult roamResult ) { struct net_device *dev = pAdapter->dev; @@ -1257,6 +1275,21 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs cfg80211_roamed(dev,chan, pRoamInfo->bssid, pFTAssocReq, assocReqlen, pFTAssocRsp, assocRsplen, GFP_KERNEL); + if (sme_GetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + sme_SetFTPTKState(WLAN_HDD_GET_HAL_CTX(pAdapter), FALSE); + pRoamInfo->fAuthRequired = FALSE; + + vos_mem_copy(pHddStaCtx->roam_info.bssid, + pRoamInfo->bssid, + HDD_MAC_ADDR_LEN); + vos_mem_copy(pHddStaCtx->roam_info.peerMac, + pRoamInfo->peerMac, + HDD_MAC_ADDR_LEN); + pHddStaCtx->roam_info.roamId = roamId; + pHddStaCtx->roam_info.roamStatus = roamStatus; + pHddStaCtx->roam_info.deferKeyComplete = TRUE; + } } else { @@ -1267,7 +1300,6 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs pFTAssocRsp, assocRsplen, WLAN_STATUS_SUCCESS, GFP_KERNEL); - cfg80211_put_bss(bss); } } else @@ -1297,9 +1329,9 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs WLAN_STATUS_SUCCESS, GFP_KERNEL); - cfg80211_put_bss(bss); } } + cfg80211_put_bss(bss); // Register the Station with TL after associated... vosStatus = hdd_roamRegisterSTA( pAdapter, pRoamInfo, @@ -1320,8 +1352,12 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs //Reassoc successfully if( pRoamInfo->fAuthRequired ) { - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ], - WLANTL_STA_CONNECTED ); + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, + pHddStaCtx->conn_info.staId[ 0 ], + WLANTL_STA_CONNECTED ); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: staId: %d Changing TL state to CONNECTED", + __func__, pHddStaCtx->conn_info.staId[0]); pHddStaCtx->conn_info.uIsAuthenticated = VOS_FALSE; } else @@ -1329,8 +1365,9 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "%s: staId: %d Changing TL state to AUTHENTICATED", __func__, pHddStaCtx->conn_info.staId[ 0 ] ); - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ], - WLANTL_STA_AUTHENTICATED ); + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, + pHddStaCtx->conn_info.staId[ 0 ], + WLANTL_STA_AUTHENTICATED ); pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE; } } @@ -1346,10 +1383,7 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs "Cannot register STA with TL. Failed with vosStatus = %d [%08lX]", vosStatus, vosStatus ); } -#ifdef WLAN_FEATURE_11W - vos_mem_zero( &pAdapter->hdd_stats.hddPmfStats, - sizeof(pAdapter->hdd_stats.hddPmfStats) ); -#endif + // Start the Queue netif_tx_wake_all_queues(dev); } @@ -1398,24 +1432,16 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs if(NULL != pHddCtx) { - //Only P2P Client is there Enable Bmps back - if((0 == pHddCtx->no_of_sessions[VOS_STA_SAP_MODE]) && - (0 == pHddCtx->no_of_sessions[VOS_P2P_GO_MODE])) - { - if (pHddCtx->hdd_wlan_suspended) - { - if(WLAN_HDD_INFRA_STATION == pAdapter->device_mode) - { - hdd_reset_pwrparams(pHddCtx); - } - else + //Only P2P Client is there Enable Bmps back + if((0 == pHddCtx->no_of_sessions[VOS_STA_SAP_MODE]) && + (0 == pHddCtx->no_of_sessions[VOS_P2P_GO_MODE])) + { + if (pHddCtx->hdd_wlan_suspended) { - hdd_set_pwrparams(pHddCtx); + hdd_set_pwrparams(pHddCtx); } - } - - hdd_enable_bmps_imps(pHddCtx); - } + hdd_enable_bmps_imps(pHddCtx); + } } } } @@ -1458,7 +1484,6 @@ static eHalStatus hdd_AssociationCompletionHandler( hdd_adapter_t *pAdapter, tCs netif_tx_disable(dev); netif_carrier_off(dev); - } return eHAL_STATUS_SUCCESS; @@ -1627,6 +1652,12 @@ static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, tCsrRo hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); ENTER(); + + if (NULL == pRoamInfo) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "pRoamInfo is NULL"); + return eHAL_STATUS_FAILURE; + } // if ( WPA ), tell TL to go to 'authenticated' after the keys are set. // then go to 'authenticated'. For all other authentication types (those that do // not require upper layer authentication) we can put TL directly into 'authenticated' @@ -1636,27 +1667,32 @@ static eHalStatus hdd_RoamSetKeyCompleteHandler( hdd_adapter_t *pAdapter, tCsrRo if( fConnected ) { // TODO: Considering getting a state machine in HDD later. - // This routuine is invoked twice. 1)set PTK 2)set GTK. The folloing if statement will be - // TRUE when setting GTK. At this time we don't handle the state in detail. + // This routuine is invoked twice. 1)set PTK 2)set GTK. + // The folloing if statement will be TRUE when setting GTK. + // At this time we don't handle the state in detail. // Related CR: 174048 - TL not in authenticated state - if(( eCSR_ROAM_RESULT_AUTHENTICATED == roamResult ) && (pRoamInfo != NULL) && !pRoamInfo->fAuthRequired) + + if ( ( eCSR_ROAM_RESULT_AUTHENTICATED == roamResult ) && + (pRoamInfo != NULL) && !pRoamInfo->fAuthRequired ) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, - "Key set for StaId= %d. Changing TL state to AUTHENTICATED", pHddStaCtx->conn_info.staId[ 0 ] ); - - // Connections that do not need Upper layer authentication, transition TL - // to 'Authenticated' state after the keys are set. - vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, pHddStaCtx->conn_info.staId[ 0 ], + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_MED, "Key set " + "for StaId= %d. Changing TL state to AUTHENTICATED", + pHddStaCtx->conn_info.staId[ 0 ] ); + + // Connections that do not need Upper layer authentication, + // transition TL to 'Authenticated' state after the keys are set. + vosStatus = WLANTL_ChangeSTAState( pHddCtx->pvosContext, + pHddStaCtx->conn_info.staId[ 0 ], WLANTL_STA_AUTHENTICATED ); - + pHddStaCtx->conn_info.uIsAuthenticated = VOS_TRUE; } else { vosStatus = WLANTL_STAPtkInstalled( pHddCtx->pvosContext, - pHddStaCtx->conn_info.staId[ 0 ]); + pHddStaCtx->conn_info.staId[ 0 ]); } - + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; } else @@ -1826,6 +1862,8 @@ VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, WLAN_STADescType staDesc = {0}; eCsrEncryptionType connectedCipherAlgo = eCSR_ENCRYPT_TYPE_UNKNOWN; v_BOOL_t fConnected = FALSE; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *cfg_param = pHddCtx->cfg_ini; fConnected = hdd_connGetConnectedCipherAlgo( pHddStaCtx, &connectedCipherAlgo ); if (!fConnected) { @@ -1880,7 +1918,7 @@ VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, staDesc.ucIsReplayCheckValid = VOS_FALSE; #endif - staDesc.ucInitState = WLANTL_STA_AUTHENTICATED ; + staDesc.ucInitState = WLANTL_STA_CONNECTED ; /* Register the Station with TL... */ vosStatus = WLANTL_RegisterSTAClient( pVosContext, @@ -1891,11 +1929,19 @@ VOS_STATUS hdd_roamRegisterTDLSSTA( hdd_adapter_t *pAdapter, if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "WLANTL_RegisterSTAClient() failed to register. \ - Status= %d [0x%08lX]", vosStatus, vosStatus ); - return vosStatus; - } - + "%s: WLANTL_RegisterSTAClient() failed to register. \ + Status= %d [0x%08lX]", __func__, vosStatus, vosStatus ); + return vosStatus; + } + + if ( cfg_param->dynSplitscan && + ( VOS_TIMER_STATE_RUNNING != + vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)) ) + { + vos_timer_start(&pHddCtx->tx_rx_trafficTmr, + cfg_param->trafficMntrTmrForSplitScan); + } + return( vosStatus ); } @@ -1993,16 +2039,20 @@ eHalStatus hdd_RoamTdlsStatusUpdateHandler(hdd_adapter_t *pAdapter, } (WLAN_HDD_GET_CTX(pAdapter))->sta_to_adapter[pRoamInfo->staId] = pAdapter; - /* store the ucast signature which will be used later when - registering to TL - */ + /* store the ucast signature , if required for further reference. */ + wlan_hdd_tdls_set_signature( pAdapter, pRoamInfo->peerMac, pRoamInfo->ucastSig ); + /* start TDLS client registration with TL */ + status = hdd_roamRegisterTDLSSTA( pAdapter, + pRoamInfo->peerMac, + pRoamInfo->staId, + pRoamInfo->ucastSig); } else { status = eHAL_STATUS_FAILURE; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "no availalbe slot in conn_info. staId %d cannot be stored", pRoamInfo->staId); + "%s: no available slot in conn_info. staId %d cannot be stored", __func__, pRoamInfo->staId); } pAdapter->tdlsAddStaStatus = status; } @@ -2098,8 +2148,8 @@ eHalStatus hdd_RoamTdlsStatusUpdateHandler(hdd_adapter_t *pAdapter, status = eHAL_STATUS_SUCCESS ; } - wlan_hdd_tdls_check_bmps(pAdapter); } + wlan_hdd_tdls_check_bmps(pAdapter); break ; } default: @@ -2120,6 +2170,7 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 hdd_wext_state_t *pWextState = NULL; hdd_station_ctx_t *pHddStaCtx = NULL; VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx = NULL; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "CSR Callback: status= %d result= %d roamID=%ld", @@ -2135,8 +2186,9 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if ((NULL == pWextState) || (NULL == pHddStaCtx)) + if ((NULL == pWextState) || (NULL == pHddStaCtx) || (NULL == pHddCtx)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "invalid WEXT state or HDD station context"); @@ -2240,28 +2292,31 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 case eCSR_ROAM_LOSTLINK: case eCSR_ROAM_DISASSOCIATED: { - hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****eCSR_ROAM_DISASSOCIATED****"); halStatus = hdd_DisConnectHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); /* Check if Mcast/Bcast Filters are set, if yes clear the filters here */ - if ((WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set == TRUE) { - hdd_conf_mcastbcast_filter((WLAN_HDD_GET_CTX(pAdapter)), FALSE); - (WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set = FALSE; - } -#ifdef WLAN_FEATURE_PACKET_FILTERING - if (pHddCtx->cfg_ini->isMcAddrListFilter) + if (pHddCtx->hdd_mcastbcast_filter_set == TRUE) { - /*Multicast addr filtering is enabled*/ - if (pAdapter->mc_addr_list.isFilterApplied) - { - /*Filter applied during suspend mode*/ - /*Clear it here*/ - wlan_hdd_set_mc_addr_list(pAdapter, FALSE); - } + hdd_conf_mcastbcast_filter(pHddCtx, FALSE); + pHddCtx->configuredMcastBcastFilter = + pHddCtx->sus_res_mcastbcast_filter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE; + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: disassociation happening, restoring configuredMcastBcastFilter"); + hddLog(VOS_TRACE_LEVEL_INFO,"McastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: already called mcastbcast filter"); + (WLAN_HDD_GET_CTX(pAdapter))->hdd_mcastbcast_filter_set = FALSE; } +#ifdef WLAN_FEATURE_PACKET_FILTERING + /* Call to clear any MC Addr List filter applied after + * successful connection. + */ + wlan_hdd_set_mc_addr_list(pAdapter, FALSE); #endif - } break; case eCSR_ROAM_IBSS_LEAVE: @@ -2272,11 +2327,13 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 case eCSR_ROAM_ASSOCIATION_COMPLETION: VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "****eCSR_ROAM_ASSOCIATION_COMPLETION****"); - if ( (roamResult != eCSR_ROAM_RESULT_ASSOCIATED) - && ( (pWextState->roamProfile.EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) - || (pWextState->roamProfile.EncryptionType.encryptionType[0] == eCSR_ENCRYPT_TYPE_WEP104_STATICKEY) - ) - && (eCSR_AUTH_TYPE_SHARED_KEY != pWextState->roamProfile.AuthType.authType[0]) + if ( (roamResult != eCSR_ROAM_RESULT_ASSOCIATED) && + ( (pWextState->roamProfile.EncryptionType.encryptionType[0] == + eCSR_ENCRYPT_TYPE_WEP40) || + (pWextState->roamProfile.EncryptionType.encryptionType[0] == + eCSR_ENCRYPT_TYPE_WEP104) + ) && + (eCSR_AUTH_TYPE_SHARED_KEY != pWextState->roamProfile.AuthType.authType[0]) ) { v_U32_t roamId = 0; @@ -2303,7 +2360,7 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 case eCSR_ROAM_CONNECT_STATUS_UPDATE: halStatus = roamRoamConnectStatusUpdateHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); - break; + break; case eCSR_ROAM_MIC_ERROR_IND: halStatus = hdd_RoamMicErrorIndicationHandler( pAdapter, pRoamInfo, roamId, roamStatus, roamResult ); @@ -2314,11 +2371,6 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; if((pHddCtx) && - (pHddCtx->cfg_ini->enableDynamicDTIM || - pHddCtx->cfg_ini->enableModulatedDTIM) && - (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && - (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) && - (pHddCtx->cfg_ini->fIsBmpsEnabled) && (VOS_TRUE == pHddStaCtx->hdd_ReassocScenario) && (TRUE == pHddCtx->hdd_wlan_suspended) && (eCSR_ROAM_RESULT_NONE == roamResult)) @@ -2355,7 +2407,7 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 #endif #if defined(FEATURE_WLAN_LFR) && (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) case eCSR_ROAM_PMK_NOTIFY: - if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType) + if (eCSR_AUTH_TYPE_RSN == pHddStaCtx->conn_info.authType) { /* Notify the supplicant of a new candidate */ halStatus = wlan_hdd_cfg80211_pmksa_candidate_notify(pAdapter, pRoamInfo, 1, false); @@ -2386,13 +2438,6 @@ eHalStatus hdd_smeRoamCallback( void *pContext, tCsrRoamInfo *pRoamInfo, tANI_U3 case eCSR_ROAM_RESULT_MGMT_TX_COMPLETE_IND: wlan_hdd_tdls_mgmt_completion_callback(pAdapter, pRoamInfo->reasonCode); break; -#endif -#ifdef WLAN_FEATURE_11W - case eCSR_ROAM_UNPROT_MGMT_FRAME_IND: - hdd_indicateUnprotMgmtFrame(pAdapter, pRoamInfo->nFrameLength, - pRoamInfo->pbFrames, - pRoamInfo->frameType); - break; #endif default: break; @@ -2429,12 +2474,6 @@ eCsrAuthType hdd_TranslateRSNToCsrAuthType( u_int8_t auth_suite[4]) auth_type = eCSR_AUTH_TYPE_CCKM_RSN; } else #endif /* FEATURE_WLAN_CCX */ -#ifdef WLAN_FEATURE_11W - if (memcmp(auth_suite , ccpRSNOui07, 4) == 0) - { - auth_type = eCSR_AUTH_TYPE_RSN_PSK_SHA256; - } else -#endif { auth_type = eCSR_AUTH_TYPE_UNKNOWN; } @@ -2550,10 +2589,6 @@ static tANI_S32 hdd_ProcessGENIE(hdd_adapter_t *pAdapter, eCsrEncryptionType *pEncryptType, eCsrEncryptionType *mcEncryptType, eCsrAuthType *pAuthType, -#ifdef WLAN_FEATURE_11W - u_int8_t *pMfpRequired, - u_int8_t *pMfpCapable, -#endif u_int16_t gen_ie_len, u_int8_t *gen_ie) { @@ -2606,10 +2641,6 @@ static tANI_S32 hdd_ProcessGENIE(hdd_adapter_t *pAdapter, *pEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.pwise_cipher_suites[0]); //dot11RSNIE.gp_cipher_suite_count *mcEncryptType = hdd_TranslateRSNToCsrEncryptionType(dot11RSNIE.gp_cipher_suite); -#ifdef WLAN_FEATURE_11W - *pMfpRequired = (dot11RSNIE.RSN_Cap[0] >> 6) & 0x1 ; - *pMfpCapable = (dot11RSNIE.RSN_Cap[0] >> 7) & 0x1 ; -#endif // Set the PMKSA ID Cache for this interface for (i=0; iWPARSNIE[1]+2, pWextState->WPARSNIE); if (status == 0) @@ -2717,11 +2740,6 @@ int hdd_SetGENIEToCsr( hdd_adapter_t *pAdapter, eCsrAuthType *RSNAuthType) pWextState->roamProfile.EncryptionType.encryptionType[0] = RSNEncryptType; // Use the cipher type in the RSN IE pWextState->roamProfile.mcEncryptionType.encryptionType[0] = mcRSNEncryptType; - -#ifdef WLAN_FEATURE_11W - pWextState->roamProfile.MFPRequired = RSNMfpRequired; - pWextState->roamProfile.MFPCapable = RSNMfpCapable; -#endif hddLog( LOG1, "%s: CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d", __func__, *RSNAuthType, RSNEncryptType, mcRSNEncryptType); } return 0; @@ -2799,12 +2817,6 @@ int hdd_set_csr_auth_type ( hdd_adapter_t *pAdapter, eCsrAuthType RSNAuthType) } else #endif -#ifdef WLAN_FEATURE_11W - if (RSNAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) { - pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN_PSK_SHA256; - } else -#endif - if( (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X) == IW_AUTH_KEY_MGMT_802_1X) { pRoamProfile->AuthType.authType[0] = eCSR_AUTH_TYPE_RSN; @@ -3329,9 +3341,6 @@ int iw_get_auth(struct net_device *dev,struct iw_request_info *info, case eCSR_AUTH_TYPE_FT_RSN_PSK: #endif case eCSR_AUTH_TYPE_RSN_PSK: -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif hddLog(LOG1,"%s called with unknown auth type", __func__); wrqu->param.value = IW_AUTH_ALG_OPEN_SYSTEM; return -EIO; @@ -3460,77 +3469,3 @@ int iw_get_ap_address(struct net_device *dev, return 0; } -#ifdef WLAN_FEATURE_11W -/**--------------------------------------------------------------------------- - - \brief hdd_indicateUnprotMgmtFrame - - This function forwards the unprotected management frame to the supplicant - \param - pAdapter - Pointer to HDD adapter - - nFrameLength - Length of the unprotected frame being passed - - pbFrames - Pointer to the frame buffer - - frameType - 802.11 frame type - \return - nothing - - --------------------------------------------------------------------------*/ -void hdd_indicateUnprotMgmtFrame( hdd_adapter_t *pAdapter, - tANI_U32 nFrameLength, - tANI_U8* pbFrames, - tANI_U8 frameType ) -{ - tANI_U8 type = 0; - tANI_U8 subType = 0; - - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Frame Type = %d Frame Length = %d", - __func__, frameType, nFrameLength); - - /* Sanity Checks */ - if (NULL == pAdapter) - { - hddLog( LOGE, FL("pAdapter is NULL")); - return; - } - - if (NULL == pAdapter->dev) - { - hddLog( LOGE, FL("pAdapter->dev is NULL")); - return; - } - - if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) - { - hddLog( LOGE, FL("pAdapter has invalid magic")); - return; - } - - if( !nFrameLength ) - { - hddLog( LOGE, FL("Frame Length is Invalid ZERO")); - return; - } - - if (NULL == pbFrames) { - hddLog( LOGE, FL("pbFrames is NULL")); - return; - } - - type = WLAN_HDD_GET_TYPE_FRM_FC(pbFrames[0]); - subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(pbFrames[0]); - - /* Get pAdapter from Destination mac address of the frame */ - if (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_DISASSOC) - { - cfg80211_send_unprot_disassoc(pAdapter->dev, pbFrames, nFrameLength); - pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx++; - } - else if (type == SIR_MAC_MGMT_FRAME && subType == SIR_MAC_MGMT_DEAUTH) - { - cfg80211_send_unprot_deauth(pAdapter->dev, pbFrames, nFrameLength); - pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx++; - } - else - { - hddLog( LOGE, FL("Frame type %d and subtype %d are not valid"), type, subType); - return; - } -} -#endif diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c index cf18291155f..96796fafc87 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg.c @@ -97,10 +97,25 @@ static void cbNotifySetFastTransitionEnabled(hdd_context_t *pHddCtx, unsigned lo sme_UpdateFastTransitionEnabled((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->isFastTransitionEnabled); } +static void cbNotifySetWESMode(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + // at the point this routine is called, the value in the cfg_ini table has already been updated + sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->isWESModeEnabled); +} + static void cbNotifySetRoamIntraBand(hdd_context_t *pHddCtx, unsigned long NotifyId) { sme_setRoamIntraBand((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->nRoamIntraBand); } +static void cbNotifySetRoamScanNProbes(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->nProbes); +} + +static void cbNotifySetRoamScanHomeAwayTime(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->nRoamScanHomeAwayTime); +} #endif #ifdef FEATURE_WLAN_OKC @@ -170,6 +185,18 @@ static void cbNotifySetNeighborScanMaxChanTime(hdd_context_t *pHddCtx, unsigned } #endif +static void cbNotifySetEnableSSR(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateEnableSSR((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->enableSSR); +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +static void cbNotifyUpdateRoamScanOffloadEnabled(hdd_context_t *pHddCtx, unsigned long NotifyId) +{ + sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->isRoamOffloadScanEnabled); +} +#endif + REG_TABLE_ENTRY g_registry_table[] = { REG_VARIABLE( CFG_RTS_THRESHOLD_NAME, WLAN_PARAM_Integer, @@ -794,6 +821,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_RETRY_LIMIT_TWO_MIN, CFG_RETRY_LIMIT_TWO_MAX ), + REG_VARIABLE( CFG_DISABLE_AGG_WITH_BTC_NAME, WLAN_PARAM_Integer, + hdd_config_t, disableAggWithBtc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DISABLE_AGG_WITH_BTC_DEFAULT, + CFG_DISABLE_AGG_WITH_BTC_MIN, + CFG_DISABLE_AGG_WITH_BTC_MAX ), + #ifdef WLAN_AP_STA_CONCURRENCY REG_VARIABLE( CFG_PASSIVE_MAX_CHANNEL_TIME_CONC_NAME, WLAN_PARAM_Integer, hdd_config_t, nPassiveMaxChnTimeConc, @@ -830,12 +864,19 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_REST_TIME_CONC_MIN, CFG_REST_TIME_CONC_MAX ), - REG_VARIABLE( CFG_NUM_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, - hdd_config_t, nNumChanCombinedConc, + REG_VARIABLE( CFG_NUM_STA_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNumStaChanCombinedConc, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_NUM_CHAN_COMBINED_CONC_DEFAULT, - CFG_NUM_CHAN_COMBINED_CONC_MIN, - CFG_NUM_CHAN_COMBINED_CONC_MAX ), + CFG_NUM_STA_CHAN_COMBINED_CONC_DEFAULT, + CFG_NUM_STA_CHAN_COMBINED_CONC_MIN, + CFG_NUM_STA_CHAN_COMBINED_CONC_MAX ), + + REG_VARIABLE( CFG_NUM_P2P_CHAN_COMBINED_CONC_NAME, WLAN_PARAM_Integer, + hdd_config_t, nNumP2PChanCombinedConc, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_NUM_P2P_CHAN_COMBINED_CONC_DEFAULT, + CFG_NUM_P2P_CHAN_COMBINED_CONC_MIN, + CFG_NUM_P2P_CHAN_COMBINED_CONC_MAX ), #endif REG_VARIABLE( CFG_MAX_PS_POLL_NAME, WLAN_PARAM_Integer, @@ -873,6 +914,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_IGNORE_DTIM_MIN, CFG_IGNORE_DTIM_MAX ), + REG_VARIABLE( CFG_MAX_LI_MODULATED_DTIM_NAME, WLAN_PARAM_Integer, + hdd_config_t, fMaxLIModulatedDTIM, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_LI_MODULATED_DTIM_DEFAULT, + CFG_MAX_LI_MODULATED_DTIM_MIN, + CFG_MAX_LI_MODULATED_DTIM_MAX ), + REG_VARIABLE( CFG_RX_ANT_CONFIGURATION_NAME, WLAN_PARAM_Integer, hdd_config_t, nRxAnt, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -1023,8 +1071,8 @@ REG_TABLE_ENTRY g_registry_table[] = VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, CFG_LFR_FEATURE_ENABLED_DEFAULT, CFG_LFR_FEATURE_ENABLED_MIN, - CFG_LFR_FEATURE_ENABLED_MAX, - NotifyIsFastRoamIniFeatureEnabled, 0 ), + CFG_LFR_FEATURE_ENABLED_MAX, + NotifyIsFastRoamIniFeatureEnabled, 0 ), #endif // FEATURE_WLAN_LFR #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) @@ -1054,6 +1102,14 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_IMMEDIATE_ROAM_RSSI_DIFF_MIN, CFG_IMMEDIATE_ROAM_RSSI_DIFF_MAX, cbNotifySetImmediateRoamRssiDiff, 0), + + REG_DYNAMIC_VARIABLE( CFG_ENABLE_WES_MODE_NAME, WLAN_PARAM_Integer, + hdd_config_t, isWESModeEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_WES_MODE_NAME_DEFAULT, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX, + cbNotifySetWESMode, 0), #endif #ifdef FEATURE_WLAN_OKC REG_DYNAMIC_VARIABLE( CFG_OKC_FEATURE_ENABLED_NAME, WLAN_PARAM_Integer, @@ -1064,7 +1120,15 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_OKC_FEATURE_ENABLED_MAX, cbNotifySetOkcFeatureEnabled, 0 ), #endif - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_OFFLOAD_ENABLED, WLAN_PARAM_Integer, + hdd_config_t, isRoamOffloadScanEnabled, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_DEFAULT, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_MIN, + CFG_ROAM_SCAN_OFFLOAD_ENABLED_MAX, + cbNotifyUpdateRoamScanOffloadEnabled, 0), +#endif REG_VARIABLE( CFG_QOS_WMM_PKT_CLASSIFY_BASIS_NAME , WLAN_PARAM_Integer, hdd_config_t, PktClassificationBasis, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -1072,6 +1136,27 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MIN, CFG_QOS_WMM_PKT_CLASSIFY_BASIS_MAX ), + REG_VARIABLE( CFG_DYNAMIC_SPLIT_SCAN_NAME, WLAN_PARAM_Integer, + hdd_config_t, dynSplitscan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_DYNAMIC_SPLIT_SCAN_DEFAULT, + CFG_DYNAMIC_SPLIT_SCAN_MIN, + CFG_DYNAMIC_SPLIT_SCAN_MAX ), + + REG_VARIABLE( CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_NAME, WLAN_PARAM_Integer, + hdd_config_t, txRxThresholdForSplitScan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_DEFAULT, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_MIN, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_THRSHLD_MAX ), + + REG_VARIABLE( CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_NAME, WLAN_PARAM_Integer, + hdd_config_t, trafficMntrTmrForSplitScan, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_DEFAULT, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_MIN, + CFG_SPLIT_SCAN_TRAFFIC_MONITOR_TIMER_MAX ), + REG_VARIABLE( CFG_QOS_WMM_INFRA_DIR_AC_VO_NAME , WLAN_PARAM_Integer, hdd_config_t, InfraDirAcVo, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -1528,6 +1613,13 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_ENABLE_HOST_ARPOFFLOAD_MIN, CFG_ENABLE_HOST_ARPOFFLOAD_MAX ), + REG_VARIABLE( CFG_ENABLE_HOST_NSOFFLOAD_NAME, WLAN_PARAM_Integer, + hdd_config_t, fhostNSOffload, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_HOST_NSOFFLOAD_DEFAULT, + CFG_ENABLE_HOST_NSOFFLOAD_MIN, + CFG_ENABLE_HOST_NSOFFLOAD_MAX ), + REG_VARIABLE( CFG_QOS_WMM_TS_INFO_ACK_POLICY_NAME , WLAN_PARAM_HexInteger, hdd_config_t, tsInfoAckPolicy, VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, @@ -1861,6 +1953,22 @@ REG_TABLE_ENTRY g_registry_table[] = CFG_ROAM_INTRA_BAND_MAX, cbNotifySetRoamIntraBand, 0 ), + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_N_PROBES, WLAN_PARAM_Integer, + hdd_config_t, nProbes, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_N_PROBES_DEFAULT, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX, + cbNotifySetRoamScanNProbes, 0 ), + + REG_DYNAMIC_VARIABLE( CFG_ROAM_SCAN_HOME_AWAY_TIME, WLAN_PARAM_Integer, + hdd_config_t, nRoamScanHomeAwayTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX, + cbNotifySetRoamScanHomeAwayTime, 0 ), + #endif REG_VARIABLE( CFG_P2P_DEVICE_ADDRESS_ADMINISTRATED_NAME, WLAN_PARAM_Integer, @@ -1890,14 +1998,6 @@ REG_VARIABLE( CFG_THERMAL_MIGRATION_ENABLE_NAME, WLAN_PARAM_Integer, CFG_THERMAL_MIGRATION_ENABLE_DEFAULT, CFG_THERMAL_MIGRATION_ENABLE_MIN, CFG_THERMAL_MIGRATION_ENABLE_MAX ), -#ifdef WLAN_FEATURE_PACKET_FILTERING - REG_VARIABLE( CFG_MC_ADDR_LIST_FILTER_NAME, WLAN_PARAM_Integer, - hdd_config_t, isMcAddrListFilter, - VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_MC_ADDR_LIST_FILTER_DEFAULT, - CFG_MC_ADDR_LIST_FILTER_MIN, - CFG_MC_ADDR_LIST_FILTER_MAX ), -#endif REG_VARIABLE( CFG_ENABLE_MODULATED_DTIM_NAME, WLAN_PARAM_Integer, hdd_config_t, enableModulatedDTIM, @@ -1964,13 +2064,6 @@ REG_VARIABLE( CFG_NUM_BUFF_ADVERT_NAME, WLAN_PARAM_Integer, CFG_NUM_BUFF_ADVERT_MIN, CFG_NUM_BUFF_ADVERT_MAX ), - REG_VARIABLE( CFG_ENABLE_IGNORE_CHAN165, WLAN_PARAM_Integer, - hdd_config_t, ignore_chan165, - VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, - CFG_ENABLE_IGNORE_CHAN165_DEFAULT, - CFG_ENABLE_IGNORE_CHAN165_MIN, - CFG_ENABLE_IGNORE_CHAN165_MAX ), - REG_VARIABLE( CFG_MCC_CONFIG_PARAM_NAME, WLAN_PARAM_Integer, hdd_config_t, configMccParam, VAR_FLAGS_OPTIONAL, @@ -2060,6 +2153,12 @@ REG_VARIABLE( CFG_TDLS_RSSI_TEARDOWN_THRESHOLD, WLAN_PARAM_SignedInteger, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_DEFAULT, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MIN, CFG_TDLS_RSSI_TEARDOWN_THRESHOLD_MAX ), +REG_VARIABLE( CFG_TDLS_EXTERNAL_CONTROL, WLAN_PARAM_Integer, + hdd_config_t, fTDLSExternalControl, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TDLS_EXTERNAL_CONTROL_DEFAULT, + CFG_TDLS_EXTERNAL_CONTROL_MIN, + CFG_TDLS_EXTERNAL_CONTROL_MAX ), #endif #ifdef WLAN_SOFTAP_VSTA_FEATURE @@ -2152,6 +2251,59 @@ REG_VARIABLE( CFG_DISABLE_LDPC_WITH_TXBF_AP, WLAN_PARAM_Integer, CFG_DISABLE_LDPC_WITH_TXBF_AP_MIN, CFG_DISABLE_LDPC_WITH_TXBF_AP_MAX ), #endif + +REG_VARIABLE_STRING( CFG_LIST_OF_NON_DFS_COUNTRY_CODE, WLAN_PARAM_String, + hdd_config_t, listOfNonDfsCountryCode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + (void *)CFG_LIST_OF_NON_DFS_COUNTRY_CODE_DEFAULT), + + REG_DYNAMIC_VARIABLE( CFG_ENABLE_SSR, WLAN_PARAM_Integer, + hdd_config_t, enableSSR, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_SSR_DEFAULT, + CFG_ENABLE_SSR_MIN, + CFG_ENABLE_SSR_MAX, + cbNotifySetEnableSSR, 0 ), + +REG_VARIABLE_STRING( CFG_LIST_OF_NON_11AC_COUNTRY_CODE, WLAN_PARAM_String, + hdd_config_t, listOfNon11acCountryCode, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + (void *)CFG_LIST_OF_NON_11AC_COUNTRY_CODE_DEFAULT), + +REG_VARIABLE(CFG_MAX_MEDIUM_TIME, WLAN_PARAM_Integer, + hdd_config_t, cfgMaxMediumTime, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_MAX_MEDIUM_TIME_STADEFAULT, + CFG_MAX_MEDIUM_TIME_STAMIN, + CFG_MAX_MEDIUM_TIME_STAMAX ), + + REG_VARIABLE( CFG_ENABLE_TRAFFIC_MONITOR, WLAN_PARAM_Integer, + hdd_config_t, enableTrafficMonitor, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_ENABLE_TRAFFIC_MONITOR_DEFAULT, + CFG_ENABLE_TRAFFIC_MONITOR_MIN, + CFG_ENABLE_TRAFFIC_MONITOR_MAX), + + REG_VARIABLE( CFG_TRAFFIC_IDLE_TIMEOUT, WLAN_PARAM_Integer, + hdd_config_t, trafficIdleTimeout, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_TRAFFIC_IDLE_TIMEOUT_DEFAULT, + CFG_TRAFFIC_IDLE_TIMEOUT_MIN, + CFG_TRAFFIC_IDLE_TIMEOUT_MAX), + + REG_VARIABLE(CFG_RA_FILTER_ENABLE_NAME, WLAN_PARAM_Integer, + hdd_config_t, cfgRAFilterEnable, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RA_FILTER_ENABLE_DEFAULT, + CFG_RA_FILTER_ENABLE_MIN, + CFG_RA_FILTER_ENABLE_MAX ), + + REG_VARIABLE(CFG_RA_RATE_LIMIT_INTERVAL_NAME, WLAN_PARAM_Integer, + hdd_config_t, cfgRARateLimitInterval, + VAR_FLAGS_OPTIONAL | VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_RA_RATE_LIMIT_INTERVAL_DEFAULT, + CFG_RA_RATE_LIMIT_INTERVAL_MIN, + CFG_RA_RATE_LIMIT_INTERVAL_MAX ), }; /* @@ -2444,6 +2596,7 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [RoamRssiDiff] Value = [%lu] ",pHddCtx->cfg_ini->RoamRssiDiff); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ImmediateRoamRssiDiff] Value = [%lu] ",pHddCtx->cfg_ini->nImmediateRoamRssiDiff); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [isWESModeEnabled] Value = [%lu] ",pHddCtx->cfg_ini->isWESModeEnabled); #endif #ifdef FEATURE_WLAN_OKC VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [OkcEnabled] Value = [%lu] ",pHddCtx->cfg_ini->isOkcIniFeatureEnabled); @@ -2527,12 +2680,16 @@ static void print_hdd_cfg(hdd_context_t *pHddCtx) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [enableFirstScan2GOnly] Value = [%u] ",pHddCtx->cfg_ini->enableFirstScan2GOnly); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [skipDfsChnlInP2pSearch] Value = [%u] ",pHddCtx->cfg_ini->skipDfsChnlInP2pSearch); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [ignoreDynamicDtimInP2pMode] Value = [%u] ",pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gIgnore_Chan165] Value = [%u] ",pHddCtx->cfg_ini->ignore_chan165); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [enableRxSTBC] Value = [%u] ",pHddCtx->cfg_ini->enableRxSTBC); VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableLpwrImgTransition] Value = [%u] ",pHddCtx->cfg_ini->enableLpwrImgTransition); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableSSR] Value = [%u] ",pHddCtx->cfg_ini->enableSSR); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gEnableTrafficMonitor] Value = [%u] ", pHddCtx->cfg_ini->enableTrafficMonitor); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, "Name = [gTrafficIdleTimeout] Value = [%u] ", pHddCtx->cfg_ini->trafficIdleTimeout); } + #define CFG_VALUE_MAX_LEN 256 #define CFG_ENTRY_MAX_LEN (32+CFG_VALUE_MAX_LEN) VOS_STATUS hdd_cfg_get_config(hdd_context_t *pHddCtx, char *pBuf, int buflen) @@ -3031,14 +3188,11 @@ static void hdd_set_power_save_config(hdd_context_t *pHddCtx, tSmeConfigParams * { sme_StartAutoBmpsTimer(pHddCtx->hHal); } - } - #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 *len, tANI_U8 intArrayMaxLen ) { char *s = str; - if( str == NULL || intArray == NULL || len == NULL ) { return VOS_STATUS_E_INVAL; @@ -3059,13 +3213,9 @@ static VOS_STATUS hdd_string_to_u8_array( char *str, tANI_U8 *intArray, tANI_U8 if( s ) s++; } - return VOS_STATUS_SUCCESS; - } #endif - - v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) { v_BOOL_t fStatus = TRUE; @@ -3637,6 +3787,27 @@ v_BOOL_t hdd_update_config_dat( hdd_context_t *pHddCtx ) hddLog(LOGE, "Could not pass on WNI_CFG_DYNAMIC_THRESHOLD_TWO to CCM"); } + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_MAX_MEDIUM_TIME, pConfig->cfgMaxMediumTime, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_MAX_MEDIUM_TIME to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RA_FILTER_ENABLE, pConfig->cfgRAFilterEnable, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_RA_FILTER_ENABLE to CCM"); + } + + if (ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_RA_RATE_LIMIT_INTERVAL, pConfig->cfgRARateLimitInterval, + NULL, eANI_BOOLEAN_FALSE) == eHAL_STATUS_FAILURE) + { + fStatus = FALSE; + hddLog(LOGE, "Could not pass on WNI_CFG_RA_FILTER_ENABLE to CCM"); + } + return fStatus; } @@ -3702,13 +3873,16 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.nPassiveMinChnTime = pConfig->nPassiveMinChnTime; smeConfig.csrConfig.nActiveMaxChnTimeBtc = pConfig->nActiveMaxChnTimeBtc; smeConfig.csrConfig.nActiveMinChnTimeBtc = pConfig->nActiveMinChnTimeBtc; + smeConfig.csrConfig.disableAggWithBtc = pConfig->disableAggWithBtc; #ifdef WLAN_AP_STA_CONCURRENCY smeConfig.csrConfig.nActiveMaxChnTimeConc = pConfig->nActiveMaxChnTimeConc; smeConfig.csrConfig.nActiveMinChnTimeConc = pConfig->nActiveMinChnTimeConc; smeConfig.csrConfig.nPassiveMaxChnTimeConc = pConfig->nPassiveMaxChnTimeConc; smeConfig.csrConfig.nPassiveMinChnTimeConc = pConfig->nPassiveMinChnTimeConc; smeConfig.csrConfig.nRestTimeConc = pConfig->nRestTimeConc; - smeConfig.csrConfig.nNumChanCombinedConc = pConfig->nNumChanCombinedConc; + smeConfig.csrConfig.nNumStaChanCombinedConc = pConfig->nNumStaChanCombinedConc; + smeConfig.csrConfig.nNumP2PChanCombinedConc = pConfig->nNumP2PChanCombinedConc; + #endif smeConfig.csrConfig.Is11eSupportEnabled = pConfig->b80211eIsEnabled; smeConfig.csrConfig.WMMSupportMode = pConfig->WmmMode; @@ -3740,10 +3914,11 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.nTxPowerCap = pConfig->nTxPowerCap; smeConfig.csrConfig.fEnableBypass11d = pConfig->enableBypass11d; smeConfig.csrConfig.fEnableDFSChnlScan = pConfig->enableDFSChnlScan; - smeConfig.csrConfig.fIgnore_chan165 = pConfig->ignore_chan165; #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) smeConfig.csrConfig.nRoamPrefer5GHz = pConfig->nRoamPrefer5GHz; smeConfig.csrConfig.nRoamIntraBand = pConfig->nRoamIntraBand; + smeConfig.csrConfig.nProbes = pConfig->nProbes; + smeConfig.csrConfig.nRoamScanHomeAwayTime = pConfig->nRoamScanHomeAwayTime; #endif smeConfig.csrConfig.fFirstScanOnly2GChnl = pConfig->enableFirstScan2GOnly; @@ -3790,8 +3965,11 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.isFastTransitionEnabled = pConfig->isFastTransitionEnabled; smeConfig.csrConfig.RoamRssiDiff = pConfig->RoamRssiDiff; smeConfig.csrConfig.nImmediateRoamRssiDiff = pConfig->nImmediateRoamRssiDiff; + smeConfig.csrConfig.isWESModeEnabled = pConfig->isWESModeEnabled; +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + smeConfig.csrConfig.isRoamOffloadScanEnabled = pConfig->isRoamOffloadScanEnabled; #endif - #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING smeConfig.csrConfig.neighborRoamConfig.nNeighborReassocRssiThreshold = pConfig->nNeighborReassocRssiThreshold; smeConfig.csrConfig.neighborRoamConfig.nNeighborLookupRssiThreshold = pConfig->nNeighborLookupRssiThreshold; @@ -3806,7 +3984,6 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) &smeConfig.csrConfig.neighborRoamConfig.neighborScanChanList.numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN ); #endif - smeConfig.csrConfig.addTSWhenACMIsOff = pConfig->AddTSWhenACMIsOff; smeConfig.csrConfig.fValidateList = pConfig->fValidateScanList; @@ -3819,17 +3996,16 @@ VOS_STATUS hdd_set_sme_config( hdd_context_t *pHddCtx ) smeConfig.csrConfig.enableTxLdpc = pConfig->enableTxLdpc; + /* update SSR config */ + sme_UpdateEnableSSR((tHalHandle)(pHddCtx->hHal), pHddCtx->cfg_ini->enableSSR); + halStatus = sme_UpdateConfig( pHddCtx->hHal, &smeConfig); if ( !HAL_STATUS_SUCCESS( halStatus ) ) { status = VOS_STATUS_E_FAILURE; } - - return status; } - - /**--------------------------------------------------------------------------- \brief hdd_execute_config_command() - diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c index 3c81079b015..25b9f1a802e 100755 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_cfg80211.c @@ -1,43 +1,23 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /**======================================================================== @@ -45,9 +25,9 @@ \brief WLAN Host Device Driver implementation - Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved. + Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary. + Qualcomm Technologies Confidential and Proprietary. ========================================================================*/ @@ -150,7 +130,7 @@ #define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 #endif -static const u32 hdd_cipher_suites[] = +static const u32 hdd_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, @@ -165,9 +145,6 @@ static const u32 hdd_cipher_suites[] = #ifdef FEATURE_WLAN_WAPI WLAN_CIPHER_SUITE_SMS4, #endif -#ifdef WLAN_FEATURE_11W - WLAN_CIPHER_SUITE_AES_CMAC, -#endif }; static inline int is_broadcast_ether_addr(const u8 *addr) @@ -177,7 +154,7 @@ static inline int is_broadcast_ether_addr(const u8 *addr) } static struct ieee80211_channel hdd_channels_2_4_GHZ[] = -{ +{ HDD2GHZCHAN(2412, 1, 0) , HDD2GHZCHAN(2417, 2, 0) , HDD2GHZCHAN(2422, 3, 0) , @@ -236,66 +213,31 @@ static struct ieee80211_channel hdd_channels_5_GHZ[] = HDD5GHZCHAN(5825,165, 0) , }; -static struct ieee80211_channel hdd_channels_5_GHZ_FCC[] = -{ - HDD5GHZCHAN(4920, 240, 0) , - HDD5GHZCHAN(4940, 244, 0) , - HDD5GHZCHAN(4960, 248, 0) , - HDD5GHZCHAN(4980, 252, 0) , - HDD5GHZCHAN(5040, 208, 0) , - HDD5GHZCHAN(5060, 212, 0) , - HDD5GHZCHAN(5080, 216, 0) , - HDD5GHZCHAN(5180, 36, IEEE80211_CHAN_PASSIVE_SCAN) , - HDD5GHZCHAN(5200, 40, IEEE80211_CHAN_PASSIVE_SCAN) , - HDD5GHZCHAN(5220, 44, IEEE80211_CHAN_PASSIVE_SCAN) , - HDD5GHZCHAN(5240, 48, IEEE80211_CHAN_PASSIVE_SCAN) , - HDD5GHZCHAN(5260, 52, 0) , - HDD5GHZCHAN(5280, 56, 0) , - HDD5GHZCHAN(5300, 60, 0) , - HDD5GHZCHAN(5320, 64, 0) , - HDD5GHZCHAN(5500,100, 0) , - HDD5GHZCHAN(5520,104, 0) , - HDD5GHZCHAN(5540,108, 0) , - HDD5GHZCHAN(5560,112, 0) , - HDD5GHZCHAN(5580,116, 0) , - HDD5GHZCHAN(5600,120, 0) , - HDD5GHZCHAN(5620,124, 0) , - HDD5GHZCHAN(5640,128, 0) , - HDD5GHZCHAN(5660,132, 0) , - HDD5GHZCHAN(5680,136, 0) , - HDD5GHZCHAN(5700,140, 0) , - HDD5GHZCHAN(5745,149, 0) , - HDD5GHZCHAN(5765,153, 0) , - HDD5GHZCHAN(5785,157, 0) , - HDD5GHZCHAN(5805,161, 0) , - HDD5GHZCHAN(5825,165, 0) , -}; - static struct ieee80211_rate g_mode_rates[] = { - HDD_G_MODE_RATETAB(10, 0x1, 0), - HDD_G_MODE_RATETAB(20, 0x2, 0), - HDD_G_MODE_RATETAB(55, 0x4, 0), - HDD_G_MODE_RATETAB(110, 0x8, 0), - HDD_G_MODE_RATETAB(60, 0x10, 0), - HDD_G_MODE_RATETAB(90, 0x20, 0), - HDD_G_MODE_RATETAB(120, 0x40, 0), - HDD_G_MODE_RATETAB(180, 0x80, 0), - HDD_G_MODE_RATETAB(240, 0x100, 0), - HDD_G_MODE_RATETAB(360, 0x200, 0), - HDD_G_MODE_RATETAB(480, 0x400, 0), + HDD_G_MODE_RATETAB(10, 0x1, 0), + HDD_G_MODE_RATETAB(20, 0x2, 0), + HDD_G_MODE_RATETAB(55, 0x4, 0), + HDD_G_MODE_RATETAB(110, 0x8, 0), + HDD_G_MODE_RATETAB(60, 0x10, 0), + HDD_G_MODE_RATETAB(90, 0x20, 0), + HDD_G_MODE_RATETAB(120, 0x40, 0), + HDD_G_MODE_RATETAB(180, 0x80, 0), + HDD_G_MODE_RATETAB(240, 0x100, 0), + HDD_G_MODE_RATETAB(360, 0x200, 0), + HDD_G_MODE_RATETAB(480, 0x400, 0), HDD_G_MODE_RATETAB(540, 0x800, 0), -}; +}; static struct ieee80211_rate a_mode_rates[] = { - HDD_G_MODE_RATETAB(60, 0x10, 0), - HDD_G_MODE_RATETAB(90, 0x20, 0), - HDD_G_MODE_RATETAB(120, 0x40, 0), - HDD_G_MODE_RATETAB(180, 0x80, 0), - HDD_G_MODE_RATETAB(240, 0x100, 0), - HDD_G_MODE_RATETAB(360, 0x200, 0), - HDD_G_MODE_RATETAB(480, 0x400, 0), + HDD_G_MODE_RATETAB(60, 0x10, 0), + HDD_G_MODE_RATETAB(90, 0x20, 0), + HDD_G_MODE_RATETAB(120, 0x40, 0), + HDD_G_MODE_RATETAB(180, 0x80, 0), + HDD_G_MODE_RATETAB(240, 0x100, 0), + HDD_G_MODE_RATETAB(360, 0x200, 0), + HDD_G_MODE_RATETAB(480, 0x400, 0), HDD_G_MODE_RATETAB(540, 0x800, 0), }; @@ -358,7 +300,7 @@ static struct ieee80211_supported_band wlan_hdd_band_5_GHZ = .ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED, }; -/* This structure contain information what kind of frame are expected in +/* This structure contain information what kind of frame are expected in TX/RX direction for each kind of interface */ static const struct ieee80211_txrx_stypes wlan_hdd_txrx_stypes[NUM_NL80211_IFTYPES] = { @@ -509,12 +451,14 @@ static struct index_data_rate_type supported_mcs_rate[] = #ifdef WLAN_FEATURE_11AC -#define DATA_RATE_11AC_MCS_MASK 0x0F +#define DATA_RATE_11AC_MCS_MASK 0x03 struct index_vht_data_rate_type { v_U8_t beacon_rate_index; - v_U16_t supported_rate[2]; + v_U16_t supported_VHT80_rate[2]; + v_U16_t supported_VHT40_rate[2]; + v_U16_t supported_VHT20_rate[2]; }; typedef enum @@ -528,17 +472,17 @@ typedef enum /* MCS Based VHT rate table */ static struct index_vht_data_rate_type supported_vht_mcs_rate[] = { -/* MCS L80 S80 */ - {0, {293, 325}}, - {1, {585, 650}}, - {2, {878, 975}}, - {3, {1170, 1300}}, - {4, {1755, 1950}}, - {5, {2340, 2600}}, - {6, {2633, 2925}}, - {7, {2925, 3250}}, - {8, {3510, 3900}}, - {9, {3900, 4333}} +/* MCS L80 S80 L40 S40 L20 S40*/ + {0, {293, 325}, {135, 150}, {65, 72}}, + {1, {585, 650}, {270, 300}, {130, 144}}, + {2, {878, 975}, {405, 450}, {195, 217}}, + {3, {1170, 1300}, {540, 600}, {260, 289}}, + {4, {1755, 1950}, {810, 900}, {390, 433}}, + {5, {2340, 2600}, {1080, 1200}, {520, 578}}, + {6, {2633, 2925}, {1215, 1350}, {585, 650}}, + {7, {2925, 3250}, {1350, 1500}, {650, 722}}, + {8, {3510, 3900}, {1620, 1800}, {780, 867}}, + {9, {3900, 4333}, {1800, 2000}, {780, 867}} }; #endif /* WLAN_FEATURE_11AC */ @@ -546,8 +490,8 @@ extern struct net_device_ops net_ops_struct; /* * FUNCTION: wlan_hdd_cfg80211_wiphy_alloc - * This function is called by hdd_wlan_startup() - * during initialization. + * This function is called by hdd_wlan_startup() + * during initialization. * This function is used to allocate wiphy structure. */ struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) @@ -555,8 +499,8 @@ struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) struct wiphy *wiphy; ENTER(); - /* - * Create wiphy device + /* + * Create wiphy device */ wiphy = wiphy_new(&wlan_hdd_cfg80211_ops, priv_size); @@ -567,38 +511,78 @@ struct wiphy *wlan_hdd_cfg80211_wiphy_alloc(int priv_size) return NULL; } + wiphy->country_ie_pref = NL80211_COUNTRY_IE_IGNORE_CORE; + return wiphy; } /* * FUNCTION: wlan_hdd_cfg80211_update_band - * This function is called from the supplicant through a + * This function is called from the supplicant through a * private ioctl to change the band value */ int wlan_hdd_cfg80211_update_band(struct wiphy *wiphy, eCsrBand eBand) { + int i, j; + eNVChannelEnabledType channelEnabledState; + ENTER(); - switch(eBand) + for (i = 0; i < IEEE80211_NUM_BANDS; i++) { - case eCSR_BAND_24: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - break; - case eCSR_BAND_5G: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; - break; - case eCSR_BAND_ALL: - default: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; + + if (NULL == wiphy->bands[i]) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d", + __func__, i); + continue; + } + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[i]; + + channelEnabledState = vos_nv_getChannelEnabledState( + band->channels[j].hw_value); + + if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == eBand) // 5G only + { + // Enable Social channels for P2P + if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq) && + NV_CHANNEL_ENABLE == channelEnabledState) + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + else + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == eBand) // 2G only + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + + if (NV_CHANNEL_DISABLE == channelEnabledState || + NV_CHANNEL_INVALID == channelEnabledState) + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + } + else if (NV_CHANNEL_DFS == channelEnabledState) + { + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + band->channels[j].flags |= IEEE80211_CHAN_RADAR; + } + else + { + band->channels[j].flags &= ~(IEEE80211_CHAN_DISABLED + |IEEE80211_CHAN_RADAR); + } + } } return 0; } /* * FUNCTION: wlan_hdd_cfg80211_init - * This function is called by hdd_wlan_startup() - * during initialization. + * This function is called by hdd_wlan_startup() + * during initialization. * This function is used to initialize and register wiphy structure. */ int wlan_hdd_cfg80211_init(struct device *dev, @@ -606,6 +590,7 @@ int wlan_hdd_cfg80211_init(struct device *dev, hdd_config_t *pCfg ) { + int i, j; hdd_context_t *pHddCtx = wiphy_priv(wiphy); ENTER(); @@ -613,7 +598,6 @@ int wlan_hdd_cfg80211_init(struct device *dev, set_wiphy_dev(wiphy, dev); wiphy->mgmt_stypes = wlan_hdd_txrx_stypes; - if (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode, CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) != 0) { @@ -621,13 +605,11 @@ int wlan_hdd_cfg80211_init(struct device *dev, } else { - /* This will disable updating of NL channels from passive to - * active if a beacon is received on passive channel. - */ + /* This will disable updating of NL channels from passive to + * active if a beacon is received on passive channel. */ wiphy->flags |= WIPHY_FLAG_DISABLE_BEACON_HINTS; wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY; } - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD @@ -651,6 +633,11 @@ int wlan_hdd_cfg80211_init(struct device *dev, wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | WIPHY_FLAG_TDLS_EXTERNAL_SETUP; #endif +#ifdef FEATURE_WLAN_SCAN_PNO + wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + wiphy->max_sched_scan_ssids = SIR_PNO_MAX_SUPP_NETWORKS; + wiphy->max_match_sets = SIR_PNO_MAX_SUPP_NETWORKS; +#endif/*FEATURE_WLAN_SCAN_PNO*/ /* even with WIPHY_FLAG_CUSTOM_REGULATORY, driver can still register regulatory callback and @@ -659,12 +646,14 @@ int wlan_hdd_cfg80211_init(struct device *dev, regulatory settings */ wiphy->reg_notifier = wlan_hdd_crda_reg_notifier; - wiphy->max_scan_ssids = MAX_SCAN_SSID; - - wiphy->max_scan_ie_len = 200 ; //TODO: define a macro + wiphy->max_scan_ssids = MAX_SCAN_SSID; + + wiphy->max_scan_ie_len = SIR_MAC_MAX_IE_LENGTH; + + wiphy->max_acl_mac_addrs = MAX_ACL_MAC_ADDRESS; /* Supports STATION & AD-HOC modes right now */ - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) @@ -703,20 +692,38 @@ int wlan_hdd_cfg80211_init(struct device *dev, wlan_hdd_band_5_GHZ.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; } - /*Initialize band capability*/ - switch(pCfg->nBandCapability) - { - case eCSR_BAND_24: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - break; - case eCSR_BAND_5G: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_p2p_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; - break; - case eCSR_BAND_ALL: - default: - wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; - wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; + wiphy->bands[IEEE80211_BAND_2GHZ] = &wlan_hdd_band_2_4_GHZ; + wiphy->bands[IEEE80211_BAND_5GHZ] = &wlan_hdd_band_5_GHZ; + + for (i = 0; i < IEEE80211_NUM_BANDS; i++) + { + + if (NULL == wiphy->bands[i]) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[i] is NULL, i = %d", + __func__, i); + continue; + } + + for (j = 0; j < wiphy->bands[i]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[i]; + + if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == pCfg->nBandCapability) // 5G only + { + // Enable social channels for P2P + if (WLAN_HDD_IS_SOCIAL_CHANNEL(band->channels[j].center_freq)) + band->channels[j].flags &= ~IEEE80211_CHAN_DISABLED; + else + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + else if (IEEE80211_BAND_5GHZ == i && eCSR_BAND_24 == pCfg->nBandCapability) // 2G only + { + band->channels[j].flags |= IEEE80211_CHAN_DISABLED; + continue; + } + } } /*Initialise the supported cipher suite details*/ wiphy->cipher_suites = hdd_cipher_suites; @@ -747,7 +754,7 @@ int wlan_hdd_cfg80211_register(struct wiphy *wiphy) EXIT(); return 0; -} +} /* In this function we will try to get default country code from crda. If the gCrdaDefaultCountryCode is configured in ini file, @@ -765,6 +772,10 @@ int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg) regulatory_hint(wiphy, pCfg->crdaDefaultCountryCode); wait_for_completion_interruptible_timeout(&pHddCtx->driver_crda_req, CRDA_WAIT_TIME); + /* if the country is not found from current regulatory.bin, + fall back to world domain */ + if (is_crda_regulatory_entry_valid() == VOS_FALSE) + crda_regulatory_entry_default(pCfg->crdaDefaultCountryCode, NUM_REG_DOMAINS-1); } return 0; } @@ -776,25 +787,35 @@ int wlan_hdd_get_crda_regd_entry(struct wiphy *wiphy, hdd_config_t *pCfg) GO should not opeate on indoor channels */ void wlan_hdd_cfg80211_update_reg_info(struct wiphy *wiphy) { + int j; hdd_context_t *pHddCtx = wiphy_priv(wiphy); tANI_U8 defaultCountryCode[3] = SME_INVALID_COUNTRY_CODE; //Default counrtycode from NV at the time of wiphy initialization. if (eHAL_STATUS_SUCCESS != sme_GetDefaultCountryCodeFrmNv(pHddCtx->hHal, &defaultCountryCode[0])) { - hddLog(LOGE, FL("%s Failed to get default country code from NV")); + hddLog(LOGE, FL("%s Failed to get default country code from NV")); } if ((defaultCountryCode[0]== 'U') && (defaultCountryCode[1]=='S')) { - wlan_hdd_band_5_GHZ.channels = hdd_channels_5_GHZ_FCC; - wlan_hdd_band_5_GHZ.n_channels = ARRAY_SIZE(hdd_channels_5_GHZ_FCC); - + if (NULL == wiphy->bands[IEEE80211_BAND_5GHZ]) + { + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: wiphy->bands[IEEE80211_BAND_5GHZ] is NULL",__func__ ); + return; + } + for (j = 0; j < wiphy->bands[IEEE80211_BAND_5GHZ]->n_channels; j++) + { + struct ieee80211_supported_band *band = wiphy->bands[IEEE80211_BAND_5GHZ]; + // Mark UNII -1 band channel as passive + if (WLAN_HDD_CHANNEL_IN_UNII_1_BAND(band->channels[j].center_freq)) + band->channels[j].flags |= IEEE80211_CHAN_PASSIVE_SCAN; + } } } /* In this function we will do all post VOS start initialization. In this function we will register for all frame in which supplicant - is interested. + is interested. */ void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter) { @@ -808,13 +829,13 @@ void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter) initialized. Once we will move to 2.6.37 kernel, in which we have frame register ops, we will move this code as a part of that */ /* GAS Initial Request */ - sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, + sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_INITIAL_REQ, GAS_INITIAL_REQ_SIZE ); /* GAS Initial Response */ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE ); - + /* GAS Comeback Request */ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE ); @@ -825,20 +846,13 @@ void wlan_hdd_cfg80211_post_voss_start(hdd_adapter_t* pAdapter) /* P2P Public Action */ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, - (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, + (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, P2P_PUBLIC_ACTION_FRAME_SIZE ); /* P2P Action */ sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)P2P_ACTION_FRAME, P2P_ACTION_FRAME_SIZE ); - -#ifdef WLAN_FEATURE_11W - /* SA Query Response Action Frame */ - sme_RegisterMgmtFrame(hHal, pAdapter->sessionId, type, - (v_U8_t*)SA_QUERY_FRAME_RSP, - SA_QUERY_FRAME_RSP_SIZE ); -#endif /* WLAN_FEATURE_11W */ } void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter) @@ -860,7 +874,7 @@ void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter) /* GAS Initial Response */ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_INITIAL_RSP, GAS_INITIAL_RSP_SIZE ); - + /* GAS Comeback Request */ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)GAS_COMEBACK_REQ, GAS_COMEBACK_REQ_SIZE ); @@ -871,20 +885,13 @@ void wlan_hdd_cfg80211_pre_voss_stop(hdd_adapter_t* pAdapter) /* P2P Public Action */ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, - (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, + (v_U8_t*)P2P_PUBLIC_ACTION_FRAME, P2P_PUBLIC_ACTION_FRAME_SIZE ); /* P2P Action */ sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, (v_U8_t*)P2P_ACTION_FRAME, P2P_ACTION_FRAME_SIZE ); - -#ifdef WLAN_FEATURE_11W - /* SA Query Response Action Frame */ - sme_DeregisterMgmtFrame(hHal, pAdapter->sessionId, type, - (v_U8_t*)SA_QUERY_FRAME_RSP, - SA_QUERY_FRAME_RSP_SIZE ); -#endif /* WLAN_FEATURE_11W */ } #ifdef FEATURE_WLAN_WAPI @@ -943,16 +950,16 @@ void wlan_hdd_cfg80211_set_key_wapi(hdd_adapter_t* pAdapter, u8 key_index, #endif /* FEATURE_WLAN_WAPI*/ #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) -int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, +int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, beacon_data_t **ppBeacon, struct beacon_parameters *params) #else -int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, +int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, beacon_data_t **ppBeacon, struct cfg80211_beacon_data *params, int dtim_period) #endif -{ +{ int size; beacon_data_t *beacon = NULL; beacon_data_t *old = NULL; @@ -1004,7 +1011,7 @@ int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, else beacon->dtim_period = old->dtim_period; #endif - + beacon->head = ((u8 *) beacon) + sizeof(beacon_data_t); beacon->tail = beacon->head + head_len; beacon->head_len = head_len; @@ -1013,16 +1020,16 @@ int wlan_hdd_cfg80211_alloc_new_beacon(hdd_adapter_t *pAdapter, if(params->head) { memcpy (beacon->head,params->head,beacon->head_len); } - else { + else { if(old) memcpy (beacon->head,old->head,beacon->head_len); } - + if(params->tail) { memcpy (beacon->tail,params->tail,beacon->tail_len); } else { - if(old) + if(old) memcpy (beacon->tail,old->tail,beacon->tail_len); } @@ -1039,9 +1046,9 @@ v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid) int left = length; v_U8_t *ptr = pIes; v_U8_t elem_id,elem_len; - + while(left >= 2) - { + { elem_id = ptr[0]; elem_len = ptr[1]; left -= 2; @@ -1052,11 +1059,11 @@ v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid) eid,elem_len,left); return NULL; } - if (elem_id == eid) + if (elem_id == eid) { return ptr; } - + left -= elem_len; ptr += (elem_len + 2); } @@ -1066,7 +1073,7 @@ v_U8_t* wlan_hdd_cfg80211_get_ie_ptr(v_U8_t *pIes, int length, v_U8_t eid) /* Check if rate is 11g rate or not */ static int wlan_hdd_rate_is_11g(u8 rate) { - u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 104}; /* actual rate * 2 */ + static const u8 gRateArray[8] = {12, 18, 24, 36, 48, 72, 96, 108}; /* actual rate * 2 */ u8 i; for (i = 0; i < 8; i++) { @@ -1144,7 +1151,7 @@ static void wlan_hdd_set_sapHwmode(hdd_adapter_t *pHostapdAdapter) pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, WLAN_EID_HT_CAPABILITY); - if(pIe) + if(pIe) { pConfig->SapHw_mode= eSAP_DOT11_MODE_11n; if(require_ht) @@ -1419,23 +1426,23 @@ static int wlan_hdd_cfg80211_update_apies(hdd_adapter_t* pHostapdAdapter, return ret; } -/* +/* * FUNCTION: wlan_hdd_validate_operation_channel * called by wlan_hdd_cfg80211_start_bss() and * wlan_hdd_cfg80211_set_channel() * This function validates whether given channel is part of valid - * channel list. - */ -static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel) + * channel list. + */ +VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,int channel) { - + v_U32_t num_ch = 0; u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN]; u32 indx = 0; tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); v_U8_t fValidChannel = FALSE, count = 0; hdd_config_t *hdd_pConfig_ini= (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; - + num_ch = WNI_CFG_VALID_CHANNEL_LIST_LEN; if ( hdd_pConfig_ini->sapAllowAllChannel) @@ -1481,7 +1488,7 @@ static VOS_STATUS wlan_hdd_validate_operation_channel(hdd_adapter_t *pAdapter,in } } return VOS_STATUS_SUCCESS; - + } /** @@ -1497,6 +1504,8 @@ static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device int channel = 0; hdd_adapter_t *pAdapter = NULL; int freq = chan->center_freq; /* freq is in MHZ */ + hdd_context_t *pHddCtx; + int status; ENTER(); @@ -1511,10 +1520,15 @@ static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d freq = %d \n",__func__, pAdapter->device_mode, chan->center_freq); - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } /* @@ -1621,27 +1635,27 @@ static int wlan_hdd_cfg80211_set_channel( struct wiphy *wiphy, struct net_device return -EINVAL; } EXIT(); - return 0; + return status; } -/* +/* * FUNCTION: wlan_hdd_select_cbmode * called by wlan_hdd_cfg80211_start_bss() and * This function selects the cbmode based on primary channel - */ + */ VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t channel) { tSmeConfigParams smeConfig; hdd_context_t *pHddCtx = ( hdd_context_t *) pAdapter; hdd_config_t *pConfigIni = ((hdd_context_t *)(pAdapter))->cfg_ini; - + if( #ifdef WLAN_FEATURE_11AC SapHw_mode != eSAP_DOT11_MODE_11ac && SapHw_mode != eSAP_DOT11_MODE_11ac_ONLY && #endif SapHw_mode != eSAP_DOT11_MODE_11n && - SapHw_mode != eSAP_DOT11_MODE_11n_ONLY + SapHw_mode != eSAP_DOT11_MODE_11n_ONLY ) { return VOS_STATUS_SUCCESS; @@ -1658,31 +1672,31 @@ VOS_STATUS wlan_sap_select_cbmode(void *pAdapter,eSapPhyMode SapHw_mode, v_U8_t #ifdef WLAN_FEATURE_11AC - if ( SapHw_mode == eSAP_DOT11_MODE_11ac || + if ( SapHw_mode == eSAP_DOT11_MODE_11ac || SapHw_mode == eSAP_DOT11_MODE_11ac_ONLY ) { if ( channel== 36 || channel == 52 || channel == 100 || channel == 116 || channel == 149 ) { - smeConfig.csrConfig.channelBondingMode5GHz = + smeConfig.csrConfig.channelBondingMode5GHz = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_LOW - 1; } else if ( channel == 40 || channel == 56 || channel == 104 || channel == 120 || channel == 153 ) { - smeConfig.csrConfig.channelBondingMode5GHz = + smeConfig.csrConfig.channelBondingMode5GHz = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_LOW - 1; } else if ( channel == 44 || channel == 60 || channel == 108 || channel == 124 || channel == 157 ) { - smeConfig.csrConfig.channelBondingMode5GHz = + smeConfig.csrConfig.channelBondingMode5GHz = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH -1; } else if ( channel == 48 || channel == 64 || channel == 112 || channel == 128 || channel == 161 ) { - smeConfig.csrConfig.channelBondingMode5GHz = + smeConfig.csrConfig.channelBondingMode5GHz = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH - 1; } else if ( channel == 165 ) @@ -1763,7 +1777,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, //pConfig->channel = pCommitConfig->channel; /*Protection parameter to enable or disable*/ - pConfig->protEnabled = + pConfig->protEnabled = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtEnabled; pConfig->dtim_period = pBeacon->dtim_period; @@ -1819,8 +1833,8 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->authType = eSAP_AUTO_SWITCH; capab_info = pMgmt_frame->u.beacon.capab_info; - - pConfig->privacy = (pMgmt_frame->u.beacon.capab_info & + + pConfig->privacy = (pMgmt_frame->u.beacon.capab_info & WLAN_CAPABILITY_PRIVACY) ? VOS_TRUE : VOS_FALSE; (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->uPrivacy = pConfig->privacy; @@ -1854,22 +1868,22 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, { pConfig->wps_state = SAP_WPS_DISABLED; } - pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up + pConfig->fwdWPSPBCProbeReq = 1; // Forward WPS PBC probe request frame up pConfig->RSNWPAReqIELength = 0; pConfig->pRSNWPAReqIE = NULL; - pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, + pIe = wlan_hdd_cfg80211_get_ie_ptr(pBeacon->tail, pBeacon->tail_len, WLAN_EID_RSN); if(pIe && pIe[1]) - { + { pConfig->RSNWPAReqIELength = pIe[1] + 2; memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength); pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0]; - /* The actual processing may eventually be more extensive than - * this. Right now, just consume any PMKIDs that are sent in + /* The actual processing may eventually be more extensive than + * this. Right now, just consume any PMKIDs that are sent in * by the app. * */ - status = hdd_softap_unpackIE( + status = hdd_softap_unpackIE( vos_get_context( VOS_MODULE_ID_SME, pVosContext), &RSNEncryptType, &mcRSNEncryptType, @@ -1879,19 +1893,19 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if( VOS_STATUS_SUCCESS == status ) { - /* Now copy over all the security attributes you have - * parsed out + /* Now copy over all the security attributes you have + * parsed out * */ pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE pConfig->mcRSNEncryptType = mcRSNEncryptType; (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType = RSNEncryptType; - hddLog( LOG1, FL("%s: CSR AuthType = %d, " + hddLog( LOG1, FL("CSR AuthType = %d, " "EncryptionType = %d mcEncryptionType = %d\n"), RSNAuthType, RSNEncryptType, mcRSNEncryptType); } } - + pIe = wlan_hdd_get_vendor_oui_ie_ptr(WPA_OUI_TYPE, WPA_OUI_TYPE_SIZE, pBeacon->tail, pBeacon->tail_len); @@ -1908,7 +1922,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, pConfig->RSNWPAReqIELength = pIe[1] + 2; memcpy(&wpaRsnIEdata[0], pIe, pConfig->RSNWPAReqIELength); pConfig->pRSNWPAReqIE = &wpaRsnIEdata[0]; - status = hdd_softap_unpackIE( + status = hdd_softap_unpackIE( vos_get_context( VOS_MODULE_ID_SME, pVosContext), &RSNEncryptType, &mcRSNEncryptType, @@ -1918,14 +1932,14 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, if( VOS_STATUS_SUCCESS == status ) { - /* Now copy over all the security attributes you have - * parsed out + /* Now copy over all the security attributes you have + * parsed out * */ pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE pConfig->mcRSNEncryptType = mcRSNEncryptType; (WLAN_HDD_GET_AP_CTX_PTR(pHostapdAdapter))->ucEncryptType = RSNEncryptType; - hddLog( LOG1, FL("%s: CSR AuthType = %d, " + hddLog( LOG1, FL("CSR AuthType = %d, " "EncryptionType = %d mcEncryptionType = %d\n"), RSNAuthType, RSNEncryptType, mcRSNEncryptType); } @@ -1957,9 +1971,9 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } #endif - vos_mem_copy(pConfig->self_macaddr.bytes, + vos_mem_copy(pConfig->self_macaddr.bytes, pHostapdAdapter->macAddressCurrent.bytes, sizeof(v_MACADDR_t)); - + /* default value */ pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED; pConfig->num_accept_mac = 0; @@ -1975,21 +1989,21 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, acl type : 1 byte no of mac addr in black list: 1 byte list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id - */ - if ((pIe != NULL) && (pIe[1] != 0)) + */ + if ((pIe != NULL) && (pIe[1] != 0)) { pConfig->SapMacaddr_acl = pIe[6]; pConfig->num_deny_mac = pIe[7]; hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no deny mac = %d\n", pIe[6], pIe[7]); - if (pConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED) - pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED; + if (pConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS) + pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS; acl_entry = (struct qc_mac_acl_entry *)(pIe + 8); for (i = 0; i < pConfig->num_deny_mac; i++) { vos_mem_copy(&pConfig->deny_mac[i], acl_entry->addr, sizeof(qcmacaddr)); acl_entry++; - } + } } pIe = wlan_hdd_get_vendor_oui_ie_ptr(WHITELIST_OUI_TYPE, WPA_OUI_TYPE_SIZE, pBeacon->tail, pBeacon->tail_len); @@ -2001,15 +2015,15 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, acl type : 1 byte no of mac addr in white list: 1 byte list of mac_acl_entries: variable, 6 bytes per mac address + sizeof(int) for vlan id - */ - if ((pIe != NULL) && (pIe[1] != 0)) + */ + if ((pIe != NULL) && (pIe[1] != 0)) { pConfig->SapMacaddr_acl = pIe[6]; pConfig->num_accept_mac = pIe[7]; hddLog(VOS_TRACE_LEVEL_INFO,"acl type = %d no accept mac = %d\n", pIe[6], pIe[7]); - if (pConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED) - pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED; + if (pConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS) + pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS; acl_entry = (struct qc_mac_acl_entry *)(pIe + 8); for (i = 0; i < pConfig->num_accept_mac; i++) { @@ -2017,17 +2031,23 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, acl_entry++; } } + wlan_hdd_set_sapHwmode(pHostapdAdapter); #ifdef WLAN_FEATURE_11AC - if(((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) || - ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) || - ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY) ) + /* Overwrite the hostapd setting for HW mode only for 11ac. + * This is valid only if mode is set to 11n in hostapd and either AUTO or 11ac in .ini . + * Otherwise, leave whatever is set in hostapd (a OR b OR g OR n mode) */ + if( ((pConfig->SapHw_mode == eSAP_DOT11_MODE_11n) || + (pConfig->SapHw_mode == eSAP_DOT11_MODE_11n_ONLY)) && + (((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_AUTO) || + ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac) || + ((WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->dot11Mode == eHDD_DOT11_MODE_11ac_ONLY)) ) { pConfig->SapHw_mode = eSAP_DOT11_MODE_11ac; } #endif - + if( AUTO_CHANNEL_SELECT != pConfig->channel) wlan_sap_select_cbmode((WLAN_HDD_GET_CTX(pHostapdAdapter)),pConfig->SapHw_mode,pConfig->channel); // ht_capab is not what the name conveys,this is used for protection bitmap @@ -2041,26 +2061,26 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } //Uapsd Enabled Bit - pConfig->UapsdEnable = + pConfig->UapsdEnable = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apUapsdEnabled; //Enable OBSS protection - pConfig->obssProtEnabled = - (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled; + pConfig->obssProtEnabled = + (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apOBSSProtEnabled; - hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"), + hddLog(LOGW, FL("SOftAP macaddress : "MAC_ADDRESS_STR"\n"), MAC_ADDR_ARRAY(pHostapdAdapter->macAddressCurrent.bytes)); - hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId); + hddLog(LOGW,FL("ssid =%s\n"), pConfig->SSIDinfo.ssid.ssId); hddLog(LOGW,FL("beaconint=%d, channel=%d\n"), (int)pConfig->beacon_int, (int)pConfig->channel); hddLog(LOGW,FL("hw_mode=%x\n"), pConfig->SapHw_mode); - hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy, - pConfig->authType); + hddLog(LOGW,FL("privacy=%d, authType=%d\n"), pConfig->privacy, + pConfig->authType); hddLog(LOGW,FL("RSN/WPALen=%d, \n"),(int)pConfig->RSNWPAReqIELength); - hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable); + hddLog(LOGW,FL("Uapsd = %d\n"),pConfig->UapsdEnable); hddLog(LOGW,FL("ProtEnabled = %d, OBSSProtEnabled = %d\n"), pConfig->protEnabled, pConfig->obssProtEnabled); - if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) + if(test_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags)) { //Bss already started. just return. //TODO Probably it should update some beacon params. @@ -2068,7 +2088,7 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, EXIT(); return 0; } - + pConfig->persona = pHostapdAdapter->device_mode; pSapEventCallback = hdd_hostapd_SAPEventCB; @@ -2079,18 +2099,18 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, return -EINVAL; } - hddLog(LOG1, + hddLog(LOG1, FL("Waiting for Scan to complete(auto mode) and BSS to start")); status = vos_wait_single_event(&pHostapdState->vosEvent, 10000); - + if (!VOS_IS_STATUS_SUCCESS(status)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, ("ERROR: HDD vos wait for single_event failed!!\n")); VOS_ASSERT(0); } - + //Succesfully started Bss update the state bit. set_bit(SOFTAP_BSS_STARTED, &pHostapdAdapter->event_flags); @@ -2119,38 +2139,42 @@ static int wlan_hdd_cfg80211_start_bss(hdd_adapter_t *pHostapdAdapter, } #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0)) -static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, - struct net_device *dev, +static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, + struct net_device *dev, struct beacon_parameters *params) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int status=VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx; + int status; ENTER(); hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "device mode=%d\n",pAdapter->device_mode); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP) + if ( (pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) ) { beacon_data_t *old,*new; old = pAdapter->sessionCtx.ap.beacon; - + if (old) return -EALREADY; status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params); - if(status != VOS_STATUS_SUCCESS) + if(status != VOS_STATUS_SUCCESS) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s:Error!!! Allocating the new beacon\n",__func__); @@ -2165,41 +2189,45 @@ static int wlan_hdd_cfg80211_add_beacon(struct wiphy *wiphy, EXIT(); return status; } - -static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, + +static int wlan_hdd_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev, struct beacon_parameters *params) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int status=VOS_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int status; ENTER(); hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) + ) { beacon_data_t *old,*new; - + old = pAdapter->sessionCtx.ap.beacon; - + if (!old) return -ENOENT; status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter,&new,params); if(status != VOS_STATUS_SUCCESS) { - hddLog(VOS_TRACE_LEVEL_FATAL, + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Error!!! Allocating the new beacon\n",__func__); return -EINVAL; } @@ -2227,7 +2255,7 @@ static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, hdd_context_t *pHddCtx = NULL; hdd_scaninfo_t *pScanInfo = NULL; hdd_adapter_t *staAdapter = NULL; - VOS_STATUS status = 0; + VOS_STATUS status; ENTER(); @@ -2238,18 +2266,14 @@ static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, return -ENODEV; } - pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (NULL == pHddCtx) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: HDD context is Null", __func__); - return -ENODEV; - } - if (pHddCtx->isLogpInProgress) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_INFRA_STATION); @@ -2258,7 +2282,7 @@ static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, staAdapter = hdd_get_adapter(pAdapter->pHddCtx, WLAN_HDD_P2P_CLIENT); if (NULL == staAdapter) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: HDD adapter context is Null", __func__); return -ENODEV; } @@ -2266,14 +2290,6 @@ static int wlan_hdd_cfg80211_stop_ap (struct wiphy *wiphy, pScanInfo = &pHddCtx->scan_info; - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; - } - - pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; - hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); @@ -2377,13 +2393,13 @@ static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, { hdd_adapter_t *pAdapter; hdd_context_t *pHddCtx; - int status = 0; + int status; ENTER(); if (NULL == dev) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Device is Null", __func__); return -ENODEV; } @@ -2391,38 +2407,26 @@ static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); if (NULL == pAdapter) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: HDD adapter is Null", __func__); return -ENODEV; } if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: HDD adapter magic is invalid", __func__); return -ENODEV; } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (NULL == pHddCtx) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: HDD context is Null", __func__); - return -ENODEV; - } - - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } + status = wlan_hdd_validate_context(pHddCtx); - if (pHddCtx->isLoadUnloadInProgress) + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: Unloading/Loading in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device mode = %d", @@ -2460,38 +2464,44 @@ static int wlan_hdd_cfg80211_start_ap(struct wiphy *wiphy, } -static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, +static int wlan_hdd_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_beacon_data *params) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - int status=VOS_STATUS_SUCCESS; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + int status; ENTER(); hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__, pAdapter->device_mode); - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) + ) { beacon_data_t *old,*new; - + old = pAdapter->sessionCtx.ap.beacon; - + if (!old) return -ENOENT; status = wlan_hdd_cfg80211_alloc_new_beacon(pAdapter, &new, params, 0); if(status != VOS_STATUS_SUCCESS) { - hddLog(VOS_TRACE_LEVEL_FATAL, + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Error!!! Allocating the new beacon\n",__func__); return -EINVAL; } @@ -2515,20 +2525,20 @@ static int wlan_hdd_cfg80211_change_bss (struct wiphy *wiphy, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); ENTER(); - + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); if((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) + ) { /* ap_isolate == -1 means that in change bss, upper layer doesn't * want to update this parameter */ - if (-1 != params->ap_isolate) + if (-1 != params->ap_isolate) { pAdapter->sessionCtx.ap.apDisableIntraBssFwd = !!params->ap_isolate; - } + } } EXIT(); @@ -2552,21 +2562,25 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, hdd_adapter_t *pP2pAdapter = NULL; tCsrRoamProfile *pRoamProfile = NULL; eCsrRoamBssType LastBSSType; - hdd_config_t *pConfig = pHddCtx->cfg_ini; + hdd_config_t *pConfig = NULL; eMib_dot11DesiredBssType connectedBssType; VOS_STATUS status; ENTER(); - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", __func__, pAdapter->device_mode); + pConfig = pHddCtx->cfg_ini; wdev = ndev->ieee80211_ptr; #ifdef WLAN_BTAMP_FEATURE @@ -2612,12 +2626,12 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, pConfig->dot11Mode = eHDD_DOT11_MODE_11ac; } #endif - pRoamProfile->phyMode = + pRoamProfile->phyMode = hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); wdev->iftype = type; //Check for sub-string p2p to confirm its a p2p interface if (NULL != strstr(ndev->name,"p2p")) - { + { pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ? WLAN_HDD_P2P_DEVICE : WLAN_HDD_P2P_CLIENT; } @@ -2626,13 +2640,30 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, pAdapter->device_mode = (type == NL80211_IFTYPE_STATION) ? WLAN_HDD_INFRA_STATION: WLAN_HDD_P2P_CLIENT; } - break; - case NL80211_IFTYPE_ADHOC: - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: setting interface Type to ADHOC", __func__); - pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; - pRoamProfile->phyMode = - hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); +#ifdef FEATURE_WLAN_TDLS + /* The open adapter for the p2p shall skip initializations in + * tdls_init if the device mode is WLAN_HDD_P2P_DEVICE, for + * TDLS is supported only on WLAN_HDD_P2P_CLIENT. Hence invoke + * tdls_init when the change_iface sets the device mode to + * WLAN_HDD_P2P_CLIENT. + */ + + if ( pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + { + if (0 != wlan_hdd_tdls_init (pAdapter)) + { + return -EINVAL; + } + } +#endif + + break; + case NL80211_IFTYPE_ADHOC: + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: setting interface Type to ADHOC", __func__); + pRoamProfile->BSSType = eCSR_BSS_TYPE_START_IBSS; + pRoamProfile->phyMode = + hdd_cfg_xlate_to_csr_phy_mode(pConfig->dot11Mode); wdev->iftype = type; break; @@ -2679,7 +2710,7 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, //before starting Go if(WLAN_HDD_P2P_GO == pAdapter->device_mode) { - if(VOS_STATUS_E_FAILURE == + if(VOS_STATUS_E_FAILURE == hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_P2P_GO)) { //Fail to Exit BMPS @@ -2774,6 +2805,10 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, /* In case of JB, for P2P-GO, only change interface will be called, * This is the right place to enable back bmps_imps() */ + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } hdd_enable_bmps_imps(pHddCtx); goto done; case NL80211_IFTYPE_AP: @@ -2828,7 +2863,7 @@ int wlan_hdd_cfg80211_change_iface( struct wiphy *wiphy, /*set bitmask based on updated value*/ wlan_hdd_set_concurrency_mode(pHddCtx, pAdapter->device_mode); #ifdef WLAN_BTAMP_FEATURE - if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) && + if((NL80211_IFTYPE_STATION == type) && (pHddCtx->concurrency_mode <= 1) && (pHddCtx->no_of_sessions[WLAN_HDD_INFRA_STATION] <=1)) { //we are ok to do AMP @@ -2894,7 +2929,7 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, } /* when others are on-going, we want to change link_status to idle */ - if (wlan_hdd_tdls_is_progress(pAdapter, mac, TRUE)) + if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, mac, TRUE, TRUE)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR @@ -2929,23 +2964,30 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, if (0 == update) wlan_hdd_tdls_set_link_status(pAdapter, mac, eTDLS_LINK_CONNECTING); + /* debug code */ if (NULL != StaParams) { VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: TDLS Peer Parameters.", __func__); - VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo); - VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "ht_capa->extended_capabilities: %0x", - StaParams->HTCap.extendedHtCapInfo); + if(StaParams->htcap_present) + { + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "ht_capa->cap_info: %0x", StaParams->HTCap.capInfo); + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "ht_capa->extended_capabilities: %0x", + StaParams->HTCap.extendedHtCapInfo); + } VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "params->capability: %0x",StaParams->capability); VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "params->ext_capab_len: %0x",StaParams->extn_capability); - VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x", - StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest, - StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest); + if(StaParams->vhtcap_present) + { + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "rxMcsMap %x rxHighest %x txMcsMap %x txHighest %x", + StaParams->VHTCap.suppMcs.rxMcsMap, StaParams->VHTCap.suppMcs.rxHighest, + StaParams->VHTCap.suppMcs.txMcsMap, StaParams->VHTCap.suppMcs.txHighest); + } { int i = 0; VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Supported rates:"); @@ -2953,6 +2995,12 @@ static int wlan_hdd_tdls_add_station(struct wiphy *wiphy, VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "[%d]: %x ", i, StaParams->supported_rates[i]); } + } /* end debug code */ + else if ((1 == update) && (NULL == StaParams)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s : update is true, but staParams is NULL. Error!", __func__); + return -EPERM; } INIT_COMPLETION(pAdapter->tdls_add_station_comp); @@ -3001,6 +3049,8 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, { VOS_STATUS status = VOS_STATUS_SUCCESS; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_context_t *pHddCtx; + hdd_station_ctx_t *pHddStaCtx; v_MACADDR_t STAMacAddress; #ifdef FEATURE_WLAN_TDLS tCsrStaParams StaParams = {0}; @@ -3008,7 +3058,24 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, #endif ENTER(); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + if ((NULL == pAdapter)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid adapter "); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if ((NULL == pHddCtx) || (NULL == pHddStaCtx)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid HDD state or HDD station context"); + return -EINVAL; + } + + if (pHddCtx->isLogpInProgress) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:LOGP in Progress. Ignore!!!", __func__); @@ -3022,16 +3089,20 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, { if (params->sta_flags_set & BIT(NL80211_STA_FLAG_AUTHORIZED)) { - status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress, + status = hdd_softap_change_STA_state( pAdapter, &STAMacAddress, WLANTL_STA_AUTHENTICATED); - VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, - "%s: Station MAC address does not matching", __func__); - return -EINVAL; + if (status != VOS_STATUS_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Not able to change TL state to AUTHENTICATED", __func__); + return -EINVAL; + } } } + else if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) + || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) { #ifdef FEATURE_WLAN_TDLS - else if (pAdapter->device_mode == WLAN_HDD_INFRA_STATION ) { if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) { StaParams.capability = params->capability; StaParams.uapsd_queues = params->uapsd_queues; @@ -3042,7 +3113,10 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, sizeof(StaParams.extn_capability)); if (NULL != params->ht_capa) + { + StaParams.htcap_present = 1; vos_mem_copy(&StaParams.HTCap, params->ht_capa, sizeof(tSirHTCap)); + } StaParams.supported_rates_len = params->supported_rates_len; @@ -3069,7 +3143,10 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, } if (NULL != params->vht_capa) + { + StaParams.vhtcap_present = 1; vos_mem_copy(&StaParams.VHTCap, params->vht_capa, sizeof(tSirVHTCap)); + } if (0 != params->ext_capab_len ) { /*Define A Macro : TODO Sunil*/ @@ -3092,38 +3169,12 @@ static int wlan_hdd_change_station(struct wiphy *wiphy, return -EINVAL; } } - } #endif - + } EXIT(); return status; } -/* - * FUNCTION: wlan_hdd_cfg80211_get_ibss_peer_staidx - * This function is used to get peer station index in IBSS mode - */ -static u8 wlan_hdd_cfg80211_get_ibss_peer_staidx(hdd_adapter_t* pAdapter) -{ - u8 idx = 0; - u8 temp[VOS_MAC_ADDR_SIZE] = {0}; - ENTER(); - memset(temp, 0, VOS_MAC_ADDR_SIZE); - for ( idx = 0; idx < HDD_MAX_NUM_IBSS_STA; idx++ ) - { - if ( (0 != - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[idx]) - && memcmp((u8*)&(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.peerMacAddress[idx], - temp, VOS_MAC_ADDR_SIZE) - ) - { - return idx; - } - } - return idx; -} - - /* * FUNCTION: wlan_hdd_cfg80211_add_key * This function is used to initialize the key information @@ -3146,20 +3197,24 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); tCsrRoamSetKey setKey; u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; - int status = 0; + int status; v_U32_t roamId= 0xFF; v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; hdd_hostapd_state_t *pHostapdState; VOS_STATUS vos_status; eHalStatus halStatus; + hdd_context_t *pHddCtx; ENTER(); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", @@ -3249,19 +3304,11 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, return 0; } #endif - #ifdef FEATURE_WLAN_CCX case WLAN_CIPHER_SUITE_KRK: setKey.encType = eCSR_ENCRYPT_TYPE_KRK; break; #endif - -#ifdef WLAN_FEATURE_11W - case WLAN_CIPHER_SUITE_AES_CMAC: - setKey.encType = eCSR_ENCRYPT_TYPE_AES_CMAC; - break; -#endif - default: hddLog(VOS_TRACE_LEVEL_ERROR, "%s: unsupported cipher type %lu", __func__, params->cipher); @@ -3272,13 +3319,6 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, __func__, setKey.encType); - - if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) - || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) - { - - if ( #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) (!pairwise) @@ -3304,6 +3344,9 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN); } + if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || + (pAdapter->device_mode == WLAN_HDD_P2P_GO)) + { pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); if( pHostapdState->bssState == BSS_START ) { @@ -3338,6 +3381,22 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) + if (!pairwise) +#else + if (!mac_addr || is_broadcast_ether_addr(mac_addr)) +#endif + { + /* set group key*/ + if (pHddStaCtx->roam_info.deferKeyComplete) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s- %d: Perform Set key Complete", + __func__, __LINE__); + hdd_PerformRoamSetKeyComplete(pAdapter); + } + } + pWextState->roamProfile.Keys.KeyLength[key_index] = (u8)params->key_len; pWextState->roamProfile.Keys.defaultIndex = key_index; @@ -3346,119 +3405,14 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, vos_mem_copy(&pWextState->roamProfile.Keys.KeyMaterial[key_index][0], params->key, params->key_len); - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; - - if (!( ( IW_AUTH_KEY_MGMT_802_1X - == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) - && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) - ) - && - ( (WLAN_CIPHER_SUITE_WEP40 == params->cipher) - || (WLAN_CIPHER_SUITE_WEP104 == params->cipher) - ) - ) - { - /* in case of static WEP, macaddr/bssid is not coming from nl80211 - * interface, copy bssid for pairwise key and group macaddr for - * group key initialization*/ - - tCsrRoamProfile *pRoamProfile = &pWextState->roamProfile; - - pWextState->roamProfile.negotiatedUCEncryptionType = - pHddStaCtx->conn_info.ucEncryptionType = - ((WLAN_CIPHER_SUITE_WEP40 == params->cipher) ? - eCSR_ENCRYPT_TYPE_WEP40_STATICKEY : - eCSR_ENCRYPT_TYPE_WEP104_STATICKEY); - - - hddLog(VOS_TRACE_LEVEL_INFO_MED, - "%s: Negotiated encryption type %d", __func__, - pWextState->roamProfile.negotiatedUCEncryptionType); - - sme_SetCfgPrivacy((tpAniSirGlobal)WLAN_HDD_GET_HAL_CTX(pAdapter), - &pWextState->roamProfile, true); - setKey.keyLength = 0; - setKey.keyDirection = eSIR_TX_RX; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - if (pairwise) - { -#endif - if (mac_addr) - { - vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN); - } - else - { - /* macaddr is NULL, set the peerMac to bssId in case of BSS, - * and peerMacAddress in case of IBSS*/ - if (eCSR_BSS_TYPE_START_IBSS == pRoamProfile->BSSType) - { - u8 staidx = wlan_hdd_cfg80211_get_ibss_peer_staidx(pAdapter); - if (HDD_MAX_NUM_IBSS_STA != staidx) - { - vos_mem_copy(setKey.peerMac, - &pHddStaCtx->conn_info.peerMacAddress[staidx], - WNI_CFG_BSSID_LEN); - - } - else - { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No peerMac found", - __func__); - return -EOPNOTSUPP; - } - } - else - { - vos_mem_copy(setKey.peerMac, - &pHddStaCtx->conn_info.bssId[0], - WNI_CFG_BSSID_LEN); - } - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - } - else - { - /* set group key*/ - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s- %d: setting Group key", - __func__, __LINE__); - setKey.keyDirection = eSIR_RX_ONLY; - vos_mem_copy(setKey.peerMac, groupmacaddr, WNI_CFG_BSSID_LEN); - } -#endif - } - else if ( -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) - (!pairwise) -#else - (!mac_addr || is_broadcast_ether_addr(mac_addr)) -#endif - ) - { - /* set group key*/ - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s- %d: setting Group key", - __func__, __LINE__); - setKey.keyDirection = eSIR_RX_ONLY; - vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN); - } - else - { - /* set pairwise key*/ - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s- %d: setting pairwise key", - __func__, __LINE__); - setKey.keyDirection = eSIR_TX_RX; - vos_mem_copy(setKey.peerMac, mac_addr,WNI_CFG_BSSID_LEN); - } + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; - hddLog(VOS_TRACE_LEVEL_INFO_MED, + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set key for peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d", - __func__, setKey.peerMac[0], setKey.peerMac[1], - setKey.peerMac[2], setKey.peerMac[3], - setKey.peerMac[4], setKey.peerMac[5], + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], + setKey.peerMac[4], setKey.peerMac[5], setKey.keyDirection); vos_status = wlan_hdd_check_ula_done(pAdapter); @@ -3476,11 +3430,20 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, } #ifdef WLAN_FEATURE_VOWIFI_11R - /* The supplicant may attempt to set the PTK once pre-authentication is done. - Save the key in the UMAC and include it in the ADD BSS request */ + /* The supplicant may attempt to set the PTK once pre-authentication + is done. Save the key in the UMAC and include it in the ADD BSS + request */ halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey); - if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT ) + if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS ) + { + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: Update PreAuth Key success", __func__); + return 0; + } + else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED ) { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Update PreAuth Key failed", __func__); return -EINVAL; } #endif /* WLAN_FEATURE_VOWIFI_11R */ @@ -3491,19 +3454,19 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, if ( 0 != status ) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamSetKey failed, returned %d", __func__, status); pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; return -EINVAL; } - /* in case of IBSS as there was no information available about WEP keys during - * IBSS join, group key intialized with NULL key, so re-initialize group key + /* in case of IBSS as there was no information available about WEP keys during + * IBSS join, group key intialized with NULL key, so re-initialize group key * with correct value*/ - if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) && - !( ( IW_AUTH_KEY_MGMT_802_1X - == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) + if ( (eCSR_BSS_TYPE_START_IBSS == pWextState->roamProfile.BSSType) && + !( ( IW_AUTH_KEY_MGMT_802_1X + == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X)) && (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType) ) && @@ -3515,20 +3478,20 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, setKey.keyDirection = eSIR_RX_ONLY; vos_mem_copy(setKey.peerMac,groupmacaddr,WNI_CFG_BSSID_LEN); - hddLog(VOS_TRACE_LEVEL_INFO_MED, + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set key peerMac %2x:%2x:%2x:%2x:%2x:%2x, direction %d", - __func__, setKey.peerMac[0], setKey.peerMac[1], - setKey.peerMac[2], setKey.peerMac[3], - setKey.peerMac[4], setKey.peerMac[5], + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], + setKey.peerMac[4], setKey.peerMac[5], setKey.keyDirection); - status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &setKey, &roamId ); if ( 0 != status ) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: sme_RoamSetKey failed for group key (IBSS), returned %d", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failed for group key (IBSS), returned %d", __func__, status); pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; return -EINVAL; @@ -3544,38 +3507,38 @@ static int wlan_hdd_cfg80211_add_key( struct wiphy *wiphy, * This function is used to get the key information */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) -static int wlan_hdd_cfg80211_get_key( - struct wiphy *wiphy, +static int wlan_hdd_cfg80211_get_key( + struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, bool pairwise, + u8 key_index, bool pairwise, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params*) ) #else -static int wlan_hdd_cfg80211_get_key( - struct wiphy *wiphy, +static int wlan_hdd_cfg80211_get_key( + struct wiphy *wiphy, struct net_device *ndev, u8 key_index, const u8 *mac_addr, void *cookie, void (*callback)(void *cookie, struct key_params*) ) #endif { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); hdd_wext_state_t *pWextState= WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); tCsrRoamProfile *pRoamProfile = &(pWextState->roamProfile); struct key_params params; ENTER(); - + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); - + memset(¶ms, 0, sizeof(params)); if (CSR_MAX_NUM_KEY <= key_index) { return -EINVAL; - } + } switch(pRoamProfile->EncryptionType.encryptionType[0]) { @@ -3619,14 +3582,14 @@ static int wlan_hdd_cfg80211_get_key( * This function is used to delete the key information */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) -static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, - bool pairwise, + u8 key_index, + bool pairwise, const u8 *mac_addr ) #else -static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, struct net_device *ndev, u8 key_index, const u8 *mac_addr @@ -3636,17 +3599,17 @@ static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, int status = 0; //This code needs to be revisited. There is sme_removeKey API, we should - //plan to use that. After the change to use correct index in setkey, + //plan to use that. After the change to use correct index in setkey, //it is observed that this is invalidating peer //key index whenever re-key is done. This is affecting data link. //It should be ok to ignore del_key. #if 0 - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); - v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + v_CONTEXT_t pVosContext = (WLAN_HDD_GET_CTX(pAdapter))->pvosContext; u8 groupmacaddr[WNI_CFG_BSSID_LEN] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; tCsrRoamSetKey setKey; v_U32_t roamId= 0xFF; - + ENTER(); hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: device_mode = %d\n", @@ -3654,7 +3617,7 @@ static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, if (CSR_MAX_NUM_KEY <= key_index) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, key_index); return -EINVAL; @@ -3672,15 +3635,15 @@ static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, if ((pAdapter->device_mode == WLAN_HDD_SOFTAP) || (pAdapter->device_mode == WLAN_HDD_P2P_GO) - ) - { - - hdd_hostapd_state_t *pHostapdState = + ) + { + + hdd_hostapd_state_t *pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); if( pHostapdState->bssState == BSS_START) { status = WLANSAP_SetKeySta( pVosContext, &setKey); - + if ( status != eHAL_STATUS_SUCCESS ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, @@ -3690,27 +3653,27 @@ static int wlan_hdd_cfg80211_del_key( struct wiphy *wiphy, } } else if ( (pAdapter->device_mode == WLAN_HDD_INFRA_STATION) - || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) + || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) ) { hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; - - hddLog(VOS_TRACE_LEVEL_INFO_MED, + pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_SETTING_KEY; + + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: delete key for peerMac %2x:%2x:%2x:%2x:%2x:%2x", - __func__, setKey.peerMac[0], setKey.peerMac[1], - setKey.peerMac[2], setKey.peerMac[3], + __func__, setKey.peerMac[0], setKey.peerMac[1], + setKey.peerMac[2], setKey.peerMac[3], setKey.peerMac[4], setKey.peerMac[5]); - if(pAdapter->sessionCtx.station.conn_info.connState == - eConnectionState_Associated) + if(pAdapter->sessionCtx.station.conn_info.connState == + eConnectionState_Associated) { - status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &setKey, &roamId ); - + if ( 0 != status ) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamSetKey failure, returned %d", __func__, status); pHddStaCtx->roam_info.roamingState = HDD_ROAM_STATE_NONE; @@ -3738,78 +3701,109 @@ static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy, u8 key_index) #endif { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - int status = 0; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + int status; + hdd_wext_state_t *pWextState; + hdd_station_ctx_t *pHddStaCtx; + hdd_context_t *pHddCtx; ENTER(); + if ((NULL == pAdapter)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid adapter"); + return -EINVAL; + } + + pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + if ((NULL == pWextState) || (NULL == pHddStaCtx)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "invalid Wext state or HDD context"); + return -EINVAL; + } + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d key_index = %d \n", __func__,pAdapter->device_mode, key_index); - + if (CSR_MAX_NUM_KEY <= key_index) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid key index %d", __func__, key_index); return -EINVAL; } - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - + if ((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT) - ) + ) { - if ( (key_index != pWextState->roamProfile.Keys.defaultIndex) && - (eCSR_ENCRYPT_TYPE_TKIP != + if ( (eCSR_ENCRYPT_TYPE_TKIP != pWextState->roamProfile.EncryptionType.encryptionType[0]) && - (eCSR_ENCRYPT_TYPE_AES != + (eCSR_ENCRYPT_TYPE_AES != pWextState->roamProfile.EncryptionType.encryptionType[0]) ) - { - /* if default key index is not same as previous one, + { + /* if default key index is not same as previous one, * then update the default key index */ - + tCsrRoamSetKey setKey; v_U32_t roamId= 0xFF; tCsrKeys *Keys = &pWextState->roamProfile.Keys; - - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d", + + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: default tx key index %d", __func__, key_index); - + Keys->defaultIndex = (u8)key_index; vos_mem_zero(&setKey,sizeof(tCsrRoamSetKey)); setKey.keyId = key_index; setKey.keyLength = Keys->KeyLength[key_index]; - - vos_mem_copy(&setKey.Key[0], - &Keys->KeyMaterial[key_index][0], + + vos_mem_copy(&setKey.Key[0], + &Keys->KeyMaterial[key_index][0], Keys->KeyLength[key_index]); - - setKey.keyDirection = eSIR_TX_ONLY; - - vos_mem_copy(setKey.peerMac, + setKey.keyDirection = eSIR_TX_RX; + vos_mem_copy(setKey.peerMac, &pHddStaCtx->conn_info.bssId[0], WNI_CFG_BSSID_LEN); - - setKey.encType = + if (Keys->KeyLength[key_index] == CSR_WEP40_KEY_LEN && + pWextState->roamProfile.EncryptionType.encryptionType[0] == + eCSR_ENCRYPT_TYPE_WEP104) + { + /*In the case of dynamic wep supplicant hardcodes DWEP type to eCSR_ENCRYPT_TYPE_WEP104 + even though ap is configured for WEP-40 encryption. In this canse the key length + is 5 but the encryption type is 104 hence checking the key langht(5) and encryption + type(104) and switching encryption type to 40*/ + pWextState->roamProfile.EncryptionType.encryptionType[0] = + eCSR_ENCRYPT_TYPE_WEP40; + pWextState->roamProfile.mcEncryptionType.encryptionType[0] = + eCSR_ENCRYPT_TYPE_WEP40; + } + + setKey.encType = pWextState->roamProfile.EncryptionType.encryptionType[0]; - + /* issue set key request */ - status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), + status = sme_RoamSetKey( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, &setKey, &roamId ); - + if ( 0 != status ) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: sme_RoamSetKey failed, returned %d", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: sme_RoamSetKey failed, returned %d", __func__, status); return -EINVAL; } @@ -3830,7 +3824,7 @@ static int wlan_hdd_cfg80211_set_default_key( struct wiphy *wiphy, pAPCtx->wepKey[key_index].keyDirection = eSIR_TX_DEFAULT; } } - + return status; } @@ -3893,8 +3887,8 @@ static struct cfg80211_bss* wlan_hdd_cfg80211_inform_bss( { rssi = (VOS_MIN ((pBssDesc->rssi + pBssDesc->sinr), 0))*100; - return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId, - le64_to_cpu(*(__le64 *)pBssDesc->timeStamp), + return (cfg80211_inform_bss(wiphy, chan, pBssDesc->bssId, + le64_to_cpu(*(__le64 *)pBssDesc->timeStamp), pBssDesc->capabilityInfo, pBssDesc->beaconInterval, ie, ie_length, rssi, GFP_KERNEL )); @@ -3944,6 +3938,8 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, struct cfg80211_bss *bss_status = NULL; size_t frame_len = sizeof (struct ieee80211_mgmt) + ie_length; int rssi = 0; + hdd_context_t *pHddCtx; + int status; #ifdef WLAN_OPEN_SOURCE struct timespec ts; #endif @@ -3953,6 +3949,16 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, if (!mgmt) return NULL; + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return NULL; + } + memcpy(mgmt->bssid, bss_desc->bssId, ETH_ALEN); #ifdef WLAN_OPEN_SOURCE @@ -3997,14 +4003,13 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, (u16)(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); } - #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,38)) - if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) && + if (chan_no <= ARRAY_SIZE(hdd_channels_2_4_GHZ) && (wiphy->bands[IEEE80211_BAND_2GHZ] != NULL)) { freq = ieee80211_channel_to_frequency(chan_no, IEEE80211_BAND_2GHZ); } - else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) && + else if ((chan_no > ARRAY_SIZE(hdd_channels_2_4_GHZ)) && (wiphy->bands[IEEE80211_BAND_5GHZ] != NULL)) { @@ -4038,13 +4043,14 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, return NULL; } /*To keep the rssi icon of the connected AP in the scan window - *and the rssi icon of the wireless networks in sync + *and the rssi icon of the wireless networks in sync * */ if (( eConnectionState_Associated == pAdapter->sessionCtx.station.conn_info.connState ) && ( VOS_TRUE == vos_mem_compare(bss_desc->bssId, pAdapter->sessionCtx.station.conn_info.bssId, - WNI_CFG_BSSID_LEN))) + WNI_CFG_BSSID_LEN)) && + (pHddCtx->hdd_wlan_suspended == FALSE)) { /* supplicant takes the signal strength in terms of mBm(100*dBm) */ rssi = (pAdapter->rssi * 100); @@ -4064,7 +4070,7 @@ wlan_hdd_cfg80211_inform_bss_frame( hdd_adapter_t *pAdapter, * FUNCTION: wlan_hdd_cfg80211_update_bss_db * This function is used to update the BSS data base of CFG8011 */ -struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, +struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo ) { @@ -4079,7 +4085,7 @@ struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, if (NULL != roamProfile.pBssDesc) { - bss = wlan_hdd_cfg80211_inform_bss(pAdapter, + bss = wlan_hdd_cfg80211_inform_bss(pAdapter, &roamProfile); if (NULL == bss) @@ -4101,10 +4107,10 @@ struct cfg80211_bss* wlan_hdd_cfg80211_update_bss_db( hdd_adapter_t *pAdapter, /* * FUNCTION: wlan_hdd_cfg80211_update_bss */ -static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, - hdd_adapter_t *pAdapter +static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, + hdd_adapter_t *pAdapter ) -{ +{ tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); tCsrScanResultInfo *pScanResult; eHalStatus status = 0; @@ -4135,20 +4141,20 @@ static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, while (pScanResult) { - /* - * cfg80211_inform_bss() is not updating ie field of bss entry, if - * entry already exists in bss data base of cfg80211 for that - * particular BSS ID. Using cfg80211_inform_bss_frame to update the - * bss entry instead of cfg80211_inform_bss, But this call expects - * mgmt packet as input. As of now there is no possibility to get - * the mgmt(probe response) frame from PE, converting bss_desc to + /* + * cfg80211_inform_bss() is not updating ie field of bss entry, if + * entry already exists in bss data base of cfg80211 for that + * particular BSS ID. Using cfg80211_inform_bss_frame to update the + * bss entry instead of cfg80211_inform_bss, But this call expects + * mgmt packet as input. As of now there is no possibility to get + * the mgmt(probe response) frame from PE, converting bss_desc to * ieee80211_mgmt(probe response) and passing to c * fg80211_inform_bss_frame. * */ bss_status = wlan_hdd_cfg80211_inform_bss_frame(pAdapter, &pScanResult->BssDescriptor); - + if (NULL == bss_status) { @@ -4163,15 +4169,15 @@ static int wlan_hdd_cfg80211_update_bss( struct wiphy *wiphy, pScanResult = sme_ScanResultGetNext(hHal, pResult); } - sme_ScanResultPurge(hHal, pResult); + sme_ScanResultPurge(hHal, pResult); - return 0; + return 0; } void hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel) { - VOS_TRACE(VOS_MODULE_ID_HDD, logLevel, + VOS_TRACE(VOS_MODULE_ID_HDD, logLevel, "%02X:%02X:%02X:%02X:%02X:%02X\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]); @@ -4180,7 +4186,7 @@ hddPrintMacAddr(tCsrBssid macAddr, tANI_U8 logLevel) void hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel) { - VOS_TRACE(VOS_MODULE_ID_HDD, logLevel, + VOS_TRACE(VOS_MODULE_ID_HDD, logLevel, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", pmkId[0], pmkId[1], pmkId[2], pmkId[3], pmkId[4], pmkId[5], pmkId[6], pmkId[7], pmkId[8], pmkId[9], pmkId[10], @@ -4213,7 +4219,7 @@ hddPrintPmkId(tANI_U8 *pmkId, tANI_U8 logLevel) * This function is used to notify the supplicant of a new PMKSA candidate. */ int wlan_hdd_cfg80211_pmksa_candidate_notify( - hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, + hdd_adapter_t *pAdapter, tCsrRoamInfo *pRoamInfo, int index, bool preauth ) { #ifdef FEATURE_WLAN_OKC @@ -4236,7 +4242,7 @@ int wlan_hdd_cfg80211_pmksa_candidate_notify( pRoamInfo->bssid, preauth, GFP_KERNEL); } #endif /* FEATURE_WLAN_OKC */ - return 0; + return 0; } #endif //FEATURE_WLAN_LFR @@ -4245,11 +4251,11 @@ int wlan_hdd_cfg80211_pmksa_candidate_notify( * scanning callback function, called after finishing scan * */ -static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, +static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, void *pContext, tANI_U32 scanId, eCsrScanStatus status) { struct net_device *dev = (struct net_device *) pContext; - //struct wireless_dev *wdev = dev->ieee80211_ptr; + //struct wireless_dev *wdev = dev->ieee80211_ptr; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info; @@ -4260,7 +4266,7 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, hddLog(VOS_TRACE_LEVEL_INFO, "%s called with halHandle = %p, pContext = %p," - "scanID = %d, returned status = %d\n", + "scanID = %d, returned status = %d\n", __func__, halHandle, pContext, (int) scanId, (int) status); //Block on scan req completion variable. Can't wait forever though. @@ -4280,19 +4286,19 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, } /* Check the scanId */ - if (pScanInfo->scanId != scanId) + if (pScanInfo->scanId != scanId) { hddLog(VOS_TRACE_LEVEL_INFO, "%s called with mismatched scanId pScanInfo->scanId = %d " - "scanId = %d \n", __func__, (int) pScanInfo->scanId, + "scanId = %d \n", __func__, (int) pScanInfo->scanId, (int) scanId); } - ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy, + ret = wlan_hdd_cfg80211_update_bss((WLAN_HDD_GET_CTX(pAdapter))->wiphy, pAdapter); if (0 > ret) - hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); + hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); /* If any client wait scan result through WEXT @@ -4333,7 +4339,7 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, /* * setting up 0, just in case. - */ + */ req->n_ssids = 0; req->n_channels = 0; req->ie = 0; @@ -4357,7 +4363,7 @@ static eHalStatus hdd_cfg80211_scan_done_callback(tHalHandle halHandle, * immediatly after the driver gets connect request(i.e after scan) * from supplicant, this result in app's is suspending and not able * to process the connect request to AP */ - hdd_allow_suspend_timeout(100); + hdd_allow_suspend_timeout(1000); #ifdef FEATURE_WLAN_TDLS wlan_hdd_tdls_scan_done_callback(pAdapter); @@ -4390,7 +4396,7 @@ v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx ) if( pAdapter ) { hddLog(VOS_TRACE_LEVEL_INFO, - "%s: Adapter with device mode %d exists", + "%s: Adapter with device mode %d exists", __func__, pAdapter->device_mode); if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || @@ -4403,7 +4409,7 @@ v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx ) staMac = (v_U8_t *) &(pAdapter->macAddressCurrent.bytes[0]); hddLog(VOS_TRACE_LEVEL_ERROR, "%s: client %02x:%02x:%02x:%02x:%02x:%02x is in the " - "middle of WPS/EAPOL exchange.", __func__, + "middle of WPS/EAPOL exchange.", __func__, staMac[0], staMac[1], staMac[2], staMac[3], staMac[4], staMac[5]); return VOS_FALSE; @@ -4414,14 +4420,14 @@ v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx ) { for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) { - if ((pAdapter->aStaInfo[staId].isUsed) && + if ((pAdapter->aStaInfo[staId].isUsed) && (WLANTL_STA_CONNECTED == pAdapter->aStaInfo[staId].tlSTAState)) { staMac = (v_U8_t *) &(pAdapter->aStaInfo[staId].macAddrSTA.bytes[0]); hddLog(VOS_TRACE_LEVEL_ERROR, "%s: client %02x:%02x:%02x:%02x:%02x:%02x of SoftAP/P2P-GO is in the " - "middle of WPS/EAPOL exchange.", __func__, + "middle of WPS/EAPOL exchange.", __func__, staMac[0], staMac[1], staMac[2], staMac[3], staMac[4], staMac[5]); return VOS_FALSE; @@ -4435,7 +4441,7 @@ v_BOOL_t hdd_isScanAllowed( hdd_context_t *pHddCtx ) hddLog(VOS_TRACE_LEVEL_INFO, "%s: Scan allowed", __func__); return VOS_TRUE; -} +} /* * FUNCTION: wlan_hdd_cfg80211_scan @@ -4451,15 +4457,15 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) struct net_device *dev = request->wdev->netdev; #endif - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); hdd_wext_state_t *pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - hdd_config_t *cfg_param = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + hdd_config_t *cfg_param = NULL; tCsrScanRequest scanRequest; tANI_U8 *channelList = NULL, i; v_U32_t scanId = 0; - int status = 0; - hdd_scaninfo_t *pScanInfo = &pHddCtx->scan_info; + int status; + hdd_scaninfo_t *pScanInfo = NULL; v_U8_t* pP2pIe = NULL; ENTER(); @@ -4467,6 +4473,18 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + + cfg_param = pHddCtx->cfg_ini; + pScanInfo = &pHddCtx->scan_info; + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && (eConnectionState_Connecting == (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) @@ -4501,20 +4519,7 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, return -EBUSY; } - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } - - if ((WLAN_HDD_GET_CTX(pAdapter))->isLoadUnloadInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:Unloading/Loading in Progress. Ignore!!!", __func__); - return -EAGAIN; - } - //Don't Allow Scan and return busy if Remain On + //Don't Allow Scan and return busy if Remain On //Channel and action frame is pending //Otherwise Cancel Remain On Channel and allow Scan //If no action frame pending @@ -4546,13 +4551,13 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, VOS_TRACE(VOS_MODULE_ID_HDD,VOS_TRACE_LEVEL_ERROR, "%s: Acquire lock fail", __func__); return -EAGAIN; - } + } if (TRUE == pHddCtx->tmInfo.tmAction.enterImps) { hddLog(VOS_TRACE_LEVEL_WARN, "%s: MAX TM Level Scan not allowed", __func__); mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); - return -EBUSY; + return -EBUSY; } mutex_unlock(&pHddCtx->tmInfo.tmOperationLock); @@ -4563,13 +4568,13 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Scan not allowed", __func__); return -EBUSY; } - + vos_mem_zero( &scanRequest, sizeof(scanRequest)); if (NULL != request) { hddLog(VOS_TRACE_LEVEL_INFO, "scan request for ssid = %d", - (int)request->n_ssids); + (int)request->n_ssids); /* Even though supplicant doesn't provide any SSIDs, n_ssids is set to 1. * Becasue of this, driver is assuming that this is not wildcard scan and so @@ -4621,7 +4626,7 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, /*Set the scan type to default type, in this case it is ACTIVE*/ scanRequest.scanType = pScanInfo->scan_mode; } - scanRequest.minChnTime = cfg_param->nActiveMinChnTime; + scanRequest.minChnTime = cfg_param->nActiveMinChnTime; scanRequest.maxChnTime = cfg_param->nActiveMaxChnTime; } else @@ -4661,16 +4666,16 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, /* set requestType to full scan */ scanRequest.requestType = eCSR_SCAN_REQUEST_FULL_SCAN; - - /* Flush the scan results(only p2p beacons) for STA scan and P2P + + /* Flush the scan results(only p2p beacons) for STA scan and P2P * search (Flush on both full scan and social scan but not on single - * channel scan).P2P search happens on 3 social channels (1, 6, 11) + * channel scan).P2P search happens on 3 social channels (1, 6, 11) */ /* Supplicant does single channel scan after 8-way handshake - * and in that case driver shoudnt flush scan results. If - * driver flushes the scan results here and unfortunately if - * the AP doesnt respond to our probe req then association + * and in that case driver shoudnt flush scan results. If + * driver flushes the scan results here and unfortunately if + * the AP doesnt respond to our probe req then association * fails which is not desired */ @@ -4683,19 +4688,31 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, if( request->ie_len ) { /* save this for future association (join requires this) */ + /*TODO: Array needs to be converted to dynamic allocation, + * as multiple ie.s can be sent in cfg80211_scan_request structure + * CR 597966 + */ memset( &pScanInfo->scanAddIE, 0, sizeof(pScanInfo->scanAddIE) ); memcpy( pScanInfo->scanAddIE.addIEdata, request->ie, request->ie_len); pScanInfo->scanAddIE.length = request->ie_len; - if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) || - (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode) - ) + (WLAN_HDD_P2P_DEVICE == pAdapter->device_mode)) { - pwextBuf->roamProfile.pAddIEScan = pScanInfo->scanAddIE.addIEdata; - pwextBuf->roamProfile.nAddIEScanLength = pScanInfo->scanAddIE.length; - } + if ( request->ie_len <= SIR_MAC_MAX_IE_LENGTH) + { + pwextBuf->roamProfile.nAddIEScanLength = request->ie_len; + memcpy( pwextBuf->roamProfile.addIEScan, + request->ie, request->ie_len); + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, "Scan Ie length is invalid:" + "%d", request->ie_len); + } + } scanRequest.uIEFieldLen = pScanInfo->scanAddIE.length; scanRequest.pIEField = pScanInfo->scanAddIE.addIEdata; @@ -4810,9 +4827,9 @@ int wlan_hdd_cfg80211_scan( struct wiphy *wiphy, /* * FUNCTION: wlan_hdd_cfg80211_connect_start - * This function is used to start the association process + * This function is used to start the association process */ -int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, +int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, const u8 *ssid, size_t ssid_len, const u8 *bssid, u8 operatingChannel) { int status = 0; @@ -4825,7 +4842,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, ENTER(); pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); - + if (SIR_MAC_MAX_SSID_LENGTH < ssid_len) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: wrong SSID len", __func__); @@ -4834,7 +4851,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, pRoamProfile = &pWextState->roamProfile; - if (pRoamProfile) + if (pRoamProfile) { int ret = 0; hdd_station_ctx_t *pHddStaCtx; @@ -4847,7 +4864,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, { /* Issue disconnect to CSR */ INIT_COMPLETION(pAdapter->disconnect_comp_var); - if( eHAL_STATUS_SUCCESS == + if( eHAL_STATUS_SUCCESS == sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, eCSR_DISCONNECT_REASON_UNSPECIFIED ) ) @@ -4872,7 +4889,7 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, } } - if (HDD_WMM_USER_MODE_NO_QOS == + if (HDD_WMM_USER_MODE_NO_QOS == (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->WmmMode) { /*QoS not enabled in cfg file*/ @@ -4881,14 +4898,14 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, else { /*QoS enabled, update uapsd mask from cfg file*/ - pRoamProfile->uapsd_mask = + pRoamProfile->uapsd_mask = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini->UapsdMask; } pRoamProfile->SSIDs.numOfSSIDs = 1; pRoamProfile->SSIDs.SSIDList->SSID.length = ssid_len; vos_mem_zero(pRoamProfile->SSIDs.SSIDList->SSID.ssId, - sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId)); + sizeof(pRoamProfile->SSIDs.SSIDList->SSID.ssId)); vos_mem_copy((void *)(pRoamProfile->SSIDs.SSIDList->SSID.ssId), ssid, ssid_len); @@ -4897,8 +4914,8 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, pRoamProfile->BSSIDs.numOfBSSIDs = 1; vos_mem_copy((void *)(pRoamProfile->BSSIDs.bssid), bssid, WNI_CFG_BSSID_LEN); - /* Save BSSID in seperate variable as well, as RoamProfile - BSSID is getting zeroed out in the association process. And in + /* Save BSSID in seperate variable as well, as RoamProfile + BSSID is getting zeroed out in the association process. And in case of join failure we should send valid BSSID to supplicant */ vos_mem_copy((void *)(pWextState->req_bssId), bssid, @@ -4907,28 +4924,12 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, if ((IW_AUTH_WPA_VERSION_WPA == pWextState->wpaVersion) || (IW_AUTH_WPA_VERSION_WPA2 == pWextState->wpaVersion)) - { + { /*set gen ie*/ hdd_SetGENIEToCsr(pAdapter, &RSNAuthType); /*set auth*/ hdd_set_csr_auth_type(pAdapter, RSNAuthType); } - else if ( (pWextState->roamProfile.AuthType.authType[0] == - eCSR_AUTH_TYPE_OPEN_SYSTEM) - && ((pWextState->roamProfile.EncryptionType.encryptionType[0] == - eCSR_ENCRYPT_TYPE_WEP40_STATICKEY) - || (pWextState->roamProfile.EncryptionType.encryptionType[0] == - eCSR_ENCRYPT_TYPE_WEP104_STATICKEY)) - ) - { - /*Android UI not having any option to configure the Authentication type to OPEN/SHARED; - * The authentication type will be always eCSR_AUTH_TYPE_OPEN_SYSTEM when WEP is used - * Use eCSR_AUTH_TYPE_AUTOSWITCH when WEP encryption used*/ - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType = - eCSR_AUTH_TYPE_AUTOSWITCH; - pWextState->roamProfile.AuthType.authType[0] = - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.authType; - } #ifdef FEATURE_WLAN_WAPI if (pAdapter->wapi_info.nWapiMode) { @@ -4979,27 +4980,24 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, pRoamProfile->ChannelInfo.ChannelList = &operatingChannel; pRoamProfile->ChannelInfo.numOfChannels = 1; } - else - { - pRoamProfile->ChannelInfo.ChannelList = NULL; - pRoamProfile->ChannelInfo.numOfChannels = 0; - } /* change conn_state to connecting before sme_RoamConnect(), because sme_RoamConnect() * has a direct path to call hdd_smeRoamCallback(), which will change the conn_state - * If direct path, conn_state will be accordingly changed to NotConnected or Associated + * If direct path, conn_state will be accordingly changed to NotConnected or Associated * by either hdd_AssociationCompletionHandler() or hdd_DisConnectHandler() in sme_RoamCallback() * if sme_RomConnect is to be queued, Connecting state will remain until it is completed. */ - if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) + if (WLAN_HDD_INFRA_STATION == pAdapter->device_mode || + WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) hdd_connSetConnectionState(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter), eConnectionState_Connecting); - - status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + + status = sme_RoamConnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, pRoamProfile, &roamId); - if( (eHAL_STATUS_SUCCESS != status) && - (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ) + if ((eHAL_STATUS_SUCCESS != status) && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode || + WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: sme_RoamConnect (session %d) failed with " @@ -5030,32 +5028,37 @@ int wlan_hdd_cfg80211_connect_start( hdd_adapter_t *pAdapter, static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter, enum nl80211_auth_type auth_type) { - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); ENTER(); /*set authentication type*/ - switch (auth_type) + switch (auth_type) { - case NL80211_AUTHTYPE_OPEN_SYSTEM: case NL80211_AUTHTYPE_AUTOMATIC: + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: set authentication type to AUTOSWITCH", __func__); + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_AUTOSWITCH; + break; + + case NL80211_AUTHTYPE_OPEN_SYSTEM: #ifdef WLAN_FEATURE_VOWIFI_11R case NL80211_AUTHTYPE_FT: #endif /* WLAN_FEATURE_VOWIFI_11R */ - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to OPEN", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; break; case NL80211_AUTHTYPE_SHARED_KEY: - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to SHARED", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_SHARED_KEY; break; #ifdef FEATURE_WLAN_CCX case NL80211_AUTHTYPE_NETWORK_EAP: - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set authentication type to CCKM WPA", __func__); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_CCKM_WPA;//eCSR_AUTH_TYPE_CCKM_RSN needs to be handled as well if required. break; @@ -5063,14 +5066,14 @@ static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter, default: - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unsupported authentication type %d", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Unsupported authentication type %d", __func__, auth_type); pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_UNKNOWN; return -EINVAL; } - pWextState->roamProfile.AuthType.authType[0] = + pWextState->roamProfile.AuthType.authType[0] = pHddStaCtx->conn_info.authType; return 0; } @@ -5080,13 +5083,13 @@ static int wlan_hdd_cfg80211_set_auth_type(hdd_adapter_t *pAdapter, * This function is used to set the key mgmt type(PSK/8021x). * */ -static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, +static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, u32 key_mgmt ) { hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); ENTER(); - + /*set key mgmt type*/ switch(key_mgmt) { @@ -5118,7 +5121,7 @@ static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, #endif default: - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported key mgmt type %d", __func__, key_mgmt); return -EINVAL; @@ -5128,56 +5131,48 @@ static int wlan_hdd_set_akm_suite( hdd_adapter_t *pAdapter, /* * FUNCTION: wlan_hdd_cfg80211_set_cipher - * This function is used to set the encryption type + * This function is used to set the encryption type * (NONE/WEP40/WEP104/TKIP/CCMP). */ -static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, - u32 cipher, +static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, + u32 cipher, bool ucast ) { eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); ENTER(); - if (!cipher) + if (!cipher) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: received cipher %d - considering none", __func__, cipher); encryptionType = eCSR_ENCRYPT_TYPE_NONE; } else { - + /*set encryption method*/ - switch (cipher) + switch (cipher) { case IW_AUTH_CIPHER_NONE: encryptionType = eCSR_ENCRYPT_TYPE_NONE; break; - + case WLAN_CIPHER_SUITE_WEP40: - if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && - (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) - encryptionType = eCSR_ENCRYPT_TYPE_WEP40; - else - encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; + encryptionType = eCSR_ENCRYPT_TYPE_WEP40; break; - + case WLAN_CIPHER_SUITE_WEP104: - if ((IW_AUTH_KEY_MGMT_802_1X == pWextState->authKeyMgmt) && - (eCSR_AUTH_TYPE_OPEN_SYSTEM == pHddStaCtx->conn_info.authType)) - encryptionType = eCSR_ENCRYPT_TYPE_WEP104; - else - encryptionType = eCSR_ENCRYPT_TYPE_WEP104_STATICKEY; + encryptionType = eCSR_ENCRYPT_TYPE_WEP104; break; - + case WLAN_CIPHER_SUITE_TKIP: encryptionType = eCSR_ENCRYPT_TYPE_TKIP; break; - + case WLAN_CIPHER_SUITE_CCMP: encryptionType = eCSR_ENCRYPT_TYPE_AES; break; @@ -5193,7 +5188,7 @@ static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, break; #endif default: - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unsupported cipher type %d", __func__, cipher); return -EOPNOTSUPP; } @@ -5201,16 +5196,16 @@ static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, if (ucast) { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d", + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting unicast cipher type to %d", __func__, encryptionType); pHddStaCtx->conn_info.ucEncryptionType = encryptionType; pWextState->roamProfile.EncryptionType.numEntries = 1; - pWextState->roamProfile.EncryptionType.encryptionType[0] = + pWextState->roamProfile.EncryptionType.encryptionType[0] = encryptionType; } else { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d", + hddLog(VOS_TRACE_LEVEL_INFO, "%s: setting mcast cipher type to %d", __func__, encryptionType); pHddStaCtx->conn_info.mcEncryptionType = encryptionType; pWextState->roamProfile.mcEncryptionType.numEntries = 1; @@ -5225,8 +5220,8 @@ static int wlan_hdd_cfg80211_set_cipher( hdd_adapter_t *pAdapter, * FUNCTION: wlan_hdd_cfg80211_set_ie * This function is used to parse WPA/RSN IE's. */ -int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, - u8 *ie, +int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, + u8 *ie, size_t ie_len ) { @@ -5252,25 +5247,25 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, elementId = *genie++; eLen = *genie++; remLen -= 2; - - hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n", + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: IE[0x%X], LEN[%d]\n", __func__, elementId, eLen); - - switch ( elementId ) + + switch ( elementId ) { - case DOT11F_EID_WPA: + case DOT11F_EID_WPA: if (4 > eLen) /* should have at least OUI which is 4 bytes so extra 2 bytes not needed */ { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid WPA IE", __func__); return -EINVAL; } - else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) + else if (0 == memcmp(&genie[0], "\x00\x50\xf2\x04", 4)) { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPS IE(len %d)", __func__, eLen + 2); - + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) { hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE. " @@ -5281,28 +5276,28 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, // WSC IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); pWextState->assocAddIE.length += eLen + 2; - + pWextState->roamProfile.bWPSAssociation = VOS_TRUE; pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; } - else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) - { + else if (0 == memcmp(&genie[0], "\x00\x50\xf2", 3)) + { hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WPA IE (len %d)",__func__, eLen + 2); memset( pWextState->WPARSNIE, 0, MAX_WPA_RSN_IE_LEN ); memcpy( pWextState->WPARSNIE, genie - 2, (eLen + 2) /*ie_len*/); pWextState->roamProfile.pWPAReqIE = pWextState->WPARSNIE; pWextState->roamProfile.nWPAReqIELength = eLen + 2;//ie_len; } - else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE, - P2P_OUI_TYPE_SIZE)) + else if ( (0 == memcmp(&genie[0], P2P_OUI_TYPE, + P2P_OUI_TYPE_SIZE)) /*Consider P2P IE, only for P2P Client */ && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ) { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set P2P IE(len %d)", __func__, eLen + 2); - + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) { hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " @@ -5313,20 +5308,20 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, // P2P IE is saved to Additional IE ; it should be accumulated to handle WPS IE + P2P IE memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); pWextState->assocAddIE.length += eLen + 2; - + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; } #ifdef WLAN_FEATURE_WFD - else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE, - WFD_OUI_TYPE_SIZE)) + else if ( (0 == memcmp(&genie[0], WFD_OUI_TYPE, + WFD_OUI_TYPE_SIZE)) /*Consider WFD IE, only for P2P Client */ && (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) ) { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set WFD IE(len %d)", __func__, eLen + 2); - + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) { hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " @@ -5338,17 +5333,17 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, // WPS IE + P2P IE + WFD IE memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); pWextState->assocAddIE.length += eLen + 2; - + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; } #endif /* Appending HS 2.0 Indication Element in Assiciation Request */ - else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE, + else if ( (0 == memcmp(&genie[0], HS20_OUI_TYPE, HS20_OUI_TYPE_SIZE)) ) { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set HS20 IE(len %d)", __func__, eLen + 2); if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) @@ -5375,11 +5370,11 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, break; /* Appending Extended Capabilities with Interworking bit set in Assoc Req */ case DOT11F_EID_EXTCAP: - { + { v_U16_t curAddIELen = pWextState->assocAddIE.length; - hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)", + hddLog (VOS_TRACE_LEVEL_INFO, "%s Set Extended CAPS IE(len %d)", __func__, eLen + 2); - + if( SIR_MAC_MAX_IE_LENGTH < (pWextState->assocAddIE.length + eLen) ) { hddLog(VOS_TRACE_LEVEL_FATAL, "Cannot accommodate assocAddIE " @@ -5389,7 +5384,7 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, } memcpy( pWextState->assocAddIE.addIEdata + curAddIELen, genie - 2, eLen + 2); pWextState->assocAddIE.length += eLen + 2; - + pWextState->roamProfile.pAddIEAssoc = pWextState->assocAddIE.addIEdata; pWextState->roamProfile.nAddIEAssocLength = pWextState->assocAddIE.length; break; @@ -5400,7 +5395,7 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, hddLog(VOS_TRACE_LEVEL_INFO,"WAPI MODE IS %lu \n", pAdapter->wapi_info.nWapiMode); tmp = (u16 *)ie; - tmp = tmp + 2; // Skip element Id and Len, Version + tmp = tmp + 2; // Skip element Id and Len, Version akmsuiteCount = WPA_GET_LE16(tmp); tmp = tmp + 1; akmlist = (int *)(tmp); @@ -5420,9 +5415,9 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO PSK", __func__); pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_PSK; - } + } if (WAPI_CERT_AKM_SUITE == akmsuite[0]) - { + { hddLog(VOS_TRACE_LEVEL_INFO, "%s: WAPI AUTH MODE SET TO CERTIFICATE", __func__); pAdapter->wapi_info.wapiAuthMode = WAPI_AUTH_MODE_CERT; @@ -5430,7 +5425,7 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, break; #endif default: - hddLog (VOS_TRACE_LEVEL_ERROR, + hddLog (VOS_TRACE_LEVEL_ERROR, "%s Set UNKNOWN IE %X", __func__, elementId); /* when Unknown IE is received we should break and continue * to the next IE in the buffer instead we were returning @@ -5444,29 +5439,65 @@ int wlan_hdd_cfg80211_set_ie( hdd_adapter_t *pAdapter, return 0; } +/* + * FUNCTION: hdd_isWPAIEPresent + * Parse the received IE to find the WPA IE + * + */ +static bool hdd_isWPAIEPresent(u8 *ie, u8 ie_len) +{ + v_U8_t eLen = 0; + v_U16_t remLen = ie_len; + v_U8_t elementId = 0; + + while (remLen >= 2) + { + elementId = *ie++; + eLen = *ie++; + remLen -= 2; + if (eLen > remLen) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: IE length is wrong %d", __func__, eLen); + return FALSE; + } + if ((elementId == DOT11F_EID_WPA) && (remLen > 5)) + { + /* OUI - 0x00 0X50 0XF2 + WPA Information Element - 0x01 + WPA version - 0x01*/ + if (0 == memcmp(&ie[0], "\x00\x50\xf2\x01\x01", 5)) + return TRUE; + } + ie += eLen; + remLen -= eLen; + } + return FALSE; +} + /* * FUNCTION: wlan_hdd_cfg80211_set_privacy - * This function is used to initialize the security + * This function is used to initialize the security * parameters during connect operation. */ -int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, +int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, struct cfg80211_connect_params *req ) { int status = 0; - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); ENTER(); /*set wpa version*/ pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; - if (req->crypto.wpa_versions) + if (req->crypto.wpa_versions) { if ( (NL80211_WPA_VERSION_1 == req->crypto.wpa_versions) - && ( (req->ie_len) - && (0 == memcmp( &req->ie[2], "\x00\x50\xf2",3) ) ) ) + && ( (req->ie_len) + && (hdd_isWPAIEPresent(req->ie, req->ie_len) ) ) ) // Make sure that it is including a WPA IE. - /* Currently NL is putting WPA version 1 even for open, + /* Currently NL is putting WPA version 1 even for open, * since p2p ie is also put in same buffer. * */ { @@ -5477,8 +5508,8 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2; } } - - hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__, + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: set wpa version to %d", __func__, pWextState->wpaVersion); /*set authentication type*/ @@ -5486,7 +5517,7 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set authentication type ", __func__); return status; } @@ -5497,7 +5528,7 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, status = wlan_hdd_set_akm_suite(pAdapter, req->crypto.akm_suites[0]); if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set akm suite", __func__); return status; } @@ -5510,7 +5541,7 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, req->crypto.ciphers_pairwise[0], true); if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set unicast cipher type", __func__); return status; } @@ -5521,7 +5552,7 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, status = wlan_hdd_cfg80211_set_cipher(pAdapter, 0, true); if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set unicast cipher type", __func__); return status; } @@ -5533,38 +5564,34 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set mcast cipher type", __func__); return status; } -#ifdef WLAN_FEATURE_11W - pWextState->roamProfile.MFPEnabled = (req->mfp == NL80211_MFP_REQUIRED); -#endif - /*parse WPA/RSN IE, and set the correspoing fileds in Roam profile*/ if (req->ie_len) { status = wlan_hdd_cfg80211_set_ie(pAdapter, req->ie, req->ie_len); if ( 0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse the WPA/RSN IE", __func__); return status; } } /*incase of WEP set default key information*/ - if (req->key && req->key_len) + if (req->key && req->key_len) { if ( (WLAN_CIPHER_SUITE_WEP40 == req->crypto.ciphers_pairwise[0]) || (WLAN_CIPHER_SUITE_WEP104 == req->crypto.ciphers_pairwise[0]) ) { - if ( IW_AUTH_KEY_MGMT_802_1X + if ( IW_AUTH_KEY_MGMT_802_1X == (pWextState->authKeyMgmt & IW_AUTH_KEY_MGMT_802_1X )) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Dynamic WEP not supported", __func__); return -EOPNOTSUPP; } @@ -5573,17 +5600,17 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, u8 key_len = req->key_len; u8 key_idx = req->key_idx; - if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len) + if ((eCSR_SECURITY_WEP_KEYSIZE_MAX_BYTES >= key_len) && (CSR_MAX_NUM_KEY > key_idx) ) { - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: setting default wep key, key_idx = %hu key_len %hu", + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: setting default wep key, key_idx = %hu key_len %hu", __func__, key_idx, key_len); vos_mem_copy( - &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0], + &pWextState->roamProfile.Keys.KeyMaterial[key_idx][0], req->key, key_len); - pWextState->roamProfile.Keys.KeyLength[key_idx] = + pWextState->roamProfile.Keys.KeyLength[key_idx] = (u8)key_len; pWextState->roamProfile.Keys.defaultIndex = (u8)key_idx; } @@ -5596,46 +5623,49 @@ int wlan_hdd_cfg80211_set_privacy( hdd_adapter_t *pAdapter, /* * FUNCTION: wlan_hdd_cfg80211_set_privacy - * This function is used to initialize the security + * This function is used to initialize the security * parameters during connect operation. */ -static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *req ) { - int status = 0; - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); + int status; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( ndev ); VOS_STATUS exitbmpsStatus = VOS_STATUS_E_INVAL; hdd_context_t *pHddCtx = NULL; ENTER(); - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } #ifdef WLAN_BTAMP_FEATURE //Infra connect not supported when AMP traffic is on. - if( VOS_TRUE == WLANBAP_AmpSessionOn() ) + if( VOS_TRUE == WLANBAP_AmpSessionOn() ) { - hddLog(VOS_TRACE_LEVEL_ERROR, + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No connection when AMP is on", __func__); return -ECONNREFUSED; } #endif /*initialise security parameters*/ - status = wlan_hdd_cfg80211_set_privacy(pAdapter, req); + status = wlan_hdd_cfg80211_set_privacy(pAdapter, req); if ( 0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security params", __func__); return status; } @@ -5645,16 +5675,7 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, if((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) && (vos_concurrent_sessions_running())) { - v_CONTEXT_t pVosContext = vos_get_global_context( VOS_MODULE_ID_HDD, NULL ); - - if (NULL != pVosContext) - { - pHddCtx = vos_get_context( VOS_MODULE_ID_HDD, pVosContext); - if(NULL != pHddCtx) - { - exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); - } - } + exitbmpsStatus = hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); } if ( req->channel ) @@ -5666,8 +5687,7 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, else { status = wlan_hdd_cfg80211_connect_start(pAdapter, req->ssid, - req->ssid_len, req->bssid, - 0); + req->ssid_len, req->bssid, 0); } if (0 > status) @@ -5676,6 +5696,10 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, if((VOS_STATUS_SUCCESS == exitbmpsStatus) && (NULL != pHddCtx)) { + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } //ReEnable Bmps and Imps back hdd_enable_bmps_imps(pHddCtx); } @@ -5683,7 +5707,7 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, hddLog(VOS_TRACE_LEVEL_ERROR, "%s: connect failed", __func__); return status; } - (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_FALSE; + pHddCtx->isAmpAllowed = VOS_FALSE; EXIT(); return status; } @@ -5693,43 +5717,44 @@ static int wlan_hdd_cfg80211_connect( struct wiphy *wiphy, * FUNCTION: wlan_hdd_cfg80211_disconnect * This function is used to issue a disconnect request to SME */ -static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, struct net_device *dev, u16 reason ) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); - tCsrRoamProfile *pRoamProfile = + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + tCsrRoamProfile *pRoamProfile = &(WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter))->roamProfile; - int status = 0; + int status; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - hdd_scaninfo_t *pScanInfo = NULL; #ifdef FEATURE_WLAN_TDLS tANI_U8 staIdx; #endif - + ENTER(); - - pScanInfo = &pHddCtx->scan_info; - hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n", __func__,pAdapter->device_mode); - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d", - __func__, reason); + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disconnect called with reason code %d", + __func__, reason); - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!",__func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } + if (NULL != pRoamProfile) { /*issue disconnect request to SME, if station is in connected state*/ if (pHddStaCtx->conn_info.connState == eConnectionState_Associated) { - eCsrRoamDisconnectReason reasonCode = + eCsrRoamDisconnectReason reasonCode = eCSR_DISCONNECT_REASON_UNSPECIFIED; switch(reason) { @@ -5754,12 +5779,6 @@ static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, break; } pHddStaCtx->conn_info.connState = eConnectionState_NotConnected; - if ((pScanInfo != NULL) && pScanInfo->mScanPending) - { - hddLog(VOS_TRACE_LEVEL_INFO," Disconnect is in progress," - " Aborting Scan"); - hdd_abort_mac_scan(pHddCtx); - } (WLAN_HDD_GET_CTX(pAdapter))->isAmpAllowed = VOS_TRUE; INIT_COMPLETION(pAdapter->disconnect_comp_var); @@ -5783,13 +5802,13 @@ static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, } #endif /*issue disconnect*/ - status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), + status = sme_RoamDisconnect( WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, reasonCode); if ( 0 != status) { hddLog(VOS_TRACE_LEVEL_ERROR, - "%s csrRoamDisconnect failure, returned %d \n", + "%s csrRoamDisconnect failure, returned %d \n", __func__, (int)status ); return -EINVAL; } @@ -5814,26 +5833,26 @@ static int wlan_hdd_cfg80211_disconnect( struct wiphy *wiphy, /* * FUNCTION: wlan_hdd_cfg80211_set_privacy_ibss - * This function is used to initialize the security + * This function is used to initialize the security * settings in IBSS mode. */ static int wlan_hdd_cfg80211_set_privacy_ibss( - hdd_adapter_t *pAdapter, + hdd_adapter_t *pAdapter, struct cfg80211_ibss_params *params ) { int status = 0; - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); + hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); eCsrEncryptionType encryptionType = eCSR_ENCRYPT_TYPE_NONE; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - + ENTER(); pWextState->wpaVersion = IW_AUTH_WPA_VERSION_DISABLED; if (params->ie_len && ( NULL != params->ie) ) { - if (WLAN_EID_RSN == params->ie[0]) + if (WLAN_EID_RSN == params->ie[0]) { pWextState->wpaVersion = IW_AUTH_WPA_VERSION_WPA2; encryptionType = eCSR_ENCRYPT_TYPE_AES; @@ -5847,24 +5866,24 @@ static int wlan_hdd_cfg80211_set_privacy_ibss( if (0 > status) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to parse WPA/RSN IE", __func__); return status; } } - pWextState->roamProfile.AuthType.authType[0] = - pHddStaCtx->conn_info.authType = + pWextState->roamProfile.AuthType.authType[0] = + pHddStaCtx->conn_info.authType = eCSR_AUTH_TYPE_OPEN_SYSTEM; if (params->privacy) { - /* Security enabled IBSS, At this time there is no information available - * about the security paramters, so initialise the encryption type to + /* Security enabled IBSS, At this time there is no information available + * about the security paramters, so initialise the encryption type to * eCSR_ENCRYPT_TYPE_WEP40_STATICKEY. - * The correct security parameters will be updated later in + * The correct security parameters will be updated later in * wlan_hdd_cfg80211_add_key */ - /* Hal expects encryption type to be set inorder + /* Hal expects encryption type to be set inorder *enable privacy bit in beacons */ encryptionType = eCSR_ENCRYPT_TYPE_WEP40_STATICKEY; @@ -5879,34 +5898,37 @@ static int wlan_hdd_cfg80211_set_privacy_ibss( /* * FUNCTION: wlan_hdd_cfg80211_join_ibss - * This function is used to create/join an IBSS + * This function is used to create/join an IBSS */ -static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, struct net_device *dev, struct cfg80211_ibss_params *params ) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); tCsrRoamProfile *pRoamProfile; int status; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); ENTER(); - - hddLog(VOS_TRACE_LEVEL_INFO, + + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } if (NULL == pWextState) { - hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n", + hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n", __func__); return -EIO; } @@ -5915,7 +5937,7 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, if ( eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType ) { - hddLog (VOS_TRACE_LEVEL_ERROR, + hddLog (VOS_TRACE_LEVEL_ERROR, "%s Interface type is not set to IBSS \n", __func__); return -EINVAL; } @@ -5926,14 +5948,14 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, u8 channelNum; if (IEEE80211_BAND_5GHZ == params->channel->band) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: IBSS join is called with unsupported band %d", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: IBSS join is called with unsupported band %d", __func__, params->channel->band); return -EOPNOTSUPP; } /* Get channel number */ - channelNum = + channelNum = ieee80211_frequency_to_channel(params->channel->center_freq); /*TODO: use macro*/ @@ -5947,7 +5969,7 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, validChan, &numChans)) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: No valid channel list", __func__); return -EOPNOTSUPP; } @@ -5961,37 +5983,37 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, } if (indx >= numChans) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %d", __func__, channelNum); return -EINVAL; } /* Set the Operational Channel */ - hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__, + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: set channel %d", __func__, channelNum); pRoamProfile->ChannelInfo.numOfChannels = 1; pHddStaCtx->conn_info.operationChannel = channelNum; - pRoamProfile->ChannelInfo.ChannelList = + pRoamProfile->ChannelInfo.ChannelList = &pHddStaCtx->conn_info.operationChannel; } else { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not valid Channel %hu", __func__, channelNum); return -EINVAL; } } /* Initialize security parameters */ - status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params); + status = wlan_hdd_cfg80211_set_privacy_ibss(pAdapter, params); if (status < 0) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: failed to set security parameters", __func__); return status; } /* Issue connect start */ - status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid, + status = wlan_hdd_cfg80211_connect_start(pAdapter, params->ssid, params->ssid_len, params->bssid, 0); if (0 > status) @@ -6005,29 +6027,33 @@ static int wlan_hdd_cfg80211_join_ibss( struct wiphy *wiphy, /* * FUNCTION: wlan_hdd_cfg80211_leave_ibss - * This function is used to leave an IBSS + * This function is used to leave an IBSS */ -static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, +static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, struct net_device *dev ) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); tCsrRoamProfile *pRoamProfile; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + int status; ENTER(); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d\n",__func__,pAdapter->device_mode); if (NULL == pWextState) { - hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n", + hddLog (VOS_TRACE_LEVEL_ERROR, "%s ERROR: Data Storage Corruption\n", __func__); return -EIO; } @@ -6037,7 +6063,7 @@ static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, /* Issue disconnect only if interface type is set to IBSS */ if (eCSR_BSS_TYPE_START_IBSS != pRoamProfile->BSSType) { - hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS", + hddLog (VOS_TRACE_LEVEL_ERROR, "%s: BSS Type is not set to IBSS", __func__); return -EINVAL; } @@ -6055,19 +6081,22 @@ static int wlan_hdd_cfg80211_leave_ibss( struct wiphy *wiphy, * This function is used to set the phy parameters * (RTS Threshold/FRAG Threshold/Retry Count etc ...) */ -static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, +static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { hdd_context_t *pHddCtx = wiphy_priv(wiphy); tHalHandle hHal = pHddCtx->hHal; + int status; ENTER(); - if ( pHddCtx->isLogpInProgress ) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } if (changed & WIPHY_PARAM_RTS_THRESHOLD) @@ -6077,25 +6106,25 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, wiphy->rts_threshold; if ((WNI_CFG_RTS_THRESHOLD_STAMIN > rts_threshold) || - (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) + (WNI_CFG_RTS_THRESHOLD_STAMAX < rts_threshold)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Invalid RTS Threshold value %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid RTS Threshold value %hu", __func__, rts_threshold); return -EINVAL; } if (0 != ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, rts_threshold, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + eANI_BOOLEAN_TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for rts_threshold value %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for rts_threshold value %hu", __func__, rts_threshold); return -EIO; } - hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__, + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set rts threshold %hu", __func__, rts_threshold); } @@ -6106,20 +6135,20 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, wiphy->frag_threshold; if ((WNI_CFG_FRAGMENTATION_THRESHOLD_STAMIN > frag_threshold)|| - (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) ) + (WNI_CFG_FRAGMENTATION_THRESHOLD_STAMAX < frag_threshold) ) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Invalid frag_threshold value %hu", __func__, + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid frag_threshold value %hu", __func__, frag_threshold); return -EINVAL; } if (0 != ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, frag_threshold, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + eANI_BOOLEAN_TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for frag_threshold value %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for frag_threshold value %hu", __func__, frag_threshold); return -EIO; } @@ -6138,7 +6167,7 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, if ((WNI_CFG_LONG_RETRY_LIMIT_STAMIN > retry_value) || (WNI_CFG_LONG_RETRY_LIMIT_STAMAX < retry_value)) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Retry count %hu", __func__, retry_value); return -EINVAL; } @@ -6147,28 +6176,28 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, { if (0 != ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, retry_value, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + eANI_BOOLEAN_TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for long retry count %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for long retry count %hu", __func__, retry_value); return -EIO; } - hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu", + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set long retry count %hu", __func__, retry_value); } else if (changed & WIPHY_PARAM_RETRY_SHORT) { if (0 != ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, retry_value, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + eANI_BOOLEAN_TRUE)) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for short retry count %hu", + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for short retry count %hu", __func__, retry_value); return -EIO; } - hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu", + hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set short retry count %hu", __func__, retry_value); } } @@ -6182,33 +6211,38 @@ static int wlan_hdd_cfg80211_set_wiphy_params(struct wiphy *wiphy, */ static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35) - enum tx_power_setting type, + enum tx_power_setting type, #else - enum nl80211_tx_power_setting type, + enum nl80211_tx_power_setting type, #endif int dbm) { hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); - tHalHandle hHal = pHddCtx->hHal; + tHalHandle hHal = NULL; tSirMacAddr bssid = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; tSirMacAddr selfMac = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + int status; ENTER(); - if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, - dbm, ccmCfgSetCallback, - eANI_BOOLEAN_TRUE)) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm); - return -EIO; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - if ( pHddCtx->isLogpInProgress ) + hHal = pHddCtx->hHal; + + if (0 != ccmCfgSetInt(hHal, WNI_CFG_CURRENT_TX_POWER_LEVEL, + dbm, ccmCfgSetCallback, + eANI_BOOLEAN_TRUE)) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: ccmCfgSetInt failed for tx power %hu", __func__, dbm); + return -EIO; } hddLog(VOS_TRACE_LEVEL_INFO_MED, "%s: set tx power level %d dbm", __func__, @@ -6221,19 +6255,19 @@ static int wlan_hdd_cfg80211_set_txpower(struct wiphy *wiphy, case NL80211_TX_POWER_LIMITED: /*limit TX power by the mBm parameter*/ if( sme_SetMaxTxPower(hHal, bssid, selfMac, dbm) != eHAL_STATUS_SUCCESS ) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed", - __func__); - return -EIO; + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Setting maximum tx power failed", + __func__); + return -EIO; } break; case NL80211_TX_POWER_FIXED: /*fix TX power to the mBm parameter*/ - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported", + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: NL80211_TX_POWER_FIXED not supported", __func__); return -EOPNOTSUPP; break; default: - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d", - __func__, type); + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid power setting type %d", + __func__, type); return -EIO; } @@ -6249,21 +6283,18 @@ static int wlan_hdd_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) hdd_adapter_t *pAdapter; hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + int status; ENTER(); - if (NULL == pHddCtx) - { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); - *dbm = 0; - return -ENOENT; - } + status = wlan_hdd_validate_context(pHddCtx); - if ( pHddCtx->isLogpInProgress ) + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + *dbm = 0; + return status; } pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION); @@ -6305,6 +6336,7 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device tANI_U8 rateFlag = 1; tANI_U8 i, j, rssidx; tANI_U16 temp; + int status; #ifdef WLAN_FEATURE_11AC tANI_U32 vht_mcs_map; @@ -6322,11 +6354,13 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device return 0; } - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } wlan_hdd_get_rssi(pAdapter, &sinfo->signal); @@ -6439,7 +6473,6 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device /* Update MAX rate */ maxRate = (currentRate > maxRate)?currentRate:maxRate; } - /* Get MCS Rate Set -- but only if we are connected at MCS rates or if we are always reporting max speed or if we have good rssi */ @@ -6455,15 +6488,14 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device rateFlag = 0; #ifdef WLAN_FEATURE_11AC /* VHT80 rate has seperate rate table */ - if (rate_flags & eHAL_TX_RATE_VHT80) + if (rate_flags & (eHAL_TX_RATE_VHT20|eHAL_TX_RATE_VHT40|eHAL_TX_RATE_VHT80)) { - currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_rate[rateFlag]; ccmCfgGetInt(WLAN_HDD_GET_HAL_CTX(pAdapter), WNI_CFG_VHT_TX_MCS_MAP, &vht_mcs_map); + vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK ); if (rate_flags & eHAL_TX_RATE_SGI) { rateFlag |= 1; } - vhtMaxMcs = (eDataRate11ACMaxMcs)(vht_mcs_map & DATA_RATE_11AC_MCS_MASK); if (DATA_RATE_11AC_MAX_MCS_7 == vhtMaxMcs) { maxMCSIdx = 7; @@ -6474,14 +6506,35 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device } else if (DATA_RATE_11AC_MAX_MCS_9 == vhtMaxMcs) { - maxMCSIdx = 9; + //VHT20 is supporting 0~8 + if (rate_flags & eHAL_TX_RATE_VHT20) + maxMCSIdx = 8; + else + maxMCSIdx = 9; + } + + if (rate_flags & eHAL_TX_RATE_VHT80) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT80_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT80_rate[rateFlag]; } - maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_rate[rateFlag]; + else if (rate_flags & eHAL_TX_RATE_VHT40) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT40_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT40_rate[rateFlag]; + } + else if (rate_flags & eHAL_TX_RATE_VHT20) + { + currentRate = supported_vht_mcs_rate[pAdapter->hdd_stats.ClassA_stat.mcs_index].supported_VHT20_rate[rateFlag]; + maxRate = supported_vht_mcs_rate[maxMCSIdx].supported_VHT20_rate[rateFlag]; + } + maxSpeedMCS = 1; if (currentRate > maxRate) { maxRate = currentRate; } + } else #endif /* WLAN_FEATURE_11AC */ @@ -6516,6 +6569,13 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device } } + else if (!(rate_flags & eHAL_TX_RATE_LEGACY)) + { + maxRate = myRate; + maxSpeedMCS = 1; + maxMCSIdx = pAdapter->hdd_stats.ClassA_stat.mcs_index; + } + // make sure we report a value at least as big as our current rate if (((maxRate < myRate) && (0 == rssidx)) || (0 == maxRate)) @@ -6532,7 +6592,7 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device } } - if ((!maxSpeedMCS) || (0 != rssidx)) + if (rate_flags & eHAL_TX_RATE_LEGACY) { sinfo->txrate.legacy = maxRate; #ifdef LINKSPEED_DEBUG_ENABLED @@ -6547,26 +6607,31 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device if (rate_flags & eHAL_TX_RATE_VHT80) { sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; } - else -#endif /* WLAN_FEATURE_11AC */ + else if (rate_flags & eHAL_TX_RATE_VHT40) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; } - if (rate_flags & eHAL_TX_RATE_SGI) + else if (rate_flags & eHAL_TX_RATE_VHT20) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; + sinfo->txrate.flags |= RATE_INFO_FLAGS_VHT_MCS; } - if (rate_flags & eHAL_TX_RATE_HT40) +#endif /* WLAN_FEATURE_11AC */ + if (rate_flags & (eHAL_TX_RATE_HT20 | eHAL_TX_RATE_HT40)) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; + if (rate_flags & eHAL_TX_RATE_HT40) + { + sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; + } } -#ifdef WLAN_FEATURE_11AC - else if (rate_flags & eHAL_TX_RATE_VHT80) + if (rate_flags & eHAL_TX_RATE_SGI) { - sinfo->txrate.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; + sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; } -#endif /* WLAN_FEATURE_11AC */ + #ifdef LINKSPEED_DEBUG_ENABLED pr_info("Reporting MCS rate %d flags %x\n", sinfo->txrate.mcs, @@ -6652,11 +6717,12 @@ static int wlan_hdd_cfg80211_get_station(struct wiphy *wiphy, struct net_device } static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, - struct net_device *dev, bool mode, v_SINT_t timeout) + struct net_device *dev, bool mode, int timeout) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx; VOS_STATUS vos_status; + int status; ENTER(); @@ -6665,18 +6731,15 @@ static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Adapter is NULL\n", __func__); return -ENODEV; } - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - if (NULL == pHddCtx) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: HDD context is NULL\n", __func__); - return -ENODEV; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } if ((DRIVER_POWER_MODE_AUTO == !mode) && @@ -6685,7 +6748,10 @@ static int wlan_hdd_cfg80211_set_power_mgmt(struct wiphy *wiphy, (eConnectionState_Associated == (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) { - vos_status = hdd_conf_hostarpoffload(pAdapter, TRUE); + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: in cfg80211_set_power_mgmt, calling arp offload"); + vos_status = hdd_conf_arp_offload(pAdapter, TRUE); if (!VOS_IS_STATUS_SUCCESS(vos_status)) { hddLog(VOS_TRACE_LEVEL_INFO, @@ -6717,7 +6783,7 @@ static int wlan_hdd_set_default_mgmt_key(struct wiphy *wiphy, ENTER(); return 0; } -#endif //LINUX_VERSION_CODE +#endif //LINUX_VERSION_CODE #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,0)) static int wlan_hdd_set_txq_params(struct wiphy *wiphy, @@ -6740,28 +6806,26 @@ static int wlan_hdd_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, u8 *mac) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; VOS_STATUS vos_status; + int status; v_U8_t staId; ENTER(); - if ( NULL == pAdapter || NULL == pAdapter->pHddCtx) + if ( NULL == pAdapter ) { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__); + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__); return -EINVAL; } - if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress) - { - hddLog( LOGE, - "%s: Wlan Load/Unload is in progress", __func__); - return -EBUSY; - } + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } if ( (WLAN_HDD_SOFTAP == pAdapter->device_mode) @@ -6875,52 +6939,50 @@ static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *d { #define MAX_PMKSAIDS_IN_CACHE 8 static tPmkidCacheInfo PMKIDCache[MAX_PMKSAIDS_IN_CACHE]; // HDD Local cache - static tANI_U32 i; // HDD Local Cache index - tANI_U32 j=0; + static tANI_U32 i; // HDD Local Cache index + tANI_U32 j=0; hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); tHalHandle halHandle; - eHalStatus result; + eHalStatus result; + int status; tANI_U8 BSSIDMatched = 0; - + hdd_context_t *pHddCtx; + ENTER(); - // Validate pAdapter - if ( NULL == pAdapter || NULL == pAdapter->pHddCtx) + // Validate pAdapter + if ( NULL == pAdapter ) { - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid Adapter or HDD Context " ,__func__); + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Adapter" ,__func__); return -EINVAL; } - if (((hdd_context_t*)pAdapter->pHddCtx)->isLoadUnloadInProgress) - { - hddLog( LOGE, - "%s: Wlan Load/Unload is in progress", __func__); - return -EBUSY; - } + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); - if ( (WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress ) + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } - // Retrieve halHandle + // Retrieve halHandle halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); for (j = 0; j < i; j++) { - if(vos_mem_compare(PMKIDCache[j].BSSID, + if(vos_mem_compare(PMKIDCache[j].BSSID, pmksa->bssid, WNI_CFG_BSSID_LEN)) { /* BSSID matched previous entry. Overwrite it. */ BSSIDMatched = 1; - vos_mem_copy(PMKIDCache[j].BSSID, + vos_mem_copy(PMKIDCache[j].BSSID, pmksa->bssid, WNI_CFG_BSSID_LEN); - vos_mem_copy(PMKIDCache[j].PMKID, - pmksa->pmkid, + vos_mem_copy(PMKIDCache[j].PMKID, + pmksa->pmkid, CSR_RSN_PMKID_SIZE); - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.", + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Reusing cache entry %d.", __func__, j ); dump_bssid(pmksa->bssid); dump_pmkid(halHandle, pmksa->pmkid); @@ -6932,31 +6994,31 @@ static int wlan_hdd_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *d if(j == MAX_PMKSAIDS_IN_CACHE) i=0; if (!BSSIDMatched) - { - // Now, we DON'T have a BSSID match, so take a new entry in the cache. - vos_mem_copy(PMKIDCache[i].BSSID, - pmksa->bssid, ETHER_ADDR_LEN); - vos_mem_copy(PMKIDCache[i].PMKID, - pmksa->pmkid, + { + // Now, we DON'T have a BSSID match, so take a new entry in the cache. + vos_mem_copy(PMKIDCache[i].BSSID, + pmksa->bssid, ETHER_ADDR_LEN); + vos_mem_copy(PMKIDCache[i].PMKID, + pmksa->pmkid, CSR_RSN_PMKID_SIZE); - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.", + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Adding a new cache entry %d.", __func__, i ); dump_bssid(pmksa->bssid); dump_pmkid(halHandle, pmksa->pmkid); - // Increment the HDD Local Cache index + // Increment the HDD Local Cache index // The "i=0" doesn't work for the call to sme_RoamSetPMKIDCache() - LFR FIXME - if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0; + if (i<=(MAX_PMKSAIDS_IN_CACHE-1)) i++; else i=0; } // Calling csrRoamSetPMKIDCache to configure the PMKIDs into the cache - //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."), + //hddLog(LOG1, FL("%s: Calling csrRoamSetPMKIDCache with %d cache entries."), // __func__, i ); - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.", + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Calling csrRoamSetPMKIDCache with %d cache entries.", __func__, i ); // Finally set the PMKSA ID Cache in CSR - result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId, - PMKIDCache, + result = sme_RoamSetPMKIDCache(halHandle,pAdapter->sessionId, + PMKIDCache, i ); return 0; } @@ -6979,7 +7041,7 @@ static int wlan_hdd_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device #endif #if defined(WLAN_FEATURE_VOWIFI_11R) && defined(KERNEL_SUPPORT_11R_CFG80211) -static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, +static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_update_ft_ies_params *ftie) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -6996,13 +7058,13 @@ static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, // Added for debug on reception of Re-assoc Req. if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) { - hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"), + hddLog(LOGE, FL("Called with Ie of length = %d when not associated\n"), ftie->ie_len); hddLog(LOGE, FL("Should be Re-assoc Req IEs\n")); } #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__, + hddLog(LOGE, FL("%s called with Ie of length = %d\n"), __func__, ftie->ie_len); #endif @@ -7014,6 +7076,299 @@ static int wlan_hdd_cfg80211_update_ft_ies(struct wiphy *wiphy, } #endif +#ifdef FEATURE_WLAN_SCAN_PNO + +void hdd_cfg80211_sched_scan_done_callback(void *callbackContext, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) +{ + int ret; + hdd_adapter_t* pAdapter = (hdd_adapter_t*)callbackContext; + hdd_context_t *pHddCtx; + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter is Null", __func__); + return ; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is Null!!!", __func__); + return ; + } + + spin_lock(&pHddCtx->schedScan_lock); + if (TRUE == pHddCtx->isWiphySuspended) + { + pHddCtx->isSchedScanUpdatePending = TRUE; + spin_unlock(&pHddCtx->schedScan_lock); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Update cfg80211 scan database after it resume", __func__); + return ; + } + spin_unlock(&pHddCtx->schedScan_lock); + + ret = wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter); + + if (0 > ret) + hddLog(VOS_TRACE_LEVEL_INFO, "%s: NO SCAN result", __func__); + + cfg80211_sched_scan_results(pHddCtx->wiphy); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: cfg80211 scan result database updated", __func__); +} + +/* + * FUNCTION: wlan_hdd_cfg80211_sched_scan_start + * NL interface to enable PNO + */ +static int wlan_hdd_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, struct cfg80211_sched_scan_request *request) +{ + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + tpSirPNOScanReq pPnoRequest = NULL; + hdd_context_t *pHddCtx; + tHalHandle hHal; + v_U32_t i, indx, num_ch; + u8 valid_ch[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + u8 channels_allowed[WNI_CFG_VALID_CHANNEL_LIST_LEN]; + v_U32_t num_channels_allowed = WNI_CFG_VALID_CHANNEL_LIST_LEN; + eHalStatus status = eHAL_STATUS_FAILURE; + int ret = 0; + + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter is Null", __func__); + return -ENODEV; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + ret = wlan_hdd_validate_context(pHddCtx); + + if (0 != ret) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return -EINVAL; + } + + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HAL context is Null!!!", __func__); + return -EINVAL; + } + + pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq)); + if (NULL == pPnoRequest) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_malloc failed", __func__); + return -ENOMEM; + } + + pPnoRequest->enable = 1; /*Enable PNO */ + pPnoRequest->ucNetworksCount = request->n_match_sets; + + if (( !pPnoRequest->ucNetworksCount ) || + ( pPnoRequest->ucNetworksCount > SIR_PNO_MAX_SUPP_NETWORKS )) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Network input is not correct"); + ret = -EINVAL; + goto error; + } + + if ( SIR_PNO_MAX_NETW_CHANNELS_EX < request->n_channels ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Incorrect number of channels"); + ret = -EINVAL; + goto error; + } + + /* Framework provides one set of channels(all) + * common for all saved profile */ + if (0 != ccmCfgGetStr(hHal, WNI_CFG_VALID_CHANNEL_LIST, + channels_allowed, &num_channels_allowed)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to get valid channel list", __func__); + ret = -EINVAL; + goto error; + } + /* Checking each channel against allowed channel list */ + num_ch = 0; + for (i = 0; i < request->n_channels; i++) + { + for (indx = 0; indx < num_channels_allowed; indx++) + { + if (request->channels[i]->hw_value == channels_allowed[indx]) + { + valid_ch[num_ch++] = request->channels[i]->hw_value; + break ; + } + } + } + + /* Filling per profile params */ + for (i = 0; i < pPnoRequest->ucNetworksCount; i++) + { + pPnoRequest->aNetworks[i].ssId.length = + request->match_sets[i].ssid.ssid_len; + + if (( 0 == pPnoRequest->aNetworks[i].ssId.length ) || + ( pPnoRequest->aNetworks[i].ssId.length > 32 ) ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "SSID Len %d is not correct for network %d", + pPnoRequest->aNetworks[i].ssId.length, i); + ret = -EINVAL; + goto error; + } + + memcpy(pPnoRequest->aNetworks[i].ssId.ssId, + request->match_sets[i].ssid.ssid, + request->match_sets[i].ssid.ssid_len); + pPnoRequest->aNetworks[i].authentication = 0; /*eAUTH_TYPE_ANY*/ + pPnoRequest->aNetworks[i].encryption = 0; /*eED_ANY*/ + pPnoRequest->aNetworks[i].bcastNetwType = 0; /*eBCAST_UNKNOWN*/ + + /*Copying list of valid channel into request */ + memcpy(pPnoRequest->aNetworks[i].aChannels, valid_ch, num_ch); + pPnoRequest->aNetworks[i].ucChannelCount = num_ch; + + pPnoRequest->aNetworks[i].rssiThreshold = 0; //Default value + } + + /* framework provides interval in ms */ + pPnoRequest->scanTimers.ucScanTimersCount = 1; + pPnoRequest->scanTimers.aTimerValues[0].uTimerValue = + (request->interval)/1000; + pPnoRequest->scanTimers.aTimerValues[0].uTimerRepeat = 0; + pPnoRequest->modePNO = SIR_PNO_MODE_ON_SUSPEND; + + status = sme_SetPreferredNetworkList(WLAN_HDD_GET_HAL_CTX(pAdapter), + pPnoRequest, pAdapter->sessionId, + hdd_cfg80211_sched_scan_done_callback, pAdapter); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Failed to enable PNO"); + ret = -EINVAL; + goto error; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "PNO scanRequest offloaded"); + +error: + vos_mem_free(pPnoRequest); + return ret; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_sched_scan_stop + * NL interface to disable PNO + */ +static int wlan_hdd_cfg80211_sched_scan_stop(struct wiphy *wiphy, + struct net_device *dev) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; + tHalHandle hHal; + tpSirPNOScanReq pPnoRequest = NULL; + int ret = 0; + + ENTER(); + + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter is Null", __func__); + return -ENODEV; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is Null", __func__); + return -ENODEV; + } + + /* The return 0 is intentional when isLogpInProgress and + * isLoadUnloadInProgress. We did observe a crash due to a return of + * failure in sched_scan_stop , especially for a case where the unload + * of the happens at the same time. The function __cfg80211_stop_sched_scan + * was clearing rdev->sched_scan_req only when the sched_scan_stop returns + * success. If it returns a failure , then its next invocation due to the + * clean up of the second interface will have the dev pointer corresponding + * to the first one leading to a crash. + */ + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return ret; + } + + if (pHddCtx->isLoadUnloadInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return ret; + } + + hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + if (NULL == hHal) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HAL context is Null!!!", __func__); + return -EINVAL; + } + + pPnoRequest = (tpSirPNOScanReq) vos_mem_malloc(sizeof (tSirPNOScanReq)); + if (NULL == pPnoRequest) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_malloc failed", __func__); + return -ENOMEM; + } + + memset(pPnoRequest, 0, sizeof (tSirPNOScanReq)); + pPnoRequest->enable = 0; /* Disable PNO */ + pPnoRequest->ucNetworksCount = 0; + + status = sme_SetPreferredNetworkList(hHal, pPnoRequest, + pAdapter->sessionId, + NULL, pAdapter); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Failed to disabled PNO"); + ret = -EINVAL; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: PNO scan disabled", __func__); + + vos_mem_free(pPnoRequest); + + EXIT(); + return ret; +} + +#endif /*FEATURE_WLAN_SCAN_PNO*/ + + #ifdef FEATURE_WLAN_TDLS static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, u8 *peer, u8 action_code, u8 dialog_token, @@ -7026,10 +7381,11 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d VOS_STATUS status; int max_sta_failed = 0; int responder; + long rc; if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini) { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "Invalid arguments"); return -EINVAL; } @@ -7051,12 +7407,6 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d return -ENOTSUPP; } - if ((SIR_MAC_TDLS_SETUP_RSP == action_code) || - (SIR_MAC_TDLS_DIS_RSP == action_code)) - { - wlan_hdd_tdls_set_cap (pAdapter, peer, eTDLS_CAP_SUPPORTED); - } - /* other than teardown frame, other mgmt frames are not sent if disabled */ if (SIR_MAC_TDLS_TEARDOWN != action_code) { @@ -7074,7 +7424,7 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d if (WLAN_IS_TDLS_SETUP_ACTION(action_code)) { - if (wlan_hdd_tdls_is_progress(pAdapter, peer, TRUE)) + if (NULL != wlan_hdd_tdls_is_progress(pHddCtx, peer, TRUE, TRUE)) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: " MAC_ADDRESS_STR @@ -7141,17 +7491,38 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d responder = 0; if (SIR_MAC_TDLS_TEARDOWN == action_code) { - responder = wlan_hdd_tdls_get_responder(pAdapter, peerMac); - if(-1 == responder) + + hddTdlsPeer_t *pTdlsPeer; + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peerMac); + + if(pTdlsPeer && TDLS_IS_CONNECTED(pTdlsPeer)) + responder = pTdlsPeer->is_responder; + else { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: " MAC_ADDRESS_STR " peer doesn't exist dialog_token %d status %d, len = %d", - "tdls_mgmt", MAC_ADDR_ARRAY(peer), - dialog_token, status_code, len); - return -EPERM; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: " MAC_ADDRESS_STR " peer doesn't exist or not connected %d dialog_token %d status %d, len = %d", + __func__, MAC_ADDR_ARRAY(peer), (NULL == pTdlsPeer) ? -1 : pTdlsPeer->link_status, + dialog_token, status_code, len); + return -EPERM; } } + /* For explicit trigger of DIS_REQ come out of BMPS for + successfully receiving DIS_RSP from peer. */ + if ((SIR_MAC_TDLS_SETUP_RSP == action_code) || + (SIR_MAC_TDLS_DIS_RSP == action_code) || + (SIR_MAC_TDLS_DIS_REQ == action_code)) + { + if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: Sending frame action_code %u.Disable BMPS", __func__, action_code); + hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); + } + if (SIR_MAC_TDLS_DIS_REQ != action_code) + wlan_hdd_tdls_set_cap(pAdapter, peerMac, eTDLS_CAP_SUPPORTED); + } + INIT_COMPLETION(pAdapter->tdls_mgmt_comp); status = sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, @@ -7161,28 +7532,27 @@ static int wlan_hdd_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *d { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: sme_SendTdlsMgmtFrame failed!", __func__); - return -EPERM; + wlan_hdd_tdls_check_bmps(pAdapter); + goto error; } - /* not block discovery request, as it is called from timer callback */ - if (SIR_MAC_TDLS_DIS_REQ != action_code) - { - long rc; + rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp, + msecs_to_jiffies(WAIT_TIME_TDLS_MGMT)); - rc = wait_for_completion_interruptible_timeout(&pAdapter->tdls_mgmt_comp, - msecs_to_jiffies(WAIT_TIME_TDLS_MGMT)); - - if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus)) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu", - __func__, rc, pAdapter->mgmtTxCompletionStatus); - return -EPERM; - } + if ((rc <= 0) || (TRUE != pAdapter->mgmtTxCompletionStatus)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Mgmt Tx Completion failed status %ld TxCompletion %lu", + __func__, rc, pAdapter->mgmtTxCompletionStatus); + wlan_hdd_tdls_check_bmps(pAdapter); + goto error; } if (max_sta_failed) + { + wlan_hdd_tdls_check_bmps(pAdapter); return max_sta_failed; + } if (SIR_MAC_TDLS_SETUP_RSP == action_code) { @@ -7211,39 +7581,24 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx = wiphy_priv(wiphy); -#ifdef WLAN_FEATURE_TDLS_DEBUG - const char *tdls_oper_str[]= { - "NL80211_TDLS_DISCOVERY_REQ", - "NL80211_TDLS_SETUP", - "NL80211_TDLS_TEARDOWN", - "NL80211_TDLS_ENABLE_LINK", - "NL80211_TDLS_DISABLE_LINK", - "NL80211_TDLS_UNKONW_OPER"}; -#endif + int status; - if ( NULL == pHddCtx || NULL == pHddCtx->cfg_ini || NULL == peer ) + if ( NULL == peer ) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Invalid arguments", __func__); return -EINVAL; } - if (pHddCtx->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } -#ifdef WLAN_FEATURE_TDLS_DEBUG - if((int)oper > 4) - oper = 5; - - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: " MAC_ADDRESS_STR " %d (%s) ", "tdls_oper", - MAC_ADDR_ARRAY(peer), (int)oper, - tdls_oper_str[(int)oper]); -#endif if( FALSE == pHddCtx->cfg_ini->fEnableTDLSSupport || FALSE == sme_IsFeatureSupportedByFW(TDLS)) @@ -7273,13 +7628,35 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d return -EINVAL; } + if (!TDLS_STA_INDEX_VALID(pTdlsPeer->staId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Invalid Staion Index %u " + MAC_ADDRESS_STR " failed", + __func__, pTdlsPeer->staId, MAC_ADDR_ARRAY(peer)); + return -EINVAL; + } + if (eTDLS_LINK_CONNECTING == pTdlsPeer->link_status) { wlan_hdd_tdls_set_peer_link_status(pTdlsPeer, eTDLS_LINK_CONNECTED); - /* start TDLS client registration with TL */ - status = hdd_roamRegisterTDLSSTA( pAdapter, peer, pTdlsPeer->staId, pTdlsPeer->signature); + /* Mark TDLS client Authenticated .*/ + status = WLANTL_ChangeSTAState( pHddCtx->pvosContext, + pTdlsPeer->staId, + WLANTL_STA_AUTHENTICATED); if (VOS_STATUS_SUCCESS == status) { + if (pTdlsPeer->is_responder == 0) + { + v_U8_t staId = (v_U8_t)pTdlsPeer->staId; + + wlan_hdd_tdls_timer_restart(pAdapter, + &pTdlsPeer->initiatorWaitTimeoutTimer, + WAIT_TIME_TDLS_INITIATOR); + /* suspend initiator TX until it receives direct packet from the + reponder or WAIT_TIME_TDLS_INITIATOR timer expires */ + WLANTL_SuspendDataTx( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, + &staId, NULL); + } wlan_hdd_tdls_increment_peer_count(pAdapter); } wlan_hdd_tdls_check_bmps(pAdapter); @@ -7291,7 +7668,7 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d { hddTdlsPeer_t *curr_peer = wlan_hdd_tdls_find_peer(pAdapter, peer); - if(NULL != curr_peer) + if((NULL != curr_peer) && TDLS_STA_INDEX_VALID(curr_peer->staId)) { long status; @@ -7320,7 +7697,63 @@ static int wlan_hdd_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *d } break; case NL80211_TDLS_TEARDOWN: + { + hddTdlsPeer_t *pTdlsPeer; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " %s : NL80211_TDLS_TEARDOWN for " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + + if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) || + (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " %s TDLS External control and Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + + if ( 0 != wlan_hdd_tdls_remove_force_peer(pAdapter, peer) ) + return -EINVAL; + + pTdlsPeer = wlan_hdd_tdls_find_peer(pAdapter, peer); + + if ( NULL == pTdlsPeer ) { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: " MAC_ADDRESS_STR + " (oper %d) peer not exsting", + __func__, MAC_ADDR_ARRAY(peer)); + } + else { + wlan_hdd_tdls_indicate_teardown(pAdapter, pTdlsPeer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } + break; + } case NL80211_TDLS_SETUP: + { + hddTdlsPeer_t *pTdlsPeer; + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " %s : NL80211_TDLS_SETUP for " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(peer)); + + if ( (FALSE == pHddCtx->cfg_ini->fTDLSExternalControl) || + (FALSE == pHddCtx->cfg_ini->fEnableTDLSImplicitTrigger) ) { + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + " %s TDLS External control and Implicit Trigger not enabled ", + __func__); + return -ENOTSUPP; + } + + if ( 0 != wlan_hdd_tdls_add_force_peer(pAdapter, peer) ) + return -EINVAL; + /* To cater the requirement of establishing the TDLS link + * irrespective of the data traffic , get an entry of TDLS peer. + */ + pTdlsPeer = wlan_hdd_tdls_get_peer(pAdapter, peer); + if (pTdlsPeer == NULL) + return -EINVAL; + break; + } case NL80211_TDLS_DISCOVERY_REQ: /* We don't support in-driver setup/teardown/discovery */ return -ENOTSUPP; @@ -7393,6 +7826,7 @@ int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev hdd_context_t *pHddCtx = wiphy_priv(wiphy); hdd_station_ctx_t *pHddStaCtx; tHalHandle hHal; + int result; tpSirGtkOffloadParams pGtkOffloadReqParams; eHalStatus status = eHAL_STATUS_FAILURE; @@ -7405,25 +7839,13 @@ int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev return -ENODEV; } - if (NULL == pHddCtx) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: HDD context is Null!!!", __func__); - return -ENODEV; - } - - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } + result = wlan_hdd_validate_context(pHddCtx); - if (pHddCtx->isLoadUnloadInProgress) + if (0 != result) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s: Unloading/Loading in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return result; } pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); @@ -7475,8 +7897,241 @@ int wlan_hdd_cfg80211_set_rekey_data(struct wiphy *wiphy, struct net_device *dev } #endif /*WLAN_FEATURE_GTK_OFFLOAD*/ +/* + * FUNCTION: wlan_hdd_cfg80211_set_mac_acl + * This function is used to set access control policy + */ +static int wlan_hdd_cfg80211_set_mac_acl(struct wiphy *wiphy, + struct net_device *dev, const struct cfg80211_acl_data *params) +{ + int i; + hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_hostapd_state_t *pHostapdState; + tsap_Config_t *pConfig; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx; + int status; + + ENTER(); + + if (NULL == pAdapter) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HDD adapter is Null", __func__); + return -ENODEV; + } + + if (NULL == params) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: params is Null", __func__); + return -EINVAL; + } + + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } + + pVosContext = pHddCtx->pvosContext; + pHostapdState = WLAN_HDD_GET_HOSTAP_STATE_PTR(pAdapter); + + if (NULL == pHostapdState) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: pHostapdState is Null", __func__); + return -EINVAL; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"acl policy: = %d" + "no acl entries = %d", params->acl_policy, params->n_acl_entries); + + if (WLAN_HDD_SOFTAP == pAdapter->device_mode) + { + pConfig = &pAdapter->sessionCtx.ap.sapConfig; + + /* default value */ + pConfig->num_accept_mac = 0; + pConfig->num_deny_mac = 0; + + /** + * access control policy + * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are + * listed in hostapd.deny file. + * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow stations which are + * listed in hostapd.accept file. + */ + if (NL80211_ACL_POLICY_DENY_UNLESS_LISTED == params->acl_policy) + { + pConfig->SapMacaddr_acl = eSAP_DENY_UNLESS_ACCEPTED; + } + else if (NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED == params->acl_policy) + { + pConfig->SapMacaddr_acl = eSAP_ACCEPT_UNLESS_DENIED; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s:Acl Policy : %d is not supported", + __func__, params->acl_policy); + return -ENOTSUPP; + } + + if (eSAP_DENY_UNLESS_ACCEPTED == pConfig->SapMacaddr_acl) + { + pConfig->num_accept_mac = params->n_acl_entries; + for (i = 0; i < params->n_acl_entries; i++) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "** Add ACL MAC entry %i in WhiletList :" + MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(params->mac_addrs[i].addr)); + + vos_mem_copy(&pConfig->accept_mac[i], params->mac_addrs[i].addr, + sizeof(qcmacaddr)); + } + } + else if (eSAP_ACCEPT_UNLESS_DENIED == pConfig->SapMacaddr_acl) + { + pConfig->num_deny_mac = params->n_acl_entries; + for (i = 0; i < params->n_acl_entries; i++) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "** Add ACL MAC entry %i in BlackList :" + MAC_ADDRESS_STR, i, + MAC_ADDR_ARRAY(params->mac_addrs[i].addr)); + + vos_mem_copy(&pConfig->deny_mac[i], params->mac_addrs[i].addr, + sizeof(qcmacaddr)); + } + } + + if (VOS_STATUS_SUCCESS != WLANSAP_SetMacACL(pVosContext, pConfig)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: SAP Set Mac Acl fail", __func__); + return -EINVAL; + } + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid device_mode = %d", + __func__, pAdapter->device_mode); + return -EINVAL; + } + + return 0; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_resume_wlan + * this is called when cfg80211 driver resume + * driver updates latest sched_scan scan result(if any) to cfg80211 database + */ +int wlan_hdd_cfg80211_resume_wlan(struct wiphy *wiphy) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + hdd_adapter_t *pAdapter; + hdd_adapter_list_node_t *pAdapterNode, *pNext; + VOS_STATUS status = VOS_STATUS_SUCCESS; + + ENTER(); + + if ( NULL == pHddCtx ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HddCtx validation failed", __func__); + return 0; + } + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return 0; + } + + if (pHddCtx->isLoadUnloadInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return 0; + } + + spin_lock(&pHddCtx->schedScan_lock); + pHddCtx->isWiphySuspended = FALSE; + if (TRUE != pHddCtx->isSchedScanUpdatePending) + { + spin_unlock(&pHddCtx->schedScan_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Return resume is not due to PNO indication", __func__); + return 0; + } + // Reset flag to avoid updatating cfg80211 data old results again + pHddCtx->isSchedScanUpdatePending = FALSE; + spin_unlock(&pHddCtx->schedScan_lock); + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + if ( (NULL != pAdapter) && + (WLAN_HDD_INFRA_STATION == pAdapter->device_mode) ) + { + if (0 != wlan_hdd_cfg80211_update_bss(pHddCtx->wiphy, pAdapter)) + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + "%s: NO SCAN result", __func__); + else + cfg80211_sched_scan_results(pHddCtx->wiphy); + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s : cfg80211 scan result database updated", __func__); + + return 0; + + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Failed to find Adapter", __func__); + return 0; +} + +/* + * FUNCTION: wlan_hdd_cfg80211_suspend_wlan + * this is called when cfg80211 driver suspends + */ +int wlan_hdd_cfg80211_suspend_wlan(struct wiphy *wiphy, + struct cfg80211_wowlan *wow) +{ + hdd_context_t *pHddCtx = wiphy_priv(wiphy); + + ENTER(); + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: HddCtx validation failed", __func__); + return 0; + } + + pHddCtx->isWiphySuspended = TRUE; + + EXIT(); + + return 0; +} + /* cfg80211_ops */ -static struct cfg80211_ops wlan_hdd_cfg80211_ops = +static struct cfg80211_ops wlan_hdd_cfg80211_ops = { .add_virtual_intf = wlan_hdd_add_virtual_intf, .del_virtual_intf = wlan_hdd_del_virtual_intf, @@ -7534,5 +8189,12 @@ static struct cfg80211_ops wlan_hdd_cfg80211_ops = #ifdef WLAN_FEATURE_GTK_OFFLOAD .set_rekey_data = wlan_hdd_cfg80211_set_rekey_data, #endif /* WLAN_FEATURE_GTK_OFFLOAD */ +#ifdef FEATURE_WLAN_SCAN_PNO + .sched_scan_start = wlan_hdd_cfg80211_sched_scan_start, + .sched_scan_stop = wlan_hdd_cfg80211_sched_scan_stop, +#endif /*FEATURE_WLAN_SCAN_PNO */ + .resume = wlan_hdd_cfg80211_resume_wlan, + .suspend = wlan_hdd_cfg80211_suspend_wlan, + .set_mac_acl = wlan_hdd_cfg80211_set_mac_acl, }; diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c index 9b7a34476a2..f522f227e04 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_dev_pwr.c @@ -143,7 +143,7 @@ static int wlan_suspend(hdd_context_t* pHddCtx) */ VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Suspending Mc, Rx and Tx Threads",__func__); - init_completion(&pHddCtx->tx_sus_event_var); + INIT_COMPLETION(pHddCtx->tx_sus_event_var); /* Indicate Tx Thread to Suspend */ set_bit(TX_SUSPEND_EVENT_MASK, &vosSchedContext->txEventFlag); @@ -163,7 +163,7 @@ static int wlan_suspend(hdd_context_t* pHddCtx) /* Set the Tx Thread as Suspended */ pHddCtx->isTxThreadSuspended = TRUE; - init_completion(&pHddCtx->rx_sus_event_var); + INIT_COMPLETION(pHddCtx->rx_sus_event_var); /* Indicate Rx Thread to Suspend */ set_bit(RX_SUSPEND_EVENT_MASK, &vosSchedContext->rxEventFlag); @@ -191,7 +191,7 @@ static int wlan_suspend(hdd_context_t* pHddCtx) /* Set the Rx Thread as Suspended */ pHddCtx->isRxThreadSuspended = TRUE; - init_completion(&pHddCtx->mc_sus_event_var); + INIT_COMPLETION(pHddCtx->mc_sus_event_var); /* Indicate MC Thread to Suspend */ set_bit(MC_SUSPEND_EVENT_MASK, &vosSchedContext->mcEventFlag); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c index 7984a354144..6af5370921b 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_early_suspend.c @@ -91,6 +91,7 @@ #include #include #include +#include /**----------------------------------------------------------------------------- * Preprocessor definitions and constants * ----------------------------------------------------------------------------*/ @@ -105,7 +106,9 @@ #include "wlan_hdd_power.h" #include "wlan_hdd_packet_filtering.h" -#define HDD_SSR_BRING_UP_TIME 10000 +#define HDD_SSR_BRING_UP_TIME 180000 +#define NS_DEFAULT_SLOT_INDEX 4 +#define NS_EXTENDED_SLOT_INDEX 18 static eHalStatus g_full_pwr_status; static eHalStatus g_standby_status; @@ -128,7 +131,7 @@ void hdd_suspend_standby_cbk (void *callbackContext, eHalStatus status) { hdd_context_t *pHddCtx = (hdd_context_t*)callbackContext; hddLog(VOS_TRACE_LEVEL_INFO, "%s: Standby status = %d", __func__, status); - g_standby_status = status; + g_standby_status = status; if(eHAL_STATUS_SUCCESS == status) { @@ -162,7 +165,7 @@ void hdd_suspend_full_pwr_callback(void *callbackContext, eHalStatus status) } eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx) -{ +{ eHalStatus status = VOS_STATUS_SUCCESS; hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from standby",__func__); @@ -175,7 +178,7 @@ eHalStatus hdd_exit_standby(hdd_context_t *pHddCtx) if(status == eHAL_STATUS_PMC_PENDING) { //Block on a completion variable. Can't wait forever though - wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, + wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); status = g_full_pwr_status; if(g_full_pwr_status != eHAL_STATUS_SUCCESS) @@ -216,20 +219,19 @@ VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx) //Note we do not disable queues unnecessarily. Queues should already be disabled //if STA is disconnected or the queue will be disabled as and when disconnect //happens because of standby procedure. - //Ensure that device is in full power first. There is scope for optimization //here especially in scenarios where PMC is already in IMPS or REQUEST_IMPS. //Core s/w needs to be optimized to handle this. Until then we request full //power before issuing request for standby. INIT_COMPLETION(pHddCtx->full_pwr_comp_var); g_full_pwr_status = eHAL_STATUS_FAILURE; - halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, + halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD); if(halStatus == eHAL_STATUS_PMC_PENDING) { //Block on a completion variable. Can't wait forever though - wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, + wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); if(g_full_pwr_status != eHAL_STATUS_SUCCESS) { @@ -262,10 +264,10 @@ VOS_STATUS hdd_enter_standby(hdd_context_t *pHddCtx) g_standby_status = eHAL_STATUS_FAILURE; halStatus = sme_RequestStandby(pHddCtx->hHal, hdd_suspend_standby_cbk, pHddCtx); - if (halStatus == eHAL_STATUS_PMC_PENDING) + if (halStatus == eHAL_STATUS_PMC_PENDING) { //Wait till WLAN device enters standby mode - wait_for_completion_timeout(&pHddCtx->standby_comp_var, + wait_for_completion_timeout(&pHddCtx->standby_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_STANDBY)); if (g_standby_status != eHAL_STATUS_SUCCESS && g_standby_status != eHAL_STATUS_PMC_NOT_NOW) { @@ -317,13 +319,13 @@ VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) //Ensure that device is in full power as we will touch H/W during vos_Stop INIT_COMPLETION(pHddCtx->full_pwr_comp_var); g_full_pwr_status = eHAL_STATUS_FAILURE; - halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, + halStatus = sme_RequestFullPower(pHddCtx->hHal, hdd_suspend_full_pwr_callback, pHddCtx, eSME_FULL_PWR_NEEDED_BY_HDD); if(halStatus == eHAL_STATUS_PMC_PENDING) { //Block on a completion variable. Can't wait forever though - wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, + wait_for_completion_interruptible_timeout(&pHddCtx->full_pwr_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_FULL_PWR)); if(g_full_pwr_status != eHAL_STATUS_SUCCESS){ hddLog(VOS_TRACE_LEVEL_FATAL,"%s: sme_RequestFullPower failed",__func__); @@ -345,7 +347,7 @@ VOS_STATUS hdd_enter_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) if(halStatus == eHAL_STATUS_SUCCESS) { //Block on a completion variable. Can't wait forever though. - wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, + wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); } @@ -398,7 +400,7 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) goto err_deep_sleep; } - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: calling vos_start",__func__); vosStatus = vos_start( pHddCtx->pvosContext ); VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); @@ -409,7 +411,7 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) goto err_deep_sleep; } - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: calling hdd_post_voss_start_config",__func__); vosStatus = hdd_post_voss_start_config( pHddCtx ); VOS_ASSERT( VOS_IS_STATUS_SUCCESS( vosStatus ) ); @@ -423,7 +425,8 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) //Open a SME session for future operation halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pHddCtx, - (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId ); + (tANI_U8 *)&pAdapter->macAddressCurrent, + &pAdapter->sessionId); if ( !HAL_STATUS_SUCCESS( halStatus ) ) { hddLog(VOS_TRACE_LEVEL_FATAL,"sme_OpenSession() failed with status code %08d [x%08lx]", @@ -446,7 +449,464 @@ VOS_STATUS hdd_exit_deep_sleep(hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter) } -VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) +/* + * Function: hdd_conf_hostoffload + * Central function to configure the supported offloads, + * either enable or disable them. + */ +void hdd_conf_hostoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) +{ + hdd_context_t *pHddCtx = NULL; + v_CONTEXT_t *pVosContext = NULL; + VOS_STATUS vstatus = VOS_STATUS_E_FAILURE; + + hddLog(VOS_TRACE_LEVEL_INFO, FL("Configuring offloads with flag: %d"), + fenable); + + pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); + + if (NULL == pVosContext) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL(" Global VOS context is Null")); + return; + } + + //Get the HDD context. + pHddCtx = (hdd_context_t *)vos_get_context(VOS_MODULE_ID_HDD, pVosContext ); + + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s: HDD context is Null", __func__); + return; + } + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + { + if (fenable) + { + if (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) + { + if ((pHddCtx->cfg_ini->fhostArpOffload)) + { + /* + * Configure the ARP Offload. + * Even if it fails we have to reconfigure the MC/BC + * filter flag as we want RIVA not to drop BroadCast + * Packets + */ + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Calling ARP Offload with flag: %d"), fenable); + vstatus = hdd_conf_arp_offload(pAdapter, fenable); + pHddCtx->configuredMcastBcastFilter &= + ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST); + + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "Failed to enable ARPOFfloadFeature %d", + vstatus); + } + } + //Configure GTK_OFFLOAD +#ifdef WLAN_FEATURE_GTK_OFFLOAD + hdd_conf_gtk_offload(pAdapter, fenable); +#endif + +#ifdef WLAN_NS_OFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) + { + /* + * Configure the NS Offload. + * Even if it fails we have to reconfigure the MC/BC filter flag + * as we want RIVA not to drop Multicast Packets + */ + + hddLog(VOS_TRACE_LEVEL_INFO, + FL("Calling NS Offload with flag: %d"), fenable); + hdd_conf_ns_offload(pAdapter, fenable); + pHddCtx->configuredMcastBcastFilter &= + ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST); + } +#endif + } + } + else + { + //Disable ARPOFFLOAD + if (pHddCtx->cfg_ini->fhostArpOffload) + { + vstatus = hdd_conf_arp_offload(pAdapter, fenable); + if (!VOS_IS_STATUS_SUCCESS(vstatus)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "Failed to disable ARPOffload Feature %d", vstatus); + } + } + //Disable GTK_OFFLOAD +#ifdef WLAN_FEATURE_GTK_OFFLOAD + hdd_conf_gtk_offload(pAdapter, fenable); +#endif + +#ifdef WLAN_NS_OFFLOAD + //Disable NSOFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) + { + hdd_conf_ns_offload(pAdapter, fenable); + } +#endif + } + } + return; +} + +#ifdef WLAN_NS_OFFLOAD +void hdd_ipv6_notifier_work_queue(struct work_struct *work) +{ + hdd_adapter_t* pAdapter = + container_of(work, hdd_adapter_t, ipv6NotifierWorkQueue); + hdd_context_t *pHddCtx; + int status; + + hddLog(LOG1, FL("Reconfiguring NS Offload")); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + hddLog(LOGE, FL("HDD context is invalid")); + return; + } + + if ((eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) + && (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)) + { + // This invocation being part of the IPv6 registration callback, + // we are passing second parameter as 2 to avoid registration + // of IPv6 notifier again. + hdd_conf_ns_offload(pAdapter, 2); + } +} + +static int wlan_hdd_ipv6_changed(struct notifier_block *nb, + unsigned long data, void *arg) +{ + struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)arg; + struct net_device *ndev = ifa->idev->dev; + hdd_adapter_t *pAdapter = + container_of(nb, struct hdd_adapter_s, ipv6_notifier); + hdd_context_t *pHddCtx; + int status; + + if (pAdapter && pAdapter->dev == ndev) + { + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + status = wlan_hdd_validate_context(pHddCtx); + if (0 != status) + { + hddLog(LOGE, FL("HDD context is invalid")); + return NOTIFY_DONE; + } + + schedule_work(&pAdapter->ipv6NotifierWorkQueue); + } + + return NOTIFY_DONE; +} + +/**---------------------------------------------------------------------------- + + \brief hdd_conf_ns_offload() - Configure NS offload + + Called during SUSPEND to configure the NS offload (MC BC filter) which + reduces power consumption. + + \param - pAdapter - Adapter context for which NS offload is to be configured + \param - fenable - 0 - disable. + 1 - enable. (with IPv6 notifier registration) + 2 - enable. (without IPv6 notifier registration) + + \return - void + + ---------------------------------------------------------------------------*/ +void hdd_conf_ns_offload(hdd_adapter_t *pAdapter, int fenable) +{ + struct inet6_dev *in6_dev; + struct inet6_ifaddr *ifp; + struct list_head *p; + tSirHostOffloadReq offLoadRequest; + int slot_index = NS_DEFAULT_SLOT_INDEX; + tANI_U8 **selfIPv6Addr; + tANI_U8 *selfIPv6AddrValid; + hdd_context_t *pHddCtx; + tHalHandle halHandle; + int status; + + int i = 0, slot = 0; + int ret = 0; + eHalStatus returnStatus; + + ENTER(); + hddLog(LOG1, FL(" fenable = %d"), fenable); + + if (NULL == pAdapter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD adapter is Null")); + return; + } + + halHandle = WLAN_HDD_GET_HAL_CTX(pAdapter); + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return; + } + + if (sme_IsFeatureSupportedByFW(EXTENDED_NSOFFLOAD_SLOT)) + { + slot_index = NS_EXTENDED_SLOT_INDEX; + } + + hddLog(VOS_TRACE_LEVEL_INFO, FL("slot_idex = %d"), slot_index); + + selfIPv6AddrValid = + (tANI_U8 *)vos_mem_malloc(sizeof(tANI_U8) * slot_index); + + if (NULL == selfIPv6AddrValid) + { + hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory for" + " selfIPv6AddrValid")); + goto end; + } + + memset(selfIPv6AddrValid, 0, slot_index * sizeof(tANI_U8)); + + selfIPv6Addr = (tANI_U8 **)vos_mem_malloc(sizeof(tANI_U8 *) * slot_index); + + if (NULL == selfIPv6Addr) + { + hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory for" + " selfIPv6Addr")); + goto end; + } + + memset(selfIPv6Addr, 0, slot_index * sizeof(tANI_U8 *)); + + for (slot = 0; slot < slot_index; slot++) + { + selfIPv6Addr[slot] = + (tANI_U8 *)vos_mem_malloc(SIR_MAC_IPV6_ADDR_LEN); + if (NULL == selfIPv6Addr[slot]) + { + hddLog (VOS_TRACE_LEVEL_ERROR, FL("Failed to allocate memory" + "for selfIPv6Addr")); + goto end; + } + memset(selfIPv6Addr[slot], 0, SIR_MAC_IPV6_ADDR_LEN); + } + + i = 0; + + if (fenable) + { + in6_dev = __in6_dev_get(pAdapter->dev); + if (NULL != in6_dev) + { + //read_lock_bh(&in6_dev->lock); + list_for_each(p, &in6_dev->addr_list) + { + if (i >= slot_index) + { + hddLog (VOS_TRACE_LEVEL_ERROR, + FL("IPv6 address list is greater than IPv6" + "address supported by firmware")); + hddLog (VOS_TRACE_LEVEL_ERROR, + FL("FW supported IPv6 address = %d"), slot_index); + break; + } + ifp = list_entry(p, struct inet6_ifaddr, if_list); + switch(ipv6_addr_src_scope(&ifp->addr)) + { + case IPV6_ADDR_SCOPE_LINKLOCAL: + vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr, + sizeof(ifp->addr.s6_addr)); + selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID; + hddLog (VOS_TRACE_LEVEL_INFO, + FL("Found IPV6_ADDR_SCOPE_LINKLOCAL Address : %pI6"), + selfIPv6Addr[i]); + break; + case IPV6_ADDR_SCOPE_GLOBAL: + vos_mem_copy(selfIPv6Addr[i], &ifp->addr.s6_addr, + sizeof(ifp->addr.s6_addr)); + selfIPv6AddrValid[i] = SIR_IPV6_ADDR_VALID; + hddLog (VOS_TRACE_LEVEL_INFO, + FL("Found IPV6_ADDR_SCOPE_GLOBAL Address : %pI6"), + selfIPv6Addr[i]); + break; + default: + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("The Scope %d is not supported"), + ipv6_addr_src_scope(&ifp->addr)); + } + if (selfIPv6AddrValid[i] == SIR_IPV6_ADDR_VALID) + { + i++; + } + } + + vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); + for (i =0; i < slot_index; i++) + { + if (selfIPv6AddrValid[i]) + { + //Filling up the request structure + /* Filling the selfIPv6Addr with solicited address + * A Solicited-Node multicast address is created by + * taking the last 24 bits of a unicast or anycast + * address and appending them to the prefix + * + * FF02:0000:0000:0000:0000:0001:FFXX:XX + * + * here XX is the unicast/anycast bits + */ + offLoadRequest.nsOffloadInfo.selfIPv6Addr[0] = 0xFF; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[1] = 0x02; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[11] = 0x01; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[12] = 0xFF; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[13] = + selfIPv6Addr[i][13]; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[14] = + selfIPv6Addr[i][14]; + offLoadRequest.nsOffloadInfo.selfIPv6Addr[15] = + selfIPv6Addr[i][15]; + offLoadRequest.nsOffloadInfo.slotIdx = i; + + vos_mem_copy(&offLoadRequest.nsOffloadInfo.targetIPv6Addr[0], + selfIPv6Addr[i], sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN); + vos_mem_copy(&offLoadRequest.nsOffloadInfo.selfMacAddr, + &pAdapter->macAddressCurrent.bytes, + sizeof(tANI_U8)*SIR_MAC_ADDR_LEN); + + offLoadRequest.nsOffloadInfo.targetIPv6AddrValid[0] = + SIR_IPV6_ADDR_VALID; + offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; + offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; + + hddLog (VOS_TRACE_LEVEL_INFO, + FL("configuredMcastBcastFilter: %d" + "NSOffload Slot = %d"), + pHddCtx->configuredMcastBcastFilter, i); + + if ((VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid) + && ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST == + pHddCtx->sus_res_mcastbcast_filter) || + (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter)) + && (!pHddCtx->cfg_ini->fEnableMCAddrList)) + { + hddLog (VOS_TRACE_LEVEL_INFO, + FL("Set offLoadRequest with" + "SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE")); + offLoadRequest.enableOrDisable = + SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE; + } + + vos_mem_copy(&offLoadRequest.params.hostIpv6Addr, + &offLoadRequest.nsOffloadInfo.targetIPv6Addr[0], + sizeof(tANI_U8)*SIR_MAC_IPV6_ADDR_LEN); + + hddLog (VOS_TRACE_LEVEL_INFO, + FL("Setting NSOffload with solicitedIp: %pI6," + "targetIp: %pI6"), + offLoadRequest.nsOffloadInfo.selfIPv6Addr, + offLoadRequest.nsOffloadInfo.targetIPv6Addr[0]); + + //Configure the Firmware with this + returnStatus = sme_SetHostOffload(halHandle, + pAdapter->sessionId, &offLoadRequest); + if(eHAL_STATUS_SUCCESS != returnStatus) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("Failed to enable HostOffload feature with" + " status: %d"), returnStatus); + } + vos_mem_zero(&offLoadRequest, sizeof(offLoadRequest)); + } + } + if (fenable == 1 && !pAdapter->ipv6_notifier_registered) + { + // Register IPv6 notifier to notify if any change in IP + // So that we can reconfigure the offload parameters + pAdapter->ipv6_notifier.notifier_call = + wlan_hdd_ipv6_changed; + ret = register_inet6addr_notifier(&pAdapter->ipv6_notifier); + if (ret) + { + hddLog(LOGE, FL("Failed to register IPv6 notifier")); + } + else + { + hddLog(LOG1, FL("Registered IPv6 notifier")); + pAdapter->ipv6_notifier_registered = true; + } + } + } + else + { + hddLog(VOS_TRACE_LEVEL_ERROR, + FL("IPv6 dev does not exist. Failed to request NSOffload")); + goto end; + } + } + else + { + //Disable NSOffload + if (pAdapter->ipv6_notifier_registered) + { + hddLog(LOG1, FL("Unregistered IPv6 notifier")); + unregister_inet6addr_notifier(&pAdapter->ipv6_notifier); + pAdapter->ipv6_notifier_registered = false; + } + vos_mem_zero((void *)&offLoadRequest, sizeof(tSirHostOffloadReq)); + offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; + offLoadRequest.offloadType = SIR_IPV6_NS_OFFLOAD; + + for (i = 0; i < slot_index; i++) + { + hddLog(VOS_TRACE_LEVEL_INFO, FL("Disable Slot= %d"), i); + offLoadRequest.nsOffloadInfo.slotIdx = i; + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Failure to disable" + " %d Slot"), i); + } + } + } +end: + while (slot > 0 && selfIPv6Addr[--slot]) + { + vos_mem_free(selfIPv6Addr[slot]); + } + if (selfIPv6Addr) + { + vos_mem_free(selfIPv6Addr); + } + if (selfIPv6AddrValid) + { + vos_mem_free(selfIPv6AddrValid); + } + return; +} +#endif +VOS_STATUS hdd_conf_arp_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) { struct in_ifaddr **ifap = NULL; struct in_ifaddr *ifa = NULL; @@ -461,7 +921,7 @@ VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) { if ((in_dev = __in_dev_get_rtnl(pAdapter->dev)) != NULL) { - for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; + for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL; ifap = &ifa->ifa_next) { if (!strcmp(pAdapter->dev->name, ifa->ifa_label)) @@ -470,49 +930,43 @@ VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) } } } - if(ifa && ifa->ifa_local) { offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; offLoadRequest.enableOrDisable = SIR_OFFLOAD_ENABLE; - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Enabled \n", __func__); + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Enabled \n", __func__); - if(pHddCtx->dynamic_mcbc_filter.enableCfg) + if (((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter) || + (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == + pHddCtx->sus_res_mcastbcast_filter)) && + (VOS_TRUE == pHddCtx->sus_res_mcastbcast_filter_valid)) { - if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) || - (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting)) - { - offLoadRequest.enableOrDisable = - SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; - } + offLoadRequest.enableOrDisable = + SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: inside arp offload conditional check"); } - else if((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->cfg_ini->mcastBcastFilterSetting ) || - (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->cfg_ini->mcastBcastFilterSetting)) - { - offLoadRequest.enableOrDisable = - SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE; - } - + + hddLog(VOS_TRACE_LEVEL_INFO, "offload: arp filter programmed = %d", + offLoadRequest.enableOrDisable); + //converting u32 to IPV4 address for(i = 0 ; i < 4; i++) { - offLoadRequest.params.hostIpv4Addr[i] = + offLoadRequest.params.hostIpv4Addr[i] = (ifa->ifa_local >> (i*8) ) & 0xFF ; } - hddLog(VOS_TRACE_LEVEL_WARN, " Enable SME HostOffload: %d.%d.%d.%d", + hddLog(VOS_TRACE_LEVEL_INFO, " Enable SME HostOffload: %d.%d.%d.%d", offLoadRequest.params.hostIpv4Addr[0], offLoadRequest.params.hostIpv4Addr[1], offLoadRequest.params.hostIpv4Addr[2], offLoadRequest.params.hostIpv4Addr[3]); - if (eHAL_STATUS_SUCCESS != - sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), - pAdapter->sessionId, &offLoadRequest)) + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failed to enable HostOffload " "feature\n", __func__); @@ -532,8 +986,9 @@ VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) offLoadRequest.enableOrDisable = SIR_OFFLOAD_DISABLE; offLoadRequest.offloadType = SIR_IPV4_ARP_REPLY_OFFLOAD; - if (eHAL_STATUS_SUCCESS != sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), pAdapter->sessionId, - &offLoadRequest)) + if (eHAL_STATUS_SUCCESS != + sme_SetHostOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, &offLoadRequest)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to disable host " "offload feature\n", __func__); @@ -545,67 +1000,41 @@ VOS_STATUS hdd_conf_hostarpoffload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) /* * This function is called before setting mcbc filters - * to modify filter value considering ARP + * to modify filter value considering Different Offloads */ -void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx, v_BOOL_t arpFlag, +void hdd_mcbc_filter_modification(hdd_context_t* pHddCtx, tANI_U8 *pMcBcFilter) { - if (TRUE == arpFlag) + if (NULL == pHddCtx) { - /*ARP offload is enabled, do not block bcast packets at RXP*/ - if (pHddCtx->dynamic_mcbc_filter.enableCfg) - { - if ((HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting)) - { - *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST; - } - else if ((HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting)) - { - *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_NONE; - } - else - { - *pMcBcFilter = pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting; - } - - pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE; - pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend = *pMcBcFilter; - } - else - { - if (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->cfg_ini->mcastBcastFilterSetting) - { - *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST; - } - else if (HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->cfg_ini->mcastBcastFilterSetting) - { - *pMcBcFilter = HDD_MCASTBCASTFILTER_FILTER_NONE; - } - else - { - *pMcBcFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; - } + hddLog(VOS_TRACE_LEVEL_ERROR, FL("NULL HDD context passed")); + return; + } - pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE; - } + *pMcBcFilter = pHddCtx->configuredMcastBcastFilter; + if (pHddCtx->cfg_ini->fhostArpOffload) + { + /* ARP offload is enabled, do not block bcast packets at RXP + * Will be using Bitmasking to reset the filter. As we have + * disable Broadcast filtering, Anding with the negation + * of Broadcast BIT + */ + *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST); } - else + +#ifdef WLAN_NS_OFFLOAD + if (pHddCtx->cfg_ini->fhostNSOffload) { - if (pHddCtx->dynamic_mcbc_filter.enableCfg) - { - *pMcBcFilter = pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting; - pHddCtx->dynamic_mcbc_filter.enableSuspend = TRUE; - } - else - { - pHddCtx->dynamic_mcbc_filter.enableSuspend = FALSE; - *pMcBcFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; - } + /* NS offload is enabled, do not block mcast packets at RXP + * Will be using Bitmasking to reset the filter. As we have + * disable Multicast filtering, Anding with the negation + * of Multicast BIT + */ + *pMcBcFilter &= ~(HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST); } +#endif + + pHddCtx->configuredMcastBcastFilter = *pMcBcFilter; } void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter) @@ -623,20 +1052,15 @@ void hdd_conf_mcastbcast_filter(hdd_context_t* pHddCtx, v_BOOL_t setfilter) "%s: Configuring Mcast/Bcast Filter Setting. setfilter %d", __func__, setfilter); if (TRUE == setfilter) { - if (pHddCtx->cfg_ini->fhostArpOffload) - { - hdd_mcbc_filter_modification(pHddCtx, TRUE, + hdd_mcbc_filter_modification(pHddCtx, &wlanRxpFilterParam->configuredMcstBcstFilterSetting); - } - else - { - hdd_mcbc_filter_modification(pHddCtx, FALSE, - &wlanRxpFilterParam->configuredMcstBcstFilterSetting); - } } else + { + /*Use the current configured value to clear*/ wlanRxpFilterParam->configuredMcstBcstFilterSetting = - pHddCtx->cfg_ini->mcastBcastFilterSetting; + pHddCtx->configuredMcastBcastFilter; + } wlanRxpFilterParam->setMcstBcstFilter = setfilter; halStatus = sme_ConfigureRxpFilter(pHddCtx->hHal, wlanRxpFilterParam); @@ -650,10 +1074,20 @@ static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, hdd_adapter_t *pAdapter) { eHalStatus halStatus = eHAL_STATUS_FAILURE; - VOS_STATUS vstatus = VOS_STATUS_E_FAILURE; tpSirWlanSuspendParam wlanSuspendParam = vos_mem_malloc(sizeof(tSirWlanSuspendParam)); + if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE; + hddLog(VOS_TRACE_LEVEL_INFO, "offload: hdd_conf_suspend_ind"); + hddLog(VOS_TRACE_LEVEL_INFO, "configuredMCastBcastFilter saved = %d", + pHddCtx->configuredMcastBcastFilter); + + } + + if(NULL == wlanSuspendParam) { hddLog(VOS_TRACE_LEVEL_FATAL, @@ -661,55 +1095,21 @@ static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, return; } - hddLog(VOS_TRACE_LEVEL_INFO, + hddLog(VOS_TRACE_LEVEL_INFO, "%s: send wlan suspend indication", __func__); if((pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_MCAST_BCAST_FILTER)) { - if((pHddCtx->cfg_ini->fhostArpOffload) && - (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) - { - vstatus = hdd_conf_hostarpoffload(pAdapter, TRUE); - if (!VOS_IS_STATUS_SUCCESS(vstatus)) - { - hdd_mcbc_filter_modification(pHddCtx, FALSE, - &wlanSuspendParam->configuredMcstBcstFilterSetting); - hddLog(VOS_TRACE_LEVEL_INFO, - "%s:Failed to enable ARPOFFLOAD Feature %d\n", - __func__, vstatus); - } - else - { - hdd_mcbc_filter_modification(pHddCtx, TRUE, - &wlanSuspendParam->configuredMcstBcstFilterSetting); - } - } - else - { - hdd_mcbc_filter_modification(pHddCtx, FALSE, - &wlanSuspendParam->configuredMcstBcstFilterSetting); - if(pHddCtx->dynamic_mcbc_filter.enableCfg) - { - pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend = - wlanSuspendParam->configuredMcstBcstFilterSetting; - } - } + //Configure supported OffLoads + hdd_conf_hostoffload(pAdapter, TRUE); + wlanSuspendParam->configuredMcstBcstFilterSetting = pHddCtx->configuredMcastBcastFilter; #ifdef WLAN_FEATURE_PACKET_FILTERING - if (pHddCtx->cfg_ini->isMcAddrListFilter) - { - /*Multicast addr list filter is enabled during suspend*/ - if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || - (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) - && pAdapter->mc_addr_list.mc_cnt - && (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) - { - /*set the filter*/ - wlan_hdd_set_mc_addr_list(pAdapter, TRUE); - } - } + /* During suspend, configure MC Addr list filter to the firmware + * function takes care of checking necessary conditions before + * configuring. + */ + wlan_hdd_set_mc_addr_list(pAdapter, TRUE); #endif } @@ -725,61 +1125,49 @@ static void hdd_conf_suspend_ind(hdd_context_t* pHddCtx, static void hdd_conf_resume_ind(hdd_adapter_t *pAdapter) { eHalStatus halStatus = eHAL_STATUS_FAILURE; - VOS_STATUS vstatus; hdd_context_t* pHddCtx = WLAN_HDD_GET_CTX(pAdapter); tpSirWlanResumeParam wlanResumeParam; hddLog(VOS_TRACE_LEVEL_INFO, "%s: send wlan resume indication", __func__); - if (pHddCtx->hdd_mcastbcast_filter_set == TRUE) - { - wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam)); + wlanResumeParam = vos_mem_malloc(sizeof(tSirWlanResumeParam)); - if(NULL == wlanResumeParam) - { - hddLog(VOS_TRACE_LEVEL_FATAL, - "%s: vos_mem_alloc failed ", __func__); - return; - } - - if (pHddCtx->cfg_ini->fhostArpOffload) - { - vstatus = hdd_conf_hostarpoffload(pAdapter, FALSE); - if (!VOS_IS_STATUS_SUCCESS(vstatus)) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s:Failed to disable ARPOFFLOAD " - "Feature %d\n", __func__, vstatus); - } - } - if (pHddCtx->dynamic_mcbc_filter.enableSuspend) - { - wlanResumeParam->configuredMcstBcstFilterSetting = - pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend; - } - else - { - wlanResumeParam->configuredMcstBcstFilterSetting = - pHddCtx->cfg_ini->mcastBcastFilterSetting; - } - halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam); - if (eHAL_STATUS_SUCCESS != halStatus) - vos_mem_free(wlanResumeParam); - pHddCtx->hdd_mcastbcast_filter_set = FALSE; + if (NULL == wlanResumeParam) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: memory allocation failed for wlanResumeParam ", __func__); + return; } + //Disable supported OffLoads + hdd_conf_hostoffload(pAdapter, FALSE); -#ifdef WLAN_FEATURE_PACKET_FILTERING - if (pHddCtx->cfg_ini->isMcAddrListFilter) + wlanResumeParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + halStatus = sme_ConfigureResumeReq(pHddCtx->hHal, wlanResumeParam); + if (eHAL_STATUS_SUCCESS != halStatus) { - /*Multicast addr filtering is enabled*/ - if (pAdapter->mc_addr_list.isFilterApplied) - { - /*Filter applied during suspend mode*/ - /*Clear it here*/ - wlan_hdd_set_mc_addr_list(pAdapter, FALSE); - } + vos_mem_free(wlanResumeParam); } + + pHddCtx->hdd_mcastbcast_filter_set = FALSE; + + pHddCtx->configuredMcastBcastFilter = + pHddCtx->sus_res_mcastbcast_filter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_FALSE; + + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: in hdd_conf_resume_ind, restoring configuredMcastBcastFilter"); + hddLog(VOS_TRACE_LEVEL_INFO, "configuredMcastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + + +#ifdef WLAN_FEATURE_PACKET_FILTERING + /* Filer was applied during suspend inditication + * clear it when we resume. + */ + wlan_hdd_set_mc_addr_list(pAdapter, FALSE); #endif } @@ -789,9 +1177,10 @@ void hdd_suspend_wlan(void) hdd_context_t *pHddCtx = NULL; v_CONTEXT_t pVosContext = NULL; - hdd_adapter_t *pAdapter = NULL; - hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; VOS_STATUS status; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + bool hdd_enter_bmps = FALSE; hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being suspended by Android OS",__func__); @@ -816,7 +1205,7 @@ void hdd_suspend_wlan(void) return; } - /*loop through all adapters. TBD fix for Concurrency */ + hdd_set_pwrparams(pHddCtx); status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { @@ -830,7 +1219,22 @@ void hdd_suspend_wlan(void) pAdapterNode = pNext; continue; } + /* Avoid multiple enter/exit BMPS in this while loop using + * hdd_enter_bmps flag + */ + if (FALSE == hdd_enter_bmps && (BMPS == pmcGetPmcState(pHddCtx->hHal))) + { + hdd_enter_bmps = TRUE; + + /* If device was already in BMPS, and dynamic DTIM is set, + * exit(set the device to full power) and enter BMPS again + * to reflect new DTIM value */ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); + + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); + pHddCtx->hdd_ignore_dtim_enabled = TRUE; + } #ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY) { @@ -838,7 +1242,7 @@ void hdd_suspend_wlan(void) netif_tx_disable(pAdapter->dev); netif_carrier_off(pAdapter->dev); } - else if (pHddCtx->cfg_ini->nEnableSuspend == + else if (pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_DEEP_SLEEP) { //Execute deep sleep procedure @@ -846,96 +1250,14 @@ void hdd_suspend_wlan(void) } #endif - //Apply Dynamic Dtim For P2P - //Only if ignoreDynamicDtimInP2pMode is not set in ini - if((pHddCtx->cfg_ini->enableDynamicDTIM || - pHddCtx->cfg_ini->enableModulatedDTIM) && - ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) && - !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) && - (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) && - (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) && - (pHddCtx->cfg_ini->fIsBmpsEnabled)) - { - tSirSetPowerParamsReq powerRequest = { 0 }; - - powerRequest.uIgnoreDTIM = 1; - - /*Back up the actual values from CFG */ - wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, - &pHddCtx->hdd_actual_ignore_DTIM_value); - wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, - &pHddCtx->hdd_actual_LI_value); - - if(pHddCtx->cfg_ini->enableModulatedDTIM) - { - powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM; - powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; - } - else - { - powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM; - } - - /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM - *specified during Enter/Exit BMPS when LCD off*/ - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, - NULL, eANI_BOOLEAN_FALSE); - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, - NULL, eANI_BOOLEAN_FALSE); - - /* switch to the DTIM specified in cfg.ini */ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Switch to DTIM%d \n", powerRequest.uListenInterval); - sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE); - - if (BMPS == pmcGetPmcState(pHddCtx->hHal)) - { - /* put the device into full power */ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); - - /* put the device back into BMPS */ - wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); + /*Suspend notification sent down to driver*/ + hdd_conf_suspend_ind(pHddCtx, pAdapter); - pHddCtx->hdd_ignore_dtim_enabled = TRUE; - } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; } - /*Suspend notification sent down to driver*/ - hdd_conf_suspend_ind(pHddCtx, pAdapter); - -#ifdef WLAN_FEATURE_GTK_OFFLOAD - if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) - { - eHalStatus ret; - hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && - (TRUE == pHddStaCtx->gtkOffloadRequestParams.requested)) - { - ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), - &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams, - pAdapter->sessionId); - if (eHAL_STATUS_SUCCESS != ret) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: sme_SetGTKOffload failed, returned %d", - __func__, ret); - } - pHddStaCtx->gtkOffloadRequestParams.requested = FALSE; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: sme_SetGTKOffload successfull", - __func__); - } - } -#endif - - status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); - pAdapterNode = pNext; - } - pHddCtx->hdd_wlan_suspended = TRUE; - + pHddCtx->hdd_wlan_suspended = TRUE; #ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP if(pHddCtx->cfg_ini->nEnableSuspend == WLAN_MAP_SUSPEND_TO_STANDBY) { @@ -953,7 +1275,7 @@ static void hdd_PowerStateChangedCB ) { hdd_context_t *pHddCtx = callbackContext; - + /* if the driver was not in BMPS during early suspend, * the dynamic DTIM is now updated at Riva */ if ((newState == BMPS) && pHddCtx->hdd_wlan_suspended @@ -965,11 +1287,24 @@ static void hdd_PowerStateChangedCB spin_lock(&pHddCtx->filter_lock); if((newState == BMPS) && pHddCtx->hdd_wlan_suspended) { spin_unlock(&pHddCtx->filter_lock); + if (VOS_FALSE == pHddCtx->sus_res_mcastbcast_filter_valid) { + pHddCtx->sus_res_mcastbcast_filter = + pHddCtx->configuredMcastBcastFilter; + pHddCtx->sus_res_mcastbcast_filter_valid = VOS_TRUE; + + hddLog(VOS_TRACE_LEVEL_INFO, "offload: callback to associated"); + hddLog(VOS_TRACE_LEVEL_INFO, "saving configuredMcastBcastFilter = %d", + pHddCtx->configuredMcastBcastFilter); + hddLog(VOS_TRACE_LEVEL_INFO, + "offload: calling hdd_conf_mcastbcast_filter"); + + } + hdd_conf_mcastbcast_filter(pHddCtx, TRUE); if(pHddCtx->hdd_mcastbcast_filter_set != TRUE) hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Not able to set mcast/bcast filter ", __func__); } - else + else spin_unlock(&pHddCtx->filter_lock); } @@ -1026,50 +1361,83 @@ void hdd_unregister_mcast_bcast_filter(hdd_context_t *pHddCtx) pmcDeregisterDeviceStateUpdateInd(smeContext, hdd_PowerStateChangedCB); } } + #ifdef WLAN_FEATURE_GTK_OFFLOAD -void wlan_hdd_update_and_dissable_gtk_offload(hdd_adapter_t *pAdapter) +void hdd_conf_gtk_offload(hdd_adapter_t *pAdapter, v_BOOL_t fenable) { eHalStatus ret; tpSirGtkOffloadParams pGtkOffloadReqParams; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - pGtkOffloadReqParams = - &pHddStaCtx->gtkOffloadRequestParams.gtkOffloadReqParams; + if(fenable) + { + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags )) + { + vos_mem_copy(&hddGtkOffloadReqParams, + &pHddStaCtx->gtkOffloadReqParams, + sizeof (tSirGtkOffloadParams)); - if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && - (0 != memcmp(&pGtkOffloadReqParams->bssId, - &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) && - (FALSE == pHddStaCtx->gtkOffloadRequestParams.requested)) + ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + &hddGtkOffloadReqParams, pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != ret) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_SetGTKOffload failed, returned %d", + __func__, ret); + return; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sme_SetGTKOffload successfull", __func__); + } + } + else { - /* Host driver has previously offloaded GTK rekey */ - ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + (0 == memcmp(&pHddStaCtx->gtkOffloadReqParams.bssId, + &pHddStaCtx->conn_info.bssId, WNI_CFG_BSSID_LEN)) && + (GTK_OFFLOAD_ENABLE == pHddStaCtx->gtkOffloadReqParams.ulFlags)) + { + + /* Host driver has previously offloaded GTK rekey */ + ret = sme_GetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), wlan_hdd_cfg80211_update_replayCounterCallback, pAdapter, pAdapter->sessionId); - if (eHAL_STATUS_SUCCESS != ret) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: sme_GetGTKOffload failed, returned %d", - __func__, ret); - } - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: sme_GetGTKOffload successfull", __func__); + if (eHAL_STATUS_SUCCESS != ret) - /* Sending GTK offload dissable */ - pGtkOffloadReqParams->ulFlags = GTK_OFFLOAD_DISABLE; - ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), - pGtkOffloadReqParams, pAdapter->sessionId); + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: sme_GetGTKOffload failed, returned %d", + __func__, ret); + return; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: sme_GetGTKOffload successful", + __func__); - if (eHAL_STATUS_SUCCESS != ret) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: failed to dissable GTK offload, returned %d", - __func__, ret); + /* Sending GTK offload dissable */ + memcpy(&hddGtkOffloadReqParams, &pHddStaCtx->gtkOffloadReqParams, + sizeof (tSirGtkOffloadParams)); + hddGtkOffloadReqParams.ulFlags = GTK_OFFLOAD_DISABLE; + ret = sme_SetGTKOffload(WLAN_HDD_GET_HAL_CTX(pAdapter), + &hddGtkOffloadReqParams, pAdapter->sessionId); + if (eHAL_STATUS_SUCCESS != ret) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to dissable GTK offload, returned %d", + __func__, ret); + return; + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: successfully dissabled GTK offload request to HAL", + __func__); + } } - pHddStaCtx->gtkOffloadRequestParams.requested = FALSE; - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "%s: successfully dissabled GTK offload request to HAL", - __func__); } + return; } #endif /*WLAN_FEATURE_GTK_OFFLOAD*/ @@ -1097,7 +1465,7 @@ void hdd_resume_wlan(void) hddLog(VOS_TRACE_LEVEL_FATAL,"%s: HDD context is Null",__func__); return; } - + if (pHddCtx->isLogpInProgress) { hddLog(VOS_TRACE_LEVEL_INFO, "%s: Ignore resume wlan, LOGP in progress!", __func__); @@ -1120,16 +1488,9 @@ void hdd_resume_wlan(void) continue; } -#ifdef WLAN_FEATURE_GTK_OFFLOAD - if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) - { - wlan_hdd_update_and_dissable_gtk_offload(pAdapter); - } -#endif -#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP - if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP) +#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP + if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_DEEP_SLEEP) { hddLog(VOS_TRACE_LEVEL_INFO, "%s: WLAN being resumed from deep sleep",__func__); hdd_exit_deep_sleep(pAdapter); @@ -1139,10 +1500,11 @@ void hdd_resume_wlan(void) if(pHddCtx->hdd_ignore_dtim_enabled == TRUE) { /*Switch back to DTIM 1*/ - tSirSetPowerParamsReq powerRequest = { 0 }; + tSirSetPowerParamsReq powerRequest = { 0 }; powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value; powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; /*Disabled ModulatedDTIM if enabled on suspend*/ if(pHddCtx->cfg_ini->enableModulatedDTIM) @@ -1151,10 +1513,10 @@ void hdd_resume_wlan(void) /* Update ignoreDTIM and ListedInterval in CFG with default values */ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, NULL, eANI_BOOLEAN_FALSE); - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, NULL, eANI_BOOLEAN_FALSE); - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Switch to DTIM%d \n",powerRequest.uListenInterval); sme_SetPowerParams( WLAN_HDD_GET_HAL_CTX(pAdapter), &powerRequest, FALSE); @@ -1175,25 +1537,25 @@ void hdd_resume_wlan(void) pAdapterNode = pNext; } -#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP - if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY) +#ifdef SUPPORT_EARLY_SUSPEND_STANDBY_DEEPSLEEP + if(pHddCtx->hdd_ps_state == eHDD_SUSPEND_STANDBY) { hdd_exit_standby(pHddCtx); - } + } #endif return; } -VOS_STATUS hdd_wlan_reset_initialization(void) +VOS_STATUS hdd_wlan_reset_initialization(void) { v_CONTEXT_t pVosContext = NULL; - hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__); + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: WLAN being reset",__func__); //Get the global VOSS context. pVosContext = vos_get_global_context(VOS_MODULE_ID_SYS, NULL); - if(!pVosContext) + if(!pVosContext) { hddLog(VOS_TRACE_LEVEL_FATAL,"%s: Global VOS context is Null", __func__); return VOS_STATUS_E_FAILURE; @@ -1410,6 +1772,9 @@ VOS_STATUS hdd_wlan_re_init(void) v_CONTEXT_t pVosContext = NULL; hdd_context_t *pHddCtx = NULL; eHalStatus halStatus; +#ifdef HAVE_WCNSS_CAL_DOWNLOAD + int max_retries = 0; +#endif #ifdef WLAN_BTAMP_FEATURE hdd_config_t *pConfig = NULL; WLANBAP_ConfigType btAmpConfig; @@ -1418,6 +1783,17 @@ VOS_STATUS hdd_wlan_re_init(void) hdd_ssr_timer_del(); hdd_prevent_suspend(); +#ifdef HAVE_WCNSS_CAL_DOWNLOAD + /* wait until WCNSS driver downloads NV */ + while (!wcnss_device_ready() && 5 >= ++max_retries) { + msleep(1000); + } + if (max_retries >= 5) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__); + goto err_re_init; + } +#endif + /* The driver should always be initialized in STA mode after SSR */ hdd_set_conparam(0); @@ -1607,6 +1983,7 @@ VOS_STATUS hdd_wlan_re_init(void) err_re_init: /* Allow the phone to go to sleep */ hdd_allow_suspend(); + VOS_BUG(0); return -EPERM; success: diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_ftm.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_ftm.c index e56780556b1..35401d0232e 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_ftm.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_ftm.c @@ -169,6 +169,7 @@ typedef struct { extern const sHalNv nvDefaults; static int wlan_ftm_register_wext(hdd_adapter_t *pAdapter); +static int wlan_ftm_stop(hdd_context_t *pHddCtx); /* for PRIMA: all the available frequency, channal pair i the table are defined for channel frequency @ RF center frequency Since it is associated to agc.channel_freq register for mapping. @@ -1009,7 +1010,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if (NULL == pVosContext) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Trying to open VOSS without a PreOpen",__func__); + "%s: Trying to open VOSS without a PreOpen", __func__); VOS_ASSERT(0); goto err_vos_status_failure; } @@ -1019,7 +1020,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if ( !VOS_IS_STATUS_SUCCESS( vStatus )) { - hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed",__func__); + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: vos_open failed", __func__); goto err_vos_status_failure; } @@ -1031,7 +1032,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if ( NULL == pHddCtx->hHal ) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: HAL context is null",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: HAL context is null", __func__); goto err_sal_close; } @@ -1039,20 +1040,20 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) wlan_hdd_get_intf_addr(pHddCtx), FALSE); if( NULL == pAdapter ) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_open_adapter failed", __func__); goto err_adapter_open_failure; } if( wlan_ftm_register_wext(pAdapter)!= 0 ) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%S: hdd_register_wext failed",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: hdd_register_wext failed", __func__); goto err_sal_close; } //Initialize the nlink service if(nl_srv_init() != 0) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%S: nl_srv_init failed",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: nl_srv_init failed", __func__); goto err_ftm_register_wext_close; } @@ -1060,7 +1061,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) //Initialize the PTT service if(ptt_sock_activate_svc(pHddCtx) != 0) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: ptt_sock_activate_svc failed",__func__); + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: ptt_sock_activate_svc failed", __func__); goto err_nl_srv_init; } #endif @@ -1085,7 +1086,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if(NULL == pHddCtx->ftm.tempNVTableBuffer) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: NV Table Buffer Alloc Fail",__func__); + "%s: NV Table Buffer Alloc Fail", __func__); VOS_ASSERT(0); goto err_nl_srv_init; } @@ -1096,7 +1097,7 @@ int wlan_hdd_ftm_open(hdd_context_t *pHddCtx) if (vos_event_init(&pHddCtx->ftm.ftm_vos_event) != VOS_STATUS_SUCCESS) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Unable to init probeEvent",__func__); + "%s: Unable to init probeEvent", __func__); VOS_ASSERT(0); vos_mem_free(pHddCtx->ftm.tempNVTableBuffer); goto err_nl_srv_init; @@ -1137,6 +1138,12 @@ int wlan_hdd_ftm_close(hdd_context_t *pHddCtx) return VOS_STATUS_E_NOMEM; } + if(WLAN_FTM_STARTED == pHddCtx->ftm.ftm_state) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s: Ftm has been started. stopping ftm", __func__); + wlan_ftm_stop(pHddCtx); + } //Assert Deep sleep signal now to put Libra HW in lowest power state vosStatus = vos_chipAssertDeepSleep( NULL, NULL, NULL ); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c index db76996f677..45c6f788b2a 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_hostapd.c @@ -456,6 +456,7 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa char *startBssEvent; hdd_context_t *pHddCtx; hdd_scaninfo_t *pScanInfo = NULL; + struct iw_michaelmicfailure msg; dev = (struct net_device *)usrDataForCallback; pHostapdAdapter = netdev_priv(dev); @@ -565,7 +566,6 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa return VOS_STATUS_SUCCESS; case eSAP_STA_MIC_FAILURE_EVENT: { - struct iw_michaelmicfailure msg; memset(&msg, '\0', sizeof(msg)); msg.src_addr.sa_family = ARPHRD_ETHER; memcpy(msg.src_addr.sa_data, &pSapEvent->sapevt.sapStationMICFailureEvent.staMac, sizeof(v_MACADDR_t)); @@ -629,8 +629,8 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa 0, (v_MACADDR_t *)wrqu.addr.sa_data, pSapEvent->sapevt.sapStationAssocReassocCompleteEvent.wmmEnabled); - } - + } + // Stop AP inactivity timer if (pHddApCtx->hdd_ap_inactivity_timer.state == VOS_TIMER_STATE_RUNNING) { @@ -643,7 +643,7 @@ VOS_STATUS hdd_hostapd_SAPEventCB( tpSap_Event pSapEvent, v_PVOID_t usrDataForCa { wake_unlock(&pHddCtx->sap_wake_lock); } - wake_lock_timeout(&pHddCtx->sap_wake_lock, HDD_SAP_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->sap_wake_lock, msecs_to_jiffies(HDD_SAP_WAKE_LOCK_DURATION)); #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) { @@ -844,6 +844,20 @@ stopbss : * we don't want interfaces to become re-enabled */ pHostapdState->bssState = BSS_STOP; + if (0 != (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->nAPAutoShutOff) + { + if (VOS_TIMER_STATE_RUNNING == pHddApCtx->hdd_ap_inactivity_timer.state) + { + vos_status = vos_timer_stop(&pHddApCtx->hdd_ap_inactivity_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to stop AP inactivity timer")); + } + + vos_status = vos_timer_destroy(&pHddApCtx->hdd_ap_inactivity_timer); + if (!VOS_IS_STATUS_SUCCESS(vos_status)) + hddLog(LOGE, FL("Failed to Destroy AP inactivity timer")); + } + /* Stop the pkts from n/w stack as we are going to free all of * the TX WMM queues for all STAID's */ hdd_hostapd_stop(dev); @@ -1213,6 +1227,24 @@ static iw_softap_set_max_tx_power(struct net_device *dev, return 0; } +int +static iw_display_data_path_snapshot(struct net_device *dev, + struct iw_request_info *info, + union iwreq_data *wrqu, char *extra) +{ + + /* Function intitiating dumping states of + * HDD(WMM Tx Queues) + * TL State (with Per Client infor) + * DXE Snapshot (Called at the end of TL Snapshot) + */ + hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hddLog(LOGE, "%s: called for SAP",__func__); + hdd_wmm_tx_snapshot(pHostapdAdapter); + WLANTL_TLDebugMessage(VOS_TRUE); + return 0; +} + int static iw_softap_set_tx_power(struct net_device *dev, struct iw_request_info *info, @@ -1442,7 +1474,7 @@ static iw_softap_commit(struct net_device *dev, //TODO: Need to handle mixed mode pConfig->RSNEncryptType = RSNEncryptType; // Use the cipher type in the RSN IE pConfig->mcRSNEncryptType = mcRSNEncryptType; - hddLog( LOG1, FL("%s: CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d\n"), + hddLog( LOG1, FL("CSR AuthType = %d, EncryptionType = %d mcEncryptionType = %d\n"), RSNAuthType, RSNEncryptType, mcRSNEncryptType); } } @@ -1472,8 +1504,8 @@ static iw_softap_commit(struct net_device *dev, // ht_capab is not what the name conveys,this is used for protection bitmap pConfig->ht_capab = (WLAN_HDD_GET_CTX(pHostapdAdapter))->cfg_ini->apProtection; - if (pCommitConfig->num_accept_mac > MAX_MAC_ADDRESS_ACCEPTED) - num_mac = pConfig->num_accept_mac = MAX_MAC_ADDRESS_ACCEPTED; + if (pCommitConfig->num_accept_mac > MAX_ACL_MAC_ADDRESS) + num_mac = pConfig->num_accept_mac = MAX_ACL_MAC_ADDRESS; else num_mac = pConfig->num_accept_mac = pCommitConfig->num_accept_mac; acl_entry = pCommitConfig->accept_mac; @@ -1482,8 +1514,8 @@ static iw_softap_commit(struct net_device *dev, vos_mem_copy(&pConfig->accept_mac[i], acl_entry->addr, sizeof(v_MACADDR_t)); acl_entry++; } - if (pCommitConfig->num_deny_mac > MAX_MAC_ADDRESS_DENIED) - num_mac = pConfig->num_deny_mac = MAX_MAC_ADDRESS_DENIED; + if (pCommitConfig->num_deny_mac > MAX_ACL_MAC_ADDRESS) + num_mac = pConfig->num_deny_mac = MAX_ACL_MAC_ADDRESS; else num_mac = pConfig->num_deny_mac = pCommitConfig->num_deny_mac; acl_entry = pCommitConfig->deny_mac; @@ -1614,7 +1646,6 @@ int iw_softap_get_channel_list(struct net_device *dev, v_U8_t bandEndChannel = RF_CHAN_165; v_U32_t temp_num_channels = 0; hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pHostapdAdapter); v_REGDOMAIN_t domainIdCurrentSoftap; tpChannelListInfo channel_list = (tpChannelListInfo) extra; @@ -1639,8 +1670,8 @@ int iw_softap_get_channel_list(struct net_device *dev, bandEndChannel = RF_CHAN_165; } - hddLog(LOG1, FL("\n nBandCapability = %d, bandStartChannel = %hu, " - "bandEndChannel = %hu \n"), pHddCtx->cfg_ini->nBandCapability, + hddLog(LOG1, FL("\n curBand = %d, bandStartChannel = %hu, " + "bandEndChannel = %hu "), curBand, bandStartChannel, bandEndChannel ); for( i = bandStartChannel; i <= bandEndChannel; i++ ) @@ -1952,7 +1983,7 @@ static int iw_set_ap_encodeext(struct net_device *dev, } VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - ("%s:EncryptionType:%d key_len:%d, :%d, KeyId:%d \n"),__func__, setKey.encType, setKey.keyLength, + ("%s:EncryptionType:%d key_len:%d, KeyId:%d"), __func__, setKey.encType, setKey.keyLength, setKey.keyId); for(i=0; i< ext->key_len; i++) VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, @@ -2593,46 +2624,71 @@ int iw_get_softap_linkspeed(struct net_device *dev, { hdd_adapter_t *pHostapdAdapter = (netdev_priv(dev)); + hdd_context_t *pHddCtx; char *pLinkSpeed = (char*)extra; - v_U16_t link_speed; + v_U32_t link_speed; unsigned short staId; - int len = sizeof(v_U16_t)+1; + int len = sizeof(v_U32_t)+1; v_BYTE_t macAddress[VOS_MAC_ADDR_SIZE]; VOS_STATUS status; - int rc; + int rc, valid; + + pHddCtx = WLAN_HDD_GET_CTX(pHostapdAdapter); + + valid = wlan_hdd_validate_context(pHddCtx); + + if (0 != valid) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context not valid")); + return valid; + } if ( hdd_string_to_hex ((char *)wrqu->data.pointer, wrqu->data.length, macAddress ) ) { - hddLog(VOS_TRACE_LEVEL_FATAL, "ERROR: Command not found"); + hddLog(VOS_TRACE_LEVEL_FATAL, FL("ERROR: Command not found")); return -EINVAL; } status = hdd_softap_GetStaId(pHostapdAdapter, (v_MACADDR_t *)macAddress, (void *)(&staId)); - if (!VOS_IS_STATUS_SUCCESS(status )) + if (!VOS_IS_STATUS_SUCCESS(status)) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!")); + hddLog(VOS_TRACE_LEVEL_ERROR, FL("ERROR: HDD Failed to find sta id!!")); link_speed = 0; } else { status = wlan_hdd_get_classAstats_for_station(pHostapdAdapter , staId); + if (!VOS_IS_STATUS_SUCCESS(status )) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Unable to retrieve SME statistics", __func__); + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME statistics")); return -EINVAL; } - link_speed =(int)pHostapdAdapter->hdd_stats.ClassA_stat.tx_rate/2; + + WLANTL_GetSTALinkCapacity(pHddCtx->pvosContext, + staId, &link_speed); + + link_speed = link_speed / 10; + + if (0 == link_speed) + { + /* The linkspeed returned by HAL is in units of 500kbps. + * converting it to mbps. + * This is required to support legacy firmware which does + * not return link capacity. + */ + link_speed =(int)pHostapdAdapter->hdd_stats.ClassA_stat.tx_rate/2; + } } wrqu->data.length = len; - rc = snprintf(pLinkSpeed, len, "%u", link_speed); + rc = snprintf(pLinkSpeed, len, "%lu", link_speed); + if ((rc < 0) || (rc >= len)) { // encoding or length error? - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to encode link speed, got [%s]", - __func__, pLinkSpeed); + hddLog(VOS_TRACE_LEVEL_ERROR,FL( "Unable to encode link speed")); return -EIO; } @@ -2754,7 +2810,7 @@ static const struct iw_priv_args hostapd_private_args[] = { IW_PRIV_TYPE_BYTE | QCSAP_MAX_WSC_IE, 0, "ap_stats" }, { QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED, IW_PRIV_TYPE_CHAR | 18, - IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" }, + IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, { QCSAP_IOCTL_PRIV_SET_THREE_INT_GET_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3, 0, "" }, @@ -2816,6 +2872,8 @@ static const struct iw_priv_args hostapd_private_args[] = { IW_PRIV_TYPE_INT| IW_PRIV_SIZE_FIXED | 1, 0, "setTxMaxPower" }, + { QCSAP_IOCTL_DATAPATH_SNAP_SHOT, + IW_PRIV_TYPE_NONE | IW_PRIV_TYPE_NONE, 0, "dataSnapshot" }, }; static const iw_handler hostapd_private[] = { @@ -2841,6 +2899,7 @@ static const iw_handler hostapd_private[] = { [QCSAP_IOCTL_PRIV_GET_SOFTAP_LINK_SPEED - SIOCIWFIRSTPRIV] = iw_get_softap_linkspeed, [QCSAP_IOCTL_SET_TX_POWER - SIOCIWFIRSTPRIV] = iw_softap_set_tx_power, [QCSAP_IOCTL_SET_MAX_TX_POWER - SIOCIWFIRSTPRIV] = iw_softap_set_max_tx_power, + [QCSAP_IOCTL_DATAPATH_SNAP_SHOT - SIOCIWFIRSTPRIV] = iw_display_data_path_snapshot, }; const struct iw_handler_def hostapd_handler_def = { .num_standard = sizeof(hostapd_handler) / sizeof(hostapd_handler[0]), @@ -2891,10 +2950,13 @@ VOS_STATUS hdd_init_ap_mode( hdd_adapter_t *pAdapter ) { hdd_hostapd_state_t * phostapdBuf; struct net_device *dev = pAdapter->dev; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); VOS_STATUS status; ENTER(); // Allocate the Wireless Extensions state structure phostapdBuf = WLAN_HDD_GET_HOSTAP_STATE_PTR( pAdapter ); + + sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode); // Zero the memory. This zeros the profile structure. memset(phostapdBuf, 0,sizeof(hdd_hostapd_state_t)); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c old mode 100644 new mode 100755 index 837c45eb88f..0330179741c --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_main.c @@ -101,6 +101,8 @@ #include #endif // WLAN_BTAMP_FEATURE +#include +#include #include #include #include "wlan_hdd_cfg80211.h" @@ -160,6 +162,20 @@ static int wlan_hdd_inited; */ #define WLAN_HDD_RESTART_RETRY_DELAY_MS 5000 /* 5 second */ #define WLAN_HDD_RESTART_RETRY_MAX_CNT 5 /* 5 retries */ + +/* + * Size of Driver command strings from upper layer + */ +#define SIZE_OF_SETROAMMODE 11 /* size of SETROAMMODE */ +#define SIZE_OF_GETROAMMODE 11 /* size of GETROAMMODE */ + +/* + * Driver miracast parameters 0-Disabled + * 1-Source, 2-Sink + */ +#define WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL 0 +#define WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL 2 + #ifdef WLAN_OPEN_SOURCE static struct wake_lock wlan_wake_lock; #endif @@ -181,13 +197,18 @@ static void hdd_set_multicast_list(struct net_device *dev); #endif void hdd_wlan_initial_scan(hdd_adapter_t *pAdapter); -int isWDresetInProgress(void); extern int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr); #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand); static VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels); static VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 *pNumChannels); +static VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, + tANI_U8 *pChannel, tANI_U8 *pDwellTime, + tANI_U8 **pBuf, tANI_U8 *pBufLen); +static VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, + tANI_U8 *pTargetApBssid, + tANI_U8 *pChannel); #endif static int hdd_netdev_notifier_call(struct notifier_block * nb, unsigned long state, @@ -206,9 +227,6 @@ static int hdd_netdev_notifier_call(struct notifier_block * nb, (strncmp(dev->name, "p2p", 3))) return NOTIFY_DONE; - if (isWDresetInProgress()) - return NOTIFY_DONE; - if (!dev->ieee80211_ptr) return NOTIFY_DONE; @@ -227,6 +245,9 @@ static int hdd_netdev_notifier_call(struct notifier_block * nb, return NOTIFY_DONE; } + if (pHddCtx->isLogpInProgress) + return NOTIFY_DONE; + hddLog(VOS_TRACE_LEVEL_INFO, "%s: %s New Net Device State = %lu", __func__, dev->name, state); @@ -328,7 +349,7 @@ static int curr_con_mode; the desired trace levels. \param - moduleId - module whose trace level is being configured - \param - bitmask - bitmask of log levels to be enabled + \param - bitmask - bitmask of log levels to be enabled. \return - void @@ -403,6 +424,134 @@ static void hdd_wdi_trace_enable(wpt_moduleid moduleId, v_U32_t bitmask) } } +/* + * FUNCTION: wlan_hdd_validate_context + * This function is used to check the HDD context + */ +int wlan_hdd_validate_context(hdd_context_t *pHddCtx) +{ + ENTER(); + + if (NULL == pHddCtx || NULL == pHddCtx->cfg_ini) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is Null", __func__); + return -ENODEV; + } + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: LOGP in Progress. Ignore!!!", __func__); + return -EAGAIN; + } + + if (pHddCtx->isLoadUnloadInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Unloading/Loading in Progress. Ignore!!!", __func__); + return -EAGAIN; + } + return 0; +} + +void hdd_checkandupdate_phymode( hdd_adapter_t *pAdapter, char *country_code) +{ + hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *cfg_param; + eCsrPhyMode phyMode; + + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "HDD Context is null !!"); + return ; + } + + cfg_param = pHddCtx->cfg_ini; + + if (NULL == cfg_param) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "cfg_params not available !!"); + return ; + } + + phyMode = sme_GetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter)); + + if (NULL != strstr(cfg_param->listOfNon11acCountryCode, country_code)) + { + if ((eCSR_DOT11_MODE_AUTO == phyMode) || + (eCSR_DOT11_MODE_11ac == phyMode) || + (eCSR_DOT11_MODE_11ac_ONLY == phyMode)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Setting phymode to 11n!!"); + sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), eCSR_DOT11_MODE_11n); + } + } + else + { + /*New country Supports 11ac as well resetting value back from .ini*/ + sme_SetPhyMode(WLAN_HDD_GET_HAL_CTX(pAdapter), + hdd_cfg_xlate_to_csr_phy_mode(cfg_param->dot11Mode)); + return ; + } + + if ((eConnectionState_Associated == pHddStaCtx->conn_info.connState) && + ((eCSR_CFG_DOT11_MODE_11AC_ONLY == pHddStaCtx->conn_info.dot11Mode) || + (eCSR_CFG_DOT11_MODE_11AC == pHddStaCtx->conn_info.dot11Mode))) + { + VOS_STATUS vosStatus; + + // need to issue a disconnect to CSR. + INIT_COMPLETION(pAdapter->disconnect_comp_var); + vosStatus = sme_RoamDisconnect(WLAN_HDD_GET_HAL_CTX(pAdapter), + pAdapter->sessionId, + eCSR_DISCONNECT_REASON_UNSPECIFIED ); + + if (VOS_STATUS_SUCCESS == vosStatus) + wait_for_completion_interruptible_timeout(&pAdapter->disconnect_comp_var, + msecs_to_jiffies(WLAN_WAIT_TIME_DISCONNECT)); + + } +} + +void hdd_checkandupdate_dfssetting( hdd_adapter_t *pAdapter, char *country_code) +{ + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + hdd_config_t *cfg_param; + + if (NULL == pHddCtx) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "HDD Context is null !!"); + return ; + } + + cfg_param = pHddCtx->cfg_ini; + + if (NULL == cfg_param) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "cfg_params not available !!"); + return ; + } + + if (NULL != strstr(cfg_param->listOfNonDfsCountryCode, country_code)) + { + /*New country doesn't support DFS */ + sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), 0); + } + else + { + /*New country Supports DFS as well resetting value back from .ini*/ + sme_UpdateDfsSetting(WLAN_HDD_GET_HAL_CTX(pAdapter), cfg_param->enableDFSChnlScan); + } + +} + int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -456,6 +605,7 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) if ((SIOCDEVPRIVATE + 1) == cmd) { hdd_context_t *pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; + struct wiphy *wiphy = pHddCtx->wiphy; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received %s cmd from Wi-Fi GUI***", __func__, command); @@ -489,6 +639,9 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) char *country_code; country_code = command + 8; + + hdd_checkandupdate_dfssetting(pAdapter, country_code); + hdd_checkandupdate_phymode(pAdapter, country_code); ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, country_code, pAdapter, pHddCtx->pvosContext); if( 0 != ret ) @@ -497,6 +650,14 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) "%s: SME Change Country code fail ret=%d\n",__func__, ret); } + /* If you get a 00 country code it means you are world roaming. + In case of world roaming, country code should be updated by + DRIVER COUNTRY */ + if (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode, + CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) == 0) + { + regulatory_hint(wiphy, "00"); + } } #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) else if ( strncasecmp(command, "SETCOUNTRYREV", 13) == 0 ) @@ -535,6 +696,8 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } + hdd_checkandupdate_dfssetting(pAdapter, countryCode); + hdd_checkandupdate_phymode(pAdapter, countryCode); ret = (int)sme_ChangeCountryCode(pHddCtx->hHal, NULL, countryCode, pAdapter, pHddCtx->pvosContext); if (0 != ret) @@ -584,15 +747,29 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) else if (strncmp(command, "SETROAMTRIGGER", 14) == 0) { tANI_U8 *value = command; - int rssi = 0; + tANI_S8 rssi = 0; tANI_U8 lookUpThreshold = CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_DEFAULT; eHalStatus status = eHAL_STATUS_SUCCESS; /* Move pointer to ahead of SETROAMTRIGGER */ value = value + 15; - sscanf(value, "%d", &rssi); + /* Convert the value from ascii to integer */ + ret = kstrtos8(value, 10, &rssi); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN, + CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX); + ret = -EINVAL; + goto exit; + } + lookUpThreshold = abs(rssi); + if ((lookUpThreshold < CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MIN) || (lookUpThreshold > CFG_NEIGHBOR_LOOKUP_RSSI_THRESHOLD_MAX)) { @@ -641,19 +818,20 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) else if (strncmp(command, "SETROAMSCANPERIOD", 17) == 0) { tANI_U8 *value = command; + tANI_U8 roamScanPeriod = 0; tANI_U16 neighborEmptyScanRefreshPeriod = CFG_EMPTY_SCAN_REFRESH_PERIOD_DEFAULT; + /* input refresh period is in terms of seconds */ /* Move pointer to ahead of SETROAMSCANPERIOD */ value = value + 18; /* Convert the value from ascii to integer */ - ret = kstrtou16(value, 10, &neighborEmptyScanRefreshPeriod); + ret = kstrtou8(value, 10, &roamScanPeriod); if (ret < 0) { /* If the input value is greater than max value of datatype, then also - kstrtou16 fails */ + kstrtou8 fails */ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: kstrtou16 failed ", - "Input value may be out of range[%d - %d]", + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", __func__, (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000), (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)); @@ -661,22 +839,22 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } - neighborEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod * 1000; - if ((neighborEmptyScanRefreshPeriod < CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN) || - (neighborEmptyScanRefreshPeriod > CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX)) + if ((roamScanPeriod < (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000)) || + (roamScanPeriod > (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "Neighbor empty scan results refresh period value %d is out of range" - " (Min: %d Max: %d)", neighborEmptyScanRefreshPeriod/1000, + "Roam scan period value %d is out of range" + " (Min: %d Max: %d)", roamScanPeriod, (CFG_EMPTY_SCAN_REFRESH_PERIOD_MIN/1000), (CFG_EMPTY_SCAN_REFRESH_PERIOD_MAX/1000)); ret = -EINVAL; goto exit; } + neighborEmptyScanRefreshPeriod = roamScanPeriod * 1000; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received Command to Set roam scan period" - " (Empty Scan refresh period) = %d", __func__, neighborEmptyScanRefreshPeriod/1000); + " (Empty Scan refresh period) = %d", __func__, roamScanPeriod); pHddCtx->cfg_ini->nEmptyScanRefreshPeriod = neighborEmptyScanRefreshPeriod; sme_UpdateEmptyScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborEmptyScanRefreshPeriod); @@ -700,19 +878,21 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) else if (strncmp(command, "SETROAMSCANREFRESHPERIOD", 24) == 0) { tANI_U8 *value = command; + tANI_U8 roamScanRefreshPeriod = 0; tANI_U16 neighborScanRefreshPeriod = CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_DEFAULT; + /* input refresh period is in terms of seconds */ /* Move pointer to ahead of SETROAMSCANREFRESHPERIOD */ value = value + 25; + /* Convert the value from ascii to integer */ - ret = kstrtou16(value, 10, &neighborScanRefreshPeriod); + ret = kstrtou8(value, 10, &roamScanRefreshPeriod); if (ret < 0) { /* If the input value is greater than max value of datatype, then also - kstrtou16 fails */ + kstrtou8 fails */ VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: kstrtou16 failed ", - "Input value may be out of range[%d - %d]", + "%s: kstrtou8 failed Input value may be out of range[%d - %d]", __func__, (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000), (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)); @@ -720,22 +900,22 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } - neighborScanRefreshPeriod = neighborScanRefreshPeriod * 1000; - if ((neighborScanRefreshPeriod < CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN) || - (neighborScanRefreshPeriod > CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX)) + if ((roamScanRefreshPeriod < (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000)) || + (roamScanRefreshPeriod > (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "Neighbor scan results refresh period value %d is out of range" - " (Min: %d Max: %d)", neighborScanRefreshPeriod/1000, + " (Min: %d Max: %d)", roamScanRefreshPeriod, (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MIN/1000), (CFG_NEIGHBOR_SCAN_RESULTS_REFRESH_PERIOD_MAX/1000)); ret = -EINVAL; goto exit; } + neighborScanRefreshPeriod = roamScanRefreshPeriod * 1000; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: Received Command to Set roam scan refresh period" - " (Scan refresh period) = %d", __func__, neighborScanRefreshPeriod/1000); + " (Scan refresh period) = %d", __func__, roamScanRefreshPeriod); pHddCtx->cfg_ini->nNeighborResultsRefreshPeriod = neighborScanRefreshPeriod; sme_setNeighborScanRefreshPeriod((tHalHandle)(pHddCtx->hHal), neighborScanRefreshPeriod); @@ -756,6 +936,83 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } } +#ifdef FEATURE_WLAN_LFR + /* SETROAMMODE */ + else if (strncmp(command, "SETROAMMODE", SIZE_OF_SETROAMMODE) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN roamMode = CFG_LFR_FEATURE_ENABLED_DEFAULT; + + /* Move pointer to ahead of SETROAMMODE */ + value = value + SIZE_OF_SETROAMMODE + 1; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, SIZE_OF_SETROAMMODE, &roamMode); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + if ((roamMode < CFG_LFR_FEATURE_ENABLED_MIN) || + (roamMode > CFG_LFR_FEATURE_ENABLED_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Roam Mode value %d is out of range" + " (Min: %d Max: %d)", roamMode, + CFG_LFR_FEATURE_ENABLED_MIN, + CFG_LFR_FEATURE_ENABLED_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set Roam Mode = %d", __func__, roamMode); + /* + * Note that + * SETROAMMODE 0 is to enable LFR while + * SETROAMMODE 1 is to disable LFR, but + * NotifyIsFastRoamIniFeatureEnabled 0/1 is to enable/disable. + * So, we have to invert the value to call sme_UpdateIsFastRoamIniFeatureEnabled. + */ + if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode) + roamMode = CFG_LFR_FEATURE_ENABLED_MAX; /* Roam enable */ + else + roamMode = CFG_LFR_FEATURE_ENABLED_MIN; /* Roam disable */ + + pHddCtx->cfg_ini->isFastRoamIniFeatureEnabled = roamMode; + sme_UpdateIsFastRoamIniFeatureEnabled((tHalHandle)(pHddCtx->hHal), roamMode); + } + /* GETROAMMODE */ + else if (strncmp(priv_data.buf, "GETROAMMODE", SIZE_OF_GETROAMMODE) == 0) + { + tANI_BOOLEAN roamMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal)); + char extra[32]; + tANI_U8 len = 0; + + /* + * roamMode value shall be inverted because the sementics is different. + */ + if (CFG_LFR_FEATURE_ENABLED_MIN == roamMode) + roamMode = CFG_LFR_FEATURE_ENABLED_MAX; + else + roamMode = CFG_LFR_FEATURE_ENABLED_MIN; + + len = snprintf(extra, sizeof(extra), "%s %d", command, roamMode); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#endif #endif #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) else if (strncmp(command, "SETROAMDELTA", 12) == 0) @@ -929,6 +1186,137 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } } + else if (strncmp(command, "SENDACTIONFRAME", 15) == 0) + { + tANI_U8 *value = command; + tANI_U8 channel = 0; + tANI_U8 dwellTime = 0; + tANI_U8 bufLen = 0; + tANI_U8 *buf = NULL; + tSirMacAddr targetApBssid; + eHalStatus status = eHAL_STATUS_SUCCESS; + struct ieee80211_channel chan; + tANI_U8 finalLen = 0; + tANI_U8 *finalBuf = NULL; + tANI_U8 temp = 0; + u64 cookie; + hdd_station_ctx_t *pHddStaCtx = NULL; + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + /* if not associated, no need to send action frame */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__); + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_send_action_frame_data(value, targetApBssid, &channel, + &dwellTime, &buf, &bufLen); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse send action frame data", __func__); + ret = -EINVAL; + goto exit; + } + + /* if the target bssid is different from currently associated AP, + then no need to send action frame */ + if (VOS_TRUE != vos_mem_compare(targetApBssid, + pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:STA is not associated to this AP!",__func__); + ret = -EINVAL; + goto exit; + } + + /* if the channel number is different from operating channel then + no need to send action frame */ + if (channel != pHddStaCtx->conn_info.operationChannel) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: channel(%d) is different from operating channel(%d)", + __func__, channel, pHddStaCtx->conn_info.operationChannel); + ret = -EINVAL; + goto exit; + } + chan.center_freq = sme_ChnToFreq(channel); + + finalLen = bufLen + 24; + finalBuf = vos_mem_malloc(finalLen); + if (NULL == finalBuf) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s:memory allocation failed",__func__); + ret = -ENOMEM; + goto exit; + } + vos_mem_zero(finalBuf, finalLen); + + /* Fill subtype */ + temp = SIR_MAC_MGMT_ACTION << 4; + vos_mem_copy(finalBuf + 0, &temp, sizeof(temp)); + + /* Fill type */ + temp = SIR_MAC_MGMT_FRAME; + vos_mem_copy(finalBuf + 2, &temp, sizeof(temp)); + + /* Fill destination address (bssid of the AP) */ + vos_mem_copy(finalBuf + 4, targetApBssid, sizeof(targetApBssid)); + + /* Fill source address (STA mac address) */ + vos_mem_copy(finalBuf + 10, pAdapter->macAddressCurrent.bytes, sizeof(pAdapter->macAddressCurrent.bytes)); + + /* Fill BSSID (AP mac address) */ + vos_mem_copy(finalBuf + 16, targetApBssid, sizeof(targetApBssid)); + + /* Fill received buffer from 24th address */ + vos_mem_copy(finalBuf + 24, buf, bufLen); + + wlan_hdd_action( NULL, dev, &chan, 0, NL80211_CHAN_HT20, + 1, dwellTime, finalBuf, finalLen, 1, + 1, &cookie ); + vos_mem_free(finalBuf); + } + else if (strncmp(command, "SETWESMODE", 10) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN wesMode = CFG_ENABLE_WES_MODE_NAME_DEFAULT; + + /* Move pointer to ahead of SETWESMODE */ + value = value + 11; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &wesMode); + + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX); + ret = -EINVAL; + goto exit; + } + + if ((wesMode < CFG_ENABLE_WES_MODE_NAME_MIN) || + (wesMode > CFG_ENABLE_WES_MODE_NAME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "WES Mode value %d is out of range" + " (Min: %d Max: %d)", wesMode, + CFG_ENABLE_WES_MODE_NAME_MIN, + CFG_ENABLE_WES_MODE_NAME_MAX); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set WES Mode rssi diff = %d", __func__, wesMode); + + pHddCtx->cfg_ini->isWESModeEnabled = wesMode; + sme_UpdateWESMode((tHalHandle)(pHddCtx->hHal), wesMode); + } else if (strncmp(command, "GETCCXMODE", 10) == 0) { tANI_BOOLEAN ccxMode = sme_getIsCcxFeatureEnabled((tHalHandle)(pHddCtx->hHal)); @@ -959,7 +1347,7 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) goto exit; } } - else if (strncmp(command, "GETFASTROAM", 10) == 0) + else if (strncmp(command, "GETFASTROAM", 11) == 0) { tANI_BOOLEAN lfrMode = sme_getIsLfrFeatureEnabled((tHalHandle)(pHddCtx->hHal)); char extra[32]; @@ -1210,6 +1598,179 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } } + else if (strncmp(command, "SETSCANNPROBES", 14) == 0) + { + tANI_U8 *value = command; + tANI_U8 nProbes = CFG_ROAM_SCAN_N_PROBES_DEFAULT; + + /* Move pointer to ahead of SETSCANNPROBES */ + value = value + 15; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &nProbes); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX); + ret = -EINVAL; + goto exit; + } + + if ((nProbes < CFG_ROAM_SCAN_N_PROBES_MIN) || + (nProbes > CFG_ROAM_SCAN_N_PROBES_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "NProbes value %d is out of range" + " (Min: %d Max: %d)", nProbes, + CFG_ROAM_SCAN_N_PROBES_MIN, + CFG_ROAM_SCAN_N_PROBES_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set nProbes = %d", __func__, nProbes); + + pHddCtx->cfg_ini->nProbes = nProbes; + sme_UpdateRoamScanNProbes((tHalHandle)(pHddCtx->hHal), nProbes); + } + else if (strncmp(priv_data.buf, "GETSCANNPROBES", 14) == 0) + { + tANI_U8 val = sme_getRoamScanNProbes((tHalHandle)(pHddCtx->hHal)); + char extra[32]; + tANI_U8 len = 0; + + len = snprintf(extra, sizeof(extra), "%s %d", command, val); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "SETSCANHOMEAWAYTIME", 19) == 0) + { + tANI_U8 *value = command; + tANI_U16 homeAwayTime = CFG_ROAM_SCAN_HOME_AWAY_TIME_DEFAULT; + + /* Move pointer to ahead of SETSCANHOMEAWAYTIME */ + /* input value is in units of msec */ + value = value + 20; + /* Convert the value from ascii to integer */ + ret = kstrtou16(value, 10, &homeAwayTime); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range [%d - %d]", __func__, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + /*Currently Home Away Time has a MIN value of 3. + * But, we sould allow the user to input Zero, + * since we are using the value of Zero to disable + * this and fallback to LFR1.5 behaviour.*/ + if (0 != homeAwayTime) + if ((homeAwayTime < CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN) || + (homeAwayTime > CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "homeAwayTime value %d is out of range" + " (Min: %d Max: %d)", homeAwayTime, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MIN, + CFG_ROAM_SCAN_HOME_AWAY_TIME_MAX); + ret = -EINVAL; + goto exit; + } + + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set scan away time = %d", __func__, homeAwayTime); + + pHddCtx->cfg_ini->nRoamScanHomeAwayTime = homeAwayTime; + sme_UpdateRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal), homeAwayTime); + } + else if (strncmp(priv_data.buf, "GETSCANHOMEAWAYTIME", 19) == 0) + { + tANI_U16 val = sme_getRoamScanHomeAwayTime((tHalHandle)(pHddCtx->hHal)); + char extra[32]; + tANI_U8 len = 0; + + len = snprintf(extra, sizeof(extra), "%s %d", command, val); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } + else if (strncmp(command, "REASSOC", 7) == 0) + { + tANI_U8 *value = command; + tANI_U8 channel = 0; + tSirMacAddr targetApBssid; + eHalStatus status = eHAL_STATUS_SUCCESS; + + hdd_station_ctx_t *pHddStaCtx = NULL; + tANI_BOOLEAN wesMode = eANI_BOOLEAN_FALSE; + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + + wesMode = sme_GetWESMode((tHalHandle)(pHddCtx->hHal)); + + /* Reassoc command is allowed only if WES mode is enabled */ + if (!wesMode) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:WES Mode is not enabled(%d)",__func__, wesMode); + ret = -EINVAL; + goto exit; + } + + /* if not associated, no need to proceed with reassoc */ + if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Not associated!",__func__); + ret = -EINVAL; + goto exit; + } + + status = hdd_parse_reassoc_command_data(value, targetApBssid, &channel); + if (eHAL_STATUS_SUCCESS != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to parse reassoc command data", __func__); + ret = -EINVAL; + goto exit; + } + + /* if the target bssid is same as currently associated AP, + then no need to proceed with reassoc */ + if (VOS_TRUE == vos_mem_compare(targetApBssid, + pHddStaCtx->conn_info.bssId, sizeof(tSirMacAddr))) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s:Reassoc BSSID is same as currently associated AP bssid",__func__); + ret = -EINVAL; + goto exit; + } + + /* Check channel number is a valid channel number */ + if(VOS_STATUS_SUCCESS != + wlan_hdd_validate_operation_channel(pAdapter, channel)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Invalid Channel [%d] \n", __func__, channel); + return -EINVAL; + } + + /* Proceed with reassoc */ + } #endif #ifdef FEATURE_WLAN_LFR else if (strncmp(command, "SETFASTROAM", 11) == 0) @@ -1374,6 +1935,152 @@ int hdd_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) pHddCtx->cfg_ini->isOkcIniFeatureEnabled = okcMode; } #endif + else if (strncmp(command, "SETROAMSCANCONTROL", 18) == 0) + { + tANI_U8 *value = command; + tANI_BOOLEAN roamScanControl = 0; + + /* Move pointer to ahead of SETROAMSCANCONTROL */ + value = value + 19; + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &roamScanControl); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, then also + kstrtou8 fails */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed ", __func__); + ret = -EINVAL; + goto exit; + } + + if (0 != roamScanControl) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "roam scan control invalid value = %d", + roamScanControl); + ret = -EINVAL; + goto exit; + } + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Received Command to Set roam scan control = %d", __func__, roamScanControl); + + sme_SetRoamScanControl((tHalHandle)(pHddCtx->hHal), roamScanControl); + } + else if (strncmp(priv_data.buf, "GETROAMSCANCONTROL", 18) == 0) + { + tANI_BOOLEAN roamScanControl = sme_GetRoamScanControl((tHalHandle)(pHddCtx->hHal)); + char extra[32]; + tANI_U8 len = 0; + + len = snprintf(extra, sizeof(extra), "%s %d", command, roamScanControl); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + } +#ifdef WLAN_FEATURE_PACKET_FILTERING + else if (strncmp(command, "ENABLE_PKTFILTER_IPV6", 21) == 0) + { + tANI_U8 filterType = 0; + tANI_U8 *value = command; + + /* Move pointer to ahead of ENABLE_PKTFILTER_IPV6 */ + value = value + 22; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &filterType); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, + * then also kstrtou8 fails + */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range ", __func__); + ret = -EINVAL; + goto exit; + } + + if (filterType != 0 && filterType != 1) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Accepted Values are 0 and 1 ", __func__); + ret = -EINVAL; + goto exit; + } + wlan_hdd_setIPv6Filter(WLAN_HDD_GET_CTX(pAdapter), filterType, + pAdapter->sessionId); + } +#endif + else if (strncmp(command, "GETDWELLTIME", 12) == 0) + { + hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + char extra[32]; + tANI_U8 len = 0; + + len = snprintf(extra, sizeof(extra), "GETDWELLTIME %u\n", + (int)pCfg->nActiveMaxChnTime); + if (copy_to_user(priv_data.buf, &extra, len + 1)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: failed to copy data to user buffer", __func__); + ret = -EFAULT; + goto exit; + } + ret = len; + } + else if (strncmp(command, "SETDWELLTIME", 12) == 0) + { + tANI_U8 *value = command; + hdd_config_t *pCfg = (WLAN_HDD_GET_CTX(pAdapter))->cfg_ini; + int val = 0, temp; + + value = value + 13; + temp = kstrtou32(value, 10, &val); + if ( temp != 0 || val < CFG_ACTIVE_MAX_CHANNEL_TIME_MIN || + val > CFG_ACTIVE_MAX_CHANNEL_TIME_MAX ) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: argument passed for SETDWELLTIME is incorrect", __func__); + ret = -EFAULT; + goto exit; + } + pCfg->nActiveMaxChnTime = val; + } + else if ( strncasecmp(command, "MIRACAST", 8) == 0 ) + { + tANI_U8 filterType = 0; + tANI_U8 *value; + value = command + 9; + + /* Convert the value from ascii to integer */ + ret = kstrtou8(value, 10, &filterType); + if (ret < 0) + { + /* If the input value is greater than max value of datatype, 1993 + * then also kstrtou8 fails 1994 + */ + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: kstrtou8 failed range ", __func__); + ret = -EINVAL; + goto exit; + } + if ((filterType < WLAN_HDD_DRIVER_MIRACAST_CFG_MIN_VAL ) || + (filterType > WLAN_HDD_DRIVER_MIRACAST_CFG_MAX_VAL)) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Accepted Values are 0 to 2. 0-Disabled, 1-Source," + " 2-Sink ", __func__); + ret = -EINVAL; + goto exit; + } + //Filtertype value should be either 0-Disabled, 1-Source, 2-sink + pHddCtx->drvr_miracast = filterType; + hdd_tx_rx_pkt_cnt_stat_timer_handler(pHddCtx); + } else { hddLog( VOS_TRACE_LEVEL_WARN, "%s: Unsupported GUI command %s", __func__, command); @@ -1395,23 +2102,174 @@ void hdd_getBand_helper(hdd_context_t *pHddCtx, int *pBand) sme_GetFreqBand((tHalHandle)(pHddCtx->hHal), &band); switch (band) { - case eCSR_BAND_ALL: - *pBand = WLAN_HDD_UI_BAND_AUTO; - break; + case eCSR_BAND_ALL: + *pBand = WLAN_HDD_UI_BAND_AUTO; + break; + + case eCSR_BAND_24: + *pBand = WLAN_HDD_UI_BAND_2_4_GHZ; + break; + + case eCSR_BAND_5G: + *pBand = WLAN_HDD_UI_BAND_5_GHZ; + break; + + default: + hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band); + *pBand = -1; + break; + } +} + +/**--------------------------------------------------------------------------- + + \brief hdd_parse_send_action_frame_data() - HDD Parse send action frame data + + This function parses the send action frame data passed in the format + SENDACTIONFRAME + + \param - pValue Pointer to input country code revision + \param - pTargetApBssid Pointer to target Ap bssid + \param - pChannel Pointer to the Target AP channel + \param - pDwellTime Pointer to the time to stay off-channel after transmitting action frame + \param - pBuf Pointer to data + \param - pBufLen Pointer to data length + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +VOS_STATUS hdd_parse_send_action_frame_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel, + tANI_U8 *pDwellTime, tANI_U8 **pBuf, tANI_U8 *pBufLen) +{ + tANI_U8 *inPtr = pValue; + tANI_U8 *dataEnd; + int tempInt; + int j = 0; + int i = 0; + int v = 0; + tANI_U8 tempBuf[32]; + tANI_U8 tempByte = 0; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) + { + return -EINVAL; + } + + /*no space after the command*/ + else if (SPACE_ASCII_VALUE != *inPtr) + { + return -EINVAL; + } + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /*getting the first argument ie the target AP bssid */ + if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':') + { + return -EINVAL; + } + j = sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1], + (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3], + (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]); + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) return -EINVAL; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /*getting the next argument ie the channel number */ + j = sscanf(inPtr, "%s ", tempBuf); + v = kstrtos32(tempBuf, 10, &tempInt); + if ( v < 0) return -EINVAL; + + *pChannel = tempInt; + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) return -EINVAL; + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } - case eCSR_BAND_24: - *pBand = WLAN_HDD_UI_BAND_2_4_GHZ; - break; + /*getting the next argument ie the dwell time */ + j = sscanf(inPtr, "%s ", tempBuf); + v = kstrtos32(tempBuf, 10, &tempInt); + if ( v < 0) return -EINVAL; - case eCSR_BAND_5G: - *pBand = WLAN_HDD_UI_BAND_5_GHZ; - break; + *pDwellTime = tempInt; - default: - hddLog( VOS_TRACE_LEVEL_WARN, "%s: Invalid Band %d", __func__, band); - *pBand = -1; - break; + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) return -EINVAL; + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /* find the length of data */ + dataEnd = inPtr; + while(('\0' != *dataEnd) ) + { + dataEnd++; + ++(*pBufLen); + } + if ( *pBufLen <= 0) return -EINVAL; + + /* Allocate the number of bytes based on the number of input characters + whether it is even or odd. + if the number of input characters are even, then we need N/2 byte. + if the number of input characters are odd, then we need do (N+1)/2 to + compensate rounding off. + For example, if N = 18, then (18 + 1)/2 = 9 bytes are enough. + If N = 19, then we need 10 bytes, hence (19 + 1)/2 = 10 bytes */ + *pBuf = vos_mem_malloc((*pBufLen + 1)/2); + if (NULL == *pBuf) + { + hddLog(VOS_TRACE_LEVEL_FATAL, + "%s: vos_mem_alloc failed ", __func__); + return -EINVAL; + } + + /* the buffer received from the upper layer is character buffer, + we need to prepare the buffer taking 2 characters in to a U8 hex decimal number + for example 7f0000f0...form a buffer to contain 7f in 0th location, 00 in 1st + and f0 in 3rd location */ + for (i = 0, j = 0; j < *pBufLen; j += 2) + { + tempByte = (hdd_parse_hex(inPtr[j]) << 4) | (hdd_parse_hex(inPtr[j + 1])); + (*pBuf)[i++] = tempByte; } + *pBufLen = i; + return VOS_STATUS_SUCCESS; } /**--------------------------------------------------------------------------- @@ -1500,11 +2358,6 @@ VOS_STATUS hdd_parse_countryrev(tANI_U8 *pValue, tANI_U8 *pCountryCode, tANI_U8 This function parses the channel list passed in the format SETROAMSCANCHANNELSChannel 1Channel 2Channel N - if the Number of channels (N) does not match with the actual number of channels passed - then take the minimum of N and count of (Ch1, Ch2, ...Ch M) - For example, if SETROAMSCANCHANNELS 3 36 40 44 48, only 36, 40 and 44 shall be taken. - If SETROAMSCANCHANNELS 5 36 40 44 48, ignore 5 and take 36, 40, 44 and 48. - This function does not take care of removing duplicate channels from the list \param - pValue Pointer to input channel list \param - ChannelList Pointer to local output array to record channel list @@ -1535,7 +2388,7 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 } /*removing empty spaces*/ - while ((SPACE_ASCII_VALUE == *inPtr)&& ('\0' != *inPtr) ) inPtr++; + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; /*no argument followed by spaces*/ if ('\0' == *inPtr) @@ -1546,7 +2399,12 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 /*getting the first argument ie the number of channels*/ sscanf(inPtr, "%32s ", buf); v = kstrtos32(buf, 10, &tempInt); - if ((v < 0) || (tempInt <= 0)) return -EINVAL; + if ((v < 0) || + (tempInt <= 0) || + (tempInt > WNI_CFG_VALID_CHANNEL_LIST_LEN)) + { + return -EINVAL; + } *pNumChannels = tempInt; @@ -1572,7 +2430,7 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 } /*removing empty space*/ - while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr)) inPtr++; /*no channel list after the number of channels argument and spaces*/ if ( '\0' == *inPtr ) @@ -1588,9 +2446,14 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 } } - sscanf(inPtr, "%s ", buf); + sscanf(inPtr, "%32s ", buf); v = kstrtos32(buf, 10, &tempInt); - if ((v < 0) || (tempInt <= 0)) return -EINVAL; + if ((v < 0) || + (tempInt <= 0) || + (tempInt > WNI_CFG_CURRENT_CHANNEL_STAMAX)) + { + return -EINVAL; + } pChannelList[j] = tempInt; VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO_HIGH, @@ -1601,7 +2464,84 @@ VOS_STATUS hdd_parse_channellist(tANI_U8 *pValue, tANI_U8 *pChannelList, tANI_U8 return VOS_STATUS_SUCCESS; } + +/**--------------------------------------------------------------------------- + + \brief hdd_parse_reassoc_command_data() - HDD Parse reassoc command data + + This function parses the reasoc command data passed in the format + REASSOC + + \param - pValue Pointer to input country code revision + \param - pTargetApBssid Pointer to target Ap bssid + \param - pChannel Pointer to the Target AP channel + + \return - 0 for success non-zero for failure + + --------------------------------------------------------------------------*/ +VOS_STATUS hdd_parse_reassoc_command_data(tANI_U8 *pValue, tANI_U8 *pTargetApBssid, tANI_U8 *pChannel) +{ + tANI_U8 *inPtr = pValue; + int tempInt; + int v = 0; + tANI_U8 tempBuf[32]; + + inPtr = strnchr(pValue, strlen(pValue), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) + { + return -EINVAL; + } + + /*no space after the command*/ + else if (SPACE_ASCII_VALUE != *inPtr) + { + return -EINVAL; + } + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /*getting the first argument ie the target AP bssid */ + if (inPtr[2] != ':' || inPtr[5] != ':' || inPtr[8] != ':' || inPtr[11] != ':' || inPtr[14] != ':') + { + return -EINVAL; + } + sscanf(inPtr, "%2x:%2x:%2x:%2x:%2x:%2x", (unsigned int *)&pTargetApBssid[0], (unsigned int *)&pTargetApBssid[1], + (unsigned int *)&pTargetApBssid[2], (unsigned int *)&pTargetApBssid[3], + (unsigned int *)&pTargetApBssid[4], (unsigned int *)&pTargetApBssid[5]); + + /* point to the next argument */ + inPtr = strnchr(inPtr, strlen(inPtr), SPACE_ASCII_VALUE); + /*no argument after the command*/ + if (NULL == inPtr) return -EINVAL; + + /*removing empty spaces*/ + while ((SPACE_ASCII_VALUE == *inPtr) && ('\0' != *inPtr) ) inPtr++; + + /*no argument followed by spaces*/ + if ('\0' == *inPtr) + { + return -EINVAL; + } + + /*getting the next argument ie the channel number */ + sscanf(inPtr, "%s ", tempBuf); + v = kstrtos32(tempBuf, 10, &tempInt); + if ( v < 0) return -EINVAL; + + *pChannel = tempInt; + return VOS_STATUS_SUCCESS; +} + #endif + /**--------------------------------------------------------------------------- \brief hdd_open() - HDD Open function @@ -1639,18 +2579,18 @@ int hdd_open (struct net_device *dev) status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) ) { - if( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of " - "standby", __func__, pAdapter->device_mode); - in_standby = FALSE; - break; - } - else - { - status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); - pAdapterNode = pNext; - } + if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags)) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: chip already out of standby", + __func__); + in_standby = FALSE; + break; + } + else + { + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } } if (TRUE == in_standby) @@ -1663,7 +2603,7 @@ int hdd_open (struct net_device *dev) } } - pAdapter->event_flags |= DEVICE_IFACE_OPENED; + set_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); if (hdd_connIsConnected(WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))) { VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, @@ -1726,7 +2666,7 @@ int hdd_stop (struct net_device *dev) return -ENODEV; } - pAdapter->event_flags &= ~(DEVICE_IFACE_OPENED); + clear_bit(DEVICE_IFACE_OPENED, &pAdapter->event_flags); hddLog(VOS_TRACE_LEVEL_INFO, "%s: Disabling OS Tx queues", __func__); netif_tx_disable(pAdapter->dev); netif_carrier_off(pAdapter->dev); @@ -1749,18 +2689,18 @@ int hdd_stop (struct net_device *dev) status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); while ( (NULL != pAdapterNode) && (VOS_STATUS_SUCCESS == status) ) { - if ( pAdapterNode->pAdapter->event_flags & DEVICE_IFACE_OPENED) - { - hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot " - "put device to sleep", __func__, pAdapter->device_mode); - enter_standby = FALSE; - break; - } - else - { - status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); - pAdapterNode = pNext; - } + if (test_bit(DEVICE_IFACE_OPENED, &pAdapterNode->pAdapter->event_flags)) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Still other ifaces are up cannot " + "put device to sleep", __func__); + enter_standby = FALSE; + break; + } + else + { + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } } if (TRUE == enter_standby) @@ -2239,6 +3179,7 @@ static hdd_adapter_t* hdd_alloc_station_adapter( hdd_context_t *pHddCtx, tSirMac #endif init_completion(&pHddCtx->mc_sus_event_var); init_completion(&pHddCtx->tx_sus_event_var); + init_completion(&pHddCtx->rx_sus_event_var); init_completion(&pAdapter->ula_complete); pAdapter->isLinkUpSvcNeeded = FALSE; @@ -2299,19 +3240,40 @@ VOS_STATUS hdd_register_interface( hdd_adapter_t *pAdapter, tANI_U8 rtnl_lock_he return VOS_STATUS_SUCCESS; } -eHalStatus hdd_smeCloseSessionCallback(void *pContext) +static eHalStatus hdd_smeCloseSessionCallback(void *pContext) { - if(pContext != NULL) + hdd_adapter_t *pAdapter = pContext; + + if (NULL == pAdapter) { - clear_bit(SME_SESSION_OPENED, &((hdd_adapter_t*)pContext)->event_flags); + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: NULL pAdapter", __func__); + return eHAL_STATUS_INVALID_PARAMETER; + } - /* need to make sure all of our scheduled work has completed. - * This callback is called from MC thread context, so it is safe to - * to call below flush workqueue API from here. - */ - flush_scheduled_work(); - complete(&((hdd_adapter_t*)pContext)->session_close_comp_var); + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Invalid magic", __func__); + return eHAL_STATUS_NOT_INITIALIZED; + } + + clear_bit(SME_SESSION_OPENED, &pAdapter->event_flags); + + /* need to make sure all of our scheduled work has completed. + * This callback is called from MC thread context, so it is safe to + * to call below flush workqueue API from here. + */ + flush_scheduled_work(); + + /* We can be blocked while waiting for scheduled work to be + * flushed, and the adapter structure can potentially be freed, in + * which case the magic will have been reset. So make sure the + * magic is still good, and hence the adapter structure is still + * valid, before signaling completion */ + if (WLAN_HDD_ADAPTER_MAGIC == pAdapter->magic) + { + complete(&pAdapter->session_close_comp_var); } + return eHAL_STATUS_SUCCESS; } @@ -2325,6 +3287,7 @@ VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter ) int rc = 0; INIT_COMPLETION(pAdapter->session_open_comp_var); + sme_SetCurrDeviceMode(pHddCtx->hHal, pAdapter->device_mode); //Open a SME session for future operation halStatus = sme_OpenSession( pHddCtx->hHal, hdd_smeRoamCallback, pAdapter, (tANI_U8 *)&pAdapter->macAddressCurrent, &pAdapter->sessionId ); @@ -2417,17 +3380,17 @@ VOS_STATUS hdd_init_station_mode( hdd_adapter_t *pAdapter ) error_init_txrx: hdd_UnregisterWext(pWlanDev); error_register_wext: - if(test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) + if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) { INIT_COMPLETION(pAdapter->session_close_comp_var); - if( eHAL_STATUS_SUCCESS == sme_CloseSession( pHddCtx->hHal, + if (eHAL_STATUS_SUCCESS == sme_CloseSession(pHddCtx->hHal, pAdapter->sessionId, - hdd_smeCloseSessionCallback, pAdapter ) ) + hdd_smeCloseSessionCallback, pAdapter)) { //Block on a completion variable. Can't wait forever though. - wait_for_completion_interruptible_timeout( + wait_for_completion_timeout( &pAdapter->session_close_comp_var, - msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); + msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); } } error_sme_open: @@ -2544,32 +3507,70 @@ void hdd_cleanup_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, tANI_ void hdd_set_pwrparams(hdd_context_t *pHddCtx) { - tSirSetPowerParamsReq powerRequest = { 0 }; + VOS_STATUS status; + hdd_adapter_t *pAdapter = NULL; + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; - powerRequest.uIgnoreDTIM = 1; + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); - if (pHddCtx->cfg_ini->enableModulatedDTIM) - { - powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM; - powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; - } - else + /*loop through all adapters.*/ + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { - powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM; - } + pAdapter = pAdapterNode->pAdapter; + if ( (WLAN_HDD_INFRA_STATION != pAdapter->device_mode) + && (WLAN_HDD_P2P_CLIENT != pAdapter->device_mode) ) - /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM - *specified during Enter/Exit BMPS when LCD off*/ - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, - NULL, eANI_BOOLEAN_FALSE); - ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, - NULL, eANI_BOOLEAN_FALSE); + { // we skip this registration for modes other than STA and P2P client modes. + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + continue; + } - /* switch to the DTIM specified in cfg.ini */ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, - "Switch to DTIM%d", powerRequest.uListenInterval); - sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE); + //Apply Dynamic DTIM For P2P + //Only if ignoreDynamicDtimInP2pMode is not set in ini + if ((pHddCtx->cfg_ini->enableDynamicDTIM || + pHddCtx->cfg_ini->enableModulatedDTIM) && + ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + ((WLAN_HDD_P2P_CLIENT == pAdapter->device_mode) && + !(pHddCtx->cfg_ini->ignoreDynamicDtimInP2pMode))) && + (eANI_BOOLEAN_TRUE == pAdapter->higherDtimTransition) && + (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState) && + (pHddCtx->cfg_ini->fIsBmpsEnabled)) + { + tSirSetPowerParamsReq powerRequest = { 0 }; + + powerRequest.uIgnoreDTIM = 1; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; + + if (pHddCtx->cfg_ini->enableModulatedDTIM) + { + powerRequest.uDTIMPeriod = pHddCtx->cfg_ini->enableModulatedDTIM; + powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + } + else + { + powerRequest.uListenInterval = pHddCtx->cfg_ini->enableDynamicDTIM; + } + + /* Update ignoreDTIM and ListedInterval in CFG to remain at the DTIM + * specified during Enter/Exit BMPS when LCD off*/ + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, + NULL, eANI_BOOLEAN_FALSE); + ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, powerRequest.uListenInterval, + NULL, eANI_BOOLEAN_FALSE); + + /* switch to the DTIM specified in cfg.ini */ + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "Switch to DTIM %d", powerRequest.uListenInterval); + sme_SetPowerParams( pHddCtx->hHal, &powerRequest, TRUE); + break; + + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } } void hdd_reset_pwrparams(hdd_context_t *pHddCtx) @@ -2579,6 +3580,7 @@ void hdd_reset_pwrparams(hdd_context_t *pHddCtx) powerRequest.uIgnoreDTIM = pHddCtx->hdd_actual_ignore_DTIM_value; powerRequest.uListenInterval = pHddCtx->hdd_actual_LI_value; + powerRequest.uMaxLIModulatedDTIM = pHddCtx->cfg_ini->fMaxLIModulatedDTIM; /* Update ignoreDTIM and ListedInterval in CFG with default values */ ccmCfgSetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, powerRequest.uIgnoreDTIM, @@ -2769,6 +3771,11 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, hdd_deinit_adapter(pHddCtx, pAdapter); goto err_free_netdev; } + +#ifdef WLAN_NS_OFFLOAD + // Workqueue which gets scheduled in IPv6 notification callback. + INIT_WORK(&pAdapter->ipv6NotifierWorkQueue, hdd_ipv6_notifier_work_queue); +#endif //Stop the Interface TX queue. netif_tx_disable(pAdapter->dev); //netif_tx_disable(pWlanDev); @@ -2862,7 +3869,6 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, } } - if( VOS_STATUS_SUCCESS == status ) { //Add it to the hdd's session list. @@ -2916,7 +3922,11 @@ hdd_adapter_t* hdd_open_adapter( hdd_context_t *pHddCtx, tANI_U8 session_type, //If bmps disabled enable it if(VOS_STATUS_SUCCESS == exitbmpsStatus) { - hdd_enable_bmps_imps(pHddCtx); + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); } return NULL; } @@ -2953,7 +3963,11 @@ VOS_STATUS hdd_close_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter, ((pHddCtx->no_of_sessions[VOS_STA_MODE] >= 1) || (pHddCtx->no_of_sessions[VOS_P2P_CLIENT_MODE] >= 1))) { - hdd_enable_bmps_imps(pHddCtx); + if (pHddCtx->hdd_wlan_suspended) + { + hdd_set_pwrparams(pHddCtx); + } + hdd_enable_bmps_imps(pHddCtx); } return VOS_STATUS_SUCCESS; @@ -3051,6 +4065,17 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) { hdd_abort_mac_scan(pHddCtx); } +#ifdef WLAN_NS_OFFLOAD +#ifdef WLAN_OPEN_SOURCE + cancel_work_sync(&pAdapter->ipv6NotifierWorkQueue); +#endif + if (pAdapter->ipv6_notifier_registered) + { + hddLog(LOG1, FL("Unregistered IPv6 notifier")); + unregister_inet6addr_notifier(&pAdapter->ipv6_notifier); + pAdapter->ipv6_notifier_registered = false; + } +#endif if (test_bit(SME_SESSION_OPENED, &pAdapter->event_flags)) { @@ -3060,7 +4085,7 @@ VOS_STATUS hdd_stop_adapter( hdd_context_t *pHddCtx, hdd_adapter_t *pAdapter ) hdd_smeCloseSessionCallback, pAdapter)) { //Block on a completion variable. Can't wait forever though. - wait_for_completion_interruptible_timeout( + wait_for_completion_timeout( &pAdapter->session_close_comp_var, msecs_to_jiffies(WLAN_WAIT_TIME_SESSIONOPENCLOSE)); } @@ -3175,12 +4200,7 @@ VOS_STATUS hdd_reset_all_adapters( hdd_context_t *pHddCtx ) netif_tx_disable(pAdapter->dev); netif_carrier_off(pAdapter->dev); - //Record whether STA is associated - pAdapter->sessionCtx.station.bSendDisconnect = - hdd_connIsConnected( WLAN_HDD_GET_STATION_CTX_PTR( pAdapter )) ? - VOS_TRUE : VOS_FALSE; pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; - hdd_deinit_tx_rx(pAdapter); hdd_wmm_adapter_close(pAdapter); @@ -3199,6 +4219,7 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) VOS_STATUS status; hdd_adapter_t *pAdapter; v_MACADDR_t bcastMac = VOS_MAC_ADDR_BROADCAST_INITIALIZER; + eConnectionState connState; ENTER(); @@ -3213,9 +4234,12 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) case WLAN_HDD_INFRA_STATION: case WLAN_HDD_P2P_CLIENT: case WLAN_HDD_P2P_DEVICE: + + connState = (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState; + hdd_init_station_mode(pAdapter); /* Open the gates for HDD to receive Wext commands */ - pAdapter->isLinkUpSvcNeeded = FALSE; + pAdapter->isLinkUpSvcNeeded = FALSE; pHddCtx->scan_info.mScanPending = FALSE; pHddCtx->scan_info.waitScanResult = FALSE; @@ -3223,20 +4247,31 @@ VOS_STATUS hdd_start_all_adapters( hdd_context_t *pHddCtx ) hdd_wlan_initial_scan(pAdapter); //Indicate disconnect event to supplicant if associated previously - if(pAdapter->sessionCtx.station.bSendDisconnect) + if (eConnectionState_Associated == connState || + eConnectionState_IbssConnected == connState ) { union iwreq_data wrqu; memset(&wrqu, '\0', sizeof(wrqu)); wrqu.ap_addr.sa_family = ARPHRD_ETHER; memset(wrqu.ap_addr.sa_data,'\0',ETH_ALEN); wireless_send_event(pAdapter->dev, SIOCGIWAP, &wrqu, NULL); - pAdapter->sessionCtx.station.bSendDisconnect = VOS_FALSE; pAdapter->sessionCtx.station.hdd_ReassocScenario = VOS_FALSE; /* indicate disconnected event to nl80211 */ cfg80211_disconnected(pAdapter->dev, WLAN_REASON_UNSPECIFIED, NULL, 0, GFP_KERNEL); } + else if (eConnectionState_Connecting == connState) + { + /* + * Indicate connect failure to supplicant if we were in the + * process of connecting + */ + cfg80211_connect_result(pAdapter->dev, NULL, + NULL, 0, NULL, 0, + WLAN_STATUS_ASSOC_DENIED_UNSPEC, + GFP_KERNEL); + } break; case WLAN_HDD_SOFTAP: @@ -3817,7 +4852,7 @@ static void hdd_full_power_callback(void *callbackContext, eHalStatus status) struct fullPowerContext *pContext = callbackContext; hddLog(VOS_TRACE_LEVEL_INFO, - "%s: context = %p, status = %d", pContext, status); + "%s: context = %p, status = %d", __func__, pContext, status); if (NULL == callbackContext) { @@ -3944,6 +4979,21 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) // all scans will be cancelled. hdd_abort_mac_scan( pHddCtx ); + //Stop the traffic monitor timer + if ( VOS_TIMER_STATE_RUNNING == + vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr)) + { + vos_timer_stop(&pHddCtx->tx_rx_trafficTmr); + } + + // Destroy the traffic monitor timer + if (!VOS_IS_STATUS_SUCCESS(vos_timer_destroy( + &pHddCtx->tx_rx_trafficTmr))) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Cannot deallocate Traffic monitor timer", __func__); + } + //Disable IMPS/BMPS as we do not want the device to enter any power //save mode during shutdown sme_DisablePowerSave(pHddCtx->hHal, ePMC_IDLE_MODE_POWER_SAVE); @@ -4024,10 +5074,6 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) vos_chipVoteOffXOBuffer(NULL, NULL, NULL); - //Clean up HDD Nlink Service - send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); - nl_srv_exit(); - //This requires pMac access, Call this before vos_close(). hdd_unregister_mcast_bcast_filter(pHddCtx); @@ -4057,6 +5103,10 @@ void hdd_wlan_exit(hdd_context_t *pHddCtx) if(pHddCtx->cfg_ini->fIsLogpEnabled) vos_watchdog_close(pVosContext); + //Clean up HDD Nlink Service + send_btc_nlink_msg(WLAN_MODULE_DOWN_IND, 0); + nl_srv_exit(); + /* Cancel the vote for XO Core ON. * This is done here to ensure there is no race condition since MC, TX and WD threads have * exited at this point @@ -4184,6 +5234,7 @@ VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx) { eHalStatus halStatus; v_U32_t listenInterval; + tANI_U32 ignoreDtim; // Send ready indication to the HDD. This will kick off the MAC @@ -4191,17 +5242,20 @@ VOS_STATUS hdd_post_voss_start_config(hdd_context_t* pHddCtx) halStatus = sme_HDDReadyInd( pHddCtx->hHal ); if ( !HAL_STATUS_SUCCESS( halStatus ) ) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%S: sme_HDDReadyInd() failed with status " + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: sme_HDDReadyInd() failed with status " "code %08d [x%08x]",__func__, halStatus, halStatus ); return VOS_STATUS_E_FAILURE; } - // Set default LI into HDD context, + // Set default LI and ignoreDtim into HDD context, // otherwise under some race condition, HDD will set 0 LI value into RIVA, // And RIVA will crash wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_LISTEN_INTERVAL, &listenInterval); pHddCtx->hdd_actual_LI_value = listenInterval; - + wlan_cfgGetInt(pHddCtx->hHal, WNI_CFG_IGNORE_DTIM, &ignoreDtim); + pHddCtx->hdd_actual_ignore_DTIM_value = ignoreDtim; + + return VOS_STATUS_SUCCESS; } @@ -4227,7 +5281,7 @@ void hdd_allow_suspend(void) void hdd_allow_suspend_timeout(v_U32_t timeout) { #ifdef WLAN_OPEN_SOURCE - wake_lock_timeout(&wlan_wake_lock, timeout); + wake_lock_timeout(&wlan_wake_lock, msecs_to_jiffies(timeout)); #else /* Do nothing as there is no API in wcnss for timeout*/ #endif @@ -4364,6 +5418,34 @@ void hdd_exchange_version_and_caps(hdd_context_t *pHddCtx) } +/**--------------------------------------------------------------------------- + + \brief hdd_is_5g_supported() - HDD function to know if hardware supports 5GHz + + \param - pHddCtx - Pointer to the hdd context + + \return - true if hardware supports 5GHz + + --------------------------------------------------------------------------*/ +static boolean hdd_is_5g_supported(hdd_context_t * pHddCtx) +{ + /* If wcnss_wlan_iris_xo_mode() returns WCNSS_XO_48MHZ(1); + * then hardware support 5Ghz. + */ + if (WCNSS_XO_48MHZ == wcnss_wlan_iris_xo_mode()) + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware supports 5Ghz", __func__); + return true; + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO, "%s: Hardware doesn't supports 5Ghz", + __func__); + return false; + } +} + + /**--------------------------------------------------------------------------- \brief hdd_wlan_startup() - HDD init function @@ -4437,6 +5519,8 @@ int hdd_wlan_startup(struct device *dev ) init_completion(&pHddCtx->scan_info.scan_req_completion_event); init_completion(&pHddCtx->scan_info.abortscan_event_var); + spin_lock_init(&pHddCtx->schedScan_lock); + hdd_list_init( &pHddCtx->hddAdapters, MAX_NUMBER_OF_ADAPTERS ); // Load all config first as TL config is needed during vos_open @@ -4458,6 +5542,24 @@ int hdd_wlan_startup(struct device *dev ) goto err_config; } + if (false == hdd_is_5g_supported(pHddCtx)) + { + //5Ghz is not supported. + if (1 != pHddCtx->cfg_ini->nBandCapability) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Setting pHddCtx->cfg_ini->nBandCapability = 1", __func__); + pHddCtx->cfg_ini->nBandCapability = 1; + } + } + + /* INI has been read, initialise the configuredMcastBcastFilter with + * INI value as this will serve as the default value + */ + pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; + hddLog(VOS_TRACE_LEVEL_INFO, "Setting configuredMcastBcastFilter: %d", + pHddCtx->cfg_ini->mcastBcastFilterSetting); + /* * cfg80211: Initialization ... */ @@ -4777,6 +5879,15 @@ int hdd_wlan_startup(struct device *dev ) #endif //WLAN_BTAMP_FEATURE +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!(IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE)) + { + hddLog(VOS_TRACE_LEVEL_DEBUG,"%s: ROAM_SCAN_OFFLOAD Feature not supported",__func__); + pHddCtx->cfg_ini->isRoamOffloadScanEnabled = 0; + sme_UpdateRoamScanOffloadEnabled((tHalHandle)(pHddCtx->hHal), + pHddCtx->cfg_ini->isRoamOffloadScanEnabled); + } +#endif #ifdef FEATURE_WLAN_SCAN_PNO /*SME must send channel update configuration to RIVA*/ sme_UpdateChannelConfig(pHddCtx->hHal); @@ -4822,7 +5933,7 @@ int hdd_wlan_startup(struct device *dev ) //Initialize the nlink service if(nl_srv_init() != 0) { - hddLog(VOS_TRACE_LEVEL_FATAL,"%S: nl_srv_init failed",__func__); + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: nl_srv_init failed", __func__); goto err_reg_netdev; } @@ -4877,6 +5988,14 @@ int hdd_wlan_startup(struct device *dev ) // Initialize the restart logic wlan_hdd_restart_init(pHddCtx); + //Register the traffic monitor timer now + if ( pHddCtx->cfg_ini->dynSplitscan) + { + vos_timer_init(&pHddCtx->tx_rx_trafficTmr, + VOS_TIMER_TYPE_SW, + hdd_tx_rx_pkt_cnt_stat_timer_handler, + (void *)pHddCtx); + } goto success; err_nl_srv: @@ -4968,6 +6087,13 @@ static int hdd_driver_init( void) v_CONTEXT_t pVosContext = NULL; struct device *dev = NULL; int ret_status = 0; +#ifdef HAVE_WCNSS_CAL_DOWNLOAD + int max_retries = 0; +#endif + +#ifdef WCONN_TRACE_KMSG_LOG_BUFF + vos_wconn_trace_init(); +#endif ENTER(); @@ -4984,6 +6110,9 @@ static int hdd_driver_init( void) { hddLog(VOS_TRACE_LEVEL_FATAL, "%s: Libra WLAN not Powered Up. " "exiting", __func__); +#ifdef WLAN_OPEN_SOURCE + wake_lock_destroy(&wlan_wake_lock); +#endif return -EIO; } @@ -4994,6 +6123,21 @@ static int hdd_driver_init( void) #endif // ANI_BUS_TYPE_PCI #ifdef ANI_BUS_TYPE_PLATFORM + +#ifdef HAVE_WCNSS_CAL_DOWNLOAD + /* wait until WCNSS driver downloads NV */ + while (!wcnss_device_ready() && 5 >= ++max_retries) { + msleep(1000); + } + if (max_retries >= 5) { + hddLog(VOS_TRACE_LEVEL_FATAL,"%s: WCNSS driver not ready", __func__); +#ifdef WLAN_OPEN_SOURCE + wake_lock_destroy(&wlan_wake_lock); +#endif + return -ENODEV; + } +#endif + dev = wcnss_wlan_get_device(); #endif // ANI_BUS_TYPE_PLATFORM @@ -5079,7 +6223,6 @@ static int hdd_driver_init( void) send_btc_nlink_msg(WLAN_MODULE_UP_IND, 0); pr_info("%s: driver loaded\n", WLAN_MODULE_NAME); - } EXIT(); @@ -5128,6 +6271,7 @@ static void hdd_driver_exit(void) { hdd_context_t *pHddCtx = NULL; v_CONTEXT_t pVosContext = NULL; + int retry = 0; pr_info("%s: unloading driver v%s\n", WLAN_MODULE_NAME, QWLAN_VERSIONSTR); @@ -5149,11 +6293,18 @@ static void hdd_driver_exit(void) } else { - /* module exit should never proceed if SSR is not completed */ - while(isWDresetInProgress()){ - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, "%s:SSR in Progress; block rmmod for 1 second!!!",__func__); + while(pHddCtx->isLogpInProgress) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:SSR in Progress; block rmmod for 1 second!!!", __func__); msleep(1000); - } + + if (retry++ == HDD_MOD_EXIT_SSR_MAX_RETRIES) { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:SSR never completed, fatal error", __func__); + VOS_BUG(0); + } + } + pHddCtx->isLoadUnloadInProgress = TRUE; vos_set_load_unload_in_progress(VOS_MODULE_ID_VOSS, TRUE); @@ -5171,6 +6322,10 @@ static void hdd_driver_exit(void) vos_mem_exit(); #endif +#ifdef WCONN_TRACE_KMSG_LOG_BUFF + vos_wconn_trace_exit(); +#endif + done: #ifdef WLAN_OPEN_SOURCE wake_lock_destroy(&wlan_wake_lock); @@ -5330,7 +6485,7 @@ VOS_STATUS hdd_softap_sta_deauth(hdd_adapter_t *pAdapter, v_U8_t *pDestMacAddres ENTER(); - hddLog( LOGE, "hdd_softap_sta_deauth:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + hddLog( LOGE, "hdd_softap_sta_deauth:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); //Ignore request to deauth bcmc station if( pDestMacAddress[0] & 0x1 ) @@ -5362,7 +6517,7 @@ void hdd_softap_sta_disassoc(hdd_adapter_t *pAdapter,v_U8_t *pDestMacAddress) ENTER(); - hddLog( LOGE, "hdd_softap_sta_disassoc:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + hddLog( LOGE, "hdd_softap_sta_disassoc:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); //Ignore request to disassoc bcmc station if( pDestMacAddress[0] & 0x1 ) @@ -5377,7 +6532,7 @@ void hdd_softap_tkip_mic_fail_counter_measure(hdd_adapter_t *pAdapter,v_BOOL_t e ENTER(); - hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(0x%x, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); + hddLog( LOGE, "hdd_softap_tkip_mic_fail_counter_measure:(%p, false)", (WLAN_HDD_GET_CTX(pAdapter))->pvosContext); WLANSAP_SetCounterMeasure(pVosContext, (v_BOOL_t)enable); } @@ -5699,6 +6854,13 @@ VOS_STATUS wlan_hdd_restart_driver(hdd_context_t *pHddCtx) return status; } +/* + * API to find if there is any STA or P2P-Client is connected + */ +VOS_STATUS hdd_issta_p2p_clientconnected(hdd_context_t *pHddCtx) +{ + return sme_isSta_p2p_clientConnected(pHddCtx->hHal); +} //Register the module init/exit functions module_init(hdd_module_init); diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c index 72cc77dae32..4a902851539 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_p2p.c @@ -57,6 +57,7 @@ #include "sme_Api.h" #include "wlan_hdd_p2p.h" #include "sapApi.h" +#include "wlan_hdd_main.h" #include #include @@ -452,15 +453,18 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy, #endif hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); - int status = 0; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); + int status; hddLog( LOG1, "Cancel remain on channel req"); - if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } /* FIXME cancel currently running remain on chan. * Need to check cookie and cancel accordingly @@ -473,8 +477,8 @@ int wlan_hdd_cfg80211_cancel_remain_on_channel( struct wiphy *wiphy, __func__); return -EINVAL; } - - /* wait until remain on channel ready event received + + /* wait until remain on channel ready event received * for already issued remain on channel request */ status = wait_for_completion_interruptible_timeout(&pAdapter->rem_on_chan_ready_event, msecs_to_jiffies(WAIT_REM_CHAN_READY)); @@ -549,25 +553,27 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, #endif hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR( dev ); hdd_cfg80211_state_t *cfgState = WLAN_HDD_GET_CFG_STATE_PTR( pAdapter ); + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX( pAdapter ); tANI_U16 extendedWait = 0; tANI_U8 type = WLAN_HDD_GET_TYPE_FRM_FC(buf[0]); tANI_U8 subType = WLAN_HDD_GET_SUBTYPE_FRM_FC(buf[0]); tActionFrmType actionFrmType; bool noack = 0; -#ifdef WLAN_FEATURE_11W - tANI_U8 *pTxFrmBuf = (tANI_U8 *) buf; // For SA Query, we have to set protect bit -#endif + int status; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,38)) hdd_adapter_t *goAdapter; #endif - if (((hdd_context_t*)pAdapter->pHddCtx)->isLogpInProgress) + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; } + #ifdef WLAN_FEATURE_P2P_DEBUG if ((type == SIR_MAC_MGMT_FRAME) && (subType == SIR_MAC_MGMT_ACTION) && @@ -788,17 +794,7 @@ int wlan_hdd_action( struct wiphy *wiphy, struct net_device *dev, hddLog(LOG1, "%s: HDD_GO_NEG_REQ_ACK_PENDING \n", __func__); } } -#ifdef WLAN_FEATURE_11W - if ((type == SIR_MAC_MGMT_FRAME) && - (subType == SIR_MAC_MGMT_ACTION) && - (buf[WLAN_HDD_PUBLIC_ACTION_FRAME_OFFSET] == WLAN_HDD_SA_QUERY_ACTION_FRAME)) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: Calling sme_sendAction. For Category %s", __func__, "SA Query"); - // Since this is an SA Query Action Frame, we have to protect it - WLAN_HDD_SET_WEP_FRM_FC(pTxFrmBuf[1]); - } -#endif + if (eHAL_STATUS_SUCCESS != sme_sendAction( WLAN_HDD_GET_HAL_CTX(pAdapter), sessionId, buf, len, extendedWait, noack)) @@ -1246,26 +1242,30 @@ int wlan_hdd_del_virtual_intf( struct wiphy *wiphy, struct net_device *dev ) #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0)) struct net_device *dev = wdev->netdev; #endif - hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); - hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - ENTER(); + hdd_context_t *pHddCtx = (hdd_context_t*) wiphy_priv(wiphy); + hdd_adapter_t *pVirtAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + int status; + ENTER(); - hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", - __func__,pVirtAdapter->device_mode); - if (pHddCtx->isLogpInProgress) - { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EAGAIN; - } + hddLog(VOS_TRACE_LEVEL_INFO, "%s: device_mode = %d", + __func__,pVirtAdapter->device_mode); + + status = wlan_hdd_validate_context(pHddCtx); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: HDD context is not valid", __func__); + return status; + } - wlan_hdd_release_intf_addr( pHddCtx, + wlan_hdd_release_intf_addr( pHddCtx, pVirtAdapter->macAddressCurrent.bytes ); - hdd_stop_adapter( pHddCtx, pVirtAdapter ); - hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE ); - EXIT(); - return 0; + hdd_stop_adapter( pHddCtx, pVirtAdapter ); + hdd_close_adapter( pHddCtx, pVirtAdapter, TRUE ); + EXIT(); + return 0; } void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter, @@ -1332,7 +1332,7 @@ void hdd_sendMgmtFrameOverMonitorIface( hdd_adapter_t *pMonAdapter, skb->ip_summed = CHECKSUM_NONE; #ifdef WLAN_OPEN_SOURCE #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION)); #endif #endif rxstat = netif_rx_ni(skb); @@ -1663,7 +1663,7 @@ static void hdd_wlan_tx_complete( hdd_adapter_t* pAdapter, memset( skb->cb, 0, sizeof( skb->cb ) ); #ifdef WLAN_OPEN_SOURCE #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION)); #endif #endif if (in_interrupt()) diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_scan.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_scan.c index 3f5fbd3257b..7f00efce5f9 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_scan.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_scan.c @@ -740,10 +740,20 @@ int iw_set_scan(struct net_device *dev, struct iw_request_info *info, memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata, pwextBuf->genIE.length ); pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length; - - pwextBuf->roamProfile.pAddIEScan = pHddCtx->scan_info.scanAddIE.addIEdata; - pwextBuf->roamProfile.nAddIEScanLength = pHddCtx->scan_info.scanAddIE.length; - + /* Maximum length of each IE is SIR_MAC_MAX_IE_LENGTH */ + if (SIR_MAC_MAX_IE_LENGTH >= pwextBuf->genIE.length) + { + memcpy( pwextBuf->roamProfile.addIEScan, + pHddCtx->scan_info.scanAddIE.addIEdata, + pHddCtx->scan_info.scanAddIE.length); + pwextBuf->roamProfile.nAddIEScanLength = + pHddCtx->scan_info.scanAddIE.length; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid ScanIE, Length is %d", pwextBuf->genIE.length); + } /* clear previous genIE after use it */ memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) ); } @@ -1121,10 +1131,20 @@ int iw_set_cscan(struct net_device *dev, struct iw_request_info *info, memcpy( pHddCtx->scan_info.scanAddIE.addIEdata, pwextBuf->genIE.addIEdata, pwextBuf->genIE.length ); pHddCtx->scan_info.scanAddIE.length = pwextBuf->genIE.length; - - pwextBuf->roamProfile.pAddIEScan = pHddCtx->scan_info.scanAddIE.addIEdata; - pwextBuf->roamProfile.nAddIEScanLength = pHddCtx->scan_info.scanAddIE.length; - + if (SIR_MAC_MAX_IE_LENGTH >= pwextBuf->genIE.length) + { + memcpy( pwextBuf->roamProfile.addIEScan, + pHddCtx->scan_info.scanAddIE.addIEdata, + pHddCtx->scan_info.scanAddIE.length); + pwextBuf->roamProfile.nAddIEScanLength = + pHddCtx->scan_info.scanAddIE.length; + } + else + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "Invalid ScanIE, Length is %d", + pwextBuf->genIE.length); + } /* clear previous genIE after use it */ memset( &pwextBuf->genIE, 0, sizeof(pwextBuf->genIE) ); } diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c index 98b5a005d03..05349f470f6 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_softap_tx_rx.c @@ -98,6 +98,45 @@ static void hdd_softap_dump_sk_buff(struct sk_buff * skb) skb->data[13], skb->data[14], skb->data[15]); } #endif + +extern void hdd_set_wlan_suspend_mode(bool suspend); + +/**============================================================================ + @brief hdd_softap_traffic_monitor_timeout_handler() - + SAP/P2P GO traffin monitor timeout handler function + If no traffic during programmed time, trigger suspand mode + + @param pUsrData : [in] pointer to hdd context + @return : NONE + ===========================================================================*/ +void hdd_softap_traffic_monitor_timeout_handler( void *pUsrData ) +{ + hdd_context_t *pHddCtx = (hdd_context_t *)pUsrData; + v_TIME_t currentTS; + + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid user data, context", __func__); + return; + } + + currentTS = vos_timer_get_system_time(); + if (pHddCtx->cfg_ini->trafficIdleTimeout < + (currentTS - pHddCtx->traffic_monitor.lastFrameTs)) + { + hdd_set_wlan_suspend_mode(1); + atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 0); + } + else + { + vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer, + pHddCtx->cfg_ini->trafficIdleTimeout); + } + + return; +} + /**============================================================================ @brief hdd_softap_flush_tx_queues() - Utility function to flush the TX queues @@ -217,7 +256,7 @@ int hdd_softap_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) } else if (FALSE == pAdapter->aStaInfo[STAId].isUsed ) { - VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,"%s: STA is unregistered", __func__, STAId); + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN,"%s: STA %d is unregistered", __func__, STAId); ++pAdapter->stats.tx_dropped; ++pAdapter->hdd_stats.hddTxRxStats.txXmitDropped; kfree_skb(skb); @@ -372,7 +411,7 @@ VOS_STATUS hdd_softap_sta_2_sta_xmit(struct sk_buff *skb, if ( FALSE == pAdapter->aStaInfo[STAId].isUsed ) { VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_WARN, - "%s: STA is unregistered", __func__, STAId ); + "%s: STA %d is unregistered", __func__, STAId ); kfree_skb(skb); status = VOS_STATUS_E_FAILURE; goto xmit_end; @@ -521,6 +560,9 @@ VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter ) HDD_SOFTAP_VI_WEIGHT_DEFAULT, HDD_SOFTAP_VO_WEIGHT_DEFAULT }; + + hdd_context_t *pHddCtx = NULL; + pAdapter->isVosOutOfResource = VOS_FALSE; vos_mem_zero(&pAdapter->stats, sizeof(struct net_device_stats)); @@ -550,6 +592,31 @@ VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter ) /* Update the AC weights suitable for SoftAP mode of operation */ WLANTL_SetACWeights((WLAN_HDD_GET_CTX(pAdapter))->pvosContext, pACWeights); + /* Initialize SAP/P2P-GO traffin monitor */ + pHddCtx = (hdd_context_t *)pAdapter->pHddCtx; + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HDD cntxt", __func__ ); + return VOS_STATUS_E_INVAL; + } + if ((pHddCtx->cfg_ini->enableTrafficMonitor) && + (!pHddCtx->traffic_monitor.isInitialized)) + { + atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1); + vos_timer_init(&pHddCtx->traffic_monitor.trafficTimer, + VOS_TIMER_TYPE_SW, + hdd_softap_traffic_monitor_timeout_handler, + pHddCtx); + vos_lock_init(&pHddCtx->traffic_monitor.trafficLock); + pHddCtx->traffic_monitor.isInitialized = 1; + pHddCtx->traffic_monitor.lastFrameTs = 0; + /* Start traffic monitor timer here + * If no AP assoc, immediatly go into suspend */ + vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer, + pHddCtx->cfg_ini->trafficIdleTimeout); + } + return status; } @@ -564,6 +631,26 @@ VOS_STATUS hdd_softap_init_tx_rx( hdd_adapter_t *pAdapter ) VOS_STATUS hdd_softap_deinit_tx_rx( hdd_adapter_t *pAdapter ) { VOS_STATUS status = VOS_STATUS_SUCCESS; + hdd_context_t *pHddCtx = NULL; + + pHddCtx = (hdd_context_t *)pAdapter->pHddCtx; + if (NULL == pHddCtx) + { + VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid HDD cntxt", __func__ ); + return VOS_STATUS_E_INVAL; + } + if (pHddCtx->traffic_monitor.isInitialized) + { + if (VOS_TIMER_STATE_STOPPED != + vos_timer_getCurrentState(&pHddCtx->traffic_monitor.trafficTimer)) + { + vos_timer_stop(&pHddCtx->traffic_monitor.trafficTimer); + } + vos_timer_destroy(&pHddCtx->traffic_monitor.trafficTimer); + vos_lock_destroy(&pHddCtx->traffic_monitor.trafficLock); + pHddCtx->traffic_monitor.isInitialized = 0; + } status = hdd_softap_flush_tx_queues(pAdapter); @@ -853,6 +940,26 @@ VOS_STATUS hdd_softap_tx_fetch_packet_cbk( v_VOID_t *vosContext, return VOS_STATUS_E_FAILURE; } + /* Monitor traffic */ + if ( pHddCtx->cfg_ini->enableTrafficMonitor ) + { + pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time(); + if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) ) + { + vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock); + /* It was IDLE mode, + * this is new state, then switch mode from suspend to resume */ + if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) ) + { + hdd_set_wlan_suspend_mode(0); + vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer, + pHddCtx->cfg_ini->trafficIdleTimeout); + atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1); + } + vos_lock_release(&pHddCtx->traffic_monitor.trafficLock); + } + } + ++pAdapter->hdd_stats.hddTxRxStats.txFetched; STAId = *pStaId; @@ -1148,7 +1255,27 @@ VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext, VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } - + + /* Monitor traffic */ + if ( pHddCtx->cfg_ini->enableTrafficMonitor ) + { + pHddCtx->traffic_monitor.lastFrameTs = vos_timer_get_system_time(); + if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) ) + { + vos_lock_acquire(&pHddCtx->traffic_monitor.trafficLock); + /* It was IDLE mode, + * this is new state, then switch mode from suspend to resume */ + if ( !atomic_read(&pHddCtx->traffic_monitor.isActiveMode) ) + { + hdd_set_wlan_suspend_mode(0); + vos_timer_start(&pHddCtx->traffic_monitor.trafficTimer, + pHddCtx->cfg_ini->trafficIdleTimeout); + atomic_set(&pHddCtx->traffic_monitor.isActiveMode, 1); + } + vos_lock_release(&pHddCtx->traffic_monitor.trafficLock); + } + } + ++pAdapter->hdd_stats.hddTxRxStats.rxChains; // walk the chain until all are processed @@ -1225,13 +1352,14 @@ VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext, skb->ip_summed = CHECKSUM_NONE; #ifdef WLAN_OPEN_SOURCE #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION)); #endif #endif rxstat = netif_rx_ni(skb); if (NET_RX_SUCCESS == rxstat) { ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered; + ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count; } else { @@ -1269,11 +1397,25 @@ VOS_STATUS hdd_softap_rx_packet_cbk( v_VOID_t *vosContext, VOS_STATUS hdd_softap_DeregisterSTA( hdd_adapter_t *pAdapter, tANI_U8 staId ) { VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; - hdd_context_t *pHddCtx = pAdapter->pHddCtx; + hdd_context_t *pHddCtx; + if (NULL == pAdapter) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: pAdapter is NULL", __func__); + return VOS_STATUS_E_INVAL; + } + + if (WLAN_HDD_ADAPTER_MAGIC != pAdapter->magic) + { + VOS_TRACE(VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pAdapter magic", __func__); + return VOS_STATUS_E_INVAL; + } + pHddCtx = (hdd_context_t*)(pAdapter->pHddCtx); //Clear station in TL and then update HDD data structures. This helps //to block RX frames from other station to this station. - vosStatus = WLANTL_ClearSTAClient( (WLAN_HDD_GET_CTX(pAdapter))->pvosContext, staId ); + vosStatus = WLANTL_ClearSTAClient( pHddCtx->pvosContext, staId ); if ( !VOS_IS_STATUS_SUCCESS( vosStatus ) ) { VOS_TRACE( VOS_MODULE_ID_HDD_SOFTAP, VOS_TRACE_LEVEL_ERROR, @@ -1402,6 +1544,15 @@ VOS_STATUS hdd_softap_RegisterSTA( hdd_adapter_t *pAdapter, return vosStatus; } + //Timer value should be in milliseconds + if ( pHddCtx->cfg_ini->dynSplitscan && + ( VOS_TIMER_STATE_RUNNING != + vos_timer_getCurrentState(&pHddCtx->tx_rx_trafficTmr))) + { + vos_timer_start(&pHddCtx->tx_rx_trafficTmr, + pHddCtx->cfg_ini->trafficMntrTmrForSplitScan); + } + // if ( WPA ), tell TL to go to 'connected' and after keys come to the driver, // then go to 'authenticated'. For all other authentication types (those that do // not require upper layer authentication) we can put TL directly into 'authenticated' diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c index 676666abd16..189f4b99ca0 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tdls.c @@ -25,6 +25,8 @@ \brief WLAN Host Device Driver implementation for TDLS + Copyright (c) 2013 Qualcomm Atheros, Inc. All Rights Reserved. + Qualcomm Atheros Confidential and Proprietary. ========================================================================*/ #include @@ -43,6 +45,10 @@ static struct mutex tdls_lock; static tANI_S32 wlan_hdd_get_tdls_discovery_peer_cnt(tdlsCtx_t *pHddTdlsCtx); static tANI_S32 wlan_hdd_tdls_peer_reset_discovery_processed(tdlsCtx_t *pHddTdlsCtx); static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx); +int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac); +#ifdef CONFIG_TDLS_IMPLICIT +static void wlan_hdd_tdls_pre_setup(struct work_struct *work); +#endif #ifndef WLAN_FEATURE_TDLS_DEBUG #define TDLS_LOG_LEVEL VOS_TRACE_LEVEL_INFO @@ -61,6 +67,21 @@ static u8 wlan_hdd_tdls_hash_key (u8 *mac) return key; } +#ifdef CONFIG_TDLS_IMPLICIT +static void wlan_hdd_tdls_pre_setup_init_work(tdlsCtx_t * pHddTdlsCtx, + hddTdlsPeer_t *curr_candidate) +{ + if (TDLS_CTX_MAGIC != pHddTdlsCtx->magic) + { + pHddTdlsCtx->curr_candidate = curr_candidate; + pHddTdlsCtx->magic = TDLS_CTX_MAGIC; + + INIT_WORK(&pHddTdlsCtx->implicit_setup, wlan_hdd_tdls_pre_setup); + schedule_work(&pHddTdlsCtx->implicit_setup); + } +} +#endif + static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tdlsCtx_t *pHddTdlsCtx, tANI_BOOLEAN mutexLock, v_U32_t discoveryExpiry) @@ -105,6 +126,7 @@ static v_VOID_t wlan_hdd_tdls_start_peer_discover_timer(tdlsCtx_t *pHddTdlsCtx, return; } +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData ) { int i; @@ -227,6 +249,7 @@ static v_VOID_t wlan_hdd_tdls_discover_peer_cb( v_PVOID_t userData ) mutex_unlock(&tdls_lock); return; } +#endif static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) { @@ -235,6 +258,7 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) struct list_head *pos; hddTdlsPeer_t *curr_peer; tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx; if (mutex_lock_interruptible(&tdls_lock)) { @@ -255,6 +279,14 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) return; } + pHddCtx = WLAN_HDD_GET_CTX( pHddTdlsCtx->pAdapter ); + + if (NULL == pHddCtx) + { + mutex_unlock(&tdls_lock); + return; + } + for (i = 0; i < 256; i++) { head = &pHddTdlsCtx->peer_list[i]; @@ -262,16 +294,24 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) curr_peer = list_entry (pos, hddTdlsPeer_t, node); VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "hdd update cb " MAC_ADDRESS_STR " link_status %d" - " tdls_support %d", MAC_ADDR_ARRAY(curr_peer->peerMac), + "%s: " MAC_ADDRESS_STR " link_status %d" + " tdls_support %d", __func__, MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status, curr_peer->tdls_support); + if (pHddCtx->cfg_ini->fTDLSExternalControl && + (0 == wpa_tdls_is_allowed_force_peer (pHddTdlsCtx, curr_peer->peerMac))) { + continue; + } if (eTDLS_CAP_SUPPORTED == curr_peer->tdls_support) { VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "%s: (tx %d, rx %d, config %d) " MAC_ADDRESS_STR " (%d) ", - __func__, curr_peer->tx_pkt, curr_peer->rx_pkt, + "tx %d, rx %d (thr.pkt %d/idle %d), rssi %d (thr.trig %d/hys %d/tear %d)", + curr_peer->tx_pkt, curr_peer->rx_pkt, pHddTdlsCtx->threshold_config.tx_packet_n, - MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->link_status); + pHddTdlsCtx->threshold_config.idle_packet_n, + curr_peer->rssi, + pHddTdlsCtx->threshold_config.rssi_trigger_threshold, + pHddTdlsCtx->threshold_config.rssi_hysteresis, + pHddTdlsCtx->threshold_config.rssi_teardown_threshold); if ((eTDLS_LINK_IDLE == curr_peer->link_status) || (eTDLS_LINK_DISCOVERING == curr_peer->link_status)){ @@ -283,7 +323,7 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Tput trigger TDLS pre-setup"); #ifdef CONFIG_TDLS_IMPLICIT - wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer); + wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer); #endif } else @@ -294,7 +334,8 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) } goto next_peer; } - } else { + } + else if (eTDLS_LINK_CONNECTED == curr_peer->link_status) { if ((tANI_S32)curr_peer->rssi < (tANI_S32)pHddTdlsCtx->threshold_config.rssi_teardown_threshold) { @@ -310,10 +351,15 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) goto next_peer; } - if ((curr_peer->tx_pkt < + /* Only teardown based on non zero idle packet threshold, to address a use + * case where this threshold does not get consider for TEAR DOWN. + */ + + if (( 0 != pHddTdlsCtx->threshold_config.idle_packet_n ) && + ((curr_peer->tx_pkt < pHddTdlsCtx->threshold_config.idle_packet_n) && (curr_peer->rx_pkt < - pHddTdlsCtx->threshold_config.idle_packet_n)) { + pHddTdlsCtx->threshold_config.idle_packet_n))) { if (VOS_TIMER_STATE_RUNNING != vos_timer_getCurrentState(&curr_peer->peerIdleTimer)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, @@ -353,7 +399,9 @@ static v_VOID_t wlan_hdd_tdls_update_peer_cb( v_PVOID_t userData ) if (curr_peer->discovery_attempt++ < pHddTdlsCtx->threshold_config.discovery_tries_n) { VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "TDLS UNKNOWN discover "); - wlan_hdd_tdls_pre_setup(pHddTdlsCtx, curr_peer); +#ifdef CONFIG_TDLS_IMPLICIT + wlan_hdd_tdls_pre_setup_init_work(pHddTdlsCtx, curr_peer); +#endif } else { @@ -381,10 +429,20 @@ static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData ) #ifdef CONFIG_TDLS_IMPLICIT hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData; - VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "%s: Tx/Rx Idle " MAC_ADDRESS_STR " trigger teardown", - __func__, - MAC_ADDR_ARRAY(curr_peer->peerMac)); + if (NULL == curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid tdls idle timer expired", __func__); + return; + } + + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: Tx/Rx Idle " MAC_ADDRESS_STR " tx_pkt: %d, rx_pkt: %d, idle_packet_n: %d\n", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac), + curr_peer->tx_pkt, + curr_peer->rx_pkt, + curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n); + if (mutex_lock_interruptible(&tdls_lock)) { VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, @@ -392,9 +450,27 @@ static v_VOID_t wlan_hdd_tdls_idle_cb( v_PVOID_t userData ) return; } - wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, - curr_peer, - eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + /* Check tx/rx statistics on this tdls link for recent activities and + * then decide whether to tear down the link or keep it. + */ + if ((curr_peer->tx_pkt >= curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n) || (curr_peer->rx_pkt >= curr_peer->pHddTdlsCtx->threshold_config.idle_packet_n)) + { + /* this tdls link got back to normal, so keep it */ + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: tdls link to " MAC_ADDRESS_STR " back to normal, will stay", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + } + else + { + /* this tdls link needs to get torn down */ + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: trigger tdls link to " MAC_ADDRESS_STR " down", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + + wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, + curr_peer, + eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + } mutex_unlock(&tdls_lock); #endif } @@ -445,6 +521,23 @@ static v_VOID_t wlan_hdd_tdls_discovery_timeout_peer_cb(v_PVOID_t userData) return; } +static v_VOID_t wlan_hdd_tdls_initiator_wait_cb( v_PVOID_t userData ) +{ + hddTdlsPeer_t *curr_peer = (hddTdlsPeer_t *)userData; + tdlsCtx_t *pHddTdlsCtx; + + if ( NULL == curr_peer ) + return; + + pHddTdlsCtx = curr_peer->pHddTdlsCtx; + + if ( NULL == pHddTdlsCtx ) + return; + + WLANTL_ResumeDataTx( (WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter))->pvosContext, + (v_U8_t *)&curr_peer->staId); +} + static void wlan_hdd_tdls_free_list(tdlsCtx_t *pHddTdlsCtx) { int i; @@ -484,22 +577,65 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) sme_IsFeatureSupportedByFW(TDLS)); return 0; } + /* TDLS is supported only in STA / P2P Client modes, + * hence the check for TDLS support in a specific Device mode. + * Do not return a failure rather do not continue further + * with the initialization as tdls_init would be called + * during the open adapter for a p2p interface at which point + * the device mode would be a P2P_DEVICE. The point here is to + * continue initialization for STA / P2P Client modes. + * TDLS exit also check for the device mode for clean up hence + * there is no issue even if success is returned. + */ + if (0 == WLAN_HDD_IS_TDLS_SUPPORTED_ADAPTER(pAdapter)) + { + return 0; + } + /* Check for the valid pHddTdlsCtx. If valid do not further + * allocate the memory, rather continue with the initialization. + * If tdls_initialization would get reinvoked without tdls_exit + * getting invoked (SSR) there is no point to further proceed + * with the memory allocations. + */ + if (NULL == pAdapter->sessionCtx.station.pHddTdlsCtx) + { + pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t)); - pHddTdlsCtx = vos_mem_malloc(sizeof(tdlsCtx_t)); + if (NULL == pHddTdlsCtx) { + hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__); + pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; + return -1; + } + /* initialize TDLS pAdater context */ + vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t)); +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER + vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_discover_peer_cb, + pHddTdlsCtx); +#endif - if (NULL == pHddTdlsCtx) { - hddLog(VOS_TRACE_LEVEL_ERROR, "%s malloc failed!", __func__); - pAdapter->sessionCtx.station.pHddTdlsCtx = NULL; - return -1; + vos_timer_init(&pHddTdlsCtx->peerUpdateTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_update_peer_cb, + pHddTdlsCtx); + vos_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_discovery_timeout_peer_cb, + pHddTdlsCtx); + + pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx; } - pAdapter->sessionCtx.station.pHddTdlsCtx = pHddTdlsCtx; + pHddTdlsCtx = pAdapter->sessionCtx.station.pHddTdlsCtx; /* initialize TDLS global context */ pHddCtx->connected_peer_count = 0; sme_SetTdlsPowerSaveProhibited(WLAN_HDD_GET_HAL_CTX(pAdapter), 0); pHddCtx->tdls_scan_ctxt.magic = 0; + pHddCtx->tdls_scan_ctxt.attempt = 0; + pHddCtx->tdls_scan_ctxt.reject = 0; pHddCtx->tdls_scan_ctxt.scan_request = NULL; for (staIdx = 0; staIdx < HDD_MAX_NUM_TDLS_STA; staIdx++) @@ -510,9 +646,6 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) sizeof(v_MACADDR_t)) ; } - /* initialize TDLS pAdater context */ - vos_mem_zero(pHddTdlsCtx, sizeof(tdlsCtx_t)); - pHddTdlsCtx->pAdapter = pAdapter; for (i = 0; i < 256; i++) @@ -520,19 +653,8 @@ int wlan_hdd_tdls_init(hdd_adapter_t *pAdapter) INIT_LIST_HEAD(&pHddTdlsCtx->peer_list[i]); } - vos_timer_init(&pHddTdlsCtx->peerDiscoverTimer, - VOS_TIMER_TYPE_SW, - wlan_hdd_tdls_discover_peer_cb, - pHddTdlsCtx); - - vos_timer_init(&pHddTdlsCtx->peerUpdateTimer, - VOS_TIMER_TYPE_SW, - wlan_hdd_tdls_update_peer_cb, - pHddTdlsCtx); - vos_timer_init(&pHddTdlsCtx->peerDiscoveryTimeoutTimer, - VOS_TIMER_TYPE_SW, - wlan_hdd_tdls_discovery_timeout_peer_cb, - pHddTdlsCtx); + pHddTdlsCtx->curr_candidate = NULL; + pHddTdlsCtx->magic = 0; /* remember configuration even if it is not used right now. it could be used later */ pHddTdlsCtx->threshold_config.tx_period_t = pHddCtx->cfg_ini->fTDLSTxStatsPeriod; @@ -605,7 +727,9 @@ static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx) struct list_head *pos; hddTdlsPeer_t *curr_peer; +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer); +#endif vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer); vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); @@ -621,6 +745,7 @@ static void wlan_hdd_tdls_timers_stop(tdlsCtx_t *pHddTdlsCtx) __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); vos_timer_stop ( &curr_peer->peerIdleTimer ); + vos_timer_stop( &curr_peer->initiatorWaitTimeoutTimer ); } } } @@ -633,8 +758,10 @@ static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx) struct list_head *pos; hddTdlsPeer_t *curr_peer; +#ifdef TDLS_USE_SEPARATE_DISCOVERY_TIMER vos_timer_stop(&pHddTdlsCtx->peerDiscoverTimer); vos_timer_destroy(&pHddTdlsCtx->peerDiscoverTimer); +#endif vos_timer_stop(&pHddTdlsCtx->peerUpdateTimer); vos_timer_destroy(&pHddTdlsCtx->peerUpdateTimer); vos_timer_stop(&pHddTdlsCtx->peerDiscoveryTimeoutTimer); @@ -653,6 +780,8 @@ static void wlan_hdd_tdls_timers_destroy(tdlsCtx_t *pHddTdlsCtx) MAC_ADDR_ARRAY(curr_peer->peerMac)); vos_timer_stop ( &curr_peer->peerIdleTimer ); vos_timer_destroy ( &curr_peer->peerIdleTimer ); + vos_timer_stop(&curr_peer->initiatorWaitTimeoutTimer); + vos_timer_destroy(&curr_peer->initiatorWaitTimeoutTimer); } } } @@ -710,6 +839,11 @@ hddTdlsPeer_t *wlan_hdd_tdls_get_peer(hdd_adapter_t *pAdapter, u8 *mac) wlan_hdd_tdls_idle_cb, peer); + vos_timer_init(&peer->initiatorWaitTimeoutTimer, + VOS_TIMER_TYPE_SW, + wlan_hdd_tdls_initiator_wait_cb, + peer); + list_add_tail(&peer->node, head); mutex_unlock(&tdls_lock); @@ -797,7 +931,7 @@ int wlan_hdd_tdls_recv_discovery_resp(hdd_adapter_t *pAdapter, u8 *mac) } else { - VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "Rssi Threshold not met: "MAC_ADDRESS_STR" rssi = %d threshold = %d ", MAC_ADDR_ARRAY(curr_peer->peerMac), curr_peer->rssi, pHddTdlsCtx->threshold_config.rssi_trigger_threshold); @@ -1030,6 +1164,137 @@ int wlan_hdd_tdls_set_sta_id(hdd_adapter_t *pAdapter, u8 *mac, u8 staId) return 0; } +int wpa_tdls_is_allowed_force_peer(tdlsCtx_t *pHddTdlsCtx, u8 *mac) +{ + int i; + for (i=0; iforcePeerCnt; i++) + { + if (!memcmp(mac, pHddTdlsCtx->forcePeer[i].macAddr, 6)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: " MAC_ADDRESS_STR "is a forced peer", + __func__,MAC_ADDR_ARRAY(mac)); + return 1; + } + } + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: " MAC_ADDRESS_STR "is not a forced peer", + __func__,MAC_ADDR_ARRAY(mac)); + return 0; +} + +int wlan_hdd_tdls_remove_force_peer(hdd_adapter_t *pAdapter, u8 *mac) +{ + int i; + tdlsCtx_t *pHddTdlsCtx; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if ((NULL == pHddCtx)) return -1; + + if (mutex_lock_interruptible(&tdls_lock)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return -1; + } + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) + { + mutex_unlock(&tdls_lock); + return -1; + } + + for (i=0; iforcePeer[i].macAddr, 6)) + { + /* + * Entry Already Exists,Clear the entry and return. + */ + memset(pHddTdlsCtx->forcePeer[i].macAddr, 0, 6); + pHddTdlsCtx->forcePeerCnt--; + mutex_unlock(&tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Removed the requested foce peer", __func__); + return 0; + } + } + + /* Should not have come here if the existing entry has to be removed */ + mutex_unlock(&tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: Failed to remove the requested force peer: No Entry Found ", __func__); + return -1; +} + +int wlan_hdd_tdls_add_force_peer(hdd_adapter_t *pAdapter, u8 *mac) +{ + int i =0; + tdlsCtx_t *pHddTdlsCtx; + tANI_U8 zeroMac[6] = {0}; + hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + if ((NULL == pHddCtx)) return -1; + + if (mutex_lock_interruptible(&tdls_lock)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + "%s: unable to lock list", __func__); + return -1; + } + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL == pHddTdlsCtx) + { + mutex_unlock(&tdls_lock); + return -1; + } + + if (pHddTdlsCtx->forcePeerCnt >= HDD_MAX_NUM_TDLS_STA ) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Fail to add the requested foce peer : Quota Full" + " forcePeerCnt is %d ", __func__,pHddTdlsCtx->forcePeerCnt); + /* Quota Full, hence return failure from here*/ + goto error; + } + + for (i=0; iforcePeer[i].macAddr, 6)) + { + /* + * Entry Already Exists,No need to create a new one. + * Hence return from here. + */ + mutex_unlock(&tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Add the requested foce peer success : Entry present" + " forcePeerCnt is %d ", __func__, + pHddTdlsCtx->forcePeerCnt); + return 0; + } + } + for (i=0; iforcePeer[i].macAddr, zeroMac, 6) ) + { + memcpy(pHddTdlsCtx->forcePeer[i].macAddr, mac, 6); + pHddTdlsCtx->forcePeerCnt++; + mutex_unlock(&tdls_lock); + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, + "%s: Add the requested foce peer success at index i" + " forcePeerCnt is %d ", __func__, i, + pHddTdlsCtx->forcePeerCnt); + return 0; + } + } +error: + mutex_unlock(&tdls_lock); + return -1; +} + /* if peerMac is found, then it returns pointer to hddTdlsPeer_t otherwise, it returns NULL */ @@ -1073,6 +1338,33 @@ hddTdlsPeer_t *wlan_hdd_tdls_find_peer(hdd_adapter_t *pAdapter, u8 *mac) return NULL; } +hddTdlsPeer_t *wlan_hdd_tdls_find_all_peer(hdd_context_t *pHddCtx, u8 *mac) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + tdlsCtx_t *pHddTdlsCtx = NULL; + hddTdlsPeer_t *curr_peer= NULL; + VOS_STATUS status = 0; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) + { + curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac); + if (curr_peer) + return curr_peer; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + return curr_peer; +} + + int wlan_hdd_tdls_reset_peer(hdd_adapter_t *pAdapter, u8 *mac) { hdd_context_t *pHddCtx; @@ -1331,9 +1623,19 @@ void wlan_hdd_tdls_check_bmps(hdd_adapter_t *pAdapter) { hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); tdlsCtx_t *pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + hddTdlsPeer_t *curr_peer; if ((NULL == pHddCtx) || (NULL == pHddTdlsCtx)) return; + curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE); + if (NULL != curr_peer) + { + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: tdls in progress. Dont check for BMPS " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY (curr_peer->peerMac)); + return; + } + if ((TDLS_CTX_MAGIC != pHddCtx->tdls_scan_ctxt.magic) && (0 == pHddCtx->connected_peer_count) && (0 == pHddTdlsCtx->discovery_sent_cnt)) @@ -1369,12 +1671,12 @@ u8 wlan_hdd_tdls_is_peer_progress(hdd_adapter_t *pAdapter, u8 *mac) return (eTDLS_LINK_CONNECTING == curr_peer->link_status); } -/* return TRUE if TDLS is ongoing +/* return pointer to hddTdlsPeer_t if TDLS is ongoing. Otherwise return NULL. * mac - if NULL check for all the peer list, otherwise, skip this mac when skip_self is TRUE * skip_self - if TRUE, skip this mac. otherwise, check all the peer list. if mac is NULL, this argument is ignored, and check for all the peer list. */ -u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self) +static hddTdlsPeer_t *wlan_hdd_tdls_find_progress_peer(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self, tANI_BOOLEAN mutexLock) { int i; struct list_head *head; @@ -1382,17 +1684,21 @@ u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self) struct list_head *pos; tdlsCtx_t *pHddTdlsCtx; - if (mutex_lock_interruptible(&tdls_lock)) + if (mutexLock) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, + if (mutex_lock_interruptible(&tdls_lock)) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: unable to lock list", __func__); - return FALSE; + return NULL; + } } pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); if (NULL == pHddTdlsCtx) { - mutex_unlock(&tdls_lock); - return FALSE; + if (mutexLock) + mutex_unlock(&tdls_lock); + return NULL; } for (i = 0; i < 256; i++) { @@ -1409,15 +1715,43 @@ u8 wlan_hdd_tdls_is_progress(hdd_adapter_t *pAdapter, u8 *mac, u8 skip_self) VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s:" MAC_ADDRESS_STR " eTDLS_LINK_CONNECTING", __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); - mutex_unlock(&tdls_lock); - return TRUE; + if (mutexLock) + mutex_unlock(&tdls_lock); + return curr_peer; } } } } - mutex_unlock(&tdls_lock); - return FALSE; + if (mutexLock) + mutex_unlock(&tdls_lock); + return NULL; +} + +hddTdlsPeer_t *wlan_hdd_tdls_is_progress(hdd_context_t *pHddCtx, u8 *mac, u8 skip_self, tANI_BOOLEAN mutexLock) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + tdlsCtx_t *pHddTdlsCtx = NULL; + hddTdlsPeer_t *curr_peer= NULL; + VOS_STATUS status = 0; + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) + { + curr_peer = wlan_hdd_tdls_find_progress_peer(pAdapter, mac, skip_self, mutexLock); + if (curr_peer) + return curr_peer; + } + status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); + pAdapterNode = pNext; + } + return NULL; } static void wlan_hdd_tdls_implicit_disable(tdlsCtx_t *pHddTdlsCtx) @@ -1479,18 +1813,14 @@ void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) { pAdapter = pAdapterNode->pAdapter; - if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) { - pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); - if (NULL != pHddTdlsCtx) - { - if(eTDLS_SUPPORT_ENABLED == tdls_mode) - wlan_hdd_tdls_implicit_enable(pHddTdlsCtx); - else if((eTDLS_SUPPORT_DISABLED == tdls_mode) || - (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode)) - wlan_hdd_tdls_implicit_disable(pHddTdlsCtx); - } + if(eTDLS_SUPPORT_ENABLED == tdls_mode) + wlan_hdd_tdls_implicit_enable(pHddTdlsCtx); + else if((eTDLS_SUPPORT_DISABLED == tdls_mode) || + (eTDLS_SUPPORT_EXPLICIT_TRIGGER_ONLY == tdls_mode)) + wlan_hdd_tdls_implicit_disable(pHddTdlsCtx); } status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); pAdapterNode = pNext; @@ -1508,10 +1838,30 @@ void wlan_hdd_tdls_set_mode(hdd_context_t *pHddCtx, mutex_unlock(&tdls_lock); } -void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, - hddTdlsPeer_t *curr_peer) +static void wlan_hdd_tdls_pre_setup(struct work_struct *work) { - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); + tdlsCtx_t *pHddTdlsCtx = + container_of(work, tdlsCtx_t, implicit_setup); + hdd_context_t *pHddCtx; + hddTdlsPeer_t *curr_peer; + hddTdlsPeer_t *temp_peer; + int status; + + if (NULL == pHddTdlsCtx) + return; + + if (unlikely(TDLS_CTX_MAGIC != pHddTdlsCtx->magic)) + return; + + pHddCtx = WLAN_HDD_GET_CTX(pHddTdlsCtx->pAdapter); + + if (NULL == pHddCtx) + return; + + curr_peer = pHddTdlsCtx->curr_candidate; + + if (NULL == curr_peer) + return; if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter))) { @@ -1519,14 +1869,30 @@ void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, hdd_disable_bmps_imps(pHddCtx, WLAN_HDD_INFRA_STATION); } + temp_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, FALSE); + if (NULL != temp_peer) + { + VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " ongoing. pre_setup ignored\n", + __func__, MAC_ADDR_ARRAY(temp_peer->peerMac)); + goto done; + } + if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) curr_peer->link_status = eTDLS_LINK_DISCOVERING; - sme_SendTdlsMgmtFrame(WLAN_HDD_GET_HAL_CTX(pHddTdlsCtx->pAdapter), - pHddTdlsCtx->pAdapter->sessionId, - curr_peer->peerMac, - WLAN_TDLS_DISCOVERY_REQUEST, - 1, 0, NULL, 0, 0); + status = wlan_hdd_cfg80211_send_tdls_discover_req(pHddTdlsCtx->pAdapter->wdev.wiphy, + pHddTdlsCtx->pAdapter->dev, + curr_peer->peerMac); + + if (0 != status) + { + VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: " MAC_ADDRESS_STR " discovery could not sent\n", + __func__, MAC_ADDR_ARRAY(curr_peer->peerMac)); + if (eTDLS_CAP_UNKNOWN != curr_peer->tdls_support) + curr_peer->link_status = eTDLS_LINK_IDLE; + goto done; + } + pHddTdlsCtx->discovery_sent_cnt++; wlan_hdd_tdls_check_power_save_prohibited(pHddTdlsCtx->pAdapter); VOS_TRACE( VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, "%s: discovery count %lu timeout %lu msec", @@ -1537,6 +1903,9 @@ void wlan_hdd_tdls_pre_setup(tdlsCtx_t *pHddTdlsCtx, &pHddTdlsCtx->peerDiscoveryTimeoutTimer, pHddTdlsCtx->threshold_config.tx_period_t - TDLS_DISCOVERY_TIMEOUT_BEFORE_UPDATE); +done: + pHddTdlsCtx->curr_candidate = NULL; + pHddTdlsCtx->magic = 0; return; } @@ -1553,14 +1922,10 @@ tANI_U32 wlan_hdd_tdls_discovery_sent_cnt(hdd_context_t *pHddCtx) { pAdapter = pAdapterNode->pAdapter; - if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || - (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); + if (NULL != pHddTdlsCtx) { - pHddTdlsCtx = WLAN_HDD_GET_TDLS_CTX_PTR(pAdapter); - if (NULL != pHddTdlsCtx) - { - count = count + pHddTdlsCtx->discovery_sent_cnt; - } + count = count + pHddTdlsCtx->discovery_sent_cnt; } status = hdd_get_next_adapter ( pHddCtx, pAdapterNode, &pNext ); pAdapterNode = pNext; @@ -1592,6 +1957,7 @@ void wlan_hdd_tdls_free_scan_request (tdls_scan_context_t *tdls_scan_ctx) return; tdls_scan_ctx->attempt = 0; + tdls_scan_ctx->reject = 0; tdls_scan_ctx->magic = 0; tdls_scan_ctx->scan_request = NULL; return; @@ -1679,6 +2045,7 @@ int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, #endif hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); u16 connectedTdlsPeers; + hddTdlsPeer_t *curr_peer; unsigned long delay; if (NULL == pHddCtx) @@ -1688,11 +2055,22 @@ int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, if (eTDLS_SUPPORT_NOT_ENABLED == pHddCtx->tdls_mode) return 1; - if (wlan_hdd_tdls_is_progress(pAdapter, NULL, 0)) + curr_peer = wlan_hdd_tdls_is_progress(pHddCtx, NULL, 0, TRUE); + if (NULL != curr_peer) { + if (pHddCtx->tdls_scan_ctxt.reject++ >= TDLS_MAX_SCAN_REJECT) + { + pHddCtx->tdls_scan_ctxt.reject = 0; + VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, + "%s: " MAC_ADDRESS_STR ". scan rejected %d. force it to idle", + __func__, MAC_ADDR_ARRAY (curr_peer->peerMac), pHddCtx->tdls_scan_ctxt.reject); + + wlan_hdd_tdls_set_peer_link_status (curr_peer, eTDLS_LINK_IDLE); + return 1; + } VOS_TRACE(VOS_MODULE_ID_HDD, TDLS_LOG_LEVEL, - "%s: tdls in progress. scan rejected", - __func__); + "%s: tdls in progress. scan rejected %d", + __func__, pHddCtx->tdls_scan_ctxt.reject); return -EBUSY; } @@ -1743,8 +2121,9 @@ int wlan_hdd_tdls_scan_callback (hdd_adapter_t *pAdapter, ("%s: indicate TDLS teadown (staId %d)"), __func__, pHddCtx->tdlsConnInfo[staIdx].staId) ; #ifdef CONFIG_TDLS_IMPLICIT - curr_peer = wlan_hdd_tdls_find_peer(pAdapter,pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes); - wlan_hdd_tdls_indicate_teardown(pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); + curr_peer = wlan_hdd_tdls_find_all_peer(pHddCtx, pHddCtx->tdlsConnInfo[staIdx].peerMac.bytes); + if(curr_peer) + wlan_hdd_tdls_indicate_teardown(curr_peer->pHddTdlsCtx->pAdapter, curr_peer, eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON); #endif } } diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c index 5fc2ab5c719..997f37ec08e 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_tx_rx.c @@ -621,6 +621,7 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueued; ++pAdapter->hdd_stats.hddTxRxStats.txXmitQueuedAC[ac]; + ++pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count; //Make sure we have access to this access category if (likely(pAdapter->hddWmmStatus.wmmAcStatus[ac].wmmAcAccessAllowed) || @@ -671,27 +672,12 @@ int hdd_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ===========================================================================*/ void hdd_tx_timeout(struct net_device *dev) { - hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); - tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "%s: Transmission timeout occurred", __func__); //Getting here implies we disabled the TX queues for too long. Queues are //disabled either because of disassociation or low resource scenarios. In //case of disassociation it is ok to ignore this. But if associated, we have //do possible recovery here - - //testing underlying data path stall - //FTM mode, data path is not initiated - if (VOS_FTM_MODE == hdd_get_conparam()) - { - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - "%s: FTM mode, how initiated TX?", __func__); - } - else - { - sme_transportDebug(hHal, 0, 1); - } } @@ -1353,7 +1339,8 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, pAdapter = pHddCtx->sta_to_adapter[staId]; if( NULL == pAdapter ) { - VOS_ASSERT(0); + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,"%s: pAdapter is Null for staId %u", + __func__, staId); return VOS_STATUS_E_FAILURE; } @@ -1411,7 +1398,8 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, "rx extract mac:" MAC_ADDRESS_STR, MAC_ADDR_ARRAY(mac) ); curr_peer = wlan_hdd_tdls_find_peer(pAdapter, mac); - if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status)) + if ((NULL != curr_peer) && (eTDLS_LINK_CONNECTED == curr_peer->link_status) + && (TRUE == pRxMetaInfo->isStaTdls)) { wlan_hdd_tdls_increment_pkt_count(pAdapter, mac, 0); VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,"rssi is %d", pRxMetaInfo->rssiAvg); @@ -1432,13 +1420,14 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, pAdapter->stats.rx_bytes += skb->len; #ifdef WLAN_OPEN_SOURCE #ifdef WLAN_FEATURE_HOLD_RX_WAKELOCK - wake_lock_timeout(&pHddCtx->rx_wake_lock, HDD_WAKE_LOCK_DURATION); + wake_lock_timeout(&pHddCtx->rx_wake_lock, msecs_to_jiffies(HDD_WAKE_LOCK_DURATION)); #endif #endif rxstat = netif_rx_ni(skb); if (NET_RX_SUCCESS == rxstat) { ++pAdapter->hdd_stats.hddTxRxStats.rxDelivered; + ++pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count; } else { @@ -1461,3 +1450,119 @@ VOS_STATUS hdd_rx_packet_cbk( v_VOID_t *vosContext, return status; } +/**=========================================================================== + @brief hdd_tx_rx_pkt_cnt_stat_timer_handler() - + Enable/Disable split scan based on TX and RX traffic. + @param HddContext : [in] pointer to Hdd context + @return : None + ===========================================================================*/ +void hdd_tx_rx_pkt_cnt_stat_timer_handler( void *phddctx) +{ + hdd_adapter_list_node_t *pAdapterNode = NULL, *pNext = NULL; + hdd_adapter_t *pAdapter = NULL; + hdd_station_ctx_t *pHddStaCtx = NULL; + hdd_context_t *pHddCtx = (hdd_context_t *)phddctx; + hdd_config_t *cfg_param = pHddCtx->cfg_ini; + VOS_STATUS status; + v_U8_t staId = 0; + v_U8_t fconnected = 0; + + if (!cfg_param->dynSplitscan) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Error : Dynamic split scan is not Enabled : %d", + __func__, pHddCtx->cfg_ini->dynSplitscan); + return; + } + + status = hdd_get_front_adapter ( pHddCtx, &pAdapterNode ); + while ( NULL != pAdapterNode && VOS_STATUS_SUCCESS == status ) + { + pAdapter = pAdapterNode->pAdapter; + + if ( pAdapter ) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: Adapter with device mode %d exists", + __func__, pAdapter->device_mode); + + if ((WLAN_HDD_INFRA_STATION == pAdapter->device_mode) || + (WLAN_HDD_P2P_CLIENT == pAdapter->device_mode)) + { + pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); + if ((eConnectionState_Associated == + pHddStaCtx->conn_info.connState) && + (VOS_TRUE == pHddStaCtx->conn_info.uIsAuthenticated)) + { + fconnected = TRUE; + } + } + else if ((WLAN_HDD_SOFTAP == pAdapter->device_mode) || + (WLAN_HDD_P2P_GO == pAdapter->device_mode)) + { + for (staId = 0; staId < WLAN_MAX_STA_COUNT; staId++) + { + if ((pAdapter->aStaInfo[staId].isUsed) && + (WLANTL_STA_AUTHENTICATED == + pAdapter->aStaInfo[staId].tlSTAState)) + { + fconnected = TRUE; + } + } + } + if ( fconnected ) + { + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: One of the interface is connected check for scan", + __func__); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: pkt_tx_count: %d, pkt_rx_count: %d", __func__, + pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count, + pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count); + + vos_timer_start(&pHddCtx->tx_rx_trafficTmr, + cfg_param->trafficMntrTmrForSplitScan); + //Check for the previous statistics count + if ((pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count > + cfg_param->txRxThresholdForSplitScan) || + (pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count > + cfg_param->txRxThresholdForSplitScan) || + pHddCtx->drvr_miracast) + { + pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0; + pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0; + + if (!pHddCtx->issplitscan_enabled) + { + pHddCtx->issplitscan_enabled = TRUE; + sme_enable_disable_split_scan( + WLAN_HDD_GET_HAL_CTX(pAdapter), + cfg_param->nNumStaChanCombinedConc, + cfg_param->nNumP2PChanCombinedConc); + } + return; + } + else + { + pAdapter->hdd_stats.hddTxRxStats.pkt_tx_count = 0; + pAdapter->hdd_stats.hddTxRxStats.pkt_rx_count = 0; + } + fconnected = FALSE; + } + } + status = hdd_get_next_adapter( pHddCtx, pAdapterNode, &pNext); + pAdapterNode = pNext; + } + + if (pHddCtx->issplitscan_enabled) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Disable split scan", __func__); + pHddCtx->issplitscan_enabled = FALSE; + sme_enable_disable_split_scan( + pHddCtx->hHal, + SME_DISABLE_SPLIT_SCAN, + SME_DISABLE_SPLIT_SCAN); + } + return; +} diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c index 48f0571b755..964ed65bebd 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wext.c @@ -104,12 +104,14 @@ #include #include #include "wlan_qct_pal_trace.h" +#include "wlan_qct_tl.h" #include "wlan_hdd_misc.h" #include "bap_hdd_misc.h" #include "wlan_hdd_dev_pwr.h" #include "qc_sap_ioctl.h" +#include "sme_Api.h" #ifdef CONFIG_HAS_EARLYSUSPEND extern void hdd_suspend_wlan(struct early_suspend *wlan_suspend); @@ -208,9 +210,6 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #ifdef FEATURE_WLAN_TDLS #define WE_GET_TDLS_PEERS 8 #endif -#ifdef WLAN_FEATURE_11W -#define WE_GET_11W_INFO 9 -#endif /* Private ioctls and their sub-ioctls */ #define WLAN_PRIV_SET_NONE_GET_NONE (SIOCIWFIRSTPRIV + 6) @@ -221,6 +220,7 @@ static const hdd_freq_chan_map_t freq_chan_map[] = { {2412, 1}, {2417, 2}, #define WE_DISABLE_AMP 5 #define WE_ENABLE_DXE_STALL_DETECT 6 #define WE_DISPLAY_DXE_SNAP_SHOT 7 +#define WE_DISPLAY_DATAPATH_SNAP_SHOT 9 #define WE_SET_REASSOC_TRIGGER 8 /* Private ioctls and their sub-ioctls */ @@ -536,9 +536,6 @@ hdd_IsAuthTypeRSN( tHalHandle halHandle, eCsrAuthType authType) case eCSR_AUTH_TYPE_FT_RSN_PSK: #endif case eCSR_AUTH_TYPE_RSN_PSK: -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif rsnType = eANI_BOOLEAN_TRUE; break; //case eCSR_AUTH_TYPE_FAILED: @@ -910,14 +907,9 @@ void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter) pWextState->roamProfile.nRSNReqIELength = 0; pWextState->roamProfile.pRSNReqIE = (tANI_U8 *)NULL; -#ifdef FEATURE_WLAN_WAPI - pWextState->roamProfile.nWAPIReqIELength = 0; - pWextState->roamProfile.pWAPIReqIE = (tANI_U8 *)NULL; -#endif - pWextState->roamProfile.bWPSAssociation = VOS_FALSE; - pWextState->roamProfile.pAddIEScan = (tANI_U8 *)NULL; pWextState->roamProfile.nAddIEScanLength = 0; + memset(pWextState->roamProfile.addIEScan, 0 , SIR_MAC_MAX_IE_LENGTH+2); pWextState->roamProfile.pAddIEAssoc = (tANI_U8 *)NULL; pWextState->roamProfile.nAddIEAssocLength = 0; @@ -932,12 +924,6 @@ void hdd_clearRoamProfileIe( hdd_adapter_t *pAdapter) pWextState->roamProfile.AuthType.numEntries = 1; pWextState->roamProfile.AuthType.authType[0] = eCSR_AUTH_TYPE_OPEN_SYSTEM; -#ifdef WLAN_FEATURE_11W - pWextState->roamProfile.MFPEnabled = eANI_BOOLEAN_FALSE; - pWextState->roamProfile.MFPRequired = 0; - pWextState->roamProfile.MFPCapable = 0; -#endif - pWextState->authKeyMgmt = 0; for (i=0; i < CSR_MAX_NUM_KEY; i++) @@ -1917,6 +1903,7 @@ static int iw_get_range(struct net_device *dev, struct iw_request_info *info, if (active_phy_mode == WNI_CFG_DOT11_MODE_11A || active_phy_mode == WNI_CFG_DOT11_MODE_11G) { /*Get the supported rates for 11G band*/ + a_len = WNI_CFG_SUPPORTED_RATES_11A_LEN; if (ccmCfgGetStr(hHal, WNI_CFG_SUPPORTED_RATES_11A, supp_rates, &a_len) == eHAL_STATUS_SUCCESS) @@ -1939,6 +1926,7 @@ static int iw_get_range(struct net_device *dev, struct iw_request_info *info, else if (active_phy_mode == WNI_CFG_DOT11_MODE_11B) { /*Get the supported rates for 11B band*/ + b_len = WNI_CFG_SUPPORTED_RATES_11B_LEN; if (ccmCfgGetStr(hHal, WNI_CFG_SUPPORTED_RATES_11B, supp_rates, &b_len) == eHAL_STATUS_SUCCESS) @@ -2326,17 +2314,22 @@ static int iw_get_linkspeed(struct net_device *dev, union iwreq_data *wrqu, char *extra) { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + hdd_context_t *pHddCtx; char *pLinkSpeed = (char*)extra; - int len = sizeof(v_U16_t) + 1; - v_U16_t link_speed; + int len = sizeof(v_U32_t) + 1; + v_U32_t link_speed; hdd_station_ctx_t *pHddStaCtx = WLAN_HDD_GET_STATION_CTX_PTR(pAdapter); - int rc; + VOS_STATUS status; + int rc, valid; - if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) + pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + + valid = wlan_hdd_validate_context(pHddCtx); + + if (0 != valid) { - VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, - "%s:LOGP in Progress. Ignore!!!", __func__); - return -EBUSY; + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD context is not valid")); + return valid; } if (eConnectionState_Associated != pHddStaCtx->conn_info.connState) @@ -2346,21 +2339,40 @@ static int iw_get_linkspeed(struct net_device *dev, } else { - wlan_hdd_get_classAstats(pAdapter); - //The linkspeed returned by HAL is in units of 500kbps. - //converting it to mbps - link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2; + status = wlan_hdd_get_classAstats(pAdapter); + + if (!VOS_IS_STATUS_SUCCESS(status )) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Unable to retrieve SME statistics")); + return -EINVAL; + } + + /* Unit of link capacity is obtained from the TL API is MbpsX10 */ + WLANTL_GetSTALinkCapacity(WLAN_HDD_GET_CTX(pAdapter)->pvosContext, + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.staId[0], + &link_speed); + + link_speed = link_speed / 10; + + if (0 == link_speed) + { + /* The linkspeed returned by HAL is in units of 500kbps. + * converting it to mbps. + * This is required to support legacy firmware which does + * not return link capacity. + */ + link_speed = pAdapter->hdd_stats.ClassA_stat.tx_rate/2; + } + } wrqu->data.length = len; // return the linkspeed in the format required by the WiFi Framework - rc = snprintf(pLinkSpeed, len, "%u", link_speed); + rc = snprintf(pLinkSpeed, len, "%lu", link_speed); if ((rc < 0) || (rc >= len)) { // encoding or length error? - hddLog(VOS_TRACE_LEVEL_ERROR, - "%s: Unable to encode link speed, got [%s]", - __func__,pLinkSpeed); + hddLog(VOS_TRACE_LEVEL_ERROR,FL("Unable to encode link speed")); return -EIO; } @@ -3314,12 +3326,21 @@ static int iw_set_encodeext(struct net_device *dev, ("%s:cipher_alg:%d key_len[%d] *pEncryptionType :%d \n"),__func__,(int)ext->alg,(int)ext->key_len,setKey.encType); #ifdef WLAN_FEATURE_VOWIFI_11R -/* The supplicant may attempt to set the PTK once pre-authentication is done. - Save the key in the UMAC and include it in the ADD BSS request */ + /* The supplicant may attempt to set the PTK once pre-authentication + is done. Save the key in the UMAC and include it in the ADD + BSS request */ halStatus = sme_FTUpdateKey( WLAN_HDD_GET_HAL_CTX(pAdapter), &setKey); - if( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_WAIT ) + if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS ) { - return -EINVAL; + hddLog(VOS_TRACE_LEVEL_INFO_MED, + "%s: Update PreAuth Key success", __func__); + return 0; + } + else if ( halStatus == eHAL_STATUS_FT_PREAUTH_KEY_FAILED ) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Update PreAuth Key failed", __func__); + return -EINVAL; } #endif /* WLAN_FEATURE_VOWIFI_11R */ @@ -4060,9 +4081,6 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); int sub_cmd = wrqu->data.flags; -#ifdef WLAN_FEATURE_11W - hdd_wext_state_t *pWextState = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter); -#endif if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { @@ -4274,25 +4292,6 @@ static int iw_get_char_setnone(struct net_device *dev, struct iw_request_info *i wrqu->data.length = wlan_hdd_tdls_get_all_peers(pAdapter, extra, WE_MAX_STR_LEN)+1; break; } -#endif -#ifdef WLAN_FEATURE_11W - case WE_GET_11W_INFO: - { - hddLog(LOGE, "WE_GET_11W_ENABLED = %d", pWextState->roamProfile.MFPEnabled ); - - snprintf(extra, WE_MAX_STR_LEN, - "\n BSSID %02X:%02X:%02X:%02X:%02X:%02X, Is PMF Assoc? %d" - "\n Number of Unprotected Disassocs %d" - "\n Number of Unprotected Deauths %d", - (*pWextState->roamProfile.BSSIDs.bssid)[0], (*pWextState->roamProfile.BSSIDs.bssid)[1], - (*pWextState->roamProfile.BSSIDs.bssid)[2], (*pWextState->roamProfile.BSSIDs.bssid)[3], - (*pWextState->roamProfile.BSSIDs.bssid)[4], (*pWextState->roamProfile.BSSIDs.bssid)[5], - pWextState->roamProfile.MFPEnabled, pAdapter->hdd_stats.hddPmfStats.numUnprotDisassocRx, - pAdapter->hdd_stats.hddPmfStats.numUnprotDeauthRx); - - wrqu->data.length = strlen(extra)+1; - break; - } #endif default: { @@ -4348,6 +4347,12 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in pr_info("Stopping AP mode\n"); + if (TRUE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + /* EXIT BMPS as fw cannot handle DEL_STA when its in BMPS */ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_ACTIVE); + } + /*Make sure that pAdapter cleaned properly*/ hdd_stop_adapter( pHddCtx, pAdapter_to_stop ); hdd_deinit_adapter( pHddCtx, pAdapter_to_stop ); @@ -4357,6 +4362,12 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in pAdapter_to_stop->macAddressCurrent.bytes); hdd_close_adapter(WLAN_HDD_GET_CTX(pAdapter), pAdapter_to_stop, TRUE); + + if (FALSE == sme_IsPmcBmps(WLAN_HDD_GET_HAL_CTX(pAdapter))) + { + /* put the device back into BMPS */ + wlan_hdd_enter_bmps(pAdapter, DRIVER_POWER_MODE_AUTO); + } } else { @@ -4411,6 +4422,13 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in sme_transportDebug(hHal, VOS_TRUE, VOS_FALSE); break; } + case WE_DISPLAY_DATAPATH_SNAP_SHOT: + { + hddLog(LOGE, "%s: called %d",__func__, sub_cmd); + hdd_wmm_tx_snapshot(pAdapter); + WLANTL_TLDebugMessage(VOS_TRUE); + break; + } case WE_SET_REASSOC_TRIGGER: { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); @@ -4433,6 +4451,42 @@ static int iw_setnone_getnone(struct net_device *dev, struct iw_request_info *in return ret; } +void hdd_wmm_tx_snapshot(hdd_adapter_t *pAdapter) +{ + /* + * Function to display HDD WMM information + * for Tx Queues. + * Prints globala as well as per client depending + * whether the clients are registered or not. + */ + int i = 0, j = 0; + for ( i=0; i< NUM_TX_QUEUES; i++) + { + spin_lock_bh(&pAdapter->wmm_tx_queue[i].lock); + hddLog(LOGE, "HDD WMM TxQueue Info For AC: %d Count: %d PrevAdress:0x%x, NextAddress:0x%x", + i, pAdapter->wmm_tx_queue[i].count, + pAdapter->wmm_tx_queue[i].anchor.prev, pAdapter->wmm_tx_queue[i].anchor.next); + spin_unlock_bh(&pAdapter->wmm_tx_queue[i].lock); + } + + for(i =0; iaStaInfo[i].isUsed) + { + hddLog(LOGE, "******STAIndex: %d*********", i); + for ( j=0; j< NUM_TX_QUEUES; j++) + { + spin_lock_bh(&pAdapter->aStaInfo[i].wmm_tx_queue[j].lock); + hddLog(LOGE, "HDD TxQueue Info For AC: %d Count: %d PrevAdress:0x%x, NextAddress:0x%x", + j, pAdapter->aStaInfo[i].wmm_tx_queue[j].count, + pAdapter->aStaInfo[i].wmm_tx_queue[j].anchor.prev, + pAdapter->aStaInfo[i].wmm_tx_queue[j].anchor.next); + spin_unlock_bh(&pAdapter->aStaInfo[i].wmm_tx_queue[j].lock); + } + } + } + +} int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) { @@ -4530,7 +4584,7 @@ int iw_set_var_ints_getnone(struct net_device *dev, struct iw_request_info *info } else { - hddLog(LOGE, "%s : Enter valid MccCredential value between MIN :40 and MAX:160\n"); + hddLog(LOGE, "%s : Enter valid MccCredential value between MIN :40 and MAX:160\n", __func__); return 0; } } @@ -4925,7 +4979,7 @@ static int iw_qcom_set_wapi_key(struct net_device *dev, struct iw_request_info * hddLog(LOG1, "%s: Received data %s", __func__, (char*)wrqu->data.pointer); hddLog(LOG1, "%s: Received data %s", __func__, (char*)extra); - hddLog(LOG1,":s: INPUT DATA:\nKey Type:0x%02x Key Direction:0x%02x KEY ID:0x%02x\n", __func__,pWapiKey->keyType,pWapiKey->keyDirection,pWapiKey->keyId); + hddLog(LOG1,":%s: INPUT DATA:\nKey Type:0x%02x Key Direction:0x%02x KEY ID:0x%02x\n", __func__, pWapiKey->keyType, pWapiKey->keyDirection, pWapiKey->keyId); hddLog(LOG1,"Add Index:0x"); for(i =0 ; i < 12 ; i++) hddLog(LOG1,"%02x",pWapiKey->addrIndex[i]); @@ -5083,12 +5137,12 @@ static int iw_set_fties(struct net_device *dev, struct iw_request_info *info, } if (!wrqu->data.length) { - hddLog(LOGE, FL("%s called with 0 length IEs\n")); + hddLog(LOGE, FL("called with 0 length IEs\n")); return -EINVAL; } if (wrqu->data.pointer == NULL) { - hddLog(LOGE, FL("%s called with NULL IE\n")); + hddLog(LOGE, FL("called with NULL IE\n")); return -EINVAL; } @@ -5121,11 +5175,9 @@ static int iw_set_dynamic_mcbc_filter(struct net_device *dev, hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); tpSirWlanSetRxpFilters wlanRxpFilterParam; tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); - VOS_STATUS vstatus = VOS_STATUS_E_FAILURE; tpSirRcvFltMcAddrList mc_addr_list_ptr; int idx; eHalStatus ret_val; - tANI_U8 mcastBcastFilterSetting; if (pHddCtx->isLogpInProgress) { @@ -5134,7 +5186,9 @@ static int iw_set_dynamic_mcbc_filter(struct net_device *dev, return -EBUSY; } - if (HDD_MULTICAST_FILTER_LIST == pRequest->mcastBcastFilterSetting) { + if (HDD_MULTICAST_FILTER_LIST == pRequest->mcastBcastFilterSetting) + { +#ifdef WLAN_FEATURE_PACKET_FILTERING mc_addr_list_ptr = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList)); if (NULL == mc_addr_list_ptr) @@ -5169,69 +5223,45 @@ static int iw_set_dynamic_mcbc_filter(struct net_device *dev, __func__); return -EINVAL; } - } else { +#endif //WLAN_FEATURE_PACKET_FILTERING + } + else + { hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: Set MC BC Filter Config request: %d suspend %d", __func__, pRequest->mcastBcastFilterSetting, pHddCtx->hdd_wlan_suspended); - wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); - if (NULL == wlanRxpFilterParam) - { - hddLog(VOS_TRACE_LEVEL_FATAL, - "%s: vos_mem_alloc failed", __func__); - return -EINVAL; - } - - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting = - pRequest->mcastBcastFilterSetting; - pHddCtx->dynamic_mcbc_filter.enableCfg = TRUE; + pHddCtx->configuredMcastBcastFilter = pRequest->mcastBcastFilterSetting; if (pHddCtx->hdd_wlan_suspended) { + wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); + if (NULL == wlanRxpFilterParam) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed", __func__); + return -EINVAL; + } + wlanRxpFilterParam->configuredMcstBcstFilterSetting = pRequest->mcastBcastFilterSetting; wlanRxpFilterParam->setMcstBcstFilter = TRUE; - if ((pHddCtx->cfg_ini->fhostArpOffload) && - (eConnectionState_Associated == - (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) - { - vstatus = hdd_conf_hostarpoffload(pAdapter, TRUE); - if (!VOS_IS_STATUS_SUCCESS(vstatus)) - { - hddLog(VOS_TRACE_LEVEL_INFO, - "%s:Failed to enable ARPOFFLOAD Feature %d", - __func__, vstatus); - } - else - { - if (HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) - { - wlanRxpFilterParam->configuredMcstBcstFilterSetting = - HDD_MCASTBCASTFILTER_FILTER_ALL_MULTICAST; - } - else if (HDD_MCASTBCASTFILTER_FILTER_ALL_BROADCAST == - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting) - { - wlanRxpFilterParam->configuredMcstBcstFilterSetting = - HDD_MCASTBCASTFILTER_FILTER_NONE; - } - } - } + hdd_conf_hostoffload(pAdapter, TRUE); + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; hddLog(VOS_TRACE_LEVEL_INFO, "%s:MC/BC changed Req %d Set %d En %d", __func__, - pHddCtx->dynamic_mcbc_filter.mcastBcastFilterSetting, + pHddCtx->configuredMcastBcastFilter, wlanRxpFilterParam->configuredMcstBcstFilterSetting, wlanRxpFilterParam->setMcstBcstFilter); - mcastBcastFilterSetting = wlanRxpFilterParam->configuredMcstBcstFilterSetting; - - if (eHAL_STATUS_SUCCESS != sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), - wlanRxpFilterParam)) + if (eHAL_STATUS_SUCCESS != + sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), + wlanRxpFilterParam)) { hddLog(VOS_TRACE_LEVEL_ERROR, "%s: Failure to execute set HW MC/BC Filter request", @@ -5240,8 +5270,6 @@ static int iw_set_dynamic_mcbc_filter(struct net_device *dev, return -EINVAL; } - pHddCtx->dynamic_mcbc_filter.mcBcFilterSuspend = - mcastBcastFilterSetting; } } @@ -5254,11 +5282,42 @@ static int iw_clear_dynamic_mcbc_filter(struct net_device *dev, { hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); - + tpSirWlanSetRxpFilters wlanRxpFilterParam; hddLog(VOS_TRACE_LEVEL_INFO_HIGH, "%s: ", __func__); - pHddCtx->dynamic_mcbc_filter.enableCfg = FALSE; + //Reset the filter to INI value as we have to clear the dynamic filter + pHddCtx->configuredMcastBcastFilter = pHddCtx->cfg_ini->mcastBcastFilterSetting; + //Configure FW with new setting + if (pHddCtx->hdd_wlan_suspended) + { + wlanRxpFilterParam = vos_mem_malloc(sizeof(tSirWlanSetRxpFilters)); + if (NULL == wlanRxpFilterParam) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: vos_mem_alloc failed", __func__); + return -EINVAL; + } + + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + wlanRxpFilterParam->setMcstBcstFilter = TRUE; + + hdd_conf_hostoffload(pAdapter, TRUE); + wlanRxpFilterParam->configuredMcstBcstFilterSetting = + pHddCtx->configuredMcastBcastFilter; + + if (eHAL_STATUS_SUCCESS != + sme_ConfigureRxpFilter(WLAN_HDD_GET_HAL_CTX(pAdapter), + wlanRxpFilterParam)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute set HW MC/BC Filter request", + __func__); + vos_mem_free(wlanRxpFilterParam); + return -EINVAL; + } + } return 0; } @@ -5446,7 +5505,7 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, packetFilterSetReq.paramsData[i].dataLength = pRequest->paramsData[i].dataLength; packetFilterSetReq.paramsData[i].reserved = 0; - hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type\n", + hddLog(VOS_TRACE_LEVEL_INFO, "Proto %d Comp Flag %d Filter Type %d\n", pRequest->paramsData[i].protocolLayer, pRequest->paramsData[i].cmpFlag, packetFilterSetReq.filterType); @@ -5499,45 +5558,272 @@ int wlan_hdd_set_filter(hdd_context_t *pHddCtx, tpPacketFilterCfg pRequest, return 0; } +int wlan_hdd_setIPv6Filter(hdd_context_t *pHddCtx, tANI_U8 filterType, + tANI_U8 sessionId) +{ + tSirRcvPktFilterCfgType packetFilterSetReq = {0}; + tSirRcvFltPktClearParam packetFilterClrReq = {0}; + + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL(" NULL HDD Context Passed")); + return -EINVAL; + } + + if (pHddCtx->isLogpInProgress) + { + VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL, + "%s:LOGP in Progress. Ignore!!!", __func__); + return -EBUSY; + } + + if (pHddCtx->cfg_ini->disablePacketFilter) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Packet Filtering Disabled. Returning ", + __func__ ); + return -EINVAL; + } + + switch (filterType) + { + /* For setting IPV6 MC and UC Filter we need to configure + * 2 filters, one for MC and one for UC. + * The Filter ID shouldn't be swapped, which results in making + * UC Filter ineffective. + * We have Hardcode all the values + * + * Reason for a seperate UC filter is because, driver need to + * specify the FW that the specific filter is for unicast + * otherwise FW will not pass the unicast frames by default + * through the filter. This is required to avoid any performance + * hits when no unicast filter is set and only MC/BC are set. + * The way driver informs host is by using the MAC protocol + * layer, CMP flag set to MAX, CMP Data set to 1. + */ + + case HDD_FILTER_IPV6_MC_UC: + /* Setting IPV6 MC Filter below + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[0].dataOffset = + WLAN_HDD_80211_FRM_DA_OFFSET; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_MC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Mulicast Filter", + __func__); + return -EINVAL; + } + + memset( &packetFilterSetReq, 0, sizeof(tSirRcvPktFilterCfgType)); + + /* + * Setting IPV6 UC Filter below + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_UC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_MAX; + packetFilterSetReq.paramsData[0].dataOffset = 0; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_UC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Unicast Filter", + __func__); + return -EINVAL; + } + + break; + + case HDD_FILTER_IPV6_MC: + /* + * IPV6 UC Filter might be already set, + * clear the UC Filter. As the Filter + * IDs are static, we can directly clear it. + */ + packetFilterSetReq.filterType = HDD_RCV_FILTER_SET; + packetFilterClrReq.filterId = HDD_FILTER_ID_IPV6_UC; + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterClearFilter(pHddCtx->hHal, + &packetFilterClrReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Clear IPv6 Unicast Filter", + __func__); + return -EINVAL; + } + + /* + * Setting IPV6 MC Filter below + */ + packetFilterSetReq.filterId = HDD_FILTER_ID_IPV6_MC; + packetFilterSetReq.numFieldParams = 2; + packetFilterSetReq.paramsData[0].protocolLayer = + HDD_FILTER_PROTO_TYPE_MAC; + packetFilterSetReq.paramsData[0].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[0].dataOffset = + WLAN_HDD_80211_FRM_DA_OFFSET; + packetFilterSetReq.paramsData[0].dataLength = 1; + packetFilterSetReq.paramsData[0].compareData[0] = + HDD_IPV6_MC_CMP_DATA; + + packetFilterSetReq.paramsData[1].protocolLayer = + HDD_FILTER_PROTO_TYPE_ARP; + packetFilterSetReq.paramsData[1].cmpFlag = + HDD_FILTER_CMP_TYPE_NOT_EQUAL; + packetFilterSetReq.paramsData[1].dataOffset = ETH_ALEN; + packetFilterSetReq.paramsData[1].dataLength = 2; + packetFilterSetReq.paramsData[1].compareData[0] = + HDD_IPV6_CMP_DATA_0; + packetFilterSetReq.paramsData[1].compareData[1] = + HDD_IPV6_CMP_DATA_1; + + + if (eHAL_STATUS_SUCCESS != sme_ReceiveFilterSetFilter(pHddCtx->hHal, + &packetFilterSetReq, sessionId)) + { + hddLog(VOS_TRACE_LEVEL_ERROR, + "%s: Failure to execute Set IPv6 Multicast Filter", + __func__); + return -EINVAL; + } + break; + + default : + hddLog(VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Packet Filter Request: Invalid", + __func__); + return -EINVAL; + } + return 0; +} + void wlan_hdd_set_mc_addr_list(hdd_adapter_t *pAdapter, v_U8_t set) { - v_U8_t filterAction; - tPacketFilterCfg request; v_U8_t i; - hdd_context_t *pHddCtx = WLAN_HDD_GET_CTX(pAdapter); + tpSirRcvFltMcAddrList pMulticastAddrs = NULL; + tHalHandle hHal = WLAN_HDD_GET_HAL_CTX(pAdapter); + hdd_context_t* pHddCtx = (hdd_context_t*)pAdapter->pHddCtx; - filterAction = set ? HDD_RCV_FILTER_SET : HDD_RCV_FILTER_CLEAR; + if (NULL == hHal) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HAL Handle is NULL")); + return; + } + if (NULL == pHddCtx) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("HDD CTX is NULL")); + return; + } - /*set mulitcast addr list*/ - for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) + /* Check if INI is enabled or not, other wise just return + */ + if (pHddCtx->cfg_ini->fEnableMCAddrList) { - memset(&request, 0, sizeof (tPacketFilterCfg)); - request.filterAction = filterAction; - request.filterId = i; + pMulticastAddrs = vos_mem_malloc(sizeof(tSirRcvFltMcAddrList)); + if (NULL == pMulticastAddrs) + { + hddLog(VOS_TRACE_LEVEL_ERROR, FL("Could not allocate Memory")); + return; + } + if (set) { - request.numParams = 1; - request.paramsData[0].protocolLayer = HDD_FILTER_PROTO_TYPE_MAC; - request.paramsData[0].cmpFlag = HDD_FILTER_CMP_TYPE_EQUAL; - request.paramsData[0].dataOffset = WLAN_HDD_80211_FRM_DA_OFFSET; - request.paramsData[0].dataLength = ETH_ALEN; - memcpy(&(request.paramsData[0].compareData[0]), - &(pAdapter->mc_addr_list.addr[i][0]), ETH_ALEN); - /*set mulitcast filters*/ - hddLog(VOS_TRACE_LEVEL_INFO, - "%s: %s multicast filter: addr =" - MAC_ADDRESS_STR, - __func__, set ? "setting" : "clearing", - MAC_ADDR_ARRAY(request.paramsData[0].compareData)); + /* Following pre-conditions should be satisfied before wei + * configure the MC address list. + */ + if (((pAdapter->device_mode == WLAN_HDD_INFRA_STATION) || + (pAdapter->device_mode == WLAN_HDD_P2P_CLIENT)) + && pAdapter->mc_addr_list.mc_cnt + && (eConnectionState_Associated == + (WLAN_HDD_GET_STATION_CTX_PTR(pAdapter))->conn_info.connState)) + { + pMulticastAddrs->ulMulticastAddrCnt = + pAdapter->mc_addr_list.mc_cnt; + for (i = 0; i < pAdapter->mc_addr_list.mc_cnt; i++) + { + memcpy(&(pMulticastAddrs->multicastAddr[i][0]), + &(pAdapter->mc_addr_list.addr[i][0]), + sizeof(pAdapter->mc_addr_list.addr[i])); + hddLog(VOS_TRACE_LEVEL_INFO, + "%s: %s multicast filter: addr =" + MAC_ADDRESS_STR, + __func__, set ? "setting" : "clearing", + MAC_ADDR_ARRAY(pMulticastAddrs->multicastAddr[i])); + } + /* Set multicast filter */ + sme_8023MulticastList(hHal, pAdapter->sessionId, + pMulticastAddrs); + } } - wlan_hdd_set_filter(pHddCtx, &request, pAdapter->sessionId); + else + { + /* Need to clear only if it was previously configured + */ + if (pAdapter->mc_addr_list.isFilterApplied) + { + pMulticastAddrs->ulMulticastAddrCnt = 0; + sme_8023MulticastList(hHal, pAdapter->sessionId, + pMulticastAddrs); + } + + } + pAdapter->mc_addr_list.isFilterApplied = set ? TRUE : FALSE; + } + else + { + hddLog(VOS_TRACE_LEVEL_INFO, + FL("fEnableMCAddrList is not enabled in INI")); } - pAdapter->mc_addr_list.isFilterApplied = set ? TRUE : FALSE; + return; } static int iw_set_packet_filter_params(struct net_device *dev, struct iw_request_info *info, union iwreq_data *wrqu, char *extra) -{ +{ hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); tpPacketFilterCfg pRequest = (tpPacketFilterCfg)wrqu->data.pointer; @@ -5772,7 +6058,7 @@ VOS_STATUS iw_set_pno(struct net_device *dev, struct iw_request_info *info, VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "PNO data len %d data %s", wrqu->data.length, - wrqu->data.pointer); + (char *)wrqu->data.pointer); if (wrqu->data.length <= nOffset ) { @@ -6153,7 +6439,7 @@ int hdd_setBand_helper(struct net_device *dev, tANI_U8* ptr) if (lrc <= 0) { - hddLog(VOS_TRACE_LEVEL_ERROR,"%s: %s while while waiting for csrRoamDisconnect ", + hddLog(VOS_TRACE_LEVEL_ERROR,"%s: %s while waiting for csrRoamDisconnect ", __func__, (0 == lrc) ? "Timeout" : "Interrupt"); return (0 == lrc) ? -ETIMEDOUT : -EINTR; @@ -6229,7 +6515,7 @@ VOS_STATUS iw_set_power_params(struct net_device *dev, struct iw_request_info *i VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "Power Params data len %d data %s", wrqu->data.length, - wrqu->data.pointer); + (char *)wrqu->data.pointer); if ((WLAN_HDD_GET_CTX(pAdapter))->isLogpInProgress) { @@ -6665,13 +6951,6 @@ static const struct iw_priv_args we_private_args[] = { 0, IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, "getTdlsPeers" }, -#endif -#ifdef WLAN_FEATURE_11W - { - WE_GET_11W_INFO, - 0, - IW_PRIV_TYPE_CHAR| WE_MAX_STR_LEN, - "getPMFInfo" }, #endif /* handlers for main ioctl */ { WLAN_PRIV_SET_NONE_GET_NONE, @@ -6708,6 +6987,10 @@ static const struct iw_priv_args we_private_args[] = { 0, 0, "dxeSnapshot" }, + { WE_DISPLAY_DATAPATH_SNAP_SHOT, + 0, + 0, + "dataSnapshot"}, { WE_SET_REASSOC_TRIGGER, 0, @@ -6877,7 +7160,7 @@ static const struct iw_priv_args we_private_args[] = { { WLAN_GET_LINK_SPEED, IW_PRIV_TYPE_CHAR | 18, - IW_PRIV_TYPE_CHAR | 3, "getLinkSpeed" }, + IW_PRIV_TYPE_CHAR | 5, "getLinkSpeed" }, }; diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c index 23dc9c5afec..d8a880286bf 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wmm.c @@ -81,6 +81,7 @@ #include #include #include +#include // change logging behavior based upon debug flag #ifdef HDD_WMM_DEBUG @@ -689,7 +690,7 @@ static eHalStatus hdd_wmm_sme_callback (tHalHandle hHal, #ifdef FEATURE_WLAN_CCX // Check if the inactivity interval is specified - if (pCurrentQosInfo->inactivity_interval) { + if (pCurrentQosInfo && pCurrentQosInfo->inactivity_interval) { VOS_TRACE(VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_INFO, "%s: Inactivity timer value = %d for AC=%d\n", __func__, pCurrentQosInfo->inactivity_interval, acType); @@ -1813,6 +1814,14 @@ v_U16_t hdd_wmm_select_queue(struct net_device * dev, struct sk_buff *skb) hdd_adapter_t *pAdapter = WLAN_HDD_GET_PRIV_PTR(dev); + if (isWDresetInProgress()) + { + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_WARN, + FL("called during WDReset")); + skb->priority = SME_QOS_WMM_UP_BE; + return HDD_LINUX_AC_BE; + } + // if we don't want QoS or the AP doesn't support Qos // All traffic will get equal opportuniy to transmit data frames. if( hdd_wmm_is_active(pAdapter) ) { @@ -2268,7 +2277,7 @@ hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter, default: // we didn't get back one of the SME_QOS_STATUS_MODIFY_* status codes VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, - "%s: unexpected SME Status=%d\n", smeStatus ); + "%s: unexpected SME Status=%d\n", __func__, smeStatus ); VOS_ASSERT(0); return HDD_WLAN_WMM_STATUS_MODIFY_FAILED; } @@ -2346,7 +2355,7 @@ hdd_wlan_wmm_status_e hdd_wmm_addts( hdd_adapter_t* pAdapter, // we didn't get back one of the SME_QOS_STATUS_SETUP_* status codes hdd_wmm_free_context(pQosContext); VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, - "%s: unexpected SME Status=%d\n", smeStatus ); + "%s: unexpected SME Status=%d\n", __func__, smeStatus ); VOS_ASSERT(0); return HDD_WLAN_WMM_STATUS_SETUP_FAILED; } @@ -2457,7 +2466,7 @@ hdd_wlan_wmm_status_e hdd_wmm_delts( hdd_adapter_t* pAdapter, default: // we didn't get back one of the SME_QOS_STATUS_RELEASE_* status codes VOS_TRACE( VOS_MODULE_ID_HDD, WMM_TRACE_LEVEL_ERROR, - "%s: unexpected SME Status=%d\n", smeStatus ); + "%s: unexpected SME Status=%d\n", __func__, smeStatus ); VOS_ASSERT(0); status = HDD_WLAN_WMM_STATUS_RELEASE_FAILED; } diff --git a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wowl.c b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wowl.c index 101bd18a9b7..e783033a3c6 100644 --- a/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wowl.c +++ b/drivers/staging/prima/CORE/HDD/src/wlan_hdd_wowl.c @@ -71,7 +71,7 @@ char *g_hdd_wowl_ptrns[WOWL_MAX_PTRNS_ALLOWED]; //Patterns 0-7 -static int parse_hex(unsigned char c) +int hdd_parse_hex(unsigned char c) { if (c >= '0' && c <= '9') return c-'0'; @@ -190,11 +190,11 @@ v_BOOL_t hdd_add_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn) // Extract the pattern size localPattern.ucPatternSize = - ( parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] ); + ( hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); // Extract the pattern mask size localPattern.ucPatternMaskSize = - ( parse_hex( ptrn[3] ) * 0x10 ) + parse_hex( ptrn[4] ); + ( hdd_parse_hex( ptrn[3] ) * 0x10 ) + hdd_parse_hex( ptrn[4] ); if(localPattern.ucPatternSize > WOWL_PTRN_MAX_SIZE || localPattern.ucPatternMaskSize > WOWL_PTRN_MASK_MAX_SIZE) @@ -234,7 +234,7 @@ v_BOOL_t hdd_add_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn) for(i=0; i < localPattern.ucPatternSize; i++) { localPattern.ucPattern[i] = - (parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] ); + (hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); ptrn += 2; //skip to next byte } @@ -244,7 +244,7 @@ v_BOOL_t hdd_add_wowl_ptrn (hdd_adapter_t *pAdapter, const char * ptrn) for(i=0; i < localPattern.ucPatternMaskSize; i++) { localPattern.ucPatternMask[i] = - (parse_hex( ptrn[0] ) * 0x10 ) + parse_hex( ptrn[1] ); + (hdd_parse_hex( ptrn[0] ) * 0x10 ) + hdd_parse_hex( ptrn[1] ); ptrn += 2; //skip to next byte } diff --git a/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h b/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h index f1b6318687a..e55dca65e5b 100644 --- a/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h +++ b/drivers/staging/prima/CORE/MAC/inc/aniGlobal.h @@ -150,6 +150,8 @@ typedef struct sAniSirGlobal *tpAniSirGlobal; #define SPACE_ASCII_VALUE 32 +#define SPACE_ASCII_VALUE 32 + // ------------------------------------------------------------------- // Change channel generic scheme typedef void (*CHANGE_CHANNEL_CALLBACK)(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data, @@ -336,6 +338,20 @@ typedef struct sAniSirLim tLimScanResultNode *gLimCachedScanHashTable[LIM_MAX_NUM_OF_SCAN_RESULTS]; + /// This indicates total length of 'matched' scan results + tANI_U16 gLimMlmLfrScanResultLength; + + /// This indicates total length of 'cached' scan results + tANI_U16 gLimSmeLfrScanResultLength; + + /** + * Hash table definition for storing LFR SCAN results + * This is the placed holder for roaming candidates as forwarded + * by FW + */ + tLimScanResultNode + *gLimCachedLfrScanHashTable[LIM_MAX_NUM_OF_SCAN_RESULTS]; + /// Place holder for current channel ID /// being scanned during background scanning tANI_U32 gLimBackgroundScanChannelId; diff --git a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h index aaf39184931..7bc4959e549 100644 --- a/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h +++ b/drivers/staging/prima/CORE/MAC/inc/qwlan_version.h @@ -58,11 +58,11 @@ BRIEF DESCRIPTION: #define QWLAN_VERSION_MAJOR 3 #define QWLAN_VERSION_MINOR 2 -#define QWLAN_VERSION_PATCH 2 -#define QWLAN_VERSION_EXTRA "B" -#define QWLAN_VERSION_BUILD 17 +#define QWLAN_VERSION_PATCH 3 +#define QWLAN_VERSION_EXTRA "" +#define QWLAN_VERSION_BUILD 18 -#define QWLAN_VERSIONSTR "3.2.2.17B" +#define QWLAN_VERSIONSTR "3.2.3.18" #endif /* QWLAN_VERSION_H */ diff --git a/drivers/staging/prima/CORE/MAC/inc/sirApi.h b/drivers/staging/prima/CORE/MAC/inc/sirApi.h index 71d4366b65a..36fab78cbb0 100644 --- a/drivers/staging/prima/CORE/MAC/inc/sirApi.h +++ b/drivers/staging/prima/CORE/MAC/inc/sirApi.h @@ -1,9 +1,43 @@ /* -* Copyright (c) 2012-2013 Qualcomm Atheros, Inc. -* All Rights Reserved. -* Qualcomm Atheros Confidential and Proprietary. -*/ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ /* * Airgo Networks, Inc proprietary. All rights reserved. @@ -986,15 +1020,11 @@ typedef struct sSirSmeJoinReq tAniEdType UCEncryptionType; tAniEdType MCEncryptionType; - -#ifdef WLAN_FEATURE_11W - tAniEdType MgmtEncryptionType; -#endif - #ifdef WLAN_FEATURE_VOWIFI_11R tAniBool is11Rconnection; #endif #ifdef FEATURE_WLAN_CCX + tAniBool isCCXFeatureIniEnabled; tAniBool isCCXconnection; tCCXTspecInfo ccxTspecInfo; #endif @@ -3219,7 +3249,9 @@ typedef struct sSirUpdateAPWPARSNIEsReq #define SIR_OFFLOAD_DISABLE 0 #define SIR_OFFLOAD_ENABLE 1 #define SIR_OFFLOAD_BCAST_FILTER_ENABLE 0x2 +#define SIR_OFFLOAD_MCAST_FILTER_ENABLE 0x4 #define SIR_OFFLOAD_ARP_AND_BCAST_FILTER_ENABLE (SIR_OFFLOAD_ENABLE|SIR_OFFLOAD_BCAST_FILTER_ENABLE) +#define SIR_OFFLOAD_NS_AND_MCAST_FILTER_ENABLE (SIR_OFFLOAD_ENABLE|SIR_OFFLOAD_MCAST_FILTER_ENABLE) #ifdef WLAN_NS_OFFLOAD typedef struct sSirNsOffloadReq @@ -3231,6 +3263,7 @@ typedef struct sSirNsOffloadReq tANI_U8 selfMacAddr[6]; tANI_U8 srcIPv6AddrValid; tANI_U8 targetIPv6AddrValid[SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA]; + tANI_U8 slotIdx; } tSirNsOffloadReq, *tpSirNsOffloadReq; #endif //WLAN_NS_OFFLOAD @@ -3273,6 +3306,7 @@ typedef struct sSirSmeAddStaSelfReq tANI_U16 mesgType; tANI_U16 mesgLen; tSirMacAddr selfMacAddr; + tVOS_CON_MODE currDeviceMode; }tSirSmeAddStaSelfReq, *tpSirSmeAddStaSelfReq; typedef struct sSirSmeDelStaSelfReq @@ -3307,6 +3341,8 @@ typedef struct sSirSmeDelStaSelfRsp #define SIR_COEX_IND_TYPE_ENABLE_HB_MONITOR (1) #define SIR_COEX_IND_TYPE_SCAN_COMPROMISED (2) #define SIR_COEX_IND_TYPE_SCAN_NOT_COMPROMISED (3) +#define SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4 (4) +#define SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4 (5) typedef struct sSirSmeCoexInd { @@ -3327,16 +3363,6 @@ typedef struct sSirSmeMgmtFrameInd tANI_U8 frameBuf[1]; //variable }tSirSmeMgmtFrameInd, *tpSirSmeMgmtFrameInd; -#ifdef WLAN_FEATURE_11W -typedef struct sSirSmeUnprotMgmtFrameInd -{ - tANI_U8 sessionId; - tANI_U8 frameType; - tANI_U8 frameLen; - tANI_U8 frameBuf[1]; //variable -}tSirSmeUnprotMgmtFrameInd, *tpSirSmeUnprotMgmtFrameInd; -#endif - #define SIR_IS_FULL_POWER_REASON_DISCONNECTED(eReason) \ ( ( eSME_LINK_DISCONNECTED_BY_HDD == (eReason) ) || \ ( eSME_LINK_DISCONNECTED_BY_OTHER == (eReason) ) || \ @@ -3399,7 +3425,8 @@ typedef struct sSirWlanSetRxpFilters #define CHANNEL_LIST_DYNAMIC_UPDATE 4 /* Occupied channel list can be learnt after update */ #define SIR_ROAM_SCAN_24G_DEFAULT_CH 1 #define SIR_ROAM_SCAN_5G_DEFAULT_CH 36 -#define SIR_ROAM_SCAN_RESERVED_BYTES 64 +#define SIR_ROAM_SCAN_CHANNEL_SWITCH_TIME 3 +#define SIR_ROAM_SCAN_RESERVED_BYTES 61 #endif typedef enum @@ -3417,7 +3444,7 @@ typedef struct tANI_U32 encryption; tANI_U32 bcastNetwType; tANI_U8 ucChannelCount; - tANI_U8 aChannels[SIR_PNO_MAX_NETW_CHANNELS]; + tANI_U8 aChannels[SIR_PNO_MAX_NETW_CHANNELS_EX]; tANI_U8 rssiThreshold; } tSirNetworkType; @@ -3487,9 +3514,18 @@ typedef struct sSirRoamOffloadScanReq tANI_U8 p24GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; tANI_U16 us5GProbeTemplateLen; tANI_U8 p5GProbeTemplate[SIR_ROAM_SCAN_MAX_PB_REQ_SIZE]; - tANI_U8 ReservedBytes[SIR_ROAM_SCAN_RESERVED_BYTES]; /*This is to add any additional data in future - without changing the interface params on Host - and firmware.*/ + tANI_U8 ReservedBytes[SIR_ROAM_SCAN_RESERVED_BYTES]; + /*ReservedBytes is to add any further params in future + without changing the interface params on Host + and firmware.The firmware right now checks + if the size of this structure matches and then + proceeds with the processing of the command. + So, in future, if there is any need to add + more params, pick the memory from reserved + bytes and keep deducting the reserved bytes + by the amount of bytes picked.*/ + tANI_U8 nProbes; + tANI_U16 HomeAwayTime; tSirRoamNetworkType ConnectedNetwork; tSirMobilityDomainInfo MDID; } tSirRoamOffloadScanReq, *tpSirRoamOffloadScanReq; @@ -3517,12 +3553,18 @@ typedef struct { // Preferred Network Found Indication typedef struct { - tANI_U16 mesgType; - tANI_U16 mesgLen; + tANI_U16 mesgType; + tANI_U16 mesgLen; /* Network that was found with the highest RSSI*/ - tSirMacSSid ssId; + tSirMacSSid ssId; /* Indicates the RSSI */ - tANI_U8 rssi; + tANI_U8 rssi; + /* Length of the beacon or probe response + * corresponding to the candidate found by PNO */ + tANI_U32 frameLength; + /* Index to memory location where the contents of + * beacon or probe response frame will be copied */ + tANI_U8 data[1]; } tSirPrefNetworkFoundInd, *tpSirPrefNetworkFoundInd; #endif // FEATURE_WLAN_SCAN_PNO @@ -3559,6 +3601,9 @@ typedef struct /* Beacon Early Termination Interval */ tANI_U32 uBETInterval; + /* MAX LI for modulated DTIM */ + tANI_U32 uMaxLIModulatedDTIM; + }tSirSetPowerParamsReq, *tpSirSetPowerParamsReq; typedef struct sSirTxPerTrackingParam @@ -4049,12 +4094,4 @@ typedef struct sSirSmeCandidateFoundInd tANI_U8 sessionId; // Session Identifier } tSirSmeCandidateFoundInd, *tpSirSmeCandidateFoundInd; -#ifdef WLAN_FEATURE_11W -typedef struct sSirWlanExcludeUnencryptParam -{ - tANI_BOOLEAN excludeUnencrypt; - tSirMacAddr bssId; -}tSirWlanExcludeUnencryptParam,*tpSirWlanExcludeUnencryptParam; -#endif - #endif /* __SIR_API_H */ diff --git a/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h b/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h index 68121e595f7..cd548457338 100644 --- a/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h +++ b/drivers/staging/prima/CORE/MAC/inc/sirMacProtDef.h @@ -38,8 +38,9 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ + + /* - * Airgo Networks, Inc proprietary. All rights reserved. * This file sirMacProtDef.h contains the MAC/PHY protocol * definitions used across various projects. * Author: Chandra Modumudi @@ -261,9 +262,7 @@ #ifdef WLAN_FEATURE_11W //11w SA query request/response action frame category code -#define SIR_MAC_ACTION_SA_QUERY 8 -#define SIR_MAC_SA_QUERY_REQ 0 -#define SIR_MAC_SA_QUERY_RSP 1 +#define SIR_MAC_ACTION_SA_QUERY 8 #endif #ifdef FEATURE_WLAN_TDLS @@ -499,8 +498,10 @@ #define SIR_MAC_OUI_WSM_SCHEDULE_MAX 20 #ifdef WLAN_NS_OFFLOAD -#define SIR_MAC_NS_OFFLOAD_SIZE 1 //support only one IPv6 offload +#define SIR_MAC_NS_OFFLOAD_SIZE 1 //support only one IPv6 offload #define SIR_MAC_NUM_TARGET_IPV6_NS_OFFLOAD_NA 2 //Number of target IP in NA frames. It must be at least 2 +#define SIR_MAC_IPV6_ADDR_LEN 16 +#define SIR_IPV6_ADDR_VALID 1 #endif //WLAN_NS_OFFLOAD #define SIR_MAC_ARP_OFFLOAD_SIZE 1 @@ -629,6 +630,13 @@ #define SIR_MAC_CLEAR_CAPABILITY(u16value, bitname) \ ((u16value) &= (~(SIR_MAC_SET_##bitname(0)))) +#define IS_WES_MODE_ENABLED(x) \ + ((x)->roam.configParam.isWESModeEnabled) + +#define BA_RECIPIENT 1 +#define BA_INITIATOR 2 +#define BA_BOTH_DIRECTIONS 3 + /// Status Code (present in Management response frames) enum typedef enum eSirMacStatusCodes @@ -2328,6 +2336,14 @@ typedef __ani_attr_pre_packed struct sSirMacActionFrameHdr tANI_U8 actionID; } __ani_attr_packed tSirMacActionFrameHdr, *tpSirMacActionFrameHdr; +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) +typedef __ani_attr_pre_packed struct sSirMacVendorSpecificFrameHdr +{ + tANI_U8 category; + tANI_U8 Oui[4]; +} __ani_attr_packed tSirMacVendorSpecificFrameHdr, *tpSirMacVendorSpecificFrameHdr; +#endif + typedef __ani_attr_pre_packed struct sSirMacVendorSpecificPublicActionFrameHdr { tANI_U8 category; diff --git a/drivers/staging/prima/CORE/MAC/inc/wniApi.h b/drivers/staging/prima/CORE/MAC/inc/wniApi.h index e3fd1b6258f..1388052e7b4 100644 --- a/drivers/staging/prima/CORE/MAC/inc/wniApi.h +++ b/drivers/staging/prima/CORE/MAC/inc/wniApi.h @@ -366,13 +366,10 @@ enum eWniMsgTypes #endif eWNI_SME_SET_BCN_FILTER_REQ, eWNI_SME_RESET_AP_CAPS_CHANGED, -#ifdef WLAN_FEATURE_11W - eWNI_SME_UNPROT_MGMT_FRM_IND, -#endif #ifdef WLAN_FEATURE_GTK_OFFLOAD eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP, #endif // WLAN_FEATURE_GTK_OFFLOAD - + eWNI_SME_CANDIDATE_FOUND_IND, //ROAM candidate indication from FW eWNI_SME_MSG_TYPES_END }; diff --git a/drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h b/drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h index 96187e29524..fcf8f83c684 100644 --- a/drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h +++ b/drivers/staging/prima/CORE/MAC/inc/wniCfgAp.h @@ -290,75 +290,78 @@ #define WNI_CFG_MAX_BA_SESSIONS 225 #define WNI_CFG_BA_AUTO_SETUP 226 #define WNI_CFG_ADDBA_REQ_DECLINE 227 -#define WNI_CFG_BG_SCAN_CHANNEL_LIST 228 -#define WNI_CFG_MAX_MEDIUM_TIME 229 -#define WNI_CFG_MAX_MPDUS_IN_AMPDU 230 -#define WNI_CFG_IBSS_AUTO_BSSID 231 -#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 232 -#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 233 -#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 234 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 235 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 236 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 237 -#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 238 -#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 239 -#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 240 -#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 241 -#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 242 -#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 243 -#define WNI_CFG_WPS_ENABLE 244 -#define WNI_CFG_WPS_STATE 245 -#define WNI_CFG_WPS_PROBE_REQ_FLAG 246 -#define WNI_CFG_WPS_VERSION 247 -#define WNI_CFG_WPS_REQUEST_TYPE 248 -#define WNI_CFG_WPS_CFG_METHOD 249 -#define WNI_CFG_WPS_UUID 250 -#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 251 -#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 252 -#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 253 -#define WNI_CFG_WPS_ASSOCIATION_STATE 254 -#define WNI_CFG_WPS_CONFIGURATION_ERROR 255 -#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 256 -#define WNI_CFG_WPS_ASSOC_METHOD 257 -#define WNI_CFG_LOW_GAIN_OVERRIDE 258 -#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 259 -#define WNI_CFG_RPE_POLLING_THRESHOLD 260 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 261 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 262 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 263 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 264 -#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 265 -#define WNI_CFG_SINGLE_TID_RC 266 -#define WNI_CFG_RRM_ENABLED 267 -#define WNI_CFG_RRM_OPERATING_CHAN_MAX 268 -#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX 269 -#define WNI_CFG_TX_PWR_CTRL_ENABLE 270 -#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 271 -#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 272 -#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 273 -#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 274 -#define WNI_CFG_TELE_BCN_WAKEUP_EN 275 -#define WNI_CFG_TELE_BCN_TRANS_LI 276 -#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 277 -#define WNI_CFG_TELE_BCN_MAX_LI 278 -#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 279 -#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 280 -#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 281 -#define WNI_CFG_ASSOC_STA_LIMIT 282 -#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 283 -#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 284 -#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 285 -#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 286 -#define WNI_CFG_ENABLE_CLOSE_LOOP 287 -#define WNI_CFG_ENABLE_LTE_COEX 288 -#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 289 -#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 290 -#define WNI_CFG_ENABLE_MC_ADDR_LIST 291 -#define WNI_CFG_ENABLE_UC_FILTER 292 -#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 293 -#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 294 -#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 295 -#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 296 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC 228 +#define WNI_CFG_BG_SCAN_CHANNEL_LIST 229 +#define WNI_CFG_MAX_MEDIUM_TIME 230 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU 231 +#define WNI_CFG_IBSS_AUTO_BSSID 232 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 233 +#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 234 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 235 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 236 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 237 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 238 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 239 +#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 240 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 241 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 242 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 243 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 244 +#define WNI_CFG_WPS_ENABLE 245 +#define WNI_CFG_WPS_STATE 246 +#define WNI_CFG_WPS_PROBE_REQ_FLAG 247 +#define WNI_CFG_WPS_VERSION 248 +#define WNI_CFG_WPS_REQUEST_TYPE 249 +#define WNI_CFG_WPS_CFG_METHOD 250 +#define WNI_CFG_WPS_UUID 251 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 252 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 253 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 254 +#define WNI_CFG_WPS_ASSOCIATION_STATE 255 +#define WNI_CFG_WPS_CONFIGURATION_ERROR 256 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 257 +#define WNI_CFG_WPS_ASSOC_METHOD 258 +#define WNI_CFG_LOW_GAIN_OVERRIDE 259 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 260 +#define WNI_CFG_RPE_POLLING_THRESHOLD 261 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 262 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 263 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 264 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 265 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 266 +#define WNI_CFG_SINGLE_TID_RC 267 +#define WNI_CFG_RRM_ENABLED 268 +#define WNI_CFG_RRM_OPERATING_CHAN_MAX 269 +#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX 270 +#define WNI_CFG_TX_PWR_CTRL_ENABLE 271 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 272 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 273 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 274 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 275 +#define WNI_CFG_TELE_BCN_WAKEUP_EN 276 +#define WNI_CFG_TELE_BCN_TRANS_LI 277 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 278 +#define WNI_CFG_TELE_BCN_MAX_LI 279 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 280 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 281 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 282 +#define WNI_CFG_ASSOC_STA_LIMIT 283 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 284 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 285 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 286 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 287 +#define WNI_CFG_ENABLE_CLOSE_LOOP 288 +#define WNI_CFG_ENABLE_LTE_COEX 289 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 290 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 291 +#define WNI_CFG_ENABLE_MC_ADDR_LIST 292 +#define WNI_CFG_ENABLE_UC_FILTER 293 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 294 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 295 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 296 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 297 +#define WNI_CFG_RA_FILTER_ENABLE 298 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL 299 /* * String parameter lengths @@ -2002,6 +2005,14 @@ #define WNI_CFG_ADDBA_REQ_DECLINE_APMAX 255 #define WNI_CFG_ADDBA_REQ_DECLINE_APDEF 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STADEF 0 + +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_APDEF 0 + #define WNI_CFG_MAX_MEDIUM_TIME_STAMIN 0 #define WNI_CFG_MAX_MEDIUM_TIME_STAMAX 65535 #define WNI_CFG_MAX_MEDIUM_TIME_STADEF 2048 @@ -2477,10 +2488,26 @@ #define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_APMAX 255 #define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_APDEF 3 -#define CFG_PARAM_MAX_NUM 297 -#define CFG_AP_IBUF_MAX_SIZE 236 +#define WNI_CFG_RA_FILTER_ENABLE_STAMIN 0 +#define WNI_CFG_RA_FILTER_ENABLE_STAMAX 1 +#define WNI_CFG_RA_FILTER_ENABLE_STADEF 1 + +#define WNI_CFG_RA_FILTER_ENABLE_APMIN 0 +#define WNI_CFG_RA_FILTER_ENABLE_APMAX 1 +#define WNI_CFG_RA_FILTER_ENABLE_APDEF 1 + +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STAMIN 0 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STAMAX 60 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STADEF 60 + +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_APMIN 0 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_APMAX 60 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_APDEF 60 + +#define CFG_PARAM_MAX_NUM 300 +#define CFG_AP_IBUF_MAX_SIZE 239 #define CFG_AP_SBUF_MAX_SIZE 3422 -#define CFG_STA_IBUF_MAX_SIZE 231 +#define CFG_STA_IBUF_MAX_SIZE 234 #define CFG_STA_SBUF_MAX_SIZE 3388 #define CFG_SEM_MAX_NUM 19 diff --git a/drivers/staging/prima/CORE/MAC/inc/wniCfgSta.h b/drivers/staging/prima/CORE/MAC/inc/wniCfgSta.h index 571d55977e3..caa5a0099e2 100644 --- a/drivers/staging/prima/CORE/MAC/inc/wniCfgSta.h +++ b/drivers/staging/prima/CORE/MAC/inc/wniCfgSta.h @@ -284,75 +284,78 @@ #define WNI_CFG_MAX_BA_SESSIONS 225 #define WNI_CFG_BA_AUTO_SETUP 226 #define WNI_CFG_ADDBA_REQ_DECLINE 227 -#define WNI_CFG_BG_SCAN_CHANNEL_LIST 228 -#define WNI_CFG_MAX_MEDIUM_TIME 229 -#define WNI_CFG_MAX_MPDUS_IN_AMPDU 230 -#define WNI_CFG_IBSS_AUTO_BSSID 231 -#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 232 -#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 233 -#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 234 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 235 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 236 -#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 237 -#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 238 -#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 239 -#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 240 -#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 241 -#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 242 -#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 243 -#define WNI_CFG_WPS_ENABLE 244 -#define WNI_CFG_WPS_STATE 245 -#define WNI_CFG_WPS_PROBE_REQ_FLAG 246 -#define WNI_CFG_WPS_VERSION 247 -#define WNI_CFG_WPS_REQUEST_TYPE 248 -#define WNI_CFG_WPS_CFG_METHOD 249 -#define WNI_CFG_WPS_UUID 250 -#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 251 -#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 252 -#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 253 -#define WNI_CFG_WPS_ASSOCIATION_STATE 254 -#define WNI_CFG_WPS_CONFIGURATION_ERROR 255 -#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 256 -#define WNI_CFG_WPS_ASSOC_METHOD 257 -#define WNI_CFG_LOW_GAIN_OVERRIDE 258 -#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 259 -#define WNI_CFG_RPE_POLLING_THRESHOLD 260 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 261 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 262 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 263 -#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 264 -#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 265 -#define WNI_CFG_SINGLE_TID_RC 266 -#define WNI_CFG_RRM_ENABLED 267 -#define WNI_CFG_RRM_OPERATING_CHAN_MAX 268 -#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX 269 -#define WNI_CFG_TX_PWR_CTRL_ENABLE 270 -#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 271 -#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 272 -#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 273 -#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 274 -#define WNI_CFG_TELE_BCN_WAKEUP_EN 275 -#define WNI_CFG_TELE_BCN_TRANS_LI 276 -#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 277 -#define WNI_CFG_TELE_BCN_MAX_LI 278 -#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 279 -#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 280 -#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 281 -#define WNI_CFG_ASSOC_STA_LIMIT 282 -#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 283 -#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 284 -#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 285 -#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 286 -#define WNI_CFG_ENABLE_CLOSE_LOOP 287 -#define WNI_CFG_ENABLE_LTE_COEX 288 -#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 289 -#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 290 -#define WNI_CFG_ENABLE_MC_ADDR_LIST 291 -#define WNI_CFG_ENABLE_UC_FILTER 292 -#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 293 -#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 294 -#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 295 -#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 296 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC 228 +#define WNI_CFG_BG_SCAN_CHANNEL_LIST 229 +#define WNI_CFG_MAX_MEDIUM_TIME 230 +#define WNI_CFG_MAX_MPDUS_IN_AMPDU 231 +#define WNI_CFG_IBSS_AUTO_BSSID 232 +#define WNI_CFG_PROBE_REQ_ADDNIE_FLAG 233 +#define WNI_CFG_PROBE_REQ_ADDNIE_DATA 234 +#define WNI_CFG_PROBE_RSP_ADDNIE_FLAG 235 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA1 236 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA2 237 +#define WNI_CFG_PROBE_RSP_ADDNIE_DATA3 238 +#define WNI_CFG_ASSOC_RSP_ADDNIE_FLAG 239 +#define WNI_CFG_ASSOC_RSP_ADDNIE_DATA 240 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_FLAG 241 +#define WNI_CFG_PROBE_REQ_ADDNP2PIE_DATA 242 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_FLAG 243 +#define WNI_CFG_PROBE_RSP_BCN_ADDNIE_DATA 244 +#define WNI_CFG_WPS_ENABLE 245 +#define WNI_CFG_WPS_STATE 246 +#define WNI_CFG_WPS_PROBE_REQ_FLAG 247 +#define WNI_CFG_WPS_VERSION 248 +#define WNI_CFG_WPS_REQUEST_TYPE 249 +#define WNI_CFG_WPS_CFG_METHOD 250 +#define WNI_CFG_WPS_UUID 251 +#define WNI_CFG_WPS_PRIMARY_DEVICE_CATEGORY 252 +#define WNI_CFG_WPS_PIMARY_DEVICE_OUI 253 +#define WNI_CFG_WPS_DEVICE_SUB_CATEGORY 254 +#define WNI_CFG_WPS_ASSOCIATION_STATE 255 +#define WNI_CFG_WPS_CONFIGURATION_ERROR 256 +#define WNI_CFG_WPS_DEVICE_PASSWORD_ID 257 +#define WNI_CFG_WPS_ASSOC_METHOD 258 +#define WNI_CFG_LOW_GAIN_OVERRIDE 259 +#define WNI_CFG_ENABLE_PHY_AGC_LISTEN_MODE 260 +#define WNI_CFG_RPE_POLLING_THRESHOLD 261 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC0_REG 262 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC1_REG 263 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC2_REG 264 +#define WNI_CFG_RPE_AGING_THRESHOLD_FOR_AC3_REG 265 +#define WNI_CFG_NO_OF_ONCHIP_REORDER_SESSIONS 266 +#define WNI_CFG_SINGLE_TID_RC 267 +#define WNI_CFG_RRM_ENABLED 268 +#define WNI_CFG_RRM_OPERATING_CHAN_MAX 269 +#define WNI_CFG_RRM_NON_OPERATING_CHAN_MAX 270 +#define WNI_CFG_TX_PWR_CTRL_ENABLE 271 +#define WNI_CFG_MCAST_BCAST_FILTER_SETTING 272 +#define WNI_CFG_BTC_DHCP_BT_SLOTS_TO_BLOCK 273 +#define WNI_CFG_DYNAMIC_PS_POLL_VALUE 274 +#define WNI_CFG_PS_NULLDATA_AP_RESP_TIMEOUT 275 +#define WNI_CFG_TELE_BCN_WAKEUP_EN 276 +#define WNI_CFG_TELE_BCN_TRANS_LI 277 +#define WNI_CFG_TELE_BCN_TRANS_LI_IDLE_BCNS 278 +#define WNI_CFG_TELE_BCN_MAX_LI 279 +#define WNI_CFG_TELE_BCN_MAX_LI_IDLE_BCNS 280 +#define WNI_CFG_BTC_A2DP_DHCP_BT_SUB_INTERVALS 281 +#define WNI_CFG_INFRA_STA_KEEP_ALIVE_PERIOD 282 +#define WNI_CFG_ASSOC_STA_LIMIT 283 +#define WNI_CFG_SAP_CHANNEL_SELECT_START_CHANNEL 284 +#define WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL 285 +#define WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND 286 +#define WNI_CFG_AP_DATA_AVAIL_POLL_PERIOD 287 +#define WNI_CFG_ENABLE_CLOSE_LOOP 288 +#define WNI_CFG_ENABLE_LTE_COEX 289 +#define WNI_CFG_AP_KEEP_ALIVE_TIMEOUT 290 +#define WNI_CFG_GO_KEEP_ALIVE_TIMEOUT 291 +#define WNI_CFG_ENABLE_MC_ADDR_LIST 292 +#define WNI_CFG_ENABLE_UC_FILTER 293 +#define WNI_CFG_ENABLE_LPWR_IMG_TRANSITION 294 +#define WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED 295 +#define WNI_CFG_DISABLE_LDPC_WITH_TXBF_AP 296 +#define WNI_CFG_AP_LINK_MONITOR_TIMEOUT 297 +#define WNI_CFG_RA_FILTER_ENABLE 298 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL 299 /* * String parameter lengths @@ -1367,6 +1370,10 @@ #define WNI_CFG_ADDBA_REQ_DECLINE_STAMAX 255 #define WNI_CFG_ADDBA_REQ_DECLINE_STADEF 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMIN 0 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STAMAX 1 +#define WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC_STADEF 0 + #define WNI_CFG_MAX_MEDIUM_TIME_STAMIN 0 #define WNI_CFG_MAX_MEDIUM_TIME_STAMAX 65535 #define WNI_CFG_MAX_MEDIUM_TIME_STADEF 2048 @@ -1610,8 +1617,16 @@ #define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STAMAX 255 #define WNI_CFG_AP_LINK_MONITOR_TIMEOUT_STADEF 3 -#define CFG_PARAM_MAX_NUM 297 -#define CFG_STA_IBUF_MAX_SIZE 231 +#define WNI_CFG_RA_FILTER_ENABLE_STAMIN 0 +#define WNI_CFG_RA_FILTER_ENABLE_STAMAX 1 +#define WNI_CFG_RA_FILTER_ENABLE_STADEF 1 + +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STAMIN 0 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STAMAX 60 +#define WNI_CFG_RA_RATE_LIMIT_INTERVAL_STADEF 60 + +#define CFG_PARAM_MAX_NUM 300 +#define CFG_STA_IBUF_MAX_SIZE 234 #define CFG_STA_SBUF_MAX_SIZE 3388 #define CFG_SEM_MAX_NUM 19 diff --git a/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c b/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c index 14b78a4c02f..86fe42c46a3 100644 --- a/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c +++ b/drivers/staging/prima/CORE/MAC/src/cfg/cfgApi.c @@ -74,12 +74,22 @@ static void Notify(tpAniSirGlobal, tANI_U16, tANI_U32); // --------------------------------------------------------------------- tANI_U32 cfgNeedRestart(tpAniSirGlobal pMac, tANI_U16 cfgId) { + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return 0; + } return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RESTART) ; } // --------------------------------------------------------------------- tANI_U32 cfgNeedReload(tpAniSirGlobal pMac, tANI_U16 cfgId) { + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return 0; + } return !!(pMac->cfg.gCfgEntry[cfgId].control & CFG_CTL_RELOAD) ; } @@ -184,6 +194,12 @@ cfgSetInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 value) return eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -259,6 +275,12 @@ cfgCheckValid(tpAniSirGlobal pMac, tANI_U16 cfgId) return(eSIR_CFG_INVALID_ID); } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; // Check if parameter is valid @@ -306,6 +328,12 @@ wlan_cfgGetInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pValue) return retVal; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -370,6 +398,12 @@ cfgIncrementInt(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 value) retVal = eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -468,6 +502,12 @@ cfgSetStrNotify(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U8 *pStr, return eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -648,6 +688,12 @@ wlan_cfgGetStrMaxLen(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pLength) retVal = eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; @@ -709,6 +755,12 @@ wlan_cfgGetStrLen(tpAniSirGlobal pMac, tANI_U16 cfgId, tANI_U32 *pLength) retVal = eSIR_CFG_INVALID_ID; } + if (!pMac->cfg.gCfgEntry) + { + PELOGE(cfgLog(pMac, LOGE, FL("gCfgEntry is NULL"));) + return eSIR_CFG_INVALID_ID; + } + control = pMac->cfg.gCfgEntry[cfgId].control; index = control & CFG_BUF_INDX_MASK; retVal = eSIR_SUCCESS; diff --git a/drivers/staging/prima/CORE/MAC/src/cfg/cfgParamName.c b/drivers/staging/prima/CORE/MAC/src/cfg/cfgParamName.c index c0db1a067af..81a01e6b482 100644 --- a/drivers/staging/prima/CORE/MAC/src/cfg/cfgParamName.c +++ b/drivers/staging/prima/CORE/MAC/src/cfg/cfgParamName.c @@ -350,6 +350,8 @@ unsigned char *gCfgParamName[] = { (unsigned char *)"ENABLE_MCC_ADAPTIVE_SCHED", (unsigned char *)"DISABLE_LDPC_WITH_TXBF_AP", (unsigned char *)"AP_LINK_MONITOR_TIMEOUT", + (unsigned char *)"RA_FILTER_ENABLE", + (unsigned char *)"RA_RATE_LIMIT_INTERVAL", }; diff --git a/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt b/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt index 463bdd08b44..e32ca7bcce4 100644 --- a/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt +++ b/drivers/staging/prima/CORE/MAC/src/cfg/cfgUtil/cfg.txt @@ -1,4 +1,4 @@ -/* + * * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. @@ -17,7 +17,7 @@ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. - */ + * * Copyright (c) 2012, The Linux Foundation. All rights reserved. * * Previously licensed under the ISC license by Qualcomm Atheros, Inc. @@ -3459,6 +3459,19 @@ V RW NP RESTART LIM 0 0xff 0 +* +* Delete all Rx BA sessions in 2.4 GHz +* when BTC requests to disable agg. +* +WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC I 4 7 +V RW NP +LIM +0 1 0 +V RW NP +LIM +0 1 0 + + * * Valid Channel List * @@ -4485,3 +4498,27 @@ HAL V RW NP HAL 1 255 3 + +* RA filter enable/disable +* +WNI_CFG_RA_FILTER_ENABLE I 4 7 +V RW NP +HAL +0 1 1 +V RW NP +HAL +0 1 1 +* +* + +* RA filter rate interval +* +WNI_CFG_RA_RATE_LIMIT_INTERVAL I 4 7 +V RW NP +HAL +0 60 60 +V RW NP +HAL +0 60 60 +* +* diff --git a/drivers/staging/prima/CORE/MAC/src/include/dot11f.h b/drivers/staging/prima/CORE/MAC/src/include/dot11f.h index 7bedcd4d5a0..c367f5290c2 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/dot11f.h +++ b/drivers/staging/prima/CORE/MAC/src/include/dot11f.h @@ -52,7 +52,7 @@ * * * This file was automatically generated by 'framesc' - * Tue Mar 19 13:37:40 2013 from the following file(s): + * Fri Jun 7 17:41:21 2013 from the following file(s): * * dot11f.frms * @@ -549,16 +549,6 @@ void dot11fUnpackFfTimeStamp(tpAniSirGlobal, tANI_U8*, tDot11fFfTimeStamp*); void dot11fPackFfTimeStamp(tpAniSirGlobal, tDot11fFfTimeStamp*, tANI_U8*); -typedef struct sDot11fFfTransactionId { - tANI_U8 transId[2]; -} tDot11fFfTransactionId; - -#define DOT11F_FF_TRANSACTIONID_LEN ( 2 ) - -void dot11fUnpackFfTransactionId(tpAniSirGlobal, tANI_U8*, tDot11fFfTransactionId*); - -void dot11fPackFfTransactionId(tpAniSirGlobal, tDot11fFfTransactionId*, tANI_U8*); - typedef struct sDot11fFfTxAntennaId { tANI_U8 antennaId; } tDot11fFfTxAntennaId; @@ -1848,6 +1838,34 @@ tANI_U32 dot11fPackIeHCF(tpAniSirGlobal, tDot11fIEHCF*, tANI_U8*, tANI_U32, tANI tANI_U32 dot11fGetPackedIEHCF(tpAniSirGlobal, tDot11fIEHCF*, tANI_U32*); +#ifdef __cplusplus +}; /* End extern "C". */ +#endif /* C++ */ +// EID 4 (0x04) +typedef struct sDot11fIEIGTK { + tANI_U8 present; + tANI_U8 keyID[2]; + tANI_U8 IPN[6]; + tANI_U8 keyLength; + tANI_U8 key[24]; +} tDot11fIEIGTK; + +#define DOT11F_EID_IGTK ( 4 ) + +// N.B. These #defines do *not* include the EID & length +#define DOT11F_IE_IGTK_MIN_LEN ( 33 ) + +#define DOT11F_IE_IGTK_MAX_LEN ( 33 ) + +#ifdef __cplusplus +extern "C" { +#endif /* C++ */ +tANI_U32 dot11fUnpackIeIGTK(tpAniSirGlobal, tANI_U8*,tANI_U8, tDot11fIEIGTK*); + +tANI_U32 dot11fPackIeIGTK(tpAniSirGlobal, tDot11fIEIGTK*, tANI_U8*, tANI_U32, tANI_U32*); + +tANI_U32 dot11fGetPackedIEIGTK(tpAniSirGlobal, tDot11fIEIGTK*, tANI_U32*); + #ifdef __cplusplus }; /* End extern "C". */ #endif /* C++ */ @@ -3702,6 +3720,7 @@ typedef struct sDot11fIEFTInfo { tDot11fIER1KH_ID R1KH_ID; tDot11fIEGTK GTK; tDot11fIER0KH_ID R0KH_ID; + tDot11fIEIGTK IGTK; } tDot11fIEFTInfo; #define DOT11F_EID_FTINFO ( 55 ) @@ -3709,7 +3728,7 @@ typedef struct sDot11fIEFTInfo { // N.B. These #defines do *not* include the EID & length #define DOT11F_IE_FTINFO_MIN_LEN ( 82 ) -#define DOT11F_IE_FTINFO_MAX_LEN ( 185 ) +#define DOT11F_IE_FTINFO_MAX_LEN ( 220 ) #ifdef __cplusplus extern "C" { @@ -4884,11 +4903,11 @@ tANI_U32 dot11fGetPackedIEQBSSLoad(tpAniSirGlobal, tDot11fIEQBSSLoad*, tANI_U32* // EID 46 (0x2e) typedef struct sDot11fIEQOSCapsAp { tANI_U8 present; - tANI_U8 reserved: 1; - tANI_U8 txopreq: 1; - tANI_U8 qreq: 1; - tANI_U8 qack: 1; tANI_U8 count: 4; + tANI_U8 qack: 1; + tANI_U8 qreq: 1; + tANI_U8 txopreq: 1; + tANI_U8 reserved: 1; } tDot11fIEQOSCapsAp; #define DOT11F_EID_QOSCAPSAP ( 46 ) @@ -4913,13 +4932,13 @@ tANI_U32 dot11fGetPackedIEQOSCapsAp(tpAniSirGlobal, tDot11fIEQOSCapsAp*, tANI_U3 // EID 46 (0x2e) typedef struct sDot11fIEQOSCapsStation { tANI_U8 present; - tANI_U8 more_data_ack: 1; - tANI_U8 max_sp_length: 2; - tANI_U8 qack: 1; - tANI_U8 acbe_uapsd: 1; - tANI_U8 acbk_uapsd: 1; - tANI_U8 acvi_uapsd: 1; tANI_U8 acvo_uapsd: 1; + tANI_U8 acvi_uapsd: 1; + tANI_U8 acbk_uapsd: 1; + tANI_U8 acbe_uapsd: 1; + tANI_U8 qack: 1; + tANI_U8 max_sp_length: 2; + tANI_U8 more_data_ack: 1; } tDot11fIEQOSCapsStation; #define DOT11F_EID_QOSCAPSSTATION ( 46 ) @@ -7243,26 +7262,6 @@ tANI_U32 dot11fGetPackedSMPowerSaveSize(tpAniSirGlobal pCtx, tDot11fSMPowerSave } /* End extern "C". */ #endif /* C++ */ -typedef struct sDot11fSaQueryRsp{ - tDot11fFfCategory Category; - tDot11fFfAction Action; - tDot11fFfTransactionId TransactionId; -} tDot11fSaQueryRsp; - -#define DOT11F_SAQUERYRSP ( 44 ) - -#ifdef __cplusplus -extern "C" { -#endif /* C++ */ - -tANI_U32 dot11fUnpackSaQueryRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSaQueryRsp *pFrm); -tANI_U32 dot11fPackSaQueryRsp(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed); -tANI_U32 dot11fGetPackedSaQueryRspSize(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U32 *pnNeeded); - -#ifdef __cplusplus -} /* End extern "C". */ -#endif /* C++ */ - typedef struct sDot11fTDLSDisReq{ tDot11fFfCategory Category; tDot11fFfAction Action; @@ -7270,7 +7269,7 @@ typedef struct sDot11fTDLSDisReq{ tDot11fIELinkIdentifier LinkIdentifier; } tDot11fTDLSDisReq; -#define DOT11F_TDLSDISREQ ( 45 ) +#define DOT11F_TDLSDISREQ ( 44 ) #ifdef __cplusplus extern "C" { @@ -7302,7 +7301,7 @@ typedef struct sDot11fTDLSDisRsp{ tDot11fIEVHTCaps VHTCaps; } tDot11fTDLSDisRsp; -#define DOT11F_TDLSDISRSP ( 46 ) +#define DOT11F_TDLSDISRSP ( 45 ) #ifdef __cplusplus extern "C" { @@ -7325,7 +7324,7 @@ typedef struct sDot11fTDLSPeerTrafficInd{ tDot11fIEPUBufferStatus PUBufferStatus; } tDot11fTDLSPeerTrafficInd; -#define DOT11F_TDLSPEERTRAFFICIND ( 47 ) +#define DOT11F_TDLSPEERTRAFFICIND ( 46 ) #ifdef __cplusplus extern "C" { @@ -7346,7 +7345,7 @@ typedef struct sDot11fTDLSPeerTrafficRsp{ tDot11fIELinkIdentifier LinkIdentifier; } tDot11fTDLSPeerTrafficRsp; -#define DOT11F_TDLSPEERTRAFFICRSP ( 48 ) +#define DOT11F_TDLSPEERTRAFFICRSP ( 47 ) #ifdef __cplusplus extern "C" { @@ -7373,9 +7372,10 @@ typedef struct sDot11fTDLSSetupCnf{ tDot11fIELinkIdentifier LinkIdentifier; tDot11fIEWMMInfoStation WMMInfoStation; tDot11fIEVHTOperation VHTOperation; + tDot11fIEOperatingMode OperatingMode; } tDot11fTDLSSetupCnf; -#define DOT11F_TDLSSETUPCNF ( 49 ) +#define DOT11F_TDLSSETUPCNF ( 48 ) #ifdef __cplusplus extern "C" { @@ -7411,7 +7411,7 @@ typedef struct sDot11fTDLSSetupReq{ tDot11fIEVHTCaps VHTCaps; } tDot11fTDLSSetupReq; -#define DOT11F_TDLSSETUPREQ ( 50 ) +#define DOT11F_TDLSSETUPREQ ( 49 ) #ifdef __cplusplus extern "C" { @@ -7446,9 +7446,10 @@ typedef struct sDot11fTDLSSetupRsp{ tDot11fIEWMMInfoStation WMMInfoStation; tDot11fIEAID AID; tDot11fIEVHTCaps VHTCaps; + tDot11fIEOperatingMode OperatingMode; } tDot11fTDLSSetupRsp; -#define DOT11F_TDLSSETUPRSP ( 51 ) +#define DOT11F_TDLSSETUPRSP ( 50 ) #ifdef __cplusplus extern "C" { @@ -7470,7 +7471,7 @@ typedef struct sDot11fTDLSTeardown{ tDot11fIELinkIdentifier LinkIdentifier; } tDot11fTDLSTeardown; -#define DOT11F_TDLSTEARDOWN ( 52 ) +#define DOT11F_TDLSTEARDOWN ( 51 ) #ifdef __cplusplus extern "C" { @@ -7491,7 +7492,7 @@ typedef struct sDot11fTPCReport{ tDot11fIETPCReport TPCReport; } tDot11fTPCReport; -#define DOT11F_TPCREPORT ( 53 ) +#define DOT11F_TPCREPORT ( 52 ) #ifdef __cplusplus extern "C" { @@ -7512,7 +7513,7 @@ typedef struct sDot11fTPCRequest{ tDot11fIETPCRequest TPCRequest; } tDot11fTPCRequest; -#define DOT11F_TPCREQUEST ( 54 ) +#define DOT11F_TPCREQUEST ( 53 ) #ifdef __cplusplus extern "C" { @@ -7535,7 +7536,7 @@ typedef struct sDot11fWMMAddTSRequest{ tDot11fIECCXTrafStrmRateSet CCXTrafStrmRateSet; } tDot11fWMMAddTSRequest; -#define DOT11F_WMMADDTSREQUEST ( 55 ) +#define DOT11F_WMMADDTSREQUEST ( 54 ) #ifdef __cplusplus extern "C" { @@ -7558,7 +7559,7 @@ typedef struct sDot11fWMMAddTSResponse{ tDot11fIECCXTrafStrmMet CCXTrafStrmMet; } tDot11fWMMAddTSResponse; -#define DOT11F_WMMADDTSRESPONSE ( 56 ) +#define DOT11F_WMMADDTSRESPONSE ( 55 ) #ifdef __cplusplus extern "C" { @@ -7580,7 +7581,7 @@ typedef struct sDot11fWMMDelTS{ tDot11fIEWMMTSPEC WMMTSPEC; } tDot11fWMMDelTS; -#define DOT11F_WMMDELTS ( 57 ) +#define DOT11F_WMMDELTS ( 56 ) #ifdef __cplusplus extern "C" { diff --git a/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h b/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h index d1e01073d44..91bb281d2dc 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h +++ b/drivers/staging/prima/CORE/MAC/src/include/dphGlobal.h @@ -387,7 +387,9 @@ typedef struct sDphHashNode tANI_U8 fAniCount:1; - tANI_U8 rmfEnabled:1; + + tANI_U8 rsvd:1; + /// Fragmentation size diff --git a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h index 287fbb51fdf..42144cf372b 100644 --- a/drivers/staging/prima/CORE/MAC/src/include/sirParams.h +++ b/drivers/staging/prima/CORE/MAC/src/include/sirParams.h @@ -93,7 +93,11 @@ typedef enum { SAP32STA = 5, TDLS = 6, P2P_GO_NOA_DECOUPLE_INIT_SCAN = 7, - WLANACTIVE_OFFLOAD = 8 + WLANACTIVE_OFFLOAD = 8, +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + WLAN_ROAM_SCAN_OFFLOAD = 23, +#endif + EXTENDED_NSOFFLOAD_SLOT = 24, //MAX_FEATURE_SUPPORTED = 128 } placeHolderInCapBitmap; @@ -553,16 +557,14 @@ typedef struct sSirMbMsgP2p #define SIR_HAL_TDLS_LINK_ESTABLISH (SIR_HAL_ITC_MSG_TYPES_BEGIN + 189) #define SIR_HAL_TDLS_LINK_TEARDOWN (SIR_HAL_ITC_MSG_TYPES_BEGIN + 190) #endif - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define SIR_HAL_ROAM_SCAN_OFFLOAD_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 191) +#endif #define SIR_HAL_GET_ROAM_RSSI_REQ (SIR_HAL_ITC_MSG_TYPES_BEGIN + 193) #define SIR_HAL_GET_ROAM_RSSI_RSP (SIR_HAL_ITC_MSG_TYPES_BEGIN + 194) #define SIR_HAL_TRAFFIC_STATS_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 195) -#ifdef WLAN_FEATURE_11W -#define SIR_HAL_EXCLUDE_UNENCRYPTED_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 196) -#endif - #define SIR_HAL_MSG_TYPES_END (SIR_HAL_ITC_MSG_TYPES_BEGIN + 0xFF) // CFG message types #define SIR_CFG_MSG_TYPES_BEGIN (SIR_CFG_MODULE_ID << 8) diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h index 2b34866075e..4912087f328 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limFTDefs.h @@ -54,6 +54,7 @@ #include +#include "halMsgApi.h" /*-------------------------------------------------------------------------- Preprocessor definitions and constants @@ -66,8 +67,8 @@ /*-------------------------------------------------------------------------- Type declarations ------------------------------------------------------------------------*/ -/*-------------------------------------------------------------------------- - FT Pre Auth Req SME<->PE +/*-------------------------------------------------------------------------- + FT Pre Auth Req SME<->PE ------------------------------------------------------------------------*/ typedef struct sSirFTPreAuthReq { @@ -84,7 +85,7 @@ typedef struct sSirFTPreAuthReq } tSirFTPreAuthReq, *tpSirFTPreAuthReq; /*------------------------------------------------------------------------- - FT Pre Auth Rsp PE<->SME + FT Pre Auth Rsp PE<->SME ------------------------------------------------------------------------*/ typedef struct sSirFTPreAuthRsp { @@ -99,29 +100,39 @@ typedef struct sSirFTPreAuthRsp tANI_U8 ric_ies[MAX_FTIE_SIZE]; } tSirFTPreAuthRsp, *tpSirFTPreAuthRsp; -/*-------------------------------------------------------------------------- - FT Pre Auth Req SME<->PE +/*-------------------------------------------------------------------------- + FT Pre Auth Rsp Key SME<->PE ------------------------------------------------------------------------*/ typedef struct sSirFTUpdateKeyInfo { - tANI_U16 messageType; - tANI_U16 length; - tSirKeyMaterial keyMaterial; + tANI_U16 messageType; + tANI_U16 length; + tSirMacAddr bssId; + tSirKeyMaterial keyMaterial; } tSirFTUpdateKeyInfo, *tpSirFTUpdateKeyInfo; +/*-------------------------------------------------------------------------- + FT Pre Auth Rsp Key SME<->PE + ------------------------------------------------------------------------*/ +typedef struct sSirFTPreAuthKeyInfo +{ + tANI_U8 extSetStaKeyParamValid; //Ext Bss Config Msg if set + tSetStaKeyParams extSetStaKeyParam; //SetStaKeyParams for ext bss msg +} tSirFTPreAuthKeyInfo, *tpSirFTPreAuthKeyInfo; + /*------------------------------------------------------------------------- - Global FT Information + Global FT Information ------------------------------------------------------------------------*/ typedef struct sFTPEContext { tpSirFTPreAuthReq pFTPreAuthReq; // Saved FT Pre Auth Req - void *psavedsessionEntry; + void *psavedsessionEntry; tSirRetStatus ftPreAuthStatus; tANI_U16 saved_auth_rsp_length; tANI_U8 saved_auth_rsp[MAX_FTIE_SIZE]; - + tSirFTPreAuthKeyInfo *pPreAuthKeyInfo; // Items created for the new FT, session - void *pftSessionEntry; // Saved session created for pre-auth + void *pftSessionEntry; // Saved session created for pre-auth void *pAddBssReq; // Save add bss req. void *pAddStaReq; // Save add sta req. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limGlobal.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limGlobal.h index 4a608f55f6e..7c2b6d9d455 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limGlobal.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limGlobal.h @@ -115,7 +115,7 @@ typedef enum eLimSystemRole eLIM_BT_AMP_AP_ROLE, eLIM_P2P_DEVICE_ROLE, eLIM_P2P_DEVICE_GO, - eLIM_P2P_DEVICE_CLINET + eLIM_P2P_DEVICE_CLIENT } tLimSystemRole; /** diff --git a/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h b/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h index 570c35bbc57..81f240d9fe5 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/include/limSession.h @@ -266,9 +266,7 @@ typedef struct sPESession // Added to Support BT-AMP tANI_U8 limWsmEnabled:1; //WSM tANI_U8 limHcfEnabled:1; tANI_U8 lim11dEnabled:1; -#ifdef WLAN_FEATURE_11W - tANI_U8 limRmfEnabled:1; //11W -#endif + tANI_U32 lim11hEnable; tPowerdBm maxTxPower; //MIN (Regulatory and local power constraint) @@ -337,7 +335,7 @@ typedef struct sPESession // Added to Support BT-AMP /*Flag to Track Status/Indicate HBFailure on this session */ tANI_BOOLEAN LimHBFailureStatus; tANI_U32 gLimPhyMode; - + tANI_U8 amsduSupportedInBA; tANI_U8 txLdpcIniFeatureEnabled; /** * Following is the place holder for free peer index pool. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c index 1bf6733ac04..e458129b581 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limApi.c @@ -119,6 +119,14 @@ static void __limInitScanVars(tpAniSirGlobal pMac) palZeroMemory(pMac->hHdd, pMac->lim.gLimCachedScanHashTable, sizeof(pMac->lim.gLimCachedScanHashTable)); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + + pMac->lim.gLimMlmLfrScanResultLength = 0; + pMac->lim.gLimSmeLfrScanResultLength = 0; + + palZeroMemory(pMac->hHdd, pMac->lim.gLimCachedLfrScanHashTable, + sizeof(pMac->lim.gLimCachedLfrScanHashTable)); +#endif pMac->lim.gLimBackgroundScanChannelId = 0; pMac->lim.gLimBackgroundScanStarted = 0; pMac->lim.gLimRestoreCBNumScanInterval = LIM_RESTORE_CB_NUM_SCAN_INTERVAL_DEFAULT; @@ -643,6 +651,9 @@ tSirRetStatus limStart(tpAniSirGlobal pMac) // By default return unique scan results pMac->lim.gLimReturnUniqueResults = true; pMac->lim.gLimSmeScanResultLength = 0; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->lim.gLimSmeLfrScanResultLength = 0; +#endif } else { @@ -2155,6 +2166,12 @@ tMgmtFrmDropReason limIsPktCandidateForDrop(tpAniSirGlobal pMac, tANI_U8 *pRxPac { return eMGMT_DROP_NO_DROP; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + else if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) || WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) + { + return eMGMT_DROP_NO_DROP; + } +#endif else if (WDA_IS_RX_IN_SCAN(pRxPacketInfo)) { return eMGMT_DROP_SCAN_MODE_FRAME; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c index e92533fc981..51ffb2a8a02 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.c @@ -307,7 +307,7 @@ limCheckRxBasicRates(tpAniSirGlobal pMac, tSirMacRateSet rxRateSet,tpPESession p pRateSet->numRates = psessionEntry->rateSet.numRates; // Extract BSS basic rateset from operational rateset - for (i = 0, j = 0; i < pRateSet->numRates; i++) + for (i = 0, j = 0; ((i < pRateSet->numRates) && (i < SIR_MAC_RATESET_EID_MAX)) ; i++) { if ((pRateSet->rate[i] & 0x80) == 0x80) { @@ -323,7 +323,7 @@ limCheckRxBasicRates(tpAniSirGlobal pMac, tSirMacRateSet rxRateSet,tpPESession p for (k = 0; k < j; k++) { match = 0; - for (i = 0; i < rxRateSet.numRates; i++) + for (i = 0; ((i < rxRateSet.numRates) && (i < SIR_MAC_RATESET_EID_MAX)); i++) { if ((rxRateSet.rate[i] | 0x80) == basicRate.rate[k]) match = 1; @@ -1627,68 +1627,40 @@ limPopulateOwnRateSet(tpAniSirGlobal pMac, { tSirMacRateSet tempRateSet; tSirMacRateSet tempRateSet2; - tANI_U32 i,j,val,min,isArate; + tANI_U32 i,j,val,min,isArate; tANI_U32 phyMode = 0; - tANI_U32 selfStaDot11Mode=0; + isArate = 0; wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &selfStaDot11Mode); limGetPhyMode(pMac, &phyMode, psessionEntry); - // Get own rate set - #if 0 - val = WNI_CFG_OPERATIONAL_RATE_SET_LEN; - if (wlan_cfgGetStr(pMac, WNI_CFG_OPERATIONAL_RATE_SET, - (tANI_U8 *) &tempRateSet.rate, - &val) != eSIR_SUCCESS) - { - /// Could not get rateset from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve rateset")); - } - #endif // TO SUPPORT BT-AMP - - /* copy operational rate set from psessionEntry */ - if ( psessionEntry->rateSet.numRates < SIR_MAC_RATESET_EID_MAX ) + /* Include 11b rates only when the device configured in + auto, 11a/b/g or 11b_only */ + if ( (selfStaDot11Mode == WNI_CFG_DOT11_MODE_ALL) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11A) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11AC) || + (selfStaDot11Mode == WNI_CFG_DOT11_MODE_11B) ) { - palCopyMemory(pMac->hHdd,(tANI_U8 *)tempRateSet.rate,(tANI_U8*)(psessionEntry->rateSet.rate), psessionEntry->rateSet.numRates); - tempRateSet.numRates = psessionEntry->rateSet.numRates; + val = WNI_CFG_SUPPORTED_RATES_11B_LEN; + wlan_cfgGetStr( pMac, WNI_CFG_SUPPORTED_RATES_11B, + (tANI_U8 *)&tempRateSet.rate, &val ); + tempRateSet.numRates = (tANI_U8) val; } else - { - limLog(pMac, LOGE, FL("more than SIR_MAC_RATESET_EID_MAX rates\n")); - goto error; - } + tempRateSet.numRates = 0; - if (phyMode == WNI_CFG_PHY_MODE_11G) + /* Include 11a rates when the device configured in non-11b mode */ + if (!IS_DOT11_MODE_11B(selfStaDot11Mode)) { - - // get own extended rate set - #if 0 - val = WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET_LEN; - if (wlan_cfgGetStr(pMac, WNI_CFG_EXTENDED_OPERATIONAL_RATE_SET, - (tANI_U8 *) &tempRateSet2.rate, - &val) != eSIR_SUCCESS) - { - /// Could not get extended rateset from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve extended rateset")); - } + val = WNI_CFG_SUPPORTED_RATES_11A_LEN; + wlan_cfgGetStr( pMac, WNI_CFG_SUPPORTED_RATES_11A, + (tANI_U8 *)&tempRateSet2.rate, &val ); tempRateSet2.numRates = (tANI_U8) val; - #endif - if (psessionEntry->extRateSet.numRates < SIR_MAC_RATESET_EID_MAX) - { - palCopyMemory(pMac->hHdd,(tANI_U8 *)tempRateSet2.rate, (tANI_U8*)(psessionEntry->extRateSet.rate), psessionEntry->extRateSet.numRates); - tempRateSet2.numRates = psessionEntry->extRateSet.numRates; - } - else { - limLog(pMac, LOGE, FL("psessionEntry->extRateSet.numRates more than SIR_MAC_RATESET_EID_MAX rates\n")); - goto error; - } - } else - tempRateSet2.numRates = 0; - + tempRateSet2.numRates = 0; if ((tempRateSet.numRates + tempRateSet2.numRates) > 12) { @@ -1698,7 +1670,6 @@ limPopulateOwnRateSet(tpAniSirGlobal pMac, goto error; } - //copy all rates in tempRateSet, there are 12 rates max for (i = 0;i < tempRateSet2.numRates; i++) tempRateSet.rate[i + tempRateSet.numRates] = tempRateSet2.rate[i]; @@ -1990,8 +1961,11 @@ limPopulateMatchingRateSet(tpAniSirGlobal pMac, } else { - for(j = 0; ((j < pExtRateSet->numRates) && (j < SIR_MAC_RATESET_EID_MAX) && ((i+j) < SIR_MAC_RATESET_EID_MAX)); j++) + for(j = 0; ((j < pExtRateSet->numRates) && (j < SIR_MAC_RATESET_EID_MAX) + && ((i+j) < SIR_MAC_RATESET_EID_MAX)); j++) + { tempRateSet.rate[i+j] = pExtRateSet->rate[j]; + } tempRateSet.numRates += pExtRateSet->numRates; } @@ -2002,9 +1976,9 @@ limPopulateMatchingRateSet(tpAniSirGlobal pMac, tANI_U8 aRateIndex = 0; tANI_U8 bRateIndex = 0; palZeroMemory( pMac->hHdd, (tANI_U8 *) rates, sizeof(tSirSupportedRates)); - for(i = 0;(i < tempRateSet2.numRates && i < SIR_MAC_RATESET_EID_MAX ); i++) + for(i = 0; (i < tempRateSet2.numRates && i < SIR_MAC_RATESET_EID_MAX ); i++) { - for(j = 0;(j < tempRateSet.numRates && j < SIR_MAC_RATESET_EID_MAX); j++) + for(j = 0; (j < tempRateSet.numRates && j < SIR_MAC_RATESET_EID_MAX); j++) { if ((tempRateSet2.rate[i] & 0x7F) == (tempRateSet.rate[j] & 0x7F)) @@ -2012,10 +1986,14 @@ limPopulateMatchingRateSet(tpAniSirGlobal pMac, if (sirIsArate(tempRateSet2.rate[i] & 0x7f)) { isArate=1; - rates->llaRates[aRateIndex++] = tempRateSet2.rate[i]; + if (aRateIndex < SIR_NUM_11A_RATES) + rates->llaRates[aRateIndex++] = tempRateSet2.rate[i]; } else - rates->llbRates[bRateIndex++] = tempRateSet2.rate[i]; + { + if (bRateIndex < SIR_NUM_11B_RATES) + rates->llbRates[bRateIndex++] = tempRateSet2.rate[i]; + } break; } } @@ -3397,24 +3375,14 @@ tSirRetStatus limStaSendAddBss( tpAniSirGlobal pMac, tpSirAssocRsp pAssocRsp, if (VOS_P2P_CLIENT_MODE == psessionEntry->pePersona) { - pAddBssParams->staContext.p2pCapableSta = 1; + pAddBssParams->staContext.p2pCapableSta = 1; } - - pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled || - limIsconnectedOnDFSChannel(bssDescription->channelId); + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; #if defined WLAN_FEATURE_VOWIFI_11R pAddBssParams->extSetStaKeyParamValid = 0; #endif -#ifdef WLAN_FEATURE_11W - if (psessionEntry->limRmfEnabled) - { - pAddBssParams->rmfEnabled = 1; - pAddBssParams->staContext.rmfEnabled = 1; - } -#endif - // Set a new state for MLME if( eLIM_MLM_WT_ASSOC_RSP_STATE == psessionEntry->limMlmState ) psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE; @@ -3689,29 +3657,19 @@ tSirRetStatus limStaSendAddBssPreAssoc( tpAniSirGlobal pMac, tANI_U8 updateEntry pAddBssParams->staContext.sessionId = psessionEntry->peSessionId; pAddBssParams->sessionId = psessionEntry->peSessionId; - - pAddBssParams->halPersona = (tANI_U8)psessionEntry->pePersona; //update persona - pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled || - limIsconnectedOnDFSChannel(bssDescription->channelId); + pAddBssParams->halPersona = (tANI_U8)psessionEntry->pePersona; //update persona + pAddBssParams->bSpectrumMgtEnabled = psessionEntry->spectrumMgtEnabled; #if defined WLAN_FEATURE_VOWIFI_11R pAddBssParams->extSetStaKeyParamValid = 0; #endif -#ifdef WLAN_FEATURE_11W - if (psessionEntry->limRmfEnabled) - { - pAddBssParams->rmfEnabled = 1; - pAddBssParams->staContext.rmfEnabled = 1; - } -#endif - // Set a new state for MLME //pMac->lim.gLimMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE; psessionEntry->limMlmState = eLIM_MLM_WT_ADD_BSS_RSP_PREASSOC_STATE; - + MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); //we need to defer the message until we get the response back from HAL. @@ -3987,49 +3945,3 @@ void limFillRxHighestSupportedRate(tpAniSirGlobal pMac, tANI_U16 *rxHighestRate, return; } - -#ifdef WLAN_FEATURE_11W -/** ------------------------------------------------------------- -\fn limSendSmeUnprotectedMgmtFrameInd -\brief Forwards the unprotected management frame to SME. -\param tpAniSirGlobal pMac -\param frameType - 802.11 frame type -\param frame - frame buffer -\param sessionId - id for the current session -\param psessionEntry - PE session context -\return none - -------------------------------------------------------------*/ -void limSendSmeUnprotectedMgmtFrameInd( - tpAniSirGlobal pMac, tANI_U8 frameType, - tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId, - tpPESession psessionEntry) -{ - tSirMsgQ mmhMsg; - tSirSmeUnprotMgmtFrameInd * pSirSmeMgmtFrame = NULL; - tANI_U16 length; - - length = sizeof(tSirSmeUnprotMgmtFrameInd) + frameLen; - - if (eHAL_STATUS_SUCCESS != - palAllocateMemory(pMac->hHdd, (void **)&pSirSmeMgmtFrame, length)) - { - limLog(pMac, LOGP, - FL("palAllocateMemory failed for tSirSmeUnprotectedMgmtFrameInd")); - return; - } - palZeroMemory(pMac->hHdd, (void*)pSirSmeMgmtFrame, length); - - pSirSmeMgmtFrame->sessionId = sessionId; - pSirSmeMgmtFrame->frameType = frameType; - - vos_mem_copy(pSirSmeMgmtFrame->frameBuf, frame, frameLen); - pSirSmeMgmtFrame->frameLen = frameLen; - - mmhMsg.type = eWNI_SME_UNPROT_MGMT_FRM_IND; - mmhMsg.bodyptr = pSirSmeMgmtFrame; - mmhMsg.bodyval = 0; - - limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); - return; -} -#endif diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h index 915d9c3affe..9a7ba3b5c5f 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limAssocUtils.h @@ -177,10 +177,6 @@ void limFillRxHighestSupportedRate(tpAniSirGlobal pMac, tANI_U16 *rxHighestRate, #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) void limSendRetryReassocReqFrame(tpAniSirGlobal pMac, tLimMlmReassocReq *pMlmReassocReq, tpPESession psessionEntry); #endif -#ifdef WLAN_FEATURE_11W -void limSendSmeUnprotectedMgmtFrameInd(tpAniSirGlobal pMac, tANI_U8 frameType, - tANI_U8 *frame, tANI_U32 frameLen, tANI_U16 sessionId, tpPESession psessionEntry); -#endif #endif /* __LIM_ASSOC_UTILS_H */ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c index 58eed714a2d..f349d66adad 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limFT.c @@ -1,52 +1,31 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ #ifdef WLAN_FEATURE_VOWIFI_11R /**========================================================================= \brief implementation for PE 11r VoWiFi FT Protocol - Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved. + Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved. - Qualcomm Confidential and Proprietary. + Qualcomm Technologies Confidential and Proprietary. ========================================================================*/ @@ -70,6 +49,7 @@ #define LIM_FT_RIC_BA_SSN 1 #define LIM_FT_RIC_BA_DIALOG_TOKEN_TID_0 248 #define LIM_FT_RIC_DESCRIPTOR_RESOURCE_TYPE_BA 1 +#define LIM_FT_RIC_DESCRIPTOR_MAX_VAR_DATA_LEN 255 /*-------------------------------------------------------------------------- Initialize the FT variables. @@ -268,7 +248,16 @@ int limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) // Now we are starting fresh make sure all's cleanup. limFTInit(pMac); - pMac->ft.ftPEContext.ftPreAuthStatus = eSIR_FAILURE; // Can set it only after sending auth + // Can set it only after sending auth + pMac->ft.ftPEContext.ftPreAuthStatus = eSIR_FAILURE; + + if( pMac->ft.ftPEContext.pFTPreAuthReq && + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription) + { + palFreeMemory(pMac->hHdd, + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription); + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } // We need information from the Pre-Auth Req. Lets save that pMac->ft.ftPEContext.pFTPreAuthReq = (tpSirFTPreAuthReq)pMsg->bodyptr; @@ -290,7 +279,13 @@ int limProcessFTPreAuthReq(tpAniSirGlobal pMac, tpSirMsgQ pMsg) limPrintMacAddr( pMac, pMac->ft.ftPEContext.pFTPreAuthReq->currbssId, LOGE ); // Post the FT Pre Auth Response to SME limPostFTPreAuthRsp(pMac, eSIR_FAILURE, NULL, 0, NULL); - pMac->ft.ftPEContext.pFTPreAuthReq = NULL; + if (pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription) + { + palFreeMemory(pMac->hHdd, + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription); + pMac->ft.ftPEContext.pFTPreAuthReq->pbssDescription = NULL; + } + pMac->ft.ftPEContext.pFTPreAuthReq = NULL; return TRUE; } @@ -805,6 +800,8 @@ void limPerformPostFTPreAuthAndChannelChange(tpAniSirGlobal pMac, eHalStatus sta tSirRetStatus limCreateRICBlockAckIE(tpAniSirGlobal pMac, tANI_U8 tid, tCfgTrafficClass *pTrafficClass, tANI_U8 *ric_ies, tANI_U32 *ieLength) { + /* BlockACK + RIC is not supported now, TODO later to support this */ +#if 0 tDot11fIERICDataDesc ricIe; tDot11fFfBAStartingSequenceControl baSsnControl; tDot11fFfAddBAParameterSet baParamSet; @@ -827,23 +824,25 @@ tSirRetStatus limCreateRICBlockAckIE(tpAniSirGlobal pMac, tANI_U8 tid, tCfgTraff vos_mem_copy((v_VOID_t *)&baTimeout, (v_VOID_t *)&pTrafficClass->tuTxBAWaitTimeout, sizeof(baTimeout)); baSsnControl.fragNumber = 0; baSsnControl.ssn = LIM_FT_RIC_BA_SSN; - if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { + if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { dot11fPackFfAddBAParameterSet(pMac, &baParamSet, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]); //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baParamSet, sizeof(tDot11fFfAddBAParameterSet)); ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfAddBAParameterSet); } - - if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { + if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { dot11fPackFfBATimeout(pMac, &baTimeout, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]); //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baTimeout, sizeof(tDot11fFfBATimeout)); ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfBATimeout); } - if ( ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { + if (ricIe.RICDescriptor.num_variableData < sizeof (ricIe.RICDescriptor.variableData)) { dot11fPackFfBAStartingSequenceControl(pMac, &baSsnControl, &ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData]); //vos_mem_copy(&ricIe.RICDescriptor.variableData[ricIe.RICDescriptor.num_variableData], &baSsnControl, sizeof(tDot11fFfBAStartingSequenceControl)); ricIe.RICDescriptor.num_variableData += sizeof(tDot11fFfBAStartingSequenceControl); } return (tSirRetStatus) dot11fPackIeRICDataDesc(pMac, &ricIe, ric_ies, sizeof(tDot11fIERICDataDesc), ieLength); +#endif + + return eSIR_FAILURE; } tSirRetStatus limFTFillRICBlockAckInfo(tpAniSirGlobal pMac, tANI_U8 *ric_ies, tANI_U32 *ric_ies_length) @@ -1067,7 +1066,7 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, { tANI_U8 smeSessionId = 0; tANI_U16 transactionId = 0; - tANI_U8 chanNum = 0; + tANI_U8 chanNum = 0; tLimMlmReassocReq *pMlmReassocReq; tANI_U16 caps; tANI_U32 val; @@ -1075,14 +1074,18 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, tSirRetStatus retCode; tANI_U32 teleBcnEn = 0; - chanNum = psessionEntry->currentOperChannel; + chanNum = psessionEntry->currentOperChannel; limGetSessionInfo(pMac,(tANI_U8*)pMsgBuf, &smeSessionId, &transactionId); psessionEntry->smeSessionId = smeSessionId; psessionEntry->transactionId = transactionId; - - if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmReassocReq, + if (NULL == pMac->ft.ftPEContext.pAddBssReq) + { + limLog(pMac, LOGE, FL("pAddBssReq is NULL")); + return; + } + if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmReassocReq, sizeof(tLimMlmReassocReq))) { // Log error @@ -1103,6 +1106,7 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, * from CFG. Log error. */ limLog(pMac, LOGE, FL("could not retrieve ReassocFailureTimeout value")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); return; } @@ -1113,52 +1117,54 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, * from CFG. Log error. */ limLog(pMac, LOGE, FL("could not retrieve Capabilities value")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); return; } pMlmReassocReq->capabilityInfo = caps; - + /* Update PE sessionId*/ pMlmReassocReq->sessionId = psessionEntry->peSessionId; /* If telescopic beaconing is enabled, set listen interval to WNI_CFG_TELE_BCN_MAX_LI */ - if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != - eSIR_SUCCESS) + if (wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != + eSIR_SUCCESS) + { limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); + return; + } - if(teleBcnEn) + if (teleBcnEn) { - if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != eSIR_SUCCESS) + if (wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_MAX_LI, &val) != eSIR_SUCCESS) { /** * Could not get ListenInterval value * from CFG. Log error. */ limLog(pMac, LOGE, FL("could not retrieve ListenInterval")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); return; } } else { - if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != eSIR_SUCCESS) + if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &val) != eSIR_SUCCESS) { /** * Could not get ListenInterval value * from CFG. Log error. */ limLog(pMac, LOGE, FL("could not retrieve ListenInterval")); + palFreeMemory(pMac->hHdd, pMlmReassocReq); return; } } - if (limSetLinkState(pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId, - psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) - { - return; - } - if (limSetLinkState(pMac, eSIR_LINK_PREASSOC_STATE, psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) { - return; + palFreeMemory(pMac->hHdd, pMlmReassocReq); + return; } pMlmReassocReq->listenInterval = (tANI_U16) val; @@ -1168,7 +1174,7 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, //we need to defer the message until we get the response back from HAL. SET_LIM_PROCESS_DEFD_MESGS(pMac, false); - + msgQ.type = SIR_HAL_ADD_BSS_REQ; msgQ.reserved = 0; msgQ.bodyptr = pMac->ft.ftPEContext.pAddBssReq; @@ -1181,7 +1187,7 @@ void limProcessMlmFTReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf, MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); retCode = wdaPostCtrlMsg( pMac, &msgQ ); - if( eSIR_SUCCESS != retCode) + if( eSIR_SUCCESS != retCode) { vos_mem_free(pMac->ft.ftPEContext.pAddBssReq); limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), @@ -1204,6 +1210,7 @@ void limProcessFTPreauthRspTimeout(tpAniSirGlobal pMac) // We have failed pre auth. We need to resume link and get back on // home channel. + limLog(pMac, LOG1, FL("FT Pre-Auth Time Out!!!!")); if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimFTPreAuthRspTimer.sessionId))== NULL) { @@ -1224,32 +1231,72 @@ void limProcessFTPreauthRspTimeout(tpAniSirGlobal pMac) *------------------------------------------------------------------*/ tANI_BOOLEAN limProcessFTUpdateKey(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf ) { - tAddBssParams * pAddBssParams; - tSirFTUpdateKeyInfo * pKeyInfo; - tANI_U32 val = 0; - - /* Sanity Check */ - if( pMac == NULL || pMsgBuf == NULL ) - { - return TRUE; - } - - pAddBssParams = pMac->ft.ftPEContext.pAddBssReq; - pKeyInfo = (tSirFTUpdateKeyInfo *)pMsgBuf; - - /* Store the key information in the ADD BSS parameters */ - pAddBssParams->extSetStaKeyParamValid = 1; - pAddBssParams->extSetStaKeyParam.encType = pKeyInfo->keyMaterial.edType; - palCopyMemory( pMac->hHdd, (tANI_U8 *) &pAddBssParams->extSetStaKeyParam.key, + tAddBssParams * pAddBssParams; + tSirFTUpdateKeyInfo * pKeyInfo; + tANI_U32 val = 0; + + /* Sanity Check */ + if( pMac == NULL || pMsgBuf == NULL ) + { + return TRUE; + } + if(pMac->ft.ftPEContext.pAddBssReq == NULL) + { + limLog( pMac, LOGE, + FL( "pAddBssReq is NULL" )); + return TRUE; + } + + pAddBssParams = pMac->ft.ftPEContext.pAddBssReq; + pKeyInfo = (tSirFTUpdateKeyInfo *)pMsgBuf; + + /* Store the key information in the ADD BSS parameters */ + pAddBssParams->extSetStaKeyParamValid = 1; + pAddBssParams->extSetStaKeyParam.encType = pKeyInfo->keyMaterial.edType; + palCopyMemory( pMac->hHdd, (tANI_U8 *) &pAddBssParams->extSetStaKeyParam.key, (tANI_U8 *) &pKeyInfo->keyMaterial.key, sizeof( tSirKeys )); - if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) - { - limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); - } + if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) + { + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); + } - pAddBssParams->extSetStaKeyParam.singleTidRc = val; + pAddBssParams->extSetStaKeyParam.singleTidRc = val; + PELOG1(limLog(pMac, LOG1, FL("Key valid %d"), + pAddBssParams->extSetStaKeyParamValid, + pAddBssParams->extSetStaKeyParam.key[0].keyLength);) - return TRUE; + pAddBssParams->extSetStaKeyParam.staIdx = 0; + + PELOG1(limLog(pMac, LOG1, + FL("BSSID = %02X-%02X-%02X-%02X-%02X-%02X"), + pKeyInfo->bssId[0], pKeyInfo->bssId[1], + pKeyInfo->bssId[2], pKeyInfo->bssId[3], + pKeyInfo->bssId[4], pKeyInfo->bssId[5]);) + + if(pAddBssParams->extSetStaKeyParam.key[0].keyLength == 16) + { + PELOG1(limLog(pMac, LOG1, + FL("BSS key = %02X-%02X-%02X-%02X-%02X-%02X-%02X- " + "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X"), + pAddBssParams->extSetStaKeyParam.key[0].key[0], + pAddBssParams->extSetStaKeyParam.key[0].key[1], + pAddBssParams->extSetStaKeyParam.key[0].key[2], + pAddBssParams->extSetStaKeyParam.key[0].key[3], + pAddBssParams->extSetStaKeyParam.key[0].key[4], + pAddBssParams->extSetStaKeyParam.key[0].key[5], + pAddBssParams->extSetStaKeyParam.key[0].key[6], + pAddBssParams->extSetStaKeyParam.key[0].key[7], + pAddBssParams->extSetStaKeyParam.key[0].key[8], + pAddBssParams->extSetStaKeyParam.key[0].key[9], + pAddBssParams->extSetStaKeyParam.key[0].key[10], + pAddBssParams->extSetStaKeyParam.key[0].key[11], + pAddBssParams->extSetStaKeyParam.key[0].key[12], + pAddBssParams->extSetStaKeyParam.key[0].key[13], + pAddBssParams->extSetStaKeyParam.key[0].key[14], + pAddBssParams->extSetStaKeyParam.key[0].key[15]);) + } + + return TRUE; } tSirRetStatus diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c index a903e22fa2b..9272b387a02 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limIbssPeerMgmt.c @@ -1085,26 +1085,25 @@ limIbssStaAdd( limPrintMacAddr(pMac, *pPeerAddr, LOGE); pPeerNode = ibss_peer_find(pMac, *pPeerAddr); - if(NULL != pPeerNode) + if (NULL != pPeerNode) { - retCode = ibss_dph_entry_add(pMac, *pPeerAddr, &pStaDs,psessionEntry); + retCode = ibss_dph_entry_add(pMac, *pPeerAddr, &pStaDs, psessionEntry); if (eSIR_SUCCESS == retCode) { prevState = pStaDs->mlmStaContext.mlmState; pStaDs->erpEnabled = pPeerNode->erpIePresent; - ibss_sta_info_update(pMac, pStaDs, pPeerNode,psessionEntry); + ibss_sta_info_update(pMac, pStaDs, pPeerNode, psessionEntry); PELOGW(limLog(pMac, LOGW, FL("initiating ADD STA for the IBSS peer."));) retCode = limAddSta(pMac, pStaDs, false, psessionEntry); - if(retCode != eSIR_SUCCESS) + if (retCode != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("ibss-sta-add failed (reason %x)"), retCode);) + PELOGE(limLog(pMac, LOGE, FL("ibss-sta-add failed (reason %x)"), + retCode);) limPrintMacAddr(pMac, *pPeerAddr, LOGE); - if(NULL != pStaDs) - { - pStaDs->mlmStaContext.mlmState = prevState; - dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, &psessionEntry->dph.dphHashTable); - } + pStaDs->mlmStaContext.mlmState = prevState; + dphDeleteHashEntry(pMac, pStaDs->staAddr, pStaDs->assocId, + &psessionEntry->dph.dphHashTable); } else { @@ -1114,7 +1113,8 @@ limIbssStaAdd( if(beaconParams.paramChangeBitmap) { PELOGE(limLog(pMac, LOGE, FL("---> Update Beacon Params "));) - schSetFixedBeaconFields(pMac, psessionEntry); + schSetFixedBeaconFields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; limSendBeaconParams(pMac, &beaconParams, psessionEntry ); } } @@ -1466,7 +1466,8 @@ limIbssCoalesce( if(beaconParams.paramChangeBitmap) { PELOGE(limLog(pMac, LOGE, FL("beaconParams.paramChangeBitmap=1 ---> Update Beacon Params "));) - schSetFixedBeaconFields(pMac, psessionEntry); + schSetFixedBeaconFields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; limSendBeaconParams(pMac, &beaconParams, psessionEntry ); } } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limLogDump.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limLogDump.c index 076f10bfec1..6dcda170fd7 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limLogDump.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limLogDump.c @@ -2339,9 +2339,9 @@ dump_lim_mcc_policy_maker(tpAniSirGlobal pMac, tANI_U32 arg1,tANI_U32 arg2,tANI_ v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); tWDA_CbContext *pWDA = vos_get_context(VOS_MODULE_ID_WDA, pVosContext); ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, TRUE, NULL, eANI_BOOLEAN_FALSE); - if(pWDA != NULL) + if(NULL != pWDA) { - WDA_TimerTrafficStatsInd(pWDA); + WDA_TimerTrafficStatsInd(pWDA); } WDA_TrafficStatsTimerActivate(FALSE); ccmCfgSetInt(pMac, WNI_CFG_ENABLE_MCC_ADAPTIVE_SCHED, FALSE,NULL, eANI_BOOLEAN_FALSE); @@ -2350,7 +2350,7 @@ dump_lim_mcc_policy_maker(tpAniSirGlobal pMac, tANI_U32 arg1,tANI_U32 arg2,tANI_ { v_VOID_t * pVosContext = vos_get_global_context(VOS_MODULE_ID_WDA, NULL); tWDA_CbContext *pWDA = vos_get_context(VOS_MODULE_ID_WDA, pVosContext); - if (pWDA != NULL && tx_timer_change(&pWDA->wdaTimers.trafficStatsTimer, arg2/10, arg2/10) != TX_SUCCESS) + if (tx_timer_change(&pWDA->wdaTimers.trafficStatsTimer, arg2/10, arg2/10) != TX_SUCCESS) { limLog(pMac, LOGP, FL("Disable timer before changing timeout value")); } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limP2P.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limP2P.c index 3080cb3a456..68013717bb4 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limP2P.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limP2P.c @@ -809,7 +809,7 @@ void limSendP2PActionFrame(tpAniSirGlobal pMac, tpSirMsgQ pMsg) tANI_U8 txFlag = 0; tpSirMacFrameCtl pFc = (tpSirMacFrameCtl ) pMbMsg->data; tANI_U8 noaLen = 0; - tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + SIR_P2P_IE_HEADER_LEN]; + tANI_U8 noaStream[SIR_MAX_NOA_ATTR_LEN + (2*SIR_P2P_IE_HEADER_LEN)]; tANI_U8 origLen = 0; tANI_U8 sessionId = 0; v_U8_t *pP2PIe = NULL; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c index da02800fc8e..424be1dc076 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessActionFrame.c @@ -1198,6 +1198,7 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps pHdr = WDA_GET_RX_MAC_HEADER( pRxPacketInfo ); pBody = WDA_GET_RX_MPDU_DATA( pRxPacketInfo ); frameLen = WDA_GET_RX_PAYLOAD_LEN( pRxPacketInfo ); + val = 0; // Unpack the received frame nStatus = dot11fUnpackAddBAReq( pMac, pBody, frameLen, &frmAddBAReq ); @@ -1223,12 +1224,14 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps PELOG2(sirDumpBuf( pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frameLen );) } + psessionEntry->amsduSupportedInBA = frmAddBAReq.AddBAParameterSet.amsduSupported; + pSta = dphLookupHashEntry( pMac, pHdr->sa, &aid, &psessionEntry->dph.dphHashTable ); if( pSta == NULL ) { limLog( pMac, LOGE, FL( "STA context not found - ignoring ADDBA from " )); - limPrintMacAddr( pMac, pHdr->sa, LOGW ); + limPrintMacAddr( pMac, pHdr->sa, LOGE ); // FIXME - Should we do this? status = eSIR_MAC_INABLITY_TO_CONFIRM_ASSOC_STATUS; @@ -1248,6 +1251,23 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps } #endif //WLAN_SOFTAP_VSTA_FEATURE + if (wlan_cfgGetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, &val) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL("Unable to get WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + val = 0; + } + if ((SIR_BAND_2_4_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) && + val) + { + limLog( pMac, LOGW, + FL( "BTC disabled aggregation - ignoring ADDBA from " )); + limPrintMacAddr( pMac, pHdr->sa, LOGW ); + + status = eSIR_MAC_REQ_DECLINED_STATUS; + goto returnAfterError; + } // Now, validate the ADDBA Req if( eSIR_MAC_SUCCESS_STATUS != @@ -1304,7 +1324,7 @@ __limProcessAddBAReq( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps { frmAddBAReq.AddBAParameterSet.bufferSize = val; } - limLog( pMac, LOGE, FL( "ADDBAREQ NUMBUFF %d" ), + limLog( pMac, LOG1, FL( "ADDBAREQ NUMBUFF %d" ), frmAddBAReq.AddBAParameterSet.bufferSize); if( eSIR_SUCCESS != limPostMsgAddBAReq( pMac, @@ -1773,7 +1793,7 @@ __limProcessNeighborReport( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESes #ifdef WLAN_FEATURE_11W /** - * limProcessSAQueryRequestActionFrame + * limProcessActionFrame * *FUNCTION: * This function is called by limProcessActionFrame() upon @@ -1786,16 +1806,14 @@ __limProcessNeighborReport( tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo ,tpPESes *NOTE: * * @param pMac - Pointer to Global MAC structure - * @param *pRxPacketInfo - Handle to the Rx packet info - * @param psessionEntry - PE session entry - * + * @param *pBd - A pointer to Buffer descriptor + associated PDUs * @return None */ -static void __limProcessSAQueryRequestActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) +static void __limProcessSAQueryRequestActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession psessionEntry) { tpSirMacMgmtHdr pHdr; tANI_U8 *pBody; - tANI_U8 transId[2]; + tANI_U16 transId = 0; /* Prima --- Below Macro not available in prima pHdr = SIR_MAC_BD_TO_MPDUHEADER(pBd); @@ -1804,62 +1822,27 @@ static void __limProcessSAQueryRequestActionFrame(tpAniSirGlobal pMac, tANI_U8 * pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); - /* If this is an unprotected SA Query Request, then ignore it. */ - if (pHdr->fc.wep == 0) - return; - /*Extract 11w trsansId from SA query request action frame In SA query response action frame we will send same transId In SA query request action frame: Category : 1 byte Action : 1 byte - Transaction ID : 2 bytes */ - vos_mem_copy( &transId[0], &pBody[2], 2 ); + Transaction ID : 2 bbytes */ + transId = pBody[2]; + transId = transId << 8; + transId |= pBody[3]; + //Send 11w SA query response action frame if (limSendSaQueryResponseFrame(pMac, transId, pHdr->sa,psessionEntry) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("fail to send SA query response action frame."));) + PELOGE(limLog(pMac, LOGE, FL("fail to send SA query response action frame. \n"));) return; } } -/** - * __limProcessSAQueryResponseActionFrame - * - *FUNCTION: - * This function is called by limProcessActionFrame() upon - * SA query response Action frame reception. - * - *LOGIC: - * - *ASSUMPTIONS: - * - *NOTE: - * - * @param pMac - Pointer to Global MAC structure - * @param *pRxPacketInfo - Handle to the Rx packet info - * @param psessionEntry - PE session entry - * @return None - */ -static void __limProcessSAQueryResponseActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession psessionEntry) -{ - tpSirMacMgmtHdr pHdr; - tANI_U32 frameLen; - - pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); - frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); - VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("SA Query Response received...")) ; - /* Forward to the SME to HDD to wpa_supplicant */ - // type is ACTION - limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, - (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), 0, - WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry, 0); -} - #endif /** @@ -1885,21 +1868,11 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps { tANI_U8 *pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); tpSirMacActionFrameHdr pActionHdr = (tpSirMacActionFrameHdr) pBody; -#ifdef WLAN_FEATURE_11W - tpSirMacMgmtHdr pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); -#endif + switch (pActionHdr->category) { case SIR_MAC_ACTION_QOS_MGMT: -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " - "since RMF is enabled."), pActionHdr->category);) - break; - } -#endif if (psessionEntry->limQosEnabled) { switch (pActionHdr->actionID) @@ -1926,14 +1899,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps break; case SIR_MAC_ACTION_SPECTRUM_MGMT: -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " - "since RMF is enabled."), pActionHdr->category);) - break; - } -#endif switch (pActionHdr->actionID) { #ifdef ANI_SUPPORT_11H @@ -1997,14 +1962,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps case SIR_MAC_ACTION_BLKACK: // Determine the "type" of BA Action Frame -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " - "since RMF is enabled."), pActionHdr->category);) - break; - } -#endif switch(pActionHdr->actionID) { case SIR_MAC_BLKACK_ADD_REQ: @@ -2038,14 +1995,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps #if defined WLAN_FEATURE_VOWIFI case SIR_MAC_ACTION_RRM: -#ifdef WLAN_FEATURE_11W - if ((psessionEntry->limRmfEnabled) && (pHdr->fc.wep == 0)) - { - PELOGE(limLog(pMac, LOGE, FL("Dropping unprotected Action category %d frame " - "since RMF is enabled."), pActionHdr->category);) - break; - } -#endif if( pMac->rrm.rrmPEContext.rrmEnable ) { switch(pActionHdr->actionID) { @@ -2070,6 +2019,44 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps PELOGE( limLog( pMac, LOGE, FL("RRM Action frame ignored as RRM is disabled in cfg"));) } break; +#endif +#if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) + case SIR_MAC_ACTION_VENDOR_SPECIFIC_CATEGORY: + { + tpSirMacVendorSpecificFrameHdr pVendorSpecific = (tpSirMacVendorSpecificFrameHdr) pActionHdr; + tpSirMacMgmtHdr pHdr; + tANI_U32 frameLen; + tANI_U8 Oui[] = { 0x00, 0x00, 0xf0 }; + + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + //Check if it is a vendor specific action frame. + if ((eLIM_STA_ROLE == psessionEntry->limSystemRole) && + (VOS_TRUE == palEqualMemory(pMac->hHdd, psessionEntry->selfMacAddr, + &pHdr->da[0], sizeof(tSirMacAddr))) && + IS_WES_MODE_ENABLED(pMac) && palEqualMemory( pMac->hHdd, pVendorSpecific->Oui, Oui, 3)) + { + PELOGE( limLog( pMac, LOGW, FL("Received Vendor specific action frame, OUI %x %x %x"), + pVendorSpecific->Oui[0], pVendorSpecific->Oui[1], pVendorSpecific->Oui[2]);) + /* Forward to the SME to HDD to wpa_supplicant */ + // type is ACTION + limSendSmeMgmtFrameInd(pMac, pHdr->fc.subType, + (tANI_U8*)pHdr, frameLen + sizeof(tSirMacMgmtHdr), 0, + WDA_GET_RX_CH( pRxPacketInfo ), psessionEntry, 0); + } + else + { + limLog( pMac, LOGE, FL("Dropping the vendor specific action frame because of( " + "WES Mode not enabled (WESMODE = %d) or OUI mismatch (%02x %02x %02x) or " + "not received with SelfSta Mac address) system role = %d"), + IS_WES_MODE_ENABLED(pMac), + pVendorSpecific->Oui[0], pVendorSpecific->Oui[1], + pVendorSpecific->Oui[2], + psessionEntry->limSystemRole ); + } + } + break; #endif case SIR_MAC_ACTION_PUBLIC_USAGE: switch(pActionHdr->actionID) { @@ -2132,22 +2119,8 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps #ifdef WLAN_FEATURE_11W case SIR_MAC_ACTION_SA_QUERY: { - PELOGE(limLog(pMac, LOG1, FL("SA Query Action category %d action %d."), pActionHdr->category, pActionHdr->actionID);) - switch (pActionHdr->actionID) - { - case SIR_MAC_SA_QUERY_REQ: - /**11w SA query request action frame received**/ - /* Respond directly to the incoming request in LIM */ - __limProcessSAQueryRequestActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry ); - break; - case SIR_MAC_SA_QUERY_RSP: - /**11w SA query response action frame received**/ - /* Forward to the SME to HDD to wpa_supplicant */ - __limProcessSAQueryResponseActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry ); - break; - default: - break; - } + /**11w SA query request action frame received**/ + __limProcessSAQueryRequestActionFrame(pMac,(tANI_U8*) pRxPacketInfo, psessionEntry ); break; } #endif @@ -2165,7 +2138,6 @@ limProcessActionFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps break; } } - break; } #endif default: diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c index 55ba8f02ab7..27413d48112 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocReqFrame.c @@ -1403,6 +1403,7 @@ void limSendMlmAssocInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession p if((pMlmAssocInd->rsnIE.length + pAssocReq->wpa.length) >= SIR_MAC_MAX_IE_LENGTH) { PELOGE(limLog(pMac, LOGE, FL("rsnIEdata index out of bounds %d"), pMlmAssocInd->rsnIE.length);) + palFreeMemory(pMac->hHdd, pMlmAssocInd); return; } pMlmAssocInd->rsnIE.rsnIEdata[pMlmAssocInd->rsnIE.length] = SIR_MAC_WPA_EID; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c index 41c787f556d..8cd7009fa0f 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAssocRspFrame.c @@ -235,12 +235,7 @@ void limUpdateAssocStaDatas(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpSirAsso pStaDs->wmeEnabled = 1; } -#ifdef WLAN_FEATURE_11W - if(psessionEntry->limRmfEnabled) - { - pStaDs->rmfEnabled = 1; - } -#endif + } /** @@ -441,9 +436,8 @@ limProcessAssocRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tANI_U8 sub } VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - FL("Assoc Resp Frame Received: BSSID %02x:%02x:%02x:%02x:%02x:%02x (Rssi %d)"), - pHdr->bssId[0], pHdr->bssId[1], pHdr->bssId[2], - pHdr->bssId[3], pHdr->bssId[4], pHdr->bssId[5], + FL("Re/Assoc Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); // Get pointer to Re/Association Response frame body diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c index 7f9b288e42a..01b581c4ac8 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessAuthFrame.c @@ -9,6 +9,7 @@ * above copyright notice and this permission notice appear in all * copies. * + * Airgo Networks, Inc proprietary. All rights reserved. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE @@ -39,9 +40,8 @@ * PERFORMANCE OF THIS SOFTWARE. */ + /* - * - * Airgo Networks, Inc proprietary. All rights reserved. * This file limProcessAuthFrame.cc contains the code * for processing received Authentication Frame. * Author: Chandra Modumudi @@ -202,9 +202,8 @@ limProcessAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession pse } VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - FL("Auth Frame Received: BSSID %02x:%02x:%02x:%02x:%02x:%02x (Rssi %d)"), - pHdr->bssId[0], pHdr->bssId[1], pHdr->bssId[2], - pHdr->bssId[3], pHdr->bssId[4], pHdr->bssId[5], + FL("Auth Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); @@ -1685,9 +1684,8 @@ tSirRetStatus limProcessAuthFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pBd, vo frameLen = WDA_GET_RX_PAYLOAD_LEN(pBd); VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - FL("Auth Frame Received: BSSID %02x:%02x:%02x:%02x:%02x:%02x (Rssi %d)"), - pHdr->bssId[0], pHdr->bssId[1], pHdr->bssId[2], - pHdr->bssId[3], pHdr->bssId[4], pHdr->bssId[5], + FL("Auth Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pBd))); // Check for the operating channel and see what needs to be done next. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c index 4a3dd869561..c6ece4d95c9 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessBeaconFrame.c @@ -121,7 +121,7 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pBeacon, sizeof(tSchBeaconStruct))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessBeaconFrame\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessBeaconFrame") ); return; } @@ -132,7 +132,7 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps // Received wrongly formatted/invalid Beacon. // Ignore it and move on. limLog(pMac, LOGW, - FL("Received invalid Beacon in state %X\n"), + FL("Received invalid Beacon in state %X"), psessionEntry->limMlmState); limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); palFreeMemory(pMac->hHdd, pBeacon); @@ -157,14 +157,9 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps if ((pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE)) { - //If we are scanning for P2P, only accept probe rsp - if((pMac->lim.gLimHalScanState != eLIM_HAL_SCANNING_STATE) || (NULL == pMac->lim.gpLimMlmScanReq) - || !pMac->lim.gpLimMlmScanReq->p2pSearch ) - { - limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, - ((pMac->lim.gLimHalScanState == eLIM_HAL_SCANNING_STATE) ? eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE), - eANI_BOOLEAN_FALSE); - } + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, + ((pMac->lim.gLimHalScanState == eLIM_HAL_SCANNING_STATE) ? eANI_BOOLEAN_TRUE : eANI_BOOLEAN_FALSE), + eANI_BOOLEAN_FALSE); } else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) { @@ -214,7 +209,7 @@ limProcessBeaconFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession ps } else { - PELOG1(limLog(pMac, LOG1, FL("Received Beacon in unexpected state %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Received Beacon in unexpected state %d"), psessionEntry->limMlmState); limPrintMlmState(pMac, LOG1, psessionEntry->limMlmState);) #ifdef WLAN_DEBUG @@ -265,14 +260,14 @@ limProcessBeaconFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pBeacon, sizeof(tSchBeaconStruct))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessBeaconFrameNoSession\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessBeaconFrameNoSession") ); return; } if (sirConvertBeaconFrame2Struct(pMac, (tANI_U8 *) pRxPacketInfo, pBeacon) != eSIR_SUCCESS) { // Received wrongly formatted/invalid Beacon. Ignore and move on. - limLog(pMac, LOGW, FL("Received invalid Beacon in global MLM state %X\n"), pMac->lim.gLimMlmState); + limLog(pMac, LOGW, FL("Received invalid Beacon in global MLM state %X"), pMac->lim.gLimMlmState); limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); palFreeMemory(pMac->hHdd, pBeacon); return; @@ -281,12 +276,8 @@ limProcessBeaconFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) if ( (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) ) { - //If we are scanning for P2P, only accept probe rsp - if((pMac->lim.gLimHalScanState != eLIM_HAL_SCANNING_STATE) || (NULL == pMac->lim.gpLimMlmScanReq) - || !pMac->lim.gpLimMlmScanReq->p2pSearch ) - { - limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_FALSE); - } + limCheckAndAddBssDescription(pMac, pBeacon, pRxPacketInfo, + eANI_BOOLEAN_TRUE, eANI_BOOLEAN_FALSE); } else if (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) { @@ -295,7 +286,7 @@ limProcessBeaconFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) } // end of (eLIM_MLM_WT_PROBE_RESP_STATE) || (eLIM_MLM_PASSIVE_SCAN_STATE) else { - limLog(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %d\n"), pMac->lim.gLimMlmState); + limLog(pMac, LOG1, FL("Rcvd Beacon in unexpected MLM state %d"), pMac->lim.gLimMlmState); limPrintMlmState(pMac, LOG1, pMac->lim.gLimMlmState); #ifdef WLAN_DEBUG pMac->lim.gLimUnexpBcnCnt++; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c index 3be5f67c0ab..6ae8ee53b82 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessCfgUpdates.c @@ -129,13 +129,13 @@ limSetDefaultKeyIdAndKeys(tpAniSirGlobal pMac) tANI_U32 val; tANI_U32 dkCfgId; - PELOG1(limLog(pMac, LOG1, FL("Setting default keys at SP\n"));) + PELOG1(limLog(pMac, LOG1, FL("Setting default keys at SP"));) if (wlan_cfgGetInt(pMac, WNI_CFG_WEP_DEFAULT_KEYID, &val) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve defaultKeyId from CFG\n")); + FL("Unable to retrieve defaultKeyId from CFG")); } dkCfgId = limGetCfgIdOfDefaultKeyid(val); #endif @@ -158,7 +158,7 @@ void limSetCfgProtection(tpAniSirGlobal pMac, tpPESession pesessionEntry) else{ limLog(pMac, LOG1, FL(" frm11a = %d, from11b = %d, frm11g = %d, " "ht20 = %d, nongf = %d, lsigTxop = %d, " - "rifs = %d, obss = %d\n"), + "rifs = %d, obss = %d"), pesessionEntry->cfgProtection.fromlla, pesessionEntry->cfgProtection.fromllb, pesessionEntry->cfgProtection.fromllg, @@ -172,7 +172,7 @@ void limSetCfgProtection(tpAniSirGlobal pMac, tpPESession pesessionEntry) else{ if (wlan_cfgGetInt(pMac, WNI_CFG_FORCE_POLICY_PROTECTION, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("reading WNI_CFG_FORCE_POLICY_PROTECTION cfg failed\n")); + limLog(pMac, LOGP, FL("reading WNI_CFG_FORCE_POLICY_PROTECTION cfg failed")); return; } else @@ -180,7 +180,7 @@ void limSetCfgProtection(tpAniSirGlobal pMac, tpPESession pesessionEntry) if (wlan_cfgGetInt(pMac, WNI_CFG_PROTECTION_ENABLED, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("reading protection cfg failed\n")); + limLog(pMac, LOGP, FL("reading protection cfg failed")); return; } @@ -221,7 +221,7 @@ static tSirRetStatus limUpdateTriggerStaBkScanFlag(tpAniSirGlobal pMac) if(wlan_cfgGetInt(pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val) != eSIR_SUCCESS) { - PELOG1(limLog(pMac, LOG1, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN from cfg\n"));) + PELOG1(limLog(pMac, LOG1, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN from cfg"));) return eSIR_FAILURE; } @@ -271,7 +271,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) tSirMacHTCapabilityInfo *pHTCapabilityInfo; tSirMacHTParametersInfo *pAmpduParamInfo; - PELOG3(limLog(pMac, LOG3, FL("Handling CFG parameter id %X update\n"), cfgId);) + PELOG3(limLog(pMac, LOG3, FL("Handling CFG parameter id %X update"), cfgId);) switch (cfgId) { case WNI_CFG_WEP_DEFAULT_KEYID: @@ -289,13 +289,13 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) &val1) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve excludeUnencr from CFG\n")); + FL("Unable to retrieve excludeUnencr from CFG")); } #if 0 halSetSpExclUndecrypted(pMac, (tHalBitVal) val); #else limLog(pMac, LOGE, - FL("Unsupported CFG: WNI_CFG_EXCLUDE_UNENCRYPTED\n")); + FL("Unsupported CFG: WNI_CFG_EXCLUDE_UNENCRYPTED")); #endif break; @@ -317,7 +317,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) if (wlan_cfgGetInt(pMac, WNI_CFG_BACKGROUND_SCAN_PERIOD, &val1) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve Background scan period value\n")); + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); break; } if (val1 == 0) @@ -337,7 +337,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) /// Could not activate background scan timer. // Log error limLog(pMac, LOGP, - FL("could not activate background scan timer\n")); + FL("could not activate background scan timer")); pMac->lim.gLimBackgroundScanStarted = FALSE; pMac->lim.gLimBackgroundScanTerminate = TRUE; } @@ -348,14 +348,14 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) } PELOG3(limLog(pMac, LOG3, - FL("Updated Background scan period\n"));) + FL("Updated Background scan period"));) } break; case WNI_CFG_BG_SCAN_CHANNEL_LIST: PELOG1(limLog(pMac, LOG1, - FL("VALID_CHANNEL_LIST has changed, reset next bg scan channel\n"));) + FL("VALID_CHANNEL_LIST has changed, reset next bg scan channel"));) pMac->lim.gLimBackgroundScanChannelId = 0; break; @@ -364,7 +364,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) if(limUpdateTriggerStaBkScanFlag(pMac) != eSIR_SUCCESS) { PELOG2(limLog(pMac, LOG2, - FL("Updating lim trigger sta bk scan global flag failed!\n"));) + FL("Updating lim trigger sta bk scan global flag failed!"));) } break; @@ -381,150 +381,148 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) status = limPostMsgApi(pMac, &msg); if (status != TX_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Failed limPostMsgApi\n"), status);) + PELOGE(limLog(pMac, LOGE, FL("Failed limPostMsgApi"), status);) break; } case WNI_CFG_GREENFIELD_CAPABILITY: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_GREENFIELD_CAPABILITY, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve GreenField CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve GreenField CFG"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->greenField = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_HT_RX_STBC: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_CAP_INFO \n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_CAP_INFO "));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_HT_RX_STBC, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_RX_STBC\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HT_RX_STBC"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->rxSTBC = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_MAX_AMSDU_LENGTH: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap Info CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_AMSDU_LENGTH, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max AMSDU Length CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Max AMSDU Length CFG"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->maximalAMSDUsize = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_SHORT_GI_20MHZ: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_20MHZ, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 20Mhz CFG"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->shortGI20MHz = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_SHORT_GI_40MHZ: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT Cap CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_GI_40MHZ, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve shortGI 40Mhz CFG"));) break; } val16 = ( tANI_U16 ) val1; pHTCapabilityInfo = ( tSirMacHTCapabilityInfo* ) &val16; pHTCapabilityInfo->shortGI40MHz = (tANI_U16)val2; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT Cap Info CFG"));) break; case WNI_CFG_MPDU_DENSITY: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_MPDU_DENSITY, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve MPDU Density CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve MPDU Density CFG"));) break; } val16 = ( tANI_U16 ) val1; pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16; pAmpduParamInfo->mpduDensity = (tANI_U8)val2; if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG"));) break; case WNI_CFG_MAX_RX_AMPDU_FACTOR: if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve HT AMPDU Param CFG"));) break; } if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_RX_AMPDU_FACTOR, &val2) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve AMPDU Factor CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve AMPDU Factor CFG"));) break; } val16 = ( tANI_U16 ) val1; pAmpduParamInfo = ( tSirMacHTParametersInfo* ) &val16; pAmpduParamInfo->maxRxAMPDUFactor = (tANI_U8)val2; if(cfgSetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, *(tANI_U8*)pAmpduParamInfo) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not update HT AMPDU Param CFG"));) break; case WNI_CFG_HEART_BEAT_THRESHOLD: if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve WNI_CFG_HEART_BEAT_THRESHOLD CFG"));) break; } if(!val1) { limDeactivateAndChangeTimer(pMac, eLIM_HEART_BEAT_TIMER); pMac->sys.gSysEnableLinkMonitorMode = 0; - PELOGE(limLog(pMac, LOGE, "Deactivating heartbeat link monitoring\n");) } else { tANI_U16 sessionId; pMac->sys.gSysEnableLinkMonitorMode = 1; - PELOGE(limLog(pMac, LOGE, "Reactivating heartbeat link monitoring\n");) for(sessionId = 0; sessionId < pMac->lim.maxBssId; sessionId++) { if( (pMac->lim.gpSession[sessionId].valid )&& @@ -534,11 +532,15 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) { PELOG2(limLog(pMac, LOG2, "HB link monitoring reactivated" " for session=%d", sessionId);) + PELOGW(limLog(pMac, LOGW, "Before reactivating HB timer; parameters are" + " session=%d limMlmState=%d pmmState=%d", sessionId, + pMac->lim.gpSession[sessionId].limMlmState, + pMac->pmm.gPmmState);) limReactivateHeartBeatTimer(pMac, &pMac->lim.gpSession[sessionId]); } else if ( pMac->lim.gpSession[sessionId].valid ) { - PELOG2(limLog(pMac, LOG2, "HB link monitoring not reactivated-" + PELOGW(limLog(pMac, LOGW, "HB link monitoring not reactivated-" "session=%d, limMlmState=%d, gPmmState=%d", sessionId, pMac->lim.gpSession[sessionId].limMlmState, pMac->pmm.gPmmState);) @@ -557,7 +559,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) if (palAllocateMemory(pMac->hHdd, (void **)&pPowerSaveConfig, sizeof(tSirPowerSaveCfg)) != eHAL_STATUS_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("LIM: Cannot allocate memory for power save configuration\n"));) + PELOGE(limLog(pMac, LOGE, FL("LIM: Cannot allocate memory for power save configuration"));) break; } @@ -568,7 +570,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) if ( (pmmSendPowerSaveCfg(pMac, pPowerSaveConfig)) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("LIM: pmmSendPowerSaveCfg() failed \n"));) + PELOGE(limLog(pMac, LOGE, FL("LIM: pmmSendPowerSaveCfg() failed "));) } } break; @@ -577,7 +579,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) case WNI_CFG_DOT11_MODE: if (wlan_cfgGetInt(pMac, WNI_CFG_DOT11_MODE, &val1) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve Dot11 Mode CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve Dot11 Mode CFG"));) break; } /* TODO */ @@ -585,7 +587,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) break; case WNI_CFG_ADDBA_REQ_DECLINE: if(wlan_cfgGetInt(pMac, WNI_CFG_ADDBA_REQ_DECLINE, &val1) != eSIR_SUCCESS) { - limLog( pMac, LOGE, FL( "Unable to get ADDBA_REQ_DECLINE cfg\n" )); + limLog( pMac, LOGE, FL( "Unable to get ADDBA_REQ_DECLINE cfg" )); break; } pMac->lim.gAddBA_Declined = (tANI_U8)val1; @@ -593,7 +595,7 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) case WNI_CFG_SCAN_IN_POWERSAVE: if(wlan_cfgGetInt(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val1) != eSIR_SUCCESS) { - limLog( pMac, LOGE, FL( "Unable to get WNI_CFG_SCAN_IN_POWERSAVE \n" )); + limLog( pMac, LOGE, FL( "Unable to get WNI_CFG_SCAN_IN_POWERSAVE " )); break; } pMac->lim.gScanInPowersave = (tANI_U8)val1; @@ -608,6 +610,28 @@ limHandleCFGparamUpdate(tpAniSirGlobal pMac, tANI_U32 cfgId) pMac->lim.gLimAssocStaLimit = (tANI_U16)val1; break; + case WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC: + if (wlan_cfgGetInt + (pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, &val1) != + eSIR_SUCCESS) + { + limLog(pMac, LOGE, + FL( "Unable to get WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + break; + } + if (val1) + { + limLog(pMac, LOGW, + FL("BTC requested to disable all RX BA sessions")); + limDelAllBASessionsBtc(pMac); + } + else + { + limLog(pMac, LOGW, + FL("Resetting the WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC")); + } + break; + default: break; } @@ -640,7 +664,7 @@ limApplyConfiguration(tpAniSirGlobal pMac,tpPESession psessionEntry) { tANI_U32 val=0, phyMode; - PELOG2(limLog(pMac, LOG2, FL("Applying config\n"));) + PELOG2(limLog(pMac, LOG2, FL("Applying config"));) limInitWdsInfoParams(pMac); @@ -669,7 +693,7 @@ limApplyConfiguration(tpAniSirGlobal pMac,tpPESession psessionEntry) if(psessionEntry->statypeForBss == STA_ENTRY_SELF) { - PELOG1(limLog(pMac, LOG1, FL("Initializing BT-AMP beacon generation\n"));) + PELOG1(limLog(pMac, LOG1, FL("Initializing BT-AMP beacon generation"));) schSetBeaconInterval(pMac,psessionEntry); schSetFixedBeaconFields(pMac,psessionEntry); } @@ -677,7 +701,7 @@ limApplyConfiguration(tpAniSirGlobal pMac,tpPESession psessionEntry) if (wlan_cfgGetInt(pMac, WNI_CFG_SCAN_IN_POWERSAVE, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve WNI_CFG_SCAN_IN_POWERSAVE\n")); + limLog(pMac, LOGP, FL("could not retrieve WNI_CFG_SCAN_IN_POWERSAVE")); return; } pMac->lim.gScanInPowersave = (tANI_U8) val; @@ -709,39 +733,39 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) #if 0 if (wlan_cfgGetStr(pMac, WNI_CFG_STA_ID, pMac->lim.gLimMyMacAddr, &len) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get sta id failed\n")); + limLog(pMac, LOGP, FL("cfg get sta id failed")); #endif //To SUPPORT BT-AMP sirCopyMacAddr(pMac->lim.gLimMyMacAddr,psessionEntry->selfMacAddr); if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get short preamble failed\n")); + limLog(pMac, LOGP, FL("cfg get short preamble failed")); psessionEntry->beaconParams.fShortPreamble = (val) ? 1 : 0; if (wlan_cfgGetInt(pMac, WNI_CFG_WME_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get wme enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get wme enabled failed")); psessionEntry->limWmeEnabled = (val) ? 1 : 0; if (wlan_cfgGetInt(pMac, WNI_CFG_WSM_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get wsm enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get wsm enabled failed")); psessionEntry->limWsmEnabled = (val) ? 1 : 0; if ((! psessionEntry->limWmeEnabled) && (psessionEntry->limWsmEnabled)) { - PELOGE(limLog(pMac, LOGE, FL("Can't enable WSM without WME\n"));) + PELOGE(limLog(pMac, LOGE, FL("Can't enable WSM without WME"));) psessionEntry->limWsmEnabled = 0; } if (wlan_cfgGetInt(pMac, WNI_CFG_QOS_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get qos enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get qos enabled failed")); psessionEntry->limQosEnabled = (val) ? 1 : 0; if (wlan_cfgGetInt(pMac, WNI_CFG_HCF_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get hcf enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get hcf enabled failed")); psessionEntry->limHcfEnabled = (val) ? 1 : 0; // Update the ADD BA Declined configuration if(wlan_cfgGetInt(pMac, WNI_CFG_ADDBA_REQ_DECLINE, &val) != eSIR_SUCCESS) - limLog( pMac, LOGP, FL( "Unable to get ADDBA_REQ_DECLINE cfg\n" )); + limLog( pMac, LOGP, FL( "Unable to get ADDBA_REQ_DECLINE cfg" )); pMac->lim.gAddBA_Declined = (val) ? 0xff : 0x0; // AP: WSM should enable HCF as well, for STA enable WSM only after @@ -750,7 +774,7 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) psessionEntry->limHcfEnabled = 1; if (wlan_cfgGetInt(pMac, WNI_CFG_11D_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get 11d enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get 11d enabled failed")); psessionEntry->lim11dEnabled = (val) ? 1 : 0; if(wlan_cfgGetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, &val) != eSIR_SUCCESS) { @@ -761,7 +785,7 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) if(ccmCfgSetInt(pMac, WNI_CFG_ASSOC_STA_LIMIT, WNI_CFG_ASSOC_STA_LIMIT_STADEF, NULL, eANI_BOOLEAN_FALSE) != eHAL_STATUS_SUCCESS) { - limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); + limLog( pMac, LOGP, FL( "cfg get assoc sta limit failed" )); } val = WNI_CFG_ASSOC_STA_LIMIT_STADEF; } @@ -770,7 +794,7 @@ limUpdateConfig(tpAniSirGlobal pMac,tpPESession psessionEntry) #if defined WLAN_FEATURE_VOWIFI rrmUpdateConfig( pMac, psessionEntry ); #endif - PELOG1(limLog(pMac, LOG1, FL("Updated Lim shadow state based on CFG\n"));) + PELOG1(limLog(pMac, LOG1, FL("Updated Lim shadow state based on CFG"));) } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c index ea155f73957..776b36ee831 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDeauthFrame.c @@ -94,9 +94,6 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p tpDphHashNode pStaDs; tpPESession pRoamSessionEntry=NULL; tANI_U8 roamSessionId; -#ifdef WLAN_FEATURE_11W - tANI_U32 frameLen; -#endif pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); @@ -115,7 +112,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p // Received Deauth frame from a BC/MC address // Log error and ignore it PELOG1(limLog(pMac, LOG1, - FL("received Deauth frame from a BC/MC address\n"));) + FL("received Deauth frame from a BC/MC address"));) return; } @@ -125,28 +122,10 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p // Received Deauth frame for a MC address // Log error and ignore it PELOG1(limLog(pMac, LOG1, - FL("received Deauth frame for a MC address\n"));) + FL("received Deauth frame for a MC address"));) return; } - -#ifdef WLAN_FEATURE_11W - /* PMF: If this session is a PMF session, then ensure that this frame was protected */ - if(psessionEntry->limRmfEnabled && (WDA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) & DPU_FEEDBACK_UNPROTECTED_ERROR)) - { - PELOGE(limLog(pMac, LOGE, FL("received an unprotected deauth from AP"));) - // If the frame received is unprotected, forward it to the supplicant to initiate - // an SA query - frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); - - //send the unprotected frame indication to SME - limSendSmeUnprotectedMgmtFrameInd( pMac, pHdr->fc.subType, - (tANI_U8*)pHdr, (frameLen + sizeof(tSirMacMgmtHdr)), - psessionEntry->smeSessionId, psessionEntry); - return; - } -#endif - // Get reasonCode from Deauthentication frame body reasonCode = sirReadU16(pBody); @@ -157,8 +136,8 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p if (limCheckDisassocDeauthAckPending(pMac, (tANI_U8*)pHdr->sa)) { - PELOGW(limLog(pMac, LOGE, - FL("Ignore the Deauth received, while waiting for ack of disassoc/deauth\n"));) + PELOGW(limLog(pMac, LOGW, + FL("Ignore the Deauth received, while waiting for ack of disassoc/deauth"));) limCleanUpDisassocDeauthReq(pMac,(tANI_U8*)pHdr->sa, 1); return; } @@ -177,7 +156,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p // Invalid reasonCode in received Deauthentication frame // Log error and ignore the frame PELOG1(limLog(pMac, LOG1, - FL("received Deauth frame with invalid reasonCode %d from \n"), + FL("received Deauth frame with invalid reasonCode %d from "), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOG1);) @@ -201,7 +180,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p // Invalid reasonCode in received Deauth frame // Log error and ignore the frame PELOG1(limLog(pMac, LOG1, - FL("received Deauth frame with invalid reasonCode %d from \n"), + FL("received Deauth frame with invalid reasonCode %d from "), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOG1);) @@ -211,11 +190,11 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p else { // Received Deauth frame in either IBSS - // or un-known role. Log error and ignore it - limLog(pMac, LOGE, - FL("received Deauth frame with reasonCode %d in role %d from \n"), + // or un-known role. Log and ignore it + limLog(pMac, LOG1, + FL("received Deauth frame with reasonCode %d in role %d from "), reasonCode, psessionEntry->limSystemRole); - limPrintMacAddr(pMac, pHdr->sa, LOGE); + limPrintMacAddr(pMac, pHdr->sa, LOG1); return; } @@ -244,7 +223,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p } if (limIsReassocInProgress(pMac,psessionEntry) || limIsReassocInProgress(pMac,pRoamSessionEntry)) { if (!IS_REASSOC_BSSID(pMac,pHdr->sa,psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from unknown/different AP while ReAssoc. Ignore \n"));) + PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from unknown/different AP while ReAssoc. Ignore "));) limPrintMacAddr(pMac, pHdr->sa, LOGE); limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOGE); return; @@ -254,7 +233,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p * Drop ReAssoc and Restore the Previous context( current connected AP). */ if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("received DeAuth from the New AP to which ReAssoc is sent \n"));) + PELOGE(limLog(pMac, LOGE, FL("received DeAuth from the New AP to which ReAssoc is sent "));) limPrintMacAddr(pMac, pHdr->sa, LOGE); limPrintMacAddr(pMac, psessionEntry->bssId, LOGE); limRestorePreReassocState(pMac, @@ -270,10 +249,10 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p if(psessionEntry->limSystemRole != eLIM_AP_ROLE ){ if (!IS_CURRENT_BSSID(pMac, pHdr->bssId, psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("received DeAuth from an AP other than we're trying to join. Ignore. \n"));) + PELOGE(limLog(pMac, LOGE, FL("received DeAuth from an AP other than we're trying to join. Ignore. "));) if (limSearchPreAuthList(pMac, pHdr->sa)) { - PELOGE(limLog(pMac, LOGE, FL("Preauth entry exist. Deleting... \n"));) + PELOG1(limLog(pMac, LOG1, FL("Preauth entry exist. Deleting... "));) limDeletePreAuthNode(pMac, pHdr->sa); } return; @@ -475,7 +454,7 @@ limProcessDeauthFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession p psessionEntry->limAssocResponseData = NULL; } - PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from ReAssoc AP. Issue REASSOC_CNF. \n"));) + PELOGE(limLog(pMac, LOGE, FL("Rcv Deauth from ReAssoc AP. Issue REASSOC_CNF. "));) /* * TODO: Instead of overloading eSIR_SME_FT_REASSOC_TIMEOUT_FAILURE * it would have been good to define/use a different failure type. diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c index 6666e7b7197..7c9f6d40d3f 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessDisassocFrame.c @@ -39,8 +39,9 @@ * PERFORMANCE OF THIS SOFTWARE. */ + + /* - * * Airgo Networks, Inc proprietary. All rights reserved. * This file limProcessDisassocFrame.cc contains the code * for processing Disassocation Frame. @@ -93,9 +94,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession tpSirMacMgmtHdr pHdr; tpDphHashNode pStaDs; tLimMlmDisassocInd mlmDisassocInd; -#ifdef WLAN_FEATURE_11W - tANI_U32 frameLen; -#endif + pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); @@ -106,7 +105,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession // Received Disassoc frame from a BC/MC address // Log error and ignore it PELOG1(limLog(pMac, LOG1, - FL("received Disassoc frame from a BC/MC address\n"));) + FL("received Disassoc frame from a BC/MC address"));) return; } @@ -116,32 +115,16 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession // Received Disassoc frame for a MC address // Log error and ignore it PELOG1(limLog(pMac, LOG1, - FL("received Disassoc frame for a MC address\n"));) + FL("received Disassoc frame for a MC address"));) return; } -#ifdef WLAN_FEATURE_11W - /* PMF: If this session is a PMF session, then ensure that this frame was protected */ - if(psessionEntry->limRmfEnabled && (WDA_GET_RX_DPU_FEEDBACK(pRxPacketInfo) & DPU_FEEDBACK_UNPROTECTED_ERROR)) - { - PELOGE(limLog(pMac, LOGE, FL("received an unprotected disassoc from AP"));) - // If the frame received is unprotected, forward it to the supplicant to initiate - // an SA query - frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); - //send the unprotected frame indication to SME - limSendSmeUnprotectedMgmtFrameInd( pMac, pHdr->fc.subType, - (tANI_U8*)pHdr, (frameLen + sizeof(tSirMacMgmtHdr)), - psessionEntry->smeSessionId, psessionEntry); - return; - } -#endif - // Get reasonCode from Disassociation frame body reasonCode = sirReadU16(pBody); PELOG2(limLog(pMac, LOG2, - FL("Received Disassoc frame (mlm state %d sme state %d), with reason code %d from "MAC_ADDRESS_STR), + FL("Received Disassoc frame (mlm state %d sme state %d), with reason code %d from "MAC_ADDRESS_STR), psessionEntry->limMlmState, psessionEntry->limSmeState, reasonCode, MAC_ADDR_ARRAY(pHdr->sa));) /** @@ -166,8 +149,8 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession if (limCheckDisassocDeauthAckPending(pMac, (tANI_U8*)pHdr->sa)) { - PELOGW(limLog(pMac, LOGE, - FL("Ignore the DisAssoc received, while waiting for ack of disassoc/deauth\n"));) + PELOGW(limLog(pMac, LOGW, + FL("Ignore the DisAssoc received, while waiting for ack of disassoc/deauth"));) limCleanUpDisassocDeauthReq(pMac,(tANI_U8*)pHdr->sa, 1); return; } @@ -180,14 +163,14 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession * drop/ignore the DisAssoc received */ if (!IS_REASSOC_BSSID(pMac,pHdr->sa,psessionEntry)) { - PELOGW(limLog(pMac, LOGW, FL("Ignore the DisAssoc received, while Processing ReAssoc with different/unknown AP\n"));) + PELOGW(limLog(pMac, LOGW, FL("Ignore the DisAssoc received, while Processing ReAssoc with different/unknown AP"));) return; } /** If the Disassoc is received from the new AP to which we tried to ReAssociate * Drop ReAssoc and Restore the Previous context( current connected AP). */ if (!IS_CURRENT_BSSID(pMac, pHdr->sa,psessionEntry)) { - PELOGW(limLog(pMac, LOGW, FL("received Disassoc from the New AP to which ReAssoc is sent \n"));) + PELOGW(limLog(pMac, LOGW, FL("received Disassoc from the New AP to which ReAssoc is sent "));) limRestorePreReassocState(pMac, eSIR_SME_REASSOC_REFUSED, reasonCode,psessionEntry); return; @@ -213,7 +196,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession default: // Invalid reasonCode in received Disassociation frame PELOG1(limLog(pMac, LOG1, - FL("received Disassoc frame with invalid reasonCode %d from \n"), + FL("received Disassoc frame with invalid reasonCode %d from "), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOG1);) break; @@ -238,10 +221,10 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession case eSIR_MAC_GR_KEY_UPDATE_TIMEOUT_REASON: case eSIR_MAC_RSN_IE_MISMATCH_REASON: case eSIR_MAC_1X_AUTH_FAILURE_REASON: - case eSIR_MAC_PREV_AUTH_NOT_VALID_REASON: // Valid reasonCode in received Disassociation frame break; + case eSIR_MAC_DEAUTH_LEAVING_BSS_REASON: case eSIR_MAC_DISASSOC_LEAVING_BSS_REASON: // Valid reasonCode in received Disassociation frame // as long as we're not about to channel switch @@ -249,7 +232,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession { limLog(pMac, LOGW, FL("Ignoring disassoc frame due to upcoming " - "channel switch, from\n"), + "channel switch, from"), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOGW); return; @@ -260,7 +243,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession // Invalid reasonCode in received Disassociation frame // Log error and ignore the frame PELOG1(limLog(pMac, LOG1, - FL("received Disassoc frame with invalid reasonCode %d from \n"), + FL("received Disassoc frame with invalid reasonCode %d from "), reasonCode); limPrintMacAddr(pMac, pHdr->sa, LOG1);) return; @@ -269,18 +252,18 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession else { // Received Disassociation frame in either IBSS - // or un-known role. Log error and ignore it - limLog(pMac, LOGE, - FL("received Disassoc frame with invalid reasonCode %d in role %d in sme state %d from \n"), + // or un-known role. Log and ignore it + limLog(pMac, LOG1, + FL("received Disassoc frame with invalid reasonCode %d in role %d in sme state %d from "), reasonCode, psessionEntry->limSystemRole, psessionEntry->limSmeState); - limPrintMacAddr(pMac, pHdr->sa, LOGE); + limPrintMacAddr(pMac, pHdr->sa, LOG1); return; } // Disassociation from peer MAC entity - PELOGE(limLog(pMac, LOGE, + PELOG1(limLog(pMac, LOG1, FL("Received Disassoc frame from sta with assocId=%d with reasonCode=%d. Peer MAC is "MAC_ADDRESS_STR), pStaDs->assocId, reasonCode, MAC_ADDR_ARRAY(pHdr->sa));) @@ -332,7 +315,7 @@ limProcessDisassocFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo, tpPESession * failure result code. By design, SME will then issue "Disassoc" * and cleanup will happen at that time. */ - PELOGE(limLog(pMac, LOGE, FL("received Disassoc from AP while waiting for Reassoc Rsp\n"));) + PELOGE(limLog(pMac, LOGE, FL("received Disassoc from AP while waiting for Reassoc Rsp"));) if (psessionEntry->limAssocResponseData) { palFreeMemory(pMac->hHdd, psessionEntry->limAssocResponseData); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c index 8b3e25daf24..050cf8c7def 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMessageQueue.c @@ -156,7 +156,7 @@ defMsgDecision(tpAniSirGlobal pMac, tpSirMsgQ limMsg) #endif (limMsg->type != WDA_ADD_TS_RSP)) { - PELOG1(limLog(pMac, LOG1, FL("Defer the current message %s , gLimProcessDefdMsgs is false and system is not in scan/learn mode\n"), + PELOG1(limLog(pMac, LOG1, FL("Defer the current message %s , gLimProcessDefdMsgs is false and system is not in scan/learn mode"), limMsgStr(limMsg->type));) // Defer processsing this message @@ -290,7 +290,7 @@ limHandleFramesInScanState(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pRxPa *deferMsg = false; pHdr = WDA_GET_RX_MAC_HEADER(pRxPacketInfo); fc = pHdr->fc; - limLog( pMac, LOG2, FL("ProtVersion %d, Type %d, Subtype %d\n"), + limLog( pMac, LOG2, FL("ProtVersion %d, Type %d, Subtype %d"), fc.protVer, fc.type, fc.subType ); // defer all message in scan state except for Beacons and Probe Response @@ -355,7 +355,7 @@ static void limHandleUnknownA2IndexFrames(tpAniSirGlobal pMac, void *pRxPacketIn if (limIsGroupAddr(pMacHdr->addr2)) { - PELOG2(limLog(pMac, LOG2, FL("Ignoring A2 Invalid Packet received for MC/BC:\n")); + PELOG2(limLog(pMac, LOG2, FL("Ignoring A2 Invalid Packet received for MC/BC:")); limPrintMacAddr(pMac, pMacHdr->addr2, LOG2);) return; @@ -366,7 +366,7 @@ static void limHandleUnknownA2IndexFrames(tpAniSirGlobal pMac, void *pRxPacketIn { /* ADD handling of Public Action Frame */ LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("limHandleUnknownA2IndexFrames: type=0x%x, subtype=0x%x\n"),pMacHdr->fc.type, pMacHdr->fc.subType)); + ("limHandleUnknownA2IndexFrames: type=0x%x, subtype=0x%x"),pMacHdr->fc.type, pMacHdr->fc.subType)); switch (pMacHdr->fc.type) { case SIR_MAC_MGMT_FRAME: @@ -446,7 +446,7 @@ limCheckMgmtRegisteredFrames(tpAniSirGlobal pMac, tANI_U8 *pBd, && (subType == SIR_MAC_MGMT_RESERVED15) ) { limLog( pMac, LOG3, - FL("rcvd frame match with SIR_MAC_MGMT_RESERVED15\n")); + FL("rcvd frame match with SIR_MAC_MGMT_RESERVED15")); match = VOS_TRUE; break; } @@ -485,7 +485,7 @@ limCheckMgmtRegisteredFrames(tpAniSirGlobal pMac, tANI_U8 *pBd, if (match) { limLog( pMac, LOG1, - FL("rcvd frame match with registered frame params\n")); + FL("rcvd frame match with registered frame params")); /* Indicate this to SME */ limSendSmeMgmtFrameInd( pMac, pHdr->fc.subType, (tANI_U8*)pHdr, @@ -546,10 +546,37 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) fcOffset = (v_U8_t)WDA_GET_RX_MPDU_HEADER_OFFSET(pRxPacketInfo); fc = pHdr->fc; - limLog( pMac, LOG4, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d\n"), + limLog( pMac, LOG4, FL("ProtVersion %d, Type %d, Subtype %d rateIndex=%d"), fc.protVer, fc.type, fc.subType, WDA_GET_RX_MAC_RATE_IDX(pRxPacketInfo)); - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if ( WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo)) + { + limLog( pMac, LOG2, FL("Notify SME with candidate ind")); + //send a session 0 for now - TBD + limSendSmeCandidateFoundInd(pMac, 0); + goto end; + } + if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + { + if (fc.subType == SIR_MAC_MGMT_BEACON) + { + limLog( pMac, LOG2, FL("Save this beacon in LFR cache")); + __limHandleBeacon(pMac, limMsg, NULL); + } + else if (fc.subType == SIR_MAC_MGMT_PROBE_RSP) + { + limLog( pMac, LOG2, FL("Save this probe rsp in LFR cache")); + limProcessProbeRspFrameNoSession(pMac, pRxPacketInfo); + } + else + { + limLog( pMac, LOGE, FL("Wrong frame Type %d, Subtype %d for LFR"), + fc.type, fc.subType); + } + goto end; + } +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD #ifdef FEATURE_WLAN_CCX if (fc.type == SIR_MAC_DATA_FRAME && isFrmFt) { @@ -567,7 +594,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) if (!psessionEntry->isCCXconnection) { - limLog( pMac, LOGE, FL("LIM received Type %d, Subtype %d in Non CCX connection\n"), + limLog( pMac, LOGE, FL("LIM received Type %d, Subtype %d in Non CCX connection"), fc.type, fc.subType); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pBD, limMsg->bodyptr); return; @@ -575,7 +602,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) limLog( pMac, LOGE, FL("Processing IAPP Frm from SA:")); limPrintMacAddr(pMac, pDataFrmHdr->sa, LOGE); #else - printk("%s: Need to port handling of IAPP frames to PRIMA for CCX\n", __func__); + printk("%s: Need to port handling of IAPP frames to PRIMA for CCX", __func__); #endif @@ -608,7 +635,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) if((psessionEntry = peFindSessionByPeerSta(pMac,pHdr->sa,&sessionId))== NULL) { - limLog(pMac, LOG1, FL("session does not exist for given bssId\n")); + limLog(pMac, LOG1, FL("session does not exist for given bssId")); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, limMsg->bodyptr); return; } @@ -625,7 +652,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) /* Check if frame is registered by HDD */ if(limCheckMgmtRegisteredFrames(pMac, pRxPacketInfo, psessionEntry)) { - limLog( pMac, LOG1, FL("Received frame is passed to SME\n")); + limLog( pMac, LOG1, FL("Received frame is passed to SME")); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, limMsg->bodyptr); return; } @@ -634,7 +661,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) if (fc.protVer != SIR_MAC_PROTOCOL_VERSION) { // Received Frame with non-zero Protocol Version - limLog(pMac, LOGE, FL("Unexpected frame with protVersion %d received\n"), + limLog(pMac, LOGE, FL("Unexpected frame with protVersion %d received"), fc.protVer); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr); #ifdef WLAN_DEBUG @@ -654,7 +681,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) #if 0 if (psessionEntry->limSystemRole == eLIM_UNKNOWN_ROLE) { - limLog( pMac, LOGW, FL( "gLimSystemRole is %d. Exiting...\n" ),psessionEntry->limSystemRole ); + limLog( pMac, LOGW, FL( "gLimSystemRole is %d. Exiting..." ),psessionEntry->limSystemRole ); limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr); #ifdef WLAN_DEBUG @@ -677,7 +704,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) if (limIsReassocInProgress( pMac,psessionEntry) && (fc.subType != SIR_MAC_MGMT_DISASSOC) && (fc.subType != SIR_MAC_MGMT_DEAUTH) && (fc.subType != SIR_MAC_MGMT_REASSOC_RSP)) { - limLog(pMac, LOGE, FL("Frame with Type - %d, Subtype - %d received in ReAssoc Wait state, dropping...\n"), + limLog(pMac, LOGE, FL("Frame with Type - %d, Subtype - %d received in ReAssoc Wait state, dropping..."), fc.type, fc.subType); return; } @@ -695,7 +722,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) else { // Unwanted messages - Log error - limLog(pMac, LOGE, FL("unexpected message received %X\n"),limMsg->type); + limLog(pMac, LOGE, FL("unexpected message received %X"),limMsg->type); limPrintMsgName(pMac, LOGE, limMsg->type); } break; @@ -714,7 +741,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) else { // Unwanted messages - Log error - limLog(pMac, LOGE, FL("unexpected message received %X\n"),limMsg->type); + limLog(pMac, LOGE, FL("unexpected message received %X"),limMsg->type); limPrintMsgName(pMac, LOGE, limMsg->type); } break; @@ -781,7 +808,7 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) tANI_U8 *rfc1042Hdr = (tANI_U8 *)(dataOffset + RFC1042_HDR_LENGTH) ; tANI_U16 ethType = GET_BE16(rfc1042Hdr) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS frame with 80211 Header\n")) ; + ("TDLS frame with 80211 Header")) ; if(ETH_TYPE_89_0d == ethType) { tANI_U8 payloadType = (rfc1042Hdr + ETH_TYPE_LEN)[0] ; @@ -808,6 +835,9 @@ limHandle80211Frames(tpAniSirGlobal pMac, tpSirMsgQ limMsg, tANI_U8 *pDeferMsg) } // switch (fc.type) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +end: +#endif limPktFree(pMac, HAL_TXRX_FRM_802_11_MGMT, pRxPacketInfo, (void *) limMsg->bodyptr) ; return; } /*** end limHandle80211Frames() ***/ @@ -850,13 +880,13 @@ limProcessAbortScanInd(tpAniSirGlobal pMac) (eLIM_HAL_FINISH_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState) ) { //Simply signal we need to abort - limLog( pMac, LOGW, FL(" waiting for HAL, simply signal abort gLimHalScanState = %d\n"), pMac->lim.gLimHalScanState ); + limLog( pMac, LOGW, FL(" waiting for HAL, simply signal abort gLimHalScanState = %d"), pMac->lim.gLimHalScanState ); pMac->lim.abortScan = 1; } else { //Force abort - limLog( pMac, LOGW, FL(" Force aborting scan\n") ); + limLog( pMac, LOGW, FL(" Force aborting scan") ); pMac->lim.abortScan = 0; limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); @@ -911,7 +941,7 @@ void limOemDataRspHandleResumeLinkRsp(tpAniSirGlobal pMac, eHalStatus status, tA { if(status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGE, FL("OEM Data Rsp failed to get the response for resume link\n")); + limLog(pMac, LOGE, FL("OEM Data Rsp failed to get the response for resume link")); } if(NULL != pMac->lim.gpLimMlmOemDataReq) @@ -943,7 +973,7 @@ void limProcessOemDataRsp(tpAniSirGlobal pMac, tANI_U32* body) status = palAllocateMemory(pMac->hHdd, (void**)(&mlmOemDataRsp), sizeof(tLimMlmOemDataRsp)); if(status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("could not allocate memory for mlmOemDataRsp\n")); + limLog(pMac, LOGP, FL("could not allocate memory for mlmOemDataRsp")); return; } @@ -1007,7 +1037,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) #endif - PELOG3(limLog(pMac, LOG3, FL("rcvd msgType = %s, sme state = %s, mlm state = %s\n"), + PELOG3(limLog(pMac, LOG3, FL("rcvd msgType = %s, sme state = %s, mlm state = %s"), limMsgStr(limMsg->type), limSmeStateStr(pMac->lim.gLimSmeState), limMlmStateStr(pMac->lim.gLimMlmState));) @@ -1030,7 +1060,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) { if(!(pMac->lim.deferredMsgCnt & 0xF)) { - PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)\n"), + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) } @@ -1130,10 +1160,10 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if ( deferMsg == true ) { - PELOG1(limLog(pMac, LOG1, FL("Defer message type=%X \n"), limMsg->type);) + PELOG1(limLog(pMac, LOG1, FL("Defer message type=%X "), limMsg->type);) if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)\n"), + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) limLogSessionStates(pMac); @@ -1284,7 +1314,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tANI_U8 i; tANI_U8 p2pGOExists = 0; - limLog(pMac, LOG1, "LIM received NOA start %x\n", limMsg->type); + limLog(pMac, LOG1, "LIM received NOA start %x", limMsg->type); /* Since insert NOA is done and NOA start msg received, we should deactivate the Insert NOA timer */ limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); @@ -1300,7 +1330,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if (psessionEntry->p2pGoPsNoaStartInd.status != eHAL_STATUS_SUCCESS) { limLog(pMac, LOGW, FL("GO NOA start failure status %d reported by FW." - " - still go ahead with deferred sme req. This is just info\n"), + " - still go ahead with deferred sme req. This is just info"), psessionEntry->p2pGoPsNoaStartInd.status); } break; @@ -1310,7 +1340,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if (p2pGOExists == 0) { limLog(pMac, LOGW, FL("By the time, we received NOA start, GO is already removed." - " - still go ahead with deferred sme req. This is just info\n")); + " - still go ahead with deferred sme req. This is just info")); } /* We received the NOA start indication. Now we can send down the SME request which requires off-channel operation */ @@ -1325,7 +1355,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tpPESession psessionEntry = &pMac->lim.gpSession[0]; tANI_U8 i; - limLog(pMac, LOGW, FL("Received message Noa_ATTR %x\n"), limMsg->type); + limLog(pMac, LOGW, FL("Received message Noa_ATTR %x"), limMsg->type); for(i=0; i < pMac->lim.maxBssId; i++) { psessionEntry = &pMac->lim.gpSession[i]; @@ -1336,7 +1366,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) palCopyMemory(pMac->hHdd,&psessionEntry->p2pGoPsUpdate, limMsg->bodyptr,sizeof(tSirP2PNoaAttr)); - limLog(pMac, LOG2, FL(" &psessionEntry->bssId%02x:%02x:%02x:%02x:%02x:%02x ctWin=%d oppPsFlag=%d\n"), + limLog(pMac, LOG2, FL(" &psessionEntry->bssId%02x:%02x:%02x:%02x:%02x:%02x ctWin=%d oppPsFlag=%d"), psessionEntry->bssId[0], psessionEntry->bssId[1], psessionEntry->bssId[2], @@ -1346,7 +1376,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) psessionEntry->p2pGoPsUpdate.ctWin, psessionEntry->p2pGoPsUpdate.oppPsFlag); - limLog(pMac, LOG2, FL(" uNoa1IntervalCnt=%d uNoa1Duration=%d uNoa1Interval=%d uNoa1StartTime=%d\n"), + limLog(pMac, LOG2, FL(" uNoa1IntervalCnt=%d uNoa1Duration=%d uNoa1Interval=%d uNoa1StartTime=%d"), psessionEntry->p2pGoPsUpdate.uNoa1IntervalCnt, psessionEntry->p2pGoPsUpdate.uNoa1Duration, psessionEntry->p2pGoPsUpdate.uNoa1Interval, @@ -1434,7 +1464,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) limProcessAddBaInd(pMac, limMsg); break; case SIR_LIM_DEL_BA_ALL_IND: - limDelAllBASessions(pMac); // refer notes and change + limDelAllBASessions(pMac); break; case SIR_LIM_DEL_BA_IND: limProcessMlmHalBADeleteInd( pMac, limMsg ); @@ -1483,7 +1513,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) */ #if 0 - PELOG1(limLog(pMac, LOG1, FL("Heartbeat timeout, SME %d, MLME %d, #bcn %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Heartbeat timeout, SME %d, MLME %d, #bcn %d"), pMac->lim.gLimSmeState, pMac->lim.gLimMlmState, pMac->lim.gLimRxedBeaconCntDuringHB);) @@ -1504,7 +1534,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) // Defer processsing this message if (limDeferMsg(pMac, limMsg) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)\n"), + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), limMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) limLogSessionStates(pMac); @@ -1619,12 +1649,12 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId) ; if(NULL == psessionEntry) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID %d\n"), pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID %d"), pMac->lim.limTimers.gLimTdlsDisRspWaitTimer.sessionId); return; } VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, - ("Discovery Rsp timer expires \n")) ; + ("Discovery Rsp timer expires ")) ; #if 0 // TDLS_hklee: D13 no need to open Addr2 unknown data packet /* restore RXP filters */ limSetLinkState(pMac, eSIR_LINK_FINISH_TDLS_DISCOVERY_STATE, @@ -1645,11 +1675,11 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tLimTdlsLinkSetupPeer *setupPeer = NULL ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS setup rsp timer expires \n")) ; + ("TDLS setup rsp timer expires ")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("TDLS setup rsp timer expires for peer:\n")) ; + ("TDLS setup rsp timer expires for peer:")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("%02X, %02X, %02X,%02X, %02X, %02X\n"), + ("%02X, %02X, %02X,%02X, %02X, %02X"), peerMac[0], peerMac[1], peerMac[2], @@ -1673,11 +1703,11 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) tLimTdlsLinkSetupPeer *setupPeer = NULL ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS setup CNF timer expires \n")) ; + ("TDLS setup CNF timer expires ")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("TDLS setup CNF timer expires for peer:\n")) ; + ("TDLS setup CNF timer expires for peer:")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("%02X, %02X, %02X,%02X, %02X, %02X\n"), + ("%02X, %02X, %02X,%02X, %02X, %02X"), peerMac[0], peerMac[1], peerMac[2], @@ -1772,7 +1802,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) case SIR_LIM_ADDR2_MISS_IND: { limLog(pMac, LOGE, - FL("Addr2 mismatch interrupt received %X\n"), + FL("Addr2 mismatch interrupt received %X"), limMsg->type); /*a message from HAL indicating addr2 mismatch interrupt occurred limMsg->bodyptr contains only pointer to 48-bit addr2 field*/ @@ -1830,7 +1860,7 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) // sending beacon filtering information down to HAL if (limSendBeaconFilterInfo(pMac, psessionEntry) != eSIR_SUCCESS) { - limLog(pMac, LOGE, FL("Fail to send Beacon Filter Info \n")); + limLog(pMac, LOGE, FL("Fail to send Beacon Filter Info ")); } } vos_mem_free((v_VOID_t *)(limMsg->bodyptr)); @@ -1844,14 +1874,14 @@ limProcessMessages(tpAniSirGlobal pMac, tpSirMsgQ limMsg) // Unwanted messages // Log error limLog(pMac, LOGE, - FL("Discarding unexpected message received %X\n"), + FL("Discarding unexpected message received %X"), limMsg->type); limPrintMsgName(pMac, LOGE, limMsg->type); break; } // switch (limMsg->type) - PELOG2(limLog(pMac, LOG2, FL("Done Processing msgType = %d, sme state = %s, mlm state = %s\n"), + PELOG2(limLog(pMac, LOG2, FL("Done Processing msgType = %d, sme state = %s, mlm state = %s"), limMsg->type, limSmeStateStr(pMac->lim.gLimSmeState), limMlmStateStr(pMac->lim.gLimMlmState));) @@ -1958,7 +1988,7 @@ void limProcessNormalHddMsg(tpAniSirGlobal pMac, tSirMsgQ *pLimMsg, tANI_U8 fRsp #ifdef WLAN_DEBUG pMac->lim.numSme++; #endif - PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)\n"), + PELOGE(limLog(pMac, LOGE, FL("Unable to Defer message(0x%X) limSmeState %d (prev sme state %d) sysRole %d mlm state %d (prev mlm state %d)"), pLimMsg->type, pMac->lim.gLimSmeState, pMac->lim.gLimPrevSmeState, pMac->lim.gLimSystemRole, pMac->lim.gLimMlmState, pMac->lim.gLimPrevMlmState);) limLogSessionStates(pMac); @@ -2002,7 +2032,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_CAP_INFO value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_CAP_INFO value")); return ; } ptr = (tANI_U8 *) &macHTCapabilityInfo; @@ -2018,7 +2048,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr if (wlan_cfgGetInt(pMac, WNI_CFG_HT_AMPDU_PARAMS, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_PARAM_INFO value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_PARAM_INFO value")); return ; } ptr = (tANI_U8 *) &macHTParametersInfo; @@ -2029,7 +2059,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr // Get HT IE Info if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD1, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD1 value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD1 value")); return ; } ptr = (tANI_U8 *) &macHTInfoField1; @@ -2040,7 +2070,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD2, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD2 value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD2 value")); return ; } ptr = (tANI_U8 *) &macHTInfoField2; @@ -2049,7 +2079,7 @@ handleHTCapabilityandHTInfo(struct sAniSirGlobal *pMac, tpPESession psessionEntr if (wlan_cfgGetInt(pMac, WNI_CFG_HT_INFO_FIELD3, &cfgValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD3 value\n")); + limLog(pMac, LOGP, FL("Fail to retrieve WNI_CFG_HT_INFO_FIELD3 value")); return ; } ptr = (tANI_U8 *) &macHTInfoField3; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c index 36edb28c641..f015dd271a0 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmReqMessages.c @@ -220,7 +220,7 @@ limSetScanMode(tpAniSirGlobal pMac) else checkTraffic = eSIR_CHECK_ROAMING_SCAN; - PELOG1(limLog(pMac, LOG1, FL("Calling limSendHalInitScanReq\n"));) + PELOG1(limLog(pMac, LOG1, FL("Calling limSendHalInitScanReq"));) limSendHalInitScanReq(pMac, eLIM_HAL_INIT_SCAN_WAIT_STATE, checkTraffic); return ; @@ -275,13 +275,13 @@ limSuspendLink(tpAniSirGlobal pMac, tSirLinkTrafficCheck trafficCheck, SUSPEND_ { if( NULL == callback ) { - limLog( pMac, LOGE, "%s:%d: Invalid parameters\n", __func__, __LINE__ ); + limLog( pMac, LOGE, "%s:%d: Invalid parameters", __func__, __LINE__ ); return; } if( pMac->lim.gpLimSuspendCallback ) { - limLog( pMac, LOGE, "%s:%d: gLimSuspendLink callback is not NULL...something is wrong\n", __func__, __LINE__ ); + limLog( pMac, LOGE, "%s:%d: gLimSuspendLink callback is not NULL...something is wrong", __func__, __LINE__ ); callback( pMac, eHAL_STATUS_FAILURE, data ); return; } @@ -318,13 +318,13 @@ limResumeLink(tpAniSirGlobal pMac, SUSPEND_RESUME_LINK_CALLBACK callback, tANI_U { if( NULL == callback ) { - limLog( pMac, LOGE, "%s:%d: Invalid parameters\n", __func__, __LINE__ ); + limLog( pMac, LOGE, "%s:%d: Invalid parameters", __func__, __LINE__ ); return; } if( pMac->lim.gpLimResumeCallback ) { - limLog( pMac, LOGE, "%s:%d: gLimResumeLink callback is not NULL...something is wrong\n", __func__, __LINE__ ); + limLog( pMac, LOGE, "%s:%d: gLimResumeLink callback is not NULL...something is wrong", __func__, __LINE__ ); callback( pMac, eHAL_STATUS_FAILURE, data ); return; } @@ -358,7 +358,7 @@ limChangeChannelWithCallback(tpAniSirGlobal pMac, tANI_U8 newChannel, { // Sanity checks for the current and new channel #if defined WLAN_VOWIFI_DEBUG - PELOGE(limLog( pMac, LOGE, "Switching channel to %d\n", newChannel);) + PELOGE(limLog( pMac, LOGE, "Switching channel to %d", newChannel);) #endif psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION; @@ -419,14 +419,14 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) (limActiveScanAllowed(pMac, channelNum))) { TX_TIMER *periodicScanTimer; - PELOG2(limLog(pMac, LOG2, FL("ACTIVE Scan chan %d, sending probe\n"), channelNum);) + PELOG2(limLog(pMac, LOG2, FL("ACTIVE Scan chan %d, sending probe"), channelNum);) do { /* Prepare and send Probe Request frame for all the SSIDs present in the saved MLM */ - PELOGE(limLog(pMac, LOG1, FL("sending ProbeReq number %d, for SSID %s on channel: %d\n"), + PELOGE(limLog(pMac, LOG1, FL("sending ProbeReq number %d, for SSID %s on channel: %d"), i, pMac->lim.gpLimMlmScanReq->ssId[i].ssId, channelNum);) // include additional IE if there is status = limSendProbeReqMgmtFrame( pMac, &pMac->lim.gpLimMlmScanReq->ssId[i], @@ -437,7 +437,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) if ( status != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("send ProbeReq failed for SSID %s on channel: %d\n"), + PELOGE(limLog(pMac, LOGE, FL("send ProbeReq failed for SSID %s on channel: %d"), pMac->lim.gpLimMlmScanReq->ssId[i].ssId, channelNum);) limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limSendHalEndScanReq(pMac, channelNum, eLIM_HAL_END_SCAN_WAIT_STATE); @@ -469,7 +469,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) if (tx_timer_activate(&pMac->lim.limTimers.gLimMinChannelTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not start min channel timer\n")); + limLog(pMac, LOGP, FL("could not start min channel timer")); return; } @@ -480,7 +480,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) else { #if defined WLAN_VOWIFI_DEBUG - PELOGE(limLog( pMac, LOGE, "Min channel time == 0, Use only max chan timer\n" );) + PELOGE(limLog( pMac, LOGE, "Min channel time == 0, Use only max chan timer" );) #endif //No Need to start Min channel timer. Start Max Channel timer. limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); @@ -490,7 +490,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) { /// Could not activate max channel timer. // Log error - limLog(pMac,LOGP, FL("could not start max channel timer\n")); + limLog(pMac,LOGP, FL("could not start max channel timer")); return; } @@ -503,7 +503,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) if (tx_timer_activate(periodicScanTimer) != TX_SUCCESS) { limLog(pMac, LOGP, FL("could not start periodic probe req " - "timer\n")); + "timer")); return; } periodicScanTimer->sessionId = channelNum; @@ -512,7 +512,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) else { tANI_U32 val; - PELOG2(limLog(pMac, LOG2, FL("START PASSIVE Scan chan %d\n"), channelNum);) + PELOG2(limLog(pMac, LOG2, FL("START PASSIVE Scan chan %d"), channelNum);) /// Passive Scanning. Activate maxChannelTimer MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, NO_SESSION, eLIM_MAX_CHANNEL_TIMER)); @@ -521,7 +521,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) { // Could not deactivate max channel timer. // Log error - limLog(pMac, LOGP, FL("Unable to deactivate max channel timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate max channel timer")); return; } else @@ -533,7 +533,7 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) * Could not get max channel value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve passive max channel value\n")); + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); return; } else @@ -567,12 +567,12 @@ void limContinuePostChannelScan(tpAniSirGlobal pMac) { // Could not change max channel timer. // Log error - limLog(pMac, LOGP, FL("Unable to change max channel timer\n")); + limLog(pMac, LOGP, FL("Unable to change max channel timer")); return; } else if (tx_timer_activate(&pMac->lim.limTimers.gLimMaxChannelTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not start max channel timer\n")); + limLog(pMac, LOGP, FL("could not start max channel timer")); return; } @@ -701,27 +701,35 @@ void limSetDFSChannelList(tpAniSirGlobal pMac,tANI_U8 channelNum, tSirDFSChannel { tANI_BOOLEAN passiveToActive = TRUE; - if (eANI_BOOLEAN_TRUE == limIsconnectedOnDFSChannel(channelNum)) + if ((1 <= channelNum) && (165 >= channelNum)) { - if (dfsChannelList->timeStamp[channelNum] == 0) - { - //Received first beacon; Convert DFS channel to Active channel. - PELOG1(limLog(pMac, LOG1, FL("Received first beacon on DFS channel: %d"), channelNum);) - limCovertChannelScanType(pMac,channelNum, passiveToActive); - } - dfsChannelList->timeStamp[channelNum] = vos_timer_get_system_time(); + if (eANI_BOOLEAN_TRUE == limIsconnectedOnDFSChannel(channelNum)) + { + if (dfsChannelList->timeStamp[channelNum] == 0) + { + //Received first beacon; Convert DFS channel to Active channel. + PELOG1(limLog(pMac, LOG1, FL("Received first beacon on DFS channel: %d"), channelNum);) + limCovertChannelScanType(pMac,channelNum, passiveToActive); + } + dfsChannelList->timeStamp[channelNum] = vos_timer_get_system_time(); + } + else + { + PELOG1(limLog(pMac, LOG1, FL("Channel %d is Active"), channelNum);) + return; + } + if (!tx_timer_running(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer)) + { + tx_timer_activate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + } } else { - PELOG1(limLog(pMac, LOG1, FL("Channel %d is Active"), channelNum);) - return; - } - if (!tx_timer_running(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer)) - { - tx_timer_activate(&pMac->lim.limTimers.gLimActiveToPassiveChannelTimer); + PELOGE(limLog(pMac, LOGE, FL("Invalid Channel: %d"), channelNum);) + return; } - return ; + return; } @@ -832,7 +840,7 @@ limSendHalInitScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState, tSirLi if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pInitScanParam, sizeof(*pInitScanParam))) { - PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed\n"));) + PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed"));) goto error; } @@ -903,14 +911,14 @@ limSendHalInitScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState, tSirLi rc = wdaPostCtrlMsg(pMac, &msg); if (rc == eSIR_SUCCESS) { - PELOG3(limLog(pMac, LOG3, FL("wdaPostCtrlMsg() return eSIR_SUCCESS pMac=%x nextState=%d\n"), + PELOG3(limLog(pMac, LOG3, FL("wdaPostCtrlMsg() return eSIR_SUCCESS pMac=%x nextState=%d"), pMac, pMac->lim.gLimHalScanState);) return; } SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void *)pInitScanParam); - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) error: switch(nextState) @@ -957,7 +965,7 @@ limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanSt (void **)&pStartScanParam, sizeof(*pStartScanParam))) { - PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed\n"));) + PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed"));) goto error; } @@ -971,7 +979,7 @@ limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanSt SET_LIM_PROCESS_DEFD_MESGS(pMac, false); MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); - limLog(pMac, LOG1, FL("Channel %d\n"), channelNum); + limLog(pMac, LOG1, FL("Channel %d"), channelNum); rc = wdaPostCtrlMsg(pMac, &msg); if (rc == eSIR_SUCCESS) { @@ -980,7 +988,7 @@ limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanSt SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void *)pStartScanParam); - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) error: switch(nextState) @@ -998,7 +1006,7 @@ limSendHalStartScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalScanSt } else { - PELOGW(limLog(pMac, LOGW, FL("Invalid state for START_SCAN_REQ message=%d\n"), pMac->lim.gLimHalScanState);) + PELOGW(limLog(pMac, LOGW, FL("Invalid state for START_SCAN_REQ message=%d"), pMac->lim.gLimHalScanState);) } return; @@ -1021,7 +1029,7 @@ void limSendHalEndScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalSca if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pEndScanParam, sizeof(*pEndScanParam))) { - PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed\n"));) + PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed"));) goto error; } @@ -1042,7 +1050,7 @@ void limSendHalEndScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalSca SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void *)pEndScanParam); - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) error: switch(nextState) @@ -1053,15 +1061,15 @@ void limSendHalEndScanReq(tpAniSirGlobal pMac, tANI_U8 channelNum, tLimLimHalSca default: - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg Rcvd invalid nextState %d\n"), nextState);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg Rcvd invalid nextState %d"), nextState);) break; } pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) } else { - PELOGW(limLog(pMac, LOGW, FL("Invalid state for END_SCAN_REQ message=%d\n"), pMac->lim.gLimHalScanState);) + PELOGW(limLog(pMac, LOGW, FL("Invalid state for END_SCAN_REQ message=%d"), pMac->lim.gLimHalScanState);) } @@ -1102,7 +1110,7 @@ void limSendHalFinishScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState) * this check will avoid that. * If PE is already waiting for the 'finish_scan_rsp' message from HAL, it will ignore this request. */ - PELOGW(limLog(pMac, LOGW, FL("Next Scan State is same as the current state: %d \n"), nextState);) + PELOGW(limLog(pMac, LOGW, FL("Next Scan State is same as the current state: %d "), nextState);) return; } @@ -1110,7 +1118,7 @@ void limSendHalFinishScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pFinishScanParam, sizeof(*pFinishScanParam))) { - PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed\n"));) + PELOGW(limLog(pMac, LOGW, FL("palAllocateMemory() failed"));) goto error; } @@ -1163,7 +1171,7 @@ void limSendHalFinishScanReq(tpAniSirGlobal pMac, tLimLimHalScanState nextState) } SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void *)pFinishScanParam); - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d\n"), rc);) + PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg failed, error code %d"), rc);) error: if(nextState == eLIM_HAL_FINISH_SCAN_WAIT_STATE) @@ -1217,7 +1225,7 @@ limContinueChannelScan(tpAniSirGlobal pMac) { tANI_U8 channelNum; - PELOG1(limLog(pMac, LOG1, FL("Continue SCAN : chan %d tot %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Continue SCAN : chan %d tot %d"), pMac->lim.gLimCurrentScanChannelId, pMac->lim.gpLimMlmScanReq->channelList.numChannels);) @@ -1251,7 +1259,7 @@ limContinueChannelScan(tpAniSirGlobal pMac) ((limGetCurrentScanChannel(pMac) > 14) && pMac->lim.gLim50Band11dScanDone)) { - limLog(pMac, LOGW, FL("skipping chan %d\n"), + limLog(pMac, LOGW, FL("skipping chan %d"), limGetCurrentScanChannel(pMac)); pMac->lim.gLimCurrentScanChannelId++; } @@ -1275,7 +1283,7 @@ limContinueChannelScan(tpAniSirGlobal pMac) } channelNum = limGetCurrentScanChannel(pMac); - PELOG2(limLog(pMac, LOG2, FL("Current Channel to be scanned is %d\n"), + PELOG2(limLog(pMac, LOG2, FL("Current Channel to be scanned is %d"), channelNum);) limSendHalStartScanReq(pMac, channelNum, eLIM_HAL_START_SCAN_WAIT_STATE); @@ -1337,7 +1345,7 @@ limRestorePreScanState(tpAniSirGlobal pMac) //limCleanupMsgQ(pMac); pMac->lim.gLimSystemInScanLearnMode = 0; - PELOG1(limLog(pMac, LOG1, FL("Scan ended, took %d tu\n"), (tx_time_get() - pMac->lim.scanStartTime));) + PELOG1(limLog(pMac, LOG1, FL("Scan ended, took %d tu"), (tx_time_get() - pMac->lim.scanStartTime));) } /*** limRestorePreScanState() ***/ #ifdef FEATURE_OEM_DATA_SUPPORT @@ -1351,7 +1359,7 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) tANI_U32 reqLen = 0; if(NULL == pMac->lim.gpLimMlmOemDataReq) { - PELOGE(limLog(pMac, LOGE, FL("Null pointer\n"));) + PELOGE(limLog(pMac, LOGE, FL("Null pointer"));) goto error; } @@ -1359,7 +1367,7 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)&pStartOemDataReq, reqLen)) { - PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Could not allocate memory for pStartOemDataReq\n"));) + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Could not allocate memory for pStartOemDataReq"));) goto error; } @@ -1386,7 +1394,7 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) SET_LIM_PROCESS_DEFD_MESGS(pMac, true); palFreeMemory(pMac->hHdd, (void*)pStartOemDataReq); - PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: posting WDA_START_OEM_DATA_REQ to HAL failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: posting WDA_START_OEM_DATA_REQ to HAL failed"));) error: pMac->lim.gLimMlmState = pMac->lim.gLimPrevMlmState; @@ -1394,7 +1402,7 @@ void limSendHalOemDataReq(tpAniSirGlobal pMac) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)(&pMlmOemDataRsp), sizeof(tLimMlmOemDataRsp))) { - limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure\n")); + limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure")); return; } @@ -1435,7 +1443,7 @@ void limSetOemDataReqModeFailed(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)(&pMlmOemDataRsp), sizeof(tLimMlmOemDataRsp))) { - limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure\n")); + limLog(pMac->hHdd, LOGP, FL("OEM_DATA: memory allocation for pMlmOemDataRsp failed under suspend link failure")); return; } @@ -1474,12 +1482,12 @@ void limSetOemDataReqMode(tpAniSirGlobal pMac, eHalStatus status, tANI_U32* data { if(status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGE, FL("OEM_DATA: failed in suspend link\n")); + limLog(pMac, LOGE, FL("OEM_DATA: failed in suspend link")); goto error; } else { - PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Calling limSendHalOemDataReq\n"));) + PELOGE(limLog(pMac, LOGE, FL("OEM_DATA: Calling limSendHalOemDataReq"));) limSendHalOemDataReq(pMac); return; } @@ -1511,12 +1519,12 @@ mlm_add_sta( /* Configuration related parameters to be changed to support BT-AMP */ if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_LISTEN_INTERVAL, &val )) - limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL\n")); + limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); pSta->listenInterval = (tANI_U16) val; if (eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) ) - limLog(pMac, LOGP, FL("Couldn't get SHORT_PREAMBLE\n")); + limLog(pMac, LOGP, FL("Couldn't get SHORT_PREAMBLE")); pSta->shortPreambleSupported = (tANI_U8)val; pSta->assocId = 0; // Is SMAC OK with this? @@ -1562,7 +1570,7 @@ mlm_add_sta( #endif limFillSupportedRatesInfo(pMac, NULL, &pSta->supportedRates,psessionEntry); - limLog( pMac, LOGE, FL( "GF: %d, ChnlWidth: %d, MimoPS: %d, lsigTXOP: %d, dsssCCK: %d, SGI20: %d, SGI40%d\n") , + limLog( pMac, LOGE, FL( "GF: %d, ChnlWidth: %d, MimoPS: %d, lsigTXOP: %d, dsssCCK: %d, SGI20: %d, SGI40%d") , pSta->greenFieldCapable, pSta->txChannelWidthSet, pSta->mimoPS, pSta->lsigTxopProtection, pSta->fDsssCckMode40Mhz,pSta->fShortGI20Mhz, pSta->fShortGI40Mhz); @@ -1599,7 +1607,7 @@ limMlmAddBss ( if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pAddBssParams, sizeof( tAddBssParams ))) { - limLog( pMac, LOGE, FL( "Unable to PAL allocate memory during ADD_BSS\n" )); + limLog( pMac, LOGE, FL( "Unable to PAL allocate memory during ADD_BSS" )); // Respond to SME with LIM_MLM_START_CNF return eSIR_SME_HAL_SEND_MESSAGE_FAIL; } @@ -1661,7 +1669,7 @@ limMlmAddBss ( pMlmStartReq->ssId.length); pAddBssParams->ssId.length = pMlmStartReq->ssId.length; pAddBssParams->bHiddenSSIDEn = pMlmStartReq->ssidHidden; - limLog( pMac, LOGE, FL( "TRYING TO HIDE SSID %d\n" ),pAddBssParams->bHiddenSSIDEn); + limLog( pMac, LOGE, FL( "TRYING TO HIDE SSID %d" ),pAddBssParams->bHiddenSSIDEn); // CR309183. Disable Proxy Probe Rsp. Host handles Probe Requests. Until FW fixed. pAddBssParams->bProxyProbeRespEn = 0; pAddBssParams->obssProtEnabled = pMlmStartReq->obssProtEnabled; @@ -1698,10 +1706,10 @@ limMlmAddBss ( msgQ.bodyval = 0; MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); - limLog( pMac, LOGW, FL( "Sending WDA_ADD_BSS_REQ...\n" )); + limLog( pMac, LOGW, FL( "Sending WDA_ADD_BSS_REQ..." )); if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { - limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X\n"), retCode ); + limLog( pMac, LOGE, FL("Posting ADD_BSS_REQ to HAL failed, reason=%X"), retCode ); palFreeMemory(pMac->hHdd,(void *)pAddBssParams); return eSIR_SME_HAL_SEND_MESSAGE_FAIL; } @@ -1741,14 +1749,14 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmStartReq = (tLimMlmStartReq *) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmStartReq->sessionId))==NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); mlmStartCnf.resultCode = eSIR_SME_REFUSED; goto end; } @@ -1759,7 +1767,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Should not have received Start req in states other than idle. * Return Start confirm with failure code. */ - PELOGE(limLog(pMac, LOGE, FL("received unexpected MLM_START_REQ in state %X\n"),psessionEntry->limMlmState);) + PELOGE(limLog(pMac, LOGE, FL("received unexpected MLM_START_REQ in state %X"),psessionEntry->limMlmState);) limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); mlmStartCnf.resultCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; goto end; @@ -1767,7 +1775,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #if 0 if (cfgSetInt(pMac, WNI_CFG_CURRENT_CHANNEL, pMlmStartReq->channelNumber)!= eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not set CURRENT_CHANNEL at CFG\n")); + limLog(pMac, LOGP, FL("could not set CURRENT_CHANNEL at CFG")); pMac->lim.gLimCurrentChannelId = pMlmStartReq->channelNumber; #endif //TO SUPPORT BT-AMP @@ -1777,7 +1785,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #if 0 //We are not using the BSSID and SSID from the config file, instead we are reading form the session table if (cfgSetStr(pMac, WNI_CFG_BSSID, (tANI_U8 *) pMlmStartReq->bssId, sizeof(tSirMacAddr)) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not update BSSID at CFG\n")); + limLog(pMac, LOGP, FL("could not update BSSID at CFG")); @@ -1789,7 +1797,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #if 0 if (cfgSetStr(pMac, WNI_CFG_SSID, (tANI_U8 *) &pMlmStartReq->ssId.ssId, pMlmStartReq->ssId.length) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not update SSID at CFG\n")); + limLog(pMac, LOGP, FL("could not update SSID at CFG")); #endif //To SUPPORT BT-AMP @@ -1800,7 +1808,7 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (tANI_U8 *) &pMac->lim.gpLimStartBssReq->operationalRateSet.rate, pMac->lim.gpLimStartBssReq->operationalRateSet.numRates) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not update Operational Rateset at CFG\n")); + limLog(pMac, LOGP, FL("could not update Operational Rateset at CFG")); #endif //TO SUPPORT BT-AMP @@ -1818,16 +1826,16 @@ limProcessMlmStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) SYS_MS_TO_TICKS(LIM_WPS_OVERLAP_TIMER_MS), // reschedule_ticks TX_AUTO_ACTIVATE /* TX_NO_ACTIVATE*/) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("failed to create WPS overlap Timer\n")); + limLog(pMac, LOGP, FL("failed to create WPS overlap Timer")); } pMac->lim.limTimers.gLimWPSOverlapTimerObj.sessionId = pMlmStartReq->sessionId; pMac->lim.limTimers.gLimWPSOverlapTimerObj.isTimerCreated = eANI_BOOLEAN_TRUE; - limLog(pMac, LOGE, FL("Create WPS overlap Timer, session=%d\n"), pMlmStartReq->sessionId); + limLog(pMac, LOGE, FL("Create WPS overlap Timer, session=%d"), pMlmStartReq->sessionId); if (tx_timer_activate(&pMac->lim.limTimers.gLimWPSOverlapTimerObj.gLimWPSOverlapTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("tx_timer_activate failed\n")); + limLog(pMac, LOGP, FL("tx_timer_activate failed")); } } } @@ -1928,7 +1936,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (pMac->lim.gLimSystemInScanLearnMode) { PELOGE(limLog(pMac, LOGE, - FL("Sending START_SCAN from LIM while one req is pending\n"));) + FL("Sending START_SCAN from LIM while one req is pending"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf); /*Send back a failure*/ mlmScanCnf.resultCode = eSIR_SME_SCAN_FAILED; @@ -1946,7 +1954,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Hold onto SCAN REQ criteria pMac->lim.gpLimMlmScanReq = (tLimMlmScanReq *) pMsgBuf; - PELOG3(limLog(pMac, LOG3, FL("Number of channels to scan are %d \n"), + PELOG3(limLog(pMac, LOG3, FL("Number of channels to scan are %d "), pMac->lim.gpLimMlmScanReq->channelList.numChannels);) pMac->lim.gLimPrevMlmState = pMac->lim.gLimMlmState; @@ -1970,7 +1978,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get max channel value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve passive max channel value\n")); + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); /* use a default value of 110ms */ val = 110; @@ -2003,7 +2011,7 @@ limProcessMlmScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ limLog(pMac, LOGW, - FL("received unexpected MLM_SCAN_REQ in state %X OR zero number of channels: %X\n"), + FL("received unexpected MLM_SCAN_REQ in state %X OR zero number of channels: %X"), pMac->lim.gLimMlmState, ((tLimMlmScanReq *) pMsgBuf)->channelList.numChannels); limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); @@ -2049,7 +2057,7 @@ static void limProcessMlmOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ - PELOGW(limLog(pMac, LOGW, FL("OEM_DATA: unexpected LIM_MLM_OEM_DATA_REQ in invalid state %X\n"),pMac->lim.gLimMlmState);) + PELOGW(limLog(pMac, LOGW, FL("OEM_DATA: unexpected LIM_MLM_OEM_DATA_REQ in invalid state %X"),pMac->lim.gLimMlmState);) limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); @@ -2064,7 +2072,7 @@ static void limProcessMlmOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } else { - limLog(pMac, LOGP, FL("Could not allocate memory for pMlmOemDataRsp\n")); + limLog(pMac, LOGP, FL("Could not allocate memory for pMlmOemDataRsp")); return; } } @@ -2107,7 +2115,7 @@ limProcessMlmPostJoinSuspendLink(tpAniSirGlobal pMac, eHalStatus status, tANI_U3 if( eHAL_STATUS_SUCCESS != status ) { - limLog(pMac, LOGE, FL("Suspend link(NOTIFY_BSS) failed. still proceeding with join\n")); + limLog(pMac, LOGE, FL("Suspend link(NOTIFY_BSS) failed. still proceeding with join")); } psessionEntry->limPrevMlmState = psessionEntry->limMlmState; psessionEntry->limMlmState = eLIM_MLM_WT_JOIN_BEACON_STATE; @@ -2119,13 +2127,13 @@ limProcessMlmPostJoinSuspendLink(tpAniSirGlobal pMac, eHalStatus status, tANI_U3 pMac->lim.limTimers.gLimJoinFailureTimer.sessionId = psessionEntry->peSessionId; linkState = ((psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE) ? eSIR_LINK_BTAMP_PREASSOC_STATE : eSIR_LINK_PREASSOC_STATE); - limLog(pMac, LOG1, FL("[limProcessMlmJoinReq]: linkState:%d\n"),linkState); + limLog(pMac, LOG1, FL("[limProcessMlmJoinReq]: linkState:%d"),linkState); if (limSetLinkState(pMac, linkState, psessionEntry->pLimMlmJoinReq->bssDescription.bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) { - limLog(pMac, LOGE, FL("limSetLinkState to eSIR_LINK_PREASSOC_STATE Failed!!\n")); + limLog(pMac, LOGE, FL("limSetLinkState to eSIR_LINK_PREASSOC_STATE Failed!!")); mlmJoinCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); @@ -2200,7 +2208,7 @@ limProcessMlmJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionBySessionId(pMac,sessionId))== NULL) { - limLog(pMac, LOGP, FL("session does not exist for given sessionId\n")); + limLog(pMac, LOGP, FL("session does not exist for given sessionId")); goto error; } @@ -2243,12 +2251,12 @@ limProcessMlmJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Return join confirm with invalid parameters code. */ PELOGE(limLog(pMac, LOGE, - FL("Unexpected Join request for role %d state %X\n"), + FL("Unexpected Join request for role %d state %X"), psessionEntry->limSystemRole, psessionEntry->limMlmState);) limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); - limLog(pMac, LOGE, FL("Unexpected Join request for role %d state %X\n"), + limLog(pMac, LOGE, FL("Unexpected Join request for role %d state %X"), psessionEntry->limSystemRole, psessionEntry->limMlmState); } @@ -2297,7 +2305,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -2305,7 +2313,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) sessionId = pMac->lim.gpLimMlmAuthReq->sessionId; if((psessionEntry= peFindSessionBySessionId(pMac,sessionId) )== NULL) { - limLog(pMac, LOGP, FL("Session Does not exist for given sessionId\n")); + limLog(pMac, LOGP, FL("Session Does not exist for given sessionId")); return; } @@ -2322,7 +2330,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //To SuppoRT BT-AMP @@ -2368,7 +2376,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMac->lim.gpLimMlmAuthReq->authType))) { PELOG2(limLog(pMac, LOG2, - FL("Already have pre-auth context with peer\n")); + FL("Already have pre-auth context with peer")); limPrintMacAddr(pMac, pMac->lim.gpLimMlmAuthReq->peerMacAddr, LOG2);) @@ -2384,13 +2392,13 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (tANI_U32 *) &numPreAuthContexts) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Could not retrieve NumPreAuthLimit from CFG\n")); + FL("Could not retrieve NumPreAuthLimit from CFG")); } if (pMac->lim.gLimNumPreAuthContexts == numPreAuthContexts) { PELOGW(limLog(pMac, LOGW, - FL("Number of pre-auth reached max limit\n"));) + FL("Number of pre-auth reached max limit"));) /// Return Auth confirm with reject code mlmAuthCnf.resultCode = @@ -2430,7 +2438,7 @@ limProcessMlmAuthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Could not start Auth failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Auth failure timer\n")); + FL("could not start Auth failure timer")); // Cleanup as if auth timer expired limProcessAuthFailureTimeout(pMac); } @@ -2494,14 +2502,14 @@ limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmAssocReq = (tLimMlmAssocReq *) pMsgBuf; if( (psessionEntry = peFindSessionBySessionId(pMac,pMlmAssocReq->sessionId) )== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmAssocReq); return; } @@ -2511,7 +2519,7 @@ limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -2537,7 +2545,7 @@ limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { if(limSetLinkState(pMac, eSIR_LINK_BTAMP_POSTASSOC_STATE, currentBssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState\n"));) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState"));) } /// Start association failure timer MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_ASSOC_FAIL_TIMER)); @@ -2547,7 +2555,7 @@ limProcessMlmAssocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Could not start Assoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Association failure timer\n")); + FL("could not start Association failure timer")); // Cleanup as if assoc timer expired limProcessAssocFailureTimeout(pMac,LIM_ASSOC ); @@ -2619,7 +2627,7 @@ limProcessMlmReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -2627,7 +2635,7 @@ limProcessMlmReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionBySessionId(pMac,pMlmReassocReq->sessionId)) == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Session Does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("Session Does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmReassocReq); return; } @@ -2674,7 +2682,7 @@ limProcessMlmReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) sizeof(tSirMacAddr)) != eSIR_SUCCESS) { /// Could not update BSSID at CFG. Log error. - limLog(pMac, LOGP, FL("could not update BSSID at CFG\n")); + limLog(pMac, LOGP, FL("could not update BSSID at CFG")); } #endif //TO SUPPORT BT-AMP @@ -2753,7 +2761,7 @@ limProcessMlmDisassocReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_ if(eHAL_STATUS_SUCCESS != suspendStatus) { - PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X\n"), suspendStatus);) + PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X"), suspendStatus);) #if 0 //It can ignore the status and proceed with the disassoc processing. mlmDisassocCnf.resultCode = eSIR_SME_REFUSED; @@ -2768,7 +2776,7 @@ limProcessMlmDisassocReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_ { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -2777,7 +2785,7 @@ limProcessMlmDisassocReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_ eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //BT-AMP Support sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -2919,12 +2927,12 @@ tANI_BOOLEAN limCheckDisassocDeauthAckPending(tpAniSirGlobal pMac, sizeof(tSirMacAddr)))) ) { - PELOGE(limLog(pMac, LOGE,FL("Disassoc/Deauth ack pending\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disassoc/Deauth ack pending"));) return eANI_BOOLEAN_TRUE; } else { - PELOGE(limLog(pMac, LOGE,FL("Disassoc/Deauth Ack not pending\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disassoc/Deauth Ack not pending"));) return eANI_BOOLEAN_FALSE; } } @@ -3014,7 +3022,7 @@ limProcessMlmDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -3024,7 +3032,7 @@ limProcessMlmDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) return; } @@ -3046,7 +3054,7 @@ limProcessMlmDeauthReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_U3 if(eHAL_STATUS_SUCCESS != suspendStatus) { - PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X\n"), suspendStatus);) + PELOGE(limLog(pMac, LOGE,FL("Suspend Status is not success %X"), suspendStatus);) #if 0 //It can ignore the status and proceed with the disassoc processing. mlmDisassocCnf.resultCode = eSIR_SME_REFUSED; @@ -3059,7 +3067,7 @@ limProcessMlmDeauthReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_U3 if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthReq->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMlmDeauthReq); return; } @@ -3068,7 +3076,7 @@ limProcessMlmDeauthReqNtf(tpAniSirGlobal pMac, eHalStatus suspendStatus, tANI_U3 eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //SUPPORT BT-AMP sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -3293,7 +3301,7 @@ limProcessMlmDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -3302,7 +3310,7 @@ limProcessMlmDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthReq->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId"));) return; } @@ -3343,7 +3351,7 @@ tpPESession psessionEntry; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -3354,12 +3362,12 @@ tpPESession psessionEntry; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmSetKeysReq->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) return; } limLog( pMac, LOGW, - FL( "Received MLM_SETKEYS_REQ with parameters:\n" + FL( "Received MLM_SETKEYS_REQ with parameters:" "AID [%d], ED Type [%d], # Keys [%d] & Peer MAC Addr - "), pMlmSetKeysReq->aid, pMlmSetKeysReq->edType, @@ -3368,7 +3376,7 @@ tpPESession psessionEntry; #if 0 if( eSIR_SUCCESS != wlan_cfgGetStr( pMac, WNI_CFG_BSSID, currentBssId, &cfg )) { - limLog( pMac, LOGP, FL("Could not retrieve BSSID\n")); + limLog( pMac, LOGP, FL("Could not retrieve BSSID")); return; } #endif //TO SUPPORT BT-AMP @@ -3383,7 +3391,7 @@ tpPESession psessionEntry; if((!limIsAddrBC( pMlmSetKeysReq->peerMacAddr ) ) && (!palEqualMemory( pMac->hHdd,pMlmSetKeysReq->peerMacAddr, currentBssId, sizeof(tSirMacAddr))) ){ - limLog( pMac, LOGW, FL("Received MLM_SETKEYS_REQ with invalid BSSID\n")); + limLog( pMac, LOGW, FL("Received MLM_SETKEYS_REQ with invalid BSSID")); limPrintMacAddr( pMac, pMlmSetKeysReq->peerMacAddr, LOGW ); // Prepare and Send LIM_MLM_SETKEYS_CNF with error code @@ -3406,7 +3414,7 @@ tpPESession psessionEntry; * pMlmSetKeysReq->key.unicast - 1 -> Unicast keys are being set */ if( limIsAddrBC( pMlmSetKeysReq->peerMacAddr )) { - limLog( pMac, LOG1, FL("Trying to set Group Keys...%d \n"), pMlmSetKeysReq->sessionId); + limLog( pMac, LOG1, FL("Trying to set Group Keys...%d "), pMlmSetKeysReq->sessionId); /** When trying to set Group Keys for any * security mode other than WEP, use the * STA Index corresponding to the AP... @@ -3424,7 +3432,7 @@ tpPESession psessionEntry; break; } }else { - limLog( pMac, LOG1, FL("Trying to set Unicast Keys...\n")); + limLog( pMac, LOG1, FL("Trying to set Unicast Keys...")); /** * Check if there exists a context for the * peer entity for which keys need to be set. @@ -3471,7 +3479,7 @@ tpPESession psessionEntry; defaultKeyId = 0; limLog( pMac, LOG1, - FL( "Trying to set keys for STA Index [%d], using defaultKeyId [%d]\n" ), + FL( "Trying to set keys for STA Index [%d], using defaultKeyId [%d]" ), staIdx, defaultKeyId ); @@ -3479,7 +3487,7 @@ tpPESession psessionEntry; psessionEntry->limPrevMlmState = psessionEntry->limMlmState; psessionEntry->limMlmState = eLIM_MLM_WT_SET_BSS_KEY_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); - limLog( pMac, LOG1, FL("Trying to set Group Keys...%d \n"), + limLog( pMac, LOG1, FL("Trying to set Group Keys...%d "), psessionEntry->peSessionId); // Package WDA_SET_BSSKEY_REQ message parameters @@ -3528,7 +3536,7 @@ tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -3538,7 +3546,7 @@ tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmRemoveKeyReq->sessionId))== NULL) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -3558,7 +3566,7 @@ tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; WNI_CFG_BSSID, currentBssId, &cfg )) - limLog( pMac, LOGP, FL("Could not retrieve BSSID\n")); + limLog( pMac, LOGP, FL("Could not retrieve BSSID")); #endif //TO-SUPPORT BT-AMP sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -3572,7 +3580,7 @@ tLimMlmRemoveKeyCnf mlmRemoveKeyCnf; sizeof(tSirMacAddr)))) { limLog( pMac, LOGW, - FL("Received MLM_REMOVEKEY_REQ with invalid BSSID\n")); + FL("Received MLM_REMOVEKEY_REQ with invalid BSSID")); limPrintMacAddr( pMac, pMlmRemoveKeyReq->peerMacAddr, LOGW ); // Prepare and Send LIM_MLM_REMOVEKEY_CNF with error code @@ -3676,7 +3684,7 @@ limProcessMinChannelTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimMinChannelTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } #endif @@ -3684,7 +3692,7 @@ limProcessMinChannelTimeout(tpAniSirGlobal pMac) if (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) { - PELOG1(limLog(pMac, LOG1, FL("Scanning : min channel timeout occurred\n"));) + PELOG1(limLog(pMac, LOG1, FL("Scanning : min channel timeout occurred"));) /// Min channel timer timed out pMac->lim.limTimers.gLimPeriodicProbeReqTimer.sessionId = 0xff; @@ -3719,7 +3727,7 @@ limProcessMinChannelTimeout(tpAniSirGlobal pMac) * Log error. */ limLog(pMac, LOGW, - FL("received unexpected MIN channel timeout in state %X\n"), + FL("received unexpected MIN channel timeout in state %X"), pMac->lim.gLimMlmState); limPrintMlmState(pMac, LOGE, pMac->lim.gLimMlmState); } @@ -3753,7 +3761,7 @@ limProcessMaxChannelTimeout(tpAniSirGlobal pMac) if (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE || pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) { - PELOG1(limLog(pMac, LOG1, FL("Scanning : Max channel timed out\n"));) + PELOG1(limLog(pMac, LOG1, FL("Scanning : Max channel timed out"));) /** * MAX channel timer timed out * Continue channel scan. @@ -3787,7 +3795,7 @@ limProcessMaxChannelTimeout(tpAniSirGlobal pMac) * Log error. */ limLog(pMac, LOGW, - FL("received unexpected MAX channel timeout in state %X\n"), + FL("received unexpected MAX channel timeout in state %X"), pMac->lim.gLimMlmState); limPrintMlmState(pMac, LOGW, pMac->lim.gLimMlmState); } @@ -3822,7 +3830,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) if(vos_timer_getCurrentState(&pPeriodicProbeReqTimer->vosTimer) != VOS_TIMER_STATE_STOPPED) { - PELOG1(limLog(pMac, LOG1, FL("Invalid state of timer\n"));) + PELOG1(limLog(pMac, LOG1, FL("Invalid state of timer"));) return; } @@ -3830,7 +3838,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) (pPeriodicProbeReqTimer->sessionId != 0xff)) { tLimMlmScanReq *pLimMlmScanReq = pMac->lim.gpLimMlmScanReq; - PELOG1(limLog(pMac, LOG1, FL("Scanning : Periodic scanning\n"));) + PELOG1(limLog(pMac, LOG1, FL("Scanning : Periodic scanning"));) /** * Periodic channel timer timed out * to send probe request. @@ -3844,7 +3852,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) /* * PELOGE(limLog(pMac, LOGW, FL("sending ProbeReq number %d," - * " for SSID %s on channel: %d\n"), + * " for SSID %s on channel: %d"), * i, pLimMlmScanReq->ssId[i].ssId, * channelNum);) */ @@ -3857,7 +3865,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) if ( status != eSIR_SUCCESS) { PELOGE(limLog(pMac, LOGE, FL("send ProbeReq failed for SSID " - "%s on channel: %d\n"), + "%s on channel: %d"), pLimMlmScanReq->ssId[i].ssId, channelNum);) return; @@ -3870,7 +3878,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) if (tx_timer_activate(pPeriodicProbeReqTimer) != TX_SUCCESS) { limLog(pMac, LOGP, FL("could not start periodic probe" - " req timer\n")); + " req timer")); return; } } @@ -3882,7 +3890,7 @@ limProcessPeriodicProbeReqTimer(tpAniSirGlobal pMac) * Log error. */ limLog(pMac, LOG1, - FL("received unexpected Periodic scan timeout in state %X\n"), + FL("received unexpected Periodic scan timeout in state %X"), pMac->lim.gLimMlmState); } } /*** limProcessPeriodicProbeReqTimer() ***/ @@ -3915,7 +3923,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimJoinFailureTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } @@ -3927,7 +3935,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); return; } @@ -3938,7 +3946,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) /** * Issue MLM join confirm with timeout reason code */ - PELOGE(limLog(pMac, LOGE, FL(" Join Failure Timeout occurred.\n"));) + PELOGE(limLog(pMac, LOGE, FL(" Join Failure Timeout occurred."));) mlmJoinCnf.resultCode = eSIR_SME_JOIN_TIMEOUT_RESULT_CODE; mlmJoinCnf.protStatusCode = eSIR_MAC_UNSPEC_FAILURE_STATUS; @@ -3947,7 +3955,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); if(limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState\n"));) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState"));) /* Update PE session Id */ mlmJoinCnf.sessionId = psessionEntry->peSessionId; @@ -3973,7 +3981,7 @@ limProcessJoinFailureTimeout(tpAniSirGlobal pMac) * Log error. */ limLog(pMac, LOGW, - FL("received unexpected JOIN failure timeout in state %X\n"),psessionEntry->limMlmState); + FL("received unexpected JOIN failure timeout in state %X"),psessionEntry->limMlmState); limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); } } /*** limProcessJoinFailureTimeout() ***/ @@ -4003,7 +4011,7 @@ static void limProcessPeriodicJoinProbeReqTimer(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer.sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given SessionId\n")); + limLog(pMac, LOGE,FL("session does not exist for given SessionId")); return; } @@ -4025,7 +4033,7 @@ static void limProcessPeriodicJoinProbeReqTimer(tpAniSirGlobal pMac) // Activate Join Periodic Probe Req timer if (tx_timer_activate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer\n")); + limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer")); return; } } @@ -4058,7 +4066,7 @@ limProcessAuthFailureTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimAuthFailureTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } @@ -4086,7 +4094,7 @@ limProcessAuthFailureTimeout(tpAniSirGlobal pMac) * in states other than wt_auth_frame2/4 * Log error. */ - PELOGE(limLog(pMac, LOGE, FL("received unexpected AUTH failure timeout in state %X\n"), psessionEntry->limMlmState);) + PELOGE(limLog(pMac, LOGE, FL("received unexpected AUTH failure timeout in state %X"), psessionEntry->limMlmState);) limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); break; @@ -4123,13 +4131,13 @@ limProcessAuthRspTimeout(tpAniSirGlobal pMac, tANI_U32 authIndex) if (NULL == pAuthNode) { - limLog(pMac, LOGW, FL("Invalid auth node\n")); + limLog(pMac, LOGW, FL("Invalid auth node")); return; } if ((psessionEntry = peFindSessionByBssid(pMac, pAuthNode->peerMacAddr, &sessionId)) == NULL) { - limLog(pMac, LOGW, FL("session does not exist for given BSSID \n")); + limLog(pMac, LOGW, FL("session does not exist for given BSSID ")); return; } @@ -4205,7 +4213,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } @@ -4223,7 +4231,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) // Log error PELOG1(limLog(pMac, LOG1, - FL("Re/Association Response not received before timeout \n"));) + FL("Re/Association Response not received before timeout "));) if (( (psessionEntry->limSystemRole == eLIM_AP_ROLE) || (psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) )|| ( (psessionEntry->limMlmState != eLIM_MLM_WT_ASSOC_RSP_STATE) && @@ -4237,7 +4245,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) // Log error limLog(pMac, LOGW, - FL("received unexpected REASSOC failure timeout in state %X for role %d\n"), + FL("received unexpected REASSOC failure timeout in state %X for role %d"), psessionEntry->limMlmState, psessionEntry->limSystemRole); limPrintMlmState(pMac, LOGW, psessionEntry->limMlmState); } @@ -4247,7 +4255,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) if ((MsgType == LIM_ASSOC) || ((MsgType == LIM_REASSOC) && (psessionEntry->limMlmState == eLIM_MLM_WT_FT_REASSOC_RSP_STATE))) { - PELOGE(limLog(pMac, LOGE, FL("(Re)Assoc Failure Timeout occurred.\n"));) + PELOGE(limLog(pMac, LOGE, FL("(Re)Assoc Failure Timeout occurred."));) psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); @@ -4266,7 +4274,7 @@ limProcessAssocFailureTimeout(tpAniSirGlobal pMac, tANI_U32 MsgType) //To remove the preauth node in case of fail to associate if (limSearchPreAuthList(pMac, psessionEntry->bssId)) { - PELOG1(limLog(pMac, LOG1, FL(" delete pre auth node for %02X-%02X-%02X-%02X-%02X-%02X\n"), + PELOG1(limLog(pMac, LOG1, FL(" delete pre auth node for %02X-%02X-%02X-%02X-%02X-%02X"), psessionEntry->bssId[0], psessionEntry->bssId[1], psessionEntry->bssId[2], psessionEntry->bssId[3], psessionEntry->bssId[4], psessionEntry->bssId[5]);) limDeletePreAuthNode(pMac, psessionEntry->bssId); @@ -4369,7 +4377,7 @@ tpLimMlmAddBACnf pMlmAddBACnf; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -4377,7 +4385,7 @@ tpLimMlmAddBACnf pMlmAddBACnf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBAReq->sessionId))== NULL) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4400,7 +4408,7 @@ tpLimMlmAddBACnf pMlmAddBACnf; sizeof( tLimMlmAddBACnf ))) { limLog( pMac, LOGP, - FL("palAllocateMemory failed with error code %d\n")); + FL("palAllocateMemory failed with error code %d")); palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4461,7 +4469,7 @@ tpLimMlmAddBARsp pMlmAddBARsp; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -4470,7 +4478,7 @@ tpLimMlmAddBARsp pMlmAddBARsp; if(( psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBARsp->sessionId))== NULL) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given session ID\n"));) + FL("session does not exist for given session ID"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4480,7 +4488,7 @@ tpLimMlmAddBARsp pMlmAddBARsp; if( eSIR_SUCCESS != limSendAddBARsp( pMac,pMlmAddBARsp,psessionEntry)) { limLog( pMac, LOGE, - FL("Failed to send ADDBA Rsp to peer \n")); + FL("Failed to send ADDBA Rsp to peer ")); limPrintMacAddr( pMac, pMlmAddBARsp->peerMacAddr, LOGE ); /* Clean the BA context maintained by HAL and TL on failure */ pSta = dphLookupHashEntry( pMac, pMlmAddBARsp->peerMacAddr, &aid, @@ -4523,7 +4531,7 @@ void limProcessMlmDelBAReq( tpAniSirGlobal pMac, if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } @@ -4532,7 +4540,7 @@ void limProcessMlmDelBAReq( tpAniSirGlobal pMac, if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDelBAReq->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId"));) palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4569,7 +4577,7 @@ void limProcessMlmDelBAReq( tpAniSirGlobal pMac, (void **) &pMlmDelBACnf, sizeof( tLimMlmDelBACnf ))) { - limLog( pMac, LOGP, FL("palAllocateMemory failed\n")); + limLog( pMac, LOGP, FL("palAllocateMemory failed")); palFreeMemory( pMac->hHdd, (tANI_U8 *) pMsgBuf ); return; } @@ -4630,23 +4638,23 @@ limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) tpPESession psessionEntry = &pMac->lim.gpSession[0]; //TBD-RAJESH HOW TO GET sessionEntry????? /** Verify the Mode of operation */ if (pMac->lim.gLimSystemRole != eSYSTEM_STA_ROLE) { - PELOGE(limLog(pMac, LOGE, FL("Got PMC indication when System not in the STA Role\n"));) + PELOGE(limLog(pMac, LOGE, FL("Got PMC indication when System not in the STA Role"));) return eSIR_FAILURE; } if ((pMac->lim.gHTMIMOPSState == state) || (state == eSIR_HT_MIMO_PS_NA )) { - PELOGE(limLog(pMac, LOGE, FL("Got Indication when already in the same mode or State passed is NA:%d \n"), state);) + PELOGE(limLog(pMac, LOGE, FL("Got Indication when already in the same mode or State passed is NA:%d "), state);) return eSIR_FAILURE; } if (!pMac->lim.htCapability){ - PELOGW(limLog(pMac, LOGW, FL(" Not in 11n or HT capable mode\n"));) + PELOGW(limLog(pMac, LOGW, FL(" Not in 11n or HT capable mode"));) return eSIR_FAILURE; } /** Update the CFG about the default MimoPS State */ if (wlan_cfgGetInt(pMac, WNI_CFG_HT_CAP_INFO, &cfgVal1) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve HT Cap CFG \n")); + limLog(pMac, LOGP, FL("could not retrieve HT Cap CFG ")); return eSIR_FAILURE; } @@ -4655,13 +4663,13 @@ limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) pHTCapabilityInfo->mimoPowerSave = state; if(cfgSetInt(pMac, WNI_CFG_HT_CAP_INFO, *(tANI_U16*)pHTCapabilityInfo) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not update HT Cap Info CFG\n")); + limLog(pMac, LOGP, FL("could not update HT Cap Info CFG")); return eSIR_FAILURE; } - PELOG2(limLog(pMac, LOG2, FL(" The HT Capability for Mimo Pwr is updated to State: %u \n"),state);) + PELOG2(limLog(pMac, LOG2, FL(" The HT Capability for Mimo Pwr is updated to State: %u "),state);) if (pMac->lim.gLimSmeState != eLIM_SME_LINK_EST_STATE) { - PELOG2(limLog(pMac, LOG2,FL(" The STA is not in the Connected/Link Est Sme_State: %d \n"), pMac->lim.gLimSmeState);) + PELOG2(limLog(pMac, LOG2,FL(" The STA is not in the Connected/Link Est Sme_State: %d "), pMac->lim.gLimSmeState);) /** Update in the LIM the MIMO PS state of the SELF */ pMac->lim.gHTMIMOPSState = state; return eSIR_SUCCESS; @@ -4669,7 +4677,7 @@ limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); if (!pSta->mlmStaContext.htCapability) { - limLog( pMac, LOGE,FL( "limSendSMPowerState: Peer is not HT Capable \n" )); + limLog( pMac, LOGE,FL( "limSendSMPowerState: Peer is not HT Capable " )); return eSIR_FAILURE; } @@ -4680,7 +4688,7 @@ limSMPowerSaveStateInd(tpAniSirGlobal pMac, tSirMacHTMIMOPowerSaveState state) /** Send Action Frame with the corresponding mode */ retStatus = limSendSMPowerStateFrame(pMac, macAddr, state); if (retStatus != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, "Update SM POWER: Sending Action Frame has failed\n");) + PELOGE(limLog(pMac, LOGE, "Update SM POWER: Sending Action Frame has failed");) return retStatus; } } @@ -4724,7 +4732,7 @@ ePhyChanBondState limGet11ACPhyCBState(tpAniSirGlobal pMac, tANI_U8 channel, tAN cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_LOW_40MHZ_HIGH; else limLog (pMac, LOGP, - FL("Invalid Channel Number = %d Center Chan = %d \n"), + FL("Invalid Channel Number = %d Center Chan = %d "), channel, peerCenterChan); } if ( (htSecondaryChannelOffset @@ -4739,7 +4747,7 @@ ePhyChanBondState limGet11ACPhyCBState(tpAniSirGlobal pMac, tANI_U8 channel, tAN cbState = PHY_QUADRUPLE_CHANNEL_20MHZ_HIGH_40MHZ_HIGH; else limLog (pMac, LOGP, - FL("Invalid Channel Number = %d Center Chan = %d \n"), + FL("Invalid Channel Number = %d Center Chan = %d "), channel, peerCenterChan); } return cbState; @@ -4759,7 +4767,7 @@ limSetChannel(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 secChannelOffset, tP if ( NULL == peSession) { - limLog (pMac, LOGP, FL("Invalid PE session = %d\n"), peSessionId); + limLog (pMac, LOGP, FL("Invalid PE session = %d"), peSessionId); return; } #if defined WLAN_FEATURE_VOWIFI @@ -4775,7 +4783,7 @@ limSetChannel(tpAniSirGlobal pMac, tANI_U8 channel, tANI_U8 secChannelOffset, tP } #else if (wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not read WNI_CFG_LOCAL_POWER_CONSTRAINT from CFG\n")); + limLog(pMac, LOGP, FL("could not read WNI_CFG_LOCAL_POWER_CONSTRAINT from CFG")); return; } // Send WDA_CHNL_SWITCH_IND to HAL diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c index 23b3984305d..6399b0c02be 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessMlmRspMessages.c @@ -127,7 +127,7 @@ limProcessMlmRspMessages(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBu if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } switch (msgType) @@ -238,7 +238,7 @@ limProcessMlmScanCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_SCAN_CNF in state %X\n"), + FL("received unexpected MLM_SCAN_CNF in state %X"), pMac->lim.gLimSmeState);) return; } @@ -287,7 +287,7 @@ limProcessMlmScanCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Could not activate background scan timer. // Log error limLog(pMac, LOGP, - FL("could not activate background scan timer\n")); + FL("could not activate background scan timer")); pMac->lim.gLimBackgroundScanStarted = FALSE; } else @@ -363,13 +363,13 @@ limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pLimMlmStartCnf = (tLimMlmStartCnf*)pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmStartCnf->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE,FL("Session does Not exist with given sessionId \n"));) + PELOGE(limLog(pMac, LOGE,FL("Session does Not exist with given sessionId "));) return; } smesessionId = psessionEntry->smeSessionId; @@ -383,7 +383,7 @@ limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_START_CNF in state %X\n"), + FL("received unexpected MLM_START_CNF in state %X"), psessionEntry->limSmeState);) return; } @@ -400,18 +400,18 @@ limProcessMlmStartCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); if(psessionEntry->bssType == eSIR_BTAMP_STA_MODE) { - limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP STA SIDE***\n")); + limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP STA SIDE***")); } else if(psessionEntry->bssType == eSIR_BTAMP_AP_MODE) { - limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP AP SIDE***\n")); + limLog(pMac, LOG1, FL("*** Started BSS in BT_AMP AP SIDE***")); } else if(psessionEntry->bssType == eSIR_INFRA_AP_MODE) { - limLog(pMac, LOG1, FL("*** Started BSS in INFRA AP SIDE***\n")); + limLog(pMac, LOG1, FL("*** Started BSS in INFRA AP SIDE***")); } else - PELOG1(limLog(pMac, LOG1, FL("*** Started BSS ***\n"));) + PELOG1(limLog(pMac, LOG1, FL("*** Started BSS ***"));) } else { @@ -459,14 +459,14 @@ limProcessMlmJoinCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pLimMlmJoinCnf = (tLimMlmJoinCnf*)pMsgBuf; if( (psessionEntry = peFindSessionBySessionId(pMac,pLimMlmJoinCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("Session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("Session does not exist for given sessionId"));) return; } if (psessionEntry->limSmeState!= eLIM_SME_WT_JOIN_STATE) { PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_JOIN_CNF in state %X\n"), + FL("received unexpected MLM_JOIN_CNF in state %X"), psessionEntry->limSmeState);) return; } @@ -525,13 +525,13 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmAuthCnf = (tLimMlmAuthCnf*)pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAuthCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE, FL("session does not exist for given sessionId"));) return; } @@ -545,7 +545,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_AUTH_CNF in state %X\n"), + FL("received unexpected MLM_AUTH_CNF in state %X"), psessionEntry->limSmeState);) return; } @@ -562,7 +562,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthType value\n")); + FL("could not retrieve AuthType value")); } } else @@ -582,7 +582,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmAuthReq\n")); + FL("call to palAllocateMemory failed for mlmAuthReq")); return; } palZeroMemory( pMac->hHdd, (tANI_U8 *) pMlmAuthReq, sizeof(tLimMlmAuthReq)); @@ -607,7 +607,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthFailureTimeout value\n")); + FL("could not retrieve AuthFailureTimeout value")); } limPostMlmMessage(pMac, LIM_MLM_AUTH_REQ, @@ -619,7 +619,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) // MAC based authentication failure if (psessionEntry->limSmeState == eLIM_SME_WT_AUTH_STATE) { - PELOGE(limLog(pMac, LOGE, FL("Auth Failure occurred.\n"));) + PELOGE(limLog(pMac, LOGE, FL("Auth Failure occurred."));) psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); psessionEntry->limMlmState = eLIM_MLM_IDLE_STATE; @@ -658,12 +658,12 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Trigger Association with BSS */ PELOG1(limLog(pMac, LOG1, - FL("*** Authenticated with BSS ***\n"));) + FL("*** Authenticated with BSS ***"));) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmAssocReq, sizeof(tLimMlmAssocReq))) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmAssocReq\n")); + FL("call to palAllocateMemory failed for mlmAssocReq")); return; } val = sizeof(tSirMacAddr); @@ -673,7 +673,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) &val) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //SUPPORT BT-AMP sirCopyMacAddr(pMlmAssocReq->peerMacAddr,psessionEntry->bssId); @@ -686,7 +686,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AssocFailureTimeout value\n")); + FL("could not retrieve AssocFailureTimeout value")); } if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) { @@ -695,7 +695,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } /*Clear spectrum management bit if AP doesn't support it*/ if(!(psessionEntry->pLimJoinReq->bssDescription.capabilityInfo & LIM_SPECTRUM_MANAGEMENT_BIT_MASK)) @@ -706,7 +706,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmAssocReq->capabilityInfo = caps; PELOG3(limLog(pMac, LOG3, - FL("Capabilities to be used in AssocReq=0x%X, privacy bit=%x shortSlotTime %x\n"), + FL("Capabilities to be used in AssocReq=0x%X, privacy bit=%x shortSlotTime %x"), caps, ((tpSirMacCapabilityInfo) &pMlmAssocReq->capabilityInfo)->privacy, ((tpSirMacCapabilityInfo) &pMlmAssocReq->capabilityInfo)->shortSlotTime);) @@ -715,7 +715,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) WNI_CFG_TELE_BCN_MAX_LI */ if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN\n")); + limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); val = WNI_CFG_LISTEN_INTERVAL_STADEF; @@ -728,7 +728,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get ListenInterval value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve ListenInterval\n")); + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); } } else @@ -739,7 +739,7 @@ limProcessMlmAuthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get ListenInterval value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve ListenInterval\n")); + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); } } @@ -797,13 +797,13 @@ limProcessMlmAssocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } pLimMlmAssocCnf = (tLimMlmAssocCnf*)pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmAssocCnf->sessionId)) == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("Session does not exist for given sessionId"));) return; } if (psessionEntry->limSmeState != eLIM_SME_WT_ASSOC_STATE || @@ -815,14 +815,14 @@ limProcessMlmAssocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_ASSOC_CNF in state %X\n"), + FL("received unexpected MLM_ASSOC_CNF in state %X"), psessionEntry->limSmeState);) return; } if (((tLimMlmAssocCnf *) pMsgBuf)->resultCode != eSIR_SME_SUCCESS) { // Association failure - PELOG1(limLog(pMac, LOG1, FL("*** Association failure ***\n"));) + PELOG1(limLog(pMac, LOG1, FL("*** Association failure ***"));) psessionEntry->limSmeState = eLIM_SME_JOIN_FAILURE_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, pMac->lim.gLimSmeState)); /** @@ -836,7 +836,7 @@ limProcessMlmAssocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { // Successful Association - PELOG1(limLog(pMac, LOG1, FL("*** Associated with BSS ***\n"));) + PELOG1(limLog(pMac, LOG1, FL("*** Associated with BSS ***"));) psessionEntry->limSmeState = eLIM_SME_LINK_EST_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); /** @@ -875,13 +875,13 @@ limProcessMlmReassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pLimMlmReassocCnf = (tLimMlmReassocCnf*) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pLimMlmReassocCnf->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE, FL("session Does not exist for given session Id\n"));) + PELOGE(limLog(pMac, LOGE, FL("session Does not exist for given session Id"));) return; } if ((psessionEntry->limSmeState != eLIM_SME_WT_REASSOC_STATE) || @@ -893,7 +893,7 @@ limProcessMlmReassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("Rcv unexpected MLM_REASSOC_CNF in role %d, sme state 0x%X\n"), + FL("Rcv unexpected MLM_REASSOC_CNF in role %d, sme state 0x%X"), psessionEntry->limSystemRole, psessionEntry->limSmeState);) return; } @@ -902,10 +902,10 @@ limProcessMlmReassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->pLimReAssocReq = NULL; } - PELOGE(limLog(pMac, LOGE, FL("Rcv MLM_REASSOC_CNF with result code %d\n"), pLimMlmReassocCnf->resultCode);) + PELOGE(limLog(pMac, LOGE, FL("Rcv MLM_REASSOC_CNF with result code %d"), pLimMlmReassocCnf->resultCode);) if (pLimMlmReassocCnf->resultCode == eSIR_SME_SUCCESS) { // Successful Reassociation - PELOG1(limLog(pMac, LOG1, FL("*** Reassociated with new BSS ***\n"));) + PELOG1(limLog(pMac, LOG1, FL("*** Reassociated with new BSS ***"));) psessionEntry->limSmeState = eLIM_SME_LINK_EST_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); @@ -973,12 +973,12 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 sessionId; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } if((psessionEntry = peFindSessionByBssid(pMac,((tpLimMlmReassocInd)pMsgBuf)->peerMacAddr, &sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) return; } /// Inform Host of STA reassociation @@ -987,7 +987,7 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_REASSOC_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_REASSOC_IND")); return; } @@ -1012,7 +1012,7 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pStaDs = dphGetHashEntry(pMac, ((tpLimMlmReassocInd) pMsgBuf)->aid, &psessionEntry->dph.dphHashTable); if (! pStaDs) { - limLog( pMac, LOGP, FL("MLM ReAssocInd: Station context no longer valid (aid %d)\n"), + limLog( pMac, LOGP, FL("MLM ReAssocInd: Station context no longer valid (aid %d)"), ((tpLimMlmReassocInd) pMsgBuf)->aid); palFreeMemory(pMac->hHdd, pSirSmeReassocInd); return; @@ -1020,7 +1020,7 @@ limProcessMlmReassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limSysProcessMmhMsgApi(pMac, &msgQ, ePROT); PELOG1(limLog(pMac, LOG1, - FL("Create CNF_WAIT_TIMER after received LIM_MLM_REASSOC_IND\n"));) + FL("Create CNF_WAIT_TIMER after received LIM_MLM_REASSOC_IND"));) /* ** turn on a timer to detect the loss of REASSOC CNF **/ @@ -1054,14 +1054,14 @@ limProcessMlmAuthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeAuthInd, sizeof(tSirSmeAuthInd))) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_AUTH_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_AUTH_IND")); } limCopyU16((tANI_U8 *) &pSirSmeAuthInd->messageType, eWNI_SME_AUTH_IND); limAuthIndSerDes(pMac, (tpLimMlmAuthInd) pMsgBuf, @@ -1162,12 +1162,12 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tpPESession psessionEntry; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } if((psessionEntry = peFindSessionBySessionId(pMac,((tpLimMlmAssocInd) pMsgBuf)->sessionId))== NULL) { - limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId\n" )); + limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId" )); return; } /// Inform Host of STA association @@ -1176,7 +1176,7 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_ASSOC_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_ASSOC_IND")); return; } @@ -1189,7 +1189,7 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) ((tpLimMlmAssocInd) pMsgBuf)->aid, &psessionEntry->dph.dphHashTable); if (! pStaDs) { // good time to panic... - limLog(pMac, LOGE, FL("MLM AssocInd: Station context no longer valid (aid %d)\n"), + limLog(pMac, LOGE, FL("MLM AssocInd: Station context no longer valid (aid %d)"), ((tpLimMlmAssocInd) pMsgBuf)->aid); palFreeMemory(pMac->hHdd, pSirSmeAssocInd); @@ -1204,7 +1204,7 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limSysProcessMmhMsgApi(pMac, &msgQ, ePROT); PELOG1(limLog(pMac, LOG1, - FL("Create CNF_WAIT_TIMER after received LIM_MLM_ASSOC_IND\n"));) + FL("Create CNF_WAIT_TIMER after received LIM_MLM_ASSOC_IND"));) /* ** turn on a timer to detect the loss of ASSOC CNF **/ @@ -1216,7 +1216,7 @@ limProcessMlmAssocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { tpSirSmeAssocCnf pSmeAssoccnf; if(!palAllocateMemory(pMac->hHdd,(void **)&pSmeAssoccnf,sizeof(tSirSmeAssocCnf))) - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed for pSmeAssoccnf \n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed for pSmeAssoccnf "));) pSmeAssoccnf->messageType = eWNI_SME_ASSOC_CNF; pSmeAssoccnf->length = sizeof(tSirSmeAssocCnf); palCopyMemory( pMac->hHdd,pSmeAssoccnf->peerMacAddr,((tpLimMlmAssocInd)pMsgBuf)->peerMacAddr,6); @@ -1263,7 +1263,7 @@ limProcessMlmDisassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmDisassocInd = (tLimMlmDisassocInd *) pMsgBuf; if( (psessionEntry = peFindSessionBySessionId(pMac,pMlmDisassocInd->sessionId) )== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } switch (psessionEntry->limSystemRole) @@ -1277,7 +1277,7 @@ limProcessMlmDisassocInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) break; default: // eLIM_AP_ROLE //eLIM_BT_AMP_AP_ROLE PELOG1(limLog(pMac, LOG1, - FL("*** Peer staId=%d Disassociated ***\n"), + FL("*** Peer staId=%d Disassociated ***"), pMlmDisassocInd->aid);) // Send SME_DISASOC_IND after Polaris cleanup // (after receiving LIM_MLM_PURGE_STA_IND) @@ -1312,7 +1312,7 @@ limProcessMlmDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmDisassocCnf = (tLimMlmDisassocCnf *) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDisassocCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id\n"));) + PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id"));) return; } resultCode = (tSirResultCodes) @@ -1333,7 +1333,7 @@ limProcessMlmDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_DISASSOC_CNF in state %X\n"),psessionEntry->limSmeState);) + FL("received unexpected MLM_DISASSOC_CNF in state %X"),psessionEntry->limSmeState);) return; } if (pMac->lim.gLimRspReqd) @@ -1398,7 +1398,7 @@ limProcessMlmDeauthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmDeauthInd = (tLimMlmDeauthInd *) pMsgBuf; if((psessionEntry = peFindSessionByBssid(pMac,pMlmDeauthInd->peerMacAddr,&sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) return; } switch (psessionEntry->limSystemRole) @@ -1413,7 +1413,7 @@ limProcessMlmDeauthInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) default: // eLIM_AP_ROLE { PELOG1(limLog(pMac, LOG1, - FL("*** Received Deauthentication from staId=%d ***\n"), + FL("*** Received Deauthentication from staId=%d ***"), pMlmDeauthInd->aid);) } // Send SME_DEAUTH_IND after Polaris cleanup @@ -1450,13 +1450,13 @@ limProcessMlmDeauthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmDeauthCnf = (tLimMlmDeauthCnf *) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmDeauthCnf->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given session Id \n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given session Id "));) return; } @@ -1478,7 +1478,7 @@ limProcessMlmDeauthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_DEAUTH_CNF in state %X\n"), + FL("received unexpected MLM_DEAUTH_CNF in state %X"), psessionEntry->limSmeState);) return; } @@ -1486,7 +1486,7 @@ limProcessMlmDeauthCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { psessionEntry->limSmeState = eLIM_SME_IDLE_STATE; PELOG1(limLog(pMac, LOG1, - FL("*** Deauthenticated with BSS ***\n"));) + FL("*** Deauthenticated with BSS ***"));) } else psessionEntry->limSmeState = psessionEntry->limPrevSmeState; @@ -1528,13 +1528,13 @@ limProcessMlmPurgeStaInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tpPESession psessionEntry; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmPurgeStaInd = (tpLimMlmPurgeStaInd) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmPurgeStaInd->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given bssId"));) return; } // Purge STA indication from MLM @@ -1558,12 +1558,12 @@ limProcessMlmPurgeStaInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error */ PELOGE(limLog(pMac, LOGE, - FL("received unexpected MLM_PURGE_STA_IND in state %X\n"), + FL("received unexpected MLM_PURGE_STA_IND in state %X"), psessionEntry->limSmeState);) break; } PELOG1(limLog(pMac, LOG1, - FL("*** Polaris cleanup completed for staId=%d ***\n"), + FL("*** Polaris cleanup completed for staId=%d ***"), pMlmPurgeStaInd->aid);) if ((psessionEntry->limSystemRole == eLIM_STA_ROLE)||(psessionEntry->limSystemRole == eLIM_BT_AMP_STA_ROLE)) { @@ -1615,17 +1615,17 @@ limProcessMlmSetKeysCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmSetKeysCnf = (tLimMlmSetKeysCnf *) pMsgBuf; if ((psessionEntry = peFindSessionBySessionId(pMac, pMlmSetKeysCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId \n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId "));) return; } limLog( pMac, LOG1, - FL("Received MLM_SETKEYS_CNF with resultCode = %d\n"), + FL("Received MLM_SETKEYS_CNF with resultCode = %d"), pMlmSetKeysCnf->resultCode ); limSendSmeSetContextRsp(pMac, pMlmSetKeysCnf->peerMacAddr, @@ -1660,17 +1660,17 @@ limProcessMlmRemoveKeyCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmRemoveKeyCnf = (tLimMlmRemoveKeyCnf *) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmRemoveKeyCnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id\n"));) + PELOGE(limLog(pMac, LOGE,FL("session Does not exist for given session Id"));) return; } limLog( pMac, LOG1, - FL("Received MLM_REMOVEKEYS_CNF with resultCode = %d\n"), + FL("Received MLM_REMOVEKEYS_CNF with resultCode = %d"), pMlmRemoveKeyCnf->resultCode ); limSendSmeRemoveKeyRsp(pMac, pMlmRemoveKeyCnf->peerMacAddr, @@ -1710,7 +1710,7 @@ limHandleSmeJoinResult(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U16 /* Newly Added on oct 11 th*/ if(psessionEntry == NULL) { - PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL \n"));) + PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL "));) return; } smesessionId = psessionEntry->smeSessionId; @@ -1742,7 +1742,7 @@ limHandleSmeJoinResult(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U16 { if(limSetLinkState(pMac, eSIR_LINK_IDLE_STATE,psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState.\n"));) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState."));) peDeleteSession(pMac,psessionEntry); psessionEntry = NULL; } @@ -1780,7 +1780,7 @@ limHandleSmeReaasocResult(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_ if(psessionEntry == NULL) { - PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL \n"));) + PELOGE(limLog(pMac, LOGE,FL("psessionEntry is NULL "));) return; } smesessionId = psessionEntry->smeSessionId; @@ -1855,7 +1855,7 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess if(NULL == pAddStaParams ) { - limLog( pMac, LOGE, FL( "Encountered NULL Pointer\n" )); + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); return; } if( eHAL_STATUS_SUCCESS == pAddStaParams->status ) @@ -1864,7 +1864,7 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess { //TODO: any response to be sent out here ? limLog( pMac, LOGE, - FL( "Received unexpected WDA_ADD_STA_RSP in state %X\n" ), + FL( "Received unexpected WDA_ADD_STA_RSP in state %X" ), psessionEntry->limMlmState); mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; goto end; @@ -1880,7 +1880,7 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; else limLog( pMac, LOGW, - FL( "Unable to get the DPH Hash Entry for AID - %d\n" ), + FL( "Unable to get the DPH Hash Entry for AID - %d" ), DPH_STA_HASH_INDEX_PEER); psessionEntry->limMlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); @@ -1903,9 +1903,13 @@ void limProcessStaMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESess //assign the sessionId to the timer Object pMac->lim.limTimers.gLimKeepaliveTimer.sessionId = psessionEntry->peSessionId; if (tx_timer_activate(&pMac->lim.limTimers.gLimKeepaliveTimer) != TX_SUCCESS) - limLog(pMac, LOGP, FL("Cannot activate keepalive timer.\n")); + limLog(pMac, LOGP, FL("Cannot activate keepalive timer.")); #ifdef WLAN_DEBUG pMac->lim.gLimNumLinkEsts++; +#endif +#ifdef FEATURE_WLAN_TDLS + /* initialize TDLS peer related data */ + limInitTdlsData(pMac,psessionEntry); #endif // Return Assoc confirm to SME with success // FIXME_GEN4 - Need the correct ASSOC RSP code to @@ -1937,7 +1941,7 @@ void limProcessMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession // tpDeleteBssParams pDeleteBssParams =( tpDeleteBssParams)limMsgQ->bodyptr; // if((psessionEntry = peFindSessionBySessionId(pMac,pDeleteBssParams->sessionId)) == NULL) // { - // limLog( pMac, LOGE, FL( "Session deos not exist with given sessionId\n" )); + // limLog( pMac, LOGE, FL( "Session deos not exist with given sessionId" )); // return; // } SET_LIM_PROCESS_DEFD_MESGS(pMac, true); @@ -1957,18 +1961,6 @@ void limProcessMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession { WDA_TrafficStatsTimerActivate(FALSE); } - -#ifdef WLAN_FEATURE_11W - if (psessionEntry->limRmfEnabled) - { - if ( eSIR_SUCCESS != limSendExcludeUnencryptInd(pMac, TRUE, psessionEntry) ) - { - limLog( pMac, LOGE, - FL( "Could not send down Exclude Unencrypted Indication!" ), - psessionEntry->limMlmState ); - } - } -#endif } void limProcessStaMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession psessionEntry) @@ -1979,30 +1971,30 @@ void limProcessStaMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi if (NULL == pDelBssParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto end; } if( eHAL_STATUS_SUCCESS == pDelBssParams->status ) { PELOGW(limLog( pMac, LOGW, - FL( "STA received the DEL_BSS_RSP for BSSID: %X.\n"),pDelBssParams->bssIdx);) + FL( "STA received the DEL_BSS_RSP for BSSID: %X."),pDelBssParams->bssIdx);) if (limSetLinkState(pMac, eSIR_LINK_IDLE_STATE, psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS) { - PELOGE(limLog( pMac, LOGE, FL( "Failure in setting link state to IDLE\n"));) + PELOGE(limLog( pMac, LOGE, FL( "Failure in setting link state to IDLE"));) statusCode = eSIR_SME_REFUSED; goto end; } if(pStaDs == NULL) { - limLog( pMac, LOGE, FL( "DPH Entry for STA 1 missing.\n")); + limLog( pMac, LOGE, FL( "DPH Entry for STA 1 missing.")); statusCode = eSIR_SME_REFUSED; goto end; } if( eLIM_MLM_WT_DEL_BSS_RSP_STATE != pStaDs->mlmStaContext.mlmState) { - PELOGE(limLog( pMac, LOGE, FL( "Received unexpected WDA_DEL_BSS_RSP in state %X\n" ), + PELOGE(limLog( pMac, LOGE, FL( "Received unexpected WDA_DEL_BSS_RSP in state %X" ), pStaDs->mlmStaContext.mlmState);) statusCode = eSIR_SME_REFUSED; goto end; @@ -2048,7 +2040,7 @@ void limProcessBtAmpApMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if(psessionEntry == NULL) { - limLog(pMac, LOGE,FL("Session entry passed is NULL\n")); + limLog(pMac, LOGE,FL("Session entry passed is NULL")); if(pDelBss != NULL) palFreeMemory( pMac->hHdd, (void *) pDelBss ); return; @@ -2056,7 +2048,7 @@ void limProcessBtAmpApMlmDelBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if (pDelBss == NULL) { - PELOGE(limLog(pMac, LOGE, FL("BSS: DEL_BSS_RSP with no body!\n"));) + PELOGE(limLog(pMac, LOGE, FL("BSS: DEL_BSS_RSP with no body!"));) rc = eSIR_SME_REFUSED; goto end; } @@ -2122,7 +2114,7 @@ void limProcessMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) if(NULL == pDeleteStaParams || NULL == (psessionEntry = peFindSessionBySessionId(pMac, pDeleteStaParams->sessionId))) { - limLog(pMac, LOGP,FL("Session Does not exist or invalid body pointer in message\n")); + limLog(pMac, LOGP,FL("Session Does not exist or invalid body pointer in message")); if(pDeleteStaParams != NULL) palFreeMemory( pMac->hHdd, (void *) pDeleteStaParams ); return; @@ -2152,7 +2144,7 @@ void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if(pStaDs == NULL) { limLog( pMac, LOGE, - FL( "DPH Entry for STA %X missing.\n"), pDelStaParams->assocId); + FL( "DPH Entry for STA %X missing."), pDelStaParams->assocId); statusCode = eSIR_SME_REFUSED; palFreeMemory( pMac->hHdd, (void *) pDelStaParams ); @@ -2161,13 +2153,13 @@ void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if( eHAL_STATUS_SUCCESS == pDelStaParams->status ) { limLog( pMac, LOGW, - FL( "AP received the DEL_STA_RSP for assocID: %X.\n"), pDelStaParams->assocId); + FL( "AP received the DEL_STA_RSP for assocID: %X."), pDelStaParams->assocId); if(( eLIM_MLM_WT_DEL_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState) && ( eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE != pStaDs->mlmStaContext.mlmState)) { limLog( pMac, LOGE, - FL( "Received unexpected WDA_DEL_STA_RSP in state %s for staId %d assocId %d \n" ), + FL( "Received unexpected WDA_DEL_STA_RSP in state %s for staId %d assocId %d " ), limMlmStateStr(pStaDs->mlmStaContext.mlmState), pStaDs->staIndex, pStaDs->assocId); statusCode = eSIR_SME_REFUSED; goto end; @@ -2183,7 +2175,7 @@ void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if (limAddSta(pMac, pStaDs, false, psessionEntry) != eSIR_SUCCESS) { PELOGE(limLog(pMac, LOGE, - FL("could not Add STA with assocId=%d\n"), + FL("could not Add STA with assocId=%d"), pStaDs->assocId);) // delete the TS if it has already been added. // send the response with error status. @@ -2211,7 +2203,7 @@ void limProcessBtAmpApMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES else { limLog( pMac, LOGW, - FL( "DEL STA failed!\n" )); + FL( "DEL STA failed!" )); statusCode = eSIR_SME_REFUSED; } end: @@ -2230,7 +2222,7 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi tpDphHashNode pStaDs = NULL; if(NULL == pDelStaParams ) { - limLog( pMac, LOGE, FL( "Encountered NULL Pointer\n" )); + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); goto end; } if( eHAL_STATUS_SUCCESS == pDelStaParams->status ) @@ -2239,7 +2231,7 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi if (pStaDs == NULL) { //TODO: any response to be sent out here ? - limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing.\n"), + limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing."), pDelStaParams->assocId); statusCode = eSIR_SME_REFUSED; goto end; @@ -2247,14 +2239,14 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi if( eLIM_MLM_WT_DEL_STA_RSP_STATE != psessionEntry->limMlmState) { //TODO: any response to be sent out here ? - limLog( pMac, LOGE, FL( "Received unexpected WDA_DELETE_STA_RSP in state %s\n" ), + limLog( pMac, LOGE, FL( "Received unexpected WDA_DELETE_STA_RSP in state %s" ), limMlmStateStr(psessionEntry->limMlmState)); statusCode = eSIR_SME_REFUSED; goto end; } PELOG1(limLog( pMac, LOG1, FL("STA AssocID %d MAC "), pStaDs->assocId ); limPrintMacAddr(pMac, pStaDs->staAddr, LOG1);) - limLog( pMac, LOGW, FL( "DEL_STA_RSP received for assocID: %X\n"), pDelStaParams->assocId); + limLog( pMac, LOGW, FL( "DEL_STA_RSP received for assocID: %X"), pDelStaParams->assocId); //we must complete all cleanup related to delSta before calling limDelBSS. if( 0 != limMsgQ->bodyptr ) { @@ -2265,7 +2257,7 @@ void limProcessStaMlmDelStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESessi } else { - limLog( pMac, LOGE, FL( "DEL_STA failed for sta Id %d\n" ), pStaDs->staIndex); + limLog( pMac, LOGE, FL( "DEL_STA failed for sta Id %d" ), pDelStaParams->staIdx); statusCode = eSIR_SME_REFUSED; } end: @@ -2283,7 +2275,7 @@ void limProcessBtAmpApMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if (NULL == pAddStaParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto end; } @@ -2291,7 +2283,7 @@ void limProcessBtAmpApMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES if(pStaDs == NULL) { //TODO: any response to be sent out here ? - limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing.\n"), pAddStaParams->assocId); + limLog( pMac, LOGE, FL( "DPH Entry for STA %X missing."), pAddStaParams->assocId); goto end; } // @@ -2303,13 +2295,13 @@ void limProcessBtAmpApMlmAddStaRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPES { //TODO: any response to be sent out here ? limLog( pMac, LOGE, - FL( "Received unexpected WDA_ADD_STA_RSP in state %X\n" ), + FL( "Received unexpected WDA_ADD_STA_RSP in state %X" ), pStaDs->mlmStaContext.mlmState); goto end; } if(eHAL_STATUS_SUCCESS != pAddStaParams->status) { - PELOGE(limLog(pMac, LOGE, FL("Error! rcvd delSta rsp from HAL with status %d\n"),pAddStaParams->status);) + PELOGE(limLog(pMac, LOGE, FL("Error! rcvd delSta rsp from HAL with status %d"),pAddStaParams->status);) limRejectAssociation(pMac, pStaDs->staAddr, pStaDs->mlmStaContext.subType, true, pStaDs->mlmStaContext.authType, @@ -2387,13 +2379,13 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) tpAddBssParams pAddBssParams = (tpAddBssParams) limMsgQ->bodyptr; if(NULL == pAddBssParams ) { - limLog( pMac, LOGE, FL( "Encountered NULL Pointer\n" )); + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); goto end; } //TBD: free the memory before returning, do it for all places where lookup fails. if((psessionEntry = peFindSessionBySessionId(pMac,pAddBssParams->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) if( NULL != pAddBssParams ) palFreeMemory( pMac->hHdd, (void *) pAddBssParams ); return; @@ -2402,7 +2394,7 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) mlmStartCnf.sessionId = pAddBssParams->sessionId; if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) { - PELOG2(limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS\n"));) + PELOG2(limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS"));) if (limSetLinkState(pMac, eSIR_LINK_AP_STATE,psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) goto end; @@ -2421,7 +2413,7 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); if (limActivateHearBeatTimer(pMac) != TX_SUCCESS) - limLog(pMac, LOGP, FL("could not activate Heartbeat timer\n")); + limLog(pMac, LOGP, FL("could not activate Heartbeat timer")); } psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; @@ -2441,12 +2433,12 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) // Start OLBC timer if (tx_timer_activate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) != TX_SUCCESS) { - limLog(pMac, LOGE, FL("tx_timer_activate failed\n")); + limLog(pMac, LOGE, FL("tx_timer_activate failed")); } /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) - limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!\n")); + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; // Apply previously set configuration at HW limApplyConfiguration(pMac,psessionEntry); @@ -2455,7 +2447,7 @@ limProcessApMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ) } else { - limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d\n" ),pAddBssParams->status ); + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ),pAddBssParams->status ); mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; } limPostSmeMessage( pMac, LIM_MLM_START_CNF, (tANI_U32 *) &mlmStartCnf ); @@ -2507,12 +2499,12 @@ limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession if (NULL == pAddBssParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto end; } if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) { - PELOG1(limLog(pMac, LOG1, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS\n"));) + PELOG1(limLog(pMac, LOG1, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS"));) if (limSetLinkState(pMac, eSIR_LINK_IBSS_STATE,psessionEntry->bssId, psessionEntry->selfMacAddr, NULL, NULL) != eSIR_SUCCESS ) goto end; @@ -2529,7 +2521,7 @@ limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); if (limActivateHearBeatTimer(pMac) != TX_SUCCESS) - limLog(pMac, LOGP, FL("could not activate Heartbeat timer\n")); + limLog(pMac, LOGP, FL("could not activate Heartbeat timer")); psessionEntry->bssIdx = (tANI_U8) pAddBssParams->bssIdx; psessionEntry->limSystemRole = eLIM_STA_IN_IBSS_ROLE; psessionEntry->statypeForBss = STA_ENTRY_SELF; @@ -2544,7 +2536,7 @@ limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession #endif /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) - limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!\n")); + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; // Apply previously set configuration at HW limApplyConfiguration(pMac,psessionEntry); @@ -2559,7 +2551,7 @@ limProcessIbssMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession } else { - limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d\n" ), + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ), pAddBssParams->status ); mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; } @@ -2583,7 +2575,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES if (NULL == pAddBssParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto joinFailure; } if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) @@ -2591,7 +2583,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES if ((pStaDs = dphAddHashEntry(pMac, pAddBssParams->staContext.staMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) == NULL) { // Could not add hash table entry - PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for \n"));) + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) limPrintMacAddr(pMac, pAddBssParams->staContext.staMac, LOGE); goto joinFailure; } @@ -2609,7 +2601,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES * Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthType\n")); + FL("could not retrieve AuthType")); } if (cfgAuthType == eSIR_AUTO_SWITCH) authMode = eSIR_OPEN_SYSTEM; // Try Open Authentication first @@ -2621,7 +2613,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmAuthReq\n")); + FL("call to palAllocateMemory failed for mlmAuthReq")); return; } #if 0 @@ -2631,7 +2623,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES &val) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMlmAuthReq->peerMacAddr,psessionEntry->bssId); @@ -2646,7 +2638,7 @@ limProcessStaMlmAddBssRspPreAssoc( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPES * value from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthFailureTimeout value\n")); + FL("could not retrieve AuthFailureTimeout value")); } // SUNIT_FIX_ME: Set BOTH? Assume not. Please verify here and below. //pMac->lim.gLimMlmState = eLIM_MLM_JOINED_STATE; @@ -2699,7 +2691,7 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) /* Sanity Checks */ if (pCbackParams == NULL) { - PELOGE(limLog(pMac, LOGE, FL("Invalid parameters\n"));) + PELOGE(limLog(pMac, LOGE, FL("Invalid parameters"));) goto end; } @@ -2707,15 +2699,13 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) if (pAddBssParams == NULL) { - PELOGE(limLog(pMac, LOGE, FL("Invalid parameters\n"));) + PELOGE(limLog(pMac, LOGE, FL("Invalid parameters"));) goto end; } if((psessionEntry = peFindSessionBySessionId(pMac,pAddBssParams->sessionId))== NULL) { - limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId\n" )); - if( NULL != pAddBssParams ) - palFreeMemory( pMac->hHdd, (void *) pAddBssParams ); + limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId" )); goto end; } @@ -2727,7 +2717,7 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) &psessionEntry->dph.dphHashTable)) == NULL) { // Could not add hash table entry - PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for \n"));) + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) limPrintMacAddr(pMac, pAddBssParams->staContext.staMac, LOGE); goto end; } @@ -2742,7 +2732,7 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) /// Could not start reassoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Reassociation failure timer\n")); + FL("could not start Reassociation failure timer")); // Return Reassoc confirm with // Resources Unavailable mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -2784,8 +2774,8 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pAddStaParams, sizeof( tAddStaParams ))) { - limLog( pMac, LOGP, FL( "Unable to PAL allocate memory during ADD_STA\n" )); - return; + limLog( pMac, LOGP, FL( "Unable to PAL allocate memory during ADD_STA" )); + goto end; } palZeroMemory( pMac->hHdd, (tANI_U8 *) pAddStaParams, sizeof(tAddStaParams)); @@ -2850,7 +2840,7 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) } if (wlan_cfgGetInt(pMac, WNI_CFG_LISTEN_INTERVAL, &listenInterval) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL\n")); + limLog(pMac, LOGP, FL("Couldn't get LISTEN_INTERVAL")); pAddStaParams->listenInterval = (tANI_U16)listenInterval; limFillSupportedRatesInfo(pMac, NULL, &pAddStaParams->supportedRates,psessionEntry); @@ -2889,6 +2879,8 @@ void limSetLinkStateForPostAssocCallback(tpAniSirGlobal pMac, void *msgParam ) /* Update PE session Id*/ if (psessionEntry != NULL) mlmReassocCnf.sessionId = psessionEntry->peSessionId; + else + mlmReassocCnf.sessionId = 0; limPostSmeMessage(pMac, LIM_MLM_REASSOC_CNF, (tANI_U32 *) &mlmReassocCnf); } @@ -2914,13 +2906,13 @@ limProcessStaMlmAddBssRspFT(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPESession if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pCbackParam, sizeof( tSetLinkCbackParams ))) { - PELOGE(limLog(pMac, LOGE, FL("Could not allocate memory for LinkState callback params\n"));) + PELOGE(limLog(pMac, LOGE, FL("Could not allocate memory for LinkState callback params"));) goto end; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pAddBssCbackInfo, sizeof( tAddBssParams ))) { - PELOGE(limLog(pMac, LOGE, FL("Could not allocate memory for Add BSS info callback param\n"));) + PELOGE(limLog(pMac, LOGE, FL("Could not allocate memory for Add BSS info callback param"));) goto end; } @@ -2934,7 +2926,7 @@ limProcessStaMlmAddBssRspFT(tpAniSirGlobal pMac, tpSirMsgQ limMsgQ, tpPESession (tpSetLinkStateCallback)limSetLinkStateForPostAssocCallback, (void *)pCbackParam) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState\n"));) + PELOGE(limLog(pMac, LOGE, FL("Failed to set the LinkState"));) goto end; } @@ -3042,11 +3034,11 @@ limProcessStaMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession ps MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); psessionEntry->statypeForBss = STA_ENTRY_PEER; //to know the session started for self or for peer oct6th // Now, send WDA_ADD_STA_REQ - limLog( pMac, LOGW, FL( "On STA: ADD_BSS was successful\n" )); + limLog( pMac, LOGW, FL( "On STA: ADD_BSS was successful" )); pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); if (pStaDs == NULL) { - PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station"));) mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; } else @@ -3075,20 +3067,14 @@ limProcessStaMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ,tpPESession ps if (limAddStaSelf(pMac,staIdx, updateSta, psessionEntry) != eSIR_SUCCESS) { // Add STA context at HW - PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not Add Self Entry for the station"));) mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; } -#ifdef FEATURE_WLAN_TDLS - else { - /* initialize TDLS peer related data */ - limInitTdlsData(pMac,psessionEntry); - } -#endif } } else { - limLog( pMac, LOGP, FL( "ADD_BSS failed!\n" )); + limLog( pMac, LOGP, FL( "ADD_BSS failed!" )); // Return Assoc confirm to SME with failure mlmAssocCnf.resultCode = (tSirResultCodes) eSIR_SME_REFUSED; } @@ -3140,7 +3126,7 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) if(NULL == pAddBssParams ) { - limLog( pMac, LOGE, FL( "Encountered NULL Pointer\n" )); + limLog( pMac, LOGE, FL( "Encountered NULL Pointer" )); return; } @@ -3156,7 +3142,7 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) // Validate MLME state if((psessionEntry = peFindSessionBySessionId(pMac,pAddBssParams->sessionId))== NULL) { - limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId\n" )); + limLog( pMac, LOGE, FL( "Session Does not exist for given sessionId" )); if( NULL != pAddBssParams ) palFreeMemory( pMac->hHdd, (void *) pAddBssParams ); return; @@ -3173,7 +3159,7 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) { // Mesg received from HAL in Invalid state! limLog( pMac, LOGE, - FL( "Received unexpected WDA_ADD_BSS_RSP in state %X\n" ), + FL( "Received unexpected WDA_ADD_BSS_RSP in state %X" ), psessionEntry->limMlmState ); mlmStartCnf.resultCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; if( 0 != limMsgQ->bodyptr ) @@ -3196,18 +3182,6 @@ void limProcessMlmAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) { WDA_TrafficStatsTimerActivate(TRUE); } - -#ifdef WLAN_FEATURE_11W - if (psessionEntry->limRmfEnabled) - { - if ( eSIR_SUCCESS != limSendExcludeUnencryptInd(pMac, FALSE, psessionEntry) ) - { - limLog( pMac, LOGE, - FL( "Could not send down Exclude Unencrypted Indication!" ), - psessionEntry->limMlmState ); - } - } -#endif } /** * limProcessMlmSetKeyRsp() @@ -3255,20 +3229,20 @@ void limProcessMlmSetStaKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) //BTAMP if( NULL == limMsgQ->bodyptr ) { - PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL"));) return; } sessionId = ((tpSetStaKeyParams) limMsgQ->bodyptr)->sessionId; if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (void *) limMsgQ->bodyptr ); return; } if( eLIM_MLM_WT_SET_STA_KEY_STATE != psessionEntry->limMlmState ) { // Mesg received from HAL in Invalid state! - limLog( pMac, LOGW, FL( "Received unexpected [Mesg Id - %d] in state %X\n" ), limMsgQ->type, psessionEntry->limMlmState ); + limLog( pMac, LOGW, FL( "Received unexpected [Mesg Id - %d] in state %X" ), limMsgQ->type, psessionEntry->limMlmState ); // There's not much that MLME can do at this stage... respReqd = 0; } @@ -3306,13 +3280,13 @@ void limProcessMlmSetBssKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) //BTAMP if( NULL == limMsgQ->bodyptr ) { - PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is null\n"));) + PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is null"));) return; } sessionId = ((tpSetBssKeyParams) limMsgQ->bodyptr)->sessionId; if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) palFreeMemory( pMac->hHdd, (void *) limMsgQ->bodyptr ); return; } @@ -3333,7 +3307,7 @@ void limProcessMlmSetBssKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) eLIM_MLM_WT_SET_STA_BCASTKEY_STATE != psessionEntry->limMlmState ) { // Mesg received from HAL in Invalid state! - limLog( pMac, LOGW, FL( "Received unexpected [Mesg Id - %d] in state %X\n" ), limMsgQ->type, psessionEntry->limMlmState ); + limLog( pMac, LOGW, FL( "Received unexpected [Mesg Id - %d] in state %X" ), limMsgQ->type, psessionEntry->limMlmState ); // There's not much that MLME can do at this stage... respReqd = 0; } @@ -3389,7 +3363,7 @@ void limProcessMlmRemoveKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) if( NULL == limMsgQ->bodyptr ) { - PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("limMsgQ bodyptr is NULL"));) return; } @@ -3400,7 +3374,7 @@ void limProcessMlmRemoveKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) if((psessionEntry = peFindSessionBySessionId(pMac, sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionId"));) return; } @@ -3415,7 +3389,7 @@ void limProcessMlmRemoveKeyRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) { // Mesg received from HAL in Invalid state! limLog(pMac, LOGW, - FL("Received unexpected [Mesg Id - %d] in state %X\n"), + FL("Received unexpected [Mesg Id - %d] in state %X"), limMsgQ->type, psessionEntry->limMlmState ); respReqd = 0; @@ -3475,7 +3449,7 @@ void limProcessInitScanRsp(tpAniSirGlobal pMac, void *body) if( pMac->lim.abortScan && (eLIM_HAL_INIT_SCAN_WAIT_STATE == pMac->lim.gLimHalScanState) ) { - limLog( pMac, LOGW, FL(" finish scan\n") ); + limLog( pMac, LOGW, FL(" finish scan") ); pMac->lim.abortScan = 0; limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); @@ -3489,7 +3463,7 @@ void limProcessInitScanRsp(tpAniSirGlobal pMac, void *body) case eLIM_HAL_INIT_SCAN_WAIT_STATE: if (status != (tANI_U32) eHAL_STATUS_SUCCESS) { - PELOGW(limLog(pMac, LOGW, FL("InitScanRsp with failed status= %d\n"), status);) + PELOGW(limLog(pMac, LOGW, FL("InitScanRsp with failed status= %d"), status);) pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; pMac->lim.gLimNumOfConsecutiveBkgndScanFailure += 1; /* @@ -3527,13 +3501,13 @@ void limProcessInitScanRsp(tpAniSirGlobal pMac, void *body) } else { - limLog( pMac, LOGP, "No suspend link callback set but station is in suspend state\n"); + limLog( pMac, LOGP, "No suspend link callback set but station is in suspend state"); return; } break; //end WLAN_SUSPEND_LINK Related default: - limLog(pMac, LOGW, FL("limProcessInitScanRsp: Rcvd InitScanRsp not in WAIT State, state %d\n"), + limLog(pMac, LOGW, FL("limProcessInitScanRsp: Rcvd InitScanRsp not in WAIT State, state %d"), pMac->lim.gLimHalScanState); break; } @@ -3567,14 +3541,14 @@ static void limProcessSwitchChannelReAssocReq(tpAniSirGlobal pMac, tpPESession p pMlmReassocReq = (tLimMlmReassocReq *)(psessionEntry->pLimMlmReassocReq); if(pMlmReassocReq == NULL) { - limLog(pMac, LOGP, FL("pLimMlmReassocReq does not exist for given switchChanSession\n")); + limLog(pMac, LOGP, FL("pLimMlmReassocReq does not exist for given switchChanSession")); mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; } if(status != eHAL_STATUS_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!\n"));) + PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!"));) mlmReassocCnf.resultCode = eSIR_SME_CHANNEL_SWITCH_FAIL; goto end; } @@ -3586,7 +3560,7 @@ static void limProcessSwitchChannelReAssocReq(tpAniSirGlobal pMac, tpPESession p /// Could not start reassoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Reassociation failure timer\n")); + FL("could not start Reassociation failure timer")); // Return Reassoc confirm with // Resources Unavailable mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -3642,13 +3616,13 @@ static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession pses tLimMlmJoinCnf mlmJoinCnf; if(status != eHAL_STATUS_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!\n"));) + PELOGE(limLog(pMac, LOGE, FL("Change channel failed!!"));) goto error; } if ( (NULL == psessionEntry ) || (NULL == psessionEntry->pLimMlmJoinReq) ) { - PELOGE(limLog(pMac, LOGE, FL("invalid pointer!!\n"));) + PELOGE(limLog(pMac, LOGE, FL("invalid pointer!!"));) goto error; } @@ -3663,7 +3637,7 @@ static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession pses /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ if(wlan_cfgGetInt(pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("failed to get WNI_CFG_TRIG_STA_BK_SCAN cfg value!\n")); + limLog(pMac, LOGP, FL("failed to get WNI_CFG_TRIG_STA_BK_SCAN cfg value!")); pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; // Apply previously set configuration at HW limApplyConfiguration(pMac, psessionEntry); @@ -3687,7 +3661,7 @@ static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession pses MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_JOIN_FAIL_TIMER)); if (tx_timer_activate(&pMac->lim.limTimers.gLimJoinFailureTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not activate Join failure timer\n")); + limLog(pMac, LOGP, FL("could not activate Join failure timer")); psessionEntry->limMlmState = psessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, pMac->lim.gLimMlmState)); //memory is freed up below. @@ -3700,7 +3674,7 @@ static void limProcessSwitchChannelJoinReq(tpAniSirGlobal pMac, tpPESession pses // Activate Join Periodic Probe Req timer if (tx_timer_activate(&pMac->lim.limTimers.gLimPeriodicJoinProbeReqTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer\n")); + limLog(pMac, LOGP, FL("could not activate Periodic Join req failure timer")); goto error; } } @@ -3758,7 +3732,7 @@ void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void *body) if((psessionEntry = peFindSessionBySessionId(pMac, peSessionId))== NULL) { palFreeMemory( pMac->hHdd, (tANI_U8 *)body); - limLog(pMac, LOGP, FL("session does not exist for given sessionId\n")); + limLog(pMac, LOGP, FL("session does not exist for given sessionId")); return; } #if defined WLAN_FEATURE_VOWIFI @@ -3788,7 +3762,7 @@ void limProcessSwitchChannelRsp(tpAniSirGlobal pMac, void *body) */ if (pMac->lim.gpchangeChannelCallback) { - PELOG1(limLog( pMac, LOG1, "Channel changed hence invoke registered call back\n");) + PELOG1(limLog( pMac, LOG1, "Channel changed hence invoke registered call back");) pMac->lim.gpchangeChannelCallback(pMac, status, pMac->lim.gpchangeChannelData, psessionEntry); } break; @@ -3834,7 +3808,7 @@ void limProcessStartScanRsp(tpAniSirGlobal pMac, void *body) palFreeMemory( pMac->hHdd, (tANI_U8 *)body); if( pMac->lim.abortScan ) { - limLog( pMac, LOGW, FL(" finish scan\n") ); + limLog( pMac, LOGW, FL(" finish scan") ); pMac->lim.abortScan = 0; limDeactivateAndChangeTimer(pMac, eLIM_MIN_CHANNEL_TIMER); limDeactivateAndChangeTimer(pMac, eLIM_MAX_CHANNEL_TIMER); @@ -3848,7 +3822,7 @@ void limProcessStartScanRsp(tpAniSirGlobal pMac, void *body) case eLIM_HAL_START_SCAN_WAIT_STATE: if (status != (tANI_U32) eHAL_STATUS_SUCCESS) { - PELOGW(limLog(pMac, LOGW, FL("StartScanRsp with failed status= %d\n"), status);) + PELOGW(limLog(pMac, LOGW, FL("StartScanRsp with failed status= %d"), status);) // // FIXME - With this, LIM will try and recover state, but // eWNI_SME_SCAN_CNF maybe reporting an incorrect @@ -3867,7 +3841,7 @@ void limProcessStartScanRsp(tpAniSirGlobal pMac, void *body) } break; default: - limLog(pMac, LOGW, FL("Rcvd StartScanRsp not in WAIT State, state %d\n"), + limLog(pMac, LOGW, FL("Rcvd StartScanRsp not in WAIT State, state %d"), pMac->lim.gLimHalScanState); break; } @@ -3886,7 +3860,7 @@ void limProcessEndScanRsp(tpAniSirGlobal pMac, void *body) case eLIM_HAL_END_SCAN_WAIT_STATE: if (status != (tANI_U32) eHAL_STATUS_SUCCESS) { - PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d\n"), status);) + PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d"), status);) pMac->lim.gLimHalScanState = eLIM_HAL_IDLE_SCAN_STATE; limCompleteMlmScan(pMac, eSIR_SME_HAL_SCAN_INIT_FAILED); } @@ -3897,7 +3871,7 @@ void limProcessEndScanRsp(tpAniSirGlobal pMac, void *body) } break; default: - limLog(pMac, LOGW, FL("Rcvd endScanRsp not in WAIT State, state %d\n"), + limLog(pMac, LOGW, FL("Rcvd endScanRsp not in WAIT State, state %d"), pMac->lim.gLimHalScanState); break; } @@ -3994,7 +3968,7 @@ void limProcessFinishScanRsp(tpAniSirGlobal pMac, void *body) } if (status != (tANI_U32) eHAL_STATUS_SUCCESS) { - PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d\n"), status);) + PELOGW(limLog(pMac, LOGW, FL("EndScanRsp with failed status= %d"), status);) } break; //WLAN_SUSPEND_LINK Related @@ -4009,14 +3983,14 @@ void limProcessFinishScanRsp(tpAniSirGlobal pMac, void *body) } else { - limLog( pMac, LOGP, "No Resume link callback set but station is in suspend state\n"); + limLog( pMac, LOGP, "No Resume link callback set but station is in suspend state"); return; } break; //end WLAN_SUSPEND_LINK Related default: - limLog(pMac, LOGW, FL("Rcvd FinishScanRsp not in WAIT State, state %d\n"), + limLog(pMac, LOGW, FL("Rcvd FinishScanRsp not in WAIT State, state %d"), pMac->lim.gLimHalScanState); break; } @@ -4047,12 +4021,12 @@ void limProcessMlmHalAddBARsp( tpAniSirGlobal pMac, //now LIM can process any defer message. SET_LIM_PROCESS_DEFD_MESGS(pMac, true); if (pAddBAParams == NULL) { - PELOGE(limLog(pMac, LOGE,FL("NULL ADD BA Response from HAL\n"));) + PELOGE(limLog(pMac, LOGE,FL("NULL ADD BA Response from HAL"));) return; } if((psessionEntry = peFindSessionBySessionId(pMac, pAddBAParams->sessionId))==NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionID: %d\n"),pAddBAParams->sessionId );) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given sessionID: %d"),pAddBAParams->sessionId );) palFreeMemory(pMac->hHdd, (void*)limMsgQ->bodyptr); return; } @@ -4063,7 +4037,7 @@ void limProcessMlmHalAddBARsp( tpAniSirGlobal pMac, // Allocate for LIM_MLM_ADDBA_CNF if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pMlmAddBACnf, sizeof( tLimMlmAddBACnf ))) { - limLog( pMac, LOGP, FL(" palAllocateMemory failed with error code %d\n")); + limLog( pMac, LOGP, FL(" palAllocateMemory failed with error code %d")); palFreeMemory(pMac->hHdd, (void*)limMsgQ->bodyptr); return; } @@ -4108,13 +4082,13 @@ tLimBAState curBaState; tpPESession psessionEntry = NULL; if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmAddBACnf = (tpLimMlmAddBACnf) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac,pMlmAddBACnf->sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; } @@ -4123,7 +4097,7 @@ pMlmAddBACnf = (tpLimMlmAddBACnf) pMsgBuf; if( NULL == pSta ) { PELOGE(limLog( pMac, LOGE, - FL( "STA context not found - ignoring ADDBA CNF from HAL\n" ));) + FL( "STA context not found - ignoring ADDBA CNF from HAL" ));) palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; } @@ -4132,7 +4106,7 @@ pMlmAddBACnf = (tpLimMlmAddBACnf) pMsgBuf; if( eLIM_BA_STATE_WT_ADD_RSP != curBaState) { PELOGE(limLog( pMac, LOGE, - FL( "Received unexpected ADDBA CNF when STA BA state is %d\n" ), + FL( "Received unexpected ADDBA CNF when STA BA state is %d" ), curBaState );) palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; @@ -4201,13 +4175,13 @@ void limProcessMlmDelBACnf( tpAniSirGlobal pMac, if(pMsgBuf == NULL) { - PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n"));) + PELOGE(limLog(pMac, LOGE,FL("Buffer is Pointing to NULL"));) return; } pMlmDelBACnf = (tpLimMlmDelBACnf) pMsgBuf; if((psessionEntry = peFindSessionBySessionId(pMac, pMlmDelBACnf->sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; } @@ -4216,14 +4190,14 @@ void limProcessMlmDelBACnf( tpAniSirGlobal pMac, if( NULL == pSta ) { limLog( pMac, LOGE, - FL( "STA context not found - ignoring DELBA CNF from HAL\n" )); + FL( "STA context not found - ignoring DELBA CNF from HAL" )); palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; } if(NULL == pMlmDelBACnf) { limLog( pMac, LOGE, - FL( "pMlmDelBACnf is NULL - ignoring DELBA CNF from HAL\n" )); + FL( "pMlmDelBACnf is NULL - ignoring DELBA CNF from HAL" )); return; } // Need to validate baState @@ -4231,7 +4205,7 @@ void limProcessMlmDelBACnf( tpAniSirGlobal pMac, if( eLIM_BA_STATE_WT_DEL_RSP != curBaState ) { limLog( pMac, LOGE, - FL( "Received unexpected DELBA CNF when STA BA state is %d\n" ), + FL( "Received unexpected DELBA CNF when STA BA state is %d" ), curBaState ); palFreeMemory( pMac->hHdd, (void *) pMsgBuf ); return; @@ -4267,7 +4241,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, if((psessionEntry = peFindSessionByBssid(pMac,pBADeleteParams->bssId,&sessionId))== NULL) { - PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId\n"));) + PELOGE(limLog(pMac, LOGE,FL("session does not exist for given BSSId"));) palFreeMemory( pMac->hHdd, (void *) limMsgQ->bodyptr ); return; } @@ -4276,7 +4250,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, if( NULL == pSta ) { limLog( pMac, LOGE, - FL( "STA context not found - ignoring BA Delete IND from HAL\n" )); + FL( "STA context not found - ignoring BA Delete IND from HAL" )); goto returnAfterCleanup; } @@ -4285,7 +4259,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, if( eLIM_BA_STATE_IDLE != curBaState ) { limLog( pMac, LOGE, - FL( "Received unexpected BA Delete IND when STA BA state is %d\n" ), + FL( "Received unexpected BA Delete IND when STA BA state is %d" ), curBaState ); goto returnAfterCleanup; } @@ -4305,7 +4279,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, if( eSIR_FAILURE == status ) { limLog( pMac, LOGW, - FL("Received an INVALID DELBA Delete Ind for TID %d...\n"), + FL("Received an INVALID DELBA Delete Ind for TID %d..."), pBADeleteParams->baTID ); } else @@ -4319,7 +4293,7 @@ void limProcessMlmHalBADeleteInd( tpAniSirGlobal pMac, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry ))) { limLog( pMac, LOGE, - FL( "Attempt to post LIM_MLM_DELBA_REQ failed with status %d\n" ), status); + FL( "Attempt to post LIM_MLM_DELBA_REQ failed with status %d" ), status); } else { @@ -4370,7 +4344,7 @@ limProcessSetMimoRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) /** If Updation of the HAL Fail's*/ if (pMIMO_PSParams->status != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Update HAL / SW Mac for MIMO State has Failed\n")); + limLog(pMac, LOGP, FL("Update HAL / SW Mac for MIMO State has Failed")); break; } @@ -4394,7 +4368,7 @@ limProcessSetMimoRsp(tpAniSirGlobal pMac, tpSirMsgQ limMsg) /** Send Action Frame with the corresponding mode */ retStatus = limSendSMPowerStateFrame(pMac, macAddr, pMIMO_PSParams->htMIMOPSState); if (retStatus != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Sending Action Frame has failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("Sending Action Frame has failed"));) break; } } @@ -4445,7 +4419,7 @@ limHandleDelBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESe if ((pStaDs = dphAddHashEntry(pMac, psessionEntry->limReAssocbssId, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable)) == NULL) { // Could not add hash table entry - PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for \n"));) + PELOGE(limLog(pMac, LOGE, FL("could not add hash entry at DPH for "));) limPrintMacAddr(pMac, psessionEntry->limReAssocbssId, LOGE); mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS; @@ -4472,7 +4446,7 @@ limHandleDelBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESe //updateBss flag is false, as in this case, PE is first deleting the existing BSS and then adding a new one. if (eSIR_SUCCESS != limStaSendAddBss( pMac, assocRsp, &beaconStruct, &psessionEntry->pLimReAssocReq->bssDescription, false, psessionEntry)) { - limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed \n")); + limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed ")); retStatus = eSIR_FAILURE; } if (retStatus != eSIR_SUCCESS) @@ -4506,7 +4480,7 @@ limHandleDelBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESe } break; default: - PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State\n"));) + PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State"));) mlmReassocCnf.resultCode = eSIR_SME_REFUSED; mlmReassocCnf.protStatusCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; goto Error; @@ -4526,12 +4500,12 @@ limProcessBtampAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession ps if (NULL == pAddBssParams) { - limLog( pMac, LOGE, FL( "Invalid body pointer in message\n")); + limLog( pMac, LOGE, FL( "Invalid body pointer in message")); goto end; } if( eHAL_STATUS_SUCCESS == pAddBssParams->status ) { - limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS\n")); + limLog(pMac, LOG2, FL("WDA_ADD_BSS_RSP returned with eHAL_STATUS_SUCCESS")); if (psessionEntry->bssType == eSIR_BTAMP_AP_MODE) { if (limSetLinkState(pMac, eSIR_LINK_BTAMP_AP_STATE, psessionEntry->bssId, @@ -4554,7 +4528,7 @@ limProcessBtampAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession ps limCreateTimers(pMac); /* Update the lim global gLimTriggerBackgroundScanDuringQuietBss */ if( eSIR_SUCCESS != wlan_cfgGetInt( pMac, WNI_CFG_TRIG_STA_BK_SCAN, &val )) - limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!\n")); + limLog( pMac, LOGP, FL("Failed to get WNI_CFG_TRIG_STA_BK_SCAN!")); pMac->lim.gLimTriggerBackgroundScanDuringQuietBss = (val) ? 1 : 0; // Apply previously set configuration at HW limApplyConfiguration(pMac,psessionEntry); @@ -4563,7 +4537,7 @@ limProcessBtampAddBssRsp( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ,tpPESession ps } else { - limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d\n" ),pAddBssParams->status ); + limLog( pMac, LOGE, FL( "WDA_ADD_BSS_REQ failed with status %d" ),pAddBssParams->status ); mlmStartCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; } mlmStartCnf.sessionId = psessionEntry->peSessionId; @@ -4606,7 +4580,7 @@ limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPES if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pBeaconStruct, sizeof(tSchBeaconStruct))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limHandleAddBssInReAssocContext\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limHandleAddBssInReAssocContext") ); mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; mlmReassocCnf.protStatusCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto Error; @@ -4616,7 +4590,7 @@ limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPES pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); if (pStaDs == NULL ) { - PELOGE(limLog(pMac, LOGE, FL("Fail to get STA PEER entry from hash\n"));) + PELOGE(limLog(pMac, LOGE, FL("Fail to get STA PEER entry from hash"));) mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; mlmReassocCnf.protStatusCode = eSIR_SME_SUCCESS; palFreeMemory(pMac->hHdd, pBeaconStruct); @@ -4645,7 +4619,7 @@ limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPES if (eSIR_SUCCESS != limStaSendAddBss( pMac, assocRsp, pBeaconStruct, &psessionEntry->pLimReAssocReq->bssDescription, true, psessionEntry)) { - limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed \n")); + limLog( pMac, LOGE, FL( "Posting ADDBSS in the ReAssocContext has Failed ")); retStatus = eSIR_FAILURE; } if (retStatus != eSIR_SUCCESS) @@ -4680,7 +4654,7 @@ limHandleAddBssInReAssocContext(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPES } break; default: - PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State\n"));) + PELOGE(limLog(pMac, LOGE, FL("DelBss is being invoked in the wrong system Role /unhandled SME State"));) mlmReassocCnf.resultCode = eSIR_SME_REFUSED; mlmReassocCnf.protStatusCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; goto Error; @@ -4701,24 +4675,24 @@ limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBu if(pMsgBuf == NULL) { - limLog(pMac, LOGE, FL("pMsgBuf is NULL \n")); + limLog(pMac, LOGE, FL("pMsgBuf is NULL ")); goto end; } if ((limAssocCnfSerDes(pMac, &assocCnf, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || !__limIsSmeAssocCnfValid(&assocCnf)) { - limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message \n")); + limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message ")); goto end; } if((psessionEntry = peFindSessionByBssid(pMac, assocCnf.bssId, &sessionId))== NULL) { - limLog(pMac, LOGE, FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE, FL("session does not exist for given bssId")); goto end; } if ( ((psessionEntry->limSystemRole != eLIM_AP_ROLE) && (psessionEntry->limSystemRole != eLIM_BT_AMP_AP_ROLE)) || ((psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) && (psessionEntry->limSmeState != eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) { - limLog(pMac, LOGE, FL("Received unexpected message %X in state %X, in role %X\n"), + limLog(pMac, LOGE, FL("Received unexpected message %X in state %X, in role %X"), msgType, psessionEntry->limSmeState , psessionEntry->limSystemRole); goto end; } @@ -4757,7 +4731,7 @@ limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBu ** Deactivate/delet CNF_WAIT timer since ASSOC_CNF ** has been received **/ - limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer\n")); + limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer")); limDeactivateAndChangePerStaIdTimer(pMac, eLIM_CNF_WAIT_TIMER, pStaDs->assocId); if (assocCnf.statusCode == eSIR_SME_SUCCESS) { @@ -4766,7 +4740,7 @@ limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBu * Association Response frame to the requesting BTAMP-STA. */ pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; - limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) \n"), pStaDs->assocId); + limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) "), pStaDs->assocId); limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS, pStaDs->assocId, pStaDs->staAddr, pStaDs->mlmStaContext.subType, pStaDs, psessionEntry); goto end; @@ -4803,14 +4777,14 @@ limSendBeaconInd(tpAniSirGlobal pMac, tpPESession psessionEntry){ /** Allocate the Memory for Beacon Pre Message and for Stations in PoweSave*/ if(psessionEntry == NULL ){ PELOGE( limLog( pMac, LOGE, - FL( "Error:Unable to get the PESessionEntry\n" ));) + FL( "Error:Unable to get the PESessionEntry" ));) return; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pBeaconGenParams, (sizeof(*pBeaconGenParams)))) { PELOGE( limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during sending beaconPreMessage\n" ));) + FL( "Unable to PAL allocate memory during sending beaconPreMessage" ));) return; } palZeroMemory( pMac->hHdd, pBeaconGenParams, sizeof(*pBeaconGenParams)); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c index a3075030fc2..4f9c623a00b 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeReqFrame.c @@ -135,7 +135,7 @@ void limGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U8 *addr, *overlap = eSAP_WPSPBC_ONE_WPSPBC_PROBE_REQ_IN120S; // One WPS probe request in 120 second } - PELOGE(limLog(pMac, LOGE, FL("overlap = %d\n"), *overlap);) + PELOGE(limLog(pMac, LOGE, FL("overlap = %d"), *overlap);) PELOGE(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOGE, addr, sizeof(tSirMacAddr));) PELOGE(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOGE, uuid_e, SIR_WPS_UUID_LEN);) @@ -169,7 +169,7 @@ static void limRemoveTimeoutPBCsessions(tpAniSirGlobal pMac, tSirWPSPBCSession * prev = pbc; pbc = pbc->next; - PELOG4(limLog(pMac, LOG4, FL("WPS PBC sessions remove\n"));) + PELOG4(limLog(pMac, LOG4, FL("WPS PBC sessions remove"));) PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, prev->addr, sizeof(tSirMacAddr));) PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, prev->uuid_e, SIR_WPS_UUID_LEN);) @@ -231,7 +231,7 @@ static void limUpdatePBCSessionEntry(tpAniSirGlobal pMac, curTime = (tANI_TIMESTAMP)(palGetTickCount(pMac->hHdd) / PAL_TICKS_PER_SECOND); - PELOG4(limLog(pMac, LOG4, FL("Receive WPS probe reques curTime=%d\n"), curTime);) + PELOG4(limLog(pMac, LOG4, FL("Receive WPS probe reques curTime=%d"), curTime);) PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, addr, sizeof(tSirMacAddr));) PELOG4(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, uuid_e, SIR_WPS_UUID_LEN);) @@ -254,7 +254,7 @@ static void limUpdatePBCSessionEntry(tpAniSirGlobal pMac, if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **) &pbc, sizeof(tSirWPSPBCSession))) { - PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!\n"));) + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) return; } palCopyMemory(pMac->hHdd, (tANI_U8 *)pbc->addr, (tANI_U8 *)addr, sizeof(tSirMacAddr)); @@ -309,7 +309,7 @@ void limWPSPBCTimeout(tpAniSirGlobal pMac, tpPESession psessionEntry) curTime = (tANI_TIMESTAMP)(palGetTickCount(pMac->hHdd) / PAL_TICKS_PER_SECOND); - PELOG3(limLog(pMac, LOG3, FL("WPS PBC cleanup timeout curTime=%d\n"), curTime);) + PELOG3(limLog(pMac, LOG3, FL("WPS PBC cleanup timeout curTime=%d"), curTime);) prev = psessionEntry->pAPWPSPBCSession; if(prev) @@ -443,7 +443,7 @@ limProcessProbeReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession || (pMac->lim.gLimHalScanState != eLIM_HAL_IDLE_SCAN_STATE))) { limLog(pMac, LOG3, - FL("While GO is scanning, don't send probe response on diff channel\n")); + FL("While GO is scanning, don't send probe response on diff channel")); break; } @@ -538,7 +538,7 @@ limProcessProbeReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession else { if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) - limLog(pMac, LOGP,"Failed to cfg get id %d\n", WNI_CFG_WPS_ENABLE ); + limLog(pMac, LOGP,"Failed to cfg get id %d", WNI_CFG_WPS_ENABLE ); wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP; if ((wpsApEnable) && @@ -551,7 +551,7 @@ limProcessProbeReqFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_PROBE_REQ\n")); + FL("call to palAllocateMemory failed for eWNI_SME_PROBE_REQ")); return; } msgQ.type = eWNI_SME_PROBE_REQ; @@ -796,7 +796,7 @@ limSendSmeProbeReqInd(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_PROBE_REQ\n")); + FL("call to palAllocateMemory failed for eWNI_SME_PROBE_REQ")); return; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c index 0e695980943..58c49f94580 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessProbeRspFrame.c @@ -118,7 +118,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pProbeRsp, sizeof(tSirProbeRespBeacon))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessProbeRspFrame\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessProbeRspFrame") ); return; } @@ -176,6 +176,14 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession { frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); + } + // Get pointer to Probe Response frame body pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); @@ -238,7 +246,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession &cfg) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(currentBssId,psessionEntry->bssId); @@ -252,7 +260,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession if (!LIM_IS_CONNECTION_ACTIVE(psessionEntry)) { limLog(pMac, LOGW, - FL("Received Probe Resp from AP. So it is alive!!\n")); + FL("Received Probe Resp from AP. So it is alive!!")); if (pProbeRsp->HTInfo.present) limReceivedHBHandler(pMac, (tANI_U8)pProbeRsp->HTInfo.primaryChannel, psessionEntry); @@ -288,7 +296,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession limGetQosMode(psessionEntry, &qosEnabled); limGetWmeMode(psessionEntry, &wmeEnabled); PELOG2(limLog(pMac, LOG2, - FL("wmeEdcaPresent: %d wmeEnabled: %d, edcaPresent: %d, qosEnabled: %d, edcaParams.qosInfo.count: %d schObject.gLimEdcaParamSetCount: %d\n"), + FL("wmeEdcaPresent: %d wmeEnabled: %d, edcaPresent: %d, qosEnabled: %d, edcaParams.qosInfo.count: %d schObject.gLimEdcaParamSetCount: %d"), pProbeRsp->wmeEdcaPresent, wmeEnabled, pProbeRsp->edcaPresent, qosEnabled, pProbeRsp->edcaParams.qosInfo.count, psessionEntry->gLimEdcaParamSetCount);) if (((pProbeRsp->wmeEdcaPresent && wmeEnabled) || @@ -296,7 +304,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession (pProbeRsp->edcaParams.qosInfo.count != psessionEntry->gLimEdcaParamSetCount)) { if (schBeaconEdcaProcess(pMac, &pProbeRsp->edcaParams, psessionEntry) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("EDCA parameter processing error\n"));) + PELOGE(limLog(pMac, LOGE, FL("EDCA parameter processing error"));) else if (pStaDs != NULL) { // If needed, downgrade the EDCA parameters @@ -308,7 +316,7 @@ limProcessProbeRspFrame(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo,tpPESession limSendEdcaParams(pMac, psessionEntry->gLimEdcaParamsActive, pStaDs->bssId, eANI_BOOLEAN_FALSE); } else - PELOGE(limLog(pMac, LOGE, FL("Self Entry missing in Hash Table\n"));) + PELOGE(limLog(pMac, LOGE, FL("Self Entry missing in Hash Table"));) } @@ -340,7 +348,7 @@ limProcessProbeRspFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pProbeRsp, sizeof(tSirProbeRespBeacon))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessProbeRspFrameNoSession\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limProcessProbeRspFrameNoSession") ); return; } @@ -357,10 +365,26 @@ limProcessProbeRspFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) WDA_GET_RX_MPDU_LEN(pRxPacketInfo)); limPrintMacAddr(pMac, pHdr->sa, LOG2); - if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo) || + WDA_GET_ROAMCANDIDATEIND(pRxPacketInfo))) { - palFreeMemory(pMac->hHdd, pProbeRsp); - return; +#endif + if (limDeactivateMinChannelTimerDuringScan(pMac) != eSIR_SUCCESS) + { + palFreeMemory(pMac->hHdd, pProbeRsp); + return; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif + // Validate IE information before processing Probe Response Frame + if (limValidateIEInformationInProbeRspFrame(pRxPacketInfo) != eSIR_SUCCESS) + { + PELOG1(limLog(pMac, LOG1,FL("Parse error ProbeResponse, length=%d"), + frameLen);) + palFreeMemory(pMac->hHdd, pProbeRsp); + return; } // Validate IE information before processing Probe Response Frame if (limValidateIEInformationInProbeRspFrame(pRxPacketInfo) != eSIR_SUCCESS) @@ -376,21 +400,58 @@ limProcessProbeRspFrameNoSession(tpAniSirGlobal pMac, tANI_U8 *pRxPacketInfo) * - eLIM_MLM_BSS_STARTED_STATE * Hence, expect Probe Response only when * 1. STA is in scan mode waiting for Beacon/Probe response + * 2. LFR logic in FW sends up candidate frames * * Ignore Probe Response frame in all other states */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo)) + { + frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); + } + + // Get pointer to Probe Response frame body + pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + + if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) == eSIR_FAILURE) + { + limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d\n"), frameLen); + palFreeMemory(pMac->hHdd, pProbeRsp); + return; + } + limLog( pMac, LOG2, FL("Save this probe rsp in LFR cache")); + limCheckAndAddBssDescription(pMac, pProbeRsp, pRxPacketInfo, + eANI_BOOLEAN_FALSE, eANI_BOOLEAN_TRUE); + } + else +#endif if( (pMac->lim.gLimMlmState == eLIM_MLM_WT_PROBE_RESP_STATE) || (pMac->lim.gLimMlmState == eLIM_MLM_PASSIVE_SCAN_STATE) || //mlm state check should be global - 18th oct (pMac->lim.gLimMlmState == eLIM_MLM_LEARN_STATE) ) { frameLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); + if (pMac->lim.gLimBackgroundScanMode == eSIR_ROAMING_SCAN) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + FL("Probe Resp Frame Received: BSSID " MAC_ADDRESS_STR " (RSSI %d)"), + MAC_ADDR_ARRAY(pHdr->bssId), + (uint)abs((tANI_S8)WDA_GET_RX_RSSI_DB(pRxPacketInfo))); + } + // Get pointer to Probe Response frame body pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); if (sirConvertProbeFrame2Struct(pMac, pBody, frameLen, pProbeRsp) == eSIR_FAILURE) { - limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d\n"), frameLen); + limLog(pMac, LOG1, FL("Parse error ProbeResponse, length=%d"), frameLen); palFreeMemory(pMac->hHdd, pProbeRsp); return; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c index d08c060a37e..f2852b351b6 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessSmeReqMessages.c @@ -121,7 +121,6 @@ void __limProcessSmeAssocCnfNew(tpAniSirGlobal, tANI_U32, tANI_U32 *); extern void peRegisterTLHandle(tpAniSirGlobal pMac); -extern int limProcessRemainOnChnlReq(tpAniSirGlobal pMac, tANI_U32 *pMsg); #ifdef BACKGROUND_SCAN_ENABLED @@ -138,7 +137,7 @@ __limBackgroundScanInitiate(tpAniSirGlobal pMac) limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, NO_SESSION, eLIM_BACKGROUND_SCAN_TIMER)); if (tx_timer_activate(&pMac->lim.limTimers.gLimBackgroundScanTimer) != TX_SUCCESS) - limLog(pMac, LOGP, FL("could not activate background scan timer\n")); + limLog(pMac, LOGP, FL("could not activate background scan timer")); pMac->lim.gLimBackgroundScanStarted = true; pMac->lim.gLimBackgroundScanChannelId = 0; } @@ -189,7 +188,7 @@ __limFreshScanReqd(tpAniSirGlobal pMac, tANI_U8 returnFreshResults) } } - PELOG1(limLog(pMac, LOG1, FL("FreshScanReqd: %d \n"), validState);) + PELOG1(limLog(pMac, LOG1, FL("FreshScanReqd: %d "), validState);) if( (validState) && (returnFreshResults & SIR_BG_SCAN_RETURN_FRESH_RESULTS)) return TRUE; @@ -284,10 +283,10 @@ __limIsDeferedMsgForLearn(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { if (limDeferMsg(pMac, pMsg) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d\n"), pMsg->type);) + PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d"), pMsg->type);) return eANI_BOOLEAN_FALSE; } - PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d"), pMsg->type);) /** Send finish scan req to HAL only if LIM is not waiting for any response @@ -328,10 +327,10 @@ __limIsDeferedMsgForRadar(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { if (limDeferMsg(pMac, pMsg) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d\n"), pMsg->type);) + PELOGE(limLog(pMac, LOGE, FL("Could not defer Msg = %d"), pMsg->type);) return eANI_BOOLEAN_FALSE; } - PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d\n"), + PELOG1(limLog(pMac, LOG1, FL("Defer the message, in learn mode type = %d"), pMsg->type);) return eANI_BOOLEAN_TRUE; } @@ -365,7 +364,7 @@ __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U16 smetransactionId; - PELOG1(limLog(pMac, LOG1, FL("Received START_REQ\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received START_REQ"));) limGetSessionInfo(pMac,(tANI_U8 *)pMsgBuf,&smesessionId,&smetransactionId); @@ -384,6 +383,9 @@ __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// By default return unique scan results pMac->lim.gLimReturnUniqueResults = true; pMac->lim.gLimSmeScanResultLength = 0; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->lim.gLimSmeLfrScanResultLength = 0; +#endif if (((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd) { @@ -394,7 +396,7 @@ __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_NEW_BSS_FOUND_IND, ((tSirSmeStartReq *) pMsgBuf)->sendNewBssInd) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set NEIGHBOR_BSS_IND at CFG\n")); + limLog(pMac, LOGP, FL("could not set NEIGHBOR_BSS_IND at CFG")); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; } } @@ -406,7 +408,7 @@ __limProcessSmeStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * other than OFFLINE. Return response to host and * log error */ - limLog(pMac, LOGE, FL("Invalid SME_START_REQ received in SME state %X\n"),pMac->lim.gLimSmeState ); + limLog(pMac, LOGE, FL("Invalid SME_START_REQ received in SME state %X"),pMac->lim.gLimSmeState ); limPrintSmeState(pMac, LOGE, pMac->lim.gLimSmeState); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; } @@ -436,12 +438,12 @@ __limProcessSmeSysReadyInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { peRegisterTLHandle(pMac); } - PELOGW(limLog(pMac, LOGW, FL("sending WDA_SYS_READY_IND msg to HAL\n"));) + PELOGW(limLog(pMac, LOGW, FL("sending WDA_SYS_READY_IND msg to HAL"));) MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); if (eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { - limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed\n")); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); return eANI_BOOLEAN_TRUE; } return eANI_BOOLEAN_FALSE; @@ -528,8 +530,8 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U32 val = 0; tSirRetStatus retStatus; tSirMacChanNum channelNumber; - tLimMlmStartReq *pMlmStartReq; - tpSirSmeStartBssReq pSmeStartBssReq; //Local variable for Start BSS Req.. Added For BT-AMP Support + tLimMlmStartReq *pMlmStartReq = NULL; + tpSirSmeStartBssReq pSmeStartBssReq = NULL; tSirResultCodes retCode = eSIR_SME_SUCCESS; tANI_U32 autoGenBssId = FALSE; //Flag Used in case of IBSS to Auto generate BSSID. tANI_U8 sessionId; @@ -542,7 +544,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limDiagEventReport(pMac, WLAN_PE_DIAG_START_BSS_REQ_EVENT, NULL, 0, 0); #endif //FEATURE_WLAN_DIAG_SUPPORT - PELOG1(limLog(pMac, LOG1, FL("Received START_BSS_REQ\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received START_BSS_REQ"));) /* Global Sme state and mlm states are not defined yet , for BT-AMP Suppoprt . TO BE DONE */ if ( (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) || @@ -553,7 +555,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSmeStartBssReq, size)) { - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed for pMac->lim.gpLimStartBssReq\n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed for pMac->lim.gpLimStartBssReq"));) /// Send failure response to host retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; @@ -564,13 +566,13 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((limStartBssReqSerDes(pMac, pSmeStartBssReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || (!limIsSmeStartBssReqValid(pMac, pSmeStartBssReq))) { - PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ"));) retCode = eSIR_SME_INVALID_PARAMETERS; goto free; } #if 0 PELOG3(limLog(pMac, LOG3, - FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d\n"), + FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d"), pMac->lim.gpLimStartBssReq->bssType, pMac->lim.gpLimStartBssReq->channelId);) #endif @@ -578,7 +580,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * If session is not existed , then create a new session */ if((psessionEntry = peFindSessionByBssid(pMac,pSmeStartBssReq->bssId,&sessionId)) != NULL) { - limLog(pMac, LOGW, FL("Session Already exists for given BSSID\n")); + limLog(pMac, LOGW, FL("Session Already exists for given BSSID")); retCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; psessionEntry = NULL; goto free; @@ -587,7 +589,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { if((psessionEntry = peCreateSession(pMac,pSmeStartBssReq->bssId,&sessionId, pMac->lim.maxStation)) == NULL) { - limLog(pMac, LOGW, FL("Session Can not be created \n")); + limLog(pMac, LOGW, FL("Session Can not be created ")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto free; } @@ -716,7 +718,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&psessionEntry->parsedAssocReq, (psessionEntry->dph.dphHashTable.size * sizeof(tpSirAssocReq)) )) { - limLog(pMac, LOGW, FL("palAllocateMemory() failed\n")); + limLog(pMac, LOGW, FL("palAllocateMemory() failed")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto free; } @@ -742,7 +744,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) &chanWidth) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve Channel Width from CFG\n")); + FL("Unable to retrieve Channel Width from CFG")); } if(chanWidth == eHT_CHANNEL_WIDTH_20MHZ || chanWidth == eHT_CHANNEL_WIDTH_40MHZ) @@ -750,7 +752,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_WIDTH, WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto free; } @@ -760,7 +762,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_WIDTH, WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto free; } @@ -768,12 +770,12 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) centerChan = limGetCenterChannel(pMac,channelNumber,pSmeStartBssReq->cbMode,WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ); if(centerChan != eSIR_CFG_INVALID_ID) { - limLog(pMac, LOGW, FL("***Center Channel for 80MHZ channel width = %ld\n"),centerChan); + limLog(pMac, LOGW, FL("***Center Channel for 80MHZ channel width = %ld"),centerChan); psessionEntry->apCenterChan = centerChan; if (cfgSetInt(pMac, WNI_CFG_VHT_CHANNEL_CENTER_FREQ_SEGMENT1, centerChan) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_CHANNEL_BONDING_MODE at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto free; } @@ -787,7 +789,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) &chanWidth) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve Channel Width from CFG\n")); + FL("Unable to retrieve Channel Width from CFG")); } /*For Sta+p2p-Go concurrency vhtTxChannelWidthSet is used for storing p2p-GO channel width @@ -802,7 +804,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } else { - PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received invalid eWNI_SME_START_BSS_REQ"));) retCode = eSIR_SME_INVALID_PARAMETERS; goto free; } @@ -836,14 +838,14 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) *reserved reserved RIFS Lsig n-GF ht20 11g 11b*/ palCopyMemory( pMac->hHdd, (void *) &psessionEntry->cfgProtection, (void *) &pSmeStartBssReq->ht_capab, - sizeof( tANI_U16 )); + sizeof( tCfgProtection )); psessionEntry->pAPWPSPBCSession = NULL; // Initialize WPS PBC session link list } // Prepare and Issue LIM_MLM_START_REQ to MLM if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmStartReq, sizeof(tLimMlmStartReq))) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmStartReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmStartReq")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto free; } @@ -870,7 +872,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) //len = sizeof(tSirMacAddr); //retStatus = wlan_cfgGetStr(pMac, WNI_CFG_STA_ID, (tANI_U8 *) pMlmStartReq->bssId, &len); //if (retStatus != eSIR_SUCCESS) - //limLog(pMac, LOGP, FL("could not retrive BSSID, retStatus=%d\n"), retStatus); + //limLog(pMac, LOGP, FL("could not retrive BSSID, retStatus=%d"), retStatus); /* Copy the BSSId from sessionTable to mlmStartReq struct */ sirCopyMacAddr(pMlmStartReq->bssId,psessionEntry->bssId); @@ -882,7 +884,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((retStatus = wlan_cfgGetInt(pMac, WNI_CFG_IBSS_AUTO_BSSID, &autoGenBssId)) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not retrieve Auto Gen BSSID, retStatus=%d\n"), retStatus); + limLog(pMac, LOGP, FL("Could not retrieve Auto Gen BSSID, retStatus=%d"), retStatus); retCode = eSIR_LOGP_EXCEPTION; goto free; } @@ -894,7 +896,7 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMlmStartReq->bssId[0] & 0x01) { - PELOGE(limLog(pMac, LOGE, FL("Request to start IBSS with group BSSID\n Autogenerating the BSSID\n"));) + PELOGE(limLog(pMac, LOGE, FL("Request to start IBSS with group BSSID\n Autogenerating the BSSID"));) autoGenBssId = TRUE; } } @@ -921,16 +923,16 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) }else { if (wlan_cfgGetInt(pMac, WNI_CFG_DTIM_PERIOD, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve DTIM Period\n")); + limLog(pMac, LOGP, FL("could not retrieve DTIM Period")); pMlmStartReq->dtimPeriod = (tANI_U8)val; } if (wlan_cfgGetInt(pMac, WNI_CFG_CFP_PERIOD, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve Beacon interval\n")); + limLog(pMac, LOGP, FL("could not retrieve Beacon interval")); pMlmStartReq->cfParamSet.cfpPeriod = (tANI_U8)val; if (wlan_cfgGetInt(pMac, WNI_CFG_CFP_MAX_DURATION, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve CFPMaxDuration\n")); + limLog(pMac, LOGP, FL("could not retrieve CFPMaxDuration")); pMlmStartReq->cfParamSet.cfpMaxDuration = (tANI_U16) val; //this may not be needed anymore now, as rateSet is now included in the session entry and MLM has session context. @@ -957,14 +959,14 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (SIR_BAND_5_GHZ == psessionEntry->limRFBand) ) { if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); psessionEntry->lim11hEnable = val; } if (!psessionEntry->lim11hEnable) { if (cfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, 0) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); } psessionEntry ->limPrevSmeState = psessionEntry->limSmeState; @@ -977,14 +979,19 @@ __limHandleSmeStartBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { - limLog(pMac, LOGE, FL("Received unexpected START_BSS_REQ, in state %X\n"),pMac->lim.gLimSmeState); + limLog(pMac, LOGE, FL("Received unexpected START_BSS_REQ, in state %X"),pMac->lim.gLimSmeState); retCode = eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED; goto end; } // if (pMac->lim.gLimSmeState == eLIM_SME_OFFLINE_STATE) free: - palFreeMemory( pMac->hHdd, pSmeStartBssReq); - pSmeStartBssReq = NULL; + if ((psessionEntry != NULL) && + (psessionEntry->pLimStartBssReq == pSmeStartBssReq)) + { + psessionEntry->pLimStartBssReq = NULL; + } + palFreeMemory(pMac->hHdd, pSmeStartBssReq); + palFreeMemory(pMac->hHdd, pMlmStartReq); end: @@ -1092,7 +1099,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #endif //FEATURE_WLAN_DIAG_SUPPORT pScanReq = (tpSirSmeScanReq) pMsgBuf; - PELOG1(limLog(pMac, LOG1, FL("SME SCAN REQ numChan %d min %d max %d IELen %d first %d fresh %d unique %d type %d mode %d rsp %d\n"), + PELOG1(limLog(pMac, LOG1, FL("SME SCAN REQ numChan %d min %d max %d IELen %d first %d fresh %d unique %d type %d mode %d rsp %d"), pScanReq->channelList.numChannels, pScanReq->minChannelTime, pScanReq->maxChannelTime, @@ -1123,7 +1130,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (!limIsSmeScanReqValid(pMac, pScanReq)) { - PELOGW(limLog(pMac, LOGW, FL("Received SME_SCAN_REQ with invalid parameters\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received SME_SCAN_REQ with invalid parameters"));) if (pMac->lim.gLimRspReqd) { @@ -1221,7 +1228,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmScanReq (%d)\n"), len); + FL("call to palAllocateMemory failed for mlmScanReq (%d)"), len); return; } @@ -1239,7 +1246,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Valid channel list\n")); + FL("could not retrieve Valid channel list")); } pMlmScanReq->channelList.numChannels = (tANI_U8) cfg_len; } @@ -1253,7 +1260,7 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmScanReq(%d)\n"), len); + FL("call to palAllocateMemory failed for mlmScanReq(%d)"), len); return; } @@ -1321,24 +1328,58 @@ __limProcessSmeScanReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U16 scanRspLen = sizeof(tSirSmeScanRsp); pMac->lim.gLimRspReqd = false; - - if (pMac->lim.gLimSmeScanResultLength == 0) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pScanReq->returnFreshResults & SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS) { - limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, pScanReq->sessionId, pScanReq->transactionId); + pMac->lim.gLimSmeLfrScanResultLength = pMac->lim.gLimMlmLfrScanResultLength; + if (pMac->lim.gLimSmeLfrScanResultLength == 0) + { + limSendSmeLfrScanRsp(pMac, scanRspLen, + eSIR_SME_SUCCESS, + pScanReq->sessionId, + pScanReq->transactionId); + } + else + { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeLfrScanResultLength - + sizeof(tSirBssDescription); + limSendSmeLfrScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } } else { - scanRspLen = sizeof(tSirSmeScanRsp) + - pMac->lim.gLimSmeScanResultLength - - sizeof(tSirBssDescription); - limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, pScanReq->sessionId, pScanReq->transactionId); +#endif + if (pMac->lim.gLimSmeScanResultLength == 0) + { + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } + else + { + scanRspLen = sizeof(tSirSmeScanRsp) + + pMac->lim.gLimSmeScanResultLength - + sizeof(tSirBssDescription); + limSendSmeScanRsp(pMac, scanRspLen, eSIR_SME_SUCCESS, + pScanReq->sessionId, pScanReq->transactionId); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_RESUTLS) { // Discard previously cached scan results limReInitScanResults(pMac); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pScanReq->returnFreshResults & SIR_BG_SCAN_PURGE_LFR_RESULTS) + { + // Discard previously cached scan results + limReInitLfrScanResults(pMac); + } +#endif } // if (pMac->lim.gLimRspReqd) } // else ((pMac->lim.gLimSmeState == eLIM_SME_IDLE_STATE) || ... @@ -1363,7 +1404,7 @@ static void __limProcessSmeOemDataReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) //post the lim mlm message now if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)&pMlmOemDataReq, (sizeof(tLimMlmOemDataReq)))) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for mlmOemDataReq\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for mlmOemDataReq")); return; } @@ -1445,7 +1486,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) limDiagEventReport(pMac, WLAN_PE_DIAG_JOIN_REQ_EVENT, NULL, 0, 0); #endif //FEATURE_WLAN_DIAG_SUPPORT - PELOG1(limLog(pMac, LOG1, FL("Received SME_JOIN_REQ\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received SME_JOIN_REQ"));) #ifdef WLAN_FEATURE_VOWIFI /* Need to read the CFG here itself as this is used in limExtractAPCapability() below. @@ -1453,7 +1494,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * read, RRM related path before calling rrmUpdateConfig() is not getting executed causing issues * like not honoring power constraint on 1st association after driver loading. */ if (wlan_cfgGetInt(pMac, WNI_CFG_RRM_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("cfg get rrm enabled failed\n")); + limLog(pMac, LOGP, FL("cfg get rrm enabled failed")); pMac->rrm.rrmPEContext.rrmEnable = (val) ? 1 : 0; val = 0; #endif /* WLAN_FEATURE_VOWIFI */ @@ -1469,7 +1510,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8*) pMsgBuf); if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSmeJoinReq, nSize)) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSmeJoinReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSmeJoinReq")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; } @@ -1480,7 +1521,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { /// Received invalid eWNI_SME_JOIN_REQ // Log the event - limLog(pMac, LOGW, FL("received SME_JOIN_REQ with invalid data\n")); + limLog(pMac, LOGW, FL("received SME_JOIN_REQ with invalid data")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -1493,7 +1534,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { if(peValidateBtJoinRequest(pMac)!= TRUE) { - limLog(pMac, LOGW, FL("Start Bss session not present::SME_JOIN_REQ in unexpected state\n")); + limLog(pMac, LOGW, FL("Start Bss session not present::SME_JOIN_REQ in unexpected state")); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; psessionEntry = NULL; goto end; @@ -1505,14 +1546,14 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,pSmeJoinReq->bssDescription.bssId,&sessionId)) != NULL) { - limLog(pMac, LOGE, FL("Session Already exists for given BSSID\n")); + limLog(pMac, LOGE, FL("Session Already exists for given BSSID")); if(psessionEntry->limSmeState == eLIM_SME_LINK_EST_STATE) { // Received eWNI_SME_JOIN_REQ for same // BSS as currently associated. // Log the event and send success - PELOGW(limLog(pMac, LOGW, FL("Received SME_JOIN_REQ for currently joined BSS\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received SME_JOIN_REQ for currently joined BSS"));) /// Send Join success response to host retCode = eSIR_SME_SUCCESS; goto end; @@ -1529,7 +1570,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /* Try to Create a new session */ if((psessionEntry = peCreateSession(pMac,pSmeJoinReq->bssDescription.bssId,&sessionId, pMac->lim.maxStation)) == NULL) { - limLog(pMac, LOGE, FL("Session Can not be created \n")); + limLog(pMac, LOGE, FL("Session Can not be created ")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; } @@ -1566,13 +1607,13 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) #ifdef WLAN_FEATURE_11AC psessionEntry->vhtCapability = IS_DOT11_MODE_VHT(psessionEntry->dot11mode); VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, - "***__limProcessSmeJoinReq: vhtCapability=%d****\n",psessionEntry->vhtCapability); + "***__limProcessSmeJoinReq: vhtCapability=%d****",psessionEntry->vhtCapability); if (psessionEntry->vhtCapability ) { psessionEntry->txBFIniFeatureEnabled = pSmeJoinReq->txBFIniFeatureEnabled; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, - "***__limProcessSmeJoinReq: txBFIniFeatureEnabled=%d****\n", + "***__limProcessSmeJoinReq: txBFIniFeatureEnabled=%d****", psessionEntry->txBFIniFeatureEnabled); if( psessionEntry->txBFIniFeatureEnabled ) @@ -1580,7 +1621,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_VHT_SU_BEAMFORMEE_CAP, psessionEntry->txBFIniFeatureEnabled) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_VHT_SU_BEAMFORMEE_CAP at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto end; } @@ -1590,7 +1631,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (cfgSetInt(pMac, WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED, pSmeJoinReq->txBFCsnValue) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not set WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED at CFG\n")); + limLog(pMac, LOGP, FL("could not set WNI_CFG_VHT_CSN_BEAMFORMEE_ANT_SUPPORTED at CFG")); retCode = eSIR_LOGP_EXCEPTION; goto end; } @@ -1608,18 +1649,6 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->htRecommendedTxWidthSet = psessionEntry->htSupportedChannelWidthSet; psessionEntry->htSecondaryChannelOffset = pSmeJoinReq->cbMode; - /* Record if management frames need to be protected */ -#ifdef WLAN_FEATURE_11W - if(eSIR_ED_AES_128_CMAC == pSmeJoinReq->MgmtEncryptionType) - { - psessionEntry->limRmfEnabled = 1; - } - else - { - psessionEntry->limRmfEnabled = 0; - } -#endif - /*Store Persona */ psessionEntry->pePersona = pSmeJoinReq->staPersona; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, @@ -1662,7 +1691,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { /* Throw an error and return and make sure to delete the session.*/ - limLog(pMac, LOGW, FL("received SME_JOIN_REQ with invalid bss type\n")); + limLog(pMac, LOGW, FL("received SME_JOIN_REQ with invalid bss type")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -1682,7 +1711,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) val = sizeof(tLimMlmJoinReq) + psessionEntry->pLimJoinReq->bssDescription.length + 2; if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmJoinReq, val)) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmJoinReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmJoinReq")); return; } (void) palZeroMemory(pMac->hHdd, (void *) pMlmJoinReq, val); @@ -1692,7 +1721,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (wlan_cfgGetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, (tANI_U32 *) &pMlmJoinReq->joinFailureTimeout) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve JoinFailureTimer value\n")); + limLog(pMac, LOGP, FL("could not retrieve JoinFailureTimer value")); /* copy operational rate from psessionEntry*/ palCopyMemory(pMac->hHdd, (void*)&psessionEntry->rateSet, (void*)&pSmeJoinReq->operationalRateSet, @@ -1738,7 +1767,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (pMac->lim.gLimCurrentBssUapsd) { pMac->lim.gUapsdPerAcBitmask = psessionEntry->pLimJoinReq->uapsdPerAcBitmask; - limLog( pMac, LOG1, FL("UAPSD flag for all AC - 0x%2x\n"), pMac->lim.gUapsdPerAcBitmask); + limLog( pMac, LOG1, FL("UAPSD flag for all AC - 0x%2x"), pMac->lim.gUapsdPerAcBitmask); // resetting the dynamic uapsd mask pMac->lim.gUapsdPerAcDeliveryEnableMask = 0; @@ -1751,7 +1780,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(SIR_BAND_5_GHZ == psessionEntry->limRFBand) { if (wlan_cfgGetInt(pMac, WNI_CFG_11H_ENABLED, &val) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_11H_ENABLED ")); psessionEntry->lim11hEnable = val; } else @@ -1764,7 +1793,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->limSmeState = eLIM_SME_WT_JOIN_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); - PELOG1(limLog(pMac, LOG1, FL("SME JoinReq: SSID %d.%c%c%c%c%c%c\n"), + PELOG1(limLog(pMac, LOG1, FL("SME JoinReq: SSID %d.%c%c%c%c%c%c"), psessionEntry->ssId.length, psessionEntry->ssId.ssId[0], psessionEntry->ssId.ssId[1], @@ -1772,7 +1801,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry->ssId.ssId[3], psessionEntry->ssId.ssId[4], psessionEntry->ssId.ssId[5]); - limLog(pMac, LOG1, FL("Channel %d, BSSID %x:%x:%x:%x:%x:%x\n"), + limLog(pMac, LOG1, FL("Channel %d, BSSID %x:%x:%x:%x:%x:%x"), psessionEntry->currentOperChannel, psessionEntry->bssId[0], psessionEntry->bssId[1], @@ -1792,7 +1821,7 @@ __limProcessSmeJoinReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { /* Received eWNI_SME_JOIN_REQ un expected state */ - limLog(pMac, LOGE, FL("received unexpected SME_JOIN_REQ in state %X\n"), pMac->lim.gLimSmeState); + limLog(pMac, LOGE, FL("received unexpected SME_JOIN_REQ in state %X"), pMac->lim.gLimSmeState); limPrintSmeState(pMac, LOGE, pMac->lim.gLimSmeState); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; psessionEntry = NULL; @@ -1878,14 +1907,14 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U16 nSize; - PELOG3(limLog(pMac, LOG3, FL("Received REASSOC_REQ\n"));) + PELOG3(limLog(pMac, LOG3, FL("Received REASSOC_REQ"));) nSize = __limGetSmeJoinReqSizeForAlloc((tANI_U8 *) pMsgBuf); if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pReassocReq, nSize )) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for pReassocReq\n")); + FL("call to palAllocateMemory failed for pReassocReq")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; @@ -1899,7 +1928,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Received invalid eWNI_SME_REASSOC_REQ // Log the event limLog(pMac, LOGW, - FL("received SME_REASSOC_REQ with invalid data\n")); + FL("received SME_REASSOC_REQ with invalid data")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; @@ -1908,7 +1937,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,pReassocReq->bssDescription.bssId,&sessionId))==NULL) { limPrintMacAddr(pMac, pReassocReq->bssDescription.bssId, LOGE); - limLog(pMac, LOGP, FL("Session does not exist for given bssId\n")); + limLog(pMac, LOGP, FL("Session does not exist for given bssId")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -1941,7 +1970,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { limPrintMacAddr(pMac, pReassocReq->bssDescription.bssId, LOGE); limPrintMacAddr(pMac, pMac->ft.ftPEContext.pFTPreAuthReq->preAuthbssId, LOGE); - limLog(pMac, LOGP, FL("Unknown bssId in reassoc state\n")); + limLog(pMac, LOGP, FL("Unknown bssId in reassoc state")); retCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -1953,7 +1982,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /// Should not have received eWNI_SME_REASSOC_REQ // Log the event limLog(pMac, LOGE, - FL("received unexpected SME_REASSOC_REQ in state %X\n"), + FL("received unexpected SME_REASSOC_REQ in state %X"), psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); @@ -2001,7 +2030,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) &cfgLen) != eSIR_SUCCESS) { /// Could not get SSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrive SSID\n")); + limLog(pMac, LOGP, FL("could not retrive SSID")); } #endif//TO SUPPORT BT-AMP @@ -2020,14 +2049,14 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (pMac->lim.gLimCurrentBssUapsd) { pMac->lim.gUapsdPerAcBitmask = psessionEntry->pLimReAssocReq->uapsdPerAcBitmask; - limLog( pMac, LOG1, FL("UAPSD flag for all AC - 0x%2x\n"), pMac->lim.gUapsdPerAcBitmask); + limLog( pMac, LOG1, FL("UAPSD flag for all AC - 0x%2x"), pMac->lim.gUapsdPerAcBitmask); } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmReassocReq, sizeof(tLimMlmReassocReq))) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmReassocReq\n")); + FL("call to palAllocateMemory failed for mlmReassocReq")); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; goto end; @@ -2046,7 +2075,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve ReassocFailureTimeout value\n")); + FL("could not retrieve ReassocFailureTimeout value")); } if (cfgGetCapabilityInfo(pMac, &caps,psessionEntry) != eSIR_SUCCESS) @@ -2056,7 +2085,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } pMlmReassocReq->capabilityInfo = caps; @@ -2067,7 +2096,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) WNI_CFG_TELE_BCN_MAX_LI */ if(wlan_cfgGetInt(pMac, WNI_CFG_TELE_BCN_WAKEUP_EN, &teleBcnEn) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN\n")); + limLog(pMac, LOGP, FL("Couldn't get WNI_CFG_TELE_BCN_WAKEUP_EN")); val = WNI_CFG_LISTEN_INTERVAL_STADEF; @@ -2080,7 +2109,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get ListenInterval value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve ListenInterval\n")); + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); } } else @@ -2091,7 +2120,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Could not get ListenInterval value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve ListenInterval\n")); + limLog(pMac, LOGP, FL("could not retrieve ListenInterval")); } } @@ -2100,7 +2129,7 @@ __limProcessSmeReassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * is lost upon disassociation and reassociation. */ - limDelAllBASessions(pMac); + limDeleteBASessions(pMac, psessionEntry, BA_BOTH_DIRECTIONS); pMlmReassocReq->listenInterval = (tANI_U16) val; @@ -2176,11 +2205,11 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 smesessionId; tANI_U16 smetransactionId; - PELOG1(limLog(pMac, LOG1,FL("received DISASSOC_REQ message\n"));) + PELOG1(limLog(pMac, LOG1,FL("received DISASSOC_REQ message"));) if (pMsgBuf == NULL) { - limLog(pMac, LOGE, FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE, FL("Buffer is Pointing to NULL")); return; } @@ -2192,7 +2221,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (!limIsSmeDisassocReqValid(pMac, &smeDisassocReq, psessionEntry)) ) { PELOGE(limLog(pMac, LOGE, - FL("received invalid SME_DISASSOC_REQ message\n"));) + FL("received invalid SME_DISASSOC_REQ message"));) if (pMac->lim.gLimRspReqd) { @@ -2207,13 +2236,13 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } - PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_REQ message. Reason: %d global SmeState: %d"), + PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_REQ message. Reason: %d global SmeState: %d"), smeDisassocReq.reasonCode, pMac->lim.gLimSmeState);) if((psessionEntry = peFindSessionByBssid(pMac,smeDisassocReq.bssId,&sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); retCode = eSIR_SME_INVALID_PARAMETERS; disassocTrigger = eLIM_HOST_DISASSOC; goto sendDisassoc; @@ -2239,6 +2268,10 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) case eLIM_SME_LINK_EST_STATE: psessionEntry->limPrevSmeState = psessionEntry->limSmeState; psessionEntry->limSmeState= eLIM_SME_WT_DISASSOC_STATE; +#ifdef FEATURE_WLAN_TDLS + /* Delete all TDLS peers connected before leaving BSS*/ + limDeleteTDLSPeers(pMac, psessionEntry); +#endif MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); break; @@ -2250,7 +2283,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) */ psessionEntry->limSmeState= eLIM_SME_WT_DISASSOC_STATE; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); - limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DEAUTH_STATE. \n")); + limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DEAUTH_STATE. ")); break; case eLIM_SME_WT_DISASSOC_STATE: @@ -2263,7 +2296,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * It will send a disassoc, which is ok. However, we can use the global flag * sendDisassoc to not send disassoc frame. */ - limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DISASSOC_STATE. \n")); + limLog(pMac, LOG1, FL("Rcvd SME_DISASSOC_REQ while in SME_WT_DISASSOC_STATE. ")); break; case eLIM_SME_JOIN_FAILURE_STATE: { @@ -2280,7 +2313,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * Log error and send response to host */ limLog(pMac, LOGE, - FL("received unexpected SME_DISASSOC_REQ in state %X\n"), + FL("received unexpected SME_DISASSOC_REQ in state %X"), psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); @@ -2308,7 +2341,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) case eLIM_STA_IN_IBSS_ROLE: default: // eLIM_UNKNOWN_ROLE limLog(pMac, LOGE, - FL("received unexpected SME_DISASSOC_REQ for role %d\n"), + FL("received unexpected SME_DISASSOC_REQ for role %d"), psessionEntry->limSystemRole); retCode = eSIR_SME_UNEXPECTED_REQ_RESULT_CODE; @@ -2337,7 +2370,7 @@ __limProcessSmeDisassocReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmDisassocReq\n")); + FL("call to palAllocateMemory failed for mlmDisassocReq")); return; } @@ -2395,25 +2428,25 @@ __limProcessSmeDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 sessionId; - PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_CNF message\n"));) + PELOG1(limLog(pMac, LOG1, FL("received DISASSOC_CNF message"));) status = limDisassocCnfSerDes(pMac, &smeDisassocCnf,(tANI_U8 *) pMsgBuf); if (status == eSIR_FAILURE) { - PELOGE(limLog(pMac, LOGE, FL("invalid SME_DISASSOC_CNF message\n"));) + PELOGE(limLog(pMac, LOGE, FL("invalid SME_DISASSOC_CNF message"));) return; } if((psessionEntry = peFindSessionByBssid(pMac, smeDisassocCnf.bssId, &sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); return; } if (!limIsSmeDisassocCnfValid(pMac, &smeDisassocCnf, psessionEntry)) { - limLog(pMac, LOGW, FL("received invalid SME_DISASSOC_CNF message\n")); + limLog(pMac, LOGW, FL("received invalid SME_DISASSOC_CNF message")); return; } @@ -2433,7 +2466,7 @@ __limProcessSmeDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (psessionEntry->limSmeState != eLIM_SME_WT_DEAUTH_STATE)) { limLog(pMac, LOGE, - FL("received unexp SME_DISASSOC_CNF in state %X\n"), + FL("received unexp SME_DISASSOC_CNF in state %X"), psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); return; @@ -2447,7 +2480,7 @@ __limProcessSmeDisassocCnf(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) case eLIM_STA_IN_IBSS_ROLE: default: // eLIM_UNKNOWN_ROLE limLog(pMac, LOGE, - FL("received unexpected SME_DISASSOC_CNF role %d\n"), + FL("received unexpected SME_DISASSOC_CNF role %d"), psessionEntry->limSystemRole); return; @@ -2508,7 +2541,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 smesessionId; tANI_U16 smetransactionId; - PELOG1(limLog(pMac, LOG1,FL("received DEAUTH_REQ message\n"));) + PELOG1(limLog(pMac, LOG1,FL("received DEAUTH_REQ message"));) status = limDeauthReqSerDes(pMac, &smeDeauthReq,(tANI_U8 *) pMsgBuf); @@ -2517,7 +2550,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) //We need to get a session first but we don't even know if the message is correct. if((psessionEntry = peFindSessionByBssid(pMac, smeDeauthReq.bssId, &sessionId)) == NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); retCode = eSIR_SME_INVALID_PARAMETERS; deauthTrigger = eLIM_HOST_DEAUTH; goto sendDeauth; @@ -2526,7 +2559,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((status == eSIR_FAILURE) || (!limIsSmeDeauthReqValid(pMac, &smeDeauthReq, psessionEntry))) { - PELOGE(limLog(pMac, LOGW,FL("received invalid SME_DEAUTH_REQ message\n"));) + PELOGE(limLog(pMac, LOGW,FL("received invalid SME_DEAUTH_REQ message"));) if (pMac->lim.gLimRspReqd) { pMac->lim.gLimRspReqd = false; @@ -2574,7 +2607,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * peer. Log error and send response to host. */ limLog(pMac, LOGE, - FL("received unexp SME_DEAUTH_REQ in state %X\n"),psessionEntry->limSmeState); + FL("received unexp SME_DEAUTH_REQ in state %X"),psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); if (pMac->lim.gLimRspReqd) @@ -2602,7 +2635,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) default: limLog(pMac, LOGE, - FL("received unexpected SME_DEAUTH_REQ for role %X\n"),psessionEntry->limSystemRole); + FL("received unexpected SME_DEAUTH_REQ for role %X"),psessionEntry->limSystemRole); return; } // end switch (pMac->lim.gLimSystemRole) @@ -2610,7 +2643,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (smeDeauthReq.reasonCode == eLIM_LINK_MONITORING_DEAUTH) { /// Deauthentication is triggered by Link Monitoring - PELOG1(limLog(pMac, LOG1, FL("**** Lost link with AP ****\n"));) + PELOG1(limLog(pMac, LOG1, FL("**** Lost link with AP ****"));) deauthTrigger = eLIM_LINK_MONITORING_DEAUTH; reasonCode = eSIR_MAC_UNSPEC_FAILURE_REASON; } @@ -2625,7 +2658,7 @@ __limProcessSmeDeauthReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmDeauthReq\n")); + FL("call to palAllocateMemory failed for mlmDeauthReq")); return; } @@ -2685,12 +2718,12 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) PELOG1(limLog(pMac, LOG1, - FL("received SETCONTEXT_REQ message\n"));); + FL("received SETCONTEXT_REQ message"));); if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -2699,20 +2732,20 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSetContextReq, (sizeof(tSirKeys) * SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS))) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSetContextReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSetContextReq")); return; } if ((limSetContextReqSerDes(pMac, pSetContextReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || (!limIsSmeSetContextReqValid(pMac, pSetContextReq))) { - limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message\n")); + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); goto end; } if(pSetContextReq->keyMaterial.numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { - PELOGE(limLog(pMac, LOGE, FL("numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS\n"), pSetContextReq->keyMaterial.numKeys);) + PELOGE(limLog(pMac, LOGE, FL("numKeys:%d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS"), pSetContextReq->keyMaterial.numKeys);) limSendSmeSetContextRsp(pMac, pSetContextReq->peerMacAddr, 1, @@ -2725,7 +2758,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, pSetContextReq->bssId, &sessionId)) == NULL) { - limLog(pMac, LOGW, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); limSendSmeSetContextRsp(pMac, pSetContextReq->peerMacAddr, 1, @@ -2750,7 +2783,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMlmSetKeysReq, sizeof(tLimMlmSetKeysReq))) { // Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmSetKeysReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for mlmSetKeysReq")); goto end; } @@ -2758,7 +2791,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmSetKeysReq->numKeys = pSetContextReq->keyMaterial.numKeys; if(pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { - limLog(pMac, LOGP, FL("Num of keys exceeded max num of default keys limit\n")); + limLog(pMac, LOGP, FL("Num of keys exceeded max num of default keys limit")); goto end; } palCopyMemory( pMac->hHdd, (tANI_U8 *) &pMlmSetKeysReq->peerMacAddr, @@ -2773,7 +2806,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMlmSetKeysReq->sessionId = sessionId; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG PELOG1(limLog(pMac, LOG1, - FL("received SETCONTEXT_REQ message sessionId=%d\n"), pMlmSetKeysReq->sessionId);); + FL("received SETCONTEXT_REQ message sessionId=%d"), pMlmSetKeysReq->sessionId);); #endif if(((pSetContextReq->keyMaterial.edType == eSIR_ED_WEP40) || (pSetContextReq->keyMaterial.edType == eSIR_ED_WEP104)) @@ -2801,7 +2834,7 @@ __limProcessSmeSetContextReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { limLog(pMac, LOGE, - FL("received unexpected SME_SETCONTEXT_REQ for role %d, state=%X\n"), + FL("received unexpected SME_SETCONTEXT_REQ for role %d, state=%X"), psessionEntry->limSystemRole, psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); @@ -2847,11 +2880,11 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U16 smetransactionId; PELOG1(limLog(pMac, LOG1, - FL("received REMOVEKEY_REQ message\n"));) + FL("received REMOVEKEY_REQ message"));) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -2863,7 +2896,7 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { //Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for pRemoveKeyReq\n")); + FL("call to palAllocateMemory failed for pRemoveKeyReq")); return; } @@ -2873,13 +2906,13 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) { limLog(pMac, LOGW, - FL("received invalid SME_REMOVECONTEXT_REQ message\n")); + FL("received invalid SME_REMOVECONTEXT_REQ message")); /* extra look up is needed since, session entry to be passed il limsendremovekey response */ if((psessionEntry = peFindSessionByBssid(pMac,pRemoveKeyReq->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); //goto end; } @@ -2894,7 +2927,7 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,pRemoveKeyReq->bssId, &sessionId))== NULL) { limLog(pMac, LOGE, - FL("session does not exist for given bssId\n")); + FL("session does not exist for given bssId")); limSendSmeRemoveKeyRsp(pMac, pRemoveKeyReq->peerMacAddr, eSIR_SME_UNEXPECTED_REQ_RESULT_CODE, NULL, @@ -2914,7 +2947,7 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for mlmRemoveKeysReq\n")); + FL("call to palAllocateMemory failed for mlmRemoveKeysReq")); goto end; } @@ -2939,7 +2972,7 @@ __limProcessSmeRemoveKeyReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) else { limLog(pMac, LOGE, - FL("received unexpected SME_REMOVEKEY_REQ for role %d, state=%X\n"), + FL("received unexpected SME_REMOVEKEY_REQ for role %d, state=%X"), psessionEntry->limSystemRole, psessionEntry->limSmeState); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); @@ -2962,13 +2995,13 @@ void limProcessSmeGetScanChannelInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMac->lim.scanChnInfo.numChnInfo > SIR_MAX_SUPPORTED_CHANNEL_LIST) { - limLog(pMac, LOGW, FL("numChn is out of bounds %d\n"), + limLog(pMac, LOGW, FL("numChn is out of bounds %d"), pMac->lim.scanChnInfo.numChnInfo); pMac->lim.scanChnInfo.numChnInfo = SIR_MAX_SUPPORTED_CHANNEL_LIST; } PELOG2(limLog(pMac, LOG2, - FL("Sending message %s with number of channels %d\n"), + FL("Sending message %s with number of channels %d"), limMsgStr(eWNI_SME_GET_SCANNED_CHANNEL_RSP), pMac->lim.scanChnInfo.numChnInfo);) len = sizeof(tSmeGetScanChnRsp) + (pMac->lim.scanChnInfo.numChnInfo - 1) * sizeof(tLimScanChn); @@ -2976,7 +3009,7 @@ void limProcessSmeGetScanChannelInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { /// Buffer not available. Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP\n")); + FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP")); return; } @@ -3019,7 +3052,7 @@ void limProcessSmeGetAssocSTAsInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (!limIsSmeGetAssocSTAsReqValid(pMac, &getAssocSTAsReq, (tANI_U8 *) pMsgBuf)) { limLog(pMac, LOGE, - FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message\n")); + FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message")); goto limAssocStaEnd; } @@ -3044,14 +3077,14 @@ void limProcessSmeGetAssocSTAsInfo(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((psessionEntry = peFindSessionByBssid(pMac, getAssocSTAsReq.bssId, &sessionId)) == NULL) { limLog(pMac, LOGE, - FL("session does not exist for given bssId\n")); + FL("session does not exist for given bssId")); goto limAssocStaEnd; } if (psessionEntry->limSystemRole != eLIM_AP_ROLE) { limLog(pMac, LOGE, - FL("Received unexpected message in state %X, in role %X\n"), + FL("Received unexpected message in state %X, in role %X"), psessionEntry->limSmeState , psessionEntry->limSystemRole); goto limAssocStaEnd; } @@ -3137,7 +3170,7 @@ void limProcessSmeGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (limIsSmeGetWPSPBCSessionsReqValid(pMac, &GetWPSPBCSessionsReq, (tANI_U8 *) pMsgBuf) != eSIR_SUCCESS) { limLog(pMac, LOGE, - FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message\n")); + FL("received invalid eWNI_SME_GET_ASSOC_STAS_REQ message")); goto limGetWPSPBCSessionsEnd; } @@ -3146,14 +3179,14 @@ void limProcessSmeGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((psessionEntry = peFindSessionByBssid(pMac, GetWPSPBCSessionsReq.bssId, &sessionId)) == NULL) { limLog(pMac, LOGE, - FL("session does not exist for given bssId\n")); + FL("session does not exist for given bssId")); goto limGetWPSPBCSessionsEnd; } if (psessionEntry->limSystemRole != eLIM_AP_ROLE) { limLog(pMac, LOGE, - FL("Received unexpected message in role %X\n"), + FL("Received unexpected message in role %X"), psessionEntry->limSystemRole); goto limGetWPSPBCSessionsEnd; } @@ -3176,7 +3209,7 @@ void limProcessSmeGetWPSPBCSessions(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) return; } - PELOG4(limLog(pMac, LOGE, FL("wpsPBCOverlap %d\n"), sapEvent.sapevt.sapGetWPSPBCSessionEvent.wpsPBCOverlap);) + PELOG4(limLog(pMac, LOGE, FL("wpsPBCOverlap %d"), sapEvent.sapevt.sapGetWPSPBCSessionEvent.wpsPBCOverlap);) PELOG4(limPrintMacAddr(pMac, sapEvent.sapevt.sapGetWPSPBCSessionEvent.addr.bytes, LOG4);) sapEvent.sapevt.sapGetWPSPBCSessionEvent.status = VOS_STATUS_SUCCESS; @@ -3229,13 +3262,13 @@ limProcessTkipCounterMeasures(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ( limTkipCntrMeasReqSerDes( pMac, &tkipCntrMeasReq, (tANI_U8 *) pMsgBuf ) != eSIR_SUCCESS ) { limLog(pMac, LOGE, - FL("received invalid eWNI_SME_TKIP_CNTR_MEAS_REQ message\n")); + FL("received invalid eWNI_SME_TKIP_CNTR_MEAS_REQ message")); return; } if ( NULL == (psessionEntry = peFindSessionByBssid( pMac, tkipCntrMeasReq.bssId, &sessionId )) ) { - limLog(pMac, LOGE, FL("session does not exist for given BSSID \n")); + limLog(pMac, LOGE, FL("session does not exist for given BSSID ")); return; } @@ -3266,7 +3299,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((limStopBssReqSerDes(pMac, &stopBssReq, (tANI_U8 *) pMsgBuf) != eSIR_SUCCESS) || !limIsSmeStopBssReqValid(pMsgBuf)) { - PELOGW(limLog(pMac, LOGW, FL("received invalid SME_STOP_BSS_REQ message\n"));) + PELOGW(limLog(pMac, LOGW, FL("received invalid SME_STOP_BSS_REQ message"));) /// Send Stop BSS response to host limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_INVALID_PARAMETERS,smesessionId,smetransactionId); return; @@ -3275,7 +3308,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,stopBssReq.bssId,&sessionId)) == NULL) { - limLog(pMac, LOGW, FL("session does not exist for given BSSID \n")); + limLog(pMac, LOGW, FL("session does not exist for given BSSID ")); limSendSmeRsp(pMac, eWNI_SME_STOP_BSS_RSP, eSIR_SME_INVALID_PARAMETERS,smesessionId,smetransactionId); return; } @@ -3294,7 +3327,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * mode. Log error and return response to host. */ limLog(pMac, LOGE, - FL("received unexpected SME_STOP_BSS_REQ in state %X, for role %d\n"), + FL("received unexpected SME_STOP_BSS_REQ in state %X, for role %d"), psessionEntry->limSmeState, psessionEntry->limSystemRole); limPrintSmeState(pMac, LOGE, psessionEntry->limSmeState); /// Send Stop BSS response to host @@ -3306,7 +3339,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) { limWPSPBCClose(pMac, psessionEntry); } - PELOGW(limLog(pMac, LOGW, FL("RECEIVED STOP_BSS_REQ with reason code=%d\n"), stopBssReq.reasonCode);) + PELOGW(limLog(pMac, LOGW, FL("RECEIVED STOP_BSS_REQ with reason code=%d"), stopBssReq.reasonCode);) prevState = psessionEntry->limSmeState; @@ -3336,7 +3369,7 @@ __limHandleSmeStopBssRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (status != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("delBss failed for bss %d\n"), psessionEntry->bssIdx);) + PELOGE(limLog(pMac, LOGE, FL("delBss failed for bss %d"), psessionEntry->bssIdx);) psessionEntry->limSmeState= prevState; MTRACE(macTrace(pMac, TRACE_CODE_SME_STATE, psessionEntry->peSessionId, psessionEntry->limSmeState)); @@ -3413,27 +3446,27 @@ __limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsg if(pMsgBuf == NULL) { - limLog(pMac, LOGE, FL("pMsgBuf is NULL \n")); + limLog(pMac, LOGE, FL("pMsgBuf is NULL ")); goto end; } if ((limAssocCnfSerDes(pMac, &assocCnf, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE) || !__limIsSmeAssocCnfValid(&assocCnf)) { - limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message \n")); + limLog(pMac, LOGE, FL("Received invalid SME_RE(ASSOC)_CNF message ")); goto end; } if((psessionEntry = peFindSessionByBssid(pMac, assocCnf.bssId, &sessionId))== NULL) { - limLog(pMac, LOGE, FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE, FL("session does not exist for given bssId")); goto end; } if ( ((psessionEntry->limSystemRole != eLIM_AP_ROLE) && (psessionEntry->limSystemRole != eLIM_BT_AMP_AP_ROLE)) || ((psessionEntry->limSmeState != eLIM_SME_NORMAL_STATE) && (psessionEntry->limSmeState != eLIM_SME_NORMAL_CHANNEL_SCAN_STATE))) { - limLog(pMac, LOGE, FL("Received unexpected message %X in state %X, in role %X\n"), + limLog(pMac, LOGE, FL("Received unexpected message %X in state %X, in role %X"), msgType, psessionEntry->limSmeState , psessionEntry->limSystemRole); goto end; } @@ -3476,7 +3509,7 @@ __limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsg ** Deactivate/delet CNF_WAIT timer since ASSOC_CNF ** has been received **/ - limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer\n")); + limLog(pMac, LOG1, FL("Received SME_ASSOC_CNF. Delete Timer")); limDeactivateAndChangePerStaIdTimer(pMac, eLIM_CNF_WAIT_TIMER, pStaDs->assocId); if (assocCnf.statusCode == eSIR_SME_SUCCESS) @@ -3486,7 +3519,7 @@ __limProcessSmeAssocCnfNew(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsg * Association Response frame to the requesting BTAMP-STA. */ pStaDs->mlmStaContext.mlmState = eLIM_MLM_LINK_ESTABLISHED_STATE; - limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) \n"), pStaDs->assocId); + limLog(pMac, LOG1, FL("sending Assoc Rsp frame to STA (assoc id=%d) "), pStaDs->assocId); limSendAssocRspMgmtFrame( pMac, eSIR_SUCCESS, pStaDs->assocId, pStaDs->staAddr, pStaDs->mlmStaContext.subType, pStaDs, psessionEntry); goto end; @@ -3541,7 +3574,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -3551,7 +3584,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, pSirAddts->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE, "Session Does not exist for given bssId\n"); + limLog(pMac, LOGE, "Session Does not exist for given bssId"); return; } #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT @@ -3567,13 +3600,13 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) * if ap, just ignore with error log */ PELOG1(limLog(pMac, LOG1, - FL("Received SME_ADDTS_REQ (TSid %d, UP %d)\n"), + FL("Received SME_ADDTS_REQ (TSid %d, UP %d)"), pSirAddts->req.tspec.tsinfo.traffic.tsid, pSirAddts->req.tspec.tsinfo.traffic.userPrio);) if ((psessionEntry->limSystemRole != eLIM_STA_ROLE)&&(psessionEntry->limSystemRole != eLIM_BT_AMP_STA_ROLE)) { - PELOGE(limLog(pMac, LOGE, "AddTs received on AP - ignoring\n");) + PELOGE(limLog(pMac, LOGE, "AddTs received on AP - ignoring");) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3582,7 +3615,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) //Ignore the request if STA is in 11B mode. if(psessionEntry->dot11mode == WNI_CFG_DOT11_MODE_11B) { - PELOGE(limLog(pMac, LOGE, "AddTS received while Dot11Mode is 11B - ignoring\n");) + PELOGE(limLog(pMac, LOGE, "AddTS received while Dot11Mode is 11B - ignoring");) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3593,7 +3626,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pStaDs == NULL) { - PELOGE(limLog(pMac, LOGE, "Cannot find AP context for addts req\n");) + PELOGE(limLog(pMac, LOGE, "Cannot find AP context for addts req");) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3602,7 +3635,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((! pStaDs->valid) || (pStaDs->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)) { - PELOGE(limLog(pMac, LOGE, "AddTs received in invalid MLM state\n");) + PELOGE(limLog(pMac, LOGE, "AddTs received in invalid MLM state");) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3621,7 +3654,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pSirAddts->req.lleTspecPresent = 1; else { - PELOGW(limLog(pMac, LOGW, FL("ADDTS_REQ ignore - qos is disabled\n"));) + PELOGW(limLog(pMac, LOGW, FL("ADDTS_REQ ignore - qos is disabled"));) limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); return; @@ -3630,7 +3663,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((psessionEntry->limSmeState != eLIM_SME_ASSOCIATED_STATE) && (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) { - limLog(pMac, LOGE, "AddTs received in invalid LIMsme state (%d)\n", + limLog(pMac, LOGE, "AddTs received in invalid LIMsme state (%d)", psessionEntry->limSmeState); limSendSmeAddtsRsp(pMac, pSirAddts->rspReqd, eSIR_FAILURE, psessionEntry, pSirAddts->req.tspec, smesessionId,smetransactionId); @@ -3639,7 +3672,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (pMac->lim.gLimAddtsSent) { - limLog(pMac, LOGE, "Addts (token %d, tsid %d, up %d) is still pending\n", + limLog(pMac, LOGE, "Addts (token %d, tsid %d, up %d) is still pending", pMac->lim.gLimAddtsReq.req.dialogToken, pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.tsid, pMac->lim.gLimAddtsReq.req.tspec.tsinfo.traffic.userPrio); @@ -3653,7 +3686,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, peerMac, &val) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); return; } #endif @@ -3666,14 +3699,14 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) // ship out the message now limSendAddtsReqActionFrame(pMac, peerMac, &pSirAddts->req, psessionEntry); - PELOG1(limLog(pMac, LOG1, "Sent ADDTS request\n");) + PELOG1(limLog(pMac, LOG1, "Sent ADDTS request");) // start a timer to wait for the response if (pSirAddts->timeout) timeout = pSirAddts->timeout; else if (wlan_cfgGetInt(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &timeout) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Unable to get Cfg param %d (Addts Rsp Timeout)\n"), + limLog(pMac, LOGP, FL("Unable to get Cfg param %d (Addts Rsp Timeout)"), WNI_CFG_ADDTS_RSP_TIMEOUT); return; } @@ -3681,14 +3714,14 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) timeout = SYS_MS_TO_TICKS(timeout); if (tx_timer_change(&pMac->lim.limTimers.gLimAddtsRspTimer, timeout, 0) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("AddtsRsp timer change failed!\n")); + limLog(pMac, LOGP, FL("AddtsRsp timer change failed!")); return; } pMac->lim.gLimAddtsRspTimerCount++; if (tx_timer_change_context(&pMac->lim.limTimers.gLimAddtsRspTimer, pMac->lim.gLimAddtsRspTimerCount) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("AddtsRsp timer change failed!\n")); + limLog(pMac, LOGP, FL("AddtsRsp timer change failed!")); return; } MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, psessionEntry->peSessionId, eLIM_ADDTS_RSP_TIMER)); @@ -3697,7 +3730,7 @@ __limProcessSmeAddtsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) pMac->lim.limTimers.gLimAddtsRspTimer.sessionId = sessionId; if (tx_timer_activate(&pMac->lim.limTimers.gLimAddtsRspTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("AddtsRsp timer activation failed!\n")); + limLog(pMac, LOGP, FL("AddtsRsp timer activation failed!")); return; } return; @@ -3722,7 +3755,7 @@ __limProcessSmeDeltsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, pDeltsReq->bssId, &sessionId))== NULL) { - limLog(pMac, LOGE, "Session Does not exist for given bssId\n"); + limLog(pMac, LOGE, "Session Does not exist for given bssId"); status = eSIR_FAILURE; goto end; } @@ -3733,13 +3766,13 @@ __limProcessSmeDeltsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (eSIR_SUCCESS != limValidateDeltsReq(pMac, pDeltsReq, peerMacAddr,psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed"));) status = eSIR_FAILURE; limSendSmeDeltsRsp(pMac, pDeltsReq, eSIR_FAILURE,psessionEntry,smesessionId,smetransactionId); return; } - PELOG1(limLog(pMac, LOG1, FL("Sent DELTS request to station with assocId = %d MacAddr = %x:%x:%x:%x:%x:%x\n"), + PELOG1(limLog(pMac, LOG1, FL("Sent DELTS request to station with assocId = %d MacAddr = %x:%x:%x:%x:%x:%x"), pDeltsReq->aid, peerMacAddr[0], peerMacAddr[1], peerMacAddr[2], peerMacAddr[3], peerMacAddr[4], peerMacAddr[5]);) @@ -3789,7 +3822,7 @@ __limProcessSmeDeltsReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) } else { - limLog(pMac, LOGE, FL("Self entry missing in Hash Table \n")); + limLog(pMac, LOGE, FL("Self entry missing in Hash Table ")); status = eSIR_FAILURE; } #ifdef FEATURE_WLAN_CCX @@ -3809,26 +3842,26 @@ limProcessSmeAddtsRspTimeout(tpAniSirGlobal pMac, tANI_U32 param) tpPESession psessionEntry; if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimAddtsRspTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } if ( (psessionEntry->limSystemRole != eLIM_STA_ROLE) && (psessionEntry->limSystemRole != eLIM_BT_AMP_STA_ROLE) ) { - limLog(pMac, LOGW, "AddtsRspTimeout in non-Sta role (%d)\n", psessionEntry->limSystemRole); + limLog(pMac, LOGW, "AddtsRspTimeout in non-Sta role (%d)", psessionEntry->limSystemRole); pMac->lim.gLimAddtsSent = false; return; } if (! pMac->lim.gLimAddtsSent) { - PELOGW(limLog(pMac, LOGW, "AddtsRspTimeout but no AddtsSent\n");) + PELOGW(limLog(pMac, LOGW, "AddtsRspTimeout but no AddtsSent");) return; } if (param != pMac->lim.gLimAddtsRspTimerCount) { - limLog(pMac, LOGE, FL("Invalid AddtsRsp Timer count %d (exp %d)\n"), + limLog(pMac, LOGE, FL("Invalid AddtsRsp Timer count %d (exp %d)"), param, pMac->lim.gLimAddtsRspTimerCount); return; } @@ -3865,7 +3898,7 @@ __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -3873,7 +3906,7 @@ __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac,pStatsReq->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE, FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE, FL("session does not exist for given bssId")); palFreeMemory( pMac, pMsgBuf ); return; } @@ -3898,7 +3931,7 @@ __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) msgQ.type = WDA_STAT_SUMM_REQ; break; default: //Unknown request. - PELOGE(limLog(pMac, LOGE, "Unknown Statistics request\n");) + PELOGE(limLog(pMac, LOGE, "Unknown Statistics request");) palFreeMemory( pMac, pMsgBuf ); return; } @@ -3925,7 +3958,7 @@ __limProcessSmeStatsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); } if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ - limLog(pMac, LOGP, "Unable to forward request\n"); + limLog(pMac, LOGP, "Unable to forward request"); palFreeMemory( pMac, pMsgBuf ); return; } @@ -3975,7 +4008,7 @@ __limProcessSmeGetStatisticsRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ palFreeMemory( pMac, pMsgBuf ); - limLog(pMac, LOGP, "Unable to forward request\n"); + limLog(pMac, LOGP, "Unable to forward request"); return; } @@ -4022,7 +4055,7 @@ __limProcessSmeGetRoamRssiRequest(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if( eSIR_SUCCESS != (wdaPostCtrlMsg( pMac, &msgQ ))){ palFreeMemory( pMac, pMsgBuf ); - limLog(pMac, LOGP, "Unable to forward request\n"); + limLog(pMac, LOGP, "Unable to forward request"); return; } @@ -4039,29 +4072,29 @@ __limProcessSmeUpdateAPWPSIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 sessionId; //PE sessionID PELOG1(limLog(pMac, LOG1, - FL("received UPDATE_APWPSIEs_REQ message\n"));); + FL("received UPDATE_APWPSIEs_REQ message"));); if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } if( palAllocateMemory( pMac->hHdd, (void **)&pUpdateAPWPSIEsReq, sizeof(tSirUpdateAPWPSIEsReq))) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pUpdateAPWPSIEsReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pUpdateAPWPSIEsReq")); return; } if ((limUpdateAPWPSIEsReqSerDes(pMac, pUpdateAPWPSIEsReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) { - limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message\n")); + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); goto end; } if((psessionEntry = peFindSessionByBssid(pMac, pUpdateAPWPSIEsReq->bssId, &sessionId)) == NULL) { - limLog(pMac, LOGW, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); goto end; } @@ -4082,11 +4115,11 @@ __limProcessSmeHideSSID(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tpPESession psessionEntry; PELOG1(limLog(pMac, LOG1, - FL("received HIDE_SSID message\n"));); + FL("received HIDE_SSID message"));); if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -4094,7 +4127,7 @@ __limProcessSmeHideSSID(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionBySessionId(pMac, pUpdateParams->sessionId)) == NULL) { - limLog(pMac, LOGW, "Session does not exist for given sessionId %d\n", + limLog(pMac, LOGW, "Session does not exist for given sessionId %d", pUpdateParams->sessionId); return; } @@ -4118,25 +4151,25 @@ __limProcessSmeSetWPARSNIEs(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } if( palAllocateMemory( pMac->hHdd, (void **)&pUpdateAPWPARSNIEsReq, sizeof(tSirUpdateAPWPSIEsReq))) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pUpdateAPWPARSNIEsReq\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pUpdateAPWPARSNIEsReq")); return; } if ((limUpdateAPWPARSNIEsReqSerDes(pMac, pUpdateAPWPARSNIEsReq, (tANI_U8 *) pMsgBuf) == eSIR_FAILURE)) { - limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message\n")); + limLog(pMac, LOGW, FL("received invalid SME_SETCONTEXT_REQ message")); goto end; } if((psessionEntry = peFindSessionByBssid(pMac, pUpdateAPWPARSNIEsReq->bssId, &sessionId)) == NULL) { - limLog(pMac, LOGW, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGW, FL("Session does not exist for given BSSID")); goto end; } @@ -4167,11 +4200,11 @@ __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tUpdateBeaconParams beaconParams; PELOG1(limLog(pMac, LOG1, - FL("received Update Beacon Interval message\n"));); + FL("received Update Beacon Interval message"));); if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -4179,7 +4212,7 @@ __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, pChangeBIParams->bssId, &sessionId)) == NULL) { - limLog(pMac, LOGE, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); return; } @@ -4202,9 +4235,10 @@ __limProcessSmeChangeBI(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /* Update beacon */ schSetFixedBeaconFields(pMac, psessionEntry); + beaconParams.bssIdx = psessionEntry->bssIdx; //Set change in beacon Interval beaconParams.beaconInterval = pChangeBIParams->beaconInterval; - beaconParams.paramChangeBitmap |= PARAM_BCN_INTERVAL_CHANGED; + beaconParams.paramChangeBitmap = PARAM_BCN_INTERVAL_CHANGED; limSendBeaconParams(pMac, &beaconParams, psessionEntry); } @@ -4236,10 +4270,10 @@ limProcessSmeDelBaPeerInd(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if ((psessionEntry = peFindSessionByBssid(pMac,pSmeDelBAPeerInd->bssId,&sessionId))==NULL) { - limLog(pMac, LOGE,FL("session does not exist for given bssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given bssId")); return; } - limLog(pMac, LOGW, FL("called with staId = %d, tid = %d, baDirection = %d\n"), + limLog(pMac, LOGW, FL("called with staId = %d, tid = %d, baDirection = %d"), pSmeDelBAPeerInd->staIdx, pSmeDelBAPeerInd->baTID, pSmeDelBAPeerInd->baDirection); pSta = dphLookupAssocId(pMac, pSmeDelBAPeerInd->staIdx, &assocId, &psessionEntry->dph.dphHashTable); @@ -4289,13 +4323,13 @@ void __limProcessReportMessage(tpAniSirGlobal pMac, tpSirMsgQ pMsg) if(pMsg->bodyptr == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } pBcnReport = (tpSirBeaconReportXmitInd )pMsg->bodyptr; if((psessionEntry = peFindSessionByBssid(pMac, pBcnReport->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE, "Session Does not exist for given bssId\n"); + limLog(pMac, LOGE, "Session Does not exist for given bssId"); return; } if (psessionEntry->isCCXconnection) @@ -4335,43 +4369,35 @@ limSendSetMaxTxPowerReq ( tpAniSirGlobal pMac, tPowerdBm txPower, tpPESession pS if( pSessionEntry == NULL ) { - PELOGE(limLog(pMac, LOGE, "%s:%d: Inavalid parameters\n", __func__, __LINE__ );) + PELOGE(limLog(pMac, LOGE, "%s:%d: Inavalid parameters", __func__, __LINE__ );) return eSIR_FAILURE; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pMaxTxParams, sizeof(tMaxTxPowerParams) ) ) { - limLog( pMac, LOGP, "%s:%d:Unable to allocate memory for pMaxTxParams \n", __func__, __LINE__); + limLog( pMac, LOGP, "%s:%d:Unable to allocate memory for pMaxTxParams ", __func__, __LINE__); return eSIR_MEM_ALLOC_FAILED; } #if defined(WLAN_VOWIFI_DEBUG) || defined(FEATURE_WLAN_CCX) - PELOG1(limLog( pMac, LOG1, "%s:%d: Allocated memory for pMaxTxParams...will be freed in other module\n", __func__, __LINE__ );) + PELOG1(limLog( pMac, LOG1, "%s:%d: Allocated memory for pMaxTxParams...will be freed in other module", __func__, __LINE__ );) #endif - if( pMaxTxParams == NULL ) - { - limLog( pMac, LOGE, "%s:%d: pMaxTxParams is NULL\n", __func__, __LINE__); - return eSIR_FAILURE; - } pMaxTxParams->power = txPower; palCopyMemory( pMac->hHdd, pMaxTxParams->bssId, pSessionEntry->bssId, sizeof(tSirMacAddr) ); palCopyMemory( pMac->hHdd, pMaxTxParams->selfStaMacAddr, pSessionEntry->selfMacAddr, sizeof(tSirMacAddr) ); - msgQ.type = WDA_SET_MAX_TX_POWER_REQ; - msgQ.bodyptr = pMaxTxParams; - msgQ.bodyval = 0; - PELOGW(limLog(pMac, LOG1, FL("Posting WDA_SET_MAX_TX_POWER_REQ to WDA\n"));) - MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, msgQ.type)); - if(eSIR_SUCCESS != (retCode = wdaPostCtrlMsg(pMac, &msgQ))) - { - PELOGW(limLog(pMac, LOGW, FL("wdaPostCtrlMsg() failed\n"));) - if (NULL != pMaxTxParams) - { - palFreeMemory(pMac->hHdd, (tANI_U8*)pMaxTxParams); - } - return retCode; - } - return retCode; + msgQ.type = WDA_SET_MAX_TX_POWER_REQ; + msgQ.bodyptr = pMaxTxParams; + msgQ.bodyval = 0; + PELOG1(limLog(pMac, LOG1, FL("Posting WDA_SET_MAX_TX_POWER_REQ to WDA"));) + MTRACE(macTraceMsgTx(pMac, pSessionEntry->peSessionId, msgQ.type)); + retCode = wdaPostCtrlMsg(pMac, &msgQ); + if (eSIR_SUCCESS != retCode) + { + PELOGE(limLog(pMac, LOGE, FL("wdaPostCtrlMsg() failed"));) + palFreeMemory(pMac->hHdd, pMaxTxParams); + } + return retCode; } #endif @@ -4409,17 +4435,18 @@ __limProcessSmeAddStaSelfReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) palCopyMemory( pMac->hHdd, pAddStaSelfParams->selfMacAddr, pSmeReq->selfMacAddr, sizeof(tSirMacAddr) ); + pAddStaSelfParams->currDeviceMode = pSmeReq->currDeviceMode; msg.type = SIR_HAL_ADD_STA_SELF_REQ; msg.reserved = 0; msg.bodyptr = pAddStaSelfParams; msg.bodyval = 0; - PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL\n"));) + PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL"));) MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { - limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed\n")); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); } return; } /*** end __limProcessAddStaSelfReq() ***/ @@ -4464,12 +4491,12 @@ __limProcessSmeDelStaSelfReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) msg.bodyptr = pDelStaSelfParams; msg.bodyval = 0; - PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL\n"));) + PELOGW(limLog(pMac, LOG1, FL("sending SIR_HAL_ADD_STA_SELF_REQ msg to HAL"));) MTRACE(macTraceMsgTx(pMac, NO_SESSION, msg.type)); if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { - limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed\n")); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg failed")); } return; } /*** end __limProcessSmeDelStaSelfReq() ***/ @@ -4500,7 +4527,7 @@ __limProcessSmeRegisterMgmtFrameReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tpLimMgmtFrameRegistration pLimMgmtRegistration = NULL, pNext = NULL; tANI_BOOLEAN match = VOS_FALSE; PELOG1(limLog(pMac, LOG1, - FL("registerFrame %d, frameType %d, matchLen %d\n"), + FL("registerFrame %d, frameType %d, matchLen %d"), pSmeReq->registerFrame, pSmeReq->frameType, pSmeReq->matchLen);) /* First check whether entry exists already*/ @@ -4583,7 +4610,7 @@ __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) pMac->hHdd, (void **) &pMsgNoA, sizeof( tP2pPsConfig ))) { limLog( pMac, LOGP, - FL( "Unable to allocate memory during NoA Update\n" )); + FL( "Unable to allocate memory during NoA Update" )); goto error; } @@ -4609,11 +4636,11 @@ __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) { /// Could not activate Insert NOA timer. // Log error - limLog(pMac, LOGP, FL("could not activate Insert Single Shot NOA during scan timer\n")); + limLog(pMac, LOGP, FL("could not activate Insert Single Shot NOA during scan timer")); // send the scan response back with status failure and do not even call insert NOA limSendSmeScanRsp(pMac, sizeof(tSirSmeScanRsp), eSIR_SME_SCAN_FAILED, pMac->lim.gSmeSessionId, pMac->lim.gTransactionId); - palFreeMemory( pMac->hHdd, (void **) &pMsgNoA); + palFreeMemory( pMac->hHdd, pMsgNoA); goto error; } @@ -4627,7 +4654,7 @@ __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { /* In this failure case, timer is already started, so its expiration will take care of sending scan response */ - limLog(pMac, LOGP, FL("wdaPost Msg failed\n")); + limLog(pMac, LOGP, FL("wdaPost Msg failed")); /* Deactivate the NOA timer in failure case */ limDeactivateAndChangeTimer(pMac, eLIM_INSERT_SINGLESHOT_NOA_TIMER); goto error; @@ -4646,14 +4673,14 @@ __limInsertSingleShotNOAForScan(tpAniSirGlobal pMac, tANI_U32 noaDuration) static void __limRegisterDeferredSmeReqForNOAStart(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 *pMsgBuf) { - limLog(pMac, LOG1, FL("Reg msgType %d\n"), msgType) ; + limLog(pMac, LOG1, FL("Reg msgType %d"), msgType) ; pMac->lim.gDeferMsgTypeForNOA = msgType; pMac->lim.gpDefdSmeMsgForNOA = pMsgBuf; } static void __limDeregisterDeferredSmeReqAfterNOAStart(tpAniSirGlobal pMac) { - limLog(pMac, LOG1, FL("Dereg msgType %d\n"), pMac->lim.gDeferMsgTypeForNOA) ; + limLog(pMac, LOG1, FL("Dereg msgType %d"), pMac->lim.gDeferMsgTypeForNOA) ; pMac->lim.gDeferMsgTypeForNOA = 0; if (pMac->lim.gpDefdSmeMsgForNOA != NULL) { @@ -4681,7 +4708,7 @@ tANI_U32 limCalculateNOADuration(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 * Could not get max channel value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve passive max channel value\n")); + limLog(pMac, LOGP, FL("could not retrieve passive max channel value")); /* use a default value of 110ms */ val = DEFAULT_PASSIVE_MAX_CHANNEL_TIME; @@ -4728,7 +4755,7 @@ tANI_U32 limCalculateNOADuration(tpAniSirGlobal pMac, tANI_U16 msgType, tANI_U32 break; } - limLog(pMac, LOGW, FL("msgType %d noa %d\n"), msgType, noaDuration); + limLog(pMac, LOGW, FL("msgType %d noa %d"), msgType, noaDuration); return noaDuration; } @@ -4736,7 +4763,7 @@ void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac) { tANI_BOOLEAN bufConsumed = TRUE; - limLog(pMac, LOG1, FL("Process defd sme req %d\n"), pMac->lim.gDeferMsgTypeForNOA); + limLog(pMac, LOG1, FL("Process defd sme req %d"), pMac->lim.gDeferMsgTypeForNOA); if ( (pMac->lim.gDeferMsgTypeForNOA != 0) && (pMac->lim.gpDefdSmeMsgForNOA != NULL) ) { @@ -4762,7 +4789,7 @@ void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac) __limProcessSmeJoinReq(pMac, pMac->lim.gpDefdSmeMsgForNOA); break; default: - limLog(pMac, LOGE, FL("Unknown deferred msg type %d\n"), pMac->lim.gDeferMsgTypeForNOA); + limLog(pMac, LOGE, FL("Unknown deferred msg type %d"), pMac->lim.gDeferMsgTypeForNOA); break; } __limDeregisterDeferredSmeReqAfterNOAStart(pMac); @@ -4770,7 +4797,7 @@ void limProcessRegdDefdSmeReqAfterNOAStart(tpAniSirGlobal pMac) else { limLog( pMac, LOGW, FL("start received from FW when no sme deferred msg pending. Do nothing." - "It might happen sometime when NOA start ind and timeout happen at the same time\n")); + "It might happen sometime when NOA start ind and timeout happen at the same time")); } } @@ -4787,13 +4814,13 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, tANI_U8 sessionId; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Discovery Req Recieved\n")) ; + ("Discovery Req Recieved")) ; if((psessionEntry = peFindSessionByBssid(pMac, disReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", disReq->sessionId); goto lim_tdls_dis_start_error; } @@ -4802,7 +4829,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "dis req received in wrong system Role %d\n", + "dis req received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_dis_start_error; } @@ -4816,7 +4843,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, { limLog(pMac, LOGE, "dis req received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_dis_start_error; } @@ -4839,7 +4866,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, (tANI_U8 *) disReq, sizeof(tSirTdlsDisReq)); VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - "Transmit Discovery Request Frame\n") ; + "Transmit Discovery Request Frame") ; /* format TDLS discovery request frame and transmit it */ limSendTdlsDisReqFrame(pMac, disReq->peerMac, disReq->dialog, psessionEntry) ; @@ -4854,7 +4881,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, */ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Start Discovery request Timeout Timer\n")) ; + ("Start Discovery request Timeout Timer")) ; MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_TDLS_DISCOVERY_RSP_WAIT)); @@ -4866,7 +4893,7 @@ static tSirRetStatus limProcessSmeDisStartReq(tpAniSirGlobal pMac, != TX_SUCCESS) { limLog(pMac, LOGP, FL("TDLS discovery response timer \ - activation failed!\n")); + activation failed!")); goto lim_tdls_dis_start_error; } /* @@ -4897,7 +4924,7 @@ eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) setupReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", setupReq->sessionId); goto lim_tdls_link_start_error; } @@ -4906,7 +4933,7 @@ eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "TDLS link setup req received in wrong system Role %d\n", + "TDLS link setup req received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_link_start_error; } @@ -4919,7 +4946,7 @@ eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) { limLog(pMac, LOGE, "Setup request in invalid LIMsme \ - state (%d)\n", pMac->lim.gLimSmeState); + state (%d)", pMac->lim.gLimSmeState); goto lim_tdls_link_start_error; } @@ -4948,7 +4975,7 @@ eHalStatus limProcessSmeLinkStartReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer ))) { limLog( pMac, LOGP, - FL( "Unable to allocate memory during ADD_STA\n" )); + FL( "Unable to allocate memory during ADD_STA" )); VOS_ASSERT(0) ; return eSIR_MEM_ALLOC_FAILED; } @@ -5001,7 +5028,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if((psessionEntry = peFindSessionByBssid(pMac, teardownReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", teardownReq->sessionId); + "PE Session does not exist for given sme sessionId %d", teardownReq->sessionId); goto lim_tdls_teardown_req_error; } @@ -5009,7 +5036,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "TDLS teardown req received in wrong system Role %d\n", psessionEntry->limSystemRole); + "TDLS teardown req received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_teardown_req_error; } @@ -5021,12 +5048,12 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) (psessionEntry->limSmeState != eLIM_SME_LINK_EST_STATE)) { limLog(pMac, LOGE, "TDLS teardwon req received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_teardown_req_error; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - "Teardown for peer = %02x,%02x,%02x,%02x,%02x,%02x\n", + "Teardown for peer = %02x,%02x,%02x,%02x,%02x,%02x", teardownReq->peerMac[0], teardownReq->peerMac[1], teardownReq->peerMac[2], @@ -5043,7 +5070,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) if(NULL == setupPeer) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("invalid Peer on teardown \n")) ; + ("invalid Peer on teardown ")) ; goto lim_tdls_teardown_req_error; } @@ -5053,7 +5080,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) /* TDLS_sessionize: check sessionId in case */ if((setupPeer)->tdls_sessionId != psessionEntry->peSessionId) { - limLog(pMac, LOGE, "TDLS teardown req; stored sessionId (%d) not matched from peSessionId (%d)\n", \ + limLog(pMac, LOGE, "TDLS teardown req; stored sessionId (%d) not matched from peSessionId (%d)", \ (setupPeer)->tdls_sessionId, psessionEntry->limSmeState); (setupPeer)->tdls_sessionId = psessionEntry->peSessionId; } @@ -5063,7 +5090,7 @@ eHalStatus limProcessSmeTeardownReq(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON, psessionEntry, NULL, 0 )) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("couldn't send teardown frame \n")) ; + ("couldn't send teardown frame ")) ; goto lim_tdls_teardown_req_error; } /* in case of success, eWNI_SME_TDLS_TEARDOWN_RSP is sent back to SME later when @@ -5087,7 +5114,7 @@ __limProcessSmeResetApCapsChange(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) tANI_U8 sessionId = 0; if (pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -5095,7 +5122,7 @@ __limProcessSmeResetApCapsChange(tpAniSirGlobal pMac, tANI_U32 *pMsgBuf) psessionEntry = peFindSessionByBssid(pMac, pResetCapsChange->bssId, &sessionId); if (psessionEntry == NULL) { - limLog(pMac, LOGE, FL("Session does not exist for given BSSID\n")); + limLog(pMac, LOGE, FL("Session does not exist for given BSSID")); return; } @@ -5129,12 +5156,13 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) { tANI_BOOLEAN bufConsumed = TRUE; //Set this flag to false within case block of any following message, that doesnt want pMsgBuf to be freed. tANI_U32 *pMsgBuf = pMsg->bodyptr; - - PELOG1(limLog(pMac, LOG1, FL("LIM Received SME Message %s(%d) Global LimSmeState:%s(%d) Global LimMlmState: %s(%d)\n"), + tpSirSmeScanReq pScanReq; + PELOG1(limLog(pMac, LOG1, FL("LIM Received SME Message %s(%d) Global LimSmeState:%s(%d) Global LimMlmState: %s(%d)"), limMsgStr(pMsg->type), pMsg->type, limSmeStateStr(pMac->lim.gLimSmeState), pMac->lim.gLimSmeState, limMlmStateStr(pMac->lim.gLimMlmState), pMac->lim.gLimMlmState );) + pScanReq = (tpSirSmeScanReq) pMsgBuf; /* Special handling of some SME Req msgs where we have an existing GO session and * want to insert NOA before processing those msgs. These msgs will be processed later when * start event happens @@ -5142,8 +5170,42 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) switch (pMsg->type) { case eWNI_SME_SCAN_REQ: - case eWNI_SME_OEM_DATA_REQ: case eWNI_SME_REMAIN_ON_CHANNEL_REQ: + + /* If scan is disabled return from here + */ + if (pMac->lim.fScanDisabled) + { + PELOGE(limLog(pMac, LOGE, FL("Error: Scan Disabled"));) + if (pMsg->type == eWNI_SME_SCAN_REQ) + { + limSendSmeScanRsp(pMac, + offsetof(tSirSmeScanRsp,bssDescription[0]), + eSIR_SME_INVALID_PARAMETERS, + pScanReq->sessionId, + pScanReq->transactionId); + + bufConsumed = TRUE; + } + else if (pMsg->type == eWNI_SME_REMAIN_ON_CHANNEL_REQ) + { + pMac->lim.gpDefdSmeMsgForNOA = NULL; + pMac->lim.gpLimRemainOnChanReq = (tpSirRemainOnChnReq )pMsgBuf; + limRemainOnChnRsp(pMac,eHAL_STATUS_FAILURE, NULL); + + /* + * limRemainOnChnRsp will free the buffer this change is to + * avoid "double free" + */ + bufConsumed = FALSE; + } + + return bufConsumed; + } + /* + * Do not add BREAK here + */ + case eWNI_SME_OEM_DATA_REQ: case eWNI_SME_JOIN_REQ: /* If we have an existing P2P GO session we need to insert NOA before actually process this SME Req */ if ((limIsNOAInsertReqd(pMac) == TRUE) && IS_FEATURE_SUPPORTED_BY_FW(P2P_GO_NOA_DECOUPLE_INIT_SCAN)) @@ -5244,24 +5306,24 @@ limProcessSmeReqMessages(tpAniSirGlobal pMac, tpSirMsgQ pMsg) case eWNI_SME_ASSOC_CNF: case eWNI_SME_REASSOC_CNF: if (pMsg->type == eWNI_SME_ASSOC_CNF) - PELOG1(limLog(pMac, LOG1, FL("Received ASSOC_CNF message\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received ASSOC_CNF message"));) else - PELOG1(limLog(pMac, LOG1, FL("Received REASSOC_CNF message\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received REASSOC_CNF message"));) __limProcessSmeAssocCnfNew(pMac, pMsg->type, pMsgBuf); break; case eWNI_SME_ADDTS_REQ: - PELOG1(limLog(pMac, LOG1, FL("Received ADDTS_REQ message\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received ADDTS_REQ message"));) __limProcessSmeAddtsReq(pMac, pMsgBuf); break; case eWNI_SME_DELTS_REQ: - PELOG1(limLog(pMac, LOG1, FL("Received DELTS_REQ message\n"));) + PELOG1(limLog(pMac, LOG1, FL("Received DELTS_REQ message"));) __limProcessSmeDeltsReq(pMac, pMsgBuf); break; case SIR_LIM_ADDTS_RSP_TIMEOUT: - PELOG1(limLog(pMac, LOG1, FL("Received SIR_LIM_ADDTS_RSP_TIMEOUT message \n"));) + PELOG1(limLog(pMac, LOG1, FL("Received SIR_LIM_ADDTS_RSP_TIMEOUT message "));) limProcessSmeAddtsRspTimeout(pMac, pMsg->bodyval); break; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessTdls.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessTdls.c index 4936b289bb2..ba906e233b0 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessTdls.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limProcessTdls.c @@ -49,10 +49,12 @@ Are listed for each API below. +Copyright (c) 2013 Qualcomm Atheros, Inc.All Rights Reserved. +Qualcomm Atheros Confidential and Proprietary. + +Copyright (c) 2010 Qualcomm Technologies, Inc.All Rights Reserved. +Qualcomm Technologies Confidential and Proprietary - Copyright (c) 2010 QUALCOMM Incorporated. - All Rights Reserved. - Qualcomm Confidential and Proprietary ===========================================================================*/ /*=========================================================================== @@ -239,6 +241,14 @@ typedef enum tdlsLinkSetupStatus #define WNI_CFG_TDLS_LINK_SETUP_CNF_TIMEOUT (200) #endif +#define IS_QOS_ENABLED(psessionEntry) ((((psessionEntry)->limQosEnabled) && \ + SIR_MAC_GET_QOS((psessionEntry)->limCurrentBssCaps)) || \ + (((psessionEntry)->limWmeEnabled ) && \ + LIM_BSS_CAPS_GET(WME, (psessionEntry)->limCurrentBssQosCaps))) + +#define TID_AC_VI 4 +#define TID_AC_BK 1 + const tANI_U8* limTraceTdlsActionString( tANI_U8 tdlsActionCode ) { switch( tdlsActionCode ) @@ -268,7 +278,7 @@ static void printMacAddr(tSirMacAddr macAddr) VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, (" %02x "), macAddr[i]); } - VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("\n")); + VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("")); return ; } #endif @@ -311,7 +321,7 @@ void limTdlsSetNegativeBehavior(tpAniSirGlobal pMac, tANI_U8 value, tANI_BOOLEAN else pMac->lim.gLimTdlsNegativeBehavior &= ~(1 << (value-1)); } - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("%d %d -> gLimTdlsNegativeBehavior= 0x%lx\n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("%d %d -> gLimTdlsNegativeBehavior= 0x%lx"), \ value, on, pMac->lim.gLimTdlsNegativeBehavior)); } #endif @@ -359,7 +369,7 @@ static void limPreparesActionFrameHdr(tpAniSirGlobal pMac, tANI_U8 *pFrame, palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->bssId, bssid, sizeof( tSirMacAddr )); - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS action frame\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS action frame\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x"), \ pMacHdr->da[0], pMacHdr->da[1], pMacHdr->da[2], pMacHdr->da[3], pMacHdr->da[4], pMacHdr->da[5], \ pMacHdr->sa[0], pMacHdr->sa[1], pMacHdr->sa[2], pMacHdr->sa[3], pMacHdr->sa[4], pMacHdr->sa[5], \ pMacHdr->bssId[0], pMacHdr->bssId[1], pMacHdr->bssId[2], \ @@ -375,9 +385,10 @@ static void limPreparesActionFrameHdr(tpAniSirGlobal pMac, tANI_U8 *pFrame, * | | | | */ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, - tDot11fIELinkIdentifier *link_iden, tANI_U8 tdlsLinkType, tANI_U8 reqType, tpPESession psessionEntry ) + tDot11fIELinkIdentifier *link_iden, tANI_U8 tdlsLinkType, tANI_U8 reqType, + tANI_U8 tid, tpPESession psessionEntry) { - tpSirMacMgmtHdr pMacHdr ; + tpSirMacDataHdr3a pMacHdr ; tANI_U32 header_offset = 0 ; tANI_U8 *addr1 = NULL ; tANI_U8 *addr3 = NULL ; @@ -388,7 +399,7 @@ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, tANI_U8 *staMac = (reqType == TDLS_INITIATOR) ? link_iden->InitStaAddr : link_iden->RespStaAddr; - pMacHdr = (tpSirMacMgmtHdr) (pFrame); + pMacHdr = (tpSirMacDataHdr3a) (pFrame); /* * if TDLS frame goes through the AP link, it follows normal address @@ -404,7 +415,8 @@ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, */ pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; pMacHdr->fc.type = SIR_MAC_DATA_FRAME ; - pMacHdr->fc.subType = SIR_MAC_DATA_DATA ; + pMacHdr->fc.subType = IS_QOS_ENABLED(psessionEntry) ? SIR_MAC_DATA_QOS_DATA : SIR_MAC_DATA_DATA; + /* * TL is not setting up below fields, so we are doing it here */ @@ -413,28 +425,34 @@ static tANI_U32 limPrepareTdlsFrameHeader(tpAniSirGlobal pMac, tANI_U8* pFrame, pMacHdr->fc.wep = (psessionEntry->encryptType == eSIR_ED_NONE)? 0 : 1; - palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->da, (tANI_U8 *)addr1, + palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->addr1, (tANI_U8 *)addr1, sizeof( tSirMacAddr )); palCopyMemory( pMac->hHdd, - (tANI_U8 *) pMacHdr->sa, + (tANI_U8 *) pMacHdr->addr2, (tANI_U8 *) staMac, sizeof( tSirMacAddr )); - palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->bssId, + palCopyMemory( pMac->hHdd, (tANI_U8 *) pMacHdr->addr3, (tANI_U8 *) (addr3), sizeof( tSirMacAddr )); - - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS frame header to %s\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x\n"), \ + + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, ("Preparing TDLS frame header to %s\n%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x/%02x:%02x:%02x:%02x:%02x:%02x"), \ (tdlsLinkType == TDLS_LINK_AP) ? "AP" : "TD", \ - pMacHdr->da[0], pMacHdr->da[1], pMacHdr->da[2], pMacHdr->da[3], pMacHdr->da[4], pMacHdr->da[5], \ - pMacHdr->sa[0], pMacHdr->sa[1], pMacHdr->sa[2], pMacHdr->sa[3], pMacHdr->sa[4], pMacHdr->sa[5], \ - pMacHdr->bssId[0], pMacHdr->bssId[1], pMacHdr->bssId[2], \ - pMacHdr->bssId[3], pMacHdr->bssId[4], pMacHdr->bssId[5])); + pMacHdr->addr1[0], pMacHdr->addr1[1], pMacHdr->addr1[2], pMacHdr->addr1[3], pMacHdr->addr1[4], pMacHdr->addr1[5], \ + pMacHdr->addr2[0], pMacHdr->addr2[1], pMacHdr->addr2[2], pMacHdr->addr2[3], pMacHdr->addr2[4], pMacHdr->addr2[5], \ + pMacHdr->addr3[0], pMacHdr->addr3[1], pMacHdr->addr3[2], pMacHdr->addr3[3], pMacHdr->addr3[4], pMacHdr->addr3[5])); //printMacAddr(pMacHdr->bssId) ; //printMacAddr(pMacHdr->sa) ; //printMacAddr(pMacHdr->da) ; - - header_offset += sizeof(tSirMacMgmtHdr) ; + + if (IS_QOS_ENABLED(psessionEntry)) + { + pMacHdr->qosControl.tid = tid; + header_offset += sizeof(tSirMacDataHdr3a); + } + else + header_offset += sizeof(tSirMacMgmtHdr); + /* * Now form RFC1042 header */ @@ -520,7 +538,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fTDLSDisReq ); } @@ -528,7 +546,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } /* @@ -538,9 +556,10 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE ; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE ; #ifndef NO_PAD_TDLS_MIN_8023_SIZE /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) @@ -567,7 +586,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -582,7 +601,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, /* fill out the buffer descriptor */ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, - LINK_IDEN_ADDR_OFFSET(tdlsDisReq), TDLS_LINK_AP, TDLS_INITIATOR, psessionEntry) ; + LINK_IDEN_ADDR_OFFSET(tdlsDisReq), TDLS_LINK_AP, TDLS_INITIATOR, TID_AC_VI, psessionEntry) ; #ifdef FEATURE_WLAN_TDLS_NEGATIVE if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_DSCV_REQ) @@ -590,7 +609,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, tdlsDisReq.LinkIdentifier.bssid[4] = 0xde; tdlsDisReq.LinkIdentifier.bssid[5] = 0xad; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Req\n"), \ + ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Req"), \ tdlsDisReq.LinkIdentifier.bssid[0], tdlsDisReq.LinkIdentifier.bssid[1], tdlsDisReq.LinkIdentifier.bssid[2], @@ -605,7 +624,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -613,7 +632,7 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } #ifndef NO_PAD_TDLS_MIN_8023_SIZE @@ -643,14 +662,14 @@ tSirRetStatus limSendTdlsDisReqFrame(tpAniSirGlobal pMac, tSirMacAddr peer_mac, halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - 7, + TID_AC_VI, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -677,7 +696,7 @@ eHalStatus limTdlsDisRspTxComplete(tpAniSirGlobal pMac, if(NULL == peerInfo) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("DisRspTxComplete: No TDLS state machine waits for this event\n")); + ("DisRspTxComplete: No TDLS state machine waits for this event")); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -694,7 +713,7 @@ eHalStatus limTdlsDisRspTxComplete(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("DisRspTxComplete: sessionID %d is not found\n"), peerInfo->sessionId); + ("DisRspTxComplete: sessionID %d is not found"), peerInfo->sessionId); return eHAL_STATUS_FAILURE; } /* send del STA to remove context for this TDLS STA */ @@ -709,7 +728,7 @@ eHalStatus limTdlsDisRspTxComplete(tpAniSirGlobal pMac, else { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("DisRspTxComplete: staDs not found for %02x:%02x:%02x:%02x:%02x:%02x\n"), + ("DisRspTxComplete: staDs not found for %02x:%02x:%02x:%02x:%02x:%02x"), (peerInfo)->peerMac[0], (peerInfo)->peerMac[1], (peerInfo)->peerMac[2], @@ -760,7 +779,7 @@ eHalStatus limTdlsSetupCnfTxComplete(tpAniSirGlobal pMac, if(NULL == peerInfo) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsSetupCnfTxComplete: No TDLS state machine waits for this event\n")); + ("limTdlsSetupCnfTxComplete: No TDLS state machine waits for this event")); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -779,7 +798,7 @@ eHalStatus limTdlsSetupCnfTxComplete(tpAniSirGlobal pMac, else { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("RSP-->SME peer MAC = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("RSP-->SME peer MAC = %02x,%02x,%02x,%02x,%02x,%02x"), (peerInfo)->peerMac[0], (peerInfo)->peerMac[1], (peerInfo)->peerMac[2], @@ -823,13 +842,13 @@ eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac, if(NULL == peerInfo) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsTeardownTxComplete: No TDLS state machine waits for this event\n")); + ("limTdlsTeardownTxComplete: No TDLS state machine waits for this event")); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("teardown peer Mac = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("teardown peer Mac = %02x,%02x,%02x,%02x,%02x,%02x"), (peerInfo)->peerMac[0] , (peerInfo)->peerMac[1] , (peerInfo)->peerMac[2] , @@ -845,7 +864,7 @@ eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsTeardownTxComplete: sessionID %d is not found\n"), (peerInfo)->tdls_sessionId); + ("limTdlsTeardownTxComplete: sessionID %d is not found"), (peerInfo)->tdls_sessionId); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -853,7 +872,7 @@ eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac, if(!txCompleteSuccess) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TX complete failure for Teardown \n")) ; + ("TX complete failure for Teardown ")) ; /* * we should be sending Teradown to AP with status code @@ -891,9 +910,9 @@ eHalStatus limTdlsTeardownTxComplete(tpAniSirGlobal pMac, pStaDs, eSIR_SUCCESS) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("TX complete SUCCESS for Teardown\n")) ; + ("TX complete SUCCESS for Teardown")) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Prev State = %d\n"), (peerInfo)->tdls_prev_link_state) ; + ("Prev State = %d"), (peerInfo)->tdls_prev_link_state) ; limSendSmeTdlsTeardownRsp(pMac, eSIR_SUCCESS, (peerInfo)->peerMac, eWNI_SME_TDLS_TEARDOWN_RSP) ; /* Delete Peer for Link Peer List */ @@ -937,6 +956,12 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, tANI_U8 *pFrame; void *pPacket; eHalStatus halstatus; + uint32 selfDot11Mode; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; /* * The scheme here is to fill out a 'tDot11fProbeRequest' structure @@ -963,7 +988,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } swapBitField16(caps, ( tANI_U16* )&tdlsDisRsp.Capabilities ); @@ -978,9 +1003,57 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, /* Populate extended supported rates */ PopulateDot11fTdlsExtCapability( pMac, &tdlsDisRsp.ExtCap ); - /* Include HT Capability IE */ - //This does not depend on peer capabilities. If it is supported then it should be included - PopulateDot11fHTCaps( pMac, psessionEntry, &tdlsDisRsp.HTCaps ); + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + + if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) + { + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsDisRsp.HTCaps ); + tdlsDisRsp.HTCaps.present = 1; + /* hardcode NO channel bonding in 2.4Ghz */ + tdlsDisRsp.HTCaps.supportedChannelWidthSet = 0; + } + else + { + tdlsDisRsp.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + /* in 2.4Ghz, hardcode NO 11ac */ + tdlsDisRsp.VHTCaps.present = 0; +#endif + } + else + { + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsDisRsp.HTCaps ); + + tdlsDisRsp.HTCaps.present = 1; + //Placeholder to support different channel bonding mode of TDLS than AP. + //wlan_cfgGetInt(pMac,WNI_CFG_TDLS_CHANNEL_BONDING_MODE,&tdlsChannelBondingMode); + //tdlsDisRsp.HTCaps.supportedChannelWidthSet = tdlsChannelBondingMode ? 1 : 0; + tdlsDisRsp.HTCaps.supportedChannelWidthSet = 1; // hardcode it to max + } + else + { + tdlsDisRsp.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + if (IS_DOT11_MODE_VHT(selfDot11Mode) && + IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + /* Include VHT Capability IE */ + PopulateDot11fVHTCaps( pMac, &tdlsDisRsp.VHTCaps ); + } + else + { + tdlsDisRsp.VHTCaps.present = 0; + } +#endif + } /* * now we pack it. First, how much space are we going to need? @@ -989,7 +1062,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -997,7 +1070,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } /* @@ -1017,7 +1090,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1053,7 +1126,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, tdlsDisRsp.LinkIdentifier.bssid[4] = 0xde; tdlsDisRsp.LinkIdentifier.bssid[5] = 0xad; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Rsp\n"), \ + ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Discovery Rsp"), \ tdlsDisRsp.LinkIdentifier.bssid[0], tdlsDisRsp.LinkIdentifier.bssid[1], tdlsDisRsp.LinkIdentifier.bssid[2], @@ -1069,7 +1142,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1077,7 +1150,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } #if 0 @@ -1094,7 +1167,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, } #endif VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("transmitting Discovery response on direct link\n")) ; + ("transmitting Discovery response on direct link")) ; LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, TDLS_DEBUG_LOG_LEVEL, ("[TDLS] action %d (%s) -DIRECT-> OTA"), SIR_MAC_TDLS_DIS_RSP, limTraceTdlsActionString(SIR_MAC_TDLS_DIS_RSP) )); @@ -1114,7 +1187,7 @@ static tSirRetStatus limSendTdlsDisRspFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1140,6 +1213,12 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, tANI_U8 *pFrame; void *pPacket; eHalStatus halstatus; + uint32 selfDot11Mode; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; /* * The scheme here is to fill out a 'tDot11fProbeRequest' structure @@ -1163,7 +1242,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } swapBitField16(caps, ( tANI_U16* )&tdlsSetupReq.Capabilities ); @@ -1202,37 +1281,67 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, * of peer caps */ - /* Include HT Capability IE */ - PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupReq.HTCaps ); + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) { - tdlsSetupReq.HTCaps.present = 1; - tdlsSetupReq.HTCaps.supportedChannelWidthSet = 0; - } - else - { - if (tdlsSetupReq.HTCaps.present) + if (IS_DOT11_MODE_HT(selfDot11Mode)) { - tdlsSetupReq.HTCaps.supportedChannelWidthSet = 1; // pVhtCaps->supportedChannelWidthSet; + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupReq.HTCaps ); + + tdlsSetupReq.HTCaps.present = 1; + /* hardcode NO channel bonding in 2.4Ghz */ + tdlsSetupReq.HTCaps.supportedChannelWidthSet = 0; } - } - /* Include VHT Capability IE */ - PopulateDot11fVHTCaps( pMac, &tdlsSetupReq.VHTCaps ); - if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) - { + else + { + tdlsSetupReq.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + /* in 2.4Ghz, hardcode NO 11ac */ tdlsSetupReq.VHTCaps.present = 0; - tdlsSetupReq.VHTCaps.supportedChannelWidthSet = 0; - tdlsSetupReq.VHTCaps.ldpcCodingCap = 0; - tdlsSetupReq.VHTCaps.suBeamFormerCap = 0; +#endif } else { - if (tdlsSetupReq.VHTCaps.present) + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupReq.HTCaps ); + + tdlsSetupReq.HTCaps.present = 1; + //Placeholder to support different channel bonding mode of TDLS than AP. + //wlan_cfgGetInt(pMac,WNI_CFG_TDLS_CHANNEL_BONDING_MODE,&tdlsChannelBondingMode); + //tdlsSetupReq.HTCaps.supportedChannelWidthSet = tdlsChannelBondingMode ? 1 : 0; + tdlsSetupReq.HTCaps.supportedChannelWidthSet = 1; // hardcode it to max + } + else + { + tdlsSetupReq.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + if (IS_DOT11_MODE_VHT(selfDot11Mode) && + IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + tANI_U16 aid; + tpDphHashNode pStaDs; + + pStaDs = dphLookupHashEntry(pMac, peerMac, &aid , &psessionEntry->dph.dphHashTable); + if (NULL != pStaDs) + { + tdlsSetupReq.AID.present = 1; + tdlsSetupReq.AID.assocId = aid | LIM_AID_MASK; // set bit 14 and 15 1's + } + + /* Include VHT Capability IE */ + PopulateDot11fVHTCaps( pMac, &tdlsSetupReq.VHTCaps ); + } + else { - tdlsSetupReq.VHTCaps.supportedChannelWidthSet = 1; // pVhtCaps->supportedChannelWidthSet; - tdlsSetupReq.VHTCaps.ldpcCodingCap = 1; // pVhtCaps->ldpcCodingCap - tdlsSetupReq.VHTCaps.suBeamFormerCap = 1; // pVhtCaps->suBeamFormerCap + tdlsSetupReq.VHTCaps.present = 0; } +#endif } /* * now we pack it. First, how much space are we going to need? @@ -1242,7 +1351,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -1250,7 +1359,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } @@ -1261,10 +1370,11 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE - + addIeLen; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; /* Ok-- try to allocate memory from MGMT PKT pool */ @@ -1274,7 +1384,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1289,7 +1399,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, /* fill out the buffer descriptor */ header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, - LINK_IDEN_ADDR_OFFSET(tdlsSetupReq), TDLS_LINK_AP, TDLS_INITIATOR, psessionEntry) ; + LINK_IDEN_ADDR_OFFSET(tdlsSetupReq), TDLS_LINK_AP, TDLS_INITIATOR, TID_AC_BK, psessionEntry) ; #ifdef FEATURE_WLAN_TDLS_NEGATIVE if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_REQ) @@ -1297,7 +1407,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, tdlsSetupReq.LinkIdentifier.bssid[4] = 0xde; tdlsSetupReq.LinkIdentifier.bssid[5] = 0xad; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Req\n"), \ + ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Req"), \ tdlsSetupReq.LinkIdentifier.bssid[0], tdlsSetupReq.LinkIdentifier.bssid[1], tdlsSetupReq.LinkIdentifier.bssid[2], @@ -1316,7 +1426,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1324,7 +1434,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } //Copy the additional IE. @@ -1333,7 +1443,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, //if there is any IOT issue. if( addIeLen != 0 ) { - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"), + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"), addIeLen )); palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen ); } @@ -1344,7 +1454,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - 7,//SMAC_SWBD_TX_TID_MGMT_HIGH, + TID_AC_BK, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME ); @@ -1352,7 +1462,7 @@ tSirRetStatus limSendTdlsLinkSetupReqFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1401,7 +1511,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -1409,7 +1519,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } @@ -1420,10 +1530,11 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE - + addIeLen; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; #ifndef NO_PAD_TDLS_MIN_8023_SIZE /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) @@ -1450,7 +1561,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1469,7 +1580,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, (reason == eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE) ? TDLS_LINK_AP : TDLS_LINK_DIRECT, (responder == TRUE) ? TDLS_RESPONDER : TDLS_INITIATOR, - psessionEntry) ; + TID_AC_VI, psessionEntry) ; status = dot11fPackTDLSTeardown( pMac, &teardown, pFrame + header_offset, nPayload, &nPayload ); @@ -1477,7 +1588,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS Teardown req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1485,7 +1596,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Teardown Request (0x%08x).\n") ); + "Teardown Request (0x%08x).") ); } #if 0 if(pMac->hal.pCBackFnTxComp == NULL) @@ -1507,7 +1618,7 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, if( addIeLen != 0 ) { - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"), + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("Copy Additional Ie Len = %d"), addIeLen )); palCopyMemory( pMac->hHdd, pFrame + header_offset + nPayload, addIe, addIeLen ); } @@ -1539,14 +1650,14 @@ tSirRetStatus limSendTdlsTeardownFrame(tpAniSirGlobal pMac, halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - 7, + TID_AC_VI, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } @@ -1571,6 +1682,12 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, tANI_U8 *pFrame; void *pPacket; eHalStatus halstatus; + uint32 selfDot11Mode; +// Placeholder to support different channel bonding mode of TDLS than AP. +// Today, WNI_CFG_CHANNEL_BONDING_MODE will be overwritten when connecting to AP +// To support this feature, we need to introduce WNI_CFG_TDLS_CHANNEL_BONDING_MODE +// As of now, we hardcoded to max channel bonding of dot11Mode (i.e HT80 for 11ac/HT40 for 11n) +// uint32 tdlsChannelBondingMode; /* * The scheme here is to fill out a 'tDot11fProbeRequest' structure @@ -1597,7 +1714,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } swapBitField16(caps, ( tANI_U16* )&tdlsSetupRsp.Capabilities ); @@ -1629,37 +1746,69 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, tdlsSetupRsp.QOSCapsStation.acvi_uapsd = 1; tdlsSetupRsp.QOSCapsStation.acvo_uapsd = 1; - PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupRsp.HTCaps ); + wlan_cfgGetInt(pMac,WNI_CFG_DOT11_MODE,&selfDot11Mode); + if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) { - tdlsSetupRsp.HTCaps.present = 1; - tdlsSetupRsp.HTCaps.supportedChannelWidthSet = 0; - } - else - { - if (tdlsSetupRsp.HTCaps.present) + if (IS_DOT11_MODE_HT(selfDot11Mode)) { - tdlsSetupRsp.HTCaps.supportedChannelWidthSet = 1; // pVhtCaps->supportedChannelWidthSet; + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupRsp.HTCaps ); + + tdlsSetupRsp.HTCaps.present = 1; + /* hardcode NO channel bonding in 2.4Ghz */ + tdlsSetupRsp.HTCaps.supportedChannelWidthSet = 0; } - } - /* Include VHT Capability IE */ - PopulateDot11fVHTCaps( pMac, &tdlsSetupRsp.VHTCaps ); - if (psessionEntry->currentOperChannel <= SIR_11B_CHANNEL_END) - { + else + { + tdlsSetupRsp.HTCaps.present = 0; + } +#ifdef WLAN_FEATURE_11AC + /* in 2.4Ghz, hardcode NO 11ac */ tdlsSetupRsp.VHTCaps.present = 0; - tdlsSetupRsp.VHTCaps.supportedChannelWidthSet = 0; - tdlsSetupRsp.VHTCaps.ldpcCodingCap = 0; - tdlsSetupRsp.VHTCaps.suBeamFormerCap = 0; +#endif } else { - if (tdlsSetupRsp.VHTCaps.present) + if (IS_DOT11_MODE_HT(selfDot11Mode)) + { + /* Include HT Capability IE */ + PopulateDot11fHTCaps( pMac, NULL, &tdlsSetupRsp.HTCaps ); + + tdlsSetupRsp.HTCaps.present = 1; + //Placeholder to support different channel bonding mode of TDLS than AP. + //wlan_cfgGetInt(pMac,WNI_CFG_TDLS_CHANNEL_BONDING_MODE,&tdlsChannelBondingMode); + //tdlsSetupRsp.HTCaps.supportedChannelWidthSet = tdlsChannelBondingMode ? 1 : 0; + tdlsSetupRsp.HTCaps.supportedChannelWidthSet = 1; // hardcode it to max + } + else { - tdlsSetupRsp.VHTCaps.supportedChannelWidthSet = 1; // pVhtCaps->supportedChannelWidthSet; - tdlsSetupRsp.VHTCaps.ldpcCodingCap = 1; // pVhtCaps->ldpcCodingCap - tdlsSetupRsp.VHTCaps.suBeamFormerCap = 1; // pVhtCaps->suBeamFormerCap + tdlsSetupRsp.HTCaps.present = 0; } +#ifdef WLAN_FEATURE_11AC + if (IS_DOT11_MODE_VHT(selfDot11Mode) && + IS_FEATURE_SUPPORTED_BY_FW(DOT11AC)) + { + tANI_U16 aid; + tpDphHashNode pStaDs; + + pStaDs = dphLookupHashEntry(pMac, peerMac, &aid , &psessionEntry->dph.dphHashTable); + if (NULL != pStaDs) + { + tdlsSetupRsp.AID.present = 1; + tdlsSetupRsp.AID.assocId = aid | LIM_AID_MASK; // set bit 14 and 15 1's + } + + /* Include VHT Capability IE */ + PopulateDot11fVHTCaps( pMac, &tdlsSetupRsp.VHTCaps ); + } + else + { + tdlsSetupRsp.VHTCaps.present = 0; + } +#endif } + tdlsSetupRsp.Status.status = setupStatus ; /* @@ -1670,7 +1819,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -1678,7 +1827,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } /* @@ -1688,10 +1837,11 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE - + addIeLen; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; /* Ok-- try to allocate memory from MGMT PKT pool */ @@ -1701,7 +1851,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1718,7 +1868,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, LINK_IDEN_ADDR_OFFSET(tdlsSetupRsp), TDLS_LINK_AP, TDLS_RESPONDER, - psessionEntry) ; + TID_AC_BK, psessionEntry) ; #ifdef FEATURE_WLAN_TDLS_NEGATIVE if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_WRONG_BSSID_IN_SETUP_RSP) @@ -1726,7 +1876,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, tdlsSetupRsp.LinkIdentifier.bssid[4] = 0xde; tdlsSetupRsp.LinkIdentifier.bssid[5] = 0xad; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Rsp\n"), \ + ("TDLS negative running: wrong BSSID %02x:%02x:%02x:%02x:%02x:%02x in TDLS Setup Rsp"), \ tdlsSetupRsp.LinkIdentifier.bssid[0], tdlsSetupRsp.LinkIdentifier.bssid[1], tdlsSetupRsp.LinkIdentifier.bssid[2], @@ -1744,7 +1894,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1752,7 +1902,7 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } //Copy the additional IE. @@ -1771,14 +1921,14 @@ static tSirRetStatus limSendTdlsSetupRspFrame(tpAniSirGlobal pMac, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, //ANI_TXDIR_IBSS, - 7, + TID_AC_BK, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } pMac->lim.mgmtFrameSessionId = psessionEntry->peSessionId; @@ -1855,7 +2005,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a discovery Request (0x%08x).\n"), status ); + "or a discovery Request (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tDot11fProbeRequest ); } @@ -1863,7 +2013,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a discovery Request (" - "0x%08x).\n"), status ); + "0x%08x)."), status ); } /* @@ -1873,10 +2023,11 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer */ - nBytes = nPayload + sizeof( tSirMacMgmtHdr ) - + sizeof( eth_890d_header ) - + PAYLOAD_TYPE_TDLS_SIZE - + addIeLen; + nBytes = nPayload + ((IS_QOS_ENABLED(psessionEntry)) + ? sizeof(tSirMacDataHdr3a) : sizeof(tSirMacMgmtHdr)) + + sizeof( eth_890d_header ) + + PAYLOAD_TYPE_TDLS_SIZE + + addIeLen; #ifndef NO_PAD_TDLS_MIN_8023_SIZE /* IOT issue with some AP : some AP doesn't like the data packet size < minimum 802.3 frame length (64) @@ -1904,7 +2055,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TDLS" - "Discovery Request.\n"), nBytes ); + "Discovery Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -1920,13 +2071,13 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer header_offset = limPrepareTdlsFrameHeader(pMac, pFrame, LINK_IDEN_ADDR_OFFSET(tdlsSetupCnf), TDLS_LINK_AP, TDLS_INITIATOR, - psessionEntry) ; + TID_AC_VI, psessionEntry) ; #ifdef FEATURE_WLAN_TDLS_NEGATIVE if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_STATUS_37_IN_SETUP_CNF) { tdlsSetupCnf.StatusCode.statusCode = 37; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: StatusCode = 37 in TDLS Setup Cnf\n")); + ("TDLS negative running: StatusCode = 37 in TDLS Setup Cnf")); } #endif status = dot11fPackTDLSSetupCnf( pMac, &tdlsSetupCnf, pFrame @@ -1935,7 +2086,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a TDLS discovery req \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; @@ -1943,7 +2094,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Discovery Request (0x%08x).\n") ); + "Discovery Request (0x%08x).") ); } #if 0 if(pMac->hal.pCBackFnTxComp == NULL) @@ -1999,7 +2150,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer halstatus = halTxFrameWithTxComplete( pMac, pPacket, ( tANI_U16 ) nBytes, HAL_TXRX_FRM_802_11_DATA, ANI_TXDIR_TODS, - 7, + TID_AC_VI, limTxComplete, pFrame, limMgmtTXComplete, HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME ); @@ -2008,7 +2159,7 @@ tSirRetStatus limSendTdlsLinkSetupCnfFrame(tpAniSirGlobal pMac, tSirMacAddr peer if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { pMac->lim.mgmtFrameSessionId = 0xff; - limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send TDLS Dis Request frame!" )); return eSIR_FAILURE; } @@ -2108,7 +2259,7 @@ void limTdlsUpdateLinkReqPeerInfo(tpAniSirGlobal pMac, { ConvertQOSCapsStation(pMac->hHdd, &setupPeer->qosCaps, &setupReq->QOSCapsStation) ; - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("setupReq->SPLen=%d (be %d %d %d %d vo) more %d qack %d.\n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR,("setupReq->SPLen=%d (be %d %d %d %d vo) more %d qack %d."), \ setupReq->QOSCapsStation.max_sp_length, setupReq->QOSCapsStation.acbe_uapsd, \ setupReq->QOSCapsStation.acbk_uapsd, setupReq->QOSCapsStation.acvi_uapsd, \ setupReq->QOSCapsStation.acvo_uapsd, setupReq->QOSCapsStation.more_data_ack, \ @@ -2159,7 +2310,7 @@ void limTdlsUpdateLinkRspPeerInfo(tpAniSirGlobal pMac, { ConvertQOSCapsStation(pMac->hHdd, &setupPeer->qosCaps, &setupRsp->QOSCapsStation) ; - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("setupRsp->SPLen=%d (be %d %d %d %d vo) more %d qack %d.\n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("setupRsp->SPLen=%d (be %d %d %d %d vo) more %d qack %d."), \ setupRsp->QOSCapsStation.max_sp_length, setupRsp->QOSCapsStation.acbe_uapsd, \ setupRsp->QOSCapsStation.acbk_uapsd, setupRsp->QOSCapsStation.acvi_uapsd, \ setupRsp->QOSCapsStation.acvo_uapsd, setupRsp->QOSCapsStation.more_data_ack, \ @@ -2300,7 +2451,7 @@ static tSirRetStatus limTdlsPopulateDot11fHTCaps(tpAniSirGlobal pMac, tpPESessio pDot11f->rxAS = pASCapabilityInfo->rxAS; pDot11f->txSoundingPPDUs = pASCapabilityInfo->txSoundingPPDUs; - pDot11f->present = 1; + pDot11f->present = pTdlsAddStaReq->htcap_present; return eSIR_SUCCESS; @@ -2322,7 +2473,7 @@ limTdlsPopulateDot11fVHTCaps(tpAniSirGlobal pMac, tSirMacVHTRxSupDataRateInfo vhtRxsupDataRateInfo; } uVHTSupDataRateInfo; - pDot11f->present = 1; + pDot11f->present = pTdlsAddStaReq->vhtcap_present; nCfgValue = pTdlsAddStaReq->vhtCap.vhtCapInfo; uVHTCapabilityInfo.nCfgValue32 = nCfgValue; @@ -2396,7 +2547,7 @@ limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, &val) != eSIR_SUCCESS) { /// Could not get rateset from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve rateset\n")); + limLog(pMac, LOGP, FL("could not retrieve rateset")); } tempRateSet.numRates = val; @@ -2415,7 +2566,7 @@ limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, if ((tempRateSet.numRates + tempRateSet2.numRates) > 12) { - PELOGE(limLog(pMac, LOGE, FL("more than 12 rates in CFG\n"));) + PELOGE(limLog(pMac, LOGE, FL("more than 12 rates in CFG"));) goto error; } @@ -2481,7 +2632,7 @@ limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, #ifdef FEATURE_WLAN_NON_INTEGRATED_SOC if ((bRateIndex > HAL_NUM_11B_RATES) || (aRateIndex > HAL_NUM_11A_RATES)) { - limLog(pMac, LOGE, FL("Invalid number of rates (11b->%d, 11a->%d)\n"), + limLog(pMac, LOGE, FL("Invalid number of rates (11b->%d, 11a->%d)"), bRateIndex, aRateIndex); return eSIR_FAILURE; } @@ -2514,7 +2665,7 @@ limTdlsPopulateMatchingRateSet(tpAniSirGlobal pMac, &val) != eSIR_SUCCESS) { /// Could not get rateset from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve supportedMCSSet\n")); + limLog(pMac, LOGP, FL("could not retrieve supportedMCSSet")); goto error; } @@ -2655,7 +2806,8 @@ static void limTdlsUpdateHashNodeInfo(tpAniSirGlobal pMac, tDphHashNode *pStaDs, if (pVhtCaps->present) { pStaDs->mlmStaContext.vhtCapability = 1 ; - pStaDs->vhtSupportedChannelWidthSet= pVhtCaps->supportedChannelWidthSet; + pStaDs->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_80MHZ; + pStaDs->htSupportedChannelWidthSet = eHT_CHANNEL_WIDTH_40MHZ ; pStaDs->vhtLdpcCapable = pVhtCaps->ldpcCodingCap; pStaDs->vhtBeamFormerCapable= pVhtCaps->suBeamFormerCap; // TODO , is it necessary , Sunil??? @@ -2664,6 +2816,7 @@ static void limTdlsUpdateHashNodeInfo(tpAniSirGlobal pMac, tDphHashNode *pStaDs, else { pStaDs->mlmStaContext.vhtCapability = 0 ; + pStaDs->vhtSupportedChannelWidthSet = WNI_CFG_VHT_CHANNEL_WIDTH_20_40MHZ; } #endif /*Calculate the Secondary Coannel Offset */ @@ -2748,7 +2901,7 @@ tSirTdlsPeerInfo *limTdlsFindDisPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac) { peerInfo = &discoveryList->tdlsDisPeerInfo ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Peer in discovery list = %02x, %02x, %02x, %02x, %02x, %02x \n"), + ("Peer in discovery list = %02x, %02x, %02x, %02x, %02x, %02x "), peerInfo->peerMac[0], peerInfo->peerMac[1], peerInfo->peerMac[2], @@ -2816,7 +2969,7 @@ static tANI_U8 limTdlsFindSetupPeerByState(tpAniSirGlobal pMac, tANI_U8 state, while (linkSetupList != NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peer state = %02x\n"), (linkSetupList)->tdls_link_state) ; + ("peer state = %02x"), (linkSetupList)->tdls_link_state) ; if((linkSetupList)->tdls_link_state == state) { checkNode = TDLS_NODE_FOUND ; @@ -2848,7 +3001,7 @@ void limTdlsDelLinkPeer(tpAniSirGlobal pMac, tSirMacAddr peerMac) sizeof(tSirMacAddr)) ) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Del Node for Peer = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("Del Node for Peer = %02x,%02x,%02x,%02x,%02x,%02x"), currentNode->peerMac[0], currentNode->peerMac[1], currentNode->peerMac[2], @@ -2893,19 +3046,19 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, status = dot11fUnpackTDLSDisReq(pMac, pBody, frmLen, &tdlsDisReq) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_WARN, - ("TDLS dis request dialog = %d\n"), tdlsDisReq.DialogToken.token); + ("TDLS dis request dialog = %d"), tdlsDisReq.DialogToken.token); if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Request frame (0x%08x," "%d bytes):\n"), + TDLS discovery Request frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -2920,7 +3073,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsDisReq.LinkIdentifier.bssid[0], tdlsDisReq.LinkIdentifier.bssid[1], tdlsDisReq.LinkIdentifier.bssid[2], @@ -2936,7 +3089,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, status = palEqualMemory(pMac->hHdd, &psessionEntry->bssId[0], &tdlsDisReq.LinkIdentifier.bssid[0], sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("lim BSSID %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("lim BSSID %02x, %02x, %02x, %02x, %02x, %02x"), psessionEntry->bssId[0], psessionEntry->bssId[1], psessionEntry->bssId[2], @@ -2945,7 +3098,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, psessionEntry->bssId[5]) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Dis req from BSSID %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("Dis req from BSSID %02x, %02x, %02x, %02x, %02x, %02x"), tdlsDisReq.LinkIdentifier.bssid[0], tdlsDisReq.LinkIdentifier.bssid[1], tdlsDisReq.LinkIdentifier.bssid[2], @@ -2955,7 +3108,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, ) ; if(!status) { - limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter")) ; return eSIR_FAILURE ; } @@ -2969,7 +3122,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, sizeof(tSirMacAddr)) ; if(status) { - limLog( pMac, LOGE, FL("Echo of our TDLS discovery request frame\n")) ; + limLog( pMac, LOGE, FL("Echo of our TDLS discovery request frame")) ; return eSIR_FAILURE ; } @@ -3000,7 +3153,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, if(status != eHAL_STATUS_SUCCESS) { limLog(pMac, LOGP, FL("alloc fail for TDLS discovery \ - reponse info\n")) ; + reponse info")) ; return eSIR_FAILURE ; } @@ -3047,7 +3200,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Capabilities value\n")); + FL("could not retrieve Capabilities value")); } swapBitField16(caps, ( tANI_U16* )&capsInfo ); /* update Caps Info */ @@ -3080,7 +3233,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, peerInfo, psessionEntry)) { VOS_ASSERT(0) ; - limLog(pMac, LOGE, "Add STA for dis response is failed \n") ; + limLog(pMac, LOGE, "Add STA for dis response is failed ") ; return eSIR_FAILURE ; } } /* use setup link sta ID for discovery rsp */ @@ -3095,7 +3248,7 @@ static tSirRetStatus limProcessTdlsDisReqFrame(tpAniSirGlobal pMac, else { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("discovery procedure in progress for this peer\n")) ; + ("discovery procedure in progress for this peer")) ; } return eSIR_SUCCESS ; @@ -3123,14 +3276,14 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS setup Request frame (0x%08x," "%d bytes):\n"), + TDLS setup Request frame (0x%08x," "%d bytes):"), status, pBody ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -3144,7 +3297,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsSetupReq.LinkIdentifier.bssid[0], tdlsSetupReq.LinkIdentifier.bssid[1], tdlsSetupReq.LinkIdentifier.bssid[2], @@ -3162,7 +3315,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGE, FL("TDLS setup request frame from other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("TDLS setup request frame from other BSS -> something wrong. Check RXP filter")) ; limSendTdlsSetupRspFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr, tdlsSetupReq.DialogToken.token , psessionEntry, TDLS_SETUP_STATUS_FAILURE, NULL, 0 ) ; @@ -3174,13 +3327,13 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, { /* simply ignore this setup request packet */ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: ignore TDLS Setup Req packet\n")); + ("TDLS negative running: ignore TDLS Setup Req packet")); return eSIR_SUCCESS ; } if(pMac->lim.gLimTdlsNegativeBehavior & LIM_TDLS_NEGATIVE_SEND_REQ_TO_SETUP_REQ) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("TDLS negative running: send TDLS Setup Req to peer TDLS Setup Req\n")); + ("TDLS negative running: send TDLS Setup Req to peer TDLS Setup Req")); /* format TDLS discovery request frame and transmit it */ limSendTdlsLinkSetupReqFrame(pMac, tdlsSetupReq.LinkIdentifier.InitStaAddr, tdlsSetupReq.DialogToken.token, psessionEntry, NULL, 0) ; @@ -3195,9 +3348,9 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, tANI_U32 tdlsStateStatus = TDLS_LINK_SETUP_START_STATE ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("Link is already setup with this peer\n" )) ; + ("Link is already setup with this peer" )) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("state = %d\n"), tmpSetupPeer->tdls_link_state) ; + ("state = %d"), tmpSetupPeer->tdls_link_state) ; //return eSIR_FAILURE ; if(tmpSetupPeer == NULL) @@ -3215,7 +3368,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, macCompare= vos_mem_compare2(tmpSetupPeer->peerMac, psessionEntry->selfMacAddr, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("MAC comparison Rslt = %d\n"), macCompare ) ; + ("MAC comparison Rslt = %d"), macCompare ) ; if(0 > macCompare) { /* @@ -3298,7 +3451,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, { VOS_ASSERT(0) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("link Setup is Recieved in unknown state\n" )) ; + ("link Setup is Recieved in unknown state" )) ; break ; } #endif @@ -3318,7 +3471,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer ))) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ( "Unable to allocate memory during ADD_STA\n" )); + ( "Unable to allocate memory during ADD_STA" )); return eSIR_MEM_ALLOC_FAILED; } @@ -3336,7 +3489,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x\n"), + ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x"), setupPeer->peerMac[0], setupPeer->peerMac[1], setupPeer->peerMac[2], @@ -3386,7 +3539,7 @@ static tSirRetStatus limProcessTdlsSetupReqFrame(tpAniSirGlobal pMac, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x\n"), + ("Setup REQ MAC = %02x,%02x, %02x, %02x, %02x, %02x"), setupPeer->peerMac[0], setupPeer->peerMac[1], setupPeer->peerMac[2], @@ -3429,14 +3582,14 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse TDLS discovery Request \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Request frame (0x%08x," "%d bytes):\n"), + TDLS discovery Request frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -3451,7 +3604,7 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsSetupRsp.LinkIdentifier.bssid[0], tdlsSetupRsp.LinkIdentifier.bssid[1], tdlsSetupRsp.LinkIdentifier.bssid[2], @@ -3470,7 +3623,7 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("TDLS discovery request frame from other BSS -> something wrong. Check RXP filter")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; @@ -3480,7 +3633,7 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("TDLS setup RSP peer = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("TDLS setup RSP peer = %02x,%02x,%02x,%02x,%02x,%02x"), peerMac[0], peerMac[1], peerMac[2], @@ -3492,12 +3645,12 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, if(NULL == setupPeer) { limLog( pMac, LOGE, FL(" unknown setup Response frame \ - other BSS\n")) ; + other BSS")) ; return eSIR_FAILURE ; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("deactivating Setup RSP timer\n")) ; + ("deactivating Setup RSP timer")) ; /* Deactivate the timer */ tx_timer_deactivate(&(setupPeer)->gLimTdlsLinkSetupRspTimeoutTimer) ; @@ -3510,7 +3663,7 @@ static tSirRetStatus limProcessTdlsSetupRspFrame(tpAniSirGlobal pMac, { limTdlsDelLinkPeer(pMac, (setupPeer)->peerMac) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("setup RSP with Failure Code\n")) ; + ("setup RSP with Failure Code")) ; return eSIR_FAILURE ; } @@ -3568,14 +3721,14 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Response frame (0x%08x," "%d bytes):\n"), + TDLS discovery Response frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -3589,7 +3742,7 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsSetupCnf.LinkIdentifier.bssid[0], tdlsSetupCnf.LinkIdentifier.bssid[1], tdlsSetupCnf.LinkIdentifier.bssid[2], @@ -3608,14 +3761,14 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGE, FL("TDLS setup CNF frame other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("TDLS setup CNF frame other BSS -> something wrong. Check RXP filter")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; } /* TODO, do more validation */ VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("setup Cnf peer MAc = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("setup Cnf peer MAc = %02x,%02x,%02x,%02x,%02x,%02x"), tdlsSetupCnf.LinkIdentifier.InitStaAddr[0], tdlsSetupCnf.LinkIdentifier.InitStaAddr[1], tdlsSetupCnf.LinkIdentifier.InitStaAddr[2], @@ -3631,12 +3784,12 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if(NULL == setupPeer) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - (" unknown setup CNF frame\n")) ; + (" unknown setup CNF frame")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("setup CNF peer MAC = %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("setup CNF peer MAC = %02x,%02x,%02x,%02x,%02x,%02x"), (setupPeer)->peerMac[0], (setupPeer)->peerMac[1], (setupPeer)->peerMac[2], @@ -3647,7 +3800,7 @@ static tSirRetStatus limProcessTdlsSetupCnfFrame(tpAniSirGlobal pMac, if((setupPeer)->dialog != tdlsSetupCnf.DialogToken.token) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("setup CNF frame not matching with setup RSP\n")) ; + ("setup CNF frame not matching with setup RSP")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; } @@ -3691,14 +3844,14 @@ static tSirRetStatus limProcessTdlsDisRspFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Response frame (0x%08x," "%d bytes):\n"), + TDLS discovery Response frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pFrame, nFrame);) } @@ -3711,14 +3864,14 @@ static tSirRetStatus limProcessTdlsDisRspFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGW, FL(" TDLS discovery Response frame other BSS\n")) ; + limLog( pMac, LOGW, FL(" TDLS discovery Response frame other BSS")) ; return eSIR_FAILURE ; } /* TODO, do more validation */ if(tdlsDisRsp.DialogToken.token != prevDisReq->dialog) { - limLog( pMac, LOGW, FL(" wrong TDLS discovery Response frame\n")) ; + limLog( pMac, LOGW, FL(" wrong TDLS discovery Response frame")) ; return eSIR_FAILURE ; } @@ -3735,7 +3888,7 @@ static tSirRetStatus limProcessTdlsDisRspFrame(tpAniSirGlobal pMac, if(status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("alloc fail for TDLS discovery reponse info\n")) ; + limLog(pMac, LOGP, FL("alloc fail for TDLS discovery reponse info")) ; return eSIR_FAILURE ; } @@ -3814,14 +3967,14 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( status ) ) { limLog(pMac, LOGE, FL("Failed to parse an TDLS discovery Response \ - frame (0x%08x, %d bytes):\n"),status, frmLen); + frame (0x%08x, %d bytes):"),status, frmLen); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while unpacking an\ - TDLS discovery Response frame (0x%08x," "%d bytes):\n"), + TDLS discovery Response frame (0x%08x," "%d bytes):"), status, frmLen ); PELOG2(sirDumpBuf(pMac, SIR_DBG_MODULE_ID, LOG2, pBody, frmLen);) } @@ -3836,7 +3989,7 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, \ - ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)\n"), \ + ("no Seesion entry for TDLS session (bssid %02x:%02x:%02x:%02x:%02x:%02x)"), \ tdlsTeardown.LinkIdentifier.bssid[0], tdlsTeardown.LinkIdentifier.bssid[1], tdlsTeardown.LinkIdentifier.bssid[2], @@ -3856,7 +4009,7 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, if(!status) { - limLog( pMac, LOGE, FL("Teardown from other BSS -> something wrong. Check RXP filter\n")) ; + limLog( pMac, LOGE, FL("Teardown from other BSS -> something wrong. Check RXP filter")) ; VOS_ASSERT(0) ; return eSIR_FAILURE ; } @@ -3869,12 +4022,12 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, { //ignore //VOS_ASSERT(0) ; - limLog( pMac, LOGE, FL("Teardown from unknown peer. --> ignored\n") ); + limLog( pMac, LOGE, FL("Teardown from unknown peer. --> ignored") ); return eSIR_FAILURE ; } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("teardown for peer %02x,%02x,%02x,%02x,%02x,%02x\n"), + ("teardown for peer %02x,%02x,%02x,%02x,%02x,%02x"), (setupPeer)->peerMac[0], (setupPeer)->peerMac[1], (setupPeer)->peerMac[2], @@ -3887,19 +4040,19 @@ static tSirRetStatus limProcessTdlsTeardownFrame(tpAniSirGlobal pMac, case eSIR_MAC_TDLS_TEARDOWN_UNSPEC_REASON: { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("teardown with unspecified reason\n")) ; + ("teardown with unspecified reason")) ; break ; } case eSIR_MAC_TDLS_TEARDOWN_PEER_UNREACHABLE: { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - (" Teardown from AP, TDLS peer unreachable\n")) ; + (" Teardown from AP, TDLS peer unreachable")) ; break ; } default: { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - (" unknown teardown\n")) ; + (" unknown teardown")) ; break ; } } @@ -3954,7 +4107,7 @@ void limProcessTdlsFrame(tpAniSirGlobal pMac, tANI_U32 *pBd) if(category != SIR_MAC_ACTION_TDLS) { - limLog( pMac, LOGE, FL("Invalid TDLS action frame=(%d). Ignored\n"), category ); + limLog( pMac, LOGE, FL("Invalid TDLS action frame=(%d). Ignored"), category ); return ; } @@ -4020,7 +4173,7 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, } VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("ADD STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("ADD STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x"), peerMac[0], peerMac[1], peerMac[2], @@ -4033,7 +4186,7 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, &aid, &psessionEntry->dph.dphHashTable)) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - (" there is hash entry for this client\n")) ; + (" there is hash entry for this client")) ; status = eSIR_FAILURE ; VOS_ASSERT(0) ; return status ; @@ -4057,7 +4210,7 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, if(NULL == pStaDs) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - (" add hash entry failed\n")) ; + (" add hash entry failed")) ; status = eSIR_FAILURE ; VOS_ASSERT(0) ; return status; @@ -4068,23 +4221,23 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, tSirMacRateSet *suppRates = &peerInfo->tdlsPeerSuppRates ; tSirMacRateSet *extRates = &peerInfo->tdlsPeerExtRates ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("pSta DS [%p] \n"), pStaDs) ; + ("pSta DS [%p] "), pStaDs) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peerInfo->tdlsPeerSuppRates = [%p]\n"), + ("peerInfo->tdlsPeerSuppRates = [%p]"), (tANI_U8 *)&peerInfo->tdlsPeerSuppRates) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peerInfo->tdlsPeerExtRates = [%p]\n"), + ("peerInfo->tdlsPeerExtRates = [%p]"), (tANI_U8 *)&peerInfo->tdlsPeerExtRates) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peerInfo->tdlsPeerPropRates = [%p]\n"), + ("peerInfo->tdlsPeerPropRates = [%p]"), (tANI_U8 *)&pStaDs->mlmStaContext.propRateSet) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("peerInfo->mcs = [%p]\n"), + ("peerInfo->mcs = [%p]"), (tANI_U8 *)peerInfo->supportedMCSSet) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("num of supp rates = %02x\n"), suppRates->numRates) ; + ("num of supp rates = %02x"), suppRates->numRates) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("num of ext rates = %01x\n"), extRates->numRates) ; + ("num of ext rates = %01x"), extRates->numRates) ; #endif /* Populate matching rate set */ @@ -4112,7 +4265,7 @@ static tSirRetStatus limTdlsDisAddSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, palCopyMemory(pMac->hHdd, pStaDs->staAddr, peerMac, sizeof(tSirMacAddr)) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Add STA for Peer: %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("Add STA for Peer: %02x, %02x, %02x, %02x, %02x, %02x"), pStaDs->staAddr[0], pStaDs->staAddr[1], pStaDs->staAddr[2], @@ -4180,7 +4333,7 @@ static tSirRetStatus limTdlsSetupAddSta(tpAniSirGlobal pMac, if(NULL == pStaDs) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - (" add hash entry failed\n")) ; + (" add hash entry failed")) ; VOS_ASSERT(0) ; return eSIR_FAILURE; } @@ -4217,7 +4370,7 @@ static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("DEL STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x \n"), + ("DEL STA peer MAC: %02x, %02x, %02x, %02x, %02x, %02x "), pStaDs->staAddr[0], pStaDs->staAddr[1], pStaDs->staAddr[2], @@ -4227,7 +4380,7 @@ static tpDphHashNode limTdlsDelSta(tpAniSirGlobal pMac, tSirMacAddr peerMac, ) ; VOS_TRACE(VOS_MODULE_ID_PE, TDLS_DEBUG_LOG_LEVEL, - ("limTdlsDelSta: STA type = %x, sta idx = %x\n"),pStaDs->staType, + ("limTdlsDelSta: STA type = %x, sta idx = %x"),pStaDs->staType, pStaDs->staIndex) ; status = limDelSta(pMac, pStaDs, false, psessionEntry) ; @@ -4269,7 +4422,7 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ; if(NULL == setupPeer) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkEstablish: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X\n"), \ + ("limTdlsLinkEstablish: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X"), \ peerMac[0], peerMac[1], peerMac[2], \ peerMac[3], peerMac[4], peerMac[5]); return eSIR_FAILURE; @@ -4281,7 +4434,7 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkEstablish: sessionID %d is not found\n"), setupPeer->tdls_sessionId); + ("limTdlsLinkEstablish: sessionID %d is not found"), setupPeer->tdls_sessionId); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -4290,7 +4443,7 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM pStaDs = dphLookupHashEntry(pMac, peerMac, &aid, &psessionEntry->dph.dphHashTable) ; if(pStaDs == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkEstablish: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X\n"), \ + ("limTdlsLinkEstablish: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X"), \ peerMac[0], peerMac[1], peerMac[2], \ peerMac[3], peerMac[4], peerMac[5]); return eSIR_FAILURE; @@ -4327,13 +4480,13 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM status = dot11fGetPackedTDLSPeerTrafficIndSize ( pMac, &tdlsPtiTemplate, &nPayload); if ( DOT11F_FAILED( status ) ) { - limLog( pMac, LOGP, FL("Failed to calculate the packed size for a PTI template (0x%08x).\n"), status ); + limLog( pMac, LOGP, FL("Failed to calculate the packed size for a PTI template (0x%08x)."), status ); /* We'll fall back on the worst case scenario: */ nPayload = sizeof( tdlsPtiTemplate ); } else if ( DOT11F_WARNED( status ) ) { - limLog( pMac, LOGW, FL("There were warnings while calculating the packed size for a PTI template (0x%08x).\n"), status ); + limLog( pMac, LOGW, FL("There were warnings while calculating the packed size for a PTI template (0x%08x)."), status ); } /* @@ -4347,7 +4500,7 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM + PAYLOAD_TYPE_TDLS_SIZE ; if(nBytes > 64) { - limLog( pMac, LOGE, FL("required memory for PTI frame is %ld, but reserved only 64.\n"), nBytes); + limLog( pMac, LOGE, FL("required memory for PTI frame is %ld, but reserved only 64."), nBytes); nBytes = 64; } /* zero out the memory */ @@ -4364,16 +4517,16 @@ static tSirRetStatus limTdlsLinkEstablish(tpAniSirGlobal pMac, tSirMacAddr peerM if ( DOT11F_FAILED( status ) ) { limLog( pMac, LOGE, FL("Failed to pack a PTI template \ - (0x%08x).\n"), status ); + (0x%08x)."), status ); return eSIR_FAILURE; } else if ( DOT11F_WARNED( status ) ) { limLog( pMac, LOGW, FL("There were warnings while packing TDLS" - "Peer Traffic Indication (0x%08x).\n") ); + "Peer Traffic Indication (0x%08x).") ); } - LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("bIsResponder=%d, header_offset=%ld, linkIdenOffset=%d, ptiBufStatusOffset=%d \n"), \ + LIM_LOG_TDLS(VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, ("bIsResponder=%d, header_offset=%ld, linkIdenOffset=%d, ptiBufStatusOffset=%d "), \ setupPeer->tdls_bIsResponder, header_offset, PTI_LINK_IDEN_OFFSET, PTI_BUF_STATUS_OFFSET)); limSendTdlsLinkEstablish(pMac, setupPeer->tdls_bIsResponder, @@ -4398,7 +4551,7 @@ static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peerMa limTdlsFindLinkPeer(pMac, peerMac, &setupPeer) ; if(NULL == setupPeer) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkTeardown: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X\n"), \ + ("limTdlsLinkTeardown: cannot find peer mac in tdls linksetup list: %02X %02X %02X %02X %02X %02X"), \ peerMac[0], peerMac[1], peerMac[2], \ peerMac[3], peerMac[4], peerMac[5]); return eSIR_FAILURE; @@ -4410,7 +4563,7 @@ static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peerMa if(NULL == psessionEntry) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkTeardown: sessionID %d is not found\n"), setupPeer->tdls_sessionId); + ("limTdlsLinkTeardown: sessionID %d is not found"), setupPeer->tdls_sessionId); VOS_ASSERT(0) ; return eHAL_STATUS_FAILURE; } @@ -4421,7 +4574,7 @@ static tSirRetStatus limTdlsLinkTeardown(tpAniSirGlobal pMac, tSirMacAddr peerMa if(pStaDs == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("limTdlsLinkTeardown: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X\n"), \ + ("limTdlsLinkTeardown: cannot find peer mac in hash table: %02X %02X %02X %02X %02X %02X"), \ peerMac[0], peerMac[1], peerMac[2], \ peerMac[3], peerMac[4], peerMac[5]); return eSIR_FAILURE; @@ -4473,7 +4626,7 @@ static tSirTdlsDisRsp *tdlsPrepareTdlsDisRsp(tpAniSirGlobal pMac, sizeof(tSirTdlsPeerInfo)); VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Msg Sent to PE, peer MAC: %02x, %02x, %02x, %02x, %02x, %02x\n"), + ("Msg Sent to PE, peer MAC: %02x, %02x, %02x, %02x, %02x, %02x"), peerInfo->peerMac[0] , peerInfo->peerMac[1] , peerInfo->peerMac[2] , @@ -4490,7 +4643,7 @@ static tSirTdlsDisRsp *tdlsPrepareTdlsDisRsp(tpAniSirGlobal pMac, || ((!tdlsDisRspList) && disStaCount)) { limLog(pMac, LOG1, FL("mismatch in dis sta count and\ - and number of nodes in list\n")) ; + and number of nodes in list")) ; VOS_ASSERT(0) ; return NULL ; } @@ -4581,7 +4734,7 @@ void limSendSmeTdlsDisRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, tANI_U8 tdlsStaCount = pMac->lim.gLimTdlsDisStaCount ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("no of TDLS STA discovered: %d\n"), tdlsStaCount) ; + ("no of TDLS STA discovered: %d"), tdlsStaCount) ; tdlsDisRsp = tdlsPrepareTdlsDisRsp(pMac, tdlsDisRsp, tdlsStaCount) ; if(tdlsDisRsp) @@ -4590,7 +4743,7 @@ void limSendSmeTdlsDisRsp(tpAniSirGlobal pMac, tSirResultCodes statusCode, } else { - limLog(pMac, LOGP, FL("fatal failure for TDLS DIS RSP\n")); + limLog(pMac, LOGP, FL("fatal failure for TDLS DIS RSP")); VOS_ASSERT(0) ; return ; } @@ -4723,7 +4876,7 @@ void limTdlsLinkSetupRspTimerHandler(void *pMacGlobal, tANI_U32 timerId) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting message %X to LIM failed, reason=%d\n"), + FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); return ; } @@ -4746,7 +4899,7 @@ void limTdlsLinkSetupCnfTimerHandler(void *pMacGlobal, tANI_U32 timerId) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting message %X to LIM failed, reason=%d\n"), + FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); return ; } @@ -4775,7 +4928,7 @@ void limStartTdlsTimer(tpAniSirGlobal pMac, tANI_U8 sessionId, TX_TIMER *timer, timerId, cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { limLog(pMac, LOGP, - FL("could not create TDLS discovery response wait timer\n")); + FL("could not create TDLS discovery response wait timer")); return; } @@ -4786,7 +4939,7 @@ void limStartTdlsTimer(tpAniSirGlobal pMac, tANI_U8 sessionId, TX_TIMER *timer, eLIM_TDLS_DISCOVERY_RSP_WAIT)); if (tx_timer_activate(timer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("TDLS link setup timer activation failed!\n")); + limLog(pMac, LOGP, FL("TDLS link setup timer activation failed!")); return ; } @@ -4865,7 +5018,7 @@ eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, { VOS_ASSERT(0) ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("Add sta failed \n")) ; + ("Add sta failed ")) ; status = eSIR_FAILURE; goto add_sta_error; } @@ -4875,7 +5028,7 @@ eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, if(NULL == pStaDs) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("pStaDs is NULL \n")) ; + ("pStaDs is NULL ")) ; status = eSIR_FAILURE; goto add_sta_error; } @@ -4892,7 +5045,7 @@ eHalStatus limProcessTdlsAddStaRsp(tpAniSirGlobal pMac, void *msg, if(eSIR_FAILURE == status) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - ("Peer IND msg to SME failed\n")) ; + ("Peer IND msg to SME failed")) ; palFreeMemory( pMac->hHdd, (void *) pAddStaParams ); return eSIR_FAILURE ; } @@ -5007,7 +5160,7 @@ eHalStatus limTdlsPrepareSetupReqFrame(tpAniSirGlobal pMac, (void **) &setupPeer, sizeof( tLimTdlsLinkSetupPeer ))) { limLog( pMac, LOGP, - FL( "Unable to allocate memory during ADD_STA\n" )); + FL( "Unable to allocate memory during ADD_STA" )); VOS_ASSERT(0) ; return eSIR_MEM_ALLOC_FAILED; } @@ -5058,13 +5211,13 @@ tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, tSirResultCodes resultCode = eSIR_SME_INVALID_PARAMETERS; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Send Mgmt Recieved\n")) ; + ("Send Mgmt Recieved")) ; if((psessionEntry = peFindSessionByBssid(pMac, pSendMgmtReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", pSendMgmtReq->sessionId); goto lim_tdls_send_mgmt_error; } @@ -5073,7 +5226,7 @@ tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "send mgmt received in wrong system Role %d\n", + "send mgmt received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_send_mgmt_error; } @@ -5087,7 +5240,7 @@ tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, { limLog(pMac, LOGE, "send mgmt received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_send_mgmt_error; } @@ -5095,7 +5248,7 @@ tSirRetStatus limProcessSmeTdlsMgmtSendReq(tpAniSirGlobal pMac, { case SIR_MAC_TDLS_DIS_REQ: VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - "Transmit Discovery Request Frame\n") ; + "Transmit Discovery Request Frame") ; /* format TDLS discovery request frame and transmit it */ limSendTdlsDisReqFrame(pMac, pSendMgmtReq->peerMac, pSendMgmtReq->dialog, psessionEntry) ; @@ -5222,13 +5375,13 @@ tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, tANI_U8 sessionId; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Send Mgmt Recieved\n")) ; + ("Send Mgmt Recieved")) ; if((psessionEntry = peFindSessionByBssid(pMac, pAddStaReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", pAddStaReq->sessionId); goto lim_tdls_add_sta_error; } @@ -5237,7 +5390,7 @@ tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "send mgmt received in wrong system Role %d\n", + "send mgmt received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_add_sta_error; } @@ -5251,7 +5404,7 @@ tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, { limLog(pMac, LOGE, "send mgmt received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_add_sta_error; } @@ -5260,7 +5413,7 @@ tSirRetStatus limProcessSmeTdlsAddStaReq(tpAniSirGlobal pMac, /* To start with, send add STA request to HAL */ if (eSIR_FAILURE == limTdlsSetupAddSta(pMac, pAddStaReq, psessionEntry)) { - limLog(pMac, LOGE, "%s: Add TDLS Station request failed \n", __func__); + limLog(pMac, LOGE, "%s: Add TDLS Station request failed ", __func__); goto lim_tdls_add_sta_error; } return eSIR_SUCCESS; @@ -5284,13 +5437,13 @@ tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, tpDphHashNode pStaDs = NULL ; VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO, - ("Send Mgmt Recieved\n")) ; + ("Send Mgmt Recieved")) ; if((psessionEntry = peFindSessionByBssid(pMac, pDelStaReq->bssid, &sessionId)) == NULL) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "PE Session does not exist for given sme sessionId %d\n", + "PE Session does not exist for given sme sessionId %d", pDelStaReq->sessionId); limSendSmeTdlsDelStaRsp(pMac, pDelStaReq->sessionId, pDelStaReq->peerMac, NULL, eSIR_FAILURE) ; @@ -5301,7 +5454,7 @@ tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_ERROR, - "Del sta received in wrong system Role %d\n", + "Del sta received in wrong system Role %d", psessionEntry->limSystemRole); goto lim_tdls_del_sta_error; } @@ -5315,7 +5468,7 @@ tSirRetStatus limProcessSmeTdlsDelStaReq(tpAniSirGlobal pMac, { limLog(pMac, LOGE, "Del Sta received in invalid LIMsme \ - state (%d)\n", psessionEntry->limSmeState); + state (%d)", psessionEntry->limSmeState); goto lim_tdls_del_sta_error; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c index 4ab03e05b65..44a28160c51 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limPropExtsUtils.c @@ -102,7 +102,7 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pBeaconStruct, sizeof(tSirProbeRespBeacon))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limExtractApCapability\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limExtractApCapability") ); return; } @@ -111,7 +111,7 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, *propCap = 0; *uapsd = 0; PELOG3(limLog( pMac, LOG3, - FL("In limExtractApCapability: The IE's being received are:\n")); + FL("In limExtractApCapability: The IE's being received are:")); sirDumpBuf( pMac, SIR_LIM_MODULE_ID, LOG3, pIE, ieLen );) if (sirParseBeaconIE(pMac, pBeaconStruct, pIE, (tANI_U32)ieLen) == eSIR_SUCCESS) { @@ -129,9 +129,9 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, #ifdef WLAN_FEATURE_11AC VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, - "***beacon.VHTCaps.present*****=%d\n",pBeaconStruct->VHTCaps.present); + "***beacon.VHTCaps.present*****=%d",pBeaconStruct->VHTCaps.present); VOS_TRACE(VOS_MODULE_ID_PE, VOS_TRACE_LEVEL_INFO_MED, - "***beacon.SU Beamformer Capable*****=%d\n",pBeaconStruct->VHTCaps.suBeamFormerCap); + "***beacon.SU Beamformer Capable*****=%d",pBeaconStruct->VHTCaps.suBeamFormerCap); if ( pBeaconStruct->VHTCaps.present && pBeaconStruct->VHTOperation.present) { @@ -176,7 +176,7 @@ limExtractApCapability(tpAniSirGlobal pMac, tANI_U8 *pIE, tANI_U16 ieLen, #if !defined WLAN_FEATURE_VOWIFI if (cfgSetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, localPowerConstraints) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not update local power constraint to cfg.\n")); + limLog(pMac, LOGP, FL("Could not update local power constraint to cfg.")); } #endif } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limRoamingAlgo.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limRoamingAlgo.c index 09c78cd614b..7beea7fe5c5 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limRoamingAlgo.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limRoamingAlgo.c @@ -79,7 +79,7 @@ tSirBackgroundScanMode limSelectsBackgroundScanMode(tpAniSirGlobal pMac) if (wlan_cfgGetInt(pMac, WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE, &cfgVal) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE value\n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_MAX_CONSECUTIVE_BACKGROUND_SCAN_FAILURE value")); return eSIR_NORMAL_BACKGROUND_SCAN; } @@ -94,7 +94,7 @@ tSirBackgroundScanMode limSelectsBackgroundScanMode(tpAniSirGlobal pMac) { pMac->lim.gLimNumOfForcedBkgndScan += 1; limLog(pMac, LOGE, - FL("Had %d consec scan fail(when expect < %d). Trigger AGGRESSIVE bkgnd scan.\n"), + FL("Had %d consec scan fail(when expect < %d). Trigger AGGRESSIVE bkgnd scan."), pMac->lim.gLimNumOfConsecutiveBkgndScanFailure, cfgVal); return eSIR_AGGRESSIVE_BACKGROUND_SCAN; } @@ -167,12 +167,12 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) tSirMacAddr bcAddr = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; tSirBackgroundScanMode backgroundScan; - PELOG1(limLog(pMac, LOG1, FL("Background Scan: %d success, %d consec fail \n"), + PELOG1(limLog(pMac, LOG1, FL("Background Scan: %d success, %d consec fail "), pMac->lim.gLimNumOfBackgroundScanSuccess, pMac->lim.gLimNumOfConsecutiveBkgndScanFailure);) if (! limIsBackgroundScanAllowed(pMac)) { - PELOG1(limLog(pMac, LOG1, FL("Skipping Background Scan \n"));) + PELOG1(limLog(pMac, LOG1, FL("Skipping Background Scan "));) return; } @@ -185,7 +185,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) * Could not get Valid channel list from CFG. * Log error. */ - PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list"));) return; } @@ -203,7 +203,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) (tANI_U32 *) &ssidLen) != eSIR_SUCCESS) { /// Could not get SSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve SSID\n")); + limLog(pMac, LOGP, FL("could not retrieve SSID")); } smeScanReq.ssId[0].length = (tANI_U8) ssidLen; smeScanReq.numSsid = 1; @@ -215,7 +215,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) &smeScanReq.minChannelTime) != eSIR_SUCCESS) { /// Could not get minChlTime value from CFG. Log error. - PELOGE(limLog(pMac, LOGE, FL("could not retrieve minChlTime value\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve minChlTime value"));) return; } @@ -224,7 +224,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) &smeScanReq.maxChannelTime) != eSIR_SUCCESS) { /// Could not get maxChlTime value from CFG. Log error. - PELOGE(limLog(pMac, LOGE, FL("could not retrieve maxChlTime value\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve maxChlTime value"));) return; } @@ -248,8 +248,8 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) { pMac->lim.gLimBackgroundScanChannelId = 0; - PELOGE(limLog(pMac, LOGE, FL("Skipping Background Scan since the channel list is exhausted.\n"));) - PELOGE(limLog(pMac, LOGE, FL("SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD indication to start the background scan again.\n"));) + PELOGE(limLog(pMac, LOGE, FL("Skipping Background Scan since the channel list is exhausted."));) + PELOGE(limLog(pMac, LOGE, FL("SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD indication to start the background scan again."));) /* Stop the BG scan timer here. SME should send WNI_CFG_BACKGROUND_SCAN_PERIOD * indication to start the background scan again. @@ -263,13 +263,13 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) // Could not deactivate BackgroundScanTimer timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate BackgroundScanTimer timer\n")); + FL("unable to deactivate BackgroundScanTimer timer")); } } pMac->lim.gLimBackgroundScanTerminate = TRUE; - PELOGE(limLog(pMac, LOGE, FL("Send dummy scan with returnFreshResults as 0 to report BG scan results to SME.\n"));) + PELOGE(limLog(pMac, LOGE, FL("Send dummy scan with returnFreshResults as 0 to report BG scan results to SME."));) return; } smeScanReq.channelList.channelNumber[0] = @@ -279,7 +279,7 @@ void limTriggerBackgroundScan(tpAniSirGlobal pMac) smeScanReq.uIEFieldOffset = sizeof(tSirSmeScanReq); backgroundScan = limSelectsBackgroundScanMode(pMac); - PELOG1(limLog(pMac, LOG1, FL("Performing (mode %d) Background Scan \n"), backgroundScan);) + PELOG1(limLog(pMac, LOG1, FL("Performing (mode %d) Background Scan "), backgroundScan);) smeScanReq.backgroundScanMode = backgroundScan; //determine whether to send the results or not, If so, notify the BG scan results to SME @@ -307,7 +307,7 @@ void limAbortBackgroundScan(tpAniSirGlobal pMac) if(pMac->lim.gLimBackgroundScanTerminate == FALSE) { - limLog(pMac, LOGE, FL("Abort Background Scan \n")); + limLog(pMac, LOGE, FL("Abort Background Scan ")); if (TX_TIMER_VALID(pMac->lim.limTimers.gLimBackgroundScanTimer)) { limDeactivateAndChangeTimer(pMac, eLIM_BACKGROUND_SCAN_TIMER); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c index 4c8f81e4ae2..4ce22cc09d3 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.c @@ -1,8 +1,43 @@ /* -* Copyright (c) 2011-2013 Qualcomm Atheros, Inc. -* All Rights Reserved. -* Qualcomm Atheros Confidential and Proprietary. -*/ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ /* * Airgo Networks, Inc proprietary. All rights reserved. @@ -104,14 +139,14 @@ limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal pMac) * @return None */ #if defined WLAN_FEATURE_VOWIFI -void +eHalStatus limCollectBssDescription(tpAniSirGlobal pMac, tSirBssDescription *pBssDescr, tpSirProbeRespBeacon pBPR, tANI_U8 *pRxPacketInfo, tANI_U8 fScanning) #else -void +eHalStatus limCollectBssDescription(tpAniSirGlobal pMac, tSirBssDescription *pBssDescr, tpSirProbeRespBeacon pBPR, @@ -130,6 +165,17 @@ limCollectBssDescription(tpAniSirGlobal pMac, rxChannel = WDA_GET_RX_CH(pRxPacketInfo); pBody = WDA_GET_RX_MPDU_DATA(pRxPacketInfo); + /** + * Drop all the beacons and probe response without P2P IE during P2P search + */ + if (NULL != pMac->lim.gpLimMlmScanReq && pMac->lim.gpLimMlmScanReq->p2pSearch) + { + if (NULL == limGetP2pIEPtr(pMac, (pBody + SIR_MAC_B_PR_SSID_OFFSET), ieLen)) + { + limLog( pMac, LOG3, MAC_ADDRESS_STR, MAC_ADDR_ARRAY(pHdr->bssId)); + return eHAL_STATUS_FAILURE; + } + } /** * Length of BSS desription is without length of @@ -248,7 +294,7 @@ limCollectBssDescription(tpAniSirGlobal pMac, pBssDescr->aniIndicator, ieLen ); - return; + return eHAL_STATUS_SUCCESS; } /*** end limCollectBssDescription() ***/ /** @@ -442,9 +488,9 @@ limCheckAndAddBssDescription(tpAniSirGlobal pMac, ieLen = WDA_GET_RX_PAYLOAD_LEN(pRxPacketInfo); if (ieLen <= SIR_MAC_B_PR_SSID_OFFSET) { - limLog(pMac, LOGP, - FL("RX packet has invalid length %d"), ieLen); - return; + limLog(pMac, LOGP, + FL("RX packet has invalid length %d\n"), ieLen); + return; } ieLen -= SIR_MAC_B_PR_SSID_OFFSET; @@ -462,11 +508,19 @@ limCheckAndAddBssDescription(tpAniSirGlobal pMac, // In scan state, store scan result. #if defined WLAN_FEATURE_VOWIFI - limCollectBssDescription(pMac, &pBssDescr->bssDescription, + status = limCollectBssDescription(pMac, &pBssDescr->bssDescription, pBPR, pRxPacketInfo, fScanning); + if (eHAL_STATUS_SUCCESS != status) + { + goto last; + } #else - limCollectBssDescription(pMac, &pBssDescr->bssDescription, + status = limCollectBssDescription(pMac, &pBssDescr->bssDescription, pBPR, pRxPacketInfo); + if (eHAL_STATUS_SUCCESS != status) + { + goto last; + } #endif /* Calling dfsChannelList which will convert DFS channel * to Active channel for x secs if this channel is DFS channel */ @@ -560,10 +614,12 @@ limCheckAndAddBssDescription(tpAniSirGlobal pMac, } }//(eANI_BOOLEAN_TRUE == fScanning) +last: if( eHAL_STATUS_SUCCESS != status ) { palFreeMemory( pMac->hHdd, pBssDescr ); } + return; } /****** end limCheckAndAddBssDescription() ******/ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h index 9ad88bfdc7c..13aa8f4ec71 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limScanResultUtils.h @@ -65,16 +65,24 @@ void limDeleteCachedScanResults(tpAniSirGlobal); void limRestorePreScanState(tpAniSirGlobal); void limCopyScanResult(tpAniSirGlobal, tANI_U8 *); void limReInitScanResults(tpAniSirGlobal); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limInitLfrHashTable(tpAniSirGlobal); +eHalStatus + limLookupNaddLfrHashEntry(tpAniSirGlobal, tLimScanResultNode *, tANI_U8, tANI_U8); +void limDeleteLfrHashEntry(tLimScanResultNode *); +void limDeleteCachedLfrScanResults(tpAniSirGlobal); +void limReInitLfrScanResults(tpAniSirGlobal); +#endif tANI_U32 limDeactivateMinChannelTimerDuringScan(tpAniSirGlobal); void limCheckAndAddBssDescription(tpAniSirGlobal, tpSirProbeRespBeacon, tANI_U8 *, tANI_BOOLEAN, tANI_U8); #if defined WLAN_FEATURE_VOWIFI -void limCollectBssDescription(tpAniSirGlobal, +eHalStatus limCollectBssDescription(tpAniSirGlobal, tSirBssDescription *, tpSirProbeRespBeacon, tANI_U8 *, tANI_U8); #else -void limCollectBssDescription(tpAniSirGlobal, +eHalStatus limCollectBssDescription(tpAniSirGlobal, tSirBssDescription *, tpSirProbeRespBeacon, tANI_U8 *); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c index 70abc3a6a2f..85f12dfb876 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSecurityUtils.c @@ -114,7 +114,7 @@ limIsAuthAlgoSupported(tpAniSirGlobal pMac, tAniAuthType authType, tpPESession p * from CFG. Log error. */ limLog(pMac, LOGE, - FL("could not retrieve AuthAlgo1 Enable value\n")); + FL("could not retrieve AuthAlgo1 Enable value")); return false; } @@ -142,7 +142,7 @@ limIsAuthAlgoSupported(tpAniSirGlobal pMac, tAniAuthType authType, tpPESession p * from CFG. Log error. */ limLog(pMac, LOGE, - FL("could not retrieve AuthAlgo2 Enable value\n")); + FL("could not retrieve AuthAlgo2 Enable value")); return false; } @@ -161,7 +161,7 @@ limIsAuthAlgoSupported(tpAniSirGlobal pMac, tAniAuthType authType, tpPESession p * from CFG. Log error. */ limLog(pMac, LOGE, - FL("could not retrieve PrivacyOptImplemented value\n")); + FL("could not retrieve PrivacyOptImplemented value")); return false; } @@ -226,7 +226,7 @@ limDeletePreAuthList(tpAniSirGlobal pMac) { pTempNode = pCurrNode->next; - PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthList \n"));) + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthList "));) limReleasePreAuthNode(pMac, pCurrNode); pCurrNode = pTempNode; @@ -380,8 +380,8 @@ limDeletePreAuthNode(tpAniSirGlobal pMac, tSirMacAddr macAddr) pMac->lim.pLimPreAuthList = pTempNode->next; - PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : first node to delete\n"));) - PELOG1(limLog(pMac, LOG1, FL("Release data entry: %x id %d peer \n"), + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : first node to delete"));) + PELOG1(limLog(pMac, LOG1, FL("Release data entry: %x id %d peer "), pTempNode, pTempNode->authNodeIdx); limPrintMacAddr(pMac, macAddr, LOG1);) limReleasePreAuthNode(pMac, pTempNode); @@ -401,8 +401,8 @@ limDeletePreAuthNode(tpAniSirGlobal pMac, tSirMacAddr macAddr) pPrevNode->next = pTempNode->next; - PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : subsequent node to delete\n")); - limLog(pMac, LOG1, FL("Release data entry: %x id %d peer \n"), + PELOG1(limLog(pMac, LOG1, FL("=====> limDeletePreAuthNode : subsequent node to delete")); + limLog(pMac, LOG1, FL("Release data entry: %x id %d peer "), pTempNode, pTempNode->authNodeIdx); limPrintMacAddr(pMac, macAddr, LOG1);) limReleasePreAuthNode(pMac, pTempNode); @@ -481,7 +481,7 @@ limRestoreFromAuthState(tpAniSirGlobal pMac, tSirResultCodes resultCode, tANI_U1 if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, currentBssId, &cfg) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(currentBssId,sessionEntry->bssId); @@ -772,7 +772,7 @@ limDecryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pKey, tANI_U8 *pEncrBody, keyLength, frameLen); - PELOG4(limLog(pMac, LOG4, FL("plainbody is \n")); + PELOG4(limLog(pMac, LOG4, FL("plainbody is ")); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG4, pPlainBody, frameLen);) // Compute CRC-32 and place them in last 4 bytes of encrypted body @@ -783,7 +783,7 @@ limDecryptAuthFrame(tpAniSirGlobal pMac, tANI_U8 *pKey, tANI_U8 *pEncrBody, // Compare RX_ICV with computed ICV for (i = 0; i < SIR_MAC_WEP_ICV_LENGTH; i++) { - PELOG4(limLog(pMac, LOG4, FL(" computed ICV%d[%x], rxed ICV%d[%x]\n"), + PELOG4(limLog(pMac, LOG4, FL(" computed ICV%d[%x], rxed ICV%d[%x]"), i, icv[i], i, pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]);) if (icv[i] != pPlainBody[frameLen - SIR_MAC_WEP_ICV_LENGTH + i]) return LIM_DECRYPT_ICV_FAIL; @@ -880,7 +880,7 @@ tANI_U32 val = 0; if(pMlmSetKeysReq->numKeys > SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS) { limLog( pMac, LOG1, - FL( "numKeys = %d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS\n" ), pMlmSetKeysReq->numKeys); + FL( "numKeys = %d is more than SIR_MAC_MAX_NUM_OF_DEFAULT_KEYS" ), pMlmSetKeysReq->numKeys); // Respond to SME with error code mlmSetKeysCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; @@ -894,7 +894,7 @@ tANI_U32 val = 0; sizeof( tSetBssKeyParams ))) { limLog( pMac, LOGE, - FL( "Unable to PAL allocate memory during SET_BSSKEY\n" )); + FL( "Unable to PAL allocate memory during SET_BSSKEY" )); // Respond to SME with error code mlmSetKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -912,7 +912,7 @@ tANI_U32 val = 0; if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) { - limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC\n" )); + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); } pSetBssKeyParams->singleTidRc = (tANI_U8)val; @@ -954,12 +954,12 @@ tANI_U32 val = 0; msgQ.bodyval = 0; limLog( pMac, LOGW, - FL( "Sending WDA_SET_BSSKEY_REQ...\n" )); + FL( "Sending WDA_SET_BSSKEY_REQ..." )); MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { limLog( pMac, LOGE, - FL("Posting SET_BSSKEY to HAL failed, reason=%X\n"), + FL("Posting SET_BSSKEY to HAL failed, reason=%X"), retCode ); // Respond to SME with LIM_MLM_SETKEYS_CNF @@ -1011,7 +1011,7 @@ tANI_U32 val = 0; // Package WDA_SET_STAKEY_REQ message parameters if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pSetStaKeyParams, sizeof( tSetStaKeyParams ))) { - limLog( pMac, LOGP, FL( "Unable to PAL allocate memory during SET_BSSKEY\n" )); + limLog( pMac, LOGP, FL( "Unable to PAL allocate memory during SET_BSSKEY" )); return; }else palZeroMemory( pMac->hHdd, (void *) pSetStaKeyParams, sizeof( tSetStaKeyParams )); @@ -1023,7 +1023,7 @@ tANI_U32 val = 0; if(eSIR_SUCCESS != wlan_cfgGetInt(pMac, WNI_CFG_SINGLE_TID_RC, &val)) { - limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC\n" )); + limLog( pMac, LOGP, FL( "Unable to read WNI_CFG_SINGLE_TID_RC" )); } pSetStaKeyParams->singleTidRc = (tANI_U8)val; @@ -1108,10 +1108,10 @@ tANI_U32 val = 0; msgQ.bodyptr = pSetStaKeyParams; msgQ.bodyval = 0; - limLog( pMac, LOG1, FL( "Sending WDA_SET_STAKEY_REQ...\n" )); + limLog( pMac, LOG1, FL( "Sending WDA_SET_STAKEY_REQ..." )); MTRACE(macTraceMsgTx(pMac, sessionEntry->peSessionId, msgQ.type)); if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { - limLog( pMac, LOGE, FL("Posting SET_STAKEY to HAL failed, reason=%X\n"), retCode ); + limLog( pMac, LOGE, FL("Posting SET_STAKEY to HAL failed, reason=%X"), retCode ); // Respond to SME with LIM_MLM_SETKEYS_CNF mlmSetKeysCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; }else @@ -1156,7 +1156,7 @@ tSirRetStatus retCode; sizeof( tRemoveBssKeyParams ))) { limLog( pMac, LOGE, - FL( "Unable to PAL allocate memory during REMOVE_BSSKEY\n" )); + FL( "Unable to PAL allocate memory during REMOVE_BSSKEY" )); // Respond to SME with error code mlmRemoveKeysCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -1188,13 +1188,13 @@ tSirRetStatus retCode; msgQ.bodyval = 0; limLog( pMac, LOGW, - FL( "Sending WDA_REMOVE_BSSKEY_REQ...\n" )); + FL( "Sending WDA_REMOVE_BSSKEY_REQ..." )); MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) { limLog( pMac, LOGE, - FL("Posting REMOVE_BSSKEY to HAL failed, reason=%X\n"), + FL("Posting REMOVE_BSSKEY to HAL failed, reason=%X"), retCode ); // Respond to SME with LIM_MLM_REMOVEKEYS_CNF @@ -1249,7 +1249,7 @@ tSirRetStatus retCode; sizeof( tRemoveStaKeyParams ))) { limLog( pMac, LOGE, - FL( "Unable to PAL allocate memory during REMOVE_STAKEY\n" )); + FL( "Unable to PAL allocate memory during REMOVE_STAKEY" )); // Respond to SME with error code mlmRemoveKeyCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -1263,11 +1263,11 @@ tSirRetStatus retCode; if( (pMlmRemoveKeyReq->edType == eSIR_ED_WEP104 || pMlmRemoveKeyReq->edType == eSIR_ED_WEP40) && pMlmRemoveKeyReq->wepType == eSIR_WEP_STATIC ) { - PELOGE(limLog(pMac, LOGE, FL("Request to remove static WEP keys through station interface\n Should use BSS interface\n"));) + PELOGE(limLog(pMac, LOGE, FL("Request to remove static WEP keys through station interface\n Should use BSS interface"));) mlmRemoveKeyCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } - + // Update the WDA_REMOVEKEY_REQ parameters pRemoveStaKeyParams->staIdx = staIdx; pRemoveStaKeyParams->encType = pMlmRemoveKeyReq->edType; @@ -1278,7 +1278,7 @@ tSirRetStatus retCode; pRemoveStaKeyParams->sessionId = psessionEntry->peSessionId; SET_LIM_PROCESS_DEFD_MESGS(pMac, false); - + msgQ.type = WDA_REMOVE_STAKEY_REQ; // // FIXME_GEN4 @@ -1290,19 +1290,21 @@ tSirRetStatus retCode; msgQ.bodyval = 0; limLog( pMac, LOGW, - FL( "Sending WDA_REMOVE_STAKEY_REQ...\n" )); + FL( "Sending WDA_REMOVE_STAKEY_REQ..." )); MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); - if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) + retCode = wdaPostCtrlMsg( pMac, &msgQ ); + if (eSIR_SUCCESS != retCode) { limLog( pMac, LOGE, - FL("Posting REMOVE_STAKEY to HAL failed, reason=%X\n"), + FL("Posting REMOVE_STAKEY to HAL failed, reason=%X"), retCode ); + palFreeMemory(pMac->hHdd, pRemoveStaKeyParams); // Respond to SME with LIM_MLM_REMOVEKEY_CNF mlmRemoveKeyCnf.resultCode = eSIR_SME_HAL_SEND_MESSAGE_FAIL; } else - return; + return; end: limPostSmeRemoveKeyCnf( pMac, diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c index 0a2325b748b..d54b6b7905d 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendManagementFrames.c @@ -128,16 +128,6 @@ tSirRetStatus limPopulateMacHeader( tpAniSirGlobal pMac, sizeof( tSirMacAddr )); // Prepare Address 2 - #if 0 - if ((statusCode = wlan_cfgGetStr(pMac, WNI_CFG_STA_ID, (tANI_U8 *) pMacHdr->sa, - &cfgLen)) != eSIR_SUCCESS) - { - // Could not get STA_ID from CFG. Log error. - limLog( pMac, LOGP, - FL("Failed to retrive STA_ID\n")); - return statusCode; - } - #endif// TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->sa,selfMacAddr); // Prepare Address 3 @@ -315,7 +305,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Probe Request (0x%08x).\n"), nStatus ); + "or a Probe Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fProbeRequest ); } @@ -323,7 +313,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Probe Request (" - "0x%08x).\n"), nStatus ); + "0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAdditionalIELen; @@ -335,7 +325,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Pro" - "be Request.\n"), nBytes ); + "be Request."), nBytes ); return eSIR_MEM_ALLOC_FAILED; } @@ -348,7 +338,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Probe Request (%d).\n"), + "tor for a Probe Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -361,7 +351,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Probe Request (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Probe Request (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -369,7 +359,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a P" - "robe Request (0x%08x).\n") ); + "robe Request (0x%08x).") ); } // Append any AddIE if present. @@ -404,7 +394,7 @@ limSendProbeReqMgmtFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("could not send Probe Request frame!\n" )); + limLog( pMac, LOGE, FL("could not send Probe Request frame!" )); //Pkt will be freed up by the callback return eSIR_FAILURE; } @@ -449,7 +439,7 @@ tSirRetStatus limGetAddnIeForProbeResp(tpAniSirGlobal pMac, if(elem_len > left) { limLog( pMac, LOGE, - FL("****Invalid IEs eid = %d elem_len=%d left=%d*****\n"), + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), elem_id,elem_len,left); palFreeMemory(pMac->hHdd, tempbuf); return eSIR_FAILURE; @@ -514,7 +504,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pFrm, sizeof(tDot11fProbeResponse))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limSendProbeRspMgmtFrame\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limSendProbeRspMgmtFrame") ); return; } @@ -534,7 +524,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, nSirStatus = wlan_cfgGetInt( pMac, WNI_CFG_BEACON_INTERVAL, &cfg); if (eSIR_SUCCESS != nSirStatus) { - limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BEACON_INTERVAL from CFG (%d).\n"), + limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BEACON_INTERVAL from CFG (%d)."), nSirStatus ); palFreeMemory(pMac->hHdd, pFrm); return; @@ -561,7 +551,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, else { if (wlan_cfgGetInt(pMac, (tANI_U16) WNI_CFG_WPS_ENABLE, &tmp) != eSIR_SUCCESS) - limLog(pMac, LOGP,"Failed to cfg get id %d\n", WNI_CFG_WPS_ENABLE ); + limLog(pMac, LOGP,"Failed to cfg get id %d", WNI_CFG_WPS_ENABLE ); wpsApEnable = tmp & WNI_CFG_WPS_ENABLE_AP; @@ -605,7 +595,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, #ifdef WLAN_FEATURE_11AC if(psessionEntry->vhtCapability) { - limLog( pMac, LOGW, FL("Populate VHT IE in Probe Response\n")); + limLog( pMac, LOGW, FL("Populate VHT IE in Probe Response")); PopulateDot11fVHTCaps( pMac, &pFrm->VHTCaps ); PopulateDot11fVHTOperation( pMac, &pFrm->VHTOperation ); // we do not support multi users yet @@ -638,7 +628,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Probe Response (0x%08x).\n"), + "or a Probe Response (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fProbeResponse ); @@ -647,7 +637,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Probe Response " - "(0x%08x).\n"), nStatus ); + "(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -790,7 +780,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Pro" - "be Response.\n"), nBytes ); + "be Response."), nBytes ); if ( addIE != NULL ) { palFreeMemory(pMac->hHdd, addIE); @@ -808,7 +798,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Probe Response (%d).\n"), + "tor for a Probe Response (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -829,7 +819,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); if ( addIE != NULL ) @@ -842,7 +832,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a P" - "robe Response (0x%08x).\n") ); + "robe Response (0x%08x).") ); } PELOG3(limLog( pMac, LOG3, FL("Sending Probe Response frame to ") ); @@ -899,7 +889,7 @@ limSendProbeRspMgmtFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("Could not send Probe Response.\n") ); + limLog( pMac, LOGE, FL("Could not send Probe Response.") ); //Pkt will be freed up by the callback } @@ -995,7 +985,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or an Add TS Request (0x%08x).\n"), + "or an Add TS Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fAddTSRequest ); @@ -1004,7 +994,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for an Add TS Request" - " (0x%08x).\n"), nStatus ); + " (0x%08x)."), nStatus ); } } else @@ -1038,7 +1028,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a WMM Add TS Request (0x%08x).\n"), + "or a WMM Add TS Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fAddTSRequest ); @@ -1047,7 +1037,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a WMM Add TS Requ" - "est (0x%08x).\n"), nStatus ); + "est (0x%08x)."), nStatus ); } } @@ -1059,7 +1049,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" - "d TS Request.\n"), nBytes ); + "d TS Request."), nBytes ); return; } @@ -1072,7 +1062,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Add TS Request (%d).\n"), + "tor for an Add TS Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -1087,7 +1077,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, ( tANI_U8* )pMacHdr->bssId, &cfgLen ) ) { limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BSSID whil" - "e sending an Add TS Request.\n") ); + "e sending an Add TS Request.") ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; @@ -1096,13 +1086,6 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // That done, pack the struct: if ( ! pAddTS->wmeTspecPresent ) { @@ -1112,7 +1095,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack an Add TS Request " - "(0x%08x).\n"), + "(0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1120,7 +1103,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "an Add TS Request (0x%08x).\n") ); + "an Add TS Request (0x%08x).") ); } } else @@ -1131,7 +1114,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a WMM Add TS Reque" - "st (0x%08x).\n"), + "st (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1139,7 +1122,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "a WMM Add TS Request (0x%08x).\n") ); + "a WMM Add TS Request (0x%08x).") ); } } @@ -1163,7 +1146,7 @@ limSendAddtsReqActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL( "*** Could not send an Add TS Request" - " (%X) ***\n" ), halstatus ); + " (%X) ***" ), halstatus ); //Pkt will be freed up by the callback } @@ -1298,7 +1281,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if( pSta->mlmStaContext.vhtCapability && psessionEntry->vhtCapability ) { - limLog( pMac, LOGW, FL("Populate VHT IEs in Assoc Response\n")); + limLog( pMac, LOGW, FL("Populate VHT IEs in Assoc Response")); PopulateDot11fVHTCaps( pMac, &frm.VHTCaps ); PopulateDot11fVHTOperation( pMac, &frm.VHTOperation); PopulateDot11fExtCap( pMac, &frm.ExtCap); @@ -1332,7 +1315,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to calculate the packed size f" - "or an Association Response (0x%08x).\n"), + "or an Association Response (0x%08x)."), nStatus ); return; } @@ -1340,7 +1323,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for an Association Re" - "sponse (0x%08x).\n"), nStatus ); + "sponse (0x%08x)."), nStatus ); } nBytes = sizeof( tSirMacMgmtHdr ) + nPayload; @@ -1381,7 +1364,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, ( void** ) &pPacket ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog(pMac, LOGP, FL("Call to bufAlloc failed for RE/ASSOC RSP.\n")); + limLog(pMac, LOGP, FL("Call to bufAlloc failed for RE/ASSOC RSP.")); return; } @@ -1399,7 +1382,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Association Response (%d).\n"), + "tor for an Association Response (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -1408,17 +1391,6 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, pMacHdr = ( tpSirMacMgmtHdr ) pFrame; - #if 0 - cfgLen = SIR_MAC_ADDR_LENGTH; - if ( eSIR_SUCCESS != cfgGetStr( pMac, WNI_CFG_BSSID, - ( tANI_U8* )pMacHdr->bssId, &cfgLen ) ) - { - limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BSSID whil" - "e sending an Association Response.\n") ); - palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); - return; // allocated! - } - #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); nStatus = dot11fPackAssocResponse( pMac, &frm, @@ -1426,7 +1398,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack an Association Response (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack an Association Response (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -1435,7 +1407,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing an " - "Association Response (0x%08x).\n") ); + "Association Response (0x%08x).") ); } macAddr = pMacHdr->da; @@ -1458,7 +1430,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if (palCopyMemory ( pMac->hHdd, pFrame+sizeof(tSirMacMgmtHdr)+nPayload, &addIE[0], addnIELen ) != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("Additional Assoc IEs request failed while Appending: %x\n"),halstatus); + limLog(pMac, LOGP, FL("Additional Assoc IEs request failed while Appending: %x"),halstatus); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; @@ -1482,7 +1454,7 @@ limSendAssocRspMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog(pMac, LOGE, - FL("*** Could not Send Re/AssocRsp, retCode=%X ***\n"), + FL("*** Could not Send Re/AssocRsp, retCode=%X ***"), nSirStatus); //Pkt will be freed up by the callback @@ -1615,7 +1587,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed si" - "ze for an Add TS Response (0x%08x).\n"), + "ze for an Add TS Response (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fAddTSResponse ); @@ -1624,7 +1596,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calcula" "tingthe packed size for an Add TS" - " Response (0x%08x).\n"), nStatus ); + " Response (0x%08x)."), nStatus ); } } else @@ -1642,7 +1614,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed si" - "ze for a WMM Add TS Response (0x%08x).\n"), + "ze for a WMM Add TS Response (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fWMMAddTSResponse ); @@ -1651,7 +1623,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calcula" "tingthe packed size for a WMM Add" - "TS Response (0x%08x).\n"), nStatus ); + "TS Response (0x%08x)."), nStatus ); } } @@ -1661,7 +1633,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" - "d TS Response.\n"), nBytes ); + "d TS Response."), nBytes ); return; } @@ -1674,7 +1646,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Add TS Response (%d).\n"), + "tor for an Add TS Response (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1688,20 +1660,13 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, ( tANI_U8* )pMacHdr->bssId, &cfgLen ) ) { limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BSSID whil" - "e sending an Add TS Response.\n") ); + "e sending an Add TS Response.") ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // That done, pack the struct: if ( ! pAddTS->wmeTspecPresent ) { @@ -1711,7 +1676,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack an Add TS Response " - "(0x%08x).\n"), + "(0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; @@ -1719,7 +1684,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "an Add TS Response (0x%08x).\n") ); + "an Add TS Response (0x%08x).") ); } } else @@ -1730,7 +1695,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a WMM Add TS Response " - "(0x%08x).\n"), + "(0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; @@ -1738,7 +1703,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "a WMM Add TS Response (0x%08x).\n") ); + "a WMM Add TS Response (0x%08x).") ); } } @@ -1762,7 +1727,7 @@ limSendAddtsRspActionFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("Failed to send Add TS Response (%X)!\n"), + limLog( pMac, LOGE, FL("Failed to send Add TS Response (%X)!"), nSirStatus ); //Pkt will be freed up by the callback } @@ -1804,7 +1769,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed si" - "ze for a Del TS (0x%08x).\n"), + "ze for a Del TS (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fDelTS ); @@ -1813,7 +1778,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calcula" "ting the packed size for a Del TS" - " (0x%08x).\n"), nStatus ); + " (0x%08x)."), nStatus ); } } else @@ -1829,7 +1794,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed si" - "ze for a WMM Del TS (0x%08x).\n"), + "ze for a WMM Del TS (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fDelTS ); @@ -1838,7 +1803,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calcula" "ting the packed size for a WMM De" - "l TS (0x%08x).\n"), nStatus ); + "l TS (0x%08x)."), nStatus ); } } @@ -1848,7 +1813,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an Ad" - "d TS Response.\n"), nBytes ); + "d TS Response."), nBytes ); return; } @@ -1862,7 +1827,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Add TS Response (%d).\n"), + "tor for an Add TS Response (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1877,20 +1842,13 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, ( tANI_U8* )pMacHdr->bssId, &cfgLen ) ) { limLog( pMac, LOGP, FL("Failed to retrieve WNI_CFG_BSSID whil" - "e sending an Add TS Response.\n") ); + "e sending an Add TS Response.") ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! } #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId, psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // That done, pack the struct: if ( !wmmTspecPresent ) { @@ -1899,7 +1857,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Del TS frame (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Del TS frame (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1907,7 +1865,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "a Del TS frame (0x%08x).\n") ); + "a Del TS frame (0x%08x).") ); } } else @@ -1917,7 +1875,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a WMM Del TS frame (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a WMM Del TS frame (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -1925,7 +1883,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing" - "a WMM Del TS frame (0x%08x).\n") ); + "a WMM Del TS frame (0x%08x).") ); } } @@ -1947,7 +1905,7 @@ limSendDeltsReqActionFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("Failed to send Del TS (%X)!\n"), + limLog( pMac, LOGE, FL("Failed to send Del TS (%X)!"), nSirStatus ); //Pkt will be freed up by the callback } @@ -1997,7 +1955,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **)&pFrm, sizeof(tDot11fAssocRequest))) { - limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limSendAssocReqMgmtFrame\n") ); + limLog(pMac, LOGE, FL("Unable to PAL allocate memory in limSendAssocReqMgmtFrame") ); return; } @@ -2163,34 +2121,43 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if (psessionEntry->pLimJoinReq->is11Rconnection) { #if defined WLAN_FEATURE_VOWIFI_11R_DEBUG - limLog( pMac, LOG1, FL("mdie = %02x %02x %02x"), + limLog( pMac, LOG1, FL("mdie = %02x %02x %02x"), (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[0], (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[1], (unsigned int)psessionEntry->pLimJoinReq->bssDescription.mdie[2]); #endif - PopulateMDIE( pMac, &pFrm->MobilityDomain, psessionEntry->pLimJoinReq->bssDescription.mdie); + PopulateMDIE( pMac, &pFrm->MobilityDomain, + psessionEntry->pLimJoinReq->bssDescription.mdie); } - else + else { // No 11r IEs dont send any MDIE - limLog( pMac, LOG1, FL("mdie not present")); + limLog( pMac, LOG1, FL("MDIE not present")); } #endif #ifdef FEATURE_WLAN_CCX - // For CCX Associations fill the CCX IEs - if (psessionEntry->isCCXconnection) + /* CCX Version IE will be included in association request + when CCX is enabled on DUT through ini */ + if (psessionEntry->pLimJoinReq->isCCXFeatureIniEnabled) { - PopulateDot11fCCXRadMgmtCap(&pFrm->CCXRadMgmtCap); PopulateDot11fCCXVersion(&pFrm->CCXVersion); } + /* For CCX Associations fill the CCX IEs */ + if (psessionEntry->isCCXconnection && + psessionEntry->pLimJoinReq->isCCXFeatureIniEnabled) + { +#ifndef FEATURE_DISABLE_RM + PopulateDot11fCCXRadMgmtCap(&pFrm->CCXRadMgmtCap); +#endif + } #endif nStatus = dot11fGetPackedAssocRequestSize( pMac, pFrm, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or an Association Request (0x%08x).\n"), + "or an Association Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fAssocRequest ); @@ -2199,7 +2166,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for an Association Re " - "quest(0x%08x).\n"), nStatus ); + "quest(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; @@ -2210,7 +2177,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for an As" - "sociation Request.\n"), nBytes ); + "sociation Request."), nBytes ); psessionEntry->limMlmState = psessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); @@ -2240,7 +2207,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Association Request (%d).\n"), + "tor for an Association Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); palFreeMemory(pMac->hHdd, pFrm); @@ -2255,7 +2222,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a Probe Response (0x%0" - "8x).\n"), + "8x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -2265,11 +2232,11 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a P" - "robe Response (0x%08x).\n") ); + "robe Response (0x%08x).") ); } PELOG1(limLog( pMac, LOG1, FL("*** Sending Association Request length %d" - "to \n"), + "to "), nBytes );) // limPrintMacAddr( pMac, bssid, LOG1 ); @@ -2319,7 +2286,7 @@ limSendAssocReqMgmtFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - limLog( pMac, LOGE, FL("Failed to send Association Request (%X)!\n"), + limLog( pMac, LOGE, FL("Failed to send Association Request (%X)!"), halstatus ); //Pkt will be freed up by the callback palFreeMemory(pMac->hHdd, pFrm); @@ -2497,7 +2464,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, } #ifdef FEATURE_WLAN_CCX - if(psessionEntry->pLimReAssocReq->cckmIE.length) + if (psessionEntry->pLimReAssocReq->cckmIE.length) { PopulateDot11fCCXCckmOpaque( pMac, &( psessionEntry->pLimReAssocReq->cckmIE ), &frm.CCXCckmOpaque ); @@ -2506,13 +2473,21 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, } #ifdef FEATURE_WLAN_CCX + /* CCX Version IE will be included in reassociation request + when CCX is enabled on DUT through ini */ + if (psessionEntry->pLimReAssocReq->isCCXFeatureIniEnabled) + { + PopulateDot11fCCXVersion(&frm.CCXVersion); + } // For CCX Associations fill the CCX IEs - if (psessionEntry->isCCXconnection) + if (psessionEntry->isCCXconnection && + psessionEntry->pLimReAssocReq->isCCXFeatureIniEnabled) { +#ifndef FEATURE_DISABLE_RM PopulateDot11fCCXRadMgmtCap(&frm.CCXRadMgmtCap); - PopulateDot11fCCXVersion(&frm.CCXVersion); +#endif } -#endif //FEATURE_WLAN_CCX +#endif //FEATURE_WLAN_CCX #endif //FEATURE_WLAN_CCX || FEATURE_WLAN_LFR // include WME EDCA IE as well @@ -2545,14 +2520,14 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, { tsrsIE.rates[0] = TSRS_11AG_RATE_6MBPS; } - else + else { tsrsIE.rates[0] = TSRS_11B_RATE_5_5MBPS; } PopulateDot11TSRSIE(pMac,&tsrsIE, &frm.CCXTrafStrmRateSet, sizeof(tANI_U8)); } } -#endif +#endif } if ( psessionEntry->htCapability && @@ -2562,7 +2537,11 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, } #if defined WLAN_FEATURE_VOWIFI_11R - if ( psessionEntry->pLimReAssocReq->bssDescription.mdiePresent && (0 == pMac->ft.ftSmeContext.reassoc_ft_ies_length) ) + if ( psessionEntry->pLimReAssocReq->bssDescription.mdiePresent && (0 == pMac->ft.ftSmeContext.reassoc_ft_ies_length) +#if defined FEATURE_WLAN_CCX + && !psessionEntry->isCCXconnection +#endif + ) { PopulateMDIE( pMac, &frm.MobilityDomain, psessionEntry->pLimReAssocReq->bssDescription.mdie); } @@ -2572,7 +2551,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Re-Association Request (0x%08x).\n"), + "or a Re-Association Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fReAssocRequest ); @@ -2581,7 +2560,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Re-Association Re " - "quest(0x%08x).\n"), nStatus ); + "quest(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; @@ -2606,7 +2585,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, psessionEntry->limMlmState = psessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Re-As" - "sociation Request.\n"), nBytes ); + "sociation Request."), nBytes ); goto end; } @@ -2623,7 +2602,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Association Request (%d).\n"), + "tor for an Association Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); goto end; @@ -2637,7 +2616,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a Re-Association Reque" - "st (0x%08x).\n"), + "st (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); goto end; @@ -2645,11 +2624,11 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a R" - "e-Association Request (0x%08x).\n") ); + "e-Association Request (0x%08x).") ); } PELOG3(limLog( pMac, LOG3, - FL("*** Sending Re-Association Request length %d %d to \n"), + FL("*** Sending Re-Association Request length %d %d to "), nBytes, nPayload );) if( psessionEntry->assocReq != NULL ) { @@ -2736,7 +2715,7 @@ limSendReassocReqWithFTIEsMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send Re-Association Request" - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback goto end; @@ -2773,7 +2752,7 @@ void limSendRetryReassocReqFrame(tpAniSirGlobal pMac, // Could not start reassoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not start Reassociation failure timer\n")); + FL("could not start Reassociation failure timer")); // Return Reassoc confirm with // Resources Unavailable mlmReassocCnf.resultCode = eSIR_SME_RESOURCES_UNAVAILABLE; @@ -2974,7 +2953,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( psessionEntry->vhtCapability && psessionEntry->vhtCapabilityPresentInBeacon) { - limLog( pMac, LOGW, FL("Populate VHT IEs in Re-Assoc Request\n")); + limLog( pMac, LOGW, FL("Populate VHT IEs in Re-Assoc Request")); PopulateDot11fVHTCaps( pMac, &frm.VHTCaps ); PopulateDot11fExtCap( pMac, &frm.ExtCap); } @@ -2984,7 +2963,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Re-Association Request (0x%08x).\n"), + "or a Re-Association Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fReAssocRequest ); @@ -2993,7 +2972,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Re-Association Re " - "quest(0x%08x).\n"), nStatus ); + "quest(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ) + nAddIELen; @@ -3006,7 +2985,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, psessionEntry->limMlmState = psessionEntry->limPrevMlmState; MTRACE(macTrace(pMac, TRACE_CODE_MLM_STATE, psessionEntry->peSessionId, psessionEntry->limMlmState)); limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Re-As" - "sociation Request.\n"), nBytes ); + "sociation Request."), nBytes ); goto end; } @@ -3020,7 +2999,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for an Association Request (%d).\n"), + "tor for an Association Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); goto end; @@ -3034,7 +3013,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGE, FL("Failed to pack a Re-Association Reque" - "st (0x%08x).\n"), + "st (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); goto end; @@ -3042,11 +3021,11 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a R" - "e-Association Request (0x%08x).\n") ); + "e-Association Request (0x%08x).") ); } PELOG1(limLog( pMac, LOG1, FL("*** Sending Re-Association Request length %d" - "to \n"), + "to "), nBytes );) if( psessionEntry->assocReq != NULL ) @@ -3096,7 +3075,7 @@ limSendReassocReqMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send Re-Association Request" - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback goto end; @@ -3189,12 +3168,12 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, if (0 != pMac->ft.ftPEContext.pFTPreAuthReq->ft_ies_length) { frameLen += pMac->ft.ftPEContext.pFTPreAuthReq->ft_ies_length; - limLog(pMac, LOG3, FL("Auth frame, FTIES length added=%d\n"), + limLog(pMac, LOG3, FL("Auth frame, FTIES length added=%d"), pMac->ft.ftPEContext.pFTPreAuthReq->ft_ies_length); } else { - limLog(pMac, LOG3, FL("Auth frame, Does not contain FTIES!!!\n")); + limLog(pMac, LOG3, FL("Auth frame, Does not contain FTIES!!!")); frameLen += (2+SIR_MDIE_SIZE); } } @@ -3273,7 +3252,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { // Log error - limLog(pMac, LOGP, FL("call to bufAlloc failed for AUTH frame\n")); + limLog(pMac, LOGP, FL("call to bufAlloc failed for AUTH frame")); return; } @@ -3308,7 +3287,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, palCopyMemory( pMac->hHdd, pBody, (tANI_U8 *) pAuthFrameBody, bodyLen); PELOG1(limLog(pMac, LOG1, - FL("*** Sending Auth seq# 3 status %d (%d) to\n"), + FL("*** Sending Auth seq# 3 status %d (%d) to"), pAuthFrameBody->authStatusCode, (pAuthFrameBody->authStatusCode == eSIR_MAC_SUCCESS_STATUS)); @@ -3327,8 +3306,8 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, *((tANI_U16 *)(pBody)) = sirSwapU16ifNeeded(pAuthFrameBody->authStatusCode); pBody += sizeof(tANI_U16); bodyLen -= sizeof(tANI_U16); - if ( bodyLen < sizeof (pAuthFrameBody->type) + sizeof (pAuthFrameBody->length) + sizeof (pAuthFrameBody->challengeText)) - palCopyMemory( pMac->hHdd, pBody, (tANI_U8 *) &pAuthFrameBody->type, bodyLen); + + palCopyMemory( pMac->hHdd, pBody, (tANI_U8 *) &pAuthFrameBody->type, bodyLen); #if defined WLAN_FEATURE_VOWIFI_11R if ((pAuthFrameBody->authAlgoNumber == eSIR_FT_AUTH) && @@ -3382,7 +3361,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || ( psessionEntry->pePersona == VOS_P2P_GO_MODE) #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - || ((NULL != pMac->ft.ftPEContext.pFTPreAuthReq) + || ((NULL != pMac->ft.ftPEContext.pFTPreAuthReq) && ( SIR_BAND_5_GHZ == limGetRFBand(pMac->ft.ftPEContext.pFTPreAuthReq->preAuthchannelNum))) #endif ) @@ -3404,7 +3383,7 @@ limSendAuthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog(pMac, LOGE, - FL("*** Could not send Auth frame, retCode=%X ***\n"), + FL("*** Could not send Auth frame, retCode=%X ***"), halstatus); //Pkt will be freed up by the callback @@ -3433,7 +3412,7 @@ eHalStatus limSendDeauthCnf(tpAniSirGlobal pMac) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) mlmDeauthCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -3491,7 +3470,7 @@ eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac) { PELOGE(limLog(pMac, LOGE, - FL("session does not exist for given sessionId\n"));) + FL("session does not exist for given sessionId"));) mlmDisassocCnf.resultCode = eSIR_SME_INVALID_PARAMETERS; goto end; } @@ -3512,19 +3491,19 @@ eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac) #ifdef WLAN_FEATURE_VOWIFI_11R if ( (psessionEntry->limSystemRole == eLIM_STA_ROLE ) && - ( + ( #ifdef FEATURE_WLAN_CCX - (psessionEntry->isCCXconnection ) || + (psessionEntry->isCCXconnection ) || #endif #ifdef FEATURE_WLAN_LFR (psessionEntry->isFastRoamIniFeatureEnabled ) || #endif (psessionEntry->is11Rconnection )) && - (pMlmDisassocReq->reasonCode != + (pMlmDisassocReq->reasonCode != eSIR_MAC_DISASSOC_DUE_TO_FTHANDOFF_REASON)) { - PELOGE(limLog(pMac, LOGE, - FL("FT Preauth Session (%p,%d) Cleanup\n"), + PELOGE(limLog(pMac, LOGE, + FL("FT Preauth Session (%p,%d) Cleanup"), psessionEntry, psessionEntry->peSessionId);); limFTCleanup(pMac); } @@ -3538,7 +3517,7 @@ eHalStatus limSendDisassocCnf(tpAniSirGlobal pMac) #ifdef FEATURE_WLAN_LFR " isLFR %d" #endif - " is11r %d reason %d\n"), + " is11r %d reason %d"), psessionEntry->limSystemRole, #ifdef FEATURE_WLAN_CCX psessionEntry->isCCXconnection, @@ -3637,7 +3616,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Disassociation (0x%08x).\n"), + "or a Disassociation (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fDisassociation ); @@ -3646,7 +3625,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Disassociation " - "(0x%08x).\n"), nStatus ); + "(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -3657,7 +3636,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Dis" - "association.\n"), nBytes ); + "association."), nBytes ); return; } @@ -3670,7 +3649,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Disassociation (%d).\n"), + "tor for a Disassociation (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -3682,19 +3661,12 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, // Prepare the BSSID sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackDisassociation( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Disassociation (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Disassociation (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -3703,11 +3675,11 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a D" - "isassociation (0x%08x).\n") ); + "isassociation (0x%08x).") ); } PELOG1(limLog( pMac, LOG1, FL("*** Sending Disassociation frame with rea" - "son %d to\n"), nReason ); + "son %d to"), nReason ); limPrintMacAddr( pMac, pMacHdr->da, LOG1 );) if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -3741,14 +3713,14 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, != TX_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to change Disassoc ack Timer val\n")); + FL("Unable to change Disassoc ack Timer val")); return; } else if(TX_SUCCESS != tx_timer_activate( &pMac->lim.limTimers.gLimDisassocAckTimer)) { limLog(pMac, LOGP, - FL("Unable to activate Disassoc ack Timer\n")); + FL("Unable to activate Disassoc ack Timer")); limDeactivateAndChangeTimer(pMac, eLIM_DISASSOC_ACK_TIMER); return; } @@ -3764,7 +3736,7 @@ limSendDisassocMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send Disassociation " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return; @@ -3820,7 +3792,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a De-Authentication (0x%08x).\n"), + "or a De-Authentication (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fDeAuth ); @@ -3829,7 +3801,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a De-Authentication " - "(0x%08x).\n"), nStatus ); + "(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -3840,7 +3812,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a De-" - "Authentication.\n"), nBytes ); + "Authentication."), nBytes ); return; } @@ -3853,7 +3825,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a De-Authentication (%d).\n"), + "tor for a De-Authentication (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -3865,19 +3837,12 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, // Prepare the BSSID sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackDeAuth( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a DeAuthentication (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a DeAuthentication (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); @@ -3886,11 +3851,11 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a D" - "e-Authentication (0x%08x).\n") ); + "e-Authentication (0x%08x).") ); } PELOG1(limLog( pMac, LOG1, FL("*** Sending De-Authentication frame with rea" - "son %d to\n"), nReason ); + "son %d to"), nReason ); limPrintMacAddr( pMac, pMacHdr->da, LOG1 );) if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -3922,7 +3887,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send De-Authentication " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback limTxComplete @@ -3940,14 +3905,14 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, != TX_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to change Deauth ack Timer val\n")); + FL("Unable to change Deauth ack Timer val")); return; } else if(TX_SUCCESS != tx_timer_activate( &pMac->lim.limTimers.gLimDeauthAckTimer)) { limLog(pMac, LOGP, - FL("Unable to activate Deauth ack Timer\n")); + FL("Unable to activate Deauth ack Timer")); limDeactivateAndChangeTimer(pMac, eLIM_DEAUTH_ACK_TIMER); return; } @@ -3979,7 +3944,7 @@ limSendDeauthMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send De-Authentication " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return; @@ -4041,7 +4006,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, break; default: limLog( pMac, LOGE, FL("Unknown measurement type %d in limSen" - "dMeasReportFrame.\n"), + "dMeasReportFrame."), pMeasReqFrame->measReqIE.measType ); return eSIR_FAILURE; } @@ -4052,7 +4017,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Measurement Report (0x%08x).\n"), + "or a Measurement Report (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fMeasurementReport ); @@ -4061,7 +4026,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Measurement Rep" - "ort (0x%08x).\n"), nStatus ); + "ort (0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4070,7 +4035,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a De-" - "Authentication.\n"), nBytes ); + "Authentication."), nBytes ); return eSIR_FAILURE; } @@ -4083,7 +4048,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Measurement Report (%d).\n"), + "tor for a Measurement Report (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4096,25 +4061,18 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to retrieve WNI_CFG_BSSID from" - " CFG (%d).\n"), + " CFG (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... } -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackMeasurementReport( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Measurement Report (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Measurement Report (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4122,7 +4080,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a M" - "easurement Report (0x%08x).\n") ); + "easurement Report (0x%08x).") ); } halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, @@ -4133,7 +4091,7 @@ limSendMeasReportFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a Measurement Report " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; // just allocated... @@ -4178,7 +4136,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a TPC Request (0x%08x).\n"), + "or a TPC Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fTPCRequest ); @@ -4187,7 +4145,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a TPC Request (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4196,7 +4154,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Request.\n"), nBytes ); + " Request."), nBytes ); return; } @@ -4209,7 +4167,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a TPC Request (%d).\n"), + "tor for a TPC Request (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // just allocated... @@ -4222,25 +4180,18 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to retrieve WNI_CFG_BSSID from" - " CFG (%d).\n"), + " CFG (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // just allocated... } -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackTPCRequest( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a TPC Request (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a TPC Request (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return; // allocated! @@ -4248,7 +4199,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a T" - "PC Request (0x%08x).\n") ); + "PC Request (0x%08x).") ); } halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, @@ -4259,7 +4210,7 @@ limSendTpcRequestFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a TPC Request " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return; @@ -4312,7 +4263,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a TPC Report (0x%08x).\n"), + "or a TPC Report (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fTPCReport ); @@ -4321,7 +4272,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a TPC Report (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4330,7 +4281,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Report.\n"), nBytes ); + " Report."), nBytes ); return eSIR_FAILURE; } @@ -4343,7 +4294,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a TPC Report (%d).\n"), + "tor for a TPC Report (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4356,25 +4307,18 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to retrieve WNI_CFG_BSSID from" - " CFG (%d).\n"), + " CFG (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... } -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackTPCReport( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a TPC Report (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a TPC Report (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4382,7 +4326,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a T" - "PC Report (0x%08x).\n") ); + "PC Report (0x%08x).") ); } @@ -4394,7 +4338,7 @@ limSendTpcReportFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a TPC Report " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; // just allocated... @@ -4455,7 +4399,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Channel Switch (0x%08x).\n"), + "or a Channel Switch (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fChannelSwitch ); @@ -4464,7 +4408,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Channel Switch (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4473,7 +4417,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Report.\n"), nBytes ); + " Report."), nBytes ); return eSIR_FAILURE; } @@ -4491,7 +4435,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Channel Switch (%d).\n"), + "tor for a Channel Switch (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4505,26 +4449,18 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to retrieve WNI_CFG_BSSID from" - " CFG (%d).\n"), + " CFG (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... } #endif - -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - nStatus = dot11fPackChannelSwitch( pMac, &frm, pFrame + sizeof(tSirMacMgmtHdr), nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4532,7 +4468,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a C" - "hannel Switch (0x%08x).\n") ); + "hannel Switch (0x%08x).") ); } if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -4550,7 +4486,7 @@ limSendChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a Channel Switch " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; @@ -4590,7 +4526,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Operating Mode (0x%08x).\n"), + "or a Operating Mode (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fOperatingMode); @@ -4599,7 +4535,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Operating Mode (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4608,7 +4544,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Operating Mode" - " Report.\n"), nBytes ); + " Report."), nBytes ); return eSIR_FAILURE; } @@ -4631,7 +4567,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Operating Mode (%d).\n"), + "tor for a Operating Mode (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4641,7 +4577,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Operating Mode (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Operating Mode (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4649,7 +4585,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a Operating Mode" - " (0x%08x).\n") ); + " (0x%08x).") ); } if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || @@ -4666,7 +4602,7 @@ limSendVHTOpmodeNotificationFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a Channel Switch " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; @@ -4730,7 +4666,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Channel Switch (0x%08x).\n"), + "or a Channel Switch (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fChannelSwitch ); @@ -4739,7 +4675,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Channel Switch (0x" - "%08x).\n"), nStatus ); + "%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -4748,7 +4684,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a TPC" - " Report.\n"), nBytes ); + " Report."), nBytes ); return eSIR_FAILURE; } // Paranoia: @@ -4765,7 +4701,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( eSIR_SUCCESS != nSirStatus ) { limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" - "tor for a Channel Switch (%d).\n"), + "tor for a Channel Switch (%d)."), nSirStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // just allocated... @@ -4775,7 +4711,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, nPayload, &nPayload ); if ( DOT11F_FAILED( nStatus ) ) { - limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x).\n"), + limLog( pMac, LOGE, FL("Failed to pack a Channel Switch (0x%08x)."), nStatus ); palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); return eSIR_FAILURE; // allocated! @@ -4783,7 +4719,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, else if ( DOT11F_WARNED( nStatus ) ) { limLog( pMac, LOGW, FL("There were warnings while packing a C" - "hannel Switch (0x%08x).\n") ); + "hannel Switch (0x%08x).") ); } if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -4801,7 +4737,7 @@ limSendVHTChannelSwitchMgmtFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGE, FL("Failed to send a Channel Switch " - "(%X)!\n"), + "(%X)!"), nSirStatus ); //Pkt will be freed up by the callback return eSIR_FAILURE; @@ -4881,7 +4817,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "Failed to calculate the packed size for " - "an ADDBA Request (0x%08x).\n"), + "an ADDBA Request (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: @@ -4891,7 +4827,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "There were warnings while calculating" - "the packed size for an ADDBA Req (0x%08x).\n"), + "the packed size for an ADDBA Req (0x%08x)."), nStatus ); } @@ -4908,7 +4844,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, { // Log error limLog( pMac, LOGP, - FL("palPktAlloc FAILED! Length [%d], Status [%d]\n"), + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), frameLen, halStatus ); @@ -4939,7 +4875,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, { limLog( pMac, LOGP, FL( "Failed to retrieve WNI_CFG_BSSID while" - "sending an ACTION Frame\n" )); + "sending an ACTION Frame" )); // FIXME - Need to convert to tSirRetStatus statusCode = eSIR_FAILURE; @@ -4948,13 +4884,6 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, #endif//TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackAddBAReq( pMac, &frmAddBAReq, @@ -4965,7 +4894,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an ADDBA Req (0x%08x).\n" ), + FL( "Failed to pack an ADDBA Req (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -4975,11 +4904,11 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing an ADDBA Req (0x%08x).\n" )); + FL( "There were warnings while packing an ADDBA Req (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending an ADDBA REQ to \n" )); + FL( "Sending an ADDBA REQ to " )); limPrintMacAddr( pMac, pMlmAddBAReq->peerMacAddr, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5001,7 +4930,7 @@ tSirRetStatus limSendAddBAReq( tpAniSirGlobal pMac, pAddBAReqBuffer, txFlag ))) { limLog( pMac, LOGE, - FL( "halTxFrame FAILED! Status [%d]\n"), + FL( "halTxFrame FAILED! Status [%d]"), halStatus ); // FIXME - Need to convert eHalStatus to tSirRetStatus @@ -5053,7 +4982,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, if(NULL == psessionEntry) { - PELOGE(limLog(pMac, LOGE, FL("Session entry is NULL!!!\n"));) + PELOGE(limLog(pMac, LOGE, FL("Session entry is NULL!!!"));) return eSIR_FAILURE; } @@ -5074,6 +5003,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, frmAddBARsp.AddBAParameterSet.tid = pMlmAddBARsp->baTID; frmAddBARsp.AddBAParameterSet.policy = pMlmAddBARsp->baPolicy; frmAddBARsp.AddBAParameterSet.bufferSize = pMlmAddBARsp->baBufferSize; + frmAddBARsp.AddBAParameterSet.amsduSupported = psessionEntry->amsduSupportedInBA; // BA timeout // 0 - indicates no BA timeout @@ -5085,7 +5015,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "Failed to calculate the packed size for " - "an ADDBA Response (0x%08x).\n"), + "an ADDBA Response (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: @@ -5095,7 +5025,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "There were warnings while calculating" - "the packed size for an ADDBA Rsp (0x%08x).\n"), + "the packed size for an ADDBA Rsp (0x%08x)."), nStatus ); } @@ -5112,7 +5042,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, { // Log error limLog( pMac, LOGP, - FL("palPktAlloc FAILED! Length [%d], Status [%d]\n"), + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), frameLen, halStatus ); @@ -5144,7 +5074,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, { limLog( pMac, LOGP, FL( "Failed to retrieve WNI_CFG_BSSID while" - "sending an ACTION Frame\n" )); + "sending an ACTION Frame" )); // FIXME - Need to convert to tSirRetStatus statusCode = eSIR_FAILURE; @@ -5153,13 +5083,6 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, #endif // TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackAddBARsp( pMac, &frmAddBARsp, @@ -5170,7 +5093,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an ADDBA Rsp (0x%08x).\n" ), + FL( "Failed to pack an ADDBA Rsp (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5180,11 +5103,11 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing an ADDBA Rsp (0x%08x).\n" )); + FL( "There were warnings while packing an ADDBA Rsp (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending an ADDBA RSP to \n" )); + FL( "Sending an ADDBA RSP to " )); limPrintMacAddr( pMac, pMlmAddBARsp->peerMacAddr, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5206,7 +5129,7 @@ tSirRetStatus limSendAddBARsp( tpAniSirGlobal pMac, pAddBARspBuffer, txFlag ))) { limLog( pMac, LOGE, - FL( "halTxFrame FAILED! Status [%d]\n" ), + FL( "halTxFrame FAILED! Status [%d]" ), halStatus ); // FIXME - HAL error codes are different from PE error @@ -5287,7 +5210,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "Failed to calculate the packed size for " - "an DELBA Indication (0x%08x).\n"), + "an DELBA Indication (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: @@ -5297,7 +5220,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL( "There were warnings while calculating" - "the packed size for an DELBA Ind (0x%08x).\n"), + "the packed size for an DELBA Ind (0x%08x)."), nStatus ); } @@ -5314,7 +5237,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, { // Log error limLog( pMac, LOGP, - FL("palPktAlloc FAILED! Length [%d], Status [%d]\n"), + FL("palPktAlloc FAILED! Length [%d], Status [%d]"), frameLen, halStatus ); @@ -5345,7 +5268,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, { limLog( pMac, LOGP, FL( "Failed to retrieve WNI_CFG_BSSID while" - "sending an ACTION Frame\n" )); + "sending an ACTION Frame" )); // FIXME - Need to convert to tSirRetStatus statusCode = eSIR_FAILURE; @@ -5354,13 +5277,6 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, #endif //TO SUPPORT BT-AMP sirCopyMacAddr(pMacHdr->bssId,psessionEntry->bssId); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackDelBAInd( pMac, &frmDelBAInd, @@ -5371,7 +5287,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an DELBA Ind (0x%08x).\n" ), + FL( "Failed to pack an DELBA Ind (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5381,11 +5297,11 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing an DELBA Ind (0x%08x).\n" )); + FL( "There were warnings while packing an DELBA Ind (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending a DELBA IND to \n" )); + FL( "Sending a DELBA IND to " )); limPrintMacAddr( pMac, pMlmDelBAReq->peerMacAddr, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5406,7 +5322,7 @@ tSirRetStatus limSendDelBAInd( tpAniSirGlobal pMac, limTxComplete, pDelBAIndBuffer, txFlag ))) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]\n" ), halStatus );) + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halStatus );) statusCode = eSIR_FAILURE; //Pkt will be freed up by the callback return statusCode; @@ -5463,7 +5379,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, if ( psessionEntry == NULL ) { - limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Neighbor Report request action frame\n") ); + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Neighbor Report request action frame") ); return eSIR_FAILURE; } palZeroMemory( pMac->hHdd, ( tANI_U8* )&frm, sizeof( frm ) ); @@ -5482,7 +5398,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Neighbor Report Request(0x%08x).\n"), + "or a Neighbor Report Request(0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fNeighborReportRequest ); @@ -5491,7 +5407,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Neighbor Rep" - "ort Request(0x%08x).\n"), nStatus ); + "ort Request(0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -5500,7 +5416,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Neighbor " - "Report Request.\n"), nBytes ); + "Report Request."), nBytes ); return eSIR_FAILURE; } @@ -5521,13 +5437,6 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackNeighborReportRequest( pMac, &frm, @@ -5538,7 +5447,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an Neighbor Report Request (0x%08x).\n" ), + FL( "Failed to pack an Neighbor Report Request (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5548,11 +5457,11 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing Neighbor Report Request (0x%08x).\n" )); + FL( "There were warnings while packing Neighbor Report Request (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending a Neighbor Report Request to \n" )); + FL( "Sending a Neighbor Report Request to " )); limPrintMacAddr( pMac, peer, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5573,7 +5482,7 @@ limSendNeighborReportRequestFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ))) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]\n" ), halstatus );) + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) statusCode = eSIR_FAILURE; //Pkt will be freed up by the callback return statusCode; @@ -5623,7 +5532,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, if ( psessionEntry == NULL ) { - limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Link Report action frame\n") ); + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Link Report action frame") ); return eSIR_FAILURE; } @@ -5653,7 +5562,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Link Report (0x%08x).\n"), + "or a Link Report (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fLinkMeasurementReport ); @@ -5662,7 +5571,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Link Rep" - "ort (0x%08x).\n"), nStatus ); + "ort (0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -5671,7 +5580,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Link " - "Report.\n"), nBytes ); + "Report."), nBytes ); return eSIR_FAILURE; } @@ -5692,13 +5601,6 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackLinkMeasurementReport( pMac, &frm, @@ -5709,7 +5611,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an Link Report (0x%08x).\n" ), + FL( "Failed to pack an Link Report (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5719,11 +5621,11 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing Link Report (0x%08x).\n" )); + FL( "There were warnings while packing Link Report (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending a Link Report to \n" )); + FL( "Sending a Link Report to " )); limPrintMacAddr( pMac, peer, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5744,7 +5646,7 @@ limSendLinkReportActionFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ))) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]\n" ), halstatus );) + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) statusCode = eSIR_FAILURE; //Pkt will be freed up by the callback return statusCode; @@ -5800,13 +5702,13 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, tDot11fRadioMeasurementReport *frm = vos_mem_malloc(sizeof(tDot11fRadioMeasurementReport)); if (!frm) { - limLog( pMac, LOGE, FL("Not enough memory to allocate tDot11fRadioMeasurementReport\n") ); + limLog( pMac, LOGE, FL("Not enough memory to allocate tDot11fRadioMeasurementReport") ); return eSIR_FAILURE; } if ( psessionEntry == NULL ) { - limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Beacon Report action frame\n") ); + limLog( pMac, LOGE, FL("(psession == NULL) in Request to send Beacon Report action frame") ); vos_mem_free(frm); return eSIR_FAILURE; } @@ -5843,7 +5745,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, if ( DOT11F_FAILED( nStatus ) ) { limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a Radio Measure Report (0x%08x).\n"), + "or a Radio Measure Report (0x%08x)."), nStatus ); // We'll fall back on the worst case scenario: nPayload = sizeof( tDot11fLinkMeasurementReport ); @@ -5854,7 +5756,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, { limLog( pMac, LOGW, FL("There were warnings while calculating" "the packed size for a Radio Measure Rep" - "ort (0x%08x).\n"), nStatus ); + "ort (0x%08x)."), nStatus ); } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); @@ -5863,7 +5765,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a Radio Measure " - "Report.\n"), nBytes ); + "Report."), nBytes ); vos_mem_free(frm); return eSIR_FAILURE; } @@ -5885,13 +5787,6 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); -#ifdef WLAN_FEATURE_11W - if ( psessionEntry->limRmfEnabled ) - { - pMacHdr->fc.wep = 1; - } -#endif - // Now, we're ready to "pack" the frames nStatus = dot11fPackRadioMeasurementReport( pMac, frm, @@ -5902,7 +5797,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, if( DOT11F_FAILED( nStatus )) { limLog( pMac, LOGE, - FL( "Failed to pack an Radio Measure Report (0x%08x).\n" ), + FL( "Failed to pack an Radio Measure Report (0x%08x)." ), nStatus ); // FIXME - Need to convert to tSirRetStatus @@ -5912,11 +5807,11 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, else if( DOT11F_WARNED( nStatus )) { limLog( pMac, LOGW, - FL( "There were warnings while packing Radio Measure Report (0x%08x).\n" )); + FL( "There were warnings while packing Radio Measure Report (0x%08x)." )); } limLog( pMac, LOGW, - FL( "Sending a Radio Measure Report to \n" )); + FL( "Sending a Radio Measure Report to " )); limPrintMacAddr( pMac, peer, LOGW ); if( ( SIR_BAND_5_GHZ == limGetRFBand(psessionEntry->currentOperChannel)) @@ -5937,7 +5832,7 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, limTxComplete, pFrame, txFlag ))) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]\n" ), halstatus );) + PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) statusCode = eSIR_FAILURE; //Pkt will be freed up by the callback vos_mem_free(frm); @@ -5965,146 +5860,87 @@ limSendRadioMeasureReportActionFrame(tpAniSirGlobal pMac, * * \param pMac The global tpAniSirGlobal object * - * \param transId Transaction identifier received in SA query request action frame - * - * \param peer The Mac address of the AP to which this action frame is addressed + * \param peer The Mac address of the AP to which this action frame is +addressed * - * \param psessionEntry The PE session entry + * \param transId Transaction identifier received in SA query request action +frame * * \return eSIR_SUCCESS if setup completes successfully * eSIR_FAILURE is some problem is encountered */ -tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac, tANI_U8 *transId, +tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac, tANI_U16 transId, tSirMacAddr peer,tpPESession psessionEntry) { - tDot11fSaQueryRsp frm; // SA query reponse action frame + tDot11wSaQueryRsp frm; // SA query reponse action frame tANI_U8 *pFrame; tSirRetStatus nSirStatus; tpSirMacMgmtHdr pMacHdr; - tANI_U32 nBytes, nPayload, nStatus; + tANI_U32 nBytes, nPayload; void *pPacket; eHalStatus halstatus; - tANI_U8 txFlag = 0; + // Local variables used to dump prepared SA query response frame + tANI_U8 *pDump; + tANI_U16 dumpCount; + tANI_U8 txFlag = 0; + //tANI_U16 nBytes palZeroMemory( pMac->hHdd, ( tANI_U8* )&frm, sizeof( frm ) ); - frm.Category.category = SIR_MAC_ACTION_SA_QUERY; - /*11w action field is : + frm.category = SIR_MAC_ACTION_SA_QUERY; + /*11w action fiedl is : action: 0 --> SA query request action frame action: 1 --> SA query response action frame */ - frm.Action.action = SIR_MAC_SA_QUERY_RSP; - /*11w SA query response transId is same as + frm.action = 1; + /*11w Draft9.0 SA query response transId is same as SA query request transId*/ - vos_mem_copy( &frm.TransactionId.transId[0], &transId[0], 2 ); - - nStatus = dot11fGetPackedSaQueryRspSize(pMac, &frm, &nPayload); - if ( DOT11F_FAILED( nStatus ) ) - { - limLog( pMac, LOGP, FL("Failed to calculate the packed size f" - "or a SA Query Response (0x%08x)."), - nStatus ); - // We'll fall back on the worst case scenario: - nPayload = sizeof( tDot11fSaQueryRsp ); - } - else if ( DOT11F_WARNED( nStatus ) ) - { - limLog( pMac, LOGW, FL("There were warnings while calculating" - "the packed size for an SA Query Response" - " (0x%08x)."), nStatus ); - } + frm.transId = transId; + nPayload = sizeof(tDot11wSaQueryRsp); nBytes = nPayload + sizeof( tSirMacMgmtHdr ); halstatus = palPktAlloc( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, nBytes, ( void** ) &pFrame, ( void** ) &pPacket ); if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { limLog( pMac, LOGP, FL("Failed to allocate %d bytes for a SA query response" - " action frame\n"), nBytes ); + " action frame"), nBytes ); return eSIR_FAILURE; } // Paranoia: palZeroMemory( pMac->hHdd, pFrame, nBytes ); - // Copy necessary info to BD - nSirStatus = limPopulateMacHeader( pMac, - pFrame, - SIR_MAC_MGMT_FRAME, - SIR_MAC_MGMT_ACTION, - peer, psessionEntry->selfMacAddr ); + // Next, we fill out the buffer descriptor: + nSirStatus = limPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_ACTION, peer,psessionEntry->selfMacAddr ); if ( eSIR_SUCCESS != nSirStatus ) - goto returnAfterError; - - // Update A3 with the BSSID - pMacHdr = ( tpSirMacMgmtHdr ) pFrame; - - sirCopyMacAddr( pMacHdr->bssId, psessionEntry->bssId ); - - // Since this is a SA Query Response, set the "protect" (aka WEP) bit - // in the FC - if ( psessionEntry->limRmfEnabled ) { - pMacHdr->fc.wep = 1; + limLog( pMac, LOGE, FL("Failed to populate the buffer descrip" + "tor for a TPC Report (%d).\n"), + nSirStatus ); + palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); + return eSIR_FAILURE; // just allocated... } - // Pack 11w SA query response frame - nStatus = dot11fPackSaQueryRsp( pMac, - &frm, - pFrame + sizeof( tSirMacMgmtHdr ), - nPayload, - &nPayload ); - - if ( DOT11F_FAILED( nStatus )) - { - limLog( pMac, LOGE, - FL( "Failed to pack an SA Query Response (0x%08x)." ), - nStatus ); - // FIXME - Need to convert to tSirRetStatus - nSirStatus = eSIR_FAILURE; - goto returnAfterError; - } - else if ( DOT11F_WARNED( nStatus )) - { - limLog( pMac, LOGW, - FL( "There were warnings while packing SA Query Response (0x%08x)." ), - nStatus); - } - - limLog( pMac, LOG1, - FL( "Sending a SA Query Response to " )); - limPrintMacAddr( pMac, peer, LOGW ); + pMacHdr = ( tpSirMacMgmtHdr ) pFrame; - if ( ( SIR_BAND_5_GHZ == limGetRFBand( psessionEntry->currentOperChannel ) ) -#ifdef WLAN_FEATURE_P2P - || ( psessionEntry->pePersona == VOS_P2P_CLIENT_MODE ) || - ( psessionEntry->pePersona == VOS_P2P_GO_MODE ) -#endif - ) - { - txFlag |= HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME; - } + // Pack 11w SA query response frame + DOT11F_MEMCPY(pMac, (tANI_U8 *)(pFrame + sizeof(tSirMacMgmtHdr)),(tANI_U8 *)&frm, nPayload); + pDump = (tANI_U8 *) pFrame; - halstatus = halTxFrame( pMac, - pPacket, - (tANI_U16) nBytes, - HAL_TXRX_FRM_802_11_MGMT, - ANI_TXDIR_TODS, - 7,//SMAC_SWBD_TX_TID_MGMT_HIGH, - limTxComplete, - pFrame, txFlag ); - if ( eHAL_STATUS_SUCCESS != halstatus ) + halstatus = halTxFrame( pMac, pPacket, ( tANI_U16 ) nBytes, + HAL_TXRX_FRM_802_11_MGMT, + ANI_TXDIR_TODS, + 7,//SMAC_SWBD_TX_TID_MGMT_HIGH, + limTxComplete, pFrame,txFlag); + if ( ! HAL_STATUS_SUCCESS ( halstatus ) ) { - PELOGE(limLog( pMac, LOGE, FL( "halTxFrame FAILED! Status [%d]" ), halstatus );) - nSirStatus = eSIR_FAILURE; - //Pkt will be freed up by the callback - return nSirStatus; - } - else { - return eSIR_SUCCESS; + limLog( pMac, LOGE, FL("Failed to send a SA Query resp frame " + "(%X)!\n"),halstatus ); + //Pkt will be freed up by the callback + return eSIR_FAILURE; // just allocated... } -returnAfterError: - palPktFree( pMac->hHdd, HAL_TXRX_FRM_802_11_MGMT, ( void* ) pFrame, ( void* ) pPacket ); - return nSirStatus; -} // End limSendSaQueryResponseFrame + return eSIR_SUCCESS; +} #endif diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.c index 4d99aad5792..f224661513f 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.c @@ -74,7 +74,6 @@ static tBeaconFilterIe beaconFilterTable[] = { {SIR_MAC_EDCA_PARAM_SET_EID, 0, {0, 0, EDCA_FILTER_MASK, 0}}, {SIR_MAC_QOS_CAPABILITY_EID, 0, {0, 0, QOS_FILTER_MASK, 0}}, {SIR_MAC_CHNL_SWITCH_ANN_EID, 1, {0, 0, 0, 0}}, - {SIR_MAC_QUIET_EID, 1, {0, 0, 0, 0}}, {SIR_MAC_HT_INFO_EID, 0, {0, 0, HT_BYTE0_FILTER_MASK, 0}}, {SIR_MAC_HT_INFO_EID, 0, {2, 0, HT_BYTE2_FILTER_MASK, 0}}, {SIR_MAC_HT_INFO_EID, 0, {5, 0, HT_BYTE5_FILTER_MASK, 0}} @@ -118,7 +117,7 @@ tSirRetStatus limSendCFParams(tpAniSirGlobal pMac, tANI_U8 bssIdx, tANI_U8 cfpCo sizeof( tUpdateCFParams ))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Update CF Params\n" )); + FL( "Unable to PAL allocate memory during Update CF Params" )); retCode = eSIR_MEM_ALLOC_FAILED; goto returnFailure; } @@ -138,7 +137,7 @@ tSirRetStatus limSendCFParams(tpAniSirGlobal pMac, tANI_U8 bssIdx, tANI_U8 cfpCo { palFreeMemory(pMac->hHdd, pCFParams); limLog( pMac, LOGP, - FL("Posting WDA_UPDATE_CF_IND to WDA failed, reason=%X\n"), + FL("Posting WDA_UPDATE_CF_IND to WDA failed, reason=%X"), retCode ); } returnFailure: @@ -178,7 +177,7 @@ tSirRetStatus limSendBeaconParams(tpAniSirGlobal pMac, (void **) &pBcnParams, sizeof(*pBcnParams))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Update Beacon Params\n" )); + FL( "Unable to PAL allocate memory during Update Beacon Params" )); return eSIR_MEM_ALLOC_FAILED; } palCopyMemory( pMac->hHdd, (tANI_U8 *) pBcnParams, pUpdatedBcnParams, sizeof(*pBcnParams)); @@ -201,7 +200,7 @@ tSirRetStatus limSendBeaconParams(tpAniSirGlobal pMac, { palFreeMemory(pMac->hHdd, pBcnParams); limLog( pMac, LOGP, - FL("Posting WDA_UPDATE_BEACON_IND to WDA failed, reason=%X\n"), + FL("Posting WDA_UPDATE_BEACON_IND to WDA failed, reason=%X"), retCode ); } limSendBeaconInd(pMac, psessionEntry); @@ -248,7 +247,7 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, if((pSessionEntry = peFindSessionBySessionId(pMac , peSessionId)) == NULL) { limLog( pMac, LOGP, - FL( "Unable to get Session for session Id %d\n" ), peSessionId); + FL( "Unable to get Session for session Id %d" ), peSessionId); return eSIR_FAILURE; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, @@ -256,7 +255,7 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, sizeof( tSwitchChannelParams ))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Switch Channel Params\n" )); + FL( "Unable to PAL allocate memory during Switch Channel Params" )); retCode = eSIR_MEM_ALLOC_FAILED; goto returnFailure; } @@ -292,7 +291,7 @@ tSirRetStatus limSendSwitchChnlParams(tpAniSirGlobal pMac, { palFreeMemory(pMac->hHdd, pChnlParams); limLog( pMac, LOGP, - FL("Posting WDA_CHNL_SWITCH_REQ to WDA failed, reason=%X\n"), + FL("Posting WDA_CHNL_SWITCH_REQ to WDA failed, reason=%X"), retCode ); } returnFailure: @@ -330,7 +329,7 @@ tSirRetStatus limSendEdcaParams(tpAniSirGlobal pMac, tSirMacEdcaParamRecord *pUp sizeof(tEdcaParams))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Update EDCA Params\n" )); + FL( "Unable to PAL allocate memory during Update EDCA Params" )); retCode = eSIR_MEM_ALLOC_FAILED; return retCode; } @@ -349,7 +348,7 @@ tSirRetStatus limSendEdcaParams(tpAniSirGlobal pMac, tSirMacEdcaParamRecord *pUp PELOG1(limLog( pMac, LOG1,FL("Sending WDA_UPDATE_EDCA_PROFILE_IND with EDCA Parameters:" ));) for(i=0; ihHdd, pEdcaParams); limLog( pMac, LOGP, - FL("Posting WDA_UPDATE_EDCA_PROFILE_IND to WDA failed, reason=%X\n"), + FL("Posting WDA_UPDATE_EDCA_PROFILE_IND to WDA failed, reason=%X"), retCode ); } return retCode; @@ -407,12 +406,12 @@ tSirRetStatus limSendEdcaParams(tpAniSirGlobal pMac, tSirMacEdcaParamRecord *pUp * such that: BE_ACM=1, BK_ACM=1, VI_ACM=1, VO_ACM=0 * then all AC will be downgraded to AC_BE. */ - limLog(pMac, LOG1, FL("adAdmitMask[UPLINK] = 0x%x \n"), pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] ); - limLog(pMac, LOG1, FL("adAdmitMask[DOWNLINK] = 0x%x \n"), pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] ); + limLog(pMac, LOG1, FL("adAdmitMask[UPLINK] = 0x%x "), pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] ); + limLog(pMac, LOG1, FL("adAdmitMask[DOWNLINK] = 0x%x "), pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_DNLINK] ); for (ac = EDCA_AC_BK; ac <= EDCA_AC_VO; ac++) { acAdmitted = ( (pMac->lim.gAcAdmitMask[SIR_MAC_DIRECTION_UPLINK] & (1 << ac)) >> ac ); - limLog(pMac, LOG1, FL("For AC[%d]: acm=%d, acAdmit=%d \n"), ac, plocalEdcaParams[ac].aci.acm, acAdmitted); + limLog(pMac, LOG1, FL("For AC[%d]: acm=%d, acAdmit=%d "), ac, plocalEdcaParams[ac].aci.acm, acAdmitted); if ( (plocalEdcaParams[ac].aci.acm == 1) && (acAdmitted == 0) ) { limLog(pMac, LOG1, FL("We need to downgrade AC %d!! "), ac); @@ -476,7 +475,7 @@ tSirRetStatus limSetLinkState(tpAniSirGlobal pMac, tSirLinkState state,tSirMacAd MTRACE(macTraceMsgTx(pMac, 0, msg.type)); retCode = wdaPostCtrlMsg(pMac, &msg); if (retCode != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x "), retCode); return retCode; } #endif //0 @@ -493,7 +492,7 @@ tSirRetStatus limSetLinkState(tpAniSirGlobal pMac, tSirLinkState state,tSirMacAd sizeof(tLinkStateParams))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory while sending Set Link State\n" )); + FL( "Unable to PAL allocate memory while sending Set Link State" )); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; return retCode; } @@ -517,7 +516,7 @@ tSirRetStatus limSetLinkState(tpAniSirGlobal pMac, tSirLinkState state,tSirMacAd if (retCode != eSIR_SUCCESS) { palFreeMemory(pMac, (void*)pLinkStateParams); - limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x "), retCode); } return retCode; } @@ -534,7 +533,7 @@ state,tSirMacAddr bssId, tSirMacAddr selfMacAddr, int ft, tpPESession psessionEn sizeof(tLinkStateParams))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory while sending Set Link State\n" )); + FL( "Unable to PAL allocate memory while sending Set Link State" )); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; return retCode; } @@ -563,7 +562,7 @@ state,tSirMacAddr bssId, tSirMacAddr selfMacAddr, int ft, tpPESession psessionEn if (retCode != eSIR_SUCCESS) { palFreeMemory(pMac, (void*)pLinkStateParams); - limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting link state %d failed, reason = %x "), retCode); } return retCode; } @@ -670,7 +669,7 @@ tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac,tpPESession psessionEn if( psessionEntry == NULL ) { - limLog( pMac, LOGE, FL("Fail to find the right session \n")); + limLog( pMac, LOGE, FL("Fail to find the right session ")); retCode = eSIR_FAILURE; return retCode; } @@ -678,7 +677,7 @@ tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac,tpPESession psessionEn if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **) &pBeaconFilterMsg, msgSize) ) { - limLog( pMac, LOGP, FL("Fail to allocate memory for beaconFiilterMsg \n")); + limLog( pMac, LOGP, FL("Fail to allocate memory for beaconFiilterMsg ")); retCode = eSIR_MEM_ALLOC_FAILED; return retCode; } @@ -717,7 +716,7 @@ tSirRetStatus limSendBeaconFilterInfo(tpAniSirGlobal pMac,tpPESession psessionEn { palFreeMemory(pMac->hHdd, pBeaconFilterMsg); limLog( pMac, LOGP, - FL("Posting WDA_BEACON_FILTER_IND to WDA failed, reason=%X\n"), + FL("Posting WDA_BEACON_FILTER_IND to WDA failed, reason=%X"), retCode ); return retCode; } @@ -737,7 +736,7 @@ tSirRetStatus limSendModeUpdate(tpAniSirGlobal pMac, (void **) &pVhtOpMode, sizeof(tUpdateVHTOpMode))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory during Update Op Mode\n" )); + FL( "Unable to PAL allocate memory during Update Op Mode" )); return eSIR_MEM_ALLOC_FAILED; } palCopyMemory( pMac->hHdd, (tANI_U8 *)pVhtOpMode, pTempParam, sizeof(tUpdateVHTOpMode)); @@ -759,7 +758,7 @@ tSirRetStatus limSendModeUpdate(tpAniSirGlobal pMac, { palFreeMemory(pMac->hHdd, pVhtOpMode); limLog( pMac, LOGP, - FL("Posting WDA_UPDATE_OP_MODE to WDA failed, reason=%X\n"), + FL("Posting WDA_UPDATE_OP_MODE to WDA failed, reason=%X"), retCode ); } @@ -788,7 +787,7 @@ tSirRetStatus limSendTdlsLinkEstablish(tpAniSirGlobal pMac, tANI_U8 bIsPeerRespo sizeof(tSirTdlsLinkEstablishInd))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory while sending Tdls Link Establish \n" )); + FL( "Unable to PAL allocate memory while sending Tdls Link Establish " )); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; return retCode; @@ -816,7 +815,7 @@ tSirRetStatus limSendTdlsLinkEstablish(tpAniSirGlobal pMac, tANI_U8 bIsPeerRespo if (retCode != eSIR_SUCCESS) { palFreeMemory(pMac, (void*)pTdlsLinkEstablish); - limLog(pMac, LOGP, FL("Posting tdls link establish %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting tdls link establish %d failed, reason = %x "), retCode); } return retCode; @@ -841,7 +840,7 @@ tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId) sizeof(tSirTdlsLinkTeardownInd))) { limLog( pMac, LOGP, - FL( "Unable to PAL allocate memory while sending Tdls Link Teardown \n" )); + FL( "Unable to PAL allocate memory while sending Tdls Link Teardown " )); retCode = eSIR_SME_RESOURCES_UNAVAILABLE; return retCode; @@ -862,7 +861,7 @@ tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId) if (retCode != eSIR_SUCCESS) { palFreeMemory(pMac, (void*)pTdlsLinkTeardown); - limLog(pMac, LOGP, FL("Posting tdls link teardown %d failed, reason = %x \n"), retCode); + limLog(pMac, LOGP, FL("Posting tdls link teardown %d failed, reason = %x "), retCode); } return retCode; @@ -870,54 +869,3 @@ tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId) #endif -#ifdef WLAN_FEATURE_11W -/** --------------------------------------------------------- -\fn limSendExcludeUnencryptInd -\brief LIM sends a message to HAL to indicate whether to - ignore or indicate the unprotected packet error -\param tpAniSirGlobal pMac -\param tANI_BOOLEAN excludeUnenc - true: ignore, false: - indicate -\param tpPESession psessionEntry - session context -\return status - -----------------------------------------------------------*/ -tSirRetStatus limSendExcludeUnencryptInd(tpAniSirGlobal pMac, - tANI_BOOLEAN excludeUnenc, - tpPESession psessionEntry) -{ - tSirRetStatus retCode = eSIR_SUCCESS; - tSirMsgQ msgQ; - tSirWlanExcludeUnencryptParam * pExcludeUnencryptParam; - - if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, - (void **) &pExcludeUnencryptParam, - sizeof(tSirWlanExcludeUnencryptParam))) - { - limLog(pMac, LOGP, - FL( "Unable to PAL allocate memory during limSendExcludeUnencryptInd")); - return eSIR_MEM_ALLOC_FAILED; - } - - pExcludeUnencryptParam->excludeUnencrypt = excludeUnenc; - sirCopyMacAddr(pExcludeUnencryptParam->bssId, psessionEntry->bssId); - - msgQ.type = WDA_EXCLUDE_UNENCRYPTED_IND; - msgQ.reserved = 0; - msgQ.bodyptr = pExcludeUnencryptParam; - msgQ.bodyval = 0; - PELOG3(limLog(pMac, LOG3, - FL("Sending WDA_EXCLUDE_UNENCRYPTED_IND"));) - MTRACE(macTraceMsgTx(pMac, psessionEntry->peSessionId, msgQ.type)); - retCode = wdaPostCtrlMsg(pMac, &msgQ); - if (eSIR_SUCCESS != retCode) - { - palFreeMemory(pMac->hHdd, pExcludeUnencryptParam); - limLog(pMac, LOGP, - FL("Posting WDA_EXCLUDE_UNENCRYPTED_IND to WDA failed, reason=%X"), - retCode); - } - - return retCode; -} -#endif - diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.h index d2d12fac83e..7f7b0735d98 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendMessages.h @@ -109,9 +109,5 @@ tSirRetStatus limSendTdlsLinkEstablish(tpAniSirGlobal pMac, tANI_U8 bIsPeerRespo tANI_U8 ptiBufStatusOffset, tANI_U8 ptiFrameLen, tANI_U8 *ptiFrame, tANI_U8 *extCapability); tSirRetStatus limSendTdlsLinkTeardown(tpAniSirGlobal pMac, tANI_U16 staId); #endif -#ifdef WLAN_FEATURE_11W -tSirRetStatus limSendExcludeUnencryptInd(tpAniSirGlobal pMac, - tANI_BOOLEAN excludeUnenc, - tpPESession psessionEntry ); -#endif + #endif diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c index 299375468b7..d91c595680b 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.c @@ -106,14 +106,14 @@ limSendSmeRsp(tpAniSirGlobal pMac, tANI_U16 msgType, tSirSmeRsp *pSirSmeRsp; PELOG1(limLog(pMac, LOG1, - FL("Sending message %s with reasonCode %s\n"), + FL("Sending message %s with reasonCode %s"), limMsgStr(msgType), limResultCodeStr(resultCode));) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeRsp, sizeof(tSirSmeRsp))) { /// Buffer not available. Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_*_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_*_RSP")); return; } @@ -256,7 +256,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, #endif //FEATURE_WLAN_DIAG_SUPPORT PELOG1(limLog(pMac, LOG1, - FL("Sending message %s with reasonCode %s\n"), + FL("Sending message %s with reasonCode %s"), limMsgStr(msgType), limResultCodeStr(resultCode));) if(psessionEntry == NULL) @@ -267,7 +267,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeJoinRsp, rspLen)) { /// Buffer not available. Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP")); return; } @@ -295,7 +295,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, { /// Buffer not available. Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP\n")); + FL("call to palAllocateMemory failed for JOIN/REASSOC_RSP")); return; } @@ -307,7 +307,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, pStaDs = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); if (pStaDs == NULL) { - PELOGE(limLog(pMac, LOGE, FL("could not Get Self Entry for the station\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not Get Self Entry for the station"));) } else { @@ -338,7 +338,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, palFreeMemory(pMac->hHdd, psessionEntry->beacon); psessionEntry->beacon = NULL; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("Beacon=%d\n"), psessionEntry->bcnLen);) + PELOG1(limLog(pMac, LOG1, FL("Beacon=%d"), psessionEntry->bcnLen);) #endif } @@ -349,7 +349,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, palFreeMemory(pMac->hHdd, psessionEntry->assocReq); psessionEntry->assocReq = NULL; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("AssocReq=%d\n"), psessionEntry->assocReqLen);) + PELOG1(limLog(pMac, LOG1, FL("AssocReq=%d"), psessionEntry->assocReqLen);) #endif } if(psessionEntry->assocRsp != NULL) @@ -366,7 +366,7 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, palCopyMemory(pMac->hHdd, pSirSmeJoinRsp->frames + psessionEntry->bcnLen + psessionEntry->assocReqLen + psessionEntry->assocRspLen, psessionEntry->ricData, pSirSmeJoinRsp->parsedRicRspLen); palFreeMemory(pMac->hHdd, psessionEntry->ricData); psessionEntry->ricData = NULL; - PELOG1(limLog(pMac, LOG1, FL("RicLength=%d\n"), pSirSmeJoinRsp->parsedRicRspLen);) + PELOG1(limLog(pMac, LOG1, FL("RicLength=%d"), pSirSmeJoinRsp->parsedRicRspLen);) } #endif #ifdef FEATURE_WLAN_CCX @@ -376,12 +376,12 @@ limSendSmeJoinReassocRsp(tpAniSirGlobal pMac, tANI_U16 msgType, palCopyMemory(pMac->hHdd, pSirSmeJoinRsp->frames + psessionEntry->bcnLen + psessionEntry->assocReqLen + psessionEntry->assocRspLen + psessionEntry->RICDataLen, psessionEntry->tspecIes, pSirSmeJoinRsp->tspecIeLen); palFreeMemory(pMac->hHdd, psessionEntry->tspecIes); psessionEntry->tspecIes = NULL; - PELOG1(limLog(pMac, LOG1, FL("CCX-TspecLen=%d\n"), psessionEntry->tspecLen);) + PELOG1(limLog(pMac, LOG1, FL("CCX-TspecLen=%d"), psessionEntry->tspecLen);) } #endif pSirSmeJoinRsp->aid = psessionEntry->limAID; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOG1(limLog(pMac, LOG1, FL("AssocRsp=%d\n"), psessionEntry->assocRspLen);) + PELOG1(limLog(pMac, LOG1, FL("AssocRsp=%d"), psessionEntry->assocRspLen);) #endif } else @@ -493,7 +493,7 @@ limSendSmeStartBssRsp(tpAniSirGlobal pMac, tANI_U16 ieLen; tANI_U16 ieOffset, curLen; - PELOG1(limLog(pMac, LOG1, FL("Sending message %s with reasonCode %s\n"), + PELOG1(limLog(pMac, LOG1, FL("Sending message %s with reasonCode %s"), limMsgStr(msgType), limResultCodeStr(resultCode));) size = sizeof(tSirSmeStartBssRsp); @@ -504,7 +504,7 @@ limSendSmeStartBssRsp(tpAniSirGlobal pMac, if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeRsp, size)) { /// Buffer not available. Log error - limLog(pMac, LOGP,FL("call to palAllocateMemory failed for eWNI_SME_START_BSS_RSP\n")); + limLog(pMac, LOGP,FL("call to palAllocateMemory failed for eWNI_SME_START_BSS_RSP")); return; } palZeroMemory(pMac, (tANI_U8*)pSirSmeRsp, size); @@ -522,7 +522,7 @@ limSendSmeStartBssRsp(tpAniSirGlobal pMac, { /// Buffer not available. Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_START_BSS_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_START_BSS_RSP")); return; } @@ -539,13 +539,13 @@ limSendSmeStartBssRsp(tpAniSirGlobal pMac, if (cfgGetCapabilityInfo( pMac, &pSirSmeRsp->bssDescription.capabilityInfo,psessionEntry) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve Capabilities value\n")); + limLog(pMac, LOGP, FL("could not retrieve Capabilities value")); limGetPhyMode(pMac, (tANI_U32 *)&pSirSmeRsp->bssDescription.nwType, psessionEntry); #if 0 if (wlan_cfgGetInt(pMac, WNI_CFG_CURRENT_CHANNEL, &len) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("could not retrieve CURRENT_CHANNEL from CFG\n")); + limLog(pMac, LOGP, FL("could not retrieve CURRENT_CHANNEL from CFG")); #endif// TO SUPPORT BT-AMP @@ -652,7 +652,7 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, tSirBssDescription *pDesc; PELOG1(limLog(pMac, LOG1, - FL("Sending message SME_SCAN_RSP with length=%d reasonCode %s\n"), + FL("Sending message SME_SCAN_RSP with length=%d reasonCode %s"), length, limResultCodeStr(resultCode));) if (resultCode != eSIR_SME_SUCCESS) @@ -670,7 +670,7 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP")); return; } @@ -710,7 +710,7 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP")); return; } msgLen = sizeof(tSirSmeScanRsp) - @@ -722,7 +722,7 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, } curMsgLen = msgLen; - PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d\n"), + PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d"), msgLen, ptemp->bssDescription.length);) pDesc->length = ptemp->bssDescription.length; @@ -765,13 +765,176 @@ limSendSmeScanRsp(tpAniSirGlobal pMac, tANI_U16 length, mmhMsg.bodyval = 0; MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); - PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS\n"));) + PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS"));) } return; } /*** end limSendSmeScanRsp() ***/ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + * limSendSmeLfrScanRsp() + * + *FUNCTION: + * This function is called by limProcessSmeReqMessages() to send + * eWNI_SME_SCAN_RSP message to applications above MAC Software + * only for sending up the roam candidates. + * + *PARAMS: + * + *LOGIC: + * + *ASSUMPTIONS: + * NA + * + *NOTE: + * NA + * + * @param pMac Pointer to Global MAC structure + * @param length Indicates length of message + * @param resultCode Indicates the result of previously issued + * eWNI_SME_SCAN_REQ message + * + * @return None + */ + +void +limSendSmeLfrScanRsp(tpAniSirGlobal pMac, tANI_U16 length, + tSirResultCodes resultCode,tANI_U8 smesessionId,tANI_U16 smetranscationId) +{ + tSirMsgQ mmhMsg; + tpSirSmeScanRsp pSirSmeScanRsp=NULL; + tLimScanResultNode *ptemp = NULL; + tANI_U16 msgLen, allocLength, curMsgLen = 0; + tANI_U16 i, bssCount; + tANI_U8 *pbBuf; + tSirBssDescription *pDesc; + + PELOG1(limLog(pMac, LOG1, + FL("Sending message SME_SCAN_RSP with length=%d reasonCode %s\n"), + length, limResultCodeStr(resultCode));) + + if (resultCode != eSIR_SME_SUCCESS) + { + limPostSmeScanRspMessage(pMac, length, resultCode,smesessionId,smetranscationId); + return; + } + + mmhMsg.type = eWNI_SME_SCAN_RSP; + i = 0; + bssCount = 0; + msgLen = 0; + allocLength = LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED * LIM_SIZE_OF_EACH_BSS; + if ( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, + (void **)&pSirSmeScanRsp, allocLength)) + { + // Log error + limLog(pMac, LOGP, + FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + + return; + } + for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + { + //when ptemp is not NULL it is a left over + ptemp = pMac->lim.gLimCachedLfrScanHashTable[i]; + while(ptemp) + { + pbBuf = ((tANI_U8 *)pSirSmeScanRsp) + msgLen; + if(0 == bssCount) + { + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + } + else + { + msgLen += ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = (tSirBssDescription *)pbBuf; + } + if ( (allocLength < msgLen) || + (LIM_MAX_NUM_OF_SCAN_RESULTS_REPORTED <= bssCount++) ) + { + pSirSmeScanRsp->statusCode = + eSIR_SME_MORE_SCAN_RESULTS_FOLLOW; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, + (void **)&pSirSmeScanRsp, + allocLength)) + { + // Log error + limLog(pMac, LOGP, + FL("call to palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + return; + } + msgLen = sizeof(tSirSmeScanRsp) - + sizeof(tSirBssDescription) + + ptemp->bssDescription.length + + sizeof(ptemp->bssDescription.length); + pDesc = pSirSmeScanRsp->bssDescription; + bssCount = 1; + } + curMsgLen = msgLen; + + PELOG2(limLog(pMac, LOG2, FL("ScanRsp : msgLen %d, bssDescr Len=%d\n"), + msgLen, ptemp->bssDescription.length);) + pDesc->length + = ptemp->bssDescription.length; + palCopyMemory( pMac->hHdd, (tANI_U8 *) &pDesc->bssId, + (tANI_U8 *) &ptemp->bssDescription.bssId, + ptemp->bssDescription.length); + + PELOG2(limLog(pMac, LOG2, FL("BssId ")); + limPrintMacAddr(pMac, ptemp->bssDescription.bssId, LOG2);) + + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + + ptemp = ptemp->next; + } //while(ptemp) + } //for (i = 0; i < LIM_MAX_NUM_OF_SCAN_RESULTS; i++) + + if (0 == bssCount) + { + limPostSmeScanRspMessage(pMac, length, resultCode, smesessionId, smetranscationId); + if (NULL != pSirSmeScanRsp) + { + palFreeMemory( pMac->hHdd, pSirSmeScanRsp); + pSirSmeScanRsp = NULL; + } + } + else + { + // send last message + pSirSmeScanRsp->statusCode = eSIR_SME_SUCCESS; + pSirSmeScanRsp->messageType = eWNI_SME_SCAN_RSP; + pSirSmeScanRsp->length = curMsgLen; + + /* Update SME session Id and SME transcation Id */ + pSirSmeScanRsp->sessionId = smesessionId; + pSirSmeScanRsp->transcationId = smetranscationId; + + mmhMsg.type = eWNI_SME_SCAN_RSP; + mmhMsg.bodyptr = pSirSmeScanRsp; + mmhMsg.bodyval = 0; + MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + PELOG2(limLog(pMac, LOG2, FL("statusCode : eSIR_SME_SUCCESS\n"));) + } + + return; + +} /*** end limSendSmeLfrScanRsp() ***/ +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD /** * limPostSmeScanRspMessage() @@ -799,12 +962,12 @@ limPostSmeScanRspMessage(tpAniSirGlobal pMac, tSirMsgQ mmhMsg; PELOG1(limLog(pMac, LOG1, - FL("limPostSmeScanRspMessage: send SME_SCAN_RSP (len %d, reasonCode %s). \n"), + FL("limPostSmeScanRspMessage: send SME_SCAN_RSP (len %d, reasonCode %s). "), length, limResultCodeStr(resultCode));) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeScanRsp, length)) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_SCAN_RSP\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_SCAN_RSP")); return; } palZeroMemory(pMac->hHdd, (void*)pSirSmeScanRsp, length); @@ -881,7 +1044,7 @@ void limSendSmeOemDataRsp(tpAniSirGlobal pMac, tANI_U32* pMsgBuf, tSirResultCode //now allocate memory for the char buffer if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void**)&pSirSmeOemDataRsp, msgLength)) { - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSirSmeOemDataRsp\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for pSirSmeOemDataRsp")); return; } @@ -951,7 +1114,7 @@ limSendSmeAuthRsp(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_AUTH_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_AUTH_RSP")); return; } @@ -1057,7 +1220,7 @@ limSendSmeDisassocNtf(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_DISASSOC_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_DISASSOC_RSP")); return; } @@ -1103,7 +1266,7 @@ limSendSmeDisassocNtf(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_DISASSOC_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_DISASSOC_IND")); return; } @@ -1167,7 +1330,7 @@ limSendSmeDisassocInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs,tpPESession pses if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeDisassocInd, sizeof(tSirSmeDisassocInd))) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_DISASSOC_IND\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_DISASSOC_IND")); return; } @@ -1219,7 +1382,7 @@ limSendSmeDeauthInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession psess if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeDeauthInd, sizeof(tSirSmeDeauthInd))) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_DEAUTH_IND \n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_DEAUTH_IND ")); return; } @@ -1287,7 +1450,7 @@ limSendSmeTDLSDelStaInd(tpAniSirGlobal pMac, tpDphHashNode pStaDs, tpPESession p if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirTdlsDelStaInd, sizeof(tSirTdlsDelStaInd))) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_TDLS_DEL_STA_IND \n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_TDLS_DEL_STA_IND ")); return; } @@ -1468,7 +1631,7 @@ limSendSmeDeauthNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tSirResultCode { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_DEAUTH_RSP\n")); + FL("call to palAllocateMemory failed for eWNI_SME_DEAUTH_RSP")); return; } @@ -1500,7 +1663,7 @@ limSendSmeDeauthNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tSirResultCode { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_DEAUTH_Ind\n")); + FL("call to palAllocateMemory failed for eWNI_SME_DEAUTH_Ind")); return; } @@ -1588,7 +1751,7 @@ limSendSmeWmStatusChangeNtf(tpAniSirGlobal pMac, tSirSmeStatusChangeCode statusC if (status != eHAL_STATUS_SUCCESS) { limLog(pMac, LOGE, - FL("call to palAllocateMemory failed for eWNI_SME_WM_STATUS_CHANGE_NTF, status = %d\n"), + FL("call to palAllocateMemory failed for eWNI_SME_WM_STATUS_CHANGE_NTF, status = %d"), status); return; } @@ -1623,7 +1786,7 @@ limSendSmeWmStatusChangeNtf(tpAniSirGlobal pMac, tSirSmeStatusChangeCode statusC { palCopyMemory( pMac->hHdd, (tANI_U8 *)&pSirSmeWmStatusChangeNtf->statusChangeInfo, (tANI_U8 *)pStatusChangeInfo, infoLen); } - limLog(pMac, LOGE, FL("***---*** StatusChg: code 0x%x, length %d ***---***\n"), + limLog(pMac, LOGE, FL("***---*** StatusChg: code 0x%x, length %d ***---***"), statusChangeCode, infoLen); break; } @@ -1633,7 +1796,7 @@ limSendSmeWmStatusChangeNtf(tpAniSirGlobal pMac, tSirSmeStatusChangeCode statusC if (eSIR_SUCCESS != limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT)) { palFreeMemory(pMac->hHdd, (void *) pSirSmeWmStatusChangeNtf); - limLog( pMac, LOGP, FL("limSysProcessMmhMsgApi failed\n")); + limLog( pMac, LOGP, FL("limSysProcessMmhMsgApi failed")); } } /*** end limSendSmeWmStatusChangeNtf() ***/ @@ -1680,7 +1843,7 @@ limSendSmeSetContextRsp(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for SmeSetContextRsp\n")); + FL("call to palAllocateMemory failed for SmeSetContextRsp")); return; } @@ -1759,7 +1922,7 @@ limSendSmeRemoveKeyRsp(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for SmeRemoveKeyRsp\n")); + FL("call to palAllocateMemory failed for SmeRemoveKeyRsp")); return; } @@ -1828,7 +1991,7 @@ limSendSmePromiscuousModeRsp(tpAniSirGlobal pMac) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pMbMsg, sizeof(tSirMbMsg))) { // Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed")); return; } @@ -1889,7 +2052,7 @@ limSendSmeNeighborBssInd(tpAniSirGlobal pMac, if (wlan_cfgGetInt(pMac, WNI_CFG_NEW_BSS_FOUND_IND, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not get NEIGHBOR_BSS_IND from CFG\n")); + limLog(pMac, LOGP, FL("could not get NEIGHBOR_BSS_IND from CFG")); return; } @@ -1909,7 +2072,7 @@ limSendSmeNeighborBssInd(tpAniSirGlobal pMac, { // Log error limLog(pMac, LOGP, - FL("call to palAllocateMemory failed for eWNI_SME_NEIGHBOR_BSS_IND\n")); + FL("call to palAllocateMemory failed for eWNI_SME_NEIGHBOR_BSS_IND")); return; } @@ -1991,7 +2154,7 @@ limSendSmeAddtsInd(tpAniSirGlobal pMac, tpSirAddtsReqInfo addts) tpSirAddtsRsp rsp; tSirMsgQ mmhMsg; - limLog(pMac, LOGW, "SendSmeAddtsInd (token %d, tsid %d, up %d)\n", + limLog(pMac, LOGW, "SendSmeAddtsInd (token %d, tsid %d, up %d)", addts->dialogToken, addts->tspec.tsinfo.traffic.tsid, addts->tspec.tsinfo.traffic.userPrio); @@ -1999,7 +2162,7 @@ limSendSmeAddtsInd(tpAniSirGlobal pMac, tpSirAddtsReqInfo addts) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&rsp, sizeof(tSirAddtsRsp))) { // Log error - limLog(pMac, LOGP, FL("palAllocateMemory failed for ADDTS_IND\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for ADDTS_IND")); return; } palZeroMemory( pMac->hHdd, (tANI_U8 *) rsp, sizeof(*rsp)); @@ -2021,7 +2184,7 @@ limSendSmeDeltsRsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, tANI_U32 status,tpP tpSirDeltsRsp rsp; tSirMsgQ mmhMsg; - limLog(pMac, LOGW, "SendSmeDeltsRsp (aid %d, tsid %d, up %d) status %d\n", + limLog(pMac, LOGW, "SendSmeDeltsRsp (aid %d, tsid %d, up %d) status %d", delts->aid, delts->req.tsinfo.traffic.tsid, delts->req.tsinfo.traffic.userPrio, @@ -2032,7 +2195,7 @@ limSendSmeDeltsRsp(tpAniSirGlobal pMac, tpSirDeltsReq delts, tANI_U32 status,tpP if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&rsp, sizeof(tSirDeltsRsp))) { // Log error - limLog(pMac, LOGP, FL("palAllocateMemory failed for DELTS_RSP\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for DELTS_RSP")); return; } palZeroMemory( pMac->hHdd, (tANI_U8 *) rsp, sizeof(*rsp)); @@ -2077,7 +2240,7 @@ limSendSmeDeltsInd(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, tANI_U16 aid,tp tpSirDeltsRsp rsp; tSirMsgQ mmhMsg; - limLog(pMac, LOGW, "SendSmeDeltsInd (aid %d, tsid %d, up %d)\n", + limLog(pMac, LOGW, "SendSmeDeltsInd (aid %d, tsid %d, up %d)", aid, delts->tsinfo.traffic.tsid, delts->tsinfo.traffic.userPrio); @@ -2085,7 +2248,7 @@ limSendSmeDeltsInd(tpAniSirGlobal pMac, tpSirDeltsReqInfo delts, tANI_U16 aid,tp if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&rsp, sizeof(tSirDeltsRsp))) { // Log error - limLog(pMac, LOGP, FL("palAllocateMemory failed for DELTS_IND\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for DELTS_IND")); return; } palZeroMemory( pMac->hHdd, (tANI_U8 *) rsp, sizeof(*rsp)); @@ -2361,7 +2524,7 @@ void limSendExitBmpsInd(tpAniSirGlobal pMac, tExitBmpsReason reasonCode) msgLen = sizeof(tSirSmeExitBmpsInd); if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pExitBmpsInd, msgLen )) { - limLog(pMac, LOGP, FL("palAllocateMemory failed for PMC_EXIT_BMPS_IND \n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed for PMC_EXIT_BMPS_IND ")); return; } palZeroMemory(pMac->hHdd, pExitBmpsInd, msgLen); @@ -2375,7 +2538,7 @@ void limSendExitBmpsInd(tpAniSirGlobal pMac, tExitBmpsReason reasonCode) mmhMsg.bodyptr = pExitBmpsInd; mmhMsg.bodyval = 0; - PELOG1(limLog(pMac, LOG1, FL("Sending eWNI_PMC_EXIT_BMPS_IND to SME. \n"));) + PELOG1(limLog(pMac, LOG1, FL("Sending eWNI_PMC_EXIT_BMPS_IND to SME. "));) MTRACE(macTraceMsgTx(pMac, NO_SESSION, mmhMsg.type)); #ifdef FEATURE_WLAN_DIAG_SUPPORT_LIM //FEATURE_WLAN_DIAG_SUPPORT limDiagEventReport(pMac, WLAN_PE_DIAG_EXIT_BMPS_IND_EVENT, peGetValidPowerSaveSession(pMac), 0, (tANI_U16)reasonCode); @@ -2405,7 +2568,7 @@ void limHandleDeleteBssRsp(tpAniSirGlobal pMac,tpSirMsgQ MsgQ) tpDeleteBssParams pDelBss = (tpDeleteBssParams)(MsgQ->bodyptr); if((psessionEntry = peFindSessionBySessionId(pMac,pDelBss->sessionId))==NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } if (psessionEntry->limSystemRole == eLIM_STA_IN_IBSS_ROLE) @@ -2518,10 +2681,53 @@ void limSendSmeMaxAssocExceededNtf(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, mmhMsg.type = pSmeMaxAssocInd->mesgType; mmhMsg.bodyptr = pSmeMaxAssocInd; PELOG1(limLog(pMac, LOG1, FL("msgType %s peerMacAddr %02x-%02x-%02x-%02x-%02x-%02x" - "sme session id %d\n"),"eWNI_SME_MAX_ASSOC_EXCEEDED", peerMacAddr[0], peerMacAddr[1], + "sme session id %d"),"eWNI_SME_MAX_ASSOC_EXCEEDED", peerMacAddr[0], peerMacAddr[1], peerMacAddr[2], peerMacAddr[3], peerMacAddr[4], peerMacAddr[5], smesessionId);) MTRACE(macTraceMsgTx(pMac, smesessionId, mmhMsg.type)); limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); return; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** ----------------------------------------------------------------- + \brief limSendSmeCandidateFoundInd() - sends + eWNI_SME_CANDIDATE_FOUND_IND + + After receiving candidate found indication frame from FW, this + function sends a eWNI_SME_CANDIDATE_FOUND_IND to SME to notify + roam candidate(s) are available. + + \param pMac - global mac structure + \param psessionEntry - session info + \return none + \sa + ----------------------------------------------------------------- */ +void +limSendSmeCandidateFoundInd(tpAniSirGlobal pMac, tANI_U8 sessionId) +{ + tSirMsgQ mmhMsg; + tSirSmeCandidateFoundInd *pSirSmeCandidateFoundInd; + + if ( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, + (void **)&pSirSmeCandidateFoundInd, + sizeof(tSirSmeCandidateFoundInd))) + { + limLog(pMac, LOGP, FL("palAllocateMemory failed for eWNI_SME_CANDIDATE_FOUND_IND\n")); + return; + } + + pSirSmeCandidateFoundInd->messageType = eWNI_SME_CANDIDATE_FOUND_IND; + pSirSmeCandidateFoundInd->length = sizeof(tSirSmeDisassocInd); + + pSirSmeCandidateFoundInd->sessionId = sessionId; + + + limLog( pMac, LOGE, FL("posting candidate ind to SME")); + mmhMsg.type = eWNI_SME_CANDIDATE_FOUND_IND; + mmhMsg.bodyptr = pSirSmeCandidateFoundInd; + mmhMsg.bodyval = 0; + + limSysProcessMmhMsgApi(pMac, &mmhMsg, ePROT); + +} /*** end limSendSmeCandidateFoundInd() ***/ +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h index a2e5c47e767..3ef5351f1d7 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSendSmeRspMessages.h @@ -63,6 +63,9 @@ void limSendSmeRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes, tANI_U8 , tANI_U16); void limSendSmeStartBssRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tpPESession,tANI_U8,tANI_U16); void limSendSmeScanRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8, tANI_U16); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limSendSmeLfrScanRsp(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8, tANI_U16); +#endif void limPostSmeScanRspMessage(tpAniSirGlobal, tANI_U16, tSirResultCodes,tANI_U8,tANI_U16); void limSendSmeAuthRsp(tpAniSirGlobal, tSirResultCodes, tSirMacAddr, tAniAuthType, tANI_U16,tpPESession,tANI_U8,tANI_U16); @@ -72,8 +75,9 @@ void limSendSmeDisassocNtf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, tANI_U1 void limSendSmeDeauthNtf(tpAniSirGlobal, tSirMacAddr, tSirResultCodes, tANI_U16, tANI_U16, tANI_U8, tANI_U16); void limSendSmeDisassocInd(tpAniSirGlobal, tpDphHashNode,tpPESession); void limSendSmeDeauthInd(tpAniSirGlobal, tpDphHashNode, tpPESession psessionEntry); - - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +void limSendSmeCandidateFoundInd(tpAniSirGlobal, tANI_U8); +#endif void limSendSmeWmStatusChangeNtf(tpAniSirGlobal, tSirSmeStatusChangeCode, tANI_U32 *, tANI_U16, tANI_U8); void limSendSmeSetContextRsp(tpAniSirGlobal, diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c index 152024d3582..9969899dd8b 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSerDesUtils.c @@ -88,7 +88,7 @@ limCheckRemainingLength(tpAniSirGlobal pMac, tANI_S16 len) else { limLog(pMac, LOGW, - FL("Received SME message with invalid rem length=%d\n"), + FL("Received SME message with invalid rem length=%d"), len); return eSIR_FAILURE; } @@ -237,7 +237,7 @@ limGetBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pBssDescription, pBssDescription->mdie[2] = *pBuf++; len --; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - PELOGE(limLog(pMac, LOG1, FL("mdie=%02x %02x %02x\n"), + PELOGE(limLog(pMac, LOG1, FL("mdie=%02x %02x %02x"), pBssDescription->mdie[0], pBssDescription->mdie[1], pBssDescription->mdie[2]);) @@ -287,7 +287,7 @@ limGetBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pBssDescription, else { limLog(pMac, LOGE, - FL("remaining bytes len %d is less than WSCIE_PROBE_RSP_LEN\n"), + FL("remaining bytes len %d is less than WSCIE_PROBE_RSP_LEN"), pBssDescription->WscIeLen); return eSIR_FAILURE; } @@ -305,7 +305,7 @@ limGetBssDescription( tpAniSirGlobal pMac, tSirBssDescription *pBssDescription, else if (len < 0) { limLog(pMac, LOGE, - FL("remaining length is negative. len = %d, actual length = %d\n"), + FL("remaining length is negative. len = %d, actual length = %d"), len, pBssDescription->length); return eSIR_FAILURE; } @@ -452,7 +452,7 @@ limGetKeysInfo(tpAniSirGlobal pMac, tpSirKeys pKeyInfo, tANI_U8 *pBuf) len += pKeyInfo->keyLength; PELOG3(limLog(pMac, LOG3, - FL("Extracted keyId=%d, keyLength=%d, Key is :\n"), + FL("Extracted keyId=%d, keyLength=%d, Key is :"), pKeyInfo->keyId, pKeyInfo->keyLength); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, pKeyInfo->key, pKeyInfo->keyLength);) @@ -504,7 +504,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI len = pStartBssReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_START_BSS_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_START_BSS_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -565,7 +565,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (*pBuf > SIR_MAC_MAX_SSID_LENGTH) { // SSID length is more than max allowed 32 bytes - PELOGW(limLog(pMac, LOGW, FL("Invalid SSID length, len=%d\n"), *pBuf);) + PELOGW(limLog(pMac, LOGW, FL("Invalid SSID length, len=%d"), *pBuf);) return eSIR_FAILURE; } @@ -574,7 +574,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (len < pStartBssReq->ssId.length) { limLog(pMac, LOGW, - FL("SSID length is longer that the remaining length. SSID len=%d, remaining len=%d\n"), + FL("SSID length is longer that the remaining length. SSID len=%d, remaining len=%d"), pStartBssReq->ssId.length, len); return eSIR_FAILURE; } @@ -683,7 +683,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (pStartBssReq->rsnIE.length > SIR_MAC_MAX_IE_LENGTH + 2) { limLog(pMac, LOGW, - FL("Invalid RSN IE length %d in SME_START_BSS_REQ\n"), + FL("Invalid RSN IE length %d in SME_START_BSS_REQ"), pStartBssReq->rsnIE.length); return eSIR_FAILURE; } @@ -710,7 +710,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (pStartBssReq->operationalRateSet.numRates > SIR_MAC_MAX_NUMBER_OF_RATES) { - limLog(pMac, LOGW, FL("Invalid numRates %d in SME_START_BSS_REQ\n"), + limLog(pMac, LOGW, FL("Invalid numRates %d in SME_START_BSS_REQ"), pStartBssReq->operationalRateSet.numRates); return eSIR_FAILURE; } @@ -740,7 +740,7 @@ limStartBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStartBssReq pStartBssReq, tANI if (len) { - limLog(pMac, LOGW, FL("Extra bytes left in SME_START_BSS_REQ, len=%d\n"), len); + limLog(pMac, LOGW, FL("Extra bytes left in SME_START_BSS_REQ, len=%d"), len); } return eSIR_SUCCESS; @@ -787,7 +787,7 @@ limStopBssReqSerDes(tpAniSirGlobal pMac, tpSirSmeStopBssReq pStopBssReq, tANI_U8 len = pStopBssReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_STOP_BSS_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_STOP_BSS_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -862,7 +862,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) if (!pJoinReq || !pBuf) { - PELOGE(limLog(pMac, LOGE, FL("NULL ptr received\n"));) + PELOGE(limLog(pMac, LOGE, FL("NULL ptr received"));) return eSIR_FAILURE; } @@ -875,15 +875,15 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) pBuf += sizeof(tANI_U16); if (pJoinReq->messageType == eWNI_SME_JOIN_REQ) - PELOG1(limLog(pMac, LOG3, FL("SME_JOIN_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG3, FL("SME_JOIN_REQ length %d bytes is:"), len);) else - PELOG1(limLog(pMac, LOG3, FL("SME_REASSOC_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG3, FL("SME_REASSOC_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) { - PELOGE(limLog(pMac, LOGE, FL("len too short %d\n"), len);) + PELOGE(limLog(pMac, LOGE, FL("len too short %d"), len);) return eSIR_FAILURE; } @@ -988,7 +988,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) (pJoinReq->rsnIE.length != 2 + *(pBuf + 1))) { limLog(pMac, LOGW, - FL("Invalid RSN IE length %d in SME_JOIN_REQ\n"), + FL("Invalid RSN IE length %d in SME_JOIN_REQ"), pJoinReq->rsnIE.length); return eSIR_FAILURE; } @@ -1012,7 +1012,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) (pJoinReq->cckmIE.length != (2 + *(pBuf + 1)))) { limLog(pMac, LOGW, - FL("Invalid CCKM IE length %d/%d in SME_JOIN/REASSOC_REQ\n"), + FL("Invalid CCKM IE length %d/%d in SME_JOIN/REASSOC_REQ"), pJoinReq->cckmIE.length, 2 + *(pBuf + 1)); return eSIR_FAILURE; } @@ -1036,7 +1036,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) if (pJoinReq->addIEScan.length > SIR_MAC_MAX_IE_LENGTH + 2) { limLog(pMac, LOGE, - FL("Invalid addIE Scan length %d in SME_JOIN_REQ\n"), + FL("Invalid addIE Scan length %d in SME_JOIN_REQ"), pJoinReq->addIEScan.length); return eSIR_FAILURE; } @@ -1060,7 +1060,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) if (pJoinReq->addIEAssoc.length > SIR_MAC_MAX_IE_LENGTH + 2) { limLog(pMac, LOGE, - FL("Invalid addIE Assoc length %d in SME_JOIN_REQ\n"), + FL("Invalid addIE Assoc length %d in SME_JOIN_REQ"), pJoinReq->addIEAssoc.length); return eSIR_FAILURE; } @@ -1073,26 +1073,18 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) return eSIR_FAILURE; } - pJoinReq->MCEncryptionType = limGetU32(pBuf); + pJoinReq->UCEncryptionType = limGetU32(pBuf); pBuf += sizeof(tANI_U32); len -= sizeof(tANI_U32); if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) return eSIR_FAILURE; - pJoinReq->UCEncryptionType = limGetU32(pBuf); + pJoinReq->MCEncryptionType = limGetU32(pBuf); pBuf += sizeof(tANI_U32); len -= sizeof(tANI_U32); if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) return eSIR_FAILURE; -#ifdef WLAN_FEATURE_11W - pJoinReq->MgmtEncryptionType = limGetU32(pBuf); - pBuf += sizeof(tANI_U32); - len -= sizeof(tANI_U32); - if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) - return eSIR_FAILURE; -#endif - #ifdef WLAN_FEATURE_VOWIFI_11R //is11Rconnection; pJoinReq->is11Rconnection = (tAniBool)limGetU32(pBuf); @@ -1103,6 +1095,13 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) #endif #ifdef FEATURE_WLAN_CCX + //CCX version IE + pJoinReq->isCCXFeatureIniEnabled = (tAniBool)limGetU32(pBuf); + pBuf += sizeof(tAniBool); + len -= sizeof(tAniBool); + if (limCheckRemainingLength(pMac, len) == eSIR_FAILURE) + return eSIR_FAILURE; + //isCCXconnection; pJoinReq->isCCXconnection = (tAniBool)limGetU32(pBuf); pBuf += sizeof(tAniBool); @@ -1174,7 +1173,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) pJoinReq->powerCap.minTxPower = *pBuf++; pJoinReq->powerCap.maxTxPower = *pBuf++; len -=2; - limLog(pMac, LOG1, FL("Power Caps: Min power = %d, Max power = %d\n"), pJoinReq->powerCap.minTxPower, pJoinReq->powerCap.maxTxPower); + limLog(pMac, LOG1, FL("Power Caps: Min power = %d, Max power = %d"), pJoinReq->powerCap.minTxPower, pJoinReq->powerCap.maxTxPower); pJoinReq->supportedChannels.numChnl = *pBuf++; len--; @@ -1184,7 +1183,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) len-= pJoinReq->supportedChannels.numChnl; PELOG2(limLog(pMac, LOG2, - FL("spectrumInd ON: minPower %d, maxPower %d , numChnls %d\n"), + FL("spectrumInd ON: minPower %d, maxPower %d , numChnls %d"), pJoinReq->powerCap.minTxPower, pJoinReq->powerCap.maxTxPower, pJoinReq->supportedChannels.numChnl);) @@ -1203,7 +1202,7 @@ limJoinReqSerDes(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq, tANI_U8 *pBuf) if (limGetBssDescription( pMac, &pJoinReq->bssDescription, len, &lenUsed, pBuf) == eSIR_FAILURE) { - PELOGE(limLog(pMac, LOGE, FL("get bss description failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("get bss description failed"));) return eSIR_FAILURE; } PELOG3(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, (tANI_U8 *) &(pJoinReq->bssDescription), pJoinReq->bssDescription.length + 2);) @@ -1314,7 +1313,7 @@ limAssocIndSerDes(tpAniSirGlobal pMac, tpLimMlmAssocInd pAssocInd, tANI_U8 *pBuf // Fill in length of SME_ASSOC_IND message limCopyU16(pLen, mLen); - PELOG1(limLog(pMac, LOG1, FL("Sending SME_ASSOC_IND length %d bytes:\n"), mLen);) + PELOG1(limLog(pMac, LOG1, FL("Sending SME_ASSOC_IND length %d bytes:"), mLen);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) } /*** end limAssocIndSerDes() ***/ @@ -1363,11 +1362,11 @@ limAssocCnfSerDes(tpAniSirGlobal pMac, tpSirSmeAssocCnf pAssocCnf, tANI_U8 *pBuf if (pAssocCnf->messageType == eWNI_SME_ASSOC_CNF) { - PELOG1(limLog(pMac, LOG1, FL("SME_ASSOC_CNF length %d bytes is:\n"), pAssocCnf->length);) + PELOG1(limLog(pMac, LOG1, FL("SME_ASSOC_CNF length %d bytes is:"), pAssocCnf->length);) } else { - PELOG1(limLog(pMac, LOG1, FL("SME_REASSOC_CNF length %d bytes is:\n"), pAssocCnf->length);) + PELOG1(limLog(pMac, LOG1, FL("SME_REASSOC_CNF length %d bytes is:"), pAssocCnf->length);) } PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, pAssocCnf->length);) @@ -1440,7 +1439,7 @@ limDisassocCnfSerDes(tpAniSirGlobal pMac, tpSirSmeDisassocCnf pDisassocCnf, tANI pDisassocCnf->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_CNF length %d bytes is:\n"), pDisassocCnf->length);) + PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_CNF length %d bytes is:"), pDisassocCnf->length);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, pDisassocCnf->length);) pDisassocCnf->statusCode = (tSirResultCodes) limGetU32(pBuf); @@ -1573,7 +1572,7 @@ limReassocIndSerDes(tpAniSirGlobal pMac, tpLimMlmReassocInd pReassocInd, tANI_U8 // Fill in length of SME_REASSOC_IND message limCopyU16(pLen, mLen); - PELOG1(limLog(pMac, LOG1, FL("Sending SME_REASSOC_IND length %d bytes:\n"), mLen);) + PELOG1(limLog(pMac, LOG1, FL("Sending SME_REASSOC_IND length %d bytes:"), mLen);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) } /*** end limReassocIndSerDes() ***/ @@ -1631,7 +1630,7 @@ limAuthIndSerDes(tpAniSirGlobal pMac, tpLimMlmAuthInd pAuthInd, tANI_U8 *pBuf) limCopyU16(pLen, mLen); - PELOG1(limLog(pMac, LOG1, FL("Sending SME_AUTH_IND length %d bytes:\n"), mLen);) + PELOG1(limLog(pMac, LOG1, FL("Sending SME_AUTH_IND length %d bytes:"), mLen);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, mLen);) } /*** end limAuthIndSerDes() ***/ @@ -1683,7 +1682,7 @@ limSetContextReqSerDes(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetContextReq len = pSetContextReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_SETCONTEXT_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_SETCONTEXT_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG3, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -1816,7 +1815,7 @@ limRemoveKeyReqSerDes(tpAniSirGlobal pMac, tpSirSmeRemoveKeyReq pRemoveKeyReq, t len = pRemoveKeyReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_REMOVEKEY_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_REMOVEKEY_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -1926,7 +1925,7 @@ limDisassocReqSerDes(tpAniSirGlobal pMac, tSirSmeDisassocReq *pDisassocReq, tANI len = pDisassocReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_DISASSOC_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -2023,7 +2022,7 @@ limDeauthReqSerDes(tpAniSirGlobal pMac, tSirSmeDeauthReq *pDeauthReq, tANI_U8 *p len = pDeauthReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_DEAUTH_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_DEAUTH_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -2179,7 +2178,7 @@ limStatSerDes(tpAniSirGlobal pMac, tpAniStaStatStruct pStat, tANI_U8 *pBuf) limCopyU32(pBuf, pStat->nXmitBytes); pBuf += sizeof(tANI_U32); - PELOG1(limLog(pMac, LOG1, FL("STAT: length %d bytes is:\n"), sizeof(tAniStaStatStruct));) + PELOG1(limLog(pMac, LOG1, FL("STAT: length %d bytes is:"), sizeof(tAniStaStatStruct));) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, sizeof(tAniStaStatStruct));) } /*** end limStatSerDes() ***/ @@ -2287,11 +2286,11 @@ limIsSmeGetAssocSTAsReqValid(tpAniSirGlobal pMac, tpSirSmeGetAssocSTAsReq pGetAs pBuf += sizeof(tANI_U32); len -= sizeof(tANI_U32); - PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes \n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes "), len);) if (len < 0) { - PELOGE(limLog(pMac, LOGE, FL("SME_GET_ASSOC_STAS_REQ invalid length\n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_GET_ASSOC_STAS_REQ invalid length"));) return eANI_BOOLEAN_FALSE; } @@ -2336,7 +2335,7 @@ limTkipCntrMeasReqSerDes(tpAniSirGlobal pMac, tpSirSmeTkipCntrMeasReq pTkipCntr len = pTkipCntrMeasReq->length = limGetU16(pBuf); pBuf += sizeof(tANI_U16); - PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length %d bytes is:\n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length %d bytes is:"), len);) PELOG1(sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG1, pTemp, len);) if (len < (tANI_S16) sizeof(tANI_U32)) @@ -2370,11 +2369,11 @@ limTkipCntrMeasReqSerDes(tpAniSirGlobal pMac, tpSirSmeTkipCntrMeasReq pTkipCntr pTkipCntrMeasReq->bEnable = *pBuf++; len --; - PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length consumed %d bytes \n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_TKIP_CNTR_MEAS_REQ length consumed %d bytes "), len);) if (len) { - PELOGE(limLog(pMac, LOGE, FL("SME_TKIP_CNTR_MEAS_REQ invalid \n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_TKIP_CNTR_MEAS_REQ invalid "));) return eSIR_FAILURE; } else @@ -2445,11 +2444,11 @@ limIsSmeGetWPSPBCSessionsReqValid(tpAniSirGlobal pMac, tSirSmeGetWPSPBCSessionsR pBuf += sizeof(tSirMacAddr); len -= sizeof(tSirMacAddr); - PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes \n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_GET_ASSOC_STAS_REQ length consumed %d bytes "), len);) if (len < 0) { - PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length\n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length"));) return eSIR_FAILURE; } @@ -2477,7 +2476,7 @@ limGetSessionInfo(tpAniSirGlobal pMac, tANI_U8 *pBuf, tANI_U8 *sessionId, tANI_U { if (!pBuf) { - limLog(pMac, LOGE, FL("NULL ptr received. \n")); + limLog(pMac, LOGE, FL("NULL ptr received. ")); return; } @@ -2565,11 +2564,11 @@ limUpdateAPWPSIEsReqSerDes(tpAniSirGlobal pMac, tpSirUpdateAPWPSIEsReq pUpdateAP pBuf += sizeof(tSirAPWPSIEs); len -= sizeof(tSirAPWPSIEs); - PELOG1(limLog(pMac, LOG1, FL("SME_UPDATE_APWPSIE_REQ length consumed %d bytes \n"), len);) + PELOG1(limLog(pMac, LOG1, FL("SME_UPDATE_APWPSIE_REQ length consumed %d bytes "), len);) if (len < 0) { - PELOGE(limLog(pMac, LOGE, FL("SME_UPDATE_APWPSIE_REQ invalid length\n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_UPDATE_APWPSIE_REQ invalid length"));) return eSIR_FAILURE; } @@ -2651,7 +2650,7 @@ limUpdateAPWPARSNIEsReqSerDes(tpAniSirGlobal pMac, tpSirUpdateAPWPARSNIEsReq pUp if (len < 0) { - PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length\n"));) + PELOGE(limLog(pMac, LOGE, FL("SME_GET_WPSPBC_SESSION_REQ invalid length"));) return eSIR_FAILURE; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c index 97a76e7a12c..805856c3949 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSession.c @@ -129,14 +129,14 @@ tpPESession peCreateSession(tpAniSirGlobal pMac, tANI_U8 *bssid , tANI_U8* sessi if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **) &pMac->lim.gpSession[i].dph.dphHashTable.pHashTable, sizeof(tpDphHashNode)*numSta)) { - limLog(pMac, LOGE, FL("memory allocate failed!\n")); + limLog(pMac, LOGE, FL("memory allocate failed!")); return NULL; } if (eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **) &pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray, sizeof(tDphHashNode)*numSta)) { - limLog(pMac, LOGE, FL("memory allocate failed!\n")); + limLog(pMac, LOGE, FL("memory allocate failed!")); palFreeMemory(pMac->hHdd,pMac->lim.gpSession[i].dph.dphHashTable.pHashTable); return NULL; } @@ -149,7 +149,7 @@ tpPESession peCreateSession(tpAniSirGlobal pMac, tANI_U8 *bssid , tANI_U8* sessi (void **) &pMac->lim.gpSession[i].gpLimPeerIdxpool, sizeof(*pMac->lim.gpSession[i].gpLimPeerIdxpool) * (numSta+1))) { - PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!\n"));) + PELOGE(limLog(pMac, LOGE, FL("memory allocate failed!"));) palFreeMemory(pMac->hHdd,pMac->lim.gpSession[i].dph.dphHashTable.pHashTable); palFreeMemory(pMac->hHdd,pMac->lim.gpSession[i].dph.dphHashTable.pDphNodeArray); return NULL; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSessionUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSessionUtils.c index d6b0ef1d701..fe5b6a20d5b 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSessionUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSessionUtils.c @@ -1,50 +1,30 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /**========================================================================= \file limSessionUtils.c \brief implementation for lim Session Utility APIs \author Sunit Bhatia + Copyright 2008 (c) Qualcomm Technologies, Inc. All Rights Reserved. ========================================================================*/ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSmeReqUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSmeReqUtils.c index 5ee773781da..f7f8f5ac591 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limSmeReqUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limSmeReqUtils.c @@ -97,14 +97,14 @@ limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) &privacy) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve POI from CFG\n")); + FL("Unable to retrieve POI from CFG")); } if (wlan_cfgGetInt(pMac, WNI_CFG_RSN_ENABLED, &val) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve RSN_ENABLED from CFG\n")); + FL("Unable to retrieve RSN_ENABLED from CFG")); } if (pRSNie->length && (!privacy || !val)) @@ -115,7 +115,7 @@ limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) * allow BSS creation/join with no Privacy capability * yet advertising WPA IE */ - PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d\n"), + PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d"), pRSNie->length, privacy, val);) } @@ -128,7 +128,7 @@ limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) #endif ) { - limLog(pMac, LOGE, FL("RSN/WPA/WAPI EID %d not [%d || %d]\n"), + limLog(pMac, LOGE, FL("RSN/WPA/WAPI EID %d not [%d || %d]"), pRSNie->rsnIEdata[0], DOT11F_EID_RSN, DOT11F_EID_WPA); return false; @@ -143,49 +143,53 @@ limIsRSNieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirRSNie pRSNie) { if((pRSNie->rsnIEdata[startPos+1] > DOT11F_IE_RSN_MAX_LEN) || (pRSNie->rsnIEdata[startPos+1] < DOT11F_IE_RSN_MIN_LEN)) - { - limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]\n"), - pRSNie->rsnIEdata[startPos+1], DOT11F_IE_RSN_MIN_LEN, - DOT11F_IE_RSN_MAX_LEN); - return false; - } + { + limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]"), + pRSNie->rsnIEdata[startPos+1], DOT11F_IE_RSN_MIN_LEN, + DOT11F_IE_RSN_MAX_LEN); + return false; + } } else if(pRSNie->rsnIEdata[startPos] == DOT11F_EID_WPA) - { - // Check validity of WPA IE - val = sirReadU32((tANI_U8 *) &pRSNie->rsnIEdata[startPos + 2]); - if((pRSNie->rsnIEdata[startPos + 1] < DOT11F_IE_WPA_MIN_LEN) || - (pRSNie->rsnIEdata[startPos + 1] > DOT11F_IE_WPA_MAX_LEN) || - (SIR_MAC_WPA_OUI != val)) { - limLog(pMac, LOGE, - FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x\n"), - pRSNie->rsnIEdata[startPos+1], DOT11F_IE_WPA_MIN_LEN, - DOT11F_IE_WPA_MAX_LEN, val, SIR_MAC_WPA_OUI); - - return false; + // Check validity of WPA IE + if (SIR_MAC_MAX_IE_LENGTH > startPos) + { + if (startPos <= (SIR_MAC_MAX_IE_LENGTH - sizeof(tANI_U32))) + val = sirReadU32((tANI_U8 *) &pRSNie->rsnIEdata[startPos + 2]); + if((pRSNie->rsnIEdata[startPos + 1] < DOT11F_IE_WPA_MIN_LEN) || + (pRSNie->rsnIEdata[startPos + 1] > DOT11F_IE_WPA_MAX_LEN) || + (SIR_MAC_WPA_OUI != val)) + { + limLog(pMac, LOGE, + FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"), + pRSNie->rsnIEdata[startPos+1], DOT11F_IE_WPA_MIN_LEN, + DOT11F_IE_WPA_MAX_LEN, val, SIR_MAC_WPA_OUI); + + return false; + } + } } - } #ifdef FEATURE_WLAN_WAPI else if(pRSNie->rsnIEdata[startPos] == DOT11F_EID_WAPI) { if((pRSNie->rsnIEdata[startPos+1] > DOT11F_IE_WAPI_MAX_LEN) || (pRSNie->rsnIEdata[startPos+1] < DOT11F_IE_WAPI_MIN_LEN)) - { + { limLog(pMac, LOGE, - FL("WAPI IE len %d not [%d,%d]\n"), + FL("WAPI IE len %d not [%d,%d]"), pRSNie->rsnIEdata[startPos+1], DOT11F_IE_WAPI_MIN_LEN, DOT11F_IE_WAPI_MAX_LEN); return false; } - } + } #endif else - { + { //we will never be here, simply for completeness - return false; - } + return false; + } startPos += 2 + pRSNie->rsnIEdata[startPos+1]; //EID + length field + length len -= startPos; }//while @@ -232,7 +236,7 @@ limIsAddieValidInSmeReqMessage(tpAniSirGlobal pMac, tpSirAddie pAddie) if(elem_len > left) { limLog( pMac, LOGE, - FL("****Invalid Add IEs eid = %d elem_len=%d left=%d*****\n"), + FL("****Invalid Add IEs eid = %d elem_len=%d left=%d*****"), elem_id,elem_len,left); return false; } @@ -277,14 +281,14 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, &privacy) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve POI from CFG\n")); + FL("Unable to retrieve POI from CFG")); } if (wlan_cfgGetInt(pMac, WNI_CFG_RSN_ENABLED, &val) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve RSN_ENABLED from CFG\n")); + FL("Unable to retrieve RSN_ENABLED from CFG")); } if (pRSNie->length && (!privacy || !val)) @@ -295,7 +299,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, * allow BSS creation/join with no Privacy capability * yet advertising WPA IE */ - PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d\n"), + PELOG1(limLog(pMac, LOG1, FL("RSN ie len %d but PRIVACY %d RSN %d"), pRSNie->length, privacy, val);) } @@ -304,7 +308,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, if ((pRSNie->rsnIEdata[0] != SIR_MAC_RSN_EID) && (pRSNie->rsnIEdata[0] != SIR_MAC_WPA_EID)) { - limLog(pMac, LOGE, FL("RSN/WPA EID %d not [%d || %d]\n"), + limLog(pMac, LOGE, FL("RSN/WPA EID %d not [%d || %d]"), pRSNie->rsnIEdata[0], SIR_MAC_RSN_EID, SIR_MAC_WPA_EID); return false; @@ -317,7 +321,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, #endif (pRSNie->rsnIEdata[1] < SIR_MAC_RSN_IE_MIN_LENGTH)) { - limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]\n"), + limLog(pMac, LOGE, FL("RSN IE len %d not [%d,%d]"), pRSNie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH, SIR_MAC_RSN_IE_MAX_LENGTH); return false; @@ -329,14 +333,14 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, { limLog(pMac, LOGE, - FL("First byte[%d] in rsnIEdata is not RSN_EID\n"), + FL("First byte[%d] in rsnIEdata is not RSN_EID"), pRSNie->rsnIEdata[1]); return false; } limLog(pMac, LOG1, - FL("WPA IE is present along with WPA2 IE\n")); + FL("WPA IE is present along with WPA2 IE")); wpaIndex = 2 + pRSNie->rsnIEdata[1]; } else if ((pRSNie->length == pRSNie->rsnIEdata[1] + 2) && @@ -344,7 +348,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, { limLog(pMac, LOG1, - FL("Only RSN IE is present\n")); + FL("Only RSN IE is present")); dot11fUnpackIeRSN(pMac,&pRSNie->rsnIEdata[2], (tANI_U8)pRSNie->length,&pSessionEntry->gStartBssRSNIe); } @@ -353,7 +357,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, { limLog(pMac, LOG1, - FL("Only WPA IE is present\n")); + FL("Only WPA IE is present")); dot11fUnpackIeWPA(pMac,&pRSNie->rsnIEdata[6],(tANI_U8)pRSNie->length-4, &pSessionEntry->gStartBssWPAIe); @@ -372,7 +376,7 @@ limSetRSNieWPAiefromSmeStartBSSReqMessage(tpAniSirGlobal pMac, (SIR_MAC_WPA_OUI != val))) { limLog(pMac, LOGE, - FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x\n"), + FL("WPA IE len %d not [%d,%d] OR data 0x%x not 0x%x"), pRSNie->rsnIEdata[1], SIR_MAC_RSN_IE_MIN_LENGTH, SIR_MAC_RSN_IE_MAX_LENGTH, val, SIR_MAC_WPA_OUI); @@ -471,7 +475,7 @@ limIsSmeStartReqValid(tpAniSirGlobal pMac, tANI_U32 *pMsg) * Log error. */ limLog(pMac, LOGW, - FL("Invalid length %d in eWNI_SME_START_REQ\n"), + FL("Invalid length %d in eWNI_SME_START_REQ"), ((tpSirSmeStartReq) pMsg)->length); valid = false; @@ -512,7 +516,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, tANI_U8 valid = true; PELOG1(limLog(pMac, LOG1, - FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d, SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d\n"), + FL("Parsed START_BSS_REQ fields are bssType=%d, channelId=%d, SSID len=%d, rsnIE len=%d, nwType=%d, rateset len=%d"), pStartBssReq->bssType, pStartBssReq->channelId, pStartBssReq->ssId.length, @@ -557,7 +561,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, * Log error */ limLog(pMac, LOGW, - FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ\n"), + FL("Invalid bssType %d in eWNI_SME_START_BSS_REQ"), pStartBssReq->bssType); valid = false; @@ -573,7 +577,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, // Invalid length for SSID. // Reject START_BSS_REQ limLog(pMac, LOGW, - FL("Invalid SSID length in eWNI_SME_START_BSS_REQ\n")); + FL("Invalid SSID length in eWNI_SME_START_BSS_REQ")); valid = false; goto end; @@ -603,7 +607,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, // Invalid Operational rates // Reject START_BSS_REQ limLog(pMac, LOGW, - FL("Invalid operational rates in eWNI_SME_START_BSS_REQ\n")); + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, pStartBssReq->operationalRateSet.rate, pStartBssReq->operationalRateSet.numRates); @@ -621,7 +625,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, // Invalid Operational rates // Reject START_BSS_REQ limLog(pMac, LOGW, - FL("Invalid operational rates in eWNI_SME_START_BSS_REQ\n")); + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, pStartBssReq->operationalRateSet.rate, pStartBssReq->operationalRateSet.numRates); @@ -638,7 +642,7 @@ limIsSmeStartBssReqValid(tpAniSirGlobal pMac, // Invalid Operational rates // Reject START_BSS_REQ limLog(pMac, LOGW, - FL("Invalid operational rates in eWNI_SME_START_BSS_REQ\n")); + FL("Invalid operational rates in eWNI_SME_START_BSS_REQ")); sirDumpBuf(pMac, SIR_LIM_MODULE_ID, LOG2, pStartBssReq->operationalRateSet.rate, pStartBssReq->operationalRateSet.numRates); @@ -683,7 +687,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) if (!limIsRSNieValidInSmeReqMessage(pMac, &pJoinReq->rsnIE)) { limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with invalid RSNIE\n")); + FL("received SME_JOIN_REQ with invalid RSNIE")); valid = false; goto end; } @@ -691,7 +695,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) if (!limIsAddieValidInSmeReqMessage(pMac, &pJoinReq->addIEScan)) { limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with invalid additional IE for scan\n")); + FL("received SME_JOIN_REQ with invalid additional IE for scan")); valid = false; goto end; } @@ -699,7 +703,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) if (!limIsAddieValidInSmeReqMessage(pMac, &pJoinReq->addIEAssoc)) { limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with invalid additional IE for assoc\n")); + FL("received SME_JOIN_REQ with invalid additional IE for assoc")); valid = false; goto end; } @@ -711,7 +715,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) /// Received eWNI_SME_JOIN_REQ with invalid BSS Info // Log the event limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with invalid bssInfo\n")); + FL("received SME_JOIN_REQ with invalid bssInfo")); valid = false; goto end; @@ -727,7 +731,7 @@ limIsSmeJoinReqValid(tpAniSirGlobal pMac, tpSirSmeJoinReq pJoinReq) { // Log the event limLog(pMac, LOGE, - FL("received SME_JOIN_REQ with Self Mac and BSSID Same\n")); + FL("received SME_JOIN_REQ with Self Mac and BSSID Same")); valid = false; goto end; @@ -888,7 +892,7 @@ limIsSmeScanReqValid(tpAniSirGlobal pMac, tpSirSmeScanReq pScanReq) if ((pScanReq->scanType == eSIR_ACTIVE_SCAN) && (pScanReq->maxChannelTime < pScanReq->minChannelTime)) { - PELOGW(limLog(pMac, LOGW, FL("Max Channel Time < Min Channel Time\n"));) + PELOGW(limLog(pMac, LOGW, FL("Max Channel Time < Min Channel Time"));) valid = false; goto end; } @@ -976,7 +980,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * Log error. */ limLog(pMac, LOGW, - FL("No keys present in SME_SETCONTEXT_REQ for edType=%d\n"), + FL("No keys present in SME_SETCONTEXT_REQ for edType=%d"), pSetContextReq->keyMaterial.edType); valid = false; @@ -991,7 +995,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * Log error. */ limLog(pMac, LOGW, - FL("Keys present in SME_SETCONTEXT_REQ for edType=%d\n"), + FL("Keys present in SME_SETCONTEXT_REQ for edType=%d"), pSetContextReq->keyMaterial.edType); valid = false; @@ -1005,7 +1009,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * Log error. */ limLog(pMac, LOGW, - FL("Invalid edType=%d in SME_SETCONTEXT_REQ\n"), + FL("Invalid edType=%d in SME_SETCONTEXT_REQ"), pSetContextReq->keyMaterial.edType); valid = false; @@ -1019,7 +1023,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte &poi) != eSIR_SUCCESS) { limLog(pMac, LOGP, - FL("Unable to retrieve POI from CFG\n")); + FL("Unable to retrieve POI from CFG")); } if (!poi) @@ -1031,7 +1035,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * yet advertising WPA IE */ PELOG1(limLog(pMac, LOG1, - FL("Privacy is not enabled, yet non-None EDtype=%d in SME_SETCONTEXT_REQ\n"), + FL("Privacy is not enabled, yet non-None EDtype=%d in SME_SETCONTEXT_REQ"), pSetContextReq->keyMaterial.edType);) } } @@ -1056,7 +1060,7 @@ limIsSmeSetContextReqValid(tpAniSirGlobal pMac, tpSirSmeSetContextReq pSetConte * Log error. */ limLog(pMac, LOGW, - FL("Invalid keyLength =%d for edType=%d in SME_SETCONTEXT_REQ\n"), + FL("Invalid keyLength =%d for edType=%d in SME_SETCONTEXT_REQ"), pKey->keyLength, pSetContextReq->keyMaterial.edType); valid = false; diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limStaHashApi.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limStaHashApi.c index 3027cb74fa8..7e1920894cb 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limStaHashApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limStaHashApi.c @@ -19,28 +19,6 @@ * PERFORMANCE OF THIS SOFTWARE. */ /* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * * Airgo Networks, Inc proprietary. All rights reserved. * limStaHashApi.c: Provides access functions to get/set values of station hash entry fields. * Author: Sunit Bhatia @@ -82,7 +60,7 @@ tSirRetStatus limGetStaHashBssidx(tpAniSirGlobal pMac, tANI_U16 assocId, tANI_U8 if (pSta == NULL) { - PELOGE(limLog(pMac, LOGE, FL("invalid STA %d\n"), assocId);) + PELOGE(limLog(pMac, LOGE, FL("invalid STA %d"), assocId);) return eSIR_LIM_INVALID_STA; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c index f5b630bc227..08dffa04000 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTimerUtils.c @@ -102,7 +102,7 @@ limCreateTimers(tpAniSirGlobal pMac) { tANI_U32 cfgValue, i=0; - PELOG1(limLog(pMac, LOG1, FL("Creating Timers used by LIM module in Role %d\n"), pMac->lim.gLimSystemRole);) + PELOG1(limLog(pMac, LOG1, FL("Creating Timers used by LIM module in Role %d"), pMac->lim.gLimSystemRole);) if (wlan_cfgGetInt(pMac, WNI_CFG_ACTIVE_MINIMUM_CHANNEL_TIME, &cfgValue) != eSIR_SUCCESS) @@ -111,7 +111,7 @@ limCreateTimers(tpAniSirGlobal pMac) * Could not get MinChannelTimeout value * from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve MinChannelTimeout value\n")); + limLog(pMac, LOGP, FL("could not retrieve MinChannelTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -124,10 +124,10 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not start min channel timer. // Log error - limLog(pMac, LOGP, FL("could not create MIN channel timer\n")); + limLog(pMac, LOGP, FL("could not create MIN channel timer")); return TX_TIMER_ERROR; } - PELOG2(limLog(pMac, LOG2, FL("Created MinChannelTimer\n"));) + PELOG2(limLog(pMac, LOG2, FL("Created MinChannelTimer"));) /* Periodic probe request timer value is half of the Min channel * timer. Probe request sends periodically till min/max channel @@ -146,7 +146,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not start Periodic Probe Req timer. // Log error - limLog(pMac, LOGP, FL("could not create periodic probe timer\n")); + limLog(pMac, LOGP, FL("could not create periodic probe timer")); goto err_timer; } } @@ -160,7 +160,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve MAXChannelTimeout value\n")); + FL("could not retrieve MAXChannelTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -172,11 +172,11 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not start max channel timer. // Log error - limLog(pMac, LOGP, FL("could not create MAX channel timer\n")); + limLog(pMac, LOGP, FL("could not create MAX channel timer")); goto err_timer; } - PELOG2(limLog(pMac, LOG2, FL("Created MaxChannelTimer\n"));) + PELOG2(limLog(pMac, LOG2, FL("Created MaxChannelTimer"));) if (pMac->lim.gLimSystemRole != eLIM_AP_ROLE) { @@ -189,7 +189,7 @@ limCreateTimers(tpAniSirGlobal pMac) 0, // reschedule_ticks TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("failed to create Channel Switch timer\n")); + limLog(pMac, LOGP, FL("failed to create Channel Switch timer")); goto err_timer; } @@ -206,7 +206,7 @@ limCreateTimers(tpAniSirGlobal pMac) 0, // reschedule_ticks TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer\n")); + limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer")); goto err_timer; } @@ -225,7 +225,7 @@ limCreateTimers(tpAniSirGlobal pMac) 0, // reschedule_ticks TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer\n")); + limLog(pMac, LOGP, FL("failed to create Quiet Begin Timer")); goto err_timer; } @@ -237,7 +237,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve JoinFailureTimeout value\n")); + FL("could not retrieve JoinFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -250,7 +250,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not create Join failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Join failure timer\n")); + limLog(pMac, LOGP, FL("could not create Join failure timer")); goto err_timer; } @@ -264,7 +264,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not create Periodic Join Probe Request timer. // Log error - limLog(pMac, LOGP, FL("could not create Periodic Join Probe Request timer\n")); + limLog(pMac, LOGP, FL("could not create Periodic Join Probe Request timer")); goto err_timer; } @@ -276,7 +276,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AssocFailureTimeout value\n")); + FL("could not retrieve AssocFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -290,7 +290,7 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not create Assoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not create Association failure timer\n")); + FL("could not create Association failure timer")); goto err_timer; } @@ -302,7 +302,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve ReassocFailureTimeout value\n")); + FL("could not retrieve ReassocFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -316,13 +316,13 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not create Reassoc failure timer. // Log error limLog(pMac, LOGP, - FL("could not create Reassociation failure timer\n")); + FL("could not create Reassociation failure timer")); goto err_timer; } if (wlan_cfgGetInt(pMac, WNI_CFG_ADDTS_RSP_TIMEOUT, &cfgValue) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_ADDTS_RSP_TIMEOUT \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_ADDTS_RSP_TIMEOUT ")); cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -336,7 +336,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not create Auth failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Addts response timer\n")); + limLog(pMac, LOGP, FL("could not create Addts response timer")); goto err_timer; } @@ -349,7 +349,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthFailureTimeout value\n")); + FL("could not retrieve AuthFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -363,7 +363,7 @@ limCreateTimers(tpAniSirGlobal pMac) { /// Could not create Auth failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Auth failure timer\n")); + limLog(pMac, LOGP, FL("could not create Auth failure timer")); goto err_timer; } @@ -376,7 +376,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve BEACON_INTERVAL value\n")); + FL("could not retrieve BEACON_INTERVAL value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -391,7 +391,7 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not start Heartbeat timer. // Log error limLog(pMac, LOGP, - FL("call to create heartbeat timer failed\n")); + FL("call to create heartbeat timer failed")); goto err_timer; } @@ -403,7 +403,7 @@ limCreateTimers(tpAniSirGlobal pMac) * value from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value\n")); + FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value")); } // Change timer to reactivate it in future @@ -420,7 +420,7 @@ limCreateTimers(tpAniSirGlobal pMac) // Could not creat wt-probe-after-HeartBeat-failure timer. // Log error limLog(pMac, LOGP, - FL("unable to create ProbeAfterHBTimer\n")); + FL("unable to create ProbeAfterHBTimer")); goto err_timer; } @@ -432,7 +432,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Background scan period value\n")); + FL("could not retrieve Background scan period value")); } /* @@ -462,7 +462,7 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not start background scan timer. // Log error limLog(pMac, LOGP, - FL("call to create background scan timer failed\n")); + FL("call to create background scan timer failed")); goto err_timer; } #ifdef FEATURE_WLAN_TDLS_INTERNAL @@ -479,7 +479,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve ReassocFailureTimeout value\n")); + FL("could not retrieve ReassocFailureTimeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -494,7 +494,7 @@ limCreateTimers(tpAniSirGlobal pMac) TX_NO_ACTIVATE) != TX_SUCCESS) { limLog(pMac, LOGP, - FL("could not create TDLS discovery response wait timer\n")); + FL("could not create TDLS discovery response wait timer")); goto err_timer; } #endif @@ -515,11 +515,11 @@ limCreateTimers(tpAniSirGlobal pMac) /// Could not start Send Disassociate Frame Threshold timer. // Log error limLog(pMac, LOGP, - FL("create Disassociate throttle timer failed\n")); + FL("create Disassociate throttle timer failed")); goto err_timer; } PELOG1(limLog(pMac, LOG1, - FL("Created Disassociate throttle timer \n"));) + FL("Created Disassociate throttle timer "));) /** * Create keepalive timer and activate it right away for AP role @@ -533,7 +533,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve keepalive timeout value\n")); + FL("could not retrieve keepalive timeout value")); } // A value of zero implies keep alive should be disabled @@ -558,7 +558,7 @@ limCreateTimers(tpAniSirGlobal pMac) != TX_SUCCESS) { // Cannot create keepalive timer. Log error. - limLog(pMac, LOGP, FL("Cannot create keepalive timer.\n")); + limLog(pMac, LOGP, FL("Cannot create keepalive timer.")); goto err_timer; } @@ -574,7 +574,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve CNF timeout value\n")); + FL("could not retrieve CNF timeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -589,7 +589,7 @@ limCreateTimers(tpAniSirGlobal pMac) TX_NO_ACTIVATE) != TX_SUCCESS) { // Cannot create timer. Log error. - limLog(pMac, LOGP, FL("Cannot create CNF wait timer.\n")); + limLog(pMac, LOGP, FL("Cannot create CNF wait timer.")); goto err_timer; } } @@ -608,18 +608,18 @@ limCreateTimers(tpAniSirGlobal pMac) ** from CFG. Log error. **/ limLog(pMac, LOGP, - FL("could not retrieve mac preauth value\n")); + FL("could not retrieve mac preauth value")); } pMac->lim.gLimPreAuthTimerTable.numEntry = cfgValue; if (palAllocateMemory(pMac->hHdd, (void **) &pMac->lim.gLimPreAuthTimerTable.pTable, cfgValue*sizeof(tLimPreAuthNode)) != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("palAllocateMemory failed!\n")); + limLog(pMac, LOGP, FL("palAllocateMemory failed!")); goto err_timer; } limInitPreAuthTimerTable(pMac, &pMac->lim.gLimPreAuthTimerTable); - PELOG1(limLog(pMac, LOG1, FL("alloc and init table for preAuth timers\n"));) + PELOG1(limLog(pMac, LOG1, FL("alloc and init table for preAuth timers"));) { @@ -634,7 +634,7 @@ limCreateTimers(tpAniSirGlobal pMac) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve OLBD detect timeout value\n")); + FL("could not retrieve OLBD detect timeout value")); } cfgValue = SYS_MS_TO_TICKS(cfgValue); @@ -650,7 +650,7 @@ limCreateTimers(tpAniSirGlobal pMac) { // Cannot create update OLBC cache timer // Log error - limLog(pMac, LOGP, FL("Cannot create update OLBC cache timer\n")); + limLog(pMac, LOGP, FL("Cannot create update OLBC cache timer")); goto err_timer; } } @@ -670,7 +670,7 @@ limCreateTimers(tpAniSirGlobal pMac) { // Could not create Join failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Join failure timer\n")); + limLog(pMac, LOGP, FL("could not create Join failure timer")); goto err_timer; } #endif @@ -687,7 +687,7 @@ limCreateTimers(tpAniSirGlobal pMac) { // Could not create Join failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Join failure timer\n")); + limLog(pMac, LOGP, FL("could not create Join failure timer")); goto err_timer; } #endif @@ -702,7 +702,7 @@ limCreateTimers(tpAniSirGlobal pMac) { // Could not create Join failure timer. // Log error - limLog(pMac, LOGP, FL("could not create Join failure timer\n")); + limLog(pMac, LOGP, FL("could not create Join failure timer")); goto err_timer; } @@ -715,7 +715,7 @@ limCreateTimers(tpAniSirGlobal pMac) cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not DISASSOC ACK TIMEOUT timer\n")); + limLog(pMac, LOGP, FL("could not DISASSOC ACK TIMEOUT timer")); goto err_timer; } @@ -727,7 +727,7 @@ limCreateTimers(tpAniSirGlobal pMac) cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not create DEAUTH ACK TIMEOUT timer\n")); + limLog(pMac, LOGP, FL("could not create DEAUTH ACK TIMEOUT timer")); goto err_timer; } @@ -739,7 +739,7 @@ limCreateTimers(tpAniSirGlobal pMac) cfgValue, 0, TX_NO_ACTIVATE) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("could not create Single Shot NOA Insert Timeout timer\n")); + limLog(pMac, LOGP, FL("could not create Single Shot NOA Insert Timeout timer")); goto err_timer; } @@ -840,7 +840,7 @@ limTimerHandler(void *pMacGlobal, tANI_U32 param) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting message %X to LIM failed, reason=%d\n"), + FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); } /****** end limTimerHandler() ******/ @@ -952,17 +952,17 @@ limAssocFailureTimerHandler(void *pMacGlobal, tANI_U32 param) if((LIM_REASSOC == param) && (NULL != pMac->lim.pSessionEntry)) { - limLog(pMac, LOGE, FL("Reassoc timeout happened\n")); + limLog(pMac, LOGE, FL("Reassoc timeout happened")); if(pMac->lim.reAssocRetryAttempt < LIM_MAX_REASSOC_RETRY_LIMIT) { limSendRetryReassocReqFrame(pMac, pMac->lim.pSessionEntry->pLimMlmReassocRetryReq, pMac->lim.pSessionEntry); pMac->lim.reAssocRetryAttempt++; - limLog(pMac, LOGW, FL("Reassoc request retry is sent %d times\n"), pMac->lim.reAssocRetryAttempt); + limLog(pMac, LOGW, FL("Reassoc request retry is sent %d times"), pMac->lim.reAssocRetryAttempt); return; } else { - limLog(pMac, LOGW, FL("Reassoc request retry MAX(%d) reached\n"), LIM_MAX_REASSOC_RETRY_LIMIT); + limLog(pMac, LOGW, FL("Reassoc request retry MAX(%d) reached"), LIM_MAX_REASSOC_RETRY_LIMIT); if(NULL != pMac->lim.pSessionEntry->pLimMlmReassocRetryReq) { palFreeMemory( pMac->hHdd, pMac->lim.pSessionEntry->pLimMlmReassocRetryReq); @@ -1055,7 +1055,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate AddtsRsp Timer // Log error limLog(pMac, LOGP, - FL("Unable to deactivate AddtsRsp timer\n")); + FL("Unable to deactivate AddtsRsp timer")); } break; @@ -1066,7 +1066,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate min channel timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate min channel timer\n")); + FL("Unable to deactivate min channel timer")); } #if 0 @@ -1115,7 +1115,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not change min channel timer. // Log error - limLog(pMac, LOGP, FL("Unable to change min channel timer\n")); + limLog(pMac, LOGP, FL("Unable to change min channel timer")); } break; @@ -1127,7 +1127,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate min channel timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate periodic timer\n")); + FL("Unable to deactivate periodic timer")); } val = SYS_MS_TO_TICKS(pMac->lim.gpLimMlmScanReq->minChannelTime)/2; @@ -1147,7 +1147,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not change min channel timer. // Log error - limLog(pMac, LOGP, FL("Unable to change periodic timer\n")); + limLog(pMac, LOGP, FL("Unable to change periodic timer")); } break; @@ -1159,7 +1159,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate max channel timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate max channel timer\n")); + FL("Unable to deactivate max channel timer")); } // If a background was triggered via Quiet BSS, @@ -1213,7 +1213,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change max channel timer. // Log error limLog(pMac, LOGP, - FL("Unable to change max channel timer\n")); + FL("Unable to change max channel timer")); } break; @@ -1227,7 +1227,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * timer. Log error. */ limLog(pMac, LOGP, - FL("Unable to deactivate Join Failure timer\n")); + FL("Unable to deactivate Join Failure timer")); } if (wlan_cfgGetInt(pMac, WNI_CFG_JOIN_FAILURE_TIMEOUT, @@ -1238,7 +1238,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve JoinFailureTimeout value\n")); + FL("could not retrieve JoinFailureTimeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1250,7 +1250,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * timer. Log error. */ limLog(pMac, LOGP, - FL("Unable to change Join Failure timer\n")); + FL("Unable to change Join Failure timer")); } break; @@ -1261,7 +1261,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not deactivate periodic join req Times. limLog(pMac, LOGP, - FL("Unable to deactivate periodic join request timer\n")); + FL("Unable to deactivate periodic join request timer")); } val = SYS_MS_TO_TICKS(LIM_JOIN_PROBE_REQ_TIMER_MS); @@ -1270,7 +1270,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not change periodic join req times. // Log error - limLog(pMac, LOGP, FL("Unable to change periodic join request timer\n")); + limLog(pMac, LOGP, FL("Unable to change periodic join request timer")); } break; @@ -1282,7 +1282,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Auth failure timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate auth failure timer\n")); + FL("Unable to deactivate auth failure timer")); } // Change timer to reactivate it in future @@ -1294,7 +1294,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AuthFailureTimeout value\n")); + FL("could not retrieve AuthFailureTimeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1304,7 +1304,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change Authentication failure timer. // Log error limLog(pMac, LOGP, - FL("unable to change Auth failure timer\n")); + FL("unable to change Auth failure timer")); } break; @@ -1316,7 +1316,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Association failure timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate Association failure timer\n")); + FL("unable to deactivate Association failure timer")); } // Change timer to reactivate it in future @@ -1328,7 +1328,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve AssocFailureTimeout value\n")); + FL("could not retrieve AssocFailureTimeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1338,7 +1338,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change Association failure timer. // Log error limLog(pMac, LOGP, - FL("unable to change Assoc failure timer\n")); + FL("unable to change Assoc failure timer")); } break; @@ -1350,7 +1350,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Reassociation failure timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate Reassoc failure timer\n")); + FL("unable to deactivate Reassoc failure timer")); } // Change timer to reactivate it in future @@ -1362,7 +1362,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve ReassocFailureTimeout value\n")); + FL("could not retrieve ReassocFailureTimeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1372,7 +1372,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change Reassociation failure timer. // Log error limLog(pMac, LOGP, - FL("unable to change Reassociation failure timer\n")); + FL("unable to change Reassociation failure timer")); } break; @@ -1384,7 +1384,11 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Heartbeat timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate Heartbeat timer\n")); + FL("unable to deactivate Heartbeat timer")); + } + else + { + limLog(pMac, LOGW, FL("Deactivated heartbeat link monitoring")); } if (wlan_cfgGetInt(pMac, WNI_CFG_BEACON_INTERVAL, @@ -1395,13 +1399,13 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve BEACON_INTERVAL value\n")); + FL("could not retrieve BEACON_INTERVAL value")); } if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != eSIR_SUCCESS) limLog(pMac, LOGP, - FL("could not retrieve heartbeat failure value\n")); + FL("could not retrieve heartbeat failure value")); // Change timer to reactivate it in future val = SYS_MS_TO_TICKS(val * val1); @@ -1412,9 +1416,12 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change HeartBeat timer. // Log error limLog(pMac, LOGP, - FL("unable to change HeartBeat timer\n")); + FL("unable to change HeartBeat timer")); + } + else + { + limLog(pMac, LOGW, FL("HeartBeat timer value is changed = %lu"), val); } - break; case eLIM_PROBE_AFTER_HB_TIMER: @@ -1424,7 +1431,11 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Heartbeat timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate probeAfterHBTimer\n")); + FL("unable to deactivate probeAfterHBTimer")); + } + else + { + limLog(pMac, LOGE, FL("Deactivated probe after hb timer")); } if (wlan_cfgGetInt(pMac, WNI_CFG_PROBE_AFTER_HB_FAIL_TIMEOUT, @@ -1435,7 +1446,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * value from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value\n")); + FL("could not retrieve PROBE_AFTER_HB_FAIL_TIMEOUT value")); } // Change timer to reactivate it in future @@ -1447,7 +1458,11 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change HeartBeat timer. // Log error limLog(pMac, LOGP, - FL("unable to change ProbeAfterHBTimer\n")); + FL("unable to change ProbeAfterHBTimer")); + } + else + { + limLog(pMac, LOGW, FL("Probe after HB timer value is changed = %lu"), val); } break; @@ -1459,7 +1474,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Keepalive timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate KeepaliveTimer timer\n")); + FL("unable to deactivate KeepaliveTimer timer")); } // Change timer to reactivate it in future @@ -1472,7 +1487,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve keepalive timeout value\n")); + FL("could not retrieve keepalive timeout value")); } if (val == 0) { @@ -1491,7 +1506,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change KeepaliveTimer timer. // Log error limLog(pMac, LOGP, - FL("unable to change KeepaliveTimer timer\n")); + FL("unable to change KeepaliveTimer timer")); } break; @@ -1503,7 +1518,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate BackgroundScanTimer timer. // Log error limLog(pMac, LOGP, - FL("unable to deactivate BackgroundScanTimer timer\n")); + FL("unable to deactivate BackgroundScanTimer timer")); } // Change timer to reactivate it in future @@ -1515,7 +1530,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve Background scan period value\n")); + FL("could not retrieve Background scan period value")); } if (val == 0) { @@ -1533,7 +1548,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not change BackgroundScanTimer timer. // Log error limLog(pMac, LOGP, - FL("unable to change BackgroundScanTimer timer\n")); + FL("unable to change BackgroundScanTimer timer")); } break; @@ -1542,7 +1557,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) case eLIM_CHANNEL_SWITCH_TIMER: if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("tx_timer_deactivate failed!\n")); + limLog(pMac, LOGP, FL("tx_timer_deactivate failed!")); return; } @@ -1550,7 +1565,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) pMac->lim.gLimChannelSwitch.switchTimeoutValue, 0) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("tx_timer_change failed \n")); + limLog(pMac, LOGP, FL("tx_timer_change failed ")); return; } break; @@ -1565,7 +1580,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer)) { limLog( pMac, LOGE, - FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...\n")); + FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...")); } // gLimQuietDuration appears to be in units of ticks @@ -1576,7 +1591,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) 0)) { limLog( pMac, LOGE, - FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...\n")); + FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...")); } break; @@ -1584,7 +1599,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) if( TX_SUCCESS != tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer)) { limLog( pMac, LOGE, - FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway...\n" )); + FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway..." )); } // Set the NEW timeout value, in ticks @@ -1592,7 +1607,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) SYS_MS_TO_TICKS(pMac->lim.gLimSpecMgmt.quietTimeoutValue), 0)) { limLog( pMac, LOGE, - FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway...\n" )); + FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway..." )); } break; #endif @@ -1610,7 +1625,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) // Could not deactivate Learn Interval timer. // Log error limLog(pMac, LOGP, - FL("Unable to deactivate WPS overlap timer\n")); + FL("Unable to deactivate WPS overlap timer")); } if (tx_timer_change( @@ -1619,13 +1634,13 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) { // Could not change Learn Interval timer. // Log error - limLog(pMac, LOGP, FL("Unable to change WPS overlap timer\n")); + limLog(pMac, LOGP, FL("Unable to change WPS overlap timer")); return; } limLog( pMac, LOGE, - FL("Setting WPS overlap TIMER to %d ticks\n"), + FL("Setting WPS overlap TIMER to %d ticks"), WPSOverlapTimer); } break; @@ -1639,7 +1654,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate Join Failure ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate Preauth response Failure timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate Preauth response Failure timer")); return; } val = 1000; @@ -1651,7 +1666,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Join Failure * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change Join Failure timer\n")); + limLog(pMac, LOGP, FL("Unable to change Join Failure timer")); return; } break; @@ -1661,7 +1676,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) if (tx_timer_deactivate(&pMac->lim.limTimers.gLimCcxTsmTimer) != TX_SUCCESS) { - limLog(pMac, LOGE, FL("Unable to deactivate TSM timer\n")); + limLog(pMac, LOGE, FL("Unable to deactivate TSM timer")); } break; #endif @@ -1672,7 +1687,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate Join Failure ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate Remain on Chn timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate Remain on Chn timer")); return; } val = 1000; @@ -1684,7 +1699,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Join Failure * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change timer\n")); + limLog(pMac, LOGP, FL("Unable to change timer")); return; } break; @@ -1721,7 +1736,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate Join Failure ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate Disassoc ack timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate Disassoc ack timer")); return; } val = 1000; @@ -1733,7 +1748,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Join Failure * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change timer\n")); + limLog(pMac, LOGP, FL("Unable to change timer")); return; } break; @@ -1745,7 +1760,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate Join Failure ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate Deauth ack timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate Deauth ack timer")); return; } val = 1000; @@ -1757,7 +1772,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Join Failure * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change timer\n")); + limLog(pMac, LOGP, FL("Unable to change timer")); return; } break; @@ -1769,7 +1784,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) ** Could not deactivate SingleShot NOA Insert ** timer. Log error. **/ - limLog(pMac, LOGP, FL("Unable to deactivate SingleShot NOA Insert timer\n")); + limLog(pMac, LOGP, FL("Unable to deactivate SingleShot NOA Insert timer")); return; } val = LIM_INSERT_SINGLESHOTNOA_TIMEOUT_VALUE; @@ -1781,7 +1796,7 @@ limDeactivateAndChangeTimer(tpAniSirGlobal pMac, tANI_U32 timerId) * Could not change Single Shot NOA Insert * timer. Log error. */ - limLog(pMac, LOGP, FL("Unable to change timer\n")); + limLog(pMac, LOGP, FL("Unable to change timer")); return; } break; @@ -1808,6 +1823,10 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn { tANI_U32 val, val1; + if (NULL == psessionEntry) + { + return; + } MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_HEART_BEAT_TIMER)); #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) @@ -1815,7 +1834,7 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn #endif if (tx_timer_deactivate(&pMac->lim.limTimers.gLimHeartBeatTimer) != TX_SUCCESS) - limLog(pMac, LOGP, FL("Fail to deactivate HeartBeatTimer \n")); + limLog(pMac, LOGP, FL("Fail to deactivate HeartBeatTimer ")); /* HB Timer sessionisation: In case of 2 or more sessions, the HB interval keeps changing. to avoid this problem, HeartBeat interval is made constant, by @@ -1825,10 +1844,10 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn val = LIM_HB_TIMER_BEACON_INTERVAL; if (wlan_cfgGetInt(pMac, WNI_CFG_HEART_BEAT_THRESHOLD, &val1) != eSIR_SUCCESS) - limLog(pMac, LOGP, FL("Fail to get WNI_CFG_HEART_BEAT_THRESHOLD \n")); + limLog(pMac, LOGP, FL("Fail to get WNI_CFG_HEART_BEAT_THRESHOLD ")); PELOGW(limLog(pMac,LOGW, - FL("HB Timer Int.=100ms * %d, Beacon Int.=%dms,Session Id=%d \n"), + FL("HB Timer Int.=100ms * %d, Beacon Int.=%dms,Session Id=%d "), val1, psessionEntry->beaconParams.beaconInterval, psessionEntry->peSessionId);) @@ -1836,7 +1855,7 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn val = SYS_MS_TO_TICKS(val * val1); if (tx_timer_change(&pMac->lim.limTimers.gLimHeartBeatTimer, val, 0) != TX_SUCCESS) - limLog(pMac, LOGP, FL("Fail to change HeartBeatTimer\n")); + limLog(pMac, LOGP, FL("Fail to change HeartBeatTimer")); } /****** end limHeartBeatDeactivateAndChangeTimer() ******/ @@ -1853,11 +1872,14 @@ limHeartBeatDeactivateAndChangeTimer(tpAniSirGlobal pMac, tpPESession psessionEn void limReactivateHeartBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry) { - PELOG3(limLog(pMac, LOG3, FL("Rxed Heartbeat. Count=%d\n"), psessionEntry->LimRxedBeaconCntDuringHB);) + PELOG3(limLog(pMac, LOG3, FL("Rxed Heartbeat. Count=%d"), psessionEntry->LimRxedBeaconCntDuringHB);) #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE if(IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE) + { + limLog(pMac, LOGW, FL("Active offload feature is enabled, FW takes care of HB monitoring")); return; + } #endif limHeartBeatDeactivateAndChangeTimer(pMac, psessionEntry); @@ -1867,8 +1889,9 @@ limReactivateHeartBeatTimer(tpAniSirGlobal pMac, tpPESession psessionEntry) if(pMac->lim.limTimers.gLimHeartBeatTimer.initScheduleTimeInMsecs > 0) { if (tx_timer_activate(&pMac->lim.limTimers.gLimHeartBeatTimer)!= TX_SUCCESS) { - limLog(pMac, LOGP,FL("could not activate Heartbeat timer\n")); + limLog(pMac, LOGP,FL("could not activate Heartbeat timer")); } + limLog(pMac, LOGW, FL("Reactivated heartbeat link monitoring")); limResetHBPktCount(psessionEntry); } @@ -1911,7 +1934,7 @@ v_UINT_t limActivateHearBeatTimer(tpAniSirGlobal pMac) if( TX_SUCCESS != status ) { PELOGE(limLog(pMac, LOGE, - FL("could not activate Heartbeat timer status(%d)\n"), status);) + FL("could not activate Heartbeat timer status(%d)"), status);) } } else @@ -1961,7 +1984,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ != TX_SUCCESS) { limLog(pMac, LOGP, - FL("unable to deactivate CNF wait timer\n")); + FL("unable to deactivate CNF wait timer")); } @@ -1975,7 +1998,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve cnf timeout value\n")); + FL("could not retrieve cnf timeout value")); } val = SYS_MS_TO_TICKS(val); @@ -1984,7 +2007,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ { // Could not change cnf timer. // Log error - limLog(pMac, LOGP, FL("unable to change cnf wait timer\n")); + limLog(pMac, LOGP, FL("unable to change cnf wait timer")); } break; @@ -1997,7 +2020,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ if (pAuthNode == NULL) { - limLog(pMac, LOGP, FL("Invalid Pre Auth Index passed :%d\n"), staId); + limLog(pMac, LOGP, FL("Invalid Pre Auth Index passed :%d"), staId); break; } @@ -2005,7 +2028,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ { // Could not deactivate auth response timer. // Log error - limLog(pMac, LOGP, FL("unable to deactivate auth response timer\n")); + limLog(pMac, LOGP, FL("unable to deactivate auth response timer")); } // Change timer to reactivate it in future @@ -2017,7 +2040,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ * from CFG. Log error. */ limLog(pMac, LOGP, - FL("could not retrieve auth response timeout value\n")); + FL("could not retrieve auth response timeout value")); } val = SYS_MS_TO_TICKS(val); @@ -2026,7 +2049,7 @@ limDeactivateAndChangePerStaIdTimer(tpAniSirGlobal pMac, tANI_U32 timerId, tANI_ { // Could not change auth rsp timer. // Log error - limLog(pMac, LOGP, FL("unable to change auth rsp timer\n")); + limLog(pMac, LOGP, FL("unable to change auth rsp timer")); } } break; @@ -2068,7 +2091,7 @@ void limActivateCnfTimer(tpAniSirGlobal pMac, tANI_U16 staId, tpPESession psessi != TX_SUCCESS) { limLog(pMac, LOGP, - FL("could not activate cnf wait timer\n")); + FL("could not activate cnf wait timer")); } } @@ -2100,7 +2123,7 @@ void limActivateAuthRspTimer(tpAniSirGlobal pMac, tLimPreAuthNode *pAuthNode) /// Could not activate auth rsp timer. // Log error limLog(pMac, LOGP, - FL("could not activate auth rsp timer\n")); + FL("could not activate auth rsp timer")); } } @@ -2136,7 +2159,7 @@ limSendDisassocFrameThresholdHandler(void *pMacGlobal, tANI_U32 param) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting to LIM failed, reason=%d\n"), statusCode); + FL("posting to LIM failed, reason=%d"), statusCode); } @@ -2171,7 +2194,7 @@ limCnfWaitTmerHandler(void *pMacGlobal, tANI_U32 param) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting to LIM failed, reason=%d\n"), statusCode); + FL("posting to LIM failed, reason=%d"), statusCode); } @@ -2206,7 +2229,7 @@ limKeepaliveTmerHandler(void *pMacGlobal, tANI_U32 param) if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting to LIM failed, reason=%d\n"), statusCode); + FL("posting to LIM failed, reason=%d"), statusCode); } @@ -2217,7 +2240,7 @@ limChannelSwitchTimerHandler(void *pMacGlobal, tANI_U32 param) tpAniSirGlobal pMac = (tpAniSirGlobal)pMacGlobal; PELOG1(limLog(pMac, LOG1, - FL("ChannelSwitch Timer expired. Posting msg to LIM \n"));) + FL("ChannelSwitch Timer expired. Posting msg to LIM "));) msg.type = SIR_LIM_CHANNEL_SWITCH_TIMEOUT; msg.bodyval = (tANI_U32)param; @@ -2237,7 +2260,7 @@ limQuietTimerHandler(void *pMacGlobal, tANI_U32 param) msg.bodyptr = NULL; PELOG1(limLog(pMac, LOG1, - FL("Post SIR_LIM_QUIET_TIMEOUT msg. \n"));) + FL("Post SIR_LIM_QUIET_TIMEOUT msg. "));) limPostMsgApi(pMac, &msg); } @@ -2251,7 +2274,7 @@ limQuietBssTimerHandler(void *pMacGlobal, tANI_U32 param) msg.bodyval = (tANI_U32)param; msg.bodyptr = NULL; PELOG1(limLog(pMac, LOG1, - FL("Post SIR_LIM_QUIET_BSS_TIMEOUT msg. \n"));) + FL("Post SIR_LIM_QUIET_BSS_TIMEOUT msg. "));) limPostMsgApi(pMac, &msg); } #if 0 @@ -2265,7 +2288,7 @@ limWPSOverlapTimerHandler(void *pMacGlobal, tANI_U32 param) msg.bodyval = (tANI_U32)param; msg.bodyptr = NULL; PELOG1(limLog(pMac, LOG1, - FL("Post SIR_LIM_WPS_OVERLAP_TIMEOUT msg. \n"));) + FL("Post SIR_LIM_WPS_OVERLAP_TIMEOUT msg. "));) limPostMsgApi(pMac, &msg); } #endif @@ -2305,10 +2328,10 @@ limMissedBeaconInActiveMode(void *pMacGlobal, tpPESession psessionEntry) msg.bodyptr = psessionEntry; msg.bodyval = 0; limLog(pMac, LOGE, - FL("Heartbeat failure from Riva\n")); + FL("Heartbeat failure from Riva")); if ((statusCode = limPostMsgApi(pMac, &msg)) != eSIR_SUCCESS) limLog(pMac, LOGE, - FL("posting message %X to LIM failed, reason=%d\n"), + FL("posting message %X to LIM failed, reason=%d"), msg.type, statusCode); } } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c index fce789c14d9..95744c8cfcf 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTrace.c @@ -169,15 +169,15 @@ void limTraceDump(tpAniSirGlobal pMac, tpTraceRecord pRecord, tANI_U16 recIndex) switch (pRecord->code) { case TRACE_CODE_MLM_STATE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "MLM State:", limTraceGetMlmStateString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_SME_STATE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "SME State:", limTraceGetSmeStateString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TX_MGMT: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX Mgmt:", frameSubtypeStr[pRecord->data], pRecord->data ); break; @@ -188,75 +188,75 @@ void limTraceDump(tpAniSirGlobal pMac, tpTraceRecord pRecord, tANI_U16 recIndex) } else { - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(%d) SN: %d \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(%d) SN: %d ", recIndex, pRecord->time, pRecord->session, "RX Mgmt:", frameSubtypeStr[LIM_TRACE_GET_SUBTYPE(pRecord->data)], LIM_TRACE_GET_SUBTYPE(pRecord->data), LIM_TRACE_GET_SSN(pRecord->data) ); } break; case TRACE_CODE_RX_MGMT_DROP: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(%d) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(%d) ", recIndex, pRecord->time, pRecord->session, "Drop RX Mgmt:", __limTraceGetMgmtDropReasonString((tANI_U16)pRecord->data), pRecord->data); break; case TRACE_CODE_RX_MGMT_TSF: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s0x%x(%d) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s0x%x(%d) ", recIndex, pRecord->time, pRecord->session, "RX Mgmt TSF:", " ", pRecord->data, pRecord->data ); break; case TRACE_CODE_TX_COMPLETE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s ", recIndex, pRecord->time, pRecord->session, "TX Complete" ); break; case TRACE_CODE_TX_SME_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX SME Msg:", macTraceGetSmeMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_RX_SME_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? "Def/Drp LIM Msg:": "RX Sme Msg:", macTraceGetSmeMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TX_WDA_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX WDA Msg:", macTraceGetWdaMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_RX_WDA_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? "Def/Drp LIM Msg:": "RX WDA Msg:", macTraceGetWdaMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TX_LIM_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX LIM Msg:", macTraceGetLimMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_RX_LIM_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? "Def/Drp LIM Msg:": "RX LIM Msg", macTraceGetLimMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TX_CFG_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "TX CFG Msg:", macTraceGetCfgMsgString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_RX_CFG_MSG: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, LIM_TRACE_GET_DEFRD_OR_DROPPED(pRecord->data) ? "Def/Drp LIM Msg:": "RX CFG Msg:", macTraceGetCfgMsgString((tANI_U16)MAC_TRACE_GET_MSG_ID(pRecord->data)), pRecord->data ); break; case TRACE_CODE_TIMER_ACTIVATE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "Timer Actvtd", __limTraceGetTimerString((tANI_U16)pRecord->data), pRecord->data ); break; case TRACE_CODE_TIMER_DEACTIVATE: - limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s %-30s(0x%x) ", recIndex, pRecord->time, pRecord->session, "Timer DeActvtd", __limTraceGetTimerString((tANI_U16)pRecord->data), pRecord->data ); break; @@ -265,7 +265,7 @@ void limTraceDump(tpAniSirGlobal pMac, tpTraceRecord pRecord, tANI_U16 recIndex) "INFORMATION_LOG", macTraceGetInfoLogString((tANI_U16)pRecord->data), pRecord->data ); break; default : - limLog(pMac, LOGE, "%04d %012u S%d %-14s(%d) (0x%x) \n", recIndex, pRecord->time, pRecord->session, + limLog(pMac, LOGE, "%04d %012u S%d %-14s(%d) (0x%x) ", recIndex, pRecord->time, pRecord->session, "Unknown Code", pRecord->code, pRecord->data ); break; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h index a8fd0c6af08..1f915e628e8 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limTypes.h @@ -871,7 +871,7 @@ void limProcessLearnIntervalTimeout(tpAniSirGlobal pMac); #ifdef WLAN_FEATURE_11W //11w SA query request action frame handler tSirRetStatus limSendSaQueryResponseFrame( tpAniSirGlobal pMac, - tANI_U8 *transId, tSirMacAddr peer,tpPESession psessionEntry); + tANI_U16 transId, tSirMacAddr peer,tpPESession psessionEntry); #endif // Inline functions @@ -905,7 +905,7 @@ limPostSmeMessage(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } @@ -950,7 +950,7 @@ limPostMlmMessage(tpAniSirGlobal pMac, tANI_U32 msgType, tANI_U32 *pMsgBuf) tSirMsgQ msg; if(pMsgBuf == NULL) { - limLog(pMac, LOGE,FL("Buffer is Pointing to NULL\n")); + limLog(pMac, LOGE,FL("Buffer is Pointing to NULL")); return; } msg.type = (tANI_U16) msgType; @@ -1103,5 +1103,10 @@ typedef struct sSetLinkCbackParams void * cbackDataPtr; } tSetLinkCbackParams; #endif + +void limProcessRxScanEvent(tpAniSirGlobal mac, void *buf); + +int limProcessRemainOnChnlReq(tpAniSirGlobal pMac, tANI_U32 *pMsg); +void limRemainOnChnRsp(tpAniSirGlobal pMac, eHalStatus status, tANI_U32 *data); #endif /* __LIM_TYPES_H */ diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c index 59500f992fd..e534aebe94d 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.c @@ -80,6 +80,11 @@ static tAniBool glimTriggerBackgroundScanDuringQuietBss_Status = eSIR_TRUE; static const tANI_U8 abChannel[]= {36,40,44,48,52,56,60,64,100,104,108,112,116, 120,124,128,132,136,140,149,153,157,161,165}; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +static const tANI_U8 aUnsortedChannelList[]= {52,56,60,64,100,104,108,112,116, + 120,124,128,132,136,140,36,40,44,48,149,153,157,161,165}; +#endif + //#define LIM_MAX_ACTIVE_SESSIONS 3 //defined temporarily for BT-AMP SUPPORT #define SUCCESS 1 //defined temporarily for BT-AMP @@ -98,7 +103,7 @@ limAssignDialogueToken(tpAniSirGlobal pMac) if(eHAL_STATUS_SUCCESS != palAllocateMemory(pMac->hHdd, (void **) &pCurrNode, sizeof(tDialogueToken))) { - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory failed"));) return NULL; } @@ -116,7 +121,7 @@ limAssignDialogueToken(tpAniSirGlobal pMac) //assocId and tid of the node will be filled in by caller. pCurrNode->next = NULL; pCurrNode->token = token++; - PELOG4(limLog(pMac, LOG4, FL("token assigned = %d\n"), token);) + PELOG4(limLog(pMac, LOG4, FL("token assigned = %d"), token);) return pCurrNode; } @@ -178,7 +183,7 @@ limSearchAndDeleteDialogueToken(tpAniSirGlobal pMac, tANI_U8 token, tANI_U16 ass return eSIR_SUCCESS; } - PELOGW(limLog(pMac, LOGW, FL("LIM does not have matching dialogue token node\n"));) + PELOGW(limLog(pMac, LOGW, FL("LIM does not have matching dialogue token node"));) return eSIR_FAILURE; } @@ -239,63 +244,63 @@ limMlmStateStr(tLimMlmStates state) switch (state) { case eLIM_MLM_OFFLINE_STATE: - return "eLIM_MLM_OFFLINE_STATE\n"; + return "eLIM_MLM_OFFLINE_STATE"; case eLIM_MLM_IDLE_STATE: - return "eLIM_MLM_IDLE_STATE\n"; + return "eLIM_MLM_IDLE_STATE"; case eLIM_MLM_WT_PROBE_RESP_STATE: - return "eLIM_MLM_WT_PROBE_RESP_STATE\n"; + return "eLIM_MLM_WT_PROBE_RESP_STATE"; case eLIM_MLM_PASSIVE_SCAN_STATE: - return "eLIM_MLM_PASSIVE_SCAN_STATE\n"; + return "eLIM_MLM_PASSIVE_SCAN_STATE"; case eLIM_MLM_WT_JOIN_BEACON_STATE: - return "eLIM_MLM_WT_JOIN_BEACON_STATE\n"; + return "eLIM_MLM_WT_JOIN_BEACON_STATE"; case eLIM_MLM_JOINED_STATE: - return "eLIM_MLM_JOINED_STATE\n"; + return "eLIM_MLM_JOINED_STATE"; case eLIM_MLM_BSS_STARTED_STATE: - return "eLIM_MLM_BSS_STARTED_STATE\n"; + return "eLIM_MLM_BSS_STARTED_STATE"; case eLIM_MLM_WT_AUTH_FRAME2_STATE: - return "eLIM_MLM_WT_AUTH_FRAME2_STATE\n"; + return "eLIM_MLM_WT_AUTH_FRAME2_STATE"; case eLIM_MLM_WT_AUTH_FRAME3_STATE: - return "eLIM_MLM_WT_AUTH_FRAME3_STATE\n"; + return "eLIM_MLM_WT_AUTH_FRAME3_STATE"; case eLIM_MLM_WT_AUTH_FRAME4_STATE: - return "eLIM_MLM_WT_AUTH_FRAME4_STATE\n"; + return "eLIM_MLM_WT_AUTH_FRAME4_STATE"; case eLIM_MLM_AUTH_RSP_TIMEOUT_STATE: - return "eLIM_MLM_AUTH_RSP_TIMEOUT_STATE\n"; + return "eLIM_MLM_AUTH_RSP_TIMEOUT_STATE"; case eLIM_MLM_AUTHENTICATED_STATE: - return "eLIM_MLM_AUTHENTICATED_STATE\n"; + return "eLIM_MLM_AUTHENTICATED_STATE"; case eLIM_MLM_WT_ASSOC_RSP_STATE: - return "eLIM_MLM_WT_ASSOC_RSP_STATE\n"; + return "eLIM_MLM_WT_ASSOC_RSP_STATE"; case eLIM_MLM_WT_REASSOC_RSP_STATE: - return "eLIM_MLM_WT_REASSOC_RSP_STATE\n"; + return "eLIM_MLM_WT_REASSOC_RSP_STATE"; case eLIM_MLM_WT_FT_REASSOC_RSP_STATE: return "eLIM_MLM_WT_FT_REASSOC_RSP_STATE"; case eLIM_MLM_WT_DEL_STA_RSP_STATE: - return "eLIM_MLM_WT_DEL_STA_RSP_STATE\n"; + return "eLIM_MLM_WT_DEL_STA_RSP_STATE"; case eLIM_MLM_WT_DEL_BSS_RSP_STATE: - return "eLIM_MLM_WT_DEL_BSS_RSP_STATE\n"; + return "eLIM_MLM_WT_DEL_BSS_RSP_STATE"; case eLIM_MLM_WT_ADD_STA_RSP_STATE: - return "eLIM_MLM_WT_ADD_STA_RSP_STATE\n"; + return "eLIM_MLM_WT_ADD_STA_RSP_STATE"; case eLIM_MLM_WT_ADD_BSS_RSP_STATE: - return "eLIM_MLM_WT_ADD_BSS_RSP_STATE\n"; + return "eLIM_MLM_WT_ADD_BSS_RSP_STATE"; case eLIM_MLM_REASSOCIATED_STATE: - return "eLIM_MLM_REASSOCIATED_STATE\n"; + return "eLIM_MLM_REASSOCIATED_STATE"; case eLIM_MLM_LINK_ESTABLISHED_STATE: - return "eLIM_MLM_LINK_ESTABLISHED_STATE\n"; + return "eLIM_MLM_LINK_ESTABLISHED_STATE"; case eLIM_MLM_WT_ASSOC_CNF_STATE: - return "eLIM_MLM_WT_ASSOC_CNF_STATE\n"; + return "eLIM_MLM_WT_ASSOC_CNF_STATE"; case eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE: - return "eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE\n"; + return "eLIM_MLM_WT_ADD_BSS_RSP_ASSOC_STATE"; case eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE: - return "eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE\n"; + return "eLIM_MLM_WT_ADD_BSS_RSP_REASSOC_STATE"; case eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE: return "eLIM_MLM_WT_ADD_BSS_RSP_FT_REASSOC_STATE"; case eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE: - return "eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE\n"; + return "eLIM_MLM_WT_ASSOC_DEL_STA_RSP_STATE"; case eLIM_MLM_WT_SET_BSS_KEY_STATE: - return "eLIM_MLM_WT_SET_BSS_KEY_STATE\n"; + return "eLIM_MLM_WT_SET_BSS_KEY_STATE"; case eLIM_MLM_WT_SET_STA_KEY_STATE: - return "eLIM_MLM_WT_SET_STA_KEY_STATE\n"; + return "eLIM_MLM_WT_SET_STA_KEY_STATE"; default: - return "INVALID MLM state\n"; + return "INVALID MLM state"; } } @@ -312,51 +317,51 @@ limSmeStateStr(tLimSmeStates state) switch (state) { case eLIM_SME_OFFLINE_STATE: - return "eLIM_SME_OFFLINE_STATE\n"; + return "eLIM_SME_OFFLINE_STATE"; case eLIM_SME_IDLE_STATE: - return "eLIM_SME_IDLE_STATE\n"; + return "eLIM_SME_IDLE_STATE"; case eLIM_SME_SUSPEND_STATE: - return "eLIM_SME_SUSPEND_STATE\n"; + return "eLIM_SME_SUSPEND_STATE"; case eLIM_SME_WT_SCAN_STATE: - return "eLIM_SME_WT_SCAN_STATE\n"; + return "eLIM_SME_WT_SCAN_STATE"; case eLIM_SME_WT_JOIN_STATE: - return "eLIM_SME_WT_JOIN_STATE\n"; + return "eLIM_SME_WT_JOIN_STATE"; case eLIM_SME_WT_AUTH_STATE: - return "eLIM_SME_WT_AUTH_STATE\n"; + return "eLIM_SME_WT_AUTH_STATE"; case eLIM_SME_WT_ASSOC_STATE: - return "eLIM_SME_WT_ASSOC_STATE\n"; + return "eLIM_SME_WT_ASSOC_STATE"; case eLIM_SME_WT_REASSOC_STATE: - return "eLIM_SME_WT_REASSOC_STATE\n"; + return "eLIM_SME_WT_REASSOC_STATE"; case eLIM_SME_WT_REASSOC_LINK_FAIL_STATE: - return "eLIM_SME_WT_REASSOC_LINK_FAIL_STATE\n"; + return "eLIM_SME_WT_REASSOC_LINK_FAIL_STATE"; case eLIM_SME_JOIN_FAILURE_STATE: - return "eLIM_SME_JOIN_FAILURE_STATE\n"; + return "eLIM_SME_JOIN_FAILURE_STATE"; case eLIM_SME_ASSOCIATED_STATE: - return "eLIM_SME_ASSOCIATED_STATE\n"; + return "eLIM_SME_ASSOCIATED_STATE"; case eLIM_SME_REASSOCIATED_STATE: - return "eLIM_SME_REASSOCIATED_STATE\n"; + return "eLIM_SME_REASSOCIATED_STATE"; case eLIM_SME_LINK_EST_STATE: - return "eLIM_SME_LINK_EST_STATE\n"; + return "eLIM_SME_LINK_EST_STATE"; case eLIM_SME_LINK_EST_WT_SCAN_STATE: - return "eLIM_SME_LINK_EST_WT_SCAN_STATE\n"; + return "eLIM_SME_LINK_EST_WT_SCAN_STATE"; case eLIM_SME_WT_PRE_AUTH_STATE: - return "eLIM_SME_WT_PRE_AUTH_STATE\n"; + return "eLIM_SME_WT_PRE_AUTH_STATE"; case eLIM_SME_WT_DISASSOC_STATE: - return "eLIM_SME_WT_DISASSOC_STATE\n"; + return "eLIM_SME_WT_DISASSOC_STATE"; case eLIM_SME_WT_DEAUTH_STATE: - return "eLIM_SME_WT_DEAUTH_STATE\n"; + return "eLIM_SME_WT_DEAUTH_STATE"; case eLIM_SME_WT_START_BSS_STATE: - return "eLIM_SME_WT_START_BSS_STATE\n"; + return "eLIM_SME_WT_START_BSS_STATE"; case eLIM_SME_WT_STOP_BSS_STATE: - return "eLIM_SME_WT_STOP_BSS_STATE\n"; + return "eLIM_SME_WT_STOP_BSS_STATE"; case eLIM_SME_NORMAL_STATE: - return "eLIM_SME_NORMAL_STATE\n"; + return "eLIM_SME_NORMAL_STATE"; case eLIM_SME_CHANNEL_SCAN_STATE: - return "eLIM_SME_CHANNEL_SCAN_STATE\n"; + return "eLIM_SME_CHANNEL_SCAN_STATE"; case eLIM_SME_NORMAL_CHANNEL_SCAN_STATE: - return "eLIM_SME_NORMAL_CHANNEL_SCAN_STATE\n"; + return "eLIM_SME_NORMAL_CHANNEL_SCAN_STATE"; default: - return "INVALID SME state\n"; + return "INVALID SME state"; } #endif return ""; @@ -370,23 +375,23 @@ char* limDot11ModeStr(tpAniSirGlobal pMac, tANI_U8 dot11Mode) switch(dot11Mode) { case WNI_CFG_DOT11_MODE_ALL: - return "ALL\n"; + return "ALL"; case WNI_CFG_DOT11_MODE_11A: - return "11A\n"; - case WNI_CFG_DOT11_MODE_11B: - return "11B\n"; - case WNI_CFG_DOT11_MODE_11G: - return "11G\n"; - case WNI_CFG_DOT11_MODE_11N: - return "11N\n"; - case WNI_CFG_DOT11_MODE_POLARIS: - return "Polaris\n"; - case WNI_CFG_DOT11_MODE_TITAN: - return "Titan\n"; + return "11A"; + case WNI_CFG_DOT11_MODE_11B: + return "11B"; + case WNI_CFG_DOT11_MODE_11G: + return "11G"; + case WNI_CFG_DOT11_MODE_11N: + return "11N"; + case WNI_CFG_DOT11_MODE_POLARIS: + return "Polaris"; + case WNI_CFG_DOT11_MODE_TITAN: + return "Titan"; case WNI_CFG_DOT11_MODE_TAURUS: - return "Taurus\n"; + return "Taurus"; default: - return "Invalid Dot11 Mode\n"; + return "Invalid Dot11 Mode"; } #endif return ""; @@ -400,21 +405,21 @@ char* limStaOpRateModeStr(tStaRateMode opRateMode) switch(opRateMode) { case eSTA_TAURUS: - return "Taurus\n"; + return "Taurus"; case eSTA_11a: - return "11A\n"; - case eSTA_11b: - return "11B\n"; - case eSTA_11bg: - return "11G\n"; - case eSTA_11n: - return "11N\n"; - case eSTA_POLARIS: - return "Polaris\n"; + return "11A"; + case eSTA_11b: + return "11B"; + case eSTA_11bg: + return "11G"; + case eSTA_11n: + return "11N"; + case eSTA_POLARIS: + return "Polaris"; case eSTA_TITAN: - return "Titan\n"; + return "Titan"; default: - return "Invalid Dot11 Mode\n"; + return "Invalid Dot11 Mode"; } #endif return ""; @@ -428,11 +433,11 @@ char* limBssTypeStr(tSirBssType bssType) return "eSIR_INFRASTRUCTURE_MODE"; case eSIR_IBSS_MODE: return "eSIR_IBSS_MODE"; - case eSIR_BTAMP_STA_MODE: + case eSIR_BTAMP_STA_MODE: return "eSIR_BTAMP_STA_MODE"; - case eSIR_BTAMP_AP_MODE: + case eSIR_BTAMP_AP_MODE: return "eSIR_BTAMP_AP_MODE"; - case eSIR_AUTO_MODE: + case eSIR_AUTO_MODE: return "eSIR_AUTO_MODE"; default: return "Invalid BSS Type"; @@ -451,236 +456,236 @@ char *limMsgStr(tANI_U32 msgType) switch (msgType) { case eWNI_SME_START_REQ: - return "eWNI_SME_START_REQ\n"; + return "eWNI_SME_START_REQ"; case eWNI_SME_START_RSP: - return "eWNI_SME_START_RSP\n"; + return "eWNI_SME_START_RSP"; case eWNI_SME_SYS_READY_IND: - return "eWNI_SME_SYS_READY_IND\n"; + return "eWNI_SME_SYS_READY_IND"; case eWNI_SME_SCAN_REQ: - return "eWNI_SME_SCAN_REQ\n"; + return "eWNI_SME_SCAN_REQ"; #ifdef FEATURE_OEM_DATA_SUPPORT case eWNI_SME_OEM_DATA_REQ: - return "eWNI_SME_OEM_DATA_REQ\n"; + return "eWNI_SME_OEM_DATA_REQ"; case eWNI_SME_OEM_DATA_RSP: - return "eWNI_SME_OEM_DATA_RSP\n"; + return "eWNI_SME_OEM_DATA_RSP"; #endif case eWNI_SME_SCAN_RSP: - return "eWNI_SME_SCAN_RSP\n"; + return "eWNI_SME_SCAN_RSP"; case eWNI_SME_JOIN_REQ: - return "eWNI_SME_JOIN_REQ\n"; + return "eWNI_SME_JOIN_REQ"; case eWNI_SME_JOIN_RSP: - return "eWNI_SME_JOIN_RSP\n"; + return "eWNI_SME_JOIN_RSP"; case eWNI_SME_SETCONTEXT_REQ: - return "eWNI_SME_SETCONTEXT_REQ\n"; + return "eWNI_SME_SETCONTEXT_REQ"; case eWNI_SME_SETCONTEXT_RSP: - return "eWNI_SME_SETCONTEXT_RSP\n"; + return "eWNI_SME_SETCONTEXT_RSP"; case eWNI_SME_REASSOC_REQ: - return "eWNI_SME_REASSOC_REQ\n"; + return "eWNI_SME_REASSOC_REQ"; case eWNI_SME_REASSOC_RSP: - return "eWNI_SME_REASSOC_RSP\n"; + return "eWNI_SME_REASSOC_RSP"; case eWNI_SME_AUTH_REQ: - return "eWNI_SME_AUTH_REQ\n"; + return "eWNI_SME_AUTH_REQ"; case eWNI_SME_AUTH_RSP: - return "eWNI_SME_AUTH_RSP\n"; + return "eWNI_SME_AUTH_RSP"; case eWNI_SME_DISASSOC_REQ: - return "eWNI_SME_DISASSOC_REQ\n"; + return "eWNI_SME_DISASSOC_REQ"; case eWNI_SME_DISASSOC_RSP: - return "eWNI_SME_DISASSOC_RSP\n"; + return "eWNI_SME_DISASSOC_RSP"; case eWNI_SME_DISASSOC_IND: - return "eWNI_SME_DISASSOC_IND\n"; + return "eWNI_SME_DISASSOC_IND"; case eWNI_SME_DISASSOC_CNF: - return "eWNI_SME_DISASSOC_CNF\n"; + return "eWNI_SME_DISASSOC_CNF"; case eWNI_SME_DEAUTH_REQ: - return "eWNI_SME_DEAUTH_REQ\n"; + return "eWNI_SME_DEAUTH_REQ"; case eWNI_SME_DEAUTH_RSP: - return "eWNI_SME_DEAUTH_RSP\n"; + return "eWNI_SME_DEAUTH_RSP"; case eWNI_SME_DEAUTH_IND: - return "eWNI_SME_DEAUTH_IND\n"; + return "eWNI_SME_DEAUTH_IND"; case eWNI_SME_WM_STATUS_CHANGE_NTF: - return "eWNI_SME_WM_STATUS_CHANGE_NTF\n"; + return "eWNI_SME_WM_STATUS_CHANGE_NTF"; case eWNI_SME_START_BSS_REQ: - return "eWNI_SME_START_BSS_REQ\n"; + return "eWNI_SME_START_BSS_REQ"; case eWNI_SME_START_BSS_RSP: - return "eWNI_SME_START_BSS_RSP\n"; + return "eWNI_SME_START_BSS_RSP"; case eWNI_SME_AUTH_IND: - return "eWNI_SME_AUTH_IND\n"; + return "eWNI_SME_AUTH_IND"; case eWNI_SME_ASSOC_IND: - return "eWNI_SME_ASSOC_IND\n"; + return "eWNI_SME_ASSOC_IND"; case eWNI_SME_ASSOC_CNF: - return "eWNI_SME_ASSOC_CNF\n"; + return "eWNI_SME_ASSOC_CNF"; case eWNI_SME_REASSOC_IND: - return "eWNI_SME_REASSOC_IND\n"; + return "eWNI_SME_REASSOC_IND"; case eWNI_SME_REASSOC_CNF: - return "eWNI_SME_REASSOC_CNF\n"; + return "eWNI_SME_REASSOC_CNF"; case eWNI_SME_SWITCH_CHL_REQ: - return "eWNI_SME_SWITCH_CHL_REQ\n"; + return "eWNI_SME_SWITCH_CHL_REQ"; case eWNI_SME_SWITCH_CHL_RSP: - return "eWNI_SME_SWITCH_CHL_RSP\n"; + return "eWNI_SME_SWITCH_CHL_RSP"; case eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ: - return "eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ\n"; + return "eWNI_SME_SWITCH_CHL_CB_PRIMARY_REQ"; case eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ: - return "eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ\n"; + return "eWNI_SME_SWITCH_CHL_CB_SECONDARY_REQ"; case eWNI_SME_STOP_BSS_REQ: - return "eWNI_SME_STOP_BSS_REQ\n"; + return "eWNI_SME_STOP_BSS_REQ"; case eWNI_SME_STOP_BSS_RSP: - return "eWNI_SME_STOP_BSS_RSP\n"; + return "eWNI_SME_STOP_BSS_RSP"; case eWNI_SME_PROMISCUOUS_MODE_REQ: - return "eWNI_SME_PROMISCUOUS_MODE_REQ\n"; + return "eWNI_SME_PROMISCUOUS_MODE_REQ"; case eWNI_SME_PROMISCUOUS_MODE_RSP: - return "eWNI_SME_PROMISCUOUS_MODE_RSP\n"; + return "eWNI_SME_PROMISCUOUS_MODE_RSP"; case eWNI_SME_NEIGHBOR_BSS_IND: - return "eWNI_SME_NEIGHBOR_BSS_IND\n"; + return "eWNI_SME_NEIGHBOR_BSS_IND"; case eWNI_SME_MEASUREMENT_REQ: - return "eWNI_SME_MEASUREMENT_REQ\n"; + return "eWNI_SME_MEASUREMENT_REQ"; case eWNI_SME_MEASUREMENT_RSP: - return "eWNI_SME_MEASUREMENT_RSP\n"; + return "eWNI_SME_MEASUREMENT_RSP"; case eWNI_SME_MEASUREMENT_IND: - return "eWNI_SME_MEASUREMENT_IND\n"; + return "eWNI_SME_MEASUREMENT_IND"; case eWNI_SME_SET_WDS_INFO_REQ: - return "eWNI_SME_SET_WDS_INFO_REQ\n"; + return "eWNI_SME_SET_WDS_INFO_REQ"; case eWNI_SME_SET_WDS_INFO_RSP: - return "eWNI_SME_SET_WDS_INFO_RSP\n"; + return "eWNI_SME_SET_WDS_INFO_RSP"; case eWNI_SME_WDS_INFO_IND: - return "eWNI_SME_WDS_INFO_IND\n"; + return "eWNI_SME_WDS_INFO_IND"; case eWNI_SME_DEAUTH_CNF: - return "eWNI_SME_DEAUTH_CNF\n"; + return "eWNI_SME_DEAUTH_CNF"; case eWNI_SME_MIC_FAILURE_IND: - return "eWNI_SME_MIC_FAILURE_IND\n"; + return "eWNI_SME_MIC_FAILURE_IND"; case eWNI_SME_ADDTS_REQ: - return "eWNI_SME_ADDTS_REQ\n"; + return "eWNI_SME_ADDTS_REQ"; case eWNI_SME_ADDTS_RSP: - return "eWNI_SME_ADDTS_RSP\n"; + return "eWNI_SME_ADDTS_RSP"; case eWNI_SME_ADDTS_CNF: - return "eWNI_SME_ADDTS_CNF\n"; + return "eWNI_SME_ADDTS_CNF"; case eWNI_SME_ADDTS_IND: - return "eWNI_SME_ADDTS_IND\n"; + return "eWNI_SME_ADDTS_IND"; case eWNI_SME_DELTS_REQ: - return "eWNI_SME_DELTS_REQ\n"; + return "eWNI_SME_DELTS_REQ"; case eWNI_SME_DELTS_RSP: - return "eWNI_SME_DELTS_RSP\n"; + return "eWNI_SME_DELTS_RSP"; case eWNI_SME_DELTS_IND: - return "eWNI_SME_DELTS_IND\n"; + return "eWNI_SME_DELTS_IND"; #if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR) case eWNI_SME_GET_ROAM_RSSI_REQ: - return "eWNI_SME_GET_ROAM_RSSI_REQ\n"; + return "eWNI_SME_GET_ROAM_RSSI_REQ"; case eWNI_SME_GET_ROAM_RSSI_RSP: - return "eWNI_SME_GET_ROAM_RSSI_RSP\n"; + return "eWNI_SME_GET_ROAM_RSSI_RSP"; #endif case WDA_SUSPEND_ACTIVITY_RSP: - return "WDA_SUSPEND_ACTIVITY_RSP\n"; + return "WDA_SUSPEND_ACTIVITY_RSP"; case SIR_LIM_RETRY_INTERRUPT_MSG: - return "SIR_LIM_RETRY_INTERRUPT_MSG\n"; + return "SIR_LIM_RETRY_INTERRUPT_MSG"; case SIR_BB_XPORT_MGMT_MSG: - return "SIR_BB_XPORT_MGMT_MSG\n"; + return "SIR_BB_XPORT_MGMT_MSG"; case SIR_LIM_INV_KEY_INTERRUPT_MSG: - return "SIR_LIM_INV_KEY_INTERRUPT_MSG\n"; + return "SIR_LIM_INV_KEY_INTERRUPT_MSG"; case SIR_LIM_KEY_ID_INTERRUPT_MSG: - return "SIR_LIM_KEY_ID_INTERRUPT_MSG\n"; + return "SIR_LIM_KEY_ID_INTERRUPT_MSG"; case SIR_LIM_REPLAY_THRES_INTERRUPT_MSG: - return "SIR_LIM_REPLAY_THRES_INTERRUPT_MSG\n"; + return "SIR_LIM_REPLAY_THRES_INTERRUPT_MSG"; case SIR_LIM_MIN_CHANNEL_TIMEOUT: - return "SIR_LIM_MIN_CHANNEL_TIMEOUT\n"; + return "SIR_LIM_MIN_CHANNEL_TIMEOUT"; case SIR_LIM_MAX_CHANNEL_TIMEOUT: - return "SIR_LIM_MAX_CHANNEL_TIMEOUT\n"; + return "SIR_LIM_MAX_CHANNEL_TIMEOUT"; case SIR_LIM_JOIN_FAIL_TIMEOUT: - return "SIR_LIM_JOIN_FAIL_TIMEOUT\n"; + return "SIR_LIM_JOIN_FAIL_TIMEOUT"; case SIR_LIM_AUTH_FAIL_TIMEOUT: - return "SIR_LIM_AUTH_FAIL_TIMEOUT\n"; + return "SIR_LIM_AUTH_FAIL_TIMEOUT"; case SIR_LIM_AUTH_RSP_TIMEOUT: - return "SIR_LIM_AUTH_RSP_TIMEOUT\n"; + return "SIR_LIM_AUTH_RSP_TIMEOUT"; case SIR_LIM_ASSOC_FAIL_TIMEOUT: - return "SIR_LIM_ASSOC_FAIL_TIMEOUT\n"; + return "SIR_LIM_ASSOC_FAIL_TIMEOUT"; case SIR_LIM_REASSOC_FAIL_TIMEOUT: - return "SIR_LIM_REASSOC_FAIL_TIMEOUT\n"; + return "SIR_LIM_REASSOC_FAIL_TIMEOUT"; case SIR_LIM_HEART_BEAT_TIMEOUT: - return "SIR_LIM_HEART_BEAT_TIMEOUT\n"; + return "SIR_LIM_HEART_BEAT_TIMEOUT"; case SIR_LIM_ADDTS_RSP_TIMEOUT: - return "SIR_LIM_ADDTS_RSP_TIMEOUT\n"; + return "SIR_LIM_ADDTS_RSP_TIMEOUT"; case SIR_LIM_CHANNEL_SCAN_TIMEOUT: - return "SIR_LIM_CHANNEL_SCAN_TIMEOUT\n"; + return "SIR_LIM_CHANNEL_SCAN_TIMEOUT"; case SIR_LIM_LINK_TEST_DURATION_TIMEOUT: - return "SIR_LIM_LINK_TEST_DURATION_TIMEOUT\n"; + return "SIR_LIM_LINK_TEST_DURATION_TIMEOUT"; case SIR_LIM_HASH_MISS_THRES_TIMEOUT: - return "SIR_LIM_HASH_MISS_THRES_TIMEOUT\n"; + return "SIR_LIM_HASH_MISS_THRES_TIMEOUT"; case SIR_LIM_KEEPALIVE_TIMEOUT: - return "SIR_LIM_KEEPALIVE_TIMEOUT\n"; + return "SIR_LIM_KEEPALIVE_TIMEOUT"; case SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT: - return "SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT\n"; + return "SIR_LIM_UPDATE_OLBC_CACHEL_TIMEOUT"; case SIR_LIM_CNF_WAIT_TIMEOUT: - return "SIR_LIM_CNF_WAIT_TIMEOUT\n"; + return "SIR_LIM_CNF_WAIT_TIMEOUT"; case SIR_LIM_RADAR_DETECT_IND: - return "SIR_LIM_RADAR_DETECT_IND\n"; + return "SIR_LIM_RADAR_DETECT_IND"; #ifdef WLAN_FEATURE_VOWIFI_11R case SIR_LIM_FT_PREAUTH_RSP_TIMEOUT: - return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT\n"; + return "SIR_LIM_FT_PREAUTH_RSP_TIMEOUT"; #endif case SIR_HAL_APP_SETUP_NTF: - return "SIR_HAL_APP_SETUP_NTF\n"; + return "SIR_HAL_APP_SETUP_NTF"; case SIR_HAL_INITIAL_CAL_FAILED_NTF: - return "SIR_HAL_INITIAL_CAL_FAILED_NTF\n"; + return "SIR_HAL_INITIAL_CAL_FAILED_NTF"; case SIR_HAL_NIC_OPER_NTF: - return "SIR_HAL_NIC_OPER_NTF\n"; + return "SIR_HAL_NIC_OPER_NTF"; case SIR_HAL_INIT_START_REQ: - return "SIR_HAL_INIT_START_REQ\n"; + return "SIR_HAL_INIT_START_REQ"; case SIR_HAL_SHUTDOWN_REQ: - return "SIR_HAL_SHUTDOWN_REQ\n"; + return "SIR_HAL_SHUTDOWN_REQ"; case SIR_HAL_SHUTDOWN_CNF: - return "SIR_HAL_SHUTDOWN_CNF\n"; + return "SIR_HAL_SHUTDOWN_CNF"; case SIR_HAL_RESET_REQ: - return "SIR_HAL_RESET_REQ\n"; + return "SIR_HAL_RESET_REQ"; case SIR_HAL_RESET_CNF: - return "SIR_HAL_RESET_CNF\n"; + return "SIR_HAL_RESET_CNF"; case SIR_WRITE_TO_TD: - return "SIR_WRITE_TO_TD\n"; + return "SIR_WRITE_TO_TD"; case WNI_CFG_PARAM_UPDATE_IND: - return "WNI_CFG_PARAM_UPDATE_IND\n"; + return "WNI_CFG_PARAM_UPDATE_IND"; case WNI_CFG_DNLD_REQ: - return "WNI_CFG_DNLD_REQ\n"; + return "WNI_CFG_DNLD_REQ"; case WNI_CFG_DNLD_CNF: - return "WNI_CFG_DNLD_CNF\n"; + return "WNI_CFG_DNLD_CNF"; case WNI_CFG_GET_RSP: - return "WNI_CFG_GET_RSP\n"; + return "WNI_CFG_GET_RSP"; case WNI_CFG_SET_CNF: - return "WNI_CFG_SET_CNF\n"; + return "WNI_CFG_SET_CNF"; case WNI_CFG_GET_ATTRIB_RSP: - return "WNI_CFG_GET_ATTRIB_RSP\n"; + return "WNI_CFG_GET_ATTRIB_RSP"; case WNI_CFG_ADD_GRP_ADDR_CNF: - return "WNI_CFG_ADD_GRP_ADDR_CNF\n"; + return "WNI_CFG_ADD_GRP_ADDR_CNF"; case WNI_CFG_DEL_GRP_ADDR_CNF: - return "WNI_CFG_DEL_GRP_ADDR_CNF\n"; + return "WNI_CFG_DEL_GRP_ADDR_CNF"; case ANI_CFG_GET_RADIO_STAT_RSP: - return "ANI_CFG_GET_RADIO_STAT_RSP\n"; + return "ANI_CFG_GET_RADIO_STAT_RSP"; case ANI_CFG_GET_PER_STA_STAT_RSP: - return "ANI_CFG_GET_PER_STA_STAT_RSP\n"; + return "ANI_CFG_GET_PER_STA_STAT_RSP"; case ANI_CFG_GET_AGG_STA_STAT_RSP: - return "ANI_CFG_GET_AGG_STA_STAT_RSP\n"; + return "ANI_CFG_GET_AGG_STA_STAT_RSP"; case ANI_CFG_CLEAR_STAT_RSP: - return "ANI_CFG_CLEAR_STAT_RSP\n"; + return "ANI_CFG_CLEAR_STAT_RSP"; case WNI_CFG_DNLD_RSP: - return "WNI_CFG_DNLD_RSP\n"; + return "WNI_CFG_DNLD_RSP"; case WNI_CFG_GET_REQ: - return "WNI_CFG_GET_REQ\n"; + return "WNI_CFG_GET_REQ"; case WNI_CFG_SET_REQ: - return "WNI_CFG_SET_REQ\n"; + return "WNI_CFG_SET_REQ"; case WNI_CFG_SET_REQ_NO_RSP: - return "WNI_CFG_SET_REQ_NO_RSP\n"; + return "WNI_CFG_SET_REQ_NO_RSP"; case eWNI_PMC_ENTER_IMPS_RSP: - return "eWNI_PMC_ENTER_IMPS_RSP\n"; + return "eWNI_PMC_ENTER_IMPS_RSP"; case eWNI_PMC_EXIT_IMPS_RSP: - return "eWNI_PMC_EXIT_IMPS_RSP\n"; + return "eWNI_PMC_EXIT_IMPS_RSP"; case eWNI_PMC_ENTER_BMPS_RSP: - return "eWNI_PMC_ENTER_BMPS_RSP\n"; + return "eWNI_PMC_ENTER_BMPS_RSP"; case eWNI_PMC_EXIT_BMPS_RSP: - return "eWNI_PMC_EXIT_BMPS_RSP\n"; + return "eWNI_PMC_EXIT_BMPS_RSP"; case eWNI_PMC_EXIT_BMPS_IND: - return "eWNI_PMC_EXIT_BMPS_IND\n"; + return "eWNI_PMC_EXIT_BMPS_IND"; case eWNI_SME_SET_BCN_FILTER_REQ: - return "eWNI_SME_SET_BCN_FILTER_REQ\n"; + return "eWNI_SME_SET_BCN_FILTER_REQ"; default: - return "INVALID SME message\n"; + return "INVALID SME message"; } #endif return ""; @@ -693,153 +698,153 @@ char *limResultCodeStr(tSirResultCodes resultCode) switch (resultCode) { case eSIR_SME_SUCCESS: - return "eSIR_SME_SUCCESS\n"; + return "eSIR_SME_SUCCESS"; case eSIR_EOF_SOF_EXCEPTION: - return "eSIR_EOF_SOF_EXCEPTION\n"; + return "eSIR_EOF_SOF_EXCEPTION"; case eSIR_BMU_EXCEPTION: - return "eSIR_BMU_EXCEPTION\n"; + return "eSIR_BMU_EXCEPTION"; case eSIR_LOW_PDU_EXCEPTION: - return "eSIR_LOW_PDU_EXCEPTION\n"; + return "eSIR_LOW_PDU_EXCEPTION"; case eSIR_USER_TRIG_RESET: - return"eSIR_USER_TRIG_RESET\n"; + return"eSIR_USER_TRIG_RESET"; case eSIR_LOGP_EXCEPTION: - return "eSIR_LOGP_EXCEPTION\n"; + return "eSIR_LOGP_EXCEPTION"; case eSIR_CP_EXCEPTION: - return "eSIR_CP_EXCEPTION\n"; + return "eSIR_CP_EXCEPTION"; case eSIR_STOP_BSS: - return "eSIR_STOP_BSS\n"; + return "eSIR_STOP_BSS"; case eSIR_AHB_HANG_EXCEPTION: - return "eSIR_AHB_HANG_EXCEPTION\n"; + return "eSIR_AHB_HANG_EXCEPTION"; case eSIR_DPU_EXCEPTION: - return "eSIR_DPU_EXCEPTION\n"; + return "eSIR_DPU_EXCEPTION"; case eSIR_RXP_EXCEPTION: - return "eSIR_RXP_EXCEPTION\n"; + return "eSIR_RXP_EXCEPTION"; case eSIR_MCPU_EXCEPTION: - return "eSIR_MCPU_EXCEPTION\n"; + return "eSIR_MCPU_EXCEPTION"; case eSIR_MCU_EXCEPTION: - return "eSIR_MCU_EXCEPTION\n"; + return "eSIR_MCU_EXCEPTION"; case eSIR_MTU_EXCEPTION: - return "eSIR_MTU_EXCEPTION\n"; + return "eSIR_MTU_EXCEPTION"; case eSIR_MIF_EXCEPTION: - return "eSIR_MIF_EXCEPTION\n"; + return "eSIR_MIF_EXCEPTION"; case eSIR_FW_EXCEPTION: - return "eSIR_FW_EXCEPTION\n"; + return "eSIR_FW_EXCEPTION"; case eSIR_MAILBOX_SANITY_CHK_FAILED: - return "eSIR_MAILBOX_SANITY_CHK_FAILED\n"; + return "eSIR_MAILBOX_SANITY_CHK_FAILED"; case eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF: - return "eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF\n"; + return "eSIR_RADIO_HW_SWITCH_STATUS_IS_OFF"; case eSIR_CFB_FLAG_STUCK_EXCEPTION: - return "eSIR_CFB_FLAG_STUCK_EXCEPTION\n"; + return "eSIR_CFB_FLAG_STUCK_EXCEPTION"; case eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS: - return "eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS\n"; + return "eSIR_SME_BASIC_RATES_NOT_SUPPORTED_STATUS"; case eSIR_SME_INVALID_PARAMETERS: - return "eSIR_SME_INVALID_PARAMETERS\n"; + return "eSIR_SME_INVALID_PARAMETERS"; case eSIR_SME_UNEXPECTED_REQ_RESULT_CODE: - return "eSIR_SME_UNEXPECTED_REQ_RESULT_CODE\n"; + return "eSIR_SME_UNEXPECTED_REQ_RESULT_CODE"; case eSIR_SME_RESOURCES_UNAVAILABLE: - return "eSIR_SME_RESOURCES_UNAVAILABLE\n"; + return "eSIR_SME_RESOURCES_UNAVAILABLE"; case eSIR_SME_SCAN_FAILED: - return "eSIR_SME_SCAN_FAILED\n"; + return "eSIR_SME_SCAN_FAILED"; case eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED: - return "eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED\n"; + return "eSIR_SME_BSS_ALREADY_STARTED_OR_JOINED"; case eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE: - return "eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE\n"; + return "eSIR_SME_LOST_LINK_WITH_PEER_RESULT_CODE"; case eSIR_SME_REFUSED: - return "eSIR_SME_REFUSED\n"; + return "eSIR_SME_REFUSED"; case eSIR_SME_JOIN_TIMEOUT_RESULT_CODE: - return "eSIR_SME_JOIN_TIMEOUT_RESULT_CODE\n"; + return "eSIR_SME_JOIN_TIMEOUT_RESULT_CODE"; case eSIR_SME_AUTH_TIMEOUT_RESULT_CODE: - return "eSIR_SME_AUTH_TIMEOUT_RESULT_CODE\n"; + return "eSIR_SME_AUTH_TIMEOUT_RESULT_CODE"; case eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE: - return "eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE\n"; + return "eSIR_SME_ASSOC_TIMEOUT_RESULT_CODE"; case eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE: - return "eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE\n"; + return "eSIR_SME_REASSOC_TIMEOUT_RESULT_CODE"; case eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED: - return "eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED\n"; + return "eSIR_SME_MAX_NUM_OF_PRE_AUTH_REACHED"; case eSIR_SME_AUTH_REFUSED: - return "eSIR_SME_AUTH_REFUSED\n"; + return "eSIR_SME_AUTH_REFUSED"; case eSIR_SME_INVALID_WEP_DEFAULT_KEY: - return "eSIR_SME_INVALID_WEP_DEFAULT_KEY\n"; + return "eSIR_SME_INVALID_WEP_DEFAULT_KEY"; case eSIR_SME_ASSOC_REFUSED: - return "eSIR_SME_ASSOC_REFUSED\n"; + return "eSIR_SME_ASSOC_REFUSED"; case eSIR_SME_REASSOC_REFUSED: - return "eSIR_SME_REASSOC_REFUSED\n"; + return "eSIR_SME_REASSOC_REFUSED"; case eSIR_SME_STA_NOT_AUTHENTICATED: - return "eSIR_SME_STA_NOT_AUTHENTICATED\n"; + return "eSIR_SME_STA_NOT_AUTHENTICATED"; case eSIR_SME_STA_NOT_ASSOCIATED: - return "eSIR_SME_STA_NOT_ASSOCIATED\n"; + return "eSIR_SME_STA_NOT_ASSOCIATED"; case eSIR_SME_STA_DISASSOCIATED: - return "eSIR_SME_STA_DISASSOCIATED\n"; + return "eSIR_SME_STA_DISASSOCIATED"; case eSIR_SME_ALREADY_JOINED_A_BSS: - return "eSIR_SME_ALREADY_JOINED_A_BSS\n"; + return "eSIR_SME_ALREADY_JOINED_A_BSS"; case eSIR_ULA_COMPLETED: - return "eSIR_ULA_COMPLETED\n"; + return "eSIR_ULA_COMPLETED"; case eSIR_ULA_FAILURE: - return "eSIR_ULA_FAILURE\n"; + return "eSIR_ULA_FAILURE"; case eSIR_SME_LINK_ESTABLISHED: - return "eSIR_SME_LINK_ESTABLISHED\n"; + return "eSIR_SME_LINK_ESTABLISHED"; case eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS: - return "eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS\n"; + return "eSIR_SME_UNABLE_TO_PERFORM_MEASUREMENTS"; case eSIR_SME_UNABLE_TO_PERFORM_DFS: - return "eSIR_SME_UNABLE_TO_PERFORM_DFS\n"; + return "eSIR_SME_UNABLE_TO_PERFORM_DFS"; case eSIR_SME_DFS_FAILED: - return "eSIR_SME_DFS_FAILED\n"; + return "eSIR_SME_DFS_FAILED"; case eSIR_SME_TRANSFER_STA: - return "eSIR_SME_TRANSFER_STA\n"; + return "eSIR_SME_TRANSFER_STA"; case eSIR_SME_INVALID_LINK_TEST_PARAMETERS: - return "eSIR_SME_INVALID_LINK_TEST_PARAMETERS\n"; + return "eSIR_SME_INVALID_LINK_TEST_PARAMETERS"; case eSIR_SME_LINK_TEST_MAX_EXCEEDED: - return "eSIR_SME_LINK_TEST_MAX_EXCEEDED\n"; + return "eSIR_SME_LINK_TEST_MAX_EXCEEDED"; case eSIR_SME_UNSUPPORTED_RATE: - return "eSIR_SME_UNSUPPORTED_RATE\n"; + return "eSIR_SME_UNSUPPORTED_RATE"; case eSIR_SME_LINK_TEST_TIMEOUT: - return "eSIR_SME_LINK_TEST_TIMEOUT\n"; + return "eSIR_SME_LINK_TEST_TIMEOUT"; case eSIR_SME_LINK_TEST_COMPLETE: - return "eSIR_SME_LINK_TEST_COMPLETE\n"; + return "eSIR_SME_LINK_TEST_COMPLETE"; case eSIR_SME_LINK_TEST_INVALID_STATE: - return "eSIR_SME_LINK_TEST_INVALID_STATE\n"; + return "eSIR_SME_LINK_TEST_INVALID_STATE"; case eSIR_SME_LINK_TEST_INVALID_ADDRESS: - return "eSIR_SME_LINK_TEST_INVALID_ADDRESS\n"; + return "eSIR_SME_LINK_TEST_INVALID_ADDRESS"; case eSIR_SME_POLARIS_RESET: - return "eSIR_SME_POLARIS_RESET\n"; + return "eSIR_SME_POLARIS_RESET"; case eSIR_SME_SETCONTEXT_FAILED: - return "eSIR_SME_SETCONTEXT_FAILED\n"; + return "eSIR_SME_SETCONTEXT_FAILED"; case eSIR_SME_BSS_RESTART: - return "eSIR_SME_BSS_RESTART\n"; + return "eSIR_SME_BSS_RESTART"; case eSIR_SME_MORE_SCAN_RESULTS_FOLLOW: - return "eSIR_SME_MORE_SCAN_RESULTS_FOLLOW\n"; + return "eSIR_SME_MORE_SCAN_RESULTS_FOLLOW"; case eSIR_SME_INVALID_ASSOC_RSP_RXED: - return "eSIR_SME_INVALID_ASSOC_RSP_RXED\n"; + return "eSIR_SME_INVALID_ASSOC_RSP_RXED"; case eSIR_SME_MIC_COUNTER_MEASURES: - return "eSIR_SME_MIC_COUNTER_MEASURES\n"; + return "eSIR_SME_MIC_COUNTER_MEASURES"; case eSIR_SME_ADDTS_RSP_TIMEOUT: - return "eSIR_SME_ADDTS_RSP_TIMEOUT\n"; + return "eSIR_SME_ADDTS_RSP_TIMEOUT"; case eSIR_SME_RECEIVED: - return "eSIR_SME_RECEIVED\n"; + return "eSIR_SME_RECEIVED"; case eSIR_SME_CHANNEL_SWITCH_FAIL: - return "eSIR_SME_CHANNEL_SWITCH_FAIL\n"; + return "eSIR_SME_CHANNEL_SWITCH_FAIL"; #ifdef GEN4_SCAN case eSIR_SME_CHANNEL_SWITCH_DISABLED: - return "eSIR_SME_CHANNEL_SWITCH_DISABLED\n"; + return "eSIR_SME_CHANNEL_SWITCH_DISABLED"; case eSIR_SME_HAL_SCAN_INIT_FAILED: - return "eSIR_SME_HAL_SCAN_INIT_FAILED\n"; + return "eSIR_SME_HAL_SCAN_INIT_FAILED"; case eSIR_SME_HAL_SCAN_START_FAILED: - return "eSIR_SME_HAL_SCAN_START_FAILED\n"; + return "eSIR_SME_HAL_SCAN_START_FAILED"; case eSIR_SME_HAL_SCAN_END_FAILED: - return "eSIR_SME_HAL_SCAN_END_FAILED\n"; + return "eSIR_SME_HAL_SCAN_END_FAILED"; case eSIR_SME_HAL_SCAN_FINISH_FAILED: - return "eSIR_SME_HAL_SCAN_FINISH_FAILED\n"; + return "eSIR_SME_HAL_SCAN_FINISH_FAILED"; case eSIR_SME_HAL_SEND_MESSAGE_FAIL: - return "eSIR_SME_HAL_SEND_MESSAGE_FAIL\n"; + return "eSIR_SME_HAL_SEND_MESSAGE_FAIL"; #else // GEN4_SCAN case eSIR_SME_CHANNEL_SWITCH_DISABLED: - return "eSIR_SME_CHANNEL_SWITCH_DISABLED\n"; + return "eSIR_SME_CHANNEL_SWITCH_DISABLED"; case eSIR_SME_HAL_SEND_MESSAGE_FAIL: - return "eSIR_SME_HAL_SEND_MESSAGE_FAIL\n"; + return "eSIR_SME_HAL_SEND_MESSAGE_FAIL"; #endif // GEN4_SCAN default: - return "INVALID resultCode\n"; + return "INVALID resultCode"; } } @@ -849,13 +854,6 @@ limPrintMsgName(tpAniSirGlobal pMac, tANI_U16 logLevel, tANI_U32 msgType) limLog(pMac, logLevel, limMsgStr(msgType)); } - -#if defined(ANI_MIPS) || defined(ANI_ARM) -#define LINK 0 -#else -#define LINK 1 -#endif - void limPrintMsgInfo(tpAniSirGlobal pMac, tANI_U16 logLevel, tSirMsgQ *msg) { @@ -905,6 +903,13 @@ limInitMlm(tpAniSirGlobal pMac) /// Initialize scan result hash table limReInitScanResults(pMac); //sep26th review +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /// Initialize lfr scan result hash table + // Could there be a problem in multisession with SAP/P2P GO, when in the + // middle of FW bg scan, SAP started; Again that could be a problem even on + // infra + SAP/P2P GO too - TBD + limReInitLfrScanResults(pMac); +#endif /// Initialize number of pre-auth contexts pMac->lim.gLimNumPreAuthContexts = 0; @@ -925,7 +930,7 @@ limInitMlm(tpAniSirGlobal pMac) } else { - limLog(pMac, LOGP, FL(" limCreateTimers Failed to create lim timers \n")); + limLog(pMac, LOGP, FL(" limCreateTimers Failed to create lim timers ")); } } /*** end limInitMlm() ***/ @@ -1098,6 +1103,10 @@ limCleanupMlm(tpAniSirGlobal pMac) /// Cleanup cached scan list limReInitScanResults(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /// Cleanup cached scan list + limReInitLfrScanResults(pMac); +#endif } /*** end limCleanupMlm() ***/ @@ -1252,7 +1261,7 @@ void limPrintMacAddr(tpAniSirGlobal pMac, tSirMacAddr macAddr, tANI_U8 logLevel) { limLog(pMac, logLevel, - FL("%X:%X:%X:%X:%X:%X\n"), + FL("%X:%X:%X:%X:%X:%X"), macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]); } /****** end limPrintMacAddr() ******/ @@ -1321,7 +1330,7 @@ void limResetDeferredMsgQ(tpAniSirGlobal pMac) tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg) { PELOG1(limLog(pMac, LOG1, - FL("** Queue a deferred message (size %d, write %d) - type 0x%x **\n"), + FL("** Queue a deferred message (size %d, write %d) - type 0x%x **"), pMac->lim.gLimDeferredMsgQ.size, pMac->lim.gLimDeferredMsgQ.write, limMsg->type);) @@ -1332,7 +1341,7 @@ tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg) { if(!(pMac->lim.deferredMsgCnt & 0xF)) { - PELOGE(limLog(pMac, LOGE, FL("Deferred Message Queue is full. Msg:%d Messages Failed:%d\n"), limMsg->type, ++pMac->lim.deferredMsgCnt);) + PELOGE(limLog(pMac, LOGE, FL("Deferred Message Queue is full. Msg:%d Messages Failed:%d"), limMsg->type, ++pMac->lim.deferredMsgCnt);) } else { @@ -1348,7 +1357,7 @@ tANI_U8 limWriteDeferredMsgQ(tpAniSirGlobal pMac, tpSirMsgQ limMsg) **/ if (pMac->lim.gLimDeferredMsgQ.size > 0) { - PELOGW(limLog(pMac, LOGW, FL("%d Deferred messages (type 0x%x, scan %d, global sme %d, global mlme %d, addts %d)\n"), + PELOGW(limLog(pMac, LOGW, FL("%d Deferred messages (type 0x%x, scan %d, global sme %d, global mlme %d, addts %d)"), pMac->lim.gLimDeferredMsgQ.size, limMsg->type, limIsSystemInScanState(pMac), pMac->lim.gLimSmeState, pMac->lim.gLimMlmState, @@ -1459,11 +1468,11 @@ tSirMsgQ* limReadDeferredMsgQ(tpAniSirGlobal pMac) pMac->lim.gLimDeferredMsgQ.read = 0; PELOG1(limLog(pMac, LOG1, - FL("** DeQueue a deferred message (size %d read %d) - type 0x%x **\n"), + FL("** DeQueue a deferred message (size %d read %d) - type 0x%x **"), pMac->lim.gLimDeferredMsgQ.size, pMac->lim.gLimDeferredMsgQ.read, msg->type);) - PELOG1(limLog(pMac, LOG1, FL("DQ msg -- scan %d, global sme %d, global mlme %d, addts %d\n"), + PELOG1(limLog(pMac, LOG1, FL("DQ msg -- scan %d, global sme %d, global mlme %d, addts %d"), limIsSystemInScanState(pMac), pMac->lim.gLimSmeState, pMac->lim.gLimMlmState, pMac->lim.gLimAddtsSent);) @@ -1603,7 +1612,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) if (psessionEntry == NULL) { - PELOGE(limLog(pMac, LOGE, FL(" Session not found\n"));) + PELOGE(limLog(pMac, LOGE, FL(" Session not found"));) return; } @@ -1619,7 +1628,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) if (!enable) { - PELOG2(limLog(pMac, LOG2, FL("Resetting OLBC cache\n"));) + PELOG2(limLog(pMac, LOG2, FL("Resetting OLBC cache"));) psessionEntry->gLimOlbcParams.numSta = 0; psessionEntry->gLimOverlap11gParams.numSta = 0; psessionEntry->gLimOverlapHt20Params.numSta = 0; @@ -1640,7 +1649,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) { if (!psessionEntry->gLim11bParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11B STA detected\n"));) + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11B STA detected"));) limEnable11gProtection(pMac, false, true, &beaconParams, psessionEntry); } } @@ -1652,7 +1661,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) { if (!psessionEntry->gLim11gParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11G STA detected\n"));) + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no 11G STA detected"));) limEnableHtProtectionFrom11g(pMac, false, true, &beaconParams,psessionEntry); } } @@ -1664,7 +1673,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) { if (!psessionEntry->gLimHt20Params.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no HT20 STA detected\n"));) + PELOG1(limLog(pMac, LOG1, FL("Overlap cache all clear and no HT20 STA detected"));) limEnable11gProtection(pMac, false, true, &beaconParams,psessionEntry); } } @@ -1682,7 +1691,7 @@ void limHandleUpdateOlbcCache(tpAniSirGlobal pMac) // Start OLBC timer if (tx_timer_activate(&pMac->lim.limTimers.gLimUpdateOlbcCacheTimer) != TX_SUCCESS) { - limLog(pMac, LOGE, FL("tx_timer_activate failed\n")); + limLog(pMac, LOGE, FL("tx_timer_activate failed")); } } @@ -1808,7 +1817,7 @@ tpPESession psessionEntry) psessionEntry->protStaCache[i].addr, peerMacAddr, sizeof(tSirMacAddr))) { - PELOG1(limLog(pMac, LOG1, FL("matching cache entry at %d already active.\n"), i);) + PELOG1(limLog(pMac, LOG1, FL("matching cache entry at %d already active."), i);) return; } } @@ -1822,7 +1831,7 @@ tpPESession psessionEntry) if (i >= LIM_PROT_STA_CACHE_SIZE) { - PELOGE(limLog(pMac, LOGE, FL("No space in ProtStaCache\n"));) + PELOGE(limLog(pMac, LOGE, FL("No space in ProtStaCache"));) return; } @@ -1856,7 +1865,7 @@ tpPESession psessionEntry) if(!lsigTxopSupported) { psessionEntry->gLimLsigTxopParams.numSta++; - limLog(pMac,LOG1, FL("!lsigTxopSupported\n")); + limLog(pMac,LOG1, FL("!lsigTxopSupported")); } }// --------------------------------------------------------------------- @@ -1884,7 +1893,7 @@ limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeac pStaDs = dphLookupHashEntry(pMac, peerMacAddr, &tmpAid, &psessionEntry->dph.dphHashTable); if(NULL == pStaDs) { - PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL\n"));) + PELOG1(limLog(pMac, LOG1, FL("pStaDs is NULL"));) return; } limGetRfBand(pMac, &rfBand, psessionEntry); @@ -1917,7 +1926,7 @@ limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeac { protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; // enable protection - PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B\n"));) + PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B"));) limEnable11gProtection(pMac, true, false, pBeaconParams,psessionEntry); } } @@ -1931,7 +1940,7 @@ limDecideApProtection(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, tpUpdateBeac { protStaCacheType = eLIM_PROT_STA_CACHE_TYPE_llB; // enable protection - PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B\n"));) + PELOG3(limLog(pMac, LOG3, FL("Enabling protection from 11B"));) limEnable11gProtection(pMac, true, false, pBeaconParams, psessionEntry); } //station being joined is non-11b and non-ht ==> 11g device @@ -1995,7 +2004,7 @@ tpUpdateBeaconParams pBeaconParams, tpSirMacMgmtHdr pMh,tpPESession psessionEntr !psessionEntry->gLimOlbcParams.protectionEnabled) { // enable protection - PELOG1(limLog(pMac, LOG1, FL("OLBC happens!!!\n"));) + PELOG1(limLog(pMac, LOG1, FL("OLBC happens!!!"));) limEnable11gProtection(pMac, true, true, pBeaconParams,psessionEntry); } } @@ -2099,10 +2108,10 @@ limUpdateShortPreamble(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, // enable long preamble - PELOG1(limLog(pMac, LOG1, FL("Disabling short preamble\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disabling short preamble"));) if (limEnableShortPreamble(pMac, false, pBeaconParams, psessionEntry) != eSIR_SUCCESS) - PELOGE(limLog(pMac, LOGE, FL("Cannot enable long preamble\n"));) + PELOGE(limLog(pMac, LOGE, FL("Cannot enable long preamble"));) } } } @@ -2217,7 +2226,7 @@ limUpdateShortSlotTime(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, // enable long slot time pBeaconParams->fShortSlotTime = false; pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; - PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time.\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time."));) psessionEntry->shortSlotTimeSupported = false; } else if ( psessionEntry->limSystemRole != eLIM_AP_ROLE) @@ -2227,7 +2236,7 @@ limUpdateShortSlotTime(tpAniSirGlobal pMac, tSirMacAddr peerMacAddr, // enable long slot time pBeaconParams->fShortSlotTime = false; pBeaconParams->paramChangeBitmap |= PARAM_SHORT_SLOT_TIME_CHANGED; - PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time.\n"));) + PELOG1(limLog(pMac, LOG1, FL("Disable short slot time. Enable long slot time."));) psessionEntry->shortSlotTimeSupported = false; } } @@ -2533,13 +2542,13 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimChannelSwitchTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } if (psessionEntry->limSystemRole != eLIM_STA_ROLE) { - PELOGW(limLog(pMac, LOGW, "Channel switch can be done only in STA role, Current Role = %d\n", psessionEntry->limSystemRole);) + PELOGW(limLog(pMac, LOGW, "Channel switch can be done only in STA role, Current Role = %d", psessionEntry->limSystemRole);) return; } channel = psessionEntry->gLimChannelSwitch.primaryChannel; @@ -2550,7 +2559,7 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) */ if(!limIsSystemInActiveState(pMac)) { - PELOGW(limLog(pMac, LOGW, FL("Device is not in active state, cannot switch channel\n"));) + PELOGW(limLog(pMac, LOGW, FL("Device is not in active state, cannot switch channel"));) return; } @@ -2569,7 +2578,7 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) /* We need to restore pre-channelSwitch state on the STA */ if(limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system\n")); + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); return; } @@ -2585,13 +2594,13 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) switch(psessionEntry->gLimChannelSwitch.state) { case eLIM_CHANNEL_SWITCH_PRIMARY_ONLY: - PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_ONLY \n"));) + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_ONLY "));) limSwitchPrimaryChannel(pMac, psessionEntry->gLimChannelSwitch.primaryChannel,psessionEntry); psessionEntry->gLimChannelSwitch.state = eLIM_CHANNEL_SWITCH_IDLE; break; case eLIM_CHANNEL_SWITCH_SECONDARY_ONLY: - PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_SECONDARY_ONLY \n"));) + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_SECONDARY_ONLY "));) limSwitchPrimarySecondaryChannel(pMac, psessionEntry, psessionEntry->currentOperChannel, psessionEntry->gLimChannelSwitch.secondarySubBand); @@ -2599,7 +2608,7 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) break; case eLIM_CHANNEL_SWITCH_PRIMARY_AND_SECONDARY: - PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY\n"));) + PELOGW(limLog(pMac, LOGW, FL("CHANNEL_SWITCH_PRIMARY_AND_SECONDARY"));) limSwitchPrimarySecondaryChannel(pMac, psessionEntry, psessionEntry->gLimChannelSwitch.primaryChannel, psessionEntry->gLimChannelSwitch.secondarySubBand); @@ -2608,10 +2617,10 @@ void limProcessChannelSwitchTimeout(tpAniSirGlobal pMac) case eLIM_CHANNEL_SWITCH_IDLE: default: - PELOGE(limLog(pMac, LOGE, FL("incorrect state \n"));) + PELOGE(limLog(pMac, LOGE, FL("incorrect state "));) if(limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system\n")); + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); } return; /* Please note, this is 'return' and not 'break' */ } @@ -2721,11 +2730,11 @@ limUpdateChannelSwitch(struct sAniSirGlobal *pMac, tpSirProbeRespBeacon pBeacon } if (eSIR_SUCCESS != limStartChannelSwitch(pMac, psessionEntry)) { - PELOGW(limLog(pMac, LOGW, FL("Could not start Channel Switch\n"));) + PELOGW(limLog(pMac, LOGW, FL("Could not start Channel Switch"));) } limLog(pMac, LOGW, - FL("session %d primary chl %d, subband %d, count %d (%d ticks) \n"), + FL("session %d primary chl %d, subband %d, count %d (%d ticks) "), psessionEntry->peSessionId, psessionEntry->gLimChannelSwitch.primaryChannel, psessionEntry->gLimChannelSwitch.secondarySubBand, @@ -2757,18 +2766,18 @@ void limCancelDot11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry if (psessionEntry->limSystemRole != eLIM_STA_ROLE) return; - PELOGW(limLog(pMac, LOGW, FL("Received a beacon without channel switch IE\n"));) + PELOGW(limLog(pMac, LOGW, FL("Received a beacon without channel switch IE"));) MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_CHANNEL_SWITCH_TIMER)); if (tx_timer_deactivate(&pMac->lim.limTimers.gLimChannelSwitchTimer) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed!\n"));) + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed!"));) } /* We need to restore pre-channelSwitch state on the STA */ if (limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("LIM: Could not restore pre-channelSwitch (11h) state, resetting the system\n"));) + PELOGE(limLog(pMac, LOGE, FL("LIM: Could not restore pre-channelSwitch (11h) state, resetting the system"));) } } @@ -2791,7 +2800,7 @@ void limCancelDot11hQuiet(tpAniSirGlobal pMac, tpPESession psessionEntry) MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_TIMER)); if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed"));) } } else if (psessionEntry->gLimSpecMgmt.quietState == eLIM_QUIET_RUNNING) @@ -2799,7 +2808,7 @@ void limCancelDot11hQuiet(tpAniSirGlobal pMac, tpPESession psessionEntry) MTRACE(macTrace(pMac, TRACE_CODE_TIMER_DEACTIVATE, psessionEntry->peSessionId, eLIM_QUIET_BSS_TIMER)); if (tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer) != TX_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("tx_timer_deactivate failed"));) } /** * If the channel switch is already running in silent mode, dont resume the @@ -2852,11 +2861,11 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimQuietTimer.sessionId))== NULL) { - limLog(pMac, LOGE,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGE,FL("Session Does not exist for given sessionID")); return; } - PELOG1(limLog(pMac, LOG1, FL("quietState = %d\n"), psessionEntry->gLimSpecMgmt.quietState);) + PELOG1(limLog(pMac, LOG1, FL("quietState = %d"), psessionEntry->gLimSpecMgmt.quietState);) switch( psessionEntry->gLimSpecMgmt.quietState ) { case eLIM_QUIET_BEGIN: @@ -2866,7 +2875,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietBssTimer)) { limLog( pMac, LOGE, - FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...\n")); + FL("Unable to de-activate gLimQuietBssTimer! Will attempt to activate anyway...")); } // gLimQuietDuration appears to be in units of ticks @@ -2877,7 +2886,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) 0)) { limLog( pMac, LOGE, - FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...\n")); + FL("Unable to change gLimQuietBssTimer! Will still attempt to activate anyway...")); } MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, pMac->lim.limTimers.gLimQuietTimer.sessionId, eLIM_QUIET_BSS_TIMER)); #ifdef GEN6_TODO @@ -2890,7 +2899,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) tx_timer_activate( &pMac->lim.limTimers.gLimQuietBssTimer )) { limLog( pMac, LOGW, - FL("Unable to activate gLimQuietBssTimer! The STA will be unable to honor Quiet BSS...\n")); + FL("Unable to activate gLimQuietBssTimer! The STA will be unable to honor Quiet BSS...")); } else { @@ -2903,7 +2912,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) (eSIR_TRUE == (glimTriggerBackgroundScanDuringQuietBss_Status = limTriggerBackgroundScanDuringQuietBss( pMac ))) ) { limLog( pMac, LOG2, - FL("Attempting to trigger a background scan...\n")); + FL("Attempting to trigger a background scan...")); } else { @@ -2912,7 +2921,7 @@ void limProcessQuietTimeout(tpAniSirGlobal pMac) limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_STOP_TX); limLog( pMac, LOG2, - FL("Quiet BSS: STA shutting down for %d ticks\n"), + FL("Quiet BSS: STA shutting down for %d ticks"), psessionEntry->gLimSpecMgmt.quietDuration ); } } @@ -2973,11 +2982,11 @@ void limProcessQuietBssTimeout( tpAniSirGlobal pMac ) if((psessionEntry = peFindSessionBySessionId(pMac, pMac->lim.limTimers.gLimQuietBssTimer.sessionId))== NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } - PELOG1(limLog(pMac, LOG1, FL("quietState = %d\n"), psessionEntry->gLimSpecMgmt.quietState);) + PELOG1(limLog(pMac, LOG1, FL("quietState = %d"), psessionEntry->gLimSpecMgmt.quietState);) if (eLIM_AP_ROLE == psessionEntry->limSystemRole) { } @@ -3005,7 +3014,7 @@ void limProcessQuietBssTimeout( tpAniSirGlobal pMac ) glimTriggerBackgroundScanDuringQuietBss_Status = eSIR_TRUE; limLog( pMac, LOG2, - FL("Quiet BSS: Resuming traffic...\n")); + FL("Quiet BSS: Resuming traffic...")); } else { @@ -3015,14 +3024,14 @@ void limProcessQuietBssTimeout( tpAniSirGlobal pMac ) // SIR_LIM_QUIET_TIMEOUT will complete on its own // limLog( pMac, LOG2, - FL("Background scan should be complete now...\n")); + FL("Background scan should be complete now...")); } break; case eLIM_QUIET_INIT: case eLIM_QUIET_BEGIN: case eLIM_QUIET_END: - PELOG2(limLog(pMac, LOG2, FL("Quiet state not in RUNNING\n"));) + PELOG2(limLog(pMac, LOG2, FL("Quiet state not in RUNNING"));) /* If the quiet period has ended, then resume the frame transmission */ limFrameTransmissionControl(pMac, eLIM_TX_ALL, eLIM_RESUME_TX); limRestorePreQuietState(pMac, psessionEntry); @@ -3061,16 +3070,16 @@ void limProcessWPSOverlapTimeout(tpAniSirGlobal pMac) if (tx_timer_activate(&pMac->lim.limTimers.gLimWPSOverlapTimerObj.gLimWPSOverlapTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("tx_timer_activate failed\n")); + limLog(pMac, LOGP, FL("tx_timer_activate failed")); } sessionId = pMac->lim.limTimers.gLimWPSOverlapTimerObj.sessionId; - PELOGE(limLog(pMac, LOGE, FL("WPS overlap timeout, sessionId=%d\n"), sessionId);) + PELOGE(limLog(pMac, LOGE, FL("WPS overlap timeout, sessionId=%d"), sessionId);) if((psessionEntry = peFindSessionBySessionId(pMac, sessionId)) == NULL) { - PELOGE(limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n"));) + PELOGE(limLog(pMac, LOGP,FL("Session Does not exist for given sessionID"));) return; } @@ -3091,7 +3100,7 @@ void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId) psessionEntry = peFindSessionBySessionId(pMac , sessionId); if(psessionEntry == NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); return; } @@ -3105,7 +3114,7 @@ void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId) if( TX_SUCCESS != tx_timer_deactivate(&pMac->lim.limTimers.gLimQuietTimer)) { limLog( pMac, LOGE, - FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway...\n" )); + FL( "Unable to deactivate gLimQuietTimer! Will still attempt to re-activate anyway..." )); } // Set the NEW timeout value, in ticks @@ -3113,14 +3122,14 @@ void limStartQuietTimer(tpAniSirGlobal pMac, tANI_U8 sessionId) SYS_MS_TO_TICKS(psessionEntry->gLimSpecMgmt.quietTimeoutValue), 0)) { limLog( pMac, LOGE, - FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway...\n" )); + FL( "Unable to change gLimQuietTimer! Will still attempt to re-activate anyway..." )); } pMac->lim.limTimers.gLimQuietTimer.sessionId = sessionId; if( TX_SUCCESS != tx_timer_activate(&pMac->lim.limTimers.gLimQuietTimer)) { limLog( pMac, LOGE, - FL("Unable to activate gLimQuietTimer! STA cannot honor Quiet BSS!\n")); + FL("Unable to activate gLimQuietTimer! STA cannot honor Quiet BSS!")); limRestorePreQuietState(pMac, psessionEntry); psessionEntry->gLimSpecMgmt.quietState = eLIM_QUIET_INIT; @@ -3177,7 +3186,7 @@ limUtilCountStaDel( if (pMac->lim.gLimNumOfAniSTAs <= 0) { - limLog(pMac, LOGE, FL("CountStaDel: ignoring Delete Req when AniPeer count is %d\n"), + limLog(pMac, LOGE, FL("CountStaDel: ignoring Delete Req when AniPeer count is %d"), pMac->lim.gLimNumOfAniSTAs); return; } @@ -3216,14 +3225,14 @@ void limSwitchChannelCback(tpAniSirGlobal pMac, eHalStatus status, /* We need to restore pre-channelSwitch state on the STA */ if (limRestorePreChannelSwitchState(pMac, psessionEntry) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system\n")); + limLog(pMac, LOGP, FL("Could not restore pre-channelSwitch (11h) state, resetting the system")); return; } mmhMsg.type = eWNI_SME_SWITCH_CHL_REQ; if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pSirSmeSwitchChInd, sizeof(tSirSmeSwitchChannelInd))) { - limLog(pMac, LOGP, FL("Failed to allocate buffer for buffer descriptor\n")); + limLog(pMac, LOGP, FL("Failed to allocate buffer for buffer descriptor")); return; } @@ -3259,7 +3268,7 @@ void limSwitchPrimaryChannel(tpAniSirGlobal pMac, tANI_U8 newChannel,tpPESession tANI_U32 localPwrConstraint; #endif - PELOG3(limLog(pMac, LOG3, FL("limSwitchPrimaryChannel: old chnl %d --> new chnl %d \n"), + PELOG3(limLog(pMac, LOG3, FL("limSwitchPrimaryChannel: old chnl %d --> new chnl %d "), psessionEntry->currentOperChannel, newChannel);) psessionEntry->currentReqChannel = newChannel; psessionEntry->limRFBand = limGetRFBand(newChannel); @@ -3275,7 +3284,7 @@ void limSwitchPrimaryChannel(tpAniSirGlobal pMac, tANI_U8 newChannel,tpPESession #else if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { - limLog( pMac, LOGP, FL( "Unable to read Local Power Constraint from cfg\n" )); + limLog( pMac, LOGP, FL( "Unable to read Local Power Constraint from cfg" )); return; } limSendSwitchChnlParams(pMac, newChannel, PHY_SINGLE_CHANNEL_CENTERED, @@ -3311,7 +3320,7 @@ void limSwitchPrimarySecondaryChannel(tpAniSirGlobal pMac, tpPESession psessionE #if !defined WLAN_FEATURE_VOWIFI if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { - limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg\n" )); + limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg" )); return; } #endif @@ -3326,14 +3335,14 @@ void limSwitchPrimarySecondaryChannel(tpAniSirGlobal pMac, tpPESession psessionE if (psessionEntry->currentOperChannel != newChannel) { limLog(pMac, LOGW, - FL("switch old chnl %d --> new chnl %d \n"), + FL("switch old chnl %d --> new chnl %d "), psessionEntry->currentOperChannel, newChannel); psessionEntry->currentOperChannel = newChannel; } if (psessionEntry->htSecondaryChannelOffset != subband) { limLog(pMac, LOGW, - FL("switch old sec chnl %d --> new sec chnl %d \n"), + FL("switch old sec chnl %d --> new sec chnl %d "), psessionEntry->htSecondaryChannelOffset, subband); psessionEntry->htSecondaryChannelOffset = subband; if (psessionEntry->htSecondaryChannelOffset == PHY_SINGLE_CHANNEL_CENTERED) @@ -3381,13 +3390,13 @@ tANI_U8 limActiveScanAllowed( if (wlan_cfgGetStr(pMac, WNI_CFG_SCAN_CONTROL_LIST, channelPair, &len) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("Unable to get scan control list\n"));) + PELOGE(limLog(pMac, LOGE, FL("Unable to get scan control list"));) return false; } if (len > WNI_CFG_SCAN_CONTROL_LIST_LEN) { - limLog(pMac, LOGE, FL("Invalid scan control list length:%d\n"), + limLog(pMac, LOGE, FL("Invalid scan control list length:%d"), len); return false; } @@ -3473,13 +3482,13 @@ tAniBool limTriggerBackgroundScanDuringQuietBss( tpAniSirGlobal pMac ) else { limLog( pMac, LOGW, - FL("The next SCAN channel is the current operating channel on which a Quiet BSS is requested.! A background scan will not be triggered during this Quiet BSS period...\n")); + FL("The next SCAN channel is the current operating channel on which a Quiet BSS is requested.! A background scan will not be triggered during this Quiet BSS period...")); } } else { limLog( pMac, LOGW, - FL("Unable to retrieve WNI_CFG_VALID_CHANNEL_LIST from CFG! A background scan will not be triggered during this Quiet BSS period...\n")); + FL("Unable to retrieve WNI_CFG_VALID_CHANNEL_LIST from CFG! A background scan will not be triggered during this Quiet BSS period...")); } } return bScanTriggered; @@ -3739,7 +3748,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, { if(NULL == psessionEntry) { - PELOG3(limLog(pMac, LOG3, FL("psessionEntry is NULL\n"));) + PELOG3(limLog(pMac, LOG3, FL("psessionEntry is NULL"));) return eSIR_FAILURE; } //overlapping protection configuration check. @@ -3753,7 +3762,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, (!psessionEntry->cfgProtection.fromlla)) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from 11a is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from 11a is disabled"));) return eSIR_SUCCESS; } } @@ -3794,7 +3803,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, //This part is common for staiton as well. if(false == psessionEntry->beaconParams.llaCoexist) { - PELOG1(limLog(pMac, LOG1, FL(" => protection from 11A Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => protection from 11A Enabled"));) pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = true; pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; } @@ -3870,7 +3879,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.gLimOverlap11aParams.protectionEnabled && !psessionEntry->gLim11aParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled"));) pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; } @@ -3878,7 +3887,7 @@ limEnable11aProtection(tpAniSirGlobal pMac, tANI_U8 enable, //for station role else { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11A Disabled"));) pBeaconParams->llaCoexist = psessionEntry->beaconParams.llaCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llACOEXIST_CHANGED; } @@ -3912,14 +3921,14 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.fromllb) { // protection disabled. - PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE) { if(!pMac->lim.cfgProtection.fromllb) { // protection disabled. - PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("protection from 11b is disabled"));) return eSIR_SUCCESS; } } @@ -3934,7 +3943,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(overlap) { psessionEntry->gLimOlbcParams.protectionEnabled = true; - PELOGE(limLog(pMac, LOGE, FL("protection from olbc is enabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("protection from olbc is enabled"));) if(true == psessionEntry->htCapability) { if((eSIR_HT_OP_MODE_OVERLAP_LEGACY != psessionEntry->htOperMode) && @@ -3953,7 +3962,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, else { psessionEntry->gLim11bParams.protectionEnabled = true; - PELOGE(limLog(pMac, LOGE, FL("protection from 11b is enabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("protection from 11b is enabled"));) if(true == psessionEntry->htCapability) { if(eSIR_HT_OP_MODE_MIXED != psessionEntry->htOperMode) @@ -3997,7 +4006,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, //This part is common for staiton as well. if(false == psessionEntry->beaconParams.llbCoexist) { - PELOG1(limLog(pMac, LOG1, FL("=> 11G Protection Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("=> 11G Protection Enabled"));) pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = true; pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; } @@ -4042,7 +4051,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, { //Disable protection from 11B stations. psessionEntry->gLim11bParams.protectionEnabled = false; - PELOGE(limLog(pMac, LOGE, FL("===> 11B Protection Disabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("===> 11B Protection Disabled"));) //Check if any other non-HT protection enabled. if(!psessionEntry->gLim11gParams.protectionEnabled) { @@ -4057,7 +4066,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, psessionEntry->gLimOverlapNonGfParams.protectionEnabled) { psessionEntry->htOperMode = eSIR_HT_OP_MODE_OVERLAP_LEGACY; - PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled"));) limEnableHtRifsProtection(pMac, true, overlap, pBeaconParams,psessionEntry); } else if(psessionEntry->gLimHt20Params.protectionEnabled) @@ -4065,7 +4074,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, //Commenting because of CR 258588 WFA cert //psessionEntry->htOperMode = eSIR_HT_OP_MODE_NO_LEGACY_20MHZ_HT; psessionEntry->htOperMode = eSIR_HT_OP_MODE_PURE; - PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled"));) limEnableHtRifsProtection(pMac, false, overlap, pBeaconParams,psessionEntry); } else @@ -4078,7 +4087,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!psessionEntry->gLimOlbcParams.protectionEnabled && !psessionEntry->gLim11bParams.protectionEnabled) { - PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled\n"));) + PELOGE(limLog(pMac, LOGE, FL("===> 11G Protection Disabled"));) pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; } @@ -4147,7 +4156,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!psessionEntry->gLimOlbcParams.protectionEnabled && !psessionEntry->gLim11bParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; } @@ -4155,7 +4164,7 @@ limEnable11gProtection(tpAniSirGlobal pMac, tANI_U8 enable, //for station role else { - PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> 11G Protection Disabled"));) pBeaconParams->llbCoexist = psessionEntry->beaconParams.llbCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llBCOEXIST_CHANGED; } @@ -4184,12 +4193,12 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, if((psessionEntry->limSystemRole == eLIM_AP_ROLE ) && (!psessionEntry->cfgProtection.overlapFromllg)) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled\n"));); + PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled"));); return eSIR_SUCCESS; }else if ((psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) && (!pMac->lim.cfgProtection.overlapFromllg)) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled\n"));); + PELOG3(limLog(pMac, LOG3, FL("overlap protection from 11g is disabled"));); return eSIR_SUCCESS; } } @@ -4199,14 +4208,14 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, if((psessionEntry->limSystemRole == eLIM_AP_ROLE ) && !psessionEntry->cfgProtection.fromllg){ // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE ) { if(!pMac->lim.cfgProtection.fromllg) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from 11g is disabled"));) return eSIR_SUCCESS; } } @@ -4361,7 +4370,7 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, if(!psessionEntry->gLimOverlap11gParams.protectionEnabled && !psessionEntry->gLim11gParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));) pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; } @@ -4427,7 +4436,7 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.gLimOverlap11gParams.protectionEnabled && !psessionEntry->gLim11gParams.protectionEnabled) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));) pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; } @@ -4435,7 +4444,7 @@ limEnableHtProtectionFrom11g(tpAniSirGlobal pMac, tANI_U8 enable, //for station role else { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from 11G Disabled"));) pBeaconParams->llgCoexist = psessionEntry->beaconParams.llgCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_llGCOEXIST_CHANGED; } @@ -4473,14 +4482,14 @@ limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, if((psessionEntry->limSystemRole == eLIM_AP_ROLE) && !psessionEntry->cfgProtection.obss) { //ToDo Update this field // protection disabled. - PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE) { if(!pMac->lim.cfgProtection.obss) { //ToDo Update this field // protection disabled. - PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("protection from Obss is disabled"));) return eSIR_SUCCESS; } } @@ -4490,14 +4499,14 @@ limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, if (eLIM_AP_ROLE == psessionEntry->limSystemRole){ if ((enable) && (false == psessionEntry->beaconParams.gHTObssMode) ) { - PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled"));) psessionEntry->beaconParams.gHTObssMode = true; pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; // UPDATE AN ENUM FOR OBSS MODE } else if (!enable && (true == psessionEntry->beaconParams.gHTObssMode)) { - PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled"));) psessionEntry->beaconParams.gHTObssMode = false; pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; @@ -4511,7 +4520,7 @@ limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, { if ((enable) && (false == psessionEntry->beaconParams.gHTObssMode) ) { - PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("=>obss protection enabled"));) psessionEntry->beaconParams.gHTObssMode = true; pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; // UPDATE AN ENUM FOR OBSS MODE @@ -4519,7 +4528,7 @@ limEnableHtOBSSProtection(tpAniSirGlobal pMac, tANI_U8 enable, else if (!enable && (true == psessionEntry->beaconParams.gHTObssMode)) { - PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> obss Protection disabled"));) psessionEntry->beaconParams.gHTObssMode = false; pBeaconParams->paramChangeBitmap |= PARAM_OBSS_MODE_CHANGED; @@ -4553,14 +4562,14 @@ limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.ht20) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE ) { if(!pMac->lim.cfgProtection.ht20) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from HT20 is disabled"));) return eSIR_SUCCESS; } } @@ -4621,7 +4630,7 @@ limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, //This part is common for staiton as well. if(false == psessionEntry->beaconParams.ht20Coexist) { - PELOG1(limLog(pMac, LOG1, FL("=> Prtection from HT20 Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("=> Prtection from HT20 Enabled"));) pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = true; pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; } @@ -4675,7 +4684,7 @@ limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); } } - PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled"));) pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; }else if(eLIM_BT_AMP_AP_ROLE == psessionEntry->limSystemRole) @@ -4721,14 +4730,14 @@ limEnableHT20Protection(tpAniSirGlobal pMac, tANI_U8 enable, limEnableHtOBSSProtection(pMac, false, overlap, pBeaconParams,psessionEntry); } } - PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT 20 Disabled"));) pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; } //for station role else { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT20 Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from HT20 Disabled"));) pBeaconParams->ht20MhzCoexist = psessionEntry->beaconParams.ht20Coexist = false; pBeaconParams->paramChangeBitmap |= PARAM_HT20MHZCOEXIST_CHANGED; } @@ -4763,7 +4772,7 @@ limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.nonGf) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE) { @@ -4771,7 +4780,7 @@ limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.cfgProtection.nonGf) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL("protection from NonGf is disabled"));) return eSIR_SUCCESS; } } @@ -4779,13 +4788,13 @@ limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(psessionEntry->limSystemRole == eLIM_AP_ROLE){ if ((enable) && (false == psessionEntry->beaconParams.llnNonGFCoexist)) { - PELOG1(limLog(pMac, LOG1, FL(" => Prtection from non GF Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Prtection from non GF Enabled"));) pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = true; pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; } else if (!enable && (true == psessionEntry->beaconParams.llnNonGFCoexist)) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled"));) pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; } @@ -4793,13 +4802,13 @@ limEnableHTNonGfProtection(tpAniSirGlobal pMac, tANI_U8 enable, { if ((enable) && (false == psessionEntry->beaconParams.llnNonGFCoexist)) { - PELOG1(limLog(pMac, LOG1, FL(" => Prtection from non GF Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Prtection from non GF Enabled"));) pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = true; pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; } else if (!enable && (true == psessionEntry->beaconParams.llnNonGFCoexist)) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from Non GF Disabled"));) pBeaconParams->llnNonGFCoexist = psessionEntry->beaconParams.llnNonGFCoexist = false; pBeaconParams->paramChangeBitmap |= PARAM_NON_GF_DEVICES_PRESENT_CHANGED; } @@ -4834,7 +4843,7 @@ limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.lsigTxop) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE) { @@ -4842,7 +4851,7 @@ limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.cfgProtection.lsigTxop) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL(" protection from LsigTxop not supported is disabled"));) return eSIR_SUCCESS; } } @@ -4852,13 +4861,13 @@ limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(psessionEntry->limSystemRole == eLIM_AP_ROLE){ if ((enable) && (false == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) { - PELOG1(limLog(pMac, LOG1, FL(" => Prtection from LsigTxop Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Prtection from LsigTxop Enabled"));) pBeaconParams->fLsigTXOPProtectionFullSupport = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = true; pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; } else if (!enable && (true == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled"));) pBeaconParams->fLsigTXOPProtectionFullSupport= psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = false; pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; } @@ -4866,13 +4875,13 @@ limEnableHTLsigTxopProtection(tpAniSirGlobal pMac, tANI_U8 enable, { if ((enable) && (false == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) { - PELOG1(limLog(pMac, LOG1, FL(" => Prtection from LsigTxop Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Prtection from LsigTxop Enabled"));) pBeaconParams->fLsigTXOPProtectionFullSupport = psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = true; pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; } else if (!enable && (true == psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport)) { - PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Protection from LsigTxop Disabled"));) pBeaconParams->fLsigTXOPProtectionFullSupport= psessionEntry->beaconParams.fLsigTXOPProtectionFullSupport = false; pBeaconParams->paramChangeBitmap |= PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED; } @@ -4908,7 +4917,7 @@ limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, !psessionEntry->cfgProtection.rifs) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled"));) return eSIR_SUCCESS; }else if(psessionEntry->limSystemRole != eLIM_AP_ROLE ) { @@ -4916,7 +4925,7 @@ limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, if(!pMac->lim.cfgProtection.rifs) { // protection disabled. - PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled\n"));) + PELOG3(limLog(pMac, LOG3, FL(" protection from Rifs is disabled"));) return eSIR_SUCCESS; } } @@ -4926,14 +4935,14 @@ limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, // Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS if ((!enable) && (false == psessionEntry->beaconParams.fRIFSMode)) { - PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled"));) pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = true; pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; } // Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS else if (enable && (true == psessionEntry->beaconParams.fRIFSMode)) { - PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled"));) pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = false; pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; } @@ -4942,14 +4951,14 @@ limEnableHtRifsProtection(tpAniSirGlobal pMac, tANI_U8 enable, // Disabling the RIFS Protection means Enable the RIFS mode of operation in the BSS if ((!enable) && (false == psessionEntry->beaconParams.fRIFSMode)) { - PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL(" => Rifs protection Disabled"));) pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = true; pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; } // Enabling the RIFS Protection means Disable the RIFS mode of operation in the BSS else if (enable && (true == psessionEntry->beaconParams.fRIFSMode)) { - PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Rifs Protection Enabled"));) pBeaconParams->fRIFSMode = psessionEntry->beaconParams.fRIFSMode = false; pBeaconParams->paramChangeBitmap |= PARAM_RIFS_MODE_CHANGED; } @@ -4982,7 +4991,7 @@ limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams if (wlan_cfgGetInt(pMac, WNI_CFG_SHORT_PREAMBLE, &val) != eSIR_SUCCESS) { /* Could not get short preamble enabled flag from CFG. Log error. */ - limLog(pMac, LOGP, FL("could not retrieve short preamble flag\n")); + limLog(pMac, LOGP, FL("could not retrieve short preamble flag")); return eSIR_FAILURE; } @@ -4991,7 +5000,7 @@ limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams if (wlan_cfgGetInt(pMac, WNI_CFG_11G_SHORT_PREAMBLE_ENABLED, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve 11G short preamble switching enabled flag\n")); + limLog(pMac, LOGP, FL("could not retrieve 11G short preamble switching enabled flag")); return eSIR_FAILURE; } @@ -5002,14 +5011,14 @@ limEnableShortPreamble(tpAniSirGlobal pMac, tANI_U8 enable, tpUpdateBeaconParams { if (enable && (psessionEntry->beaconParams.fShortPreamble == 0)) { - PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Enabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Enabled"));) psessionEntry->beaconParams.fShortPreamble = true; pBeaconParams->fShortPreamble = (tANI_U8) psessionEntry->beaconParams.fShortPreamble; pBeaconParams->paramChangeBitmap |= PARAM_SHORT_PREAMBLE_CHANGED; } else if (!enable && (psessionEntry->beaconParams.fShortPreamble == 1)) { - PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Disabled\n"));) + PELOG1(limLog(pMac, LOG1, FL("===> Short Preamble Disabled"));) psessionEntry->beaconParams.fShortPreamble = false; pBeaconParams->fShortPreamble = (tANI_U8) psessionEntry->beaconParams.fShortPreamble; pBeaconParams->paramChangeBitmap |= PARAM_SHORT_PREAMBLE_CHANGED; @@ -5122,7 +5131,7 @@ void limUpdateStaRunTimeHTSwitchChnlParams( tpAniSirGlobal pMac, #if !defined WLAN_FEATURE_VOWIFI if(wlan_cfgGetInt(pMac, WNI_CFG_LOCAL_POWER_CONSTRAINT, &localPwrConstraint) != eSIR_SUCCESS) { - limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg\n" )); + limLog( pMac, LOGP, FL( "Unable to get Local Power Constraint from cfg" )); return; } #endif @@ -5137,9 +5146,9 @@ void limUpdateStaRunTimeHTSwitchChnlParams( tpAniSirGlobal pMac, // Notify HAL limLog( pMac, LOGW, FL( "Channel Information in HT IE change" - "d; sending notification to HAL.\n" ) ); + "d; sending notification to HAL." ) ); limLog( pMac, LOGW, FL( "Primary Channel: %d, Secondary Chan" - "nel Offset: %d, Channel Width: %d\n" ), + "nel Offset: %d, Channel Width: %d" ), pHTInfo->primaryChannel, secondaryChnlOffset, psessionEntry->htRecommendedTxWidthSet ); psessionEntry->channelChangeReasonCode=LIM_SWITCH_CHANNEL_OPERATION; @@ -5314,7 +5323,7 @@ tSirRetStatus limProcessHalIndMessages(tpAniSirGlobal pMac, tANI_U32 msgId, void default: palFreeMemory(pMac->hHdd, msgParam); - limLog(pMac, LOGP, FL("invalid message id = %d received\n"), msgId); + limLog(pMac, LOGP, FL("invalid message id = %d received"), msgId); return eSIR_FAILURE; } @@ -5353,7 +5362,7 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe */ if(pDeltsReq == NULL) { - PELOGE(limLog(pMac, LOGE, FL("Delete TS request pointer is NULL\n"));) + PELOGE(limLog(pMac, LOGE, FL("Delete TS request pointer is NULL"));) return eSIR_FAILURE; } @@ -5369,7 +5378,7 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe if (wlan_cfgGetStr(pMac, WNI_CFG_BSSID, peerMacAddr, &val) != eSIR_SUCCESS) { /// Could not get BSSID from CFG. Log error. - limLog(pMac, LOGP, FL("could not retrieve BSSID\n")); + limLog(pMac, LOGP, FL("could not retrieve BSSID")); return eSIR_FAILURE; } #endif// TO SUPPORT BT-AMP @@ -5395,14 +5404,14 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe if (pSta == NULL) { - PELOGE(limLog(pMac, LOGE, "Cannot find station context for delts req\n");) + PELOGE(limLog(pMac, LOGE, "Cannot find station context for delts req");) return eSIR_FAILURE; } if ((! pSta->valid) || (pSta->mlmStaContext.mlmState != eLIM_MLM_LINK_ESTABLISHED_STATE)) { - PELOGE(limLog(pMac, LOGE, "Invalid Sta (or state) for DelTsReq\n");) + PELOGE(limLog(pMac, LOGE, "Invalid Sta (or state) for DelTsReq");) return eSIR_FAILURE; } @@ -5419,14 +5428,14 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe pDeltsReq->req.lleTspecPresent = 1; else { - PELOGW(limLog(pMac, LOGW, FL("DELTS_REQ ignore - qos is disabled\n"));) + PELOGW(limLog(pMac, LOGW, FL("DELTS_REQ ignore - qos is disabled"));) return eSIR_FAILURE; } tsinfo = pDeltsReq->req.wmeTspecPresent ? &pDeltsReq->req.tspec.tsinfo : &pDeltsReq->req.tsinfo; PELOG1(limLog(pMac, LOG1, - FL("received DELTS_REQ message (wmeTspecPresent = %d, lleTspecPresent = %d, wsmTspecPresent = %d, tsid %d, up %d, direction = %d)\n"), + FL("received DELTS_REQ message (wmeTspecPresent = %d, lleTspecPresent = %d, wsmTspecPresent = %d, tsid %d, up %d, direction = %d)"), pDeltsReq->req.wmeTspecPresent, pDeltsReq->req.lleTspecPresent, pDeltsReq->req.wsmTspecPresent, tsinfo->traffic.tsid, tsinfo->traffic.userPrio, tsinfo->traffic.direction);) @@ -5435,7 +5444,7 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe if (limAdmitControlDeleteTS(pMac, pSta->assocId, tsinfo, &tsStatus, &tspecIdx) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, "ERROR DELTS request for sta assocId %d (tsid %d, up %d)\n", + PELOGE(limLog(pMac, LOGE, "ERROR DELTS request for sta assocId %d (tsid %d, up %d)", pSta->assocId, tsinfo->traffic.tsid, tsinfo->traffic.userPrio);) return eSIR_FAILURE; } @@ -5452,7 +5461,7 @@ limValidateDeltsReq(tpAniSirGlobal pMac, tpSirDeltsReq pDeltsReq, tSirMacAddr pe //send message to HAL to delete TS if(eSIR_SUCCESS != limSendHalMsgDelTs(pMac, pSta->staIndex, tspecIdx, pDeltsReq->req, psessionEntry->peSessionId)) { - limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request\n"), + limLog(pMac, LOGW, FL("DelTs with UP %d failed in limSendHalMsgDelTs - ignoring request"), tsinfo->traffic.userPrio); return eSIR_FAILURE; } @@ -5475,7 +5484,7 @@ limRegisterHalIndCallBack(tpAniSirGlobal pMac) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pHalCB, sizeof(tHalIndCB))) { - limLog(pMac, LOGP, FL("palAllocateMemory() failed\n")); + limLog(pMac, LOGP, FL("palAllocateMemory() failed")); return; } @@ -5489,7 +5498,7 @@ limRegisterHalIndCallBack(tpAniSirGlobal pMac) if(eSIR_SUCCESS != wdaPostCtrlMsg(pMac, &msg)) { palFreeMemory(pMac->hHdd, pHalCB); - limLog(pMac, LOGP, FL("wdaPostCtrlMsg() failed\n")); + limLog(pMac, LOGP, FL("wdaPostCtrlMsg() failed")); } return; @@ -5530,7 +5539,7 @@ limProcessAddBaInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if ((psessionEntry = peFindSessionByBssid(pMac,pBaActivityInd->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given BSSId\n")); + limLog(pMac, LOGE,FL("session does not exist for given BSSId")); palFreeMemory(pMac->hHdd, limMsg->bodyptr); return; } @@ -5599,60 +5608,135 @@ limProcessAddBaInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) /** ------------------------------------------------------------- -\fn limDelAllBASessions -\brief Deletes all the exisitng BA sessions. -\ Note : This API is provided for Mac OSx only. The reason for this is that Mac OSx may not -\ restart after CFG update. +\fn limDeleteBASessions +\brief Deletes all the exisitng BA sessions for given session + and BA direction. \param tpAniSirGlobal pMac -\return None +\param tpPESession pSessionEntry +\param tANI_U32 baDirection +\return None -------------------------------------------------------------*/ void -limDelAllBASessions(tpAniSirGlobal pMac) +limDeleteBASessions(tpAniSirGlobal pMac, tpPESession pSessionEntry, + tANI_U32 baDirection) { tANI_U32 i; tANI_U8 tid; tpDphHashNode pSta; - tpPESession psessionEntry = &pMac->lim.gpSession[0]; //TBD-RAJESH HOW TO GET sessionEntry????? - for(tid = 0; tid < STACFG_MAX_TC; tid++) + if (NULL == pSessionEntry) { - if((eLIM_AP_ROLE == psessionEntry->limSystemRole) ||(psessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE)|| - (eLIM_STA_IN_IBSS_ROLE == psessionEntry->limSystemRole)) + limLog(pMac, LOGE, FL("Session does not exist")); + } + else + { + for(tid = 0; tid < STACFG_MAX_TC; tid++) { - for(i = 0; i < pMac->lim.maxStation; i++) + if ((eLIM_AP_ROLE == pSessionEntry->limSystemRole) || + (pSessionEntry->limSystemRole == eLIM_BT_AMP_AP_ROLE) || + (eLIM_STA_IN_IBSS_ROLE == pSessionEntry->limSystemRole) || + (pSessionEntry->limSystemRole == eLIM_P2P_DEVICE_GO)) + { + for (i = 0; i < pMac->lim.maxStation; i++) + { + pSta = pSessionEntry->dph.dphHashTable.pDphNodeArray + i; + if (pSta && pSta->added) + { + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) && + (baDirection & BA_INITIATOR)) + { + limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); + } + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) && + (baDirection & BA_RECIPIENT)) + { + limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); + } + } + } + } + else if ((eLIM_STA_ROLE == pSessionEntry->limSystemRole) || + (eLIM_BT_AMP_STA_ROLE == pSessionEntry->limSystemRole) || + (eLIM_P2P_DEVICE_ROLE == pSessionEntry->limSystemRole)) { - pSta = psessionEntry->dph.dphHashTable.pDphNodeArray + i; + pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, + &pSessionEntry->dph.dphHashTable); if (pSta && pSta->added) { - if(eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) && + (baDirection & BA_INITIATOR)) { - limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); + limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); } - else if(eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) + if ((eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) && + (baDirection & BA_RECIPIENT)) { - limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); + limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, + eSIR_MAC_UNSPEC_FAILURE_REASON, + pSessionEntry); } } } } - else if((eLIM_STA_ROLE == psessionEntry->limSystemRole)||(eLIM_BT_AMP_STA_ROLE == psessionEntry->limSystemRole)) + } +} + +/** ------------------------------------------------------------- +\fn limDelAllBASessions +\brief Deletes all the exisitng BA sessions. +\param tpAniSirGlobal pMac +\return None +-------------------------------------------------------------*/ + +void limDelAllBASessions(tpAniSirGlobal pMac) +{ + tANI_U32 i; + tpPESession pSessionEntry; + + for (i = 0; i < pMac->lim.maxBssId; i++) + { + pSessionEntry = peFindSessionBySessionId(pMac, i); + if (pSessionEntry) { - pSta = dphGetHashEntry(pMac, DPH_STA_HASH_INDEX_PEER, &psessionEntry->dph.dphHashTable); - if (pSta && pSta->added) + limDeleteBASessions(pMac, pSessionEntry, BA_BOTH_DIRECTIONS); + } + } +} + +/** ------------------------------------------------------------- +\fn limDelAllBASessionsBtc +\brief Deletes all the exisitng BA receipent sessions in 2.4GHz + band. +\param tpAniSirGlobal pMac +\return None +-------------------------------------------------------------*/ + +void limDelAllBASessionsBtc(tpAniSirGlobal pMac) +{ + tANI_U32 i; + tpPESession pSessionEntry; + + for (i = 0; i < pMac->lim.maxBssId; i++) + { + pSessionEntry = peFindSessionBySessionId(pMac, i); + if (pSessionEntry) + { + if (SIR_BAND_2_4_GHZ == + limGetRFBand(pSessionEntry->currentOperChannel)) { - if(eBA_ENABLE == pSta->tcCfg[tid].fUseBATx) - { - limPostMlmDelBAReq(pMac, pSta, eBA_INITIATOR, tid, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); - } - if(eBA_ENABLE == pSta->tcCfg[tid].fUseBARx) - { - limPostMlmDelBAReq(pMac, pSta, eBA_RECIPIENT, tid, eSIR_MAC_UNSPEC_FAILURE_REASON,psessionEntry); - } + limDeleteBASessions(pMac, pSessionEntry, BA_RECIPIENT); } } } } + /** ------------------------------------------------------------- \fn limProcessDelTsInd \brief handles the DeleteTS indication coming from HAL or generated by PE itself in some error cases. @@ -5675,7 +5759,7 @@ limProcessDelTsInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg) if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== NULL) { - limLog(pMac, LOGE,FL("session does not exist for given BssId\n")); + limLog(pMac, LOGE,FL("session does not exist for given BssId")); palFreeMemory(pMac->hHdd, (void *)(limMsg->bodyptr)); return; } @@ -5683,21 +5767,21 @@ if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== pTspecInfo = &(pMac->lim.tspecInfo[pDelTsParam->tspecIdx]); if(pTspecInfo->inuse == false) { - PELOGE(limLog(pMac, LOGE, FL("tspec entry with index %d is not in use\n"), pDelTsParam->tspecIdx);) + PELOGE(limLog(pMac, LOGE, FL("tspec entry with index %d is not in use"), pDelTsParam->tspecIdx);) goto error1; } pSta = dphGetHashEntry(pMac, pTspecInfo->assocId, &psessionEntry->dph.dphHashTable); if(pSta == NULL) { - limLog(pMac, LOGE, FL("Could not find entry in DPH table for assocId = %d\n"), + limLog(pMac, LOGE, FL("Could not find entry in DPH table for assocId = %d"), pTspecInfo->assocId); goto error1; } if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pDelTsReq, sizeof(tSirDeltsReq))) { - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory() failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory() failed"));) goto error1; } @@ -5712,10 +5796,10 @@ if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== //validate the req if (eSIR_SUCCESS != limValidateDeltsReq(pMac, pDelTsReq, peerMacAddr,psessionEntry)) { - PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("limValidateDeltsReq failed"));) goto error2; } - PELOG1(limLog(pMac, LOG1, "Sent DELTS request to station with assocId = %d MacAddr = %x:%x:%x:%x:%x:%x\n", + PELOG1(limLog(pMac, LOG1, "Sent DELTS request to station with assocId = %d MacAddr = %x:%x:%x:%x:%x:%x", pDelTsReq->aid, peerMacAddr[0], peerMacAddr[1], peerMacAddr[2], peerMacAddr[3], peerMacAddr[4], peerMacAddr[5]);) @@ -5725,7 +5809,7 @@ if((psessionEntry = peFindSessionByBssid(pMac,pDelTsParam->bssId,&sessionId))== // prepare and send an sme indication to HDD if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pDelTsReqInfo, sizeof(tSirDeltsReqInfo))) { - PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory() failed\n"));) + PELOGE(limLog(pMac, LOGE, FL("palAllocateMemory() failed"));) goto error3; } palZeroMemory( pMac->hHdd, (tANI_U8 *)pDelTsReqInfo, sizeof(tSirDeltsReqInfo)); @@ -5767,10 +5851,10 @@ tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, tANI_U8 tid, tANI_U16 startingSeqNum,tpPESession psessionEntry) { tSirRetStatus status = eSIR_SUCCESS; - tpLimMlmAddBAReq pMlmAddBAReq; + tpLimMlmAddBAReq pMlmAddBAReq = NULL; tpDialogueToken dialogueTokenNode; tANI_U32 val = 0; - + // Check if the peer is a 11n capable STA // FIXME - Need a 11n peer indication in DPH. // For now, using the taurusPeer attribute @@ -5782,7 +5866,7 @@ tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, (void **) &pMlmAddBAReq, sizeof( tLimMlmAddBAReq ))) { - limLog( pMac, LOGP, FL("palAllocateMemory failed\n")); + limLog( pMac, LOGP, FL("palAllocateMemory failed")); status = eSIR_MEM_ALLOC_FAILED; goto returnFailure; } @@ -5809,23 +5893,22 @@ tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, pMlmAddBAReq->baBufferSize = 0; limLog( pMac, LOGW, - FL( "Requesting an ADDBA to setup a %s BA session with STA %d for TID %d\n" ), + FL( "Requesting an ADDBA to setup a %s BA session with STA %d for TID %d" ), (pMlmAddBAReq->baPolicy ? "Immediate": "Delayed"), pStaDs->staIndex, tid ); // BA Timeout - // pMlmAddBAReq->baTimeout = pMac->hal.halMac.baTimeout; // In TU's - if (wlan_cfgGetInt(pMac, WNI_CFG_BA_TIMEOUT, &val) != eSIR_SUCCESS) + if (wlan_cfgGetInt(pMac, WNI_CFG_BA_TIMEOUT, &val) != eSIR_SUCCESS) { - limLog(pMac, LOGE, FL("could not retrieve BA TIME OUT Param CFG\n")); + limLog(pMac, LOGE, FL("could not retrieve BA TIME OUT Param CFG")); status = eSIR_FAILURE; goto returnFailure; } pMlmAddBAReq->baTimeout = val; // In TU's // ADDBA Failure Timeout - // FIXME_AMPDU - Need to retrieve this from CFG. + // FIXME_AMPDU - Need to retrieve this from CFG. //right now we are not checking for response timeout. so this field is dummy just to be compliant with the spec. pMlmAddBAReq->addBAFailureTimeout = 2000; // In TU's @@ -5837,20 +5920,26 @@ tSirRetStatus limPostMlmAddBAReq( tpAniSirGlobal pMac, LIM_SET_STA_BA_STATE(pStaDs, tid, eLIM_BA_STATE_WT_ADD_RSP); - if( NULL == (dialogueTokenNode = limAssignDialogueToken(pMac))) - goto returnFailure; - + dialogueTokenNode = limAssignDialogueToken(pMac); + if (NULL == dialogueTokenNode) + { + limLog(pMac, LOGE, FL("could not assign dialogue token")); + status = eSIR_FAILURE; + goto returnFailure; + } + pMlmAddBAReq->baDialogToken = dialogueTokenNode->token; - //set assocId and tid information in the lim linked list + //set assocId and tid information in the lim linked list dialogueTokenNode->assocId = pStaDs->assocId; dialogueTokenNode->tid = tid; // Send ADDBA Req to MLME limPostMlmMessage( pMac, LIM_MLM_ADDBA_REQ, (tANI_U32 *) pMlmAddBAReq ); + return eSIR_SUCCESS; returnFailure: - + palFreeMemory(pMac->hHdd, pMlmAddBAReq); return status; } @@ -5900,7 +5989,7 @@ tpLimMlmAddBARsp pMlmAddBARsp; sizeof( tLimMlmAddBARsp ))) { limLog( pMac, LOGE, - FL("palAllocateMemory failed with error code %d\n"), + FL("palAllocateMemory failed with error code %d"), status ); status = eSIR_MEM_ALLOC_FAILED; @@ -5976,7 +6065,7 @@ LIM_GET_STA_BA_STATE(pSta, baTID, &curBaState); if( eLIM_BA_STATE_IDLE != curBaState) { limLog( pMac, LOGE, - FL( "Received unexpected DELBA REQ when STA BA state for tid = %d is %d\n" ), + FL( "Received unexpected DELBA REQ when STA BA state for tid = %d is %d" ), baTID, curBaState); @@ -5990,7 +6079,7 @@ LIM_GET_STA_BA_STATE(pSta, baTID, &curBaState); sizeof( tLimMlmDelBAReq ))) { limLog( pMac, LOGE, - FL("palAllocateMemory failed with error code %d\n"), + FL("palAllocateMemory failed with error code %d"), status ); status = eSIR_MEM_ALLOC_FAILED; @@ -6101,7 +6190,7 @@ tSirMsgQ msgQ; sizeof( tAddBAParams )))) { limLog( pMac, LOGE, - FL("palAllocateMemory failed with error code %d\n"), + FL("palAllocateMemory failed with error code %d"), status ); retCode = eSIR_MEM_ALLOC_FAILED; @@ -6154,7 +6243,7 @@ tSirMsgQ msgQ; if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) limLog( pMac, LOGE, - FL("Posting WDA_ADDBA_REQ to HAL failed! Reason = %d\n"), + FL("Posting WDA_ADDBA_REQ to HAL failed! Reason = %d"), retCode ); else return retCode; @@ -6206,7 +6295,7 @@ tSirMsgQ msgQ; sizeof( tDelBAParams )))) { limLog( pMac, LOGE, - FL("palAllocateMemory failed with error code %d\n"), + FL("palAllocateMemory failed with error code %d"), status ); retCode = eSIR_MEM_ALLOC_FAILED; @@ -6247,7 +6336,7 @@ tSirMsgQ msgQ; if( eSIR_SUCCESS != (retCode = wdaPostCtrlMsg( pMac, &msgQ ))) limLog( pMac, LOGE, - FL("Posting WDA_DELBA_IND to HAL failed! Reason = %d\n"), + FL("Posting WDA_DELBA_IND to HAL failed! Reason = %d"), retCode ); else { @@ -6308,7 +6397,7 @@ limPostSMStateUpdate(tpAniSirGlobal pMac, // Allocate for WDA_SET_MIMOPS_REQ status = palAllocateMemory( pMac->hHdd, (void **) &pMIMO_PSParams, sizeof( tSetMIMOPS)); if( eHAL_STATUS_SUCCESS != status) { - limLog( pMac, LOGP,FL(" palAllocateMemory failed with error code %d\n"), status ); + limLog( pMac, LOGP,FL(" palAllocateMemory failed with error code %d"), status ); return eSIR_MEM_ALLOC_FAILED; } @@ -6324,7 +6413,7 @@ limPostSMStateUpdate(tpAniSirGlobal pMac, retCode = wdaPostCtrlMsg( pMac, &msgQ ); if (eSIR_SUCCESS != retCode) { - limLog( pMac, LOGP, FL("Posting WDA_SET_MIMOPS_REQ to HAL failed! Reason = %d\n"), retCode ); + limLog( pMac, LOGP, FL("Posting WDA_SET_MIMOPS_REQ to HAL failed! Reason = %d"), retCode ); palFreeMemory(pMac->hHdd, (void *) pMIMO_PSParams); return retCode; } @@ -6402,7 +6491,7 @@ void limAddScanChannelInfo(tpAniSirGlobal pMac, tANI_U8 channelId) } else { - PELOGW(limLog(pMac, LOGW, FL(" -- number of channels exceed mac\n"));) + PELOGW(limLog(pMac, LOGW, FL(" -- number of channels exceed mac"));) } } } @@ -6436,7 +6525,7 @@ limIsChannelValidForChannelSwitch(tpAniSirGlobal pMac, tANI_U8 channel) (tANI_U8 *)validChannelList, (tANI_U32 *)&validChannelListLen) != eSIR_SUCCESS) { - PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list\n"));) + PELOGE(limLog(pMac, LOGE, FL("could not retrieve valid channel list"));) return (eSIR_FALSE); } @@ -6495,7 +6584,7 @@ __limFillTxControlParams(tpAniSirGlobal pMac, tpTxControlParams pTxCtrlMsg, case eLIM_TX_BSS: //Fall thru... default: - PELOGW(limLog(pMac, LOGW, FL("Invalid case: Not Handled\n"));) + PELOGW(limLog(pMac, LOGW, FL("Invalid case: Not Handled"));) return eHAL_STATUS_FAILURE; } @@ -6536,7 +6625,7 @@ void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLim (sizeof(*pTxCtrlMsg) + nBytes)); if (status != eHAL_STATUS_SUCCESS) { - limLog(pMac, LOGP, FL("palAllocateMemory() failed\n")); + limLog(pMac, LOGP, FL("palAllocateMemory() failed")); return; } @@ -6545,7 +6634,7 @@ void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLim if (status != eHAL_STATUS_SUCCESS) { palFreeMemory(pMac->hHdd, (void *) pTxCtrlMsg); - limLog(pMac, LOGP, FL("palZeroMemory() failed, status = %d\n"), status); + limLog(pMac, LOGP, FL("palZeroMemory() failed, status = %d"), status); return; } @@ -6553,7 +6642,7 @@ void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLim if (status != eHAL_STATUS_SUCCESS) { palFreeMemory(pMac->hHdd, (void *) pTxCtrlMsg); - limLog(pMac, LOGP, FL("__limFillTxControlParams failed, status = %d\n"), status); + limLog(pMac, LOGP, FL("__limFillTxControlParams failed, status = %d"), status); return; } @@ -6566,17 +6655,17 @@ void limFrameTransmissionControl(tpAniSirGlobal pMac, tLimQuietTxMode type, tLim if(wdaPostCtrlMsg( pMac, &msgQ) != eSIR_SUCCESS) { palFreeMemory(pMac->hHdd, (void *) pTxCtrlMsg); - limLog( pMac, LOGP, FL("Posting Message to HAL failed\n")); + limLog( pMac, LOGP, FL("Posting Message to HAL failed")); return; } if (mode == eLIM_STOP_TX) { - PELOG1(limLog(pMac, LOG1, FL("Stopping the transmission of all packets, indicated softmac\n"));) + PELOG1(limLog(pMac, LOG1, FL("Stopping the transmission of all packets, indicated softmac"));) } else { - PELOG1(limLog(pMac, LOG1, FL("Resuming the transmission of all packets, indicated softmac\n"));) + PELOG1(limLog(pMac, LOG1, FL("Resuming the transmission of all packets, indicated softmac"));) } return; } @@ -6627,7 +6716,7 @@ limRestorePreChannelSwitchState(tpAniSirGlobal pMac, tpPESession psessionEntry) &val)) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve Background scan period value\n")); + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); return (retCode); } @@ -6689,7 +6778,7 @@ tSirRetStatus limRestorePreQuietState(tpAniSirGlobal pMac, tpPESession psessionE &val)) != eSIR_SUCCESS) { - limLog(pMac, LOGP, FL("could not retrieve Background scan period value\n")); + limLog(pMac, LOGP, FL("could not retrieve Background scan period value")); return (retCode); } @@ -6756,7 +6845,7 @@ limPrepareFor11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry) if(pMac->lim.gLimSmeState == eLIM_SME_LINK_EST_WT_SCAN_STATE || pMac->lim.gLimSmeState == eLIM_SME_CHANNEL_SCAN_STATE) { - PELOGE(limLog(pMac, LOGE, FL("Posting finish scan as we are in scan state\n"));) + PELOGE(limLog(pMac, LOGE, FL("Posting finish scan as we are in scan state"));) /* Stop ongoing scanning if any */ if (GET_LIM_PROCESS_DEFD_MESGS(pMac)) { @@ -6773,7 +6862,7 @@ limPrepareFor11hChannelSwitch(tpAniSirGlobal pMac, tpPESession psessionEntry) } else { - PELOGE(limLog(pMac, LOGE, FL("Not in scan state, start channel switch timer\n"));) + PELOGE(limLog(pMac, LOGE, FL("Not in scan state, start channel switch timer"));) /** We are safe to switch channel at this point */ limStopTxAndSwitchChannel(pMac, psessionEntry->peSessionId); } @@ -6825,14 +6914,14 @@ tSirNwType limGetNwType(tpAniSirGlobal pMac, tANI_U8 channelNum, tANI_U32 type, } if (pBeacon->extendedRatesPresent) { - PELOG3(limLog(pMac, LOG3, FL("Beacon, nwtype=G\n"));) + PELOG3(limLog(pMac, LOG3, FL("Beacon, nwtype=G"));) nwType = eSIR_11G_NW_TYPE; } } else { // 11a packet - PELOG3(limLog(pMac, LOG3,FL("Beacon, nwtype=A\n"));) + PELOG3(limLog(pMac, LOG3,FL("Beacon, nwtype=A"));) nwType = eSIR_11A_NW_TYPE; } } @@ -6887,7 +6976,7 @@ void limSetTspecUapsdMask(tpAniSirGlobal pMac, tSirMacTSInfo *pTsInfo, tANI_U32 tANI_U16 direction = pTsInfo->traffic.direction; tANI_U8 ac = upToAc(userPrio); - PELOG1(limLog(pMac, LOG1, FL(" Set UAPSD mask for AC %d, direction %d, action=%d (1=set,0=clear) \n"),ac, direction, action );) + PELOG1(limLog(pMac, LOG1, FL(" Set UAPSD mask for AC %d, direction %d, action=%d (1=set,0=clear) "),ac, direction, action );) /* Converting AC to appropriate Uapsd Bit Mask * AC_BE(0) --> UAPSD_BITOFFSET_ACVO(3) @@ -6922,8 +7011,8 @@ void limSetTspecUapsdMask(tpAniSirGlobal pMac, tSirMacTSInfo *pTsInfo, tANI_U32 } } - limLog(pMac, LOGE, FL("New pMac->lim.gUapsdPerAcTriggerEnableMask = 0x%x \n"), pMac->lim.gUapsdPerAcTriggerEnableMask ); - limLog(pMac, LOGE, FL("New pMac->lim.gUapsdPerAcDeliveryEnableMask = 0x%x \n"), pMac->lim.gUapsdPerAcDeliveryEnableMask ); + limLog(pMac, LOGE, FL("New pMac->lim.gUapsdPerAcTriggerEnableMask = 0x%x "), pMac->lim.gUapsdPerAcTriggerEnableMask ); + limLog(pMac, LOGE, FL("New pMac->lim.gUapsdPerAcDeliveryEnableMask = 0x%x "), pMac->lim.gUapsdPerAcDeliveryEnableMask ); return; } @@ -6961,13 +7050,13 @@ void limHandleHeartBeatTimeout(tpAniSirGlobal pMac ) if(pMac->lim.gpSession[i].LimHBFailureStatus == eANI_BOOLEAN_TRUE) { /* Activate Probe After HeartBeat Timer incase HB Failure detected */ - PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d\n"), + PELOGW(limLog(pMac, LOGW,FL("Sending Probe for Session: %d"), i);) limDeactivateAndChangeTimer(pMac, eLIM_PROBE_AFTER_HB_TIMER); MTRACE(macTrace(pMac, TRACE_CODE_TIMER_ACTIVATE, 0, eLIM_PROBE_AFTER_HB_TIMER)); if (tx_timer_activate(&pMac->lim.limTimers.gLimProbeAfterHBTimer) != TX_SUCCESS) { - limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer\n")); + limLog(pMac, LOGP, FL("Fail to re-activate Probe-after-heartbeat timer")); limReactivateHeartBeatTimer(pMac, &pMac->lim.gpSession[i]); } break; @@ -7044,7 +7133,7 @@ void limProcessAddStaRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) if((psessionEntry = peFindSessionBySessionId(pMac,pAddStaParams->sessionId))==NULL) { - limLog(pMac, LOGP,FL("Session Does not exist for given sessionID\n")); + limLog(pMac, LOGP,FL("Session Does not exist for given sessionID")); palFreeMemory(pMac, pAddStaParams); return; } @@ -7107,13 +7196,14 @@ void limHandleHeartBeatFailureTimeout(tpAniSirGlobal pMac) psessionEntry = &pMac->lim.gpSession[i]; if(psessionEntry->LimHBFailureStatus == eANI_BOOLEAN_TRUE) { - limLog(pMac, LOGE, FL("Probe_hb_failure: SME %d, MLME %d, HB-Count %d\n"),psessionEntry->limSmeState, + limLog(pMac, LOGE, FL("Probe_hb_failure: SME %d, MLME %d, HB-Count %d"),psessionEntry->limSmeState, psessionEntry->limMlmState, psessionEntry->LimRxedBeaconCntDuringHB); if (psessionEntry->limMlmState == eLIM_MLM_LINK_ESTABLISHED_STATE) { - if (!LIM_IS_CONNECTION_ACTIVE(psessionEntry)) + if ((!LIM_IS_CONNECTION_ACTIVE(psessionEntry))&& + (psessionEntry->limSmeState != eLIM_SME_WT_DISASSOC_STATE)) { - limLog(pMac, LOGE, FL("Probe_hb_failure: for session:%d \n" ),psessionEntry->peSessionId); + limLog(pMac, LOGE, FL("Probe_hb_failure: for session:%d " ),psessionEntry->peSessionId); /* AP did not respond to Probe Request. Tear down link with it.*/ limTearDownLinkWithAp(pMac, psessionEntry->peSessionId, @@ -7127,7 +7217,7 @@ void limHandleHeartBeatFailureTimeout(tpAniSirGlobal pMac) } else { - limLog(pMac, LOGE, FL("Unexpected wt-probe-timeout in state \n")); + limLog(pMac, LOGE, FL("Unexpected wt-probe-timeout in state ")); limPrintMlmState(pMac, LOGE, psessionEntry->limMlmState); limReactivateHeartBeatTimer(pMac, psessionEntry); } @@ -7246,7 +7336,7 @@ void limProcessAddStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pRsp, sizeof(tSirSmeAddStaSelfRsp))) { /// Buffer not available. Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for Add Sta self RSP\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for Add Sta self RSP")); palFreeMemory( pMac->hHdd, (tANI_U8 *)pAddStaSelfParams); return; } @@ -7282,7 +7372,7 @@ void limProcessDelStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) if( eHAL_STATUS_SUCCESS != palAllocateMemory( pMac->hHdd, (void **)&pRsp, sizeof(tSirSmeDelStaSelfRsp))) { /// Buffer not available. Log error - limLog(pMac, LOGP, FL("call to palAllocateMemory failed for Add Sta self RSP\n")); + limLog(pMac, LOGP, FL("call to palAllocateMemory failed for Add Sta self RSP")); palFreeMemory( pMac->hHdd, (tANI_U8 *)pDelStaSelfParams); return; } @@ -7314,6 +7404,11 @@ void limProcessDelStaSelfRsp(tpAniSirGlobal pMac,tpSirMsgQ limMsgQ) tANI_U8 limUnmapChannel(tANI_U8 mapChannel) { if( mapChannel > 0 && mapChannel < 25 ) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE) + return aUnsortedChannelList[mapChannel -1]; + else +#endif return abChannel[mapChannel -1]; else return 0; @@ -7376,7 +7471,7 @@ v_U8_t* limGetVendorIEOuiPtr(tpAniSirGlobal pMac, tANI_U8 *oui, tANI_U8 oui_size if(elem_len > left) { limLog( pMac, LOGE, - FL("****Invalid IEs eid = %d elem_len=%d left=%d*****\n"), + FL("****Invalid IEs eid = %d elem_len=%d left=%d*****"), elem_id,elem_len,left); return NULL; } @@ -7411,12 +7506,21 @@ v_U8_t limBuildP2pIe(tpAniSirGlobal pMac, tANI_U8 *ie, tANI_U8 *data, tANI_U8 ie v_U8_t limGetNoaAttrStreamInMultP2pIes(tpAniSirGlobal pMac,v_U8_t* noaStream,v_U8_t noaLen,v_U8_t overFlowLen) { v_U8_t overFlowP2pStream[SIR_MAX_NOA_ATTR_LEN]; - palCopyMemory( pMac->hHdd, overFlowP2pStream, noaStream + noaLen - overFlowLen, overFlowLen); - noaStream[noaLen - overFlowLen] = SIR_MAC_EID_VENDOR; - noaStream[noaLen - overFlowLen+1] = overFlowLen + SIR_MAC_P2P_OUI_SIZE; - palCopyMemory( pMac->hHdd, noaStream+ noaLen - overFlowLen+2,SIR_MAC_P2P_OUI,SIR_MAC_P2P_OUI_SIZE); - - palCopyMemory( pMac->hHdd, noaStream+ noaLen - overFlowLen+2+SIR_MAC_P2P_OUI_SIZE,overFlowP2pStream,overFlowLen); + + if ((noaLen <= (SIR_MAX_NOA_ATTR_LEN+SIR_P2P_IE_HEADER_LEN)) && + (noaLen >= overFlowLen) && (overFlowLen <= SIR_MAX_NOA_ATTR_LEN)) + { + palCopyMemory( pMac->hHdd, overFlowP2pStream, + noaStream + noaLen - overFlowLen, overFlowLen); + noaStream[noaLen - overFlowLen] = SIR_MAC_EID_VENDOR; + noaStream[noaLen - overFlowLen + 1] = overFlowLen + SIR_MAC_P2P_OUI_SIZE; + palCopyMemory( pMac->hHdd, noaStream+noaLen-overFlowLen + 2, + SIR_MAC_P2P_OUI, SIR_MAC_P2P_OUI_SIZE); + palCopyMemory( pMac->hHdd, + noaStream+noaLen + 2 + SIR_MAC_P2P_OUI_SIZE - overFlowLen, + overFlowP2pStream, overFlowLen); + } + return (noaLen + SIR_P2P_IE_HEADER_LEN); } @@ -7615,6 +7719,6 @@ tANI_U8 limGetShortSlotFromPhyMode(tpAniSirGlobal pMac, tpPESession psessionEntr // Will reach here in 11b case val = false; } - limLog(pMac, LOG1, FL("phyMode = %u shortslotsupported = %u\n"), phyMode, val); + limLog(pMac, LOG1, FL("phyMode = %u shortslotsupported = %u"), phyMode, val); return val; } diff --git a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h index 3a1f9b69775..d4a17812809 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h +++ b/drivers/staging/prima/CORE/MAC/src/pe/lim/limUtils.h @@ -348,6 +348,8 @@ tSirRetStatus limPostSMStateUpdate(tpAniSirGlobal pMac, void limDeleteStaContext(tpAniSirGlobal pMac, tpSirMsgQ limMsg); void limProcessAddBaInd(tpAniSirGlobal pMac, tpSirMsgQ limMsg); +void limDeleteBASessions(tpAniSirGlobal pMac, tpPESession pSessionEntry, tANI_U32 baDirection); +void limDelAllBASessionsBtc(tpAniSirGlobal pMac); void limDelAllBASessions(tpAniSirGlobal pMac); void limDeleteDialogueTokenList(tpAniSirGlobal pMac); tSirRetStatus limSearchAndDeleteDialogueToken(tpAniSirGlobal pMac, tANI_U8 token, tANI_U16 assocId, tANI_U16 tid); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c b/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c index 4dfbe7587c6..d280b6336f2 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/pmm/pmmApi.c @@ -815,12 +815,6 @@ tSirRetStatus pmmSendPowerSaveCfg(tpAniSirGlobal pMac, tpSirPowerSaveCfg pUpdate pmmLog(pMac, LOGP, FL("pmmCfg: cfgGet failed for ignoreDtim")); pUpdatedPwrSaveCfg->ignoreDtim = (tANI_U8) ignoreDtim; - /* The numBeaconPerRssiAverage should be <= rssiFilter Period, - * and less than the max allowed (default set to 20 in CFG) - */ - if (numBeaconPerRssiAverage > rssiFilterPeriod) - pUpdatedPwrSaveCfg->numBeaconPerRssiAverage = (tANI_U8)GET_MIN_VALUE(rssiFilterPeriod, WNI_CFG_NUM_BEACON_PER_RSSI_AVERAGE_STAMAX); - //Save a copy of the CFG in global pmm context. palCopyMemory( pMac->hHdd, (tANI_U8 *) &pMac->pmm.gPmmCfg, pUpdatedPwrSaveCfg, sizeof(tSirPowerSaveCfg)); @@ -2157,17 +2151,23 @@ void pmmEnterWowlRequestHandler(tpAniSirGlobal pMac, tpSirMsgQ pMsg) #endif //FEATURE_WLAN_DIAG_SUPPORT pSmeWowlParams = (tpSirSmeWowlEnterParams)(pMbMsg->data); + if (NULL == pSmeWowlParams) + { + limLog(pMac, LOGE, + FL("NULL message received")); + return; + } - if((pSessionEntry = peFindSessionByBssid(pMac,pSmeWowlParams->bssId,&peSessionId))== NULL) + pSessionEntry = peFindSessionByBssid(pMac, pSmeWowlParams->bssId, + &peSessionId); + if (NULL == pSessionEntry) { - limLog(pMac, LOGE, + limLog(pMac, LOGE, FL("session does not exist for given BSSId")); goto end; } pMac->pmm.sessionId = peSessionId; - if (NULL == pSmeWowlParams) - return; // Need to fix it ASAP - TBH #if 0 if (pMac->lim.gLimSmeState != eLIM_SME_LINK_EST_STATE) diff --git a/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c b/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c index d276e519df7..29987c52ec1 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/rrm/rrmApi.c @@ -39,15 +39,15 @@ * PERFORMANCE OF THIS SOFTWARE. */ + + + /**========================================================================= \file rrmApi.c \brief implementation for PE RRM APIs - Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved. - - Qualcomm Confidential and Proprietary. ========================================================================*/ @@ -223,16 +223,31 @@ rrmSetMaxTxPowerRsp ( tpAniSirGlobal pMac, tpSirMsgQ limMsgQ ) tSirRetStatus retCode = eSIR_SUCCESS; tpMaxTxPowerParams pMaxTxParams = (tpMaxTxPowerParams) limMsgQ->bodyptr; tpPESession pSessionEntry; - tANI_U8 sessionId; + tANI_U8 sessionId, i; + tSirMacAddr bssid = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - if((pSessionEntry = peFindSessionByBssid(pMac, pMaxTxParams->bssId, &sessionId))==NULL) + if( palEqualMemory(pMac->hHdd, bssid, pMaxTxParams->bssId, sizeof(tSirMacAddr))) { - PELOGE(limLog(pMac, LOGE, FL("Unable to find session:") );) - retCode = eSIR_FAILURE; + for (i =0;i < pMac->lim.maxBssId;i++) + { + if ( (pMac->lim.gpSession[i].valid == TRUE )) + { + pSessionEntry = &pMac->lim.gpSession[i]; + rrmCacheMgmtTxPower ( pMac, pMaxTxParams->power, pSessionEntry ); + } + } } else { - rrmCacheMgmtTxPower ( pMac, pMaxTxParams->power, pSessionEntry ); + if((pSessionEntry = peFindSessionByBssid(pMac, pMaxTxParams->bssId, &sessionId))==NULL) + { + PELOGE(limLog(pMac, LOGE, FL("Unable to find session:") );) + retCode = eSIR_FAILURE; + } + else + { + rrmCacheMgmtTxPower ( pMac, pMaxTxParams->power, pSessionEntry ); + } } palFreeMemory(pMac->hHdd, (void*)limMsgQ->bodyptr); diff --git a/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c b/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c index ab66fa211bf..3d6db8c73fc 100644 --- a/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c +++ b/drivers/staging/prima/CORE/MAC/src/pe/sch/schBeaconProcess.c @@ -656,7 +656,11 @@ void schBeaconProcess(tpAniSirGlobal pMac, tANI_U8* pRxPacketInfo, tpPESession p * */ - if((pAPSession = limIsApSessionActive(pMac)) != NULL) + if (((pAPSession = limIsApSessionActive(pMac)) != NULL) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (!(WDA_GET_OFFLOADSCANLEARN(pRxPacketInfo))) +#endif + ) { beaconParams.bssIdx = pAPSession->bssIdx; if (pAPSession->gLimProtectionControl != WNI_CFG_FORCE_POLICY_PROTECTION_DISABLE) diff --git a/drivers/staging/prima/CORE/SAP/inc/sapApi.h b/drivers/staging/prima/CORE/SAP/inc/sapApi.h index 18cfef49339..43c2e9d2aac 100644 --- a/drivers/staging/prima/CORE/SAP/inc/sapApi.h +++ b/drivers/staging/prima/CORE/SAP/inc/sapApi.h @@ -109,10 +109,9 @@ when who what, where, why /*-------------------------------------------------------------------------- defines and enum ------------------------------------------------------------------------*/ - + #define MAX_SSID_LEN 32 -#define MAX_MAC_ADDRESS_ACCEPTED 16 -#define MAX_MAC_ADDRESS_DENIED MAX_MAC_ADDRESS_ACCEPTED +#define MAX_ACL_MAC_ADDRESS 16 #define AUTO_CHANNEL_SELECT 0 #define MAX_ASSOC_IND_IE_LEN 255 @@ -419,11 +418,11 @@ typedef struct sap_Config { tSap_SSIDInfo_t SSIDinfo; eSapPhyMode SapHw_mode; /* Wireless Mode */ eSapMacAddrACL SapMacaddr_acl; - v_MACADDR_t accept_mac[MAX_MAC_ADDRESS_ACCEPTED]; /* MAC filtering */ + v_MACADDR_t accept_mac[MAX_ACL_MAC_ADDRESS]; /* MAC filtering */ v_BOOL_t ieee80211d; /*Specify if 11D is enabled or disabled*/ v_BOOL_t protEnabled; /*Specify if protection is enabled or disabled*/ v_BOOL_t obssProtEnabled; /*Specify if OBSS protection is enabled or disabled*/ - v_MACADDR_t deny_mac[MAX_MAC_ADDRESS_DENIED]; /* MAC filtering */ + v_MACADDR_t deny_mac[MAX_ACL_MAC_ADDRESS]; /* MAC filtering */ v_MACADDR_t self_macaddr; //self macaddress or BSSID v_U8_t channel; /* Operation channel */ @@ -906,6 +905,38 @@ WLANSAP_StartBss tsap_Config_t *pConfig, v_PVOID_t pUsrContext ); +/*========================================================================== + FUNCTION WLANSAP_SetMacACL + + DESCRIPTION + This api function provides SAP to set mac list entry in accept list as well + as deny list + + DEPENDENCIES + NA. + + PARAMETERS + + IN +pvosGCtx: Pointer to vos global context structure +pConfig: Pointer to configuration structure passed down from + HDD(HostApd for Android) + + + RETURN VALUE + The VOS_STATUS code associated with performing the operation + + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetMacACL +( + v_PVOID_t pvosGCtx, + tsap_Config_t *pConfig +); + /*========================================================================== FUNCTION WLANSAP_Stop diff --git a/drivers/staging/prima/CORE/SAP/src/sapChSelect.c b/drivers/staging/prima/CORE/SAP/src/sapChSelect.c index d7c5f924584..8c5b143410e 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapChSelect.c +++ b/drivers/staging/prima/CORE/SAP/src/sapChSelect.c @@ -96,6 +96,11 @@ --------------------------------------------------------------------------*/ #define SAP_DEBUG +#define IS_RSSI_VALID( extRssi, rssi ) \ +( \ + ((extRssi < rssi)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) + /*========================================================================== FUNCTION sapCleanupChannelList @@ -487,6 +492,7 @@ v_U32_t sapweightRssiCount(v_S7_t rssi, v_U16_t count) void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) { tSapSpectChInfo *pExtSpectCh = NULL; + v_S31_t rssi; switch(pSpectCh->chNum) { case CHANNEL_1: @@ -494,7 +500,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -502,7 +512,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -510,7 +524,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -518,7 +536,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -528,7 +550,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -536,7 +562,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -544,7 +574,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -552,7 +586,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -568,7 +606,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -576,7 +618,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -584,7 +630,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -592,7 +642,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -602,7 +656,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -610,7 +668,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -618,7 +680,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -626,7 +692,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -636,7 +706,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FIRST_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -644,7 +718,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_SEC_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -652,7 +730,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_THIRD_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -660,7 +742,11 @@ void sapInterferenceRssiCount(tSapSpectChInfo *pSpectCh) if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_24GHZ_FOURTH_OVERLAP_CHAN_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -797,8 +883,12 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; // REducing the rssi by -20 and assigning it to Extension channel - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -807,7 +897,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, pExtSpectCh = (pSpectCh - 1); if(pExtSpectCh != NULL) { - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; ++pExtSpectCh->bssCount; @@ -823,7 +917,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); // Reducing the rssi by -20 and assigning it to Subband 1 + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -20 and assigning it to Subband 1 + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -831,7 +929,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY); // Reducing the rssi by -30 and assigning it to Subband 2 + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -30 and assigning it to Subband 2 + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -839,7 +941,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY); // Reducing the rssi by -40 and assigning it to Subband 3 + rssi = pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; // Reducing the rssi by -40 and assigning it to Subband 3 + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -851,7 +957,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -859,7 +969,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -867,7 +981,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -879,7 +997,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -887,7 +1009,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -895,7 +1021,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -907,7 +1037,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND1_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -915,7 +1049,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND2_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -923,7 +1061,11 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, if(pExtSpectCh != NULL) { ++pExtSpectCh->bssCount; - pExtSpectCh->rssiAgr = (pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY); + rssi = pSpectCh->rssiAgr + SAP_SUBBAND3_RSSI_EFFECT_PRIMARY; + if (IS_RSSI_VALID(pExtSpectCh->rssiAgr, rssi)) + { + pExtSpectCh->rssiAgr = rssi; + } if(pExtSpectCh->rssiAgr < SOFTAP_MIN_RSSI) pExtSpectCh->rssiAgr = SOFTAP_MIN_RSSI; } @@ -937,7 +1079,7 @@ void sapComputeSpectWeight( tSapChSelSpectInfo* pSpectInfoParams, } VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, - "In %s, bssdes.ch_self=%d, bssdes.ch_ID=%d, bssdes.rssi=%d, SpectCh.bssCount=%d, pScanResult=0x%x, ChannelWidth %d, secondaryChanOffset %d, center frequency %d \n", + "In %s, bssdes.ch_self=%d, bssdes.ch_ID=%d, bssdes.rssi=%d, SpectCh.bssCount=%d, pScanResult=%p, ChannelWidth %d, secondaryChanOffset %d, center frequency %d \n", __func__, pScanResult->BssDescriptor.channelIdSelf, pScanResult->BssDescriptor.channelId, pScanResult->BssDescriptor.rssi, pSpectCh->bssCount, pScanResult,pSpectCh->channelWidth,secondaryChannelOffset,centerFreq); pSpectCh++; break; @@ -1070,57 +1212,6 @@ void sapSortChlWeight(tSapChSelSpectInfo *pSpectInfoParams) } -/*========================================================================== - FUNCTION sapComputeNonOverlapChannel - - DESCRIPTION - Checking for the Free Non Overlapping Channel - - DEPENDENCIES - NA. - - PARAMETERS - - IN - pSpectInfoParams: Spectrum Info params - - RETURN VALUE - v_U8_t : Success - Bit mask - - SIDE EFFECTS -============================================================================*/ -v_U8_t sapComputeNonOverlapChannel(tSapChSelSpectInfo* pSpectInfoParams) -{ - v_U8_t nonOverlap = 0; - tSapSpectChInfo *pSpectCh = NULL; - v_U8_t chn_num = 0; - pSpectCh = pSpectInfoParams->pSpectCh; - for (chn_num = 0; chn_num < (pSpectInfoParams->numSpectChans); chn_num++) { - if(pSpectCh->chNum == CHANNEL_1 || pSpectCh->chNum == CHANNEL_6 || pSpectCh->chNum == CHANNEL_11) - { - switch(pSpectCh->chNum) - { - case 1: - if(pSpectCh->weight == 0) - nonOverlap |= 0x1; //Bit 0 For channel 1 - break; - case 6: - if(pSpectCh->weight == 0) - nonOverlap |= 0x2; // Bit 1 For Channel 6 - break; - case 11: - if(pSpectCh->weight == 0) - nonOverlap |= 0x4; // Bit 2 for Channel 11 - break; - default: - break; - } - } - pSpectCh++; - } - return nonOverlap; -} - /*========================================================================== FUNCTION sapSelectChannel @@ -1147,7 +1238,6 @@ v_U8_t sapSelectChannel(tHalHandle halHandle, ptSapContext pSapCtx, tScanResult // DFS param object holding all the data req by the algo tSapChSelSpectInfo oSpectInfoParams = {NULL,0}; tSapChSelSpectInfo *pSpectInfoParams = &oSpectInfoParams; // Memory? NB - v_U8_t nonOverlap = 0; v_U8_t bestChNum = 0; #ifdef SOFTAP_CHANNEL_RANGE v_U32_t startChannelNum; @@ -1177,59 +1267,49 @@ v_U8_t sapSelectChannel(tHalHandle halHandle, ptSapContext pSapCtx, tScanResult ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_END_CHANNEL, &endChannelNum); ccmCfgGetInt( halHandle, WNI_CFG_SAP_CHANNEL_SELECT_OPERATING_BAND, &operatingBand); - // Calculating the Non overlapping Channel Availability */ - if(operatingBand == RF_SUBBAND_2_4_GHZ) - nonOverlap = sapComputeNonOverlapChannel(pSpectInfoParams); - /*Loop till get the best channel in the given range */ for(count=0; count < pSpectInfoParams->numSpectChans ; count++) { if((startChannelNum <= pSpectInfoParams->pSpectCh[count].chNum)&& ( endChannelNum >= pSpectInfoParams->pSpectCh[count].chNum)) { - bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum; - break; - } - } - + if(bestChNum == 0) + { + bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum; + } + else + { + if(operatingBand == RF_SUBBAND_2_4_GHZ) + { + /* Give preference to Non-overlap channels */ + if(((pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_1) || + (pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_6) || + (pSpectInfoParams->pSpectCh[count].chNum == CHANNEL_11))&& + (pSpectInfoParams->pSpectCh[count].weight == 0)) + { + bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[count].chNum; + break; + } + } + } + } + } #else // Get the first channel in sorted array as best 20M Channel bestChNum = (v_U8_t)pSpectInfoParams->pSpectCh[0].chNum; - #endif - + //Select Best Channel from Channel List if Configured bestChNum = sapSelectPreferredChannelFromChannelList(bestChNum, pSapCtx, pSpectInfoParams); - if(operatingBand == RF_SUBBAND_2_4_GHZ) - { - if(nonOverlap) - { - switch(nonOverlap) - { - case 0x1: - bestChNum = CHANNEL_1; - break; - case 0x2: - bestChNum = CHANNEL_6; - break; - case 0x4: - bestChNum = CHANNEL_11; - break; - default: - break; - } - } - } - // Free all the allocated memory sapChanSelExit(pSpectInfoParams); VOS_TRACE(VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "In %s, Running SAP Ch select Completed, Ch=%d", - __func__, bestChNum); - + __func__, bestChNum); if (bestChNum > 0 && bestChNum <= 252) return bestChNum; else return SAP_CHANNEL_NOT_SELECTED; } + diff --git a/drivers/staging/prima/CORE/SAP/src/sapFsm.c b/drivers/staging/prima/CORE/SAP/src/sapFsm.c index 13860c10bd5..fb441a3caca 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapFsm.c +++ b/drivers/staging/prima/CORE/SAP/src/sapFsm.c @@ -513,7 +513,11 @@ sapSignalHDDevent /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /* Format the Start BSS Complete event to return... */ - VOS_ASSERT(sapContext->pfnSapEventCallback); + if (NULL == sapContext->pfnSapEventCallback) + { + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } switch (sapHddevent) { diff --git a/drivers/staging/prima/CORE/SAP/src/sapInternal.h b/drivers/staging/prima/CORE/SAP/src/sapInternal.h index 915ef1f315c..a4629942b9e 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapInternal.h +++ b/drivers/staging/prima/CORE/SAP/src/sapInternal.h @@ -204,9 +204,9 @@ typedef struct sSapContext { // Mac filtering settings eSapMacAddrACL eSapMacAddrAclMode; - v_MACADDR_t acceptMacList[MAX_MAC_ADDRESS_ACCEPTED]; + v_MACADDR_t acceptMacList[MAX_ACL_MAC_ADDRESS]; v_U8_t nAcceptMac; - v_MACADDR_t denyMacList[MAX_MAC_ADDRESS_DENIED]; + v_MACADDR_t denyMacList[MAX_ACL_MAC_ADDRESS]; v_U8_t nDenyMac; // QOS config @@ -592,26 +592,28 @@ sapSortMacList(v_MACADDR_t *macList, v_U8_t size); FUNCTION sapAddMacToACL - DESCRIPTION + DESCRIPTION Function to ADD a mac address in an ACL. The function ensures that the ACL list remains sorted after the addition. - This API does not take care of buffer overflow i.e. if the list is already maxed out while adding a mac address, - it will still try to add. - The caller must take care that the ACL size is less than MAX_MAC_ADDRESS_ACCEPTED before calling this function. + This API does not take care of buffer overflow i.e. if the list is already + maxed out while adding a mac address, it will still try to add. + The caller must take care that the ACL size is less than MAX_ACL_MAC_ADDRESS + before calling this function. - DEPENDENCIES + DEPENDENCIES - PARAMETERS + PARAMETERS IN macList : ACL list of mac addresses (black/white list) - size (I/O) : size of the ACL. It is an I/O arg. The API takes care of incrementing the size by 1. + size (I/O) : size of the ACL. It is an I/O arg. The API takes care + of incrementing the size by 1. peerMac : Mac address of the peer to be added RETURN VALUE None. - SIDE EFFECTS + SIDE EFFECTS ============================================================================*/ void diff --git a/drivers/staging/prima/CORE/SAP/src/sapModule.c b/drivers/staging/prima/CORE/SAP/src/sapModule.c index 4b3a9fb014f..b6a184fc6b0 100644 --- a/drivers/staging/prima/CORE/SAP/src/sapModule.c +++ b/drivers/staging/prima/CORE/SAP/src/sapModule.c @@ -466,7 +466,7 @@ WLANSAP_CleanCB pSapCtx->sapsMachine= eSAP_DISCONNECTED; - VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Initializing State: %d, sapContext value = %x", + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, "%s: Initializing State: %d, sapContext value = %p", __func__, pSapCtx->sapsMachine, pSapCtx); pSapCtx->sessionId = 0; pSapCtx->channel = 0; @@ -674,6 +674,82 @@ WLANSAP_StartBss return vosStatus; }// WLANSAP_StartBss +/*========================================================================== + FUNCTION WLANSAP_SetMacACL + + DESCRIPTION + This api function provides SAP to set mac list entry in accept list as well + as deny list + + DEPENDENCIES + + PARAMETERS + + IN + pContext : Pointer to Sap Context structure + pQctCommitConfig : Pointer to configuration structure passed down from + HDD(HostApd for Android) + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_FAULT: Pointer to SAP cb is NULL ; access would cause a page + fault + VOS_STATUS_SUCCESS: Success + + SIDE EFFECTS +============================================================================*/ +VOS_STATUS +WLANSAP_SetMacACL +( + v_PVOID_t pvosGCtx, //pwextCtx + tsap_Config_t *pConfig +) +{ + VOS_STATUS vosStatus = VOS_STATUS_SUCCESS; + ptSapContext pSapCtx = NULL; + + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "WLANSAP_SetMacACL"); + + if (VOS_STA_SAP_MODE == vos_get_conparam ()) + { + pSapCtx = VOS_GET_SAP_CB(pvosGCtx); + if ( NULL == pSapCtx ) + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_INFO_HIGH, + "%s: Invalid SAP pointer from pvosGCtx", __func__); + return VOS_STATUS_E_FAULT; + } + + // Copy MAC filtering settings to sap context + pSapCtx->eSapMacAddrAclMode = pConfig->SapMacaddr_acl; + + if (eSAP_DENY_UNLESS_ACCEPTED == pSapCtx->eSapMacAddrAclMode) + { + vos_mem_copy(pSapCtx->acceptMacList, pConfig->accept_mac, + sizeof(pConfig->accept_mac)); + pSapCtx->nAcceptMac = pConfig->num_accept_mac; + sapSortMacList(pSapCtx->acceptMacList, pSapCtx->nAcceptMac); + } + else if (eSAP_ACCEPT_UNLESS_DENIED == pSapCtx->eSapMacAddrAclMode) + { + vos_mem_copy(pSapCtx->denyMacList, pConfig->deny_mac, + sizeof(pConfig->deny_mac)); + pSapCtx->nDenyMac = pConfig->num_deny_mac; + sapSortMacList(pSapCtx->denyMacList, pSapCtx->nDenyMac); + } + } + else + { + VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, + "%s : SoftAp role has not been enabled", __func__); + return VOS_STATUS_E_FAULT; + } + + return vosStatus; +}//WLANSAP_SetMacACL + /*========================================================================== FUNCTION WLANSAP_StopBss @@ -1011,7 +1087,7 @@ WLANSAP_ModifyACL { //error check // if list is already at max, return failure - if (pSapCtx->nAcceptMac == MAX_MAC_ADDRESS_ACCEPTED) + if (pSapCtx->nAcceptMac == MAX_ACL_MAC_ADDRESS) { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "White list is already maxed out. Cannot accept %02x:%02x:%02x:%02x:%02x:%02x", @@ -1074,7 +1150,7 @@ WLANSAP_ModifyACL { //error check // if list is already at max, return failure - if (pSapCtx->nDenyMac == MAX_MAC_ADDRESS_ACCEPTED) + if (pSapCtx->nDenyMac == MAX_ACL_MAC_ADDRESS) { VOS_TRACE( VOS_MODULE_ID_SAP, VOS_TRACE_LEVEL_ERROR, "Black list is already maxed out. Cannot accept %02x:%02x:%02x:%02x:%02x:%02x", diff --git a/drivers/staging/prima/CORE/SME/inc/csrApi.h b/drivers/staging/prima/CORE/SME/inc/csrApi.h index 432c01c955a..05a240f868a 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrApi.h +++ b/drivers/staging/prima/CORE/SME/inc/csrApi.h @@ -81,9 +81,6 @@ typedef enum eCSR_AUTH_TYPE_CCKM_WPA, eCSR_AUTH_TYPE_CCKM_RSN, #endif /* FEATURE_WLAN_CCX */ -#ifdef WLAN_FEATURE_11W - eCSR_AUTH_TYPE_RSN_PSK_SHA256, -#endif eCSR_NUM_OF_SUPPORT_AUTH_TYPE, eCSR_AUTH_TYPE_FAILED = 0xff, eCSR_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED, @@ -265,7 +262,9 @@ typedef struct tagCsrStaParams tANI_U8 extn_capability[SIR_MAC_MAX_EXTN_CAP]; tANI_U8 supported_rates_len; tANI_U8 supported_rates[SIR_MAC_MAX_SUPP_RATES]; + tANI_U8 htcap_present; tSirHTCap HTCap; + tANI_U8 vhtcap_present; tSirVHTCap VHTCap; tANI_U8 uapsd_queues; tANI_U8 max_sp; @@ -463,9 +462,6 @@ typedef enum eCSR_ROAM_DISCONNECT_ALL_P2P_CLIENTS, //Disaconnect all the clients eCSR_ROAM_SEND_P2P_STOP_BSS, //Stopbss triggered from SME due to different // beacon interval -#ifdef WLAN_FEATURE_11W - eCSR_ROAM_UNPROT_MGMT_FRAME_IND, -#endif }eRoamCmdStatus; @@ -711,8 +707,7 @@ typedef enum }eCsrWEPStaticKeyID; -// Two extra key indicies are used for the IGTK (which is used by BIP) -#define CSR_MAX_NUM_KEY (eCSR_SECURITY_WEP_STATIC_KEY_ID_MAX + 2 + 1) +#define CSR_MAX_NUM_KEY (eCSR_SECURITY_WEP_STATIC_KEY_ID_MAX + 1) typedef enum { @@ -833,13 +828,6 @@ typedef struct tagCsrRoamProfile //This field is for output only, not for input eCsrEncryptionType negotiatedMCEncryptionType; -#ifdef WLAN_FEATURE_11W - // Management Frame Protection - tANI_BOOLEAN MFPEnabled; - tANI_U8 MFPRequired; - tANI_U8 MFPCapable; -#endif - tCsrKeys Keys; eCsrCBChoice CBMode; //up, down or auto tCsrChannelInfo ChannelInfo; @@ -858,8 +846,13 @@ typedef struct tagCsrRoamProfile tANI_U8 *pWAPIReqIE; //If not null, it has the IE byte stream for WAPI #endif /* FEATURE_WLAN_WAPI */ - tANI_U32 nAddIEScanLength; //The byte count in the pAddIE for scan (at the time of join) - tANI_U8 *pAddIEScan; //If not null, it has the IE byte stream for additional IE, which can be WSC IE and/or P2P IE + //The byte count in the pAddIE for scan (at the time of join) + tANI_U32 nAddIEScanLength; + /* Additional IE information. + * It has the IE byte stream for additional IE, + * which can be WSC IE and/or P2P IE + */ + tANI_U8 addIEScan[SIR_MAC_MAX_IE_LENGTH+2]; //Additional IE information. tANI_U32 nAddIEAssocLength; //The byte count in the pAddIE for assoc tANI_U8 *pAddIEAssoc; //If not null, it has the IE byte stream for additional IE, which can be WSC IE and/or P2P IE @@ -925,6 +918,7 @@ typedef struct tagCsrRoamConnectedProfile tCsrCcxCckmInfo ccxCckmInfo; tANI_BOOLEAN isCCXAssoc; #endif + tANI_U32 dot11Mode; }tCsrRoamConnectedProfile; @@ -1013,14 +1007,17 @@ typedef struct tagCsrConfigParam tANI_U32 nActiveMinChnTimeBtc; //in units of milliseconds tANI_U32 nActiveMaxChnTimeBtc; //in units of milliseconds + tANI_U32 disableAggWithBtc; #ifdef WLAN_AP_STA_CONCURRENCY tANI_U32 nPassiveMinChnTimeConc; //in units of milliseconds tANI_U32 nPassiveMaxChnTimeConc; //in units of milliseconds tANI_U32 nActiveMinChnTimeConc; //in units of milliseconds tANI_U32 nActiveMaxChnTimeConc; //in units of milliseconds tANI_U32 nRestTimeConc; //in units of milliseconds - tANI_U8 nNumChanCombinedConc; //number of channels combined - //in each split scan operation + tANI_U8 nNumStaChanCombinedConc; //number of channels combined for + //STA in each split scan operation + tANI_U8 nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation #endif tANI_BOOLEAN IsIdleScanEnabled; @@ -1041,9 +1038,10 @@ typedef struct tagCsrConfigParam #endif #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - tANI_U8 isFastTransitionEnabled; - tANI_U8 RoamRssiDiff; - tANI_U8 nImmediateRoamRssiDiff; + tANI_U8 isFastTransitionEnabled; + tANI_U8 RoamRssiDiff; + tANI_U8 nImmediateRoamRssiDiff; + tANI_BOOLEAN isWESModeEnabled; #endif #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING @@ -1084,10 +1082,15 @@ typedef struct tagCsrConfigParam */ tANI_BOOLEAN fFirstScanOnly2GChnl; - tANI_BOOLEAN fIgnore_chan165; #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) tANI_BOOLEAN nRoamPrefer5GHz; tANI_BOOLEAN nRoamIntraBand; + tANI_U8 nProbes; + tANI_U16 nRoamScanHomeAwayTime; +#endif + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tANI_BOOLEAN isRoamOffloadScanEnabled; #endif tANI_U8 scanCfgAgingTime; diff --git a/drivers/staging/prima/CORE/SME/inc/csrInternal.h b/drivers/staging/prima/CORE/SME/inc/csrInternal.h old mode 100644 new mode 100755 index 189c1991696..91a8427afd6 --- a/drivers/staging/prima/CORE/SME/inc/csrInternal.h +++ b/drivers/staging/prima/CORE/SME/inc/csrInternal.h @@ -18,6 +18,37 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + + + \file csrInternal.h + + Define internal data structure for MAC. + + Copyright (C) 2006 Airgo Networks, Incorporated + ========================================================================== */ #ifndef CSRINTERNAL_H__ #define CSRINTERNAL_H__ @@ -74,6 +105,13 @@ ) #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CSR_IS_ROAM_SCAN_OFFLOAD_ENABLED( pMac ) \ +( \ + (((pMac)->roam.configParam.isRoamOffloadScanEnabled)?eANI_BOOLEAN_TRUE:eANI_BOOLEAN_FALSE) \ +) +#endif + //Support for "Fast roaming" (i.e., CCX, LFR, or 802.11r.) #define CSR_BG_SCAN_OCCUPIED_CHANNEL_LIST_LEN 15 @@ -135,7 +173,8 @@ typedef enum eCsrScanProbeBss, // directed probe on an entry from the candidate list - HO eCsrScanAbortBgScan, //aborting a BG scan (meaning the scan is triggered by LIM timer) eCsrScanAbortNormalScan, //aborting a normal scan (the scan is trigger by eWNI_SME_SCAN_REQ) - eCsrScanP2PFindPeer + eCsrScanP2PFindPeer, + eCsrScanGetLfrResult, // get the LFR candidates from PE scan cache }eCsrScanReason; typedef enum @@ -422,6 +461,7 @@ typedef struct tagAddStaForSessionCmd { //Session self mac addr tSirMacAddr selfMacAddr; + tVOS_CON_MODE currDeviceMode; }tAddStaForSessionCmd; typedef struct tagDelStaForSessionCmd @@ -535,14 +575,17 @@ typedef struct tagCsrConfig tANI_U32 nActiveMinChnTimeBtc; //in units of milliseconds tANI_U32 nActiveMaxChnTimeBtc; //in units of milliseconds + tANI_U8 disableAggWithBtc; #ifdef WLAN_AP_STA_CONCURRENCY tANI_U32 nPassiveMinChnTimeConc; //in units of milliseconds tANI_U32 nPassiveMaxChnTimeConc; //in units of milliseconds tANI_U32 nActiveMinChnTimeConc; //in units of milliseconds tANI_U32 nActiveMaxChnTimeConc; //in units of milliseconds tANI_U32 nRestTimeConc; //in units of milliseconds - tANI_U8 nNumChanCombinedConc; //number of channels combined - //in each split scan operation + tANI_U8 nNumStaChanCombinedConc; //number of channels combined for + //Sta in each split scan operation + tANI_U8 nNumP2PChanCombinedConc; //number of channels combined for + //P2P in each split scan operation #endif tANI_BOOLEAN IsIdleScanEnabled; @@ -561,6 +604,9 @@ typedef struct tagCsrConfig #ifdef FEATURE_WLAN_LFR tANI_U8 isFastRoamIniFeatureEnabled; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + tANI_U8 isRoamOffloadScanEnabled; +#endif #endif #ifdef FEATURE_WLAN_CCX @@ -572,9 +618,11 @@ typedef struct tagCsrConfig tANI_U8 RoamRssiDiff; tANI_U8 nImmediateRoamRssiDiff; tANI_BOOLEAN nRoamPrefer5GHz; - tANI_BOOLEAN nRoamIntraBand; tANI_BOOLEAN isWESModeEnabled; tANI_BOOLEAN nRoamScanControl; + tANI_BOOLEAN nRoamIntraBand; + tANI_U8 nProbes; + tANI_U16 nRoamScanHomeAwayTime; #endif #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING @@ -667,6 +715,7 @@ typedef struct tagCsrScanStruct tANI_U8 countryCode11d[WNI_CFG_COUNTRY_CODE_LEN]; v_REGDOMAIN_t domainIdDefault; //default regulatory domain v_REGDOMAIN_t domainIdCurrent; //current regulatory domain + tCsrBssid currentCountryBssid; // Bssid for current country code tANI_BOOLEAN f11dInfoApplied; tANI_BOOLEAN fCancelIdleScan; #ifdef FEATURE_WLAN_WAPI @@ -708,8 +757,6 @@ typedef struct tagCsrScanStruct tDblLinkList scanCmdPendingList; #endif tCsrChannel occupiedChannels; //This includes all channels on which candidate APs are found - - tANI_BOOLEAN fIgnore_chan165; }tCsrScanStruct; #ifdef FEATURE_WLAN_TDLS_INTERNAL @@ -836,8 +883,11 @@ typedef struct tagCsrRoamSession tANI_U32 nWapiRspIeLength; //the byte count for pWapiRspIE tANI_U8 *pWapiRspIE; //this contain the WAPI IE in beacon/probe rsp #endif /* FEATURE_WLAN_WAPI */ - tANI_U32 nAddIEScanLength; //the byte count of pAddIeScanIE; - tANI_U8 *pAddIEScan; //this contains the additional IE in (unicast) probe request at the time of join + tANI_U32 nAddIEScanLength; //length of addIeScan + /* This contains the additional IE in (unicast) + * probe request at the time of join + */ + tANI_U8 addIEScan[SIR_MAC_MAX_IE_LENGTH+2]; tANI_U32 nAddIEAssocLength; //the byte count for pAddIeAssocIE tANI_U8 *pAddIEAssoc; //this contains the additional IE in (re) assoc request @@ -1062,10 +1112,6 @@ void csrScanSuspendIMPS( tpAniSirGlobal pMac ); void csrScanResumeIMPS( tpAniSirGlobal pMac ); eHalStatus csrInitGetChannels(tpAniSirGlobal pMac); -// Getting the 5GHz Channel list -eHalStatus csrGet5GChannels(tpAniSirGlobal pMac); -// Getting the 2.4GHz Channel list -eHalStatus csrGet24GChannels(tpAniSirGlobal pMac); eHalStatus csrSetModifyProfileFields(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamModifyProfileFields *pModifyProfileFields); @@ -1271,7 +1317,8 @@ tANI_BOOLEAN csrIsSetKeyAllowed(tpAniSirGlobal pMac, tANI_U32 sessionId); void csrSetOppositeBandChannelInfo( tpAniSirGlobal pMac ); void csrConstructCurrentValidChannelList( tpAniSirGlobal pMac, tDblLinkList *pChannelSetList, tANI_U8 *pChannelList, tANI_U8 bSize, tANI_U8 *pNumChannels ); - +eHalStatus csrScanSavePreferredNetworkFound(tpAniSirGlobal pMac, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd); #endif #ifdef WLAN_FEATURE_VOWIFI_11R @@ -1291,7 +1338,15 @@ void csrDisconnectAllActiveSessions(tpAniSirGlobal pMac); #ifdef FEATURE_WLAN_LFR //Returns whether "Legacy Fast Roaming" is enabled...or not tANI_BOOLEAN csrRoamIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U32 sessionId); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac); +#endif tANI_BOOLEAN csrIsChannelPresentInList( tANI_U8 *pChannelList, int numChannels, tANI_U8 channel ); VOS_STATUS csrAddToChannelListFront( tANI_U8 *pChannelList, int numChannels, tANI_U8 channel ); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId, + csrScanCompleteCallback callback, void *pContext); +#endif +tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId); #endif diff --git a/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h b/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h index dab7fa7cef0..768fd1e0505 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h +++ b/drivers/staging/prima/CORE/SME/inc/csrNeighborRoam.h @@ -245,7 +245,29 @@ VOS_STATUS csrNeighborRoamChannelsFilterByCurrentBand( tANI_U8* pOutputChannelList, int* pMergedOutputNumOfChannels ); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define ROAM_SCAN_OFFLOAD_START 1 +#define ROAM_SCAN_OFFLOAD_STOP 2 +#define ROAM_SCAN_OFFLOAD_RESTART 3 +#define ROAM_SCAN_OFFLOAD_UPDATE_CFG 4 +#define REASON_CONNECT 1 +#define REASON_CHANNEL_LIST_CHANGED 2 +#define REASON_LOOKUP_THRESH_CHANGED 3 +#define REASON_DISCONNECTED 4 +#define REASON_RSSI_DIFF_CHANGED 5 +#define REASON_CCX_INI_CFG_CHANGED 6 +#define REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED 7 +#define REASON_VALID_CHANNEL_LIST_CHANGED 8 +#define REASON_FLUSH_CHANNEL_LIST 9 +#define REASON_EMPTY_SCAN_REF_PERIOD_CHANGED 10 +#define REASON_PREAUTH_FAILED_FOR_ALL 11 +#define REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW 12 +#define REASON_NPROBES_CHANGED 13 +#define REASON_HOME_AWAY_TIME_CHANGED 14 +eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reason); +eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, void* pMsg); +#endif #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ diff --git a/drivers/staging/prima/CORE/SME/inc/csrSupport.h b/drivers/staging/prima/CORE/SME/inc/csrSupport.h index e2a6ba47766..1034298d70a 100644 --- a/drivers/staging/prima/CORE/SME/inc/csrSupport.h +++ b/drivers/staging/prima/CORE/SME/inc/csrSupport.h @@ -40,13 +40,15 @@ */ /** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * + \file csrSupport.h - + Exports and types for the Common Scan and Roaming supporting interfaces. Copyright (C) 2006 Airgo Networks, Incorporated - + ========================================================================== */ #ifndef CSR_SUPPORT_H__ #define CSR_SUPPORT_H__ @@ -591,9 +593,7 @@ typedef __ani_attr_pre_packed struct tagCsrRSNCapabilities tANI_U16 NoPairwise:1; tANI_U16 PTKSAReplayCounter:2; tANI_U16 GTKSAReplayCounter:2; - tANI_U16 MFPRequired:1; - tANI_U16 MFPCapable:1; - tANI_U16 Reserved:8; + tANI_U16 Reserved:10; } __ani_attr_packed tCsrRSNCapabilities; typedef __ani_attr_pre_packed struct tagCsrRSNPMKIe @@ -827,7 +827,7 @@ csrIsconcurrentsessionValid(tpAniSirGlobal pMac,tANI_U32 cursessionId, eHalStatus csrUpdatep2pBeaconInterval(tpAniSirGlobal pMac); //BeaconInterval validation for MCC support -eHalStatus csrValidateMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U8 channelId, +eHalStatus csrValidateMCCBeaconInterval(tpAniSirGlobal pMac, tANI_U8 channelId, tANI_U16 *beaconInterval, tANI_U32 cursessionId, tVOS_CON_MODE currBssPersona); diff --git a/drivers/staging/prima/CORE/SME/inc/smeInside.h b/drivers/staging/prima/CORE/SME/inc/smeInside.h index 86b5f81e24c..1a4ee23da27 100644 --- a/drivers/staging/prima/CORE/SME/inc/smeInside.h +++ b/drivers/staging/prima/CORE/SME/inc/smeInside.h @@ -140,7 +140,9 @@ typedef struct TdlsAddStaInfo tANI_U8 extnCapability[SIR_MAC_MAX_EXTN_CAP]; tANI_U8 supportedRatesLen; tANI_U8 supportedRates[SIR_MAC_MAX_SUPP_RATES]; + tANI_U8 htcap_present; tSirHTCap HTCap; + tANI_U8 vhtcap_present; tSirVHTCap VHTCap; tANI_U8 uapsdQueues; tANI_U8 maxSp; @@ -308,9 +310,10 @@ eHalStatus csrTdlsTeardownReq(tHalHandle hHal, tANI_U8 sessionId, #endif /* FEATURE_WLAN_TDLS */ #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) -eHalStatus csrFlushAndCreateBgScanRoamChannelList(tpAniSirGlobal pMac, - const tANI_U8 *pChannelList, - const tANI_U8 numChannels); +eHalStatus csrFlushBgScanRoamChannelList(tpAniSirGlobal pMac); +eHalStatus csrCreateBgScanRoamChannelList(tpAniSirGlobal pMac, + const tANI_U8 *pChannelList, + const tANI_U8 numChannels); eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, eCsrBand eBand); eHalStatus csrInitCountryValidChannelList(tpAniSirGlobal pMac, tANI_U8 revision); void csr_SetRevision(tpAniSirGlobal pMac, tANI_U8 revision); diff --git a/drivers/staging/prima/CORE/SME/inc/smeInternal.h b/drivers/staging/prima/CORE/SME/inc/smeInternal.h index f37ce4b12b4..cfb7b5db7cf 100644 --- a/drivers/staging/prima/CORE/SME/inc/smeInternal.h +++ b/drivers/staging/prima/CORE/SME/inc/smeInternal.h @@ -155,6 +155,7 @@ typedef struct tagSmeStruct tDblLinkList smeCmdFreeList; //preallocated roam cmd list void (*pTxPerHitCallback) (void *pCallbackContext); /* callback for Tx PER hit to HDD */ void *pTxPerHitCbContext; + tVOS_CON_MODE currDeviceMode; } tSmeStruct, *tpSmeStruct; diff --git a/drivers/staging/prima/CORE/SME/inc/sme_Api.h b/drivers/staging/prima/CORE/SME/inc/sme_Api.h old mode 100644 new mode 100755 index 3233c8d78de..2114b960b84 --- a/drivers/staging/prima/CORE/SME/inc/sme_Api.h +++ b/drivers/staging/prima/CORE/SME/inc/sme_Api.h @@ -92,6 +92,9 @@ #define SME_INVALID_COUNTRY_CODE "XX" +//Macro to disable split scan +#define SME_DISABLE_SPLIT_SCAN 255 + /*-------------------------------------------------------------------------- Type declarations ------------------------------------------------------------------------*/ @@ -111,8 +114,9 @@ typedef struct _smeConfigParams tP2PConfigParam p2pConfig; #endif #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - tANI_U8 isFastTransitionEnabled; - tANI_U8 RoamRssiDiff; + tANI_U8 isFastTransitionEnabled; + tANI_U8 RoamRssiDiff; + tANI_BOOLEAN isWESModeEnabled; #endif } tSmeConfigParams, *tpSmeConfigParams; @@ -221,9 +225,18 @@ eHalStatus sme_Stop(tHalHandle hHal, tANI_BOOLEAN pmcFlag); \sa --------------------------------------------------------------------------*/ -eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, void *pContext, - tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId); +eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, + void *pContext, tANI_U8 *pSelfMacAddr, + tANI_U8 *pbSessionId); +/*-------------------------------------------------------------------------- + + \brief sme_SetCurrDeviceMode() - Sets the current operating device mode. + \param hHal - The handle returned by macOpen. + \param currDeviceMode - Current operating device mode. + --------------------------------------------------------------------------*/ + +void sme_SetCurrDeviceMode (tHalHandle hHal, tVOS_CON_MODE currDeviceMode); /*-------------------------------------------------------------------------- @@ -2260,6 +2273,28 @@ eHalStatus sme_UpdateRoamPrefer5GHz(tHalHandle hHal, v_BOOL_t nRoamPrefer5GHz); -------------------------------------------------------------------------*/ eHalStatus sme_setRoamIntraBand(tHalHandle hHal, const v_BOOL_t nRoamIntraBand); +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanNProbes + \brief function to update roam scan N probes + This function is called through dynamic setConfig callback function + to update roam scan N probes + \param hHal - HAL handle for device + \param nProbes number of probe requests to be sent out + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanNProbes(tHalHandle hHal, const v_U8_t nProbes); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanHomeAwayTime + \brief function to update roam scan Home away time + This function is called through dynamic setConfig callback function + to update roam scan home away time + \param hHal - HAL handle for device + \param nRoamScanAwayTime Scan home away time + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanHomeAwayTime(tHalHandle hHal, const v_U16_t nRoamScanHomeAwayTime); + /* --------------------------------------------------------------------------- \fn sme_getRoamIntraBand \brief get Intra band roaming @@ -2268,6 +2303,22 @@ eHalStatus sme_setRoamIntraBand(tHalHandle hHal, const v_BOOL_t nRoamIntraBand); -------------------------------------------------------------------------*/ v_BOOL_t sme_getRoamIntraBand(tHalHandle hHal); +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanNProbes + \brief get N Probes + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U8_t sme_getRoamScanNProbes(tHalHandle hHal); + +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanHomeAwayTime + \brief get Roam scan home away time + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U16_t sme_getRoamScanHomeAwayTime(tHalHandle hHal); + /* --------------------------------------------------------------------------- \fn sme_UpdateImmediateRoamRssiDiff \brief Update nImmediateRoamRssiDiff @@ -2309,6 +2360,29 @@ eHalStatus sme_UpdateRoamRssiDiff(tHalHandle hHal, v_U8_t RoamRssiDiff); eHalStatus sme_UpdateFastTransitionEnabled(tHalHandle hHal, v_BOOL_t isFastTransitionEnabled); + +/* --------------------------------------------------------------------------- + \fn sme_UpdateWESMode + \brief Update WESMode + This function is called through dynamic setConfig callback function + to configure isWESModeEnabled + \param hHal - HAL handle for device + \param isWESModeEnabled - Enable/Disable WES Mode + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateWESMode(tHalHandle hHal, v_BOOL_t isWESModeEnabled); + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamScanControl + \brief Set roam scan control + This function is called to set roam scan control + if roam scan control is set to 0, roaming scan cache is cleared + any value other than 0 is treated as invalid value + \param hHal - HAL handle for device + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME failure to update + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamScanControl(tHalHandle hHal, v_BOOL_t roamScanControl); #endif /* (WLAN_FEATURE_VOWIFI_11R) || (FEATURE_WLAN_CCX) || (FEATURE_WLAN_LFR) */ #ifdef FEATURE_WLAN_LFR @@ -2563,6 +2637,24 @@ eHalStatus sme_getRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, --------------------------------------------------------------------------*/ eHalStatus sme_GetCountryRevision(tHalHandle hHal, tANI_U8 *pRevision); +/*-------------------------------------------------------------------------- + \brief sme_getWESMode() - getWES Mode + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_U8_t - WES Mode Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetWESMode(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_GetRoamScanControl() - get scan control + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_BOOL_t - Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetRoamScanControl(tHalHandle hHal); + /*-------------------------------------------------------------------------- \brief sme_getIsCcxFeatureEnabled() - get CCX feature enabled or not This is a synchronuous call @@ -2595,6 +2687,22 @@ tANI_BOOLEAN sme_getIsFtFeatureEnabled(tHalHandle hHal); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamScanOffloadEnabled() - enable/disable roam scan offload feaure + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + gRoamScanOffloadEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal, v_BOOL_t nRoamScanOffloadEnabled); +#endif + + /* --------------------------------------------------------------------------- \fn sme_IsFeatureSupportedByFW \brief Check if an feature is enabled by FW @@ -2647,13 +2755,6 @@ VOS_STATUS sme_AddTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr pe \- return VOS_STATUS_SUCCES -------------------------------------------------------------------------*/ VOS_STATUS sme_DeleteTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr peerMac); -/* --------------------------------------------------------------------------- - \fn sme_IsPmcBmps - \brief API to Check if PMC state is BMPS. - - \- return v_BOOL_t - -------------------------------------------------------------------------*/ -v_BOOL_t sme_IsPmcBmps(tHalHandle hHal); /* --------------------------------------------------------------------------- \fn sme_SetTdlsPowerSaveProhibited \API to set/reset the isTdlsPowerSaveProhibited. @@ -2662,6 +2763,14 @@ v_BOOL_t sme_IsPmcBmps(tHalHandle hHal); -------------------------------------------------------------------------*/ void sme_SetTdlsPowerSaveProhibited(tHalHandle hHal, v_BOOL_t val); #endif +/* --------------------------------------------------------------------------- + \fn sme_IsPmcBmps + \brief API to Check if PMC state is BMPS. + + \- return v_BOOL_t + -------------------------------------------------------------------------*/ +v_BOOL_t sme_IsPmcBmps(tHalHandle hHal); + #ifdef FEATURE_WLAN_TDLS_INTERNAL typedef struct smeTdlsDisResult { @@ -2674,7 +2783,61 @@ v_U8_t sme_GetTdlsDiscoveryResult(tHalHandle hHal, tSmeTdlsDisResult *disResult, v_U8_t listType); VOS_STATUS sme_StartTdlsLinkSetupReq(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr peerMac); VOS_STATUS sme_StartTdlsLinkTeardownReq(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr peerMac); - #endif /* FEATURE_WLAN_TDLS */ +eHalStatus sme_UpdateDfsSetting(tHalHandle hHal, tANI_U8 fUpdateEnableDFSChnlScan); + +/* + * SME API to enable/disable WLAN driver initiated SSR + */ +void sme_UpdateEnableSSR(tHalHandle hHal, tANI_BOOLEAN enableSSR); + +/* --------------------------------------------------------------------------- + + \fn sme_SetPhyMode + + \brief Changes the PhyMode. + + \param hHal - The handle returned by macOpen. + \param phyMode new phyMode which is to set + + \return eHalStatus SUCCESS. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetPhyMode(tHalHandle hHal, eCsrPhyMode phyMode); + +/* --------------------------------------------------------------------------- + + \fn sme_GetPhyMode + + \brief gets current PhyMode. + + \param hHal - The handle returned by macOpen. + + \return eHalStatus PhyMode + + -------------------------------------------------------------------------------*/ +eCsrPhyMode sme_GetPhyMode(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_isSta_p2p_clientConnected() - a wrapper function to check if there + is any connected session . + This is a synchronous call + \param hHal - The handle returned by macOpen + \return VOS_STATUS - SME passed the request to CSR successfully. + Other status means SME is failed to send the request. + \sa + --------------------------------------------------------------------------*/ +VOS_STATUS sme_isSta_p2p_clientConnected(tHalHandle hHal); + +/*-------------------------------------------------------------------------- + \brief sme_enable_disable_split_scan() - a wrapper function to set the split + scan parameter. + This is a synchronous call + \param hHal - The handle returned by macOpen + \return None. + \sa + --------------------------------------------------------------------------*/ +void sme_enable_disable_split_scan (tHalHandle hHal, tANI_U8 nNumStaChan, + tANI_U8 nNumP2PChan); #endif //#if !defined( __SME_API_H ) diff --git a/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h b/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h index 115f3f9f0b7..98a0e237b9b 100644 --- a/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h +++ b/drivers/staging/prima/CORE/SME/inc/sme_FTApi.h @@ -39,6 +39,8 @@ * PERFORMANCE OF THIS SOFTWARE. */ + + #if !defined( __SME_FTAPI_H ) #define __SME_FTAPI_H @@ -82,9 +84,12 @@ typedef struct sFTSMEContext // Saved pFTPreAuthRsp tpSirFTPreAuthRsp psavedFTPreAuthRsp; + v_BOOL_t setFTPreAuthState; + v_BOOL_t setFTPTKState; // Time to trigger reassoc once pre-auth is successful tPalTimerHandle preAuthReassocIntvlTimer; + tCsrRoamSetKey *pCsrFTKeyInfo; } tftSMEContext, *tpftSMEContext; @@ -99,6 +104,10 @@ void csrFTPreAuthRspProcessor( tHalHandle hHal, tpSirFTPreAuthRsp pFTPreAuthRsp void sme_GetFTPreAuthResponse( tHalHandle hHal, tANI_U8 *ft_ies, tANI_U32 ft_ies_ip_len, tANI_U16 *ft_ies_length ); void sme_GetRICIEs( tHalHandle hHal, tANI_U8 *ric_ies, tANI_U32 ric_ies_ip_len, tANI_U32 *ric_ies_length ); void sme_PreauthReassocIntvlTimerCallback(void *context); +void sme_SetFTPreAuthState(tHalHandle hHal, v_BOOL_t state); +v_BOOL_t sme_GetFTPreAuthState(tHalHandle hHal); +v_BOOL_t sme_GetFTPTKState(tHalHandle hHal); +void sme_SetFTPTKState(tHalHandle hHal, v_BOOL_t state); #endif //#if !defined( __SME_FTAPI_H ) diff --git a/drivers/staging/prima/CORE/SME/src/QoS/sme_Qos.c b/drivers/staging/prima/CORE/SME/src/QoS/sme_Qos.c index bff6a5e559d..21bb864f43e 100644 --- a/drivers/staging/prima/CORE/SME/src/QoS/sme_Qos.c +++ b/drivers/staging/prima/CORE/SME/src/QoS/sme_Qos.c @@ -2766,7 +2766,7 @@ sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac, VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: %d: Session %d has an Invalid BSS Descriptor", __func__, __LINE__, - sessionId, ac); + sessionId); return status; } hstatus = csrGetParsedBssDescriptionIEs(pMac, @@ -2777,7 +2777,7 @@ sme_QosStatusType sme_QosSetup(tpAniSirGlobal pMac, VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: %d: On session %d unable to parse BSS IEs", __func__, __LINE__, - sessionId, ac); + sessionId); return status; } @@ -3598,7 +3598,7 @@ eHalStatus sme_QosProcessAggrQosRsp(tpAniSirGlobal pMac, void *pMsgBuf) addtsRsp.rsp.tspec = pAggrRsp->aggrInfo.aggrRsp[i].tspec; VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - FL("%s: Processing Addts rsp from LIM AC=%d, flow=%d"), i, j); + FL("Processing Addts rsp from LIM AC=%d, flow=%d"), i, j); /* post ADD TS response for each */ if (sme_QosProcessAddTsRsp(pMac, &addtsRsp) != eHAL_STATUS_SUCCESS) { @@ -3807,6 +3807,7 @@ eHalStatus sme_QosAddTsReq(tpAniSirGlobal pMac, VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: %d: BSS descriptor is NULL so we don't send request to PE", __func__, __LINE__); + vos_mem_free(pMsg); return eHAL_STATUS_FAILURE; } vos_mem_copy( &pMsg->bssId[ 0 ], @@ -4412,15 +4413,19 @@ eHalStatus sme_QosProcessReassocSuccessEv(tpAniSirGlobal pMac, v_U8_t sessionId, #ifdef WLAN_FEATURE_VOWIFI_11R if (pSession->ftHandoffInProgress) { - if (csrRoamIs11rAssoc(pMac)) { - if (pCsrRoamSession->connectedInfo.nRICRspLength) { + if (csrRoamIs11rAssoc(pMac)) + { + if (pCsrRoamSession && pCsrRoamSession->connectedInfo.nRICRspLength) + { status = sme_QosProcessFTReassocRspEv(pMac, sessionId, pEvent_info); } } #ifdef FEATURE_WLAN_CCX // If CCX association check for TSPEC IEs in the reassoc rsp frame - if (csrRoamIsCCXAssoc(pMac)) { - if (pCsrRoamSession->connectedInfo.nTspecIeLength) { + if (csrRoamIsCCXAssoc(pMac)) + { + if (pCsrRoamSession && pCsrRoamSession->connectedInfo.nTspecIeLength) + { status = sme_QosCCXProcessReassocTspecRsp(pMac, sessionId, pEvent_info); } } diff --git a/drivers/staging/prima/CORE/SME/src/btc/btcApi.c b/drivers/staging/prima/CORE/SME/src/btc/btcApi.c index 4dce802c381..453508826c2 100644 --- a/drivers/staging/prima/CORE/SME/src/btc/btcApi.c +++ b/drivers/staging/prima/CORE/SME/src/btc/btcApi.c @@ -820,14 +820,24 @@ static VOS_STATUS btcDeferAclCreate( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) else { //There is history on this BD address - VOS_ASSERT(pAclEventHist->bNextEventIdx > 0); + if ((pAclEventHist->bNextEventIdx <= 0) || + (pAclEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_ACL_DEFERRED)) + { + VOS_ASSERT(0); + status = VOS_STATUS_E_FAILURE; + break; + } + pAclEvent = &pAclEventHist->btAclConnection[pAclEventHist->bNextEventIdx - 1]; if(BT_EVENT_CREATE_ACL_CONNECTION == pAclEventHist->btEventType[pAclEventHist->bNextEventIdx - 1]) { //The last cached event is creation, replace it with the new one - vos_mem_copy(pAclEvent, - &pEvent->uEventParam.btAclConnection, - sizeof(tSmeBtAclConnectionParam)); + if (pAclEvent) + { + vos_mem_copy(pAclEvent, + &pEvent->uEventParam.btAclConnection, + sizeof(tSmeBtAclConnectionParam)); + } //done break; } @@ -978,15 +988,23 @@ static VOS_STATUS btcDeferSyncCreate( tpAniSirGlobal pMac, tpSmeBtEvent pEvent ) else { //There is history on this BD address - VOS_ASSERT(pSyncEventHist->bNextEventIdx > 0); + if ((pSyncEventHist->bNextEventIdx <= 0) || + (pSyncEventHist->bNextEventIdx > BT_MAX_NUM_EVENT_SCO_DEFERRED)) + { + VOS_ASSERT(0); + return VOS_STATUS_E_FAILURE; + } pSyncEvent = &pSyncEventHist->btSyncConnection[pSyncEventHist->bNextEventIdx - 1]; if(BT_EVENT_CREATE_SYNC_CONNECTION == pSyncEventHist->btEventType[pSyncEventHist->bNextEventIdx - 1]) { //The last cached event is creation, replace it with the new one - vos_mem_copy(pSyncEvent, - &pEvent->uEventParam.btSyncConnection, - sizeof(tSmeBtSyncConnectionParam)); + if(pSyncEvent) + { + vos_mem_copy(pSyncEvent, + &pEvent->uEventParam.btSyncConnection, + sizeof(tSmeBtSyncConnectionParam)); + } //done break; } @@ -1924,6 +1942,28 @@ eHalStatus btcHandleCoexInd(tHalHandle hHal, void* pMsg) smsLog(pMac, LOGW, "Coex indication in %s(), type - SIR_COEX_IND_TYPE_SCAN_NOT_COMPROMISED", __func__); } + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4) + { + if (pMac->roam.configParam.disableAggWithBtc) + { + ccmCfgSetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, 1, + NULL, eANI_BOOLEAN_FALSE); + smsLog(pMac, LOGW, + "Coex indication in %s(), type - SIR_COEX_IND_TYPE_DISABLE_AGGREGATION_IN_2p4", + __func__); + } + } + else if (pSmeCoexInd->coexIndType == SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4) + { + if (pMac->roam.configParam.disableAggWithBtc) + { + ccmCfgSetInt(pMac, WNI_CFG_DEL_ALL_RX_BA_SESSIONS_2_4_G_BTC, 0, + NULL, eANI_BOOLEAN_FALSE); + smsLog(pMac, LOGW, + "Coex indication in %s(), type - SIR_COEX_IND_TYPE_ENABLE_AGGREGATION_IN_2p4", + __func__); + } + } // unknown indication type else { diff --git a/drivers/staging/prima/CORE/SME/src/ccm/ccmApi.c b/drivers/staging/prima/CORE/SME/src/ccm/ccmApi.c index 92532182ddf..fbd891a109c 100644 --- a/drivers/staging/prima/CORE/SME/src/ccm/ccmApi.c +++ b/drivers/staging/prima/CORE/SME/src/ccm/ccmApi.c @@ -542,8 +542,8 @@ void ccmCfgCnfMsgHandler(tHalHandle hHal, void *m) { freeCfgReq(hHdd, old) ; } + pMac->ccm.comp[cfgId] = req ; } - pMac->ccm.comp[cfgId] = req ; } else { @@ -839,303 +839,3 @@ eHalStatus ccmCfgUpdate(tHalHandle hHal, tCcmCfgSetCallback callback) return status ; } -#if 0 -/////////////////////////////////////////////////////////////////// -#include -#include -extern struct net_device * hdd_dev[]; - -typedef struct pal_netdev_priv_s -{ - // pointer to the PCI device structure for this device - struct pci_dev *pci_dev; - - // TAURUS has three BAR registers - - // BAR0 is a fixed window for the PIF registers - volatile void *win0_addr; - tANI_U32 win0_size; - - // BAR1 is a movable window for all other registers - volatile void *win1_addr; - tANI_U32 win1_size; - tANI_U32 win1_current; - - // BAR2 is a movable window for all other memory - volatile void *win2_addr; - tANI_U32 win2_size; - tANI_U32 win2_current; - - -} pal_netdev_priv_t; - -typedef struct hdd_stats_s { - /* Stats on the MAC SW messages sent to applications */ - ulong stats_mac_rx_mbx_tot_cnt; - ulong stats_mac_rx_mbx_success_cnt; - ulong stats_mac_rx_mbx_drop_cnt; - - /* Stats on messages sent to the MAC SW messages from applications */ - ulong stats_mac_tx_mbx_tot_cnt; - ulong stats_mac_tx_mbx_success_cnt; - ulong stats_mac_tx_mbx_drop_cnt; -} hdd_stats_t; - -/* HDD Driver Private Data structure */ -typedef struct hdd_netdev_priv_s -{ - tANI_U32 magic_head; - - // chipset-specific private data - pal_netdev_priv_t ANI_CHIPSET; - - tHalHandle halHandle; - -#ifdef ANI_BUS_TYPE_PCI - struct pci_dev *pci_dev; - struct pci_device_id * pPciDevId; -#endif // ANI_BUS_TYPE_PCI - - // Queued EAPOL frame destination. - tANI_U32 eapol_pid; - - unsigned int num_xmit; - - /* - * Various frequently used variables that pertain to this - * instance of the driver - */ - tANI_U32 rx_buf_sz; /* Based on MTU+extra headroom needed.*/ - tANI_U32 td_enqueue_nested; - - /* - * Flag set by MAC SW to indicate a TD ring is desired - */ - int td_flush; - - int selectiveFlush; - - spinlock_t lock; - - /* Stats */ - struct net_device_stats stats; - int curr_acc_cat; - tANI_U16 lport; /* switch logical port */ - - /* management and control */ - tANI_U32 status; - tANI_U32 msg_enable; - tANI_U32 radio_id; /* Unit # of this device */ - - int ap_flag; /* - * indicates if the Radio is in AP - * or BP mode. - */ - - /* NAPI Polling suport */ - struct timer_list oom_timer; /* Out of memory timer. */ - - struct timer_list reset_req_timer;/* - * Timer started when a Reset - * request is sent to WSM. Cleared - * when a subsequent Radio Disable - * Request is received. - */ - - struct tasklet_struct *rx_tasklet; - struct tasklet_struct *tx_tasklet; - - tANI_U32 learn_mode_frame_cnt; /* - * Data Frames forwarded to MAC SW - * when Polaris is in learn mode - */ - - tANI_U32 mgmt_ctl_frames; /* MGMT/CTL Frames forwarded to MAC SW */ - - tANI_U32 nir; /* total number of times the ISR has - * been invoked.*/ - tANI_U32 stats_dummy_pkt_requeue_cnt; - tANI_U32 stats_rx_td_dummy_pkt_cnt;/* TD Dummy pkts that were after HIF loopback */ - tANI_U32 stats_rx_tm_dummy_pkt_cnt;/* TM Dummy pkts that were after HIF loopback */ - tANI_U32 stats_td_dummy_pkt_cnt; /* Dummy pkts that were succesfully - * put on the TD ring and that - * were picked up by the HIF - */ - - tANI_U32 stats_mac_dummy_pkt_drop_cnt;/* Number of dummy pkts dropped by the HDD - * due to any reason - */ - tANI_U32 stats_wns_l2update_cnt; - tANI_U32 stats_app_hif_wr_pkt_cnt; - hdd_stats_t hdd_stats; - - tANI_U32 stats_reset_req_timer_cnt; /* - * Number of times the - * Reset Req Timer expired - */ - -#ifdef TCP_PROFILE - unsigned int pv_current_ip_proto; - unsigned int pv_current_ip_byte; - unsigned int pv_current_ack_seq; - unsigned int pv_current_seq; - unsigned int pv_rtt; - unsigned int pv_sent_seq; - unsigned int pv_p_ts; - unsigned int pv_tfpl_ts; -#endif - tANI_U32 stats_mac_reset_cnt; /* MAC SW Reset Requests */ - tANI_U32 stats_mac_reset_eof_sof; - tANI_U32 stats_mac_reset_bmu; - tANI_U32 stats_mac_reset_pdu_low; - tANI_U32 stats_mac_reset_user; - tANI_U32 stats_mac_reset_wd_timeout; - tANI_U32 stats_mac_reset_unspecified; - - tANI_U32 stats_wd_timeout_cnt; - tANI_U32 stats_radio_enable_cnt; - tANI_U32 stats_radio_disable_cnt; - -#ifdef PLM_EXTRA_STATS - tANI_U32 stats_tx_xmit_refilled; /* Pkts xmit-filled */ - tANI_U32 stats_tx_queue_stop; - tANI_U32 stats_tx_queue_start; - - tANI_U32 stats_alloc_fail; - tANI_U32 stats_poll_starts; - tANI_U32 stats_poll_pkts; - tANI_U32 stats_poll_exit_done; - tANI_U32 stats_poll_exit_not_done; - tANI_U32 stats_poll_exit_oom; - tANI_U32 stats_poll_exit_done_rx_pending; - tANI_U32 stats_poll_zero_rx; - -#ifdef CONFIG_PROC_FS -#ifdef ANI_USE_TASKLET - struct proc_dir_entry *proc_driver_dir; // for /proc/net/drivers -#endif - struct proc_dir_entry *proc_ent_dir; // for the directory itself - - struct proc_dir_entry *proc_ent_stats; - struct proc_dir_entry *proc_ent_np_dump; - struct proc_dir_entry *proc_ent_ring; - char proc_fname_stats[32]; - char proc_fname_np_dump[32]; - char proc_fname_ring[32]; - - /* Setting Debug levels */ - struct proc_dir_entry * proc_ent_dbg; - char proc_fname_dbg[32]; - - /* For bypass flags */ - struct proc_dir_entry * proc_ent_bypass; - char proc_fname_bypass[32]; - - int sir_dump_cmd; // Dump SIR command - int sir_dump_arg1; // Dump SIR argument 1 - int sir_dump_arg2; // Dump SIR argument 2 - int sir_dump_arg3; // Dump SIR argument 3 - int sir_dump_arg4; // Dump SIR argument 4 - struct proc_dir_entry * proc_ent_sir_dump; - char proc_fname_sir_dump[32]; - - eHalStatus status ; - struct proc_dir_entry * proc_ent_eeprom_info; - char proc_fname_eeprom_info[32]; - -#endif /* ifdef CONFIG_PROC_FS */ - - tANI_U32 rx_small_skb_failure; - - unsigned long open_time; /* jiffies for last open */ -#endif /* PLM_EXTRA_STATS */ - - int mac_down; - tANI_U32 rx_mac_msg_cnt; - tANI_U32 tx_mac_msg_cnt; - - int mbx_sent; - - tANI_U32 bypass; // Used to various types of bypasses - // in the driver - - /* - * this table is initialized once for all by poldrv and so is not in - * mac_param struct - */ - t_mac_block_table * mac_block_table; - struct sk_buff_head mac_list; - tANI_U32 magic_tail; -} hdd_netdev_priv_t; - -static void ccm_callback(tHalHandle hHal, tANI_S32 cfgId) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - smsLog(pMac, LOGW, FL("cfgId = %d"), cfgId); -} - -static void ccm_callback2(tHalHandle hHal, tANI_S32 result) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - smsLog(pMac, LOGW, FL("result = %d"), result); -} - -void ccm_test(void) -{ - tHalHandle hHal ; - tpAniSirGlobal pMac; - eHalStatus status ; - struct net_device *dev; - hdd_netdev_priv_t *np; - char str[80] = {1} ; - - dev = hdd_dev[0]; - np = (hdd_netdev_priv_t *)dev->priv; - hHal = np->halHandle ; - pMac = PMAC_STRUCT( hHal ); - - smsLog(pMac, LOGW, "ccmStart()"); - ccmStart(hHal) ; - - status = ccmCfgUpdate(hHal, ccm_callback2) ; - smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d", status); - - status = ccmCfgSetInt(hHal, WNI_CFG_FRAGMENTATION_THRESHOLD, 100, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_FRAGMENTATION_THRESHOLD = %d): status=%d", - WNI_CFG_FRAGMENTATION_THRESHOLD, status); - - status = ccmCfgSetInt(hHal, WNI_CFG_RTS_THRESHOLD, 100, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_RTS_THRESHOLD = %d): status=%d", - WNI_CFG_RTS_THRESHOLD, status); - - /* this cfgid causes reload */ - status = ccmCfgSetInt(hHal, WNI_CFG_MIMO_ENABLED, 1, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_MIMO_ENABLED = %d): status=%d", - WNI_CFG_MIMO_ENABLED, status); - - status = ccmCfgSetInt(hHal, WNI_CFG_SHORT_RETRY_LIMIT, 100, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_SHORT_RETRY_LIMIT = %d): status=%d", - WNI_CFG_SHORT_RETRY_LIMIT, status); - - status = ccmCfgSetInt(hHal, WNI_CFG_LONG_RETRY_LIMIT, 100, ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetInt(WNI_CFG_LONG_RETRY_LIMIT = %d): status=%d", - WNI_CFG_LONG_RETRY_LIMIT, status); - - /* this cfgid causes restart */ - status = ccmCfgSetStr(hHal, WNI_CFG_EDCA_WME_ACVI, str, sizeof(str), ccm_callback, 1) ; - smsLog(pMac, LOGW, "ccmCfgSetStr(WNI_CFG_EDCA_WME_ACVI = %d): status=%d", - WNI_CFG_EDCA_WME_ACVI, status); - - mdelay(100); - - smsLog(pMac, LOGW, "ccmStop()"); - ccmStop(hHal); - status = ccmCfgUpdate(hHal, ccm_callback2) ; - smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d", status); - - smsLog(pMac, LOGW, "ccmStart()"); - ccmStart(hHal) ; - status = ccmCfgUpdate(hHal, ccm_callback2) ; - smsLog(pMac, LOGW, "ccmCfgUpdate(): status=%d", status); -} -#endif diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c index 45b72b9f4ae..2f8d75a9e3d 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrApiRoam.c @@ -150,9 +150,6 @@ int diagAuthTypeFromCSRType(eCsrAuthType authType) n = AUTH_WPA2_EAP; break; case eCSR_AUTH_TYPE_RSN_PSK: -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif n = AUTH_WPA2_PSK; break; #ifdef FEATURE_WLAN_WAPI @@ -945,13 +942,15 @@ static void initConfigParam(tpAniSirGlobal pMac) pMac->roam.configParam.nPassiveMinChnTime = CSR_PASSIVE_MIN_CHANNEL_TIME; pMac->roam.configParam.nActiveMaxChnTimeBtc = CSR_ACTIVE_MAX_CHANNEL_TIME_BTC; pMac->roam.configParam.nActiveMinChnTimeBtc = CSR_ACTIVE_MIN_CHANNEL_TIME_BTC; + pMac->roam.configParam.disableAggWithBtc = eANI_BOOLEAN_TRUE; #ifdef WLAN_AP_STA_CONCURRENCY pMac->roam.configParam.nActiveMaxChnTimeConc = CSR_ACTIVE_MAX_CHANNEL_TIME_CONC; pMac->roam.configParam.nActiveMinChnTimeConc = CSR_ACTIVE_MIN_CHANNEL_TIME_CONC; pMac->roam.configParam.nPassiveMaxChnTimeConc = CSR_PASSIVE_MAX_CHANNEL_TIME_CONC; pMac->roam.configParam.nPassiveMinChnTimeConc = CSR_PASSIVE_MIN_CHANNEL_TIME_CONC; pMac->roam.configParam.nRestTimeConc = CSR_REST_TIME_CONC; - pMac->roam.configParam.nNumChanCombinedConc = CSR_NUM_CHAN_COMBINED_CONC; + pMac->roam.configParam.nNumStaChanCombinedConc = CSR_NUM_STA_CHAN_COMBINED_CONC; + pMac->roam.configParam.nNumP2PChanCombinedConc = CSR_NUM_P2P_CHAN_COMBINED_CONC; #endif pMac->roam.configParam.IsIdleScanEnabled = TRUE; //enable the idle scan by default pMac->roam.configParam.nTxPowerCap = CSR_MAX_TX_POWER; @@ -1030,12 +1029,9 @@ void csr_SetRevision(tpAniSirGlobal pMac, tANI_U8 revision) } /* - This function flushes the roam scan cache and creates fresh cache - based on the input channel list + This function flushes the roam scan cache */ -eHalStatus csrFlushAndCreateBgScanRoamChannelList(tpAniSirGlobal pMac, - const tANI_U8 *pChannelList, - const tANI_U8 numChannels) +eHalStatus csrFlushBgScanRoamChannelList(tpAniSirGlobal pMac) { eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; @@ -1045,7 +1041,24 @@ eHalStatus csrFlushAndCreateBgScanRoamChannelList(tpAniSirGlobal pMac, { vos_mem_free(pNeighborRoamInfo->cfgParams.channelInfo.ChannelList); pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = NULL; + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = 0; } + return status; +} + + + +/* + This function flushes the roam scan cache and creates fresh cache + based on the input channel list +*/ +eHalStatus csrCreateBgScanRoamChannelList(tpAniSirGlobal pMac, + const tANI_U8 *pChannelList, + const tANI_U8 numChannels) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; + pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels = numChannels; pNeighborRoamInfo->cfgParams.channelInfo.ChannelList = @@ -1103,7 +1116,8 @@ eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, ChannelList[outNumChannels++] = inPtr[i]; } } - csrFlushAndCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); + csrFlushBgScanRoamChannelList(pMac); + csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); } else if (eCSR_BAND_5G == eBand) { @@ -1117,7 +1131,8 @@ eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, ChannelList[outNumChannels++] = inPtr[i]; } } - csrFlushAndCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); + csrFlushBgScanRoamChannelList(pMac); + csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); } else if (eCSR_BAND_ALL == eBand) { @@ -1129,7 +1144,8 @@ eHalStatus csrUpdateBgScanConfigIniChannelList(tpAniSirGlobal pMac, ChannelList[outNumChannels++] = inPtr[i]; } } - csrFlushAndCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); + csrFlushBgScanRoamChannelList(pMac); + csrCreateBgScanRoamChannelList(pMac, ChannelList, outNumChannels); } else { @@ -1149,7 +1165,7 @@ eHalStatus csrInitCountryValidChannelList(tpAniSirGlobal pMac, { eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; - tANI_U8 *pOutChannelList = pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.ChannelList; + tANI_U8 **pOutChannelList = &pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.ChannelList; tANI_U8 *pNumChannels = &pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.numOfChannels; const tANI_U8 *pChannelList = NULL; @@ -1171,24 +1187,19 @@ eHalStatus csrInitCountryValidChannelList(tpAniSirGlobal pMac, else return eHAL_STATUS_INVALID_PARAMETER; - /* Free up the memory first */ - if (NULL != pOutChannelList) - { - vos_mem_free(pOutChannelList); - pOutChannelList = NULL; - } + /* Free any existing channel list */ + vos_mem_free(*pOutChannelList); - pOutChannelList = vos_mem_malloc(*pNumChannels); + *pOutChannelList = vos_mem_malloc(*pNumChannels); - if (NULL == pOutChannelList) + if (NULL == *pOutChannelList) { smsLog(pMac, LOGE, FL("Memory Allocation for CFG Channel List failed")); *pNumChannels = 0; return eHAL_STATUS_RESOURCES; } - /* Update the roam global structure */ - palCopyMemory(pMac->hHdd, pOutChannelList, pChannelList, *pNumChannels); + palCopyMemory(pMac->hHdd, *pOutChannelList, pChannelList, *pNumChannels); return status; } @@ -1389,6 +1400,7 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa pMac->roam.configParam.bandCapability = pParam->bandCapability; pMac->roam.configParam.cbChoice = pParam->cbChoice; pMac->roam.configParam.bgScanInterval = pParam->bgScanInterval; + pMac->roam.configParam.disableAggWithBtc = pParam->disableAggWithBtc; //if HDD passed down non zero values then only update, //otherwise keep using the defaults if (pParam->nActiveMaxChnTime) @@ -1436,9 +1448,13 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa { pMac->roam.configParam.nRestTimeConc = pParam->nRestTimeConc; } - if (pParam->nNumChanCombinedConc) + if (pParam->nNumStaChanCombinedConc) { - pMac->roam.configParam.nNumChanCombinedConc = pParam->nNumChanCombinedConc; + pMac->roam.configParam.nNumStaChanCombinedConc = pParam->nNumStaChanCombinedConc; + } + if (pParam->nNumP2PChanCombinedConc) + { + pMac->roam.configParam.nNumP2PChanCombinedConc = pParam->nNumP2PChanCombinedConc; } #endif //if upper layer wants to disable idle scan altogether set it to 0 @@ -1515,7 +1531,7 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa } -#ifdef WLAN_FEATURE_VOWIFI_11R +#ifdef WLAN_FEATURE_VOWIFI_11R palCopyMemory( pMac->hHdd, &pMac->roam.configParam.csr11rConfig, &pParam->csr11rConfig, sizeof(tCsr11rConfigParams) ); smsLog( pMac, LOG1, "IsFTResourceReqSupp = %d", pMac->roam.configParam.csr11rConfig.IsFTResourceReqSupported); #endif @@ -1526,13 +1542,19 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa smsLog( pMac, LOG1, "nImmediateRoamRssiDiff = %d", pMac->roam.configParam.nImmediateRoamRssiDiff ); pMac->roam.configParam.nRoamPrefer5GHz = pParam->nRoamPrefer5GHz; + pMac->roam.configParam.isWESModeEnabled = pParam->isWESModeEnabled; pMac->roam.configParam.nRoamIntraBand = pParam->nRoamIntraBand; + pMac->roam.configParam.nProbes = pParam->nProbes; + pMac->roam.configParam.nRoamScanHomeAwayTime = pParam->nRoamScanHomeAwayTime; #endif -#ifdef FEATURE_WLAN_LFR +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pMac->roam.configParam.isRoamOffloadScanEnabled = pParam->isRoamOffloadScanEnabled; +#endif +#ifdef FEATURE_WLAN_LFR pMac->roam.configParam.isFastRoamIniFeatureEnabled = pParam->isFastRoamIniFeatureEnabled; #endif -#ifdef FEATURE_WLAN_CCX +#ifdef FEATURE_WLAN_CCX pMac->roam.configParam.isCcxIniFeatureEnabled = pParam->isCcxIniFeatureEnabled; #endif #ifdef WLAN_FEATURE_NEIGHBOR_ROAMING @@ -1577,7 +1599,6 @@ eHalStatus csrChangeDefaultConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pPa pMac->roam.configParam.txBFEnable= pParam->enableTxBF; pMac->roam.configParam.txBFCsnValue = pParam->txBFCsnValue; #endif - pMac->scan.fIgnore_chan165 = pParam->fIgnore_chan165; pMac->roam.configParam.txLdpcEnable = pParam->enableTxLdpc; } @@ -1613,13 +1634,17 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->nActiveMinChnTime = pMac->roam.configParam.nActiveMinChnTime; pParam->nPassiveMaxChnTime = pMac->roam.configParam.nPassiveMaxChnTime; pParam->nPassiveMinChnTime = pMac->roam.configParam.nPassiveMinChnTime; + pParam->nActiveMaxChnTimeBtc = pMac->roam.configParam.nActiveMaxChnTimeBtc; + pParam->nActiveMinChnTimeBtc = pMac->roam.configParam.nActiveMinChnTimeBtc; + pParam->disableAggWithBtc = pMac->roam.configParam.disableAggWithBtc; #ifdef WLAN_AP_STA_CONCURRENCY pParam->nActiveMaxChnTimeConc = pMac->roam.configParam.nActiveMaxChnTimeConc; pParam->nActiveMinChnTimeConc = pMac->roam.configParam.nActiveMinChnTimeConc; pParam->nPassiveMaxChnTimeConc = pMac->roam.configParam.nPassiveMaxChnTimeConc; pParam->nPassiveMinChnTimeConc = pMac->roam.configParam.nPassiveMinChnTimeConc; pParam->nRestTimeConc = pMac->roam.configParam.nRestTimeConc; - pParam->nNumChanCombinedConc = pMac->roam.configParam.nNumChanCombinedConc; + pParam->nNumStaChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + pParam->nNumP2PChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; #endif //Change the unit from microsecond to second pParam->impsSleepTime = pMac->roam.configParam.impsSleepTime / PAL_TIMER_TO_SEC_UNIT; @@ -1645,7 +1670,6 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->fValidateList = pMac->roam.configParam.fValidateList; pParam->fEnableBypass11d = pMac->scan.fEnableBypass11d; pParam->fEnableDFSChnlScan = pMac->scan.fEnableDFSChnlScan; - pParam->fIgnore_chan165= pMac->scan.fIgnore_chan165; pParam->fScanTwice = pMac->roam.configParam.fScanTwice; pParam->fFirstScanOnly2GChnl = pMac->scan.fFirstScanOnly2GChnl; pParam->fEnableMCCMode = pMac->roam.configParam.fenableMCCMode; @@ -1660,7 +1684,7 @@ eHalStatus csrGetConfigParam(tpAniSirGlobal pMac, tCsrConfigParam *pParam) pParam->enableTxBF = pMac->roam.configParam.txBFEnable; pParam->txBFCsnValue = pMac->roam.configParam.txBFCsnValue; #endif - + pParam->enableTxLdpc = pMac->roam.configParam.txLdpcEnable; csrSetChannels(pMac, pParam); status = eHAL_STATUS_SUCCESS; @@ -1878,115 +1902,6 @@ eHalStatus csrIsValidChannel(tpAniSirGlobal pMac, tANI_U8 chnNum) return status; } -eHalStatus csrGet5GChannels(tpAniSirGlobal pMac) -{ - eHalStatus status = eHAL_STATUS_SUCCESS; - tANI_U8 num20MHzChannelsFound = 0; - VOS_STATUS vosStatus; - tANI_U8 num40MHzChannelsFound = 0; - tANI_U8 Index = 0; - tANI_U8 channelList = 0; - - // Updating the defaultpower Table for changed Domain Id - vosStatus = vos_nv_getChannelListWithPower( pMac->scan.defaultPowerTable, &num20MHzChannelsFound, - pMac->scan.defaultPowerTable40MHz, &num40MHzChannelsFound); - - if ( (VOS_STATUS_SUCCESS != vosStatus) || (num20MHzChannelsFound == 0) ) - { - smsLog( pMac, LOGE, FL("failed to get channels")); - status = eHAL_STATUS_FAILURE; - } - else - { - if ( num20MHzChannelsFound > WNI_CFG_VALID_CHANNEL_LIST_LEN ) - { - num20MHzChannelsFound = WNI_CFG_VALID_CHANNEL_LIST_LEN; - } - - // Move the only 5GHZ channel list to the global data, - // As 2.4GHZ list coming from the AP for the changed domain - // structure -- this will be used as the scan list - for(channelList = 0; channelList < WNI_CFG_VALID_CHANNEL_LIST_LEN; channelList++) - { - // If Channel is 5GHz just break the for loop - if(!(pMac->scan.base20MHzChannels.channelList[ channelList ] > 0 && pMac->scan.base20MHzChannels.channelList[ channelList ] <= 14)) - break; - } - // Update the 5G channels from nv.bin - for ( Index = 0; Index < num20MHzChannelsFound; Index++) - { - if(pMac->scan.defaultPowerTable[Index].chanId >= 36 && pMac->scan.defaultPowerTable[Index].chanId <= 165) - { - pMac->scan.base20MHzChannels.channelList[ channelList ] = pMac->scan.defaultPowerTable[Index].chanId; - channelList++; - } - } - - pMac->scan.numChannelsDefault = (num20MHzChannelsFound > channelList) ? num20MHzChannelsFound : channelList; - pMac->scan.base20MHzChannels.numChannels = (num20MHzChannelsFound > channelList) ? num20MHzChannelsFound : channelList; - // Filling the remaining index as Zero Just for causion - for(Index = pMac->scan.base20MHzChannels.numChannels; Index < WNI_CFG_VALID_CHANNEL_LIST_LEN; Index++) - pMac->scan.base20MHzChannels.channelList[ Index ] = 0; - } - return status; -} - -eHalStatus csrGet24GChannels(tpAniSirGlobal pMac) -{ - eHalStatus status = eHAL_STATUS_SUCCESS; - tANI_U8 num20MHzChannelsFound = 0; - VOS_STATUS vosStatus; - tANI_U8 Index = 0; - tANI_U8 num40MHzChannelsFound = 0; - tANI_U8 channelList5GBackup[WNI_CFG_VALID_CHANNEL_LIST_LEN] = {0}, nuum5GchannelListBackup; - tANI_U8 channelList = 0; - - // Read the scan channel list (including the power limit) from EEPROM - vosStatus = vos_nv_getChannelListWithPower( pMac->scan.defaultPowerTable, &num20MHzChannelsFound, - pMac->scan.defaultPowerTable40MHz, &num40MHzChannelsFound); - - if ( (VOS_STATUS_SUCCESS != vosStatus) || (num20MHzChannelsFound == 0) ) - { - smsLog( pMac, LOGE, FL("failed to get channels \n")); - status = eHAL_STATUS_FAILURE; - } - else - { - if ( num20MHzChannelsFound > WNI_CFG_VALID_CHANNEL_LIST_LEN ) - { - num20MHzChannelsFound = WNI_CFG_VALID_CHANNEL_LIST_LEN; - } - - // Move the 2.4GHZ channel list only to the global data, - // As 5GHz list been provided by AP as part of 11d IE - // structure -- this will be used as the scan list - for(channelList = 0, nuum5GchannelListBackup = 0; channelList < WNI_CFG_VALID_CHANNEL_LIST_LEN; channelList++) - { - if(pMac->scan.base20MHzChannels.channelList[ channelList ] >= 36 && pMac->scan.base20MHzChannels.channelList[ channelList ] <= 165) - { - // First taking the 5GHz channel list backup - channelList5GBackup[nuum5GchannelListBackup] = pMac->scan.base20MHzChannels.channelList[ channelList ]; - nuum5GchannelListBackup++; - } - } - // Updating the 2.4GHz list - for ( Index = 0; Index < num20MHzChannelsFound; Index++) - { - if(pMac->scan.defaultPowerTable[Index].chanId > 0 && pMac->scan.defaultPowerTable[Index].chanId <= 14) - pMac->scan.base20MHzChannels.channelList[ Index ] = pMac->scan.defaultPowerTable[Index].chanId; - } - // Restoring the Backed up 5 GHZ channels - for(channelList = 0;channelList < nuum5GchannelListBackup; channelList++ ) - { - pMac->scan.base20MHzChannels.channelList[ Index ] = channelList5GBackup[channelList]; - Index++; - } - - pMac->scan.numChannelsDefault = (num20MHzChannelsFound > Index) ? num20MHzChannelsFound : Index; - pMac->scan.base20MHzChannels.numChannels = (num20MHzChannelsFound > Index) ? num20MHzChannelsFound : Index; - } - return (status); -} eHalStatus csrInitGetChannels(tpAniSirGlobal pMac) { @@ -2243,7 +2158,7 @@ eHalStatus csrRoamCallCallback(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoam WLAN_VOS_DIAG_EVENT_DEF(connectionStatus, vos_event_wlan_status_payload_type); #endif tCsrRoamSession *pSession; - if( CSR_IS_SESSION_VALID( pMac, sessionId) ) + if( pMac->roam.roamSession && CSR_IS_SESSION_VALID( pMac, sessionId) ) { pSession = CSR_GET_SESSION( pMac, sessionId ); } @@ -2257,7 +2172,7 @@ eHalStatus csrRoamCallCallback(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoam { smsLog(pMac, LOGW, " Assoc complete result = %d statusCode = %d reasonCode = %d", u2, pRoamInfo->statusCode, pRoamInfo->reasonCode); } - if ((u1 == eCSR_ROAM_FT_REASSOC_FAILED) && (pSession->bRefAssocStartCnt)) { + if (pSession && (u1 == eCSR_ROAM_FT_REASSOC_FAILED) && (pSession->bRefAssocStartCnt)) { /* * Decrement bRefAssocStartCnt for FT reassoc failure. * Reason: For FT reassoc failures, we first call @@ -2983,6 +2898,7 @@ void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOL break; case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: // Privacy is ON. NO RSN for Wep40 static key. PrivacyEnabled = 1; @@ -3036,6 +2952,7 @@ void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOL break; case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP104: // Privacy is ON. NO RSN for Wep40 static key. PrivacyEnabled = 1; @@ -3090,8 +3007,6 @@ void csrSetCfgPrivacy( tpAniSirGlobal pMac, tCsrRoamProfile *pProfile, tANI_BOOL break; - case eCSR_ENCRYPT_TYPE_WEP40: - case eCSR_ENCRYPT_TYPE_WEP104: case eCSR_ENCRYPT_TYPE_TKIP: case eCSR_ENCRYPT_TYPE_AES: #ifdef FEATURE_WLAN_WAPI @@ -4337,8 +4252,8 @@ eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) switch ( pCommand->u.roamCmd.roamReason ) { case eCsrForcedDisassoc: - csrFreeRoamProfile(pMac, sessionId); status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, FALSE ); + csrFreeRoamProfile(pMac, sessionId); break; case eCsrSmeIssuedDisassocForHandoff: //Not to free pMac->roam.pCurRoamProfile (via csrFreeRoamProfile) because it is needed after disconnect @@ -4350,12 +4265,12 @@ eHalStatus csrRoamProcessCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) break; case eCsrForcedDisassocMICFailure: - csrFreeRoamProfile(pMac, sessionId); status = csrRoamProcessDisassocDeauth( pMac, pCommand, TRUE, TRUE ); + csrFreeRoamProfile(pMac, sessionId); break; case eCsrForcedDeauth: - csrFreeRoamProfile(pMac, sessionId); status = csrRoamProcessDisassocDeauth( pMac, pCommand, FALSE, FALSE ); + csrFreeRoamProfile(pMac, sessionId); break; case eCsrHddIssuedReassocToSameAP: case eCsrSmeIssuedReassocToSameAP: @@ -4591,10 +4506,6 @@ static eHalStatus csrRoamSaveSecurityRspIE(tpAniSirGlobal pMac, tANI_U32 session || (eCSR_AUTH_TYPE_WAPI_WAI_PSK == authType) || (eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE == authType) -#endif /* FEATURE_WLAN_WAPI */ -#ifdef WLAN_FEATURE_11W - || - (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == authType) #endif /* FEATURE_WLAN_WAPI */ ) { @@ -4611,9 +4522,6 @@ static eHalStatus csrRoamSaveSecurityRspIE(tpAniSirGlobal pMac, tANI_U32 session (eCSR_AUTH_TYPE_FT_RSN == authType) || (eCSR_AUTH_TYPE_FT_RSN_PSK == authType) || #endif /* WLAN_FEATURE_VOWIFI_11R */ -#if defined WLAN_FEATURE_11W - (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == authType) || -#endif (eCSR_AUTH_TYPE_RSN_PSK == authType)) { if(pIesLocal->RSN.present) @@ -4866,6 +4774,13 @@ tANI_BOOLEAN csrRoamIsFastRoamEnabled(tpAniSirGlobal pMac, tANI_U32 sessionId) return (pMac->roam.configParam.isFastRoamIniFeatureEnabled && (!csrIsConcurrentSessionRunning(pMac))); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +//Returns whether "FW based BG scan" is currently enabled...or not +tANI_BOOLEAN csrRoamIsRoamOffloadScanEnabled(tpAniSirGlobal pMac) +{ + return (pMac->roam.configParam.isRoamOffloadScanEnabled); +} +#endif #endif //Return true means the command can be release, else not @@ -5129,6 +5044,7 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman pSession->connectedProfile.modifyProfileFields.uapsd_mask); pmcStartUapsd( pMac, NULL, NULL ); } + pSession->connectedProfile.dot11Mode = pSession->bssParams.uCfgDot11Mode; roamInfo.u.pConnectedProfile = &pSession->connectedProfile; if( pSession->bRefAssocStartCnt > 0 ) { @@ -5603,7 +5519,7 @@ static tANI_BOOLEAN csrRoamProcessResults( tpAniSirGlobal pMac, tSmeCmd *pComman case eCsrForcedDisassocSta: case eCsrForcedDeauthSta: csrRoamStateChange( pMac, eCSR_ROAMING_STATE_JOINED, sessionId); - if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + if( pMac->roam.roamSession && CSR_IS_SESSION_VALID(pMac, sessionId) ) { pSession = CSR_GET_SESSION(pMac, sessionId); if (!pSession) @@ -5714,15 +5630,19 @@ eHalStatus csrRoamCopyProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pDstProfile, #endif /* FEATURE_WLAN_WAPI */ if(pSrcProfile->nAddIEScanLength) { - status = palAllocateMemory(pMac->hHdd, - (void **)&pDstProfile->pAddIEScan, pSrcProfile->nAddIEScanLength); - if(!HAL_STATUS_SUCCESS(status)) + memset(pDstProfile->addIEScan, 0 , SIR_MAC_MAX_IE_LENGTH); + if ( SIR_MAC_MAX_IE_LENGTH >= pSrcProfile->nAddIEScanLength) { - break; + vos_mem_copy(pDstProfile->addIEScan, pSrcProfile->addIEScan, + pSrcProfile->nAddIEScanLength); + pDstProfile->nAddIEScanLength = pSrcProfile->nAddIEScanLength; + } + else + { + VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + FL(" AddIEScanLength is not valid %u"), + pSrcProfile->nAddIEScanLength); } - pDstProfile->nAddIEScanLength = pSrcProfile->nAddIEScanLength; - palCopyMemory(pMac->hHdd, pDstProfile->pAddIEScan, pSrcProfile->pAddIEScan, - pSrcProfile->nAddIEScanLength); } if(pSrcProfile->nAddIEAssocLength) { @@ -5752,11 +5672,6 @@ eHalStatus csrRoamCopyProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pDstProfile, pDstProfile->negotiatedUCEncryptionType = pSrcProfile->negotiatedUCEncryptionType; pDstProfile->negotiatedMCEncryptionType = pSrcProfile->negotiatedMCEncryptionType; pDstProfile->negotiatedAuthType = pSrcProfile->negotiatedAuthType; -#ifdef WLAN_FEATURE_11W - pDstProfile->MFPEnabled = pSrcProfile->MFPEnabled; - pDstProfile->MFPRequired = pSrcProfile->MFPRequired; - pDstProfile->MFPCapable = pSrcProfile->MFPCapable; -#endif pDstProfile->BSSType = pSrcProfile->BSSType; pDstProfile->phyMode = pSrcProfile->phyMode; pDstProfile->csrPersona = pSrcProfile->csrPersona; @@ -6707,6 +6622,11 @@ eHalStatus csrRoamSaveConnectedInfomation(tpAniSirGlobal pMac, tANI_U32 sessionI pConnectProfile->beaconInterval = pSirBssDesc->beaconInterval; palCopyMemory(pMac->hHdd, &pConnectProfile->Keys, &pProfile->Keys, sizeof(tCsrKeys)); + if(pConnectProfile->pAddIEAssoc) + { + palFreeMemory(pMac->hHdd, pConnectProfile->pAddIEAssoc); + pConnectProfile->pAddIEAssoc = NULL; + } /* saving the addional IE`s like Hot spot indication element and extended capabilities */ if(pProfile->nAddIEAssocLength) { @@ -6742,9 +6662,6 @@ eHalStatus csrRoamSaveConnectedInfomation(tpAniSirGlobal pMac, tANI_U32 sessionI || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN) -#ifdef WLAN_FEATURE_11W - || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) -#endif || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK)))) && (pMac->roam.configParam.isCcxIniFeatureEnabled)) { @@ -6925,7 +6842,17 @@ void csrRoamReissueRoamCommand(tpAniSirGlobal pMac) smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); return; } - + + /* While switching between two AP, csr will reissue roam command again + to the nextbss if it was interrupted by the dissconnect req for the + previous bss.During this csr is incrementing bRefAssocStartCnt twice. + so reset the bRefAssocStartCnt. + */ + if(pSession->bRefAssocStartCnt > 0) + { + pSession->bRefAssocStartCnt--; + } + if( pCommand->u.roamCmd.fStopWds ) { palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo)); @@ -7828,7 +7755,7 @@ void csrRoamJoinedStateMsgProcessor( tpAniSirGlobal pMac, void *pMsgBuf ) tSirSmeAssocIndToUpperLayerCnf *pUpperLayerAssocCnf; tCsrRoamInfo roamInfo; tCsrRoamInfo *pRoamInfo = NULL; - tANI_U32 sessionId; + tANI_U32 sessionId = 0; eHalStatus status; smsLog( pMac, LOG1, FL("ASSOCIATION confirmation can be given to upper layer ")); palZeroMemory(pMac->hHdd, &roamInfo, sizeof(tCsrRoamInfo)); @@ -8016,15 +7943,16 @@ static eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessi #ifdef WLAN_FEATURE_11W //Check for 11w BIP - else if (eCSR_ENCRYPT_TYPE_AES_CMAC == pSetKey->encType) + else if ( eCSR_ENCRYPT_TYPE_AES_CMAC == pSetKey->encType ) { - if (pSetKey->keyLength < CSR_AES_KEY_LEN) + tANI_U16 count = 0; + if ( pSetKey->keyLength < CSR_AES_KEY_LEN ) { - smsLog(pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call", pSetKey->keyLength); + smsLog( pMac, LOGW, "Invalid AES/CCMP keylength [= %d] in SetContext call", pSetKey->keyLength ); break; } pCommand->u.setKeyCmd.keyLength = CSR_AES_KEY_LEN; - palCopyMemory(pMac->hHdd, pCommand->u.setKeyCmd.Key, pSetKey->Key, CSR_AES_KEY_LEN); + palCopyMemory( pMac->hHdd, pCommand->u.setKeyCmd.Key, pSetKey->Key, CSR_AES_KEY_LEN ); } #endif status = eHAL_STATUS_SUCCESS; @@ -8045,11 +7973,12 @@ static eHalStatus csrRoamIssueSetKeyCommand( tpAniSirGlobal pMac, tANI_U32 sessi } while (0); // Free the command if there has been a failure, or it is a // "local" operation like the set CCX CCKM KRK key. - if( (!HAL_STATUS_SUCCESS( status ) && ( NULL != pCommand )) + if ( ( NULL != pCommand ) && + ( (!HAL_STATUS_SUCCESS( status ) ) #ifdef FEATURE_WLAN_CCX || ( eCSR_ENCRYPT_TYPE_KRK == pSetKey->encType ) #endif /* FEATURE_WLAN_CCX */ - ) + ) ) { csrReleaseCommandSetKey( pMac, pCommand ); } @@ -8500,16 +8429,16 @@ static void csrUpdateRssi(tpAniSirGlobal pMac, void* pMsg) #if defined WLAN_FEATURE_VOWIFI_11R || defined FEATURE_WLAN_CCX || defined(FEATURE_WLAN_LFR) void csrRoamRssiRspProcessor(tpAniSirGlobal pMac, void* pMsg) { - v_S7_t rssi = 0; tAniGetRoamRssiRsp* pRoamRssiRsp = (tAniGetRoamRssiRsp*)pMsg; - /* Get roam Rssi request is backed up and passed back to the response, - Extract the request message to fetch callback */ - tpAniGetRssiReq reqBkp = (tAniGetRssiReq*)pRoamRssiRsp->rssiReq; - if(pRoamRssiRsp) + if (NULL != pRoamRssiRsp) { - rssi = pRoamRssiRsp->rssi; - if((reqBkp) && (NULL != reqBkp->rssiCallback)) + /* Get roam Rssi request is backed up and passed back to the response, + Extract the request message to fetch callback */ + tpAniGetRssiReq reqBkp = (tAniGetRssiReq*)pRoamRssiRsp->rssiReq; + v_S7_t rssi = pRoamRssiRsp->rssi; + + if ((NULL != reqBkp) && (NULL != reqBkp->rssiCallback)) { ((tCsrRssiCallback)(reqBkp->rssiCallback))(rssi, pRoamRssiRsp->staId, reqBkp->pDevContext); reqBkp->rssiCallback = NULL; @@ -8600,7 +8529,6 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) tCsrRoamSession *pSession = NULL; tpSirSmeSwitchChannelInd pSwitchChnInd; tSmeMaxAssocInd *pSmeMaxAssocInd; - tSmeCmd pCommand; pSirMsg->messageType = (pSirMsg->messageType); pSirMsg->length = (pSirMsg->length); pSirMsg->statusCode = (pSirMsg->statusCode); @@ -8682,77 +8610,105 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) } break; case eWNI_SME_DISASSOC_IND: - smsLog( pMac, LOGE, FL("DISASSOCIATION Indication from MAC")); - // Check if AP dis-associated us because of MIC failure. If so, - // then we need to take action immediately and not wait till the - // the WmStatusChange requests is pushed and processed - pDisassocInd = (tSirSmeDisassocInd *)pSirMsg; - status = csrRoamGetSessionIdFromBSSID( pMac, (tCsrBssid *)pDisassocInd->bssId, &sessionId ); - if( HAL_STATUS_SUCCESS( status ) ) { - // If we are in neighbor preauth done state then on receiving - // disassoc or deauth we dont roam instead we just disassoc - // from current ap and then go to disconnected state - // This happens for CCX and 11r FT connections ONLY. -#ifdef WLAN_FEATURE_VOWIFI_11R - if (csrRoamIs11rAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac))) + // Check if AP dis-associated us because of MIC failure. If so, + // then we need to take action immediately and not wait till the + // the WmStatusChange requests is pushed and processed + tSmeCmd *pCommand; + + pDisassocInd = (tSirSmeDisassocInd *)pSirMsg; + status = csrRoamGetSessionIdFromBSSID( pMac, + (tCsrBssid *)pDisassocInd->bssId, &sessionId ); + if( HAL_STATUS_SUCCESS( status ) ) { - csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); - } + smsLog( pMac, LOGE, FL("DISASSOCIATION Indication from MAC" + " for session %d "), sessionId); + smsLog( pMac, LOGE, FL("DISASSOCIATION from peer =" + MAC_ADDRESS_STR " " + " reason = %d status = %d "), + MAC_ADDR_ARRAY(pDisassocInd->peerMacAddr), + pDisassocInd->reasonCode, + pDisassocInd->statusCode); + // If we are in neighbor preauth done state then on receiving + // disassoc or deauth we dont roam instead we just disassoc + // from current ap and then go to disconnected state + // This happens for CCX and 11r FT connections ONLY. +#ifdef WLAN_FEATURE_VOWIFI_11R + if (csrRoamIs11rAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac))) + { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); + } #endif #ifdef FEATURE_WLAN_CCX - if (csrRoamIsCCXAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac))) - { - csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); - } + if (csrRoamIsCCXAssoc(pMac) && (csrNeighborRoamStatePreauthDone(pMac))) + { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); + } #endif #ifdef FEATURE_WLAN_LFR - if (csrRoamIsFastRoamEnabled(pMac, sessionId) && (csrNeighborRoamStatePreauthDone(pMac))) - { - csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); - } + if (csrRoamIsFastRoamEnabled(pMac, sessionId) && (csrNeighborRoamStatePreauthDone(pMac))) + { + csrNeighborRoamTranistionPreauthDoneToDisconnected(pMac); + } #endif - pSession = CSR_GET_SESSION( pMac, sessionId ); + pSession = CSR_GET_SESSION( pMac, sessionId ); - if(!pSession) - { - smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); - return; - } + if (!pSession) + { + smsLog(pMac, LOGE, FL(" session %d not found "), sessionId); + return; + } - if ( csrIsConnStateInfra( pMac, sessionId ) ) - { - pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; - } + if ( csrIsConnStateInfra( pMac, sessionId ) ) + { + pSession->connectState = eCSR_ASSOC_STATE_TYPE_NOT_CONNECTED; + } #ifndef WLAN_MDM_CODE_REDUCTION_OPT - sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL); + sme_QosCsrEventInd(pMac, (v_U8_t)sessionId, SME_QOS_CSR_DISCONNECT_IND, NULL); #endif - csrRoamLinkDown(pMac, sessionId); - csrRoamIssueWmStatusChange( pMac, sessionId, eCsrDisassociated, pSirMsg ); - if(CSR_IS_INFRA_AP(&pSession->connectedProfile)) - { - - pRoamInfo = &roamInfo; + csrRoamLinkDown(pMac, sessionId); + csrRoamIssueWmStatusChange( pMac, sessionId, eCsrDisassociated, pSirMsg ); + if (CSR_IS_INFRA_AP(&pSession->connectedProfile)) + { - pRoamInfo->statusCode = pDisassocInd->statusCode; - pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + pCommand = csrGetCommandBuffer(pMac); + if (NULL == pCommand) + { + smsLog( pMac, LOGE, FL(" fail to get command buffer") ); + status = eHAL_STATUS_RESOURCES; + } + pRoamInfo = &roamInfo; + pRoamInfo->statusCode = pDisassocInd->statusCode; + pRoamInfo->u.pConnectedProfile = &pSession->connectedProfile; + pRoamInfo->staId = (tANI_U8)pDisassocInd->staId; - pRoamInfo->staId = (tANI_U8)pDisassocInd->staId; + vos_mem_copy(pRoamInfo->peerMac, pDisassocInd->peerMacAddr, + sizeof(tSirMacAddr)); + vos_mem_copy(&pRoamInfo->bssid, pDisassocInd->bssId, + sizeof(tCsrBssid)); - palCopyMemory(pMac->hHdd, pRoamInfo->peerMac, pDisassocInd->peerMacAddr, sizeof(tSirMacAddr)); - palCopyMemory(pMac->hHdd, &pRoamInfo->bssid, pDisassocInd->bssId, sizeof(tCsrBssid)); + status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, + eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_DISASSOC_IND); - status = csrRoamCallCallback(pMac, sessionId, pRoamInfo, 0, eCSR_ROAM_INFRA_IND, eCSR_ROAM_RESULT_DISASSOC_IND); + /* + * STA/P2P client got disassociated so remove any pending deauth + * commands in sme pending list + */ + pCommand->command = eSmeCommandRoam; + pCommand->sessionId = (tANI_U8)sessionId; + pCommand->u.roamCmd.roamReason = eCsrForcedDeauthSta; + vos_mem_copy(pCommand->u.roamCmd.peerMac, + pDisassocInd->peerMacAddr, + sizeof(tSirMacAddr)); + csrRoamRemoveDuplicateCommand(pMac, sessionId, pCommand, eCsrForcedDeauthSta); + csrReleaseCommand( pMac, pCommand ); - /* - * STA/P2P client got disassociated so remove any pending deauth - * commands in sme pending list - */ - pCommand.command = eSmeCommandRoam; - pCommand.sessionId = (tANI_U8)sessionId; - pCommand.u.roamCmd.roamReason = eCsrForcedDeauthSta; - vos_mem_copy(pCommand.u.roamCmd.peerMac, pDisassocInd->peerMacAddr, sizeof(tSirMacAddr)); - csrRoamRemoveDuplicateCommand(pMac, sessionId, &pCommand, eCsrForcedDeauthSta); + } + } + else + { + smsLog(pMac, LOGE, FL(" Session Id not found for BSSID " MAC_ADDRESS_STR), + MAC_ADDR_ARRAY(pDisassocInd->bssId)); } } break; @@ -8846,7 +8802,7 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) { tSirSmeDeauthRsp* pDeauthRsp = (tSirSmeDeauthRsp *)pSirMsg; sessionId = pDeauthRsp->sessionId; - if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + if( pMac->roam.roamSession && CSR_IS_SESSION_VALID(pMac, sessionId) ) { pSession = CSR_GET_SESSION(pMac, sessionId); if(!pSession) @@ -8873,7 +8829,7 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) { tSirSmeDisassocRsp *pDisassocRsp = (tSirSmeDisassocRsp *)pSirMsg; sessionId = pDisassocRsp->sessionId; - if( CSR_IS_SESSION_VALID(pMac, sessionId) ) + if( pMac->roam.roamSession && CSR_IS_SESSION_VALID(pMac, sessionId) ) { pSession = CSR_GET_SESSION(pMac, sessionId); if(!pSession) @@ -9467,6 +9423,12 @@ void csrRoamCheckForLinkStatusChange( tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg ) smsLog( pMac, LOG1, FL("RSSI indication from TL serialized through MC thread")); csrRoamRssiIndHdlr( pMac, pSirMsg ); break; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eWNI_SME_CANDIDATE_FOUND_IND: + smsLog( pMac, LOG2, FL("Candidate found indication from PE")); + csrNeighborRoamCandidateFoundIndHdlr( pMac, pSirMsg ); + break; +#endif default: break; @@ -11968,36 +11930,22 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe } #endif /* FEATURE_WLAN_CCX */ // addIEScan - if(pProfile->nAddIEScanLength && pProfile->pAddIEScan) + if (pProfile->nAddIEScanLength) { ieLen = pProfile->nAddIEScanLength; - if(ieLen > pSession->nAddIEScanLength) - { - if(pSession->pAddIEScan && pSession->nAddIEScanLength) - { - palFreeMemory(pMac->hHdd, pSession->pAddIEScan); - } - status = palAllocateMemory(pMac->hHdd, - (void **)&pSession->pAddIEScan, ieLen); - if(!HAL_STATUS_SUCCESS(status)) break; - } + memset(pSession->addIEScan, 0 , pSession->nAddIEScanLength); pSession->nAddIEScanLength = ieLen; - palCopyMemory(pMac->hHdd, pSession->pAddIEScan, - pProfile->pAddIEScan, ieLen); + vos_mem_copy(pSession->addIEScan, pProfile->addIEScan, ieLen); wTmp = pal_cpu_to_be16( ieLen ); palCopyMemory( pMac->hHdd, pBuf, &wTmp, sizeof(tANI_U16) ); pBuf += sizeof(tANI_U16); - palCopyMemory( pMac->hHdd, pBuf, pProfile->pAddIEScan, ieLen ); + vos_mem_copy(pBuf, pProfile->addIEScan, ieLen); pBuf += ieLen; } else { + memset(pSession->addIEScan, 0, pSession->nAddIEScanLength); pSession->nAddIEScanLength = 0; - if(pSession->pAddIEScan) - { - palFreeMemory(pMac->hHdd, pSession->pAddIEScan); - pSession->pAddIEScan = NULL; - } *pBuf = 0; *(pBuf + 1) = 0; pBuf += 2; @@ -12065,19 +12013,6 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe dwTmp = pal_cpu_to_be32( csrTranslateEncryptTypeToEdType( pProfile->negotiatedMCEncryptionType) ); palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tANI_U32) ); pBuf += sizeof(tANI_U32); -#ifdef WLAN_FEATURE_11W - //MgmtEncryption - if (pProfile->MFPEnabled) - { - dwTmp = pal_cpu_to_be32(eSIR_ED_AES_128_CMAC); - } - else - { - dwTmp = pal_cpu_to_be32(eSIR_ED_NONE); - } - palCopyMemory(pMac->hHdd, pBuf, &dwTmp, sizeof(tANI_U32)); - pBuf += sizeof(tANI_U32); -#endif #ifdef WLAN_FEATURE_VOWIFI_11R pProfile->MDID.mdiePresent = pBssDescription->mdiePresent; if (csrIsProfile11r( pProfile ) @@ -12101,6 +12036,21 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe } #endif #ifdef FEATURE_WLAN_CCX + + // isCCXFeatureIniEnabled + if (TRUE == pMac->roam.configParam.isCcxIniFeatureEnabled) + { + dwTmp = pal_cpu_to_be32(TRUE); + palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) ); + pBuf += sizeof(tAniBool); + } + else + { + dwTmp = pal_cpu_to_be32(FALSE); + palCopyMemory( pMac->hHdd, pBuf, &dwTmp, sizeof(tAniBool) ); + pBuf += sizeof(tAniBool); + } + /* A profile can not be both CCX and 11R. But an 802.11R AP * may be advertising support for CCX as well. So if we are * associating Open or explicitly CCX then we will get CCX. @@ -12113,9 +12063,6 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN) -#ifdef WLAN_FEATURE_11W - || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) -#endif || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK)))) && (pMac->roam.configParam.isCcxIniFeatureEnabled)) { @@ -12149,9 +12096,6 @@ eHalStatus csrSendJoinReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, tSirBssDe || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_WPA_PSK) || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN) -#ifdef WLAN_FEATURE_11W - || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK_SHA256) -#endif || (pProfile->negotiatedAuthType == eCSR_AUTH_TYPE_RSN_PSK)))) && (pMac->roam.configParam.isCcxIniFeatureEnabled)) { @@ -12865,8 +12809,8 @@ eHalStatus csrSendMBStartBssReqMsg( tpAniSirGlobal pMac, tANI_U32 sessionId, eCs { wTmp = pal_cpu_to_be16( WNI_CFG_BEACON_INTERVAL_STADEF ); } - if(csrIsconcurrentsessionValid (pMac, sessionId, - pParam->bssPersona) + if(csrIsconcurrentsessionValid (pMac, sessionId, + pParam->bssPersona) == eHAL_STATUS_SUCCESS ) { csrValidateMCCBeaconInterval(pMac, pParam->operationChn, &wTmp, sessionId, @@ -13145,22 +13089,24 @@ eHalStatus csrProcessAddStaSessionRsp( tpAniSirGlobal pMac, tANI_U8 *pMsg) } while(0); return status; } -eHalStatus csrSendMBAddSelfStaReqMsg( tpAniSirGlobal pMac, tSirMacAddr macAddr ) +eHalStatus csrSendMBAddSelfStaReqMsg(tpAniSirGlobal pMac, tAddStaForSessionCmd *pAddStaReq) { tSirSmeAddStaSelfReq *pMsg; tANI_U16 msgLen; eHalStatus status = eHAL_STATUS_FAILURE; do { - msgLen = sizeof( tANI_U16 ) + sizeof( tANI_U16 ) + sizeof( tSirMacAddr ) /*+ - sizeof( tSirBssType )*/; + msgLen = sizeof(tSirSmeAddStaSelfReq); status = palAllocateMemory(pMac->hHdd, (void **)&pMsg, msgLen); if ( !HAL_STATUS_SUCCESS(status) ) break; palZeroMemory(pMac->hHdd, pMsg, msgLen); pMsg->mesgType = pal_cpu_to_be16((tANI_U16)eWNI_SME_ADD_STA_SELF_REQ); pMsg->mesgLen = pal_cpu_to_be16(msgLen); // self station address - palCopyMemory( pMac->hHdd, (tANI_U8 *)pMsg->selfMacAddr, (tANI_U8 *)macAddr, sizeof(tSirMacAddr) ); - smsLog( pMac, LOG1, FL("selfMac=%02x, %02x, %02x, %02x, %02x, %02x"), + palCopyMemory(pMac->hHdd, (tANI_U8 *)pMsg->selfMacAddr, + (tANI_U8 *)&pAddStaReq->selfMacAddr, sizeof(tSirMacAddr)); + pMsg->currDeviceMode = pAddStaReq->currDeviceMode; + + smsLog( pMac, LOG1, FL("selfMac=%02x, %02x, %02x, %02x, %02x, %02x"), pMsg->selfMacAddr[0], pMsg->selfMacAddr[1], pMsg->selfMacAddr[2], @@ -13171,7 +13117,8 @@ eHalStatus csrSendMBAddSelfStaReqMsg( tpAniSirGlobal pMac, tSirMacAddr macAddr ) } while( 0 ); return( status ); } -eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, tSirMacAddr sessionMacAddr) +eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, + tSirMacAddr sessionMacAddr) { eHalStatus status = eHAL_STATUS_SUCCESS; tSmeCmd *pCommand; @@ -13184,7 +13131,8 @@ eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, { pCommand->command = eSmeCommandAddStaSession; pCommand->sessionId = (tANI_U8)sessionId; - palCopyMemory( pMac->hHdd, pCommand->u.addStaSessionCmd.selfMacAddr, sessionMacAddr, sizeof( tSirMacAddr ) ); + palCopyMemory(pMac->hHdd, pCommand->u.addStaSessionCmd.selfMacAddr, sessionMacAddr, sizeof(tSirMacAddr)); + pCommand->u.addStaSessionCmd.currDeviceMode = pMac->sme.currDeviceMode; status = csrQueueSmeCommand(pMac, pCommand, TRUE); if( !HAL_STATUS_SUCCESS( status ) ) { @@ -13196,11 +13144,11 @@ eHalStatus csrIssueAddStaForSessionReq(tpAniSirGlobal pMac, tANI_U32 sessionId, } eHalStatus csrProcessAddStaSessionCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) { - return csrSendMBAddSelfStaReqMsg( pMac, - pCommand->u.addStaSessionCmd.selfMacAddr ); + return csrSendMBAddSelfStaReqMsg( pMac, &pCommand->u.addStaSessionCmd); } -eHalStatus csrRoamOpenSession( tpAniSirGlobal pMac, csrRoamCompleteCallback callback, void *pContext, - tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId ) +eHalStatus csrRoamOpenSession(tpAniSirGlobal pMac, + csrRoamCompleteCallback callback, void *pContext, + tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId) { eHalStatus status = eHAL_STATUS_SUCCESS; tANI_U32 i; @@ -13243,7 +13191,7 @@ eHalStatus csrRoamOpenSession( tpAniSirGlobal pMac, csrRoamCompleteCallback call smsLog(pMac, LOGE, FL("cannot allocate memory for IbssJoining timer")); break; } - status = csrIssueAddStaForSessionReq ( pMac, i, pSelfMacAddr ); + status = csrIssueAddStaForSessionReq(pMac, i, pSelfMacAddr); break; } } @@ -13513,10 +13461,9 @@ static void csrInitSession( tpAniSirGlobal pMac, tANI_U32 sessionId ) } pSession->nWapiRspIeLength = 0; #endif /* FEATURE_WLAN_WAPI */ - if(pSession->pAddIEScan) + if (pSession->nAddIEScanLength) { - palFreeMemory(pMac->hHdd, pSession->pAddIEScan); - pSession->pAddIEScan = NULL; + memset(pSession->addIEScan, 0 , SIR_MAC_MAX_IE_LENGTH); } pSession->nAddIEScanLength = 0; if(pSession->pAddIEAssoc) @@ -13798,6 +13745,7 @@ void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg) v_PVOID_t pvosGCtx; v_S7_t rssi = 0; tANI_U32 *pRssi = NULL; + tANI_U32 linkCapacity; pSmeStatsRsp = (tAniGetPEStatsRsp *)pSirMsg; if(pSmeStatsRsp->rc) { @@ -13895,13 +13843,27 @@ void csrRoamStatsRspProcessor(tpAniSirGlobal pMac, tSirSmeRsp *pSirMsg) { pRssi = (tANI_U32*)pStats; rssi = (v_S7_t)*pRssi; + pStats += sizeof(tANI_U32); + length -= sizeof(tANI_U32); } else { /* If riva is not sending rssi, continue to use the hack */ rssi = RSSI_HACK_BMPS; } + WDA_UpdateRssiBmps(pvosGCtx, pSmeStatsRsp->staId, rssi); + + if (length != 0) + { + linkCapacity = *(tANI_U32*)pStats; + } + else + { + linkCapacity = 0; + } + + WDA_UpdateLinkCapacity(pvosGCtx, pSmeStatsRsp->staId, linkCapacity); post_update: //make sure to update the pe stats req list pEntry = csrRoamFindInPeStatsReqList(pMac, pSmeStatsRsp->statsMask); @@ -14244,8 +14206,8 @@ eHalStatus csrGetRoamRssi(tpAniSirGlobal pMac, status = palSendMBMessage(pMac->hHdd, pMsg ); if(!HAL_STATUS_SUCCESS(status)) { - smsLog(pMac, LOG1, " csrGetRoamRssi: failed to send down the stats req"); - palFreeMemory(pMac->hHdd, (void *)pMsg); + smsLog(pMac, LOG1, " csrGetRoamRssi: failed to send down the rssi req"); + //pMsg is freed by palSendMBMessage status = eHAL_STATUS_FAILURE; } return status; @@ -14521,6 +14483,365 @@ eHalStatus csrGetStatistics(tpAniSirGlobal pMac, eCsrStatsRequesterType requeste return eHAL_STATUS_SUCCESS; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +static tSirRetStatus +csrRoamScanOffloadPopulateMacHeader(tpAniSirGlobal pMac, + tANI_U8* pBD, + tANI_U8 type, + tANI_U8 subType, + tSirMacAddr peerAddr, + tSirMacAddr selfMacAddr) +{ + tSirRetStatus statusCode = eSIR_SUCCESS; + tpSirMacMgmtHdr pMacHdr; + + /* Prepare MAC management header */ + pMacHdr = (tpSirMacMgmtHdr) (pBD); + + /* Prepare FC */ + pMacHdr->fc.protVer = SIR_MAC_PROTOCOL_VERSION; + pMacHdr->fc.type = type; + pMacHdr->fc.subType = subType; + + /* Prepare Address 1 */ + palCopyMemory( pMac->hHdd, + (tANI_U8 *) pMacHdr->da, + (tANI_U8 *) peerAddr, + sizeof( tSirMacAddr )); + + sirCopyMacAddr(pMacHdr->sa,selfMacAddr); + + /* Prepare Address 3 */ + palCopyMemory( pMac->hHdd, + (tANI_U8 *) pMacHdr->bssId, + (tANI_U8 *) peerAddr, + sizeof( tSirMacAddr )); + return statusCode; +} /*** csrRoamScanOffloadPopulateMacHeader() ***/ + +static tSirRetStatus +csrRoamScanOffloadPrepareProbeReqTemplate(tpAniSirGlobal pMac, + tANI_U8 nChannelNum, + tANI_U32 dot11mode, + tSirMacAddr selfMacAddr, + tANI_U8 *pFrame, + tANI_U16 *pusLen) +{ + tDot11fProbeRequest pr; + tANI_U32 nStatus, nBytes, nPayload; + tSirRetStatus nSirStatus; + /*Bcast tx*/ + tSirMacAddr bssId = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + + palZeroMemory( pMac->hHdd, ( tANI_U8* )&pr, sizeof( pr ) ); + + PopulateDot11fSuppRates( pMac, nChannelNum, &pr.SuppRates,NULL); + + if ( WNI_CFG_DOT11_MODE_11B != dot11mode ) + { + PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates ); + } + + + if (IS_DOT11_MODE_HT(dot11mode)) + { + PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps ); + } + + + nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to calculate the packed size f" + "or a Probe Request (0x%08x).\n", nStatus ); + + + nPayload = sizeof( tDot11fProbeRequest ); + } + else if ( DOT11F_WARNED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while calculating" + "the packed size for a Probe Request (" + "0x%08x).\n", nStatus ); + } + + nBytes = nPayload + sizeof( tSirMacMgmtHdr ); + + /* Prepare outgoing frame*/ + palZeroMemory( pMac->hHdd, pFrame, nBytes ); + + + nSirStatus = csrRoamScanOffloadPopulateMacHeader( pMac, pFrame, SIR_MAC_MGMT_FRAME, + SIR_MAC_MGMT_PROBE_REQ, bssId ,selfMacAddr); + + if ( eSIR_SUCCESS != nSirStatus ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to populate the buffer descriptor for a Probe Request (%d).\n", + nSirStatus ); + return nSirStatus; + } + + + nStatus = dot11fPackProbeRequest( pMac, &pr, pFrame + + sizeof( tSirMacMgmtHdr ), + nPayload, &nPayload ); + if ( DOT11F_FAILED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "Failed to pack a Probe Request (0x%08x).\n", nStatus ); + return eSIR_FAILURE; + } + else if ( DOT11F_WARNED( nStatus ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while packing a Probe Request (0x%08x).\n" ); + } + + *pusLen = nPayload + sizeof(tSirMacMgmtHdr); + return eSIR_SUCCESS; +} + +eHalStatus csrRoamOffloadScan(tpAniSirGlobal pMac, tANI_U8 command, tANI_U8 reason) +{ + vos_msg_t msg; + tSirRoamOffloadScanReq *pRequestBuf; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; + tCsrRoamSession *pSession; + tANI_U8 i,num_channels = 0, ucDot11Mode; + tANI_U8 *ChannelList = NULL; + tANI_U8 MaxDwellPeriod; + tANI_U32 sessionId; + eHalStatus status = eHAL_STATUS_SUCCESS; + tpCsrChannelInfo currChannelListInfo; + currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; + + if (0 == pMac->roam.configParam.isRoamOffloadScanEnabled) + { + return eHAL_STATUS_FAILURE; + } + status = csrRoamGetSessionIdFromBSSID(pMac, + (tCsrBssid *)pNeighborRoamInfo->currAPbssid, + &sessionId); + /*The Dynamic Config Items Update may happen even if the state is in INIT. + * It is important to ensure that the command is passed down to the FW only + * if the Infra Station is in a connected state.A connected station could also be + * in a PREAUTH or REASSOC states.So, consider not sending the command down in INIT state. + * We also have to ensure that if there is a STOP command we always have to inform Riva, + * irrespective of whichever state we are in.*/ + if ((pMac->roam.neighborRoamInfo.neighborRoamState == eCSR_NEIGHBOR_ROAM_STATE_INIT) && + (command != ROAM_SCAN_OFFLOAD_STOP)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "Scan Command not sent to FW with state = %d and cmd = %d\n", + pMac->roam.neighborRoamInfo.neighborRoamState, command); + return eHAL_STATUS_FAILURE; + } + + if ( !HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to find the sessionId for Roam Offload scan request", __func__); + return eHAL_STATUS_FAILURE; + } + pSession = CSR_GET_SESSION( pMac, sessionId ); + pRequestBuf = vos_mem_malloc(sizeof(tSirRoamOffloadScanReq)); + if (NULL == pRequestBuf) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to allocate memory for Roam Offload scan request", __func__); + return eHAL_STATUS_FAILED_ALLOC; + } + + vos_mem_zero(pRequestBuf,sizeof(tSirRoamOffloadScanReq)); + /* If command is STOP, then pass down ScanOffloadEnabled as Zero.This will handle the case of + * host driver reloads, but Riva still up and running*/ + if(command == ROAM_SCAN_OFFLOAD_STOP) + pRequestBuf->RoamScanOffloadEnabled = 0; + else + pRequestBuf->RoamScanOffloadEnabled = pMac->roam.configParam.isRoamOffloadScanEnabled; + vos_mem_copy(pRequestBuf->ConnectedNetwork.currAPbssid, pNeighborRoamInfo->currAPbssid, + sizeof(tCsrBssid)); + pRequestBuf->ConnectedNetwork.ssId.length = + pMac->roam.roamSession[sessionId].connectedProfile.SSID.length; + vos_mem_copy(pRequestBuf->ConnectedNetwork.ssId.ssId, + pMac->roam.roamSession[sessionId].connectedProfile.SSID.ssId, + pRequestBuf->ConnectedNetwork.ssId.length); + pRequestBuf->ConnectedNetwork.authentication = + pMac->roam.roamSession[sessionId].connectedProfile.AuthType; + pRequestBuf->ConnectedNetwork.encryption = + pMac->roam.roamSession[sessionId].connectedProfile.EncryptionType; + pRequestBuf->ConnectedNetwork.mcencryption = + pMac->roam.roamSession[sessionId].connectedProfile.mcEncryptionType; + pRequestBuf->LookupThreshold = + (v_S7_t)pNeighborRoamInfo->cfgParams.neighborLookupThreshold * (-1); + pRequestBuf->RoamRssiDiff = + pMac->roam.configParam.RoamRssiDiff; + pRequestBuf->Command = command; + pRequestBuf->StartScanReason = reason; + pRequestBuf->NeighborScanTimerPeriod = + pNeighborRoamInfo->cfgParams.neighborScanPeriod; + pRequestBuf->NeighborRoamScanRefreshPeriod = + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod; + pRequestBuf->NeighborScanChannelMinTime = + pNeighborRoamInfo->cfgParams.minChannelScanTime; + pRequestBuf->NeighborScanChannelMaxTime = + pNeighborRoamInfo->cfgParams.maxChannelScanTime; + pRequestBuf->EmptyRefreshScanPeriod = + pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod; +#ifdef FEATURE_WLAN_CCX + pRequestBuf->IsCCXEnabled = pMac->roam.configParam.isCcxIniFeatureEnabled; +#endif + if ( +#ifdef FEATURE_WLAN_CCX + ((pNeighborRoamInfo->isCCXAssoc) && + (pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived == + eANI_BOOLEAN_FALSE)) || + (pNeighborRoamInfo->isCCXAssoc == eANI_BOOLEAN_FALSE) || +#endif // CCX + currChannelListInfo->numOfChannels == 0) + { + + /*Retreive the Channel Cache either from ini or from the Occupied Channels list. + * Give Preference to INI Channels.*/ + if (pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) + { + ChannelList = pNeighborRoamInfo->cfgParams.channelInfo.ChannelList; + for (i=0; icfgParams.channelInfo.numOfChannels ;i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC; + } + else{ + ChannelList = pMac->scan.occupiedChannels.channelList; + for(i=0; iscan.occupiedChannels.numChannels; i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + /* If the profile changes as to what it was earlier, inform the FW through + * FLUSH as ChannelCacheType in which case, the FW will flush the occupied channels + * for the earlier profile and try to learn them afresh.*/ + if (reason == REASON_FLUSH_CHANNEL_LIST) + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_FLUSH; + else { + if (csrNeighborRoamIsNewConnectedProfile(pMac)) + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_INIT; + else + pRequestBuf->ChannelCacheType = CHANNEL_LIST_DYNAMIC_UPDATE; + } + } + } +#ifdef FEATURE_WLAN_CCX + else + { + /* If CCX is enabled, and a neighbor Report is received,then + * Ignore the INI Channels or the Occupied Channel List. Consider + * the channels in the neighbor list sent by the CCX AP.*/ + if (currChannelListInfo->numOfChannels != 0) + { + ChannelList = currChannelListInfo->ChannelList; + for (i=0;inumOfChannels;i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ConnectedNetwork.ChannelCache[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ConnectedNetwork.ChannelCount = num_channels; + pRequestBuf->ChannelCacheType = CHANNEL_LIST_STATIC; + } + } +#endif + num_channels = 0; + ChannelList = NULL; + + /* Maintain the Valid Channels List*/ + if (0 == strncmp(pMac->scan.countryCodeCurrent, "KR", 2)) + { + ChannelList = pNeighborRoamInfo->cfgParams.countryChannelInfo.countryValidChannelList.ChannelList; + for(i=0; icfgParams.countryChannelInfo.countryValidChannelList.numOfChannels; i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ValidChannelList[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ValidChannelCount = num_channels; + } else { + ChannelList = pMac->roam.validChannelList; + for(i=0; iroam.numValidChannels; i++) + { + if(!CSR_IS_CHANNEL_DFS(*ChannelList) && *ChannelList) + { + pRequestBuf->ValidChannelList[num_channels++] = *ChannelList; + } + ChannelList++; + } + pRequestBuf->ValidChannelCount = num_channels; + } + pRequestBuf->MDID.mdiePresent = + pMac->roam.roamSession[sessionId].connectedProfile.MDID.mdiePresent; + pRequestBuf->MDID.mobilityDomain = + pMac->roam.roamSession[sessionId].connectedProfile.MDID.mobilityDomain; + /*Ensure that the nProbes does not fall below its MIN Value which is 2*/ + if(pMac->roam.configParam.nProbes < 2) + pRequestBuf->nProbes = 2; + else + pRequestBuf->nProbes = pMac->roam.configParam.nProbes; + + /*Max Dwell Period is calculated here to ensure that, + * Home Away Time is atleast equal to (MaxDwellPeriod + + * (2*SRF)), where SRF is the RF Switching time.The RF + * switching time is considered twice to consider the + * time to go off channel and return to the home channel.*/ + MaxDwellPeriod = pRequestBuf->NeighborScanChannelMaxTime/pRequestBuf->nProbes; + if(MaxDwellPeriod < 1) + MaxDwellPeriod = 1; + if(pMac->roam.configParam.nRoamScanHomeAwayTime < + (MaxDwellPeriod + (2 * SIR_ROAM_SCAN_CHANNEL_SWITCH_TIME))) + { + pRequestBuf->HomeAwayTime = MaxDwellPeriod + (2 * SIR_ROAM_SCAN_CHANNEL_SWITCH_TIME); + } else { + pRequestBuf->HomeAwayTime = pMac->roam.configParam.nRoamScanHomeAwayTime; + } + /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/ + ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, + csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); + csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen); + + csrRoamScanOffloadPrepareProbeReqTemplate(pMac,SIR_ROAM_SCAN_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen); + msg.type = WDA_ROAM_SCAN_OFFLOAD_REQ; + msg.reserved = 0; + msg.bodyptr = pRequestBuf; + if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_ROAM_SCAN_OFFLOAD_REQ message to WDA", __func__); + vos_mem_free(pRequestBuf); + return eHAL_STATUS_FAILURE; + } + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, "Roam Scan Offload Command %d, Reason %d", command, reason); + return status; +} +#endif + tCsrPeStatsReqInfo * csrRoamCheckPeStatsReqList(tpAniSirGlobal pMac, tANI_U32 statsMask, tANI_U32 periodicity, tANI_BOOLEAN *pFound, tANI_U8 staId) { @@ -14936,6 +15257,9 @@ eHalStatus csrIsFullPowerNeeded( tpAniSirGlobal pMac, tSmeCmd *pCommand, { switch( pCommand->u.scanCmd.reason ) { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif case eCsrScanGetResult: case eCsrScanBGScanAbort: case eCsrScanBGScanEnable: @@ -15513,8 +15837,48 @@ eHalStatus csrSetTxPower(tpAniSirGlobal pMac, v_U8_t sessionId, v_U8_t mW) if (!HAL_STATUS_SUCCESS(status)) { smsLog(pMac, LOGE, FL(" csr set TX Power Post MSG Fail %d "), status); - palFreeMemory(pMac->hHdd, pMsg); + //pMsg is freed by palSendMBMessage } } return status; } + +/* Returns whether a session is in VOS_STA_MODE...or not */ +tANI_BOOLEAN csrRoamIsStaMode(tpAniSirGlobal pMac, tANI_U32 sessionId) +{ + tCsrRoamSession *pSession = NULL; + pSession = CSR_GET_SESSION ( pMac, sessionId ); + if(!pSession) + { + smsLog(pMac, LOGE, FL(" %s: session %d not found "), __func__, sessionId); + return eANI_BOOLEAN_FALSE; + } + if ( !CSR_IS_SESSION_VALID ( pMac, sessionId ) ) + { + smsLog(pMac, LOGE, FL(" %s: Inactive session"), __func__); + return eANI_BOOLEAN_FALSE; + } + if ( eCSR_BSS_TYPE_INFRASTRUCTURE != pSession->connectedProfile.BSSType ) + { + return eANI_BOOLEAN_FALSE; + } + /* There is a possibility that the above check may fail,because + * P2P CLI also uses the same BSSType (eCSR_BSS_TYPE_INFRASTRUCTURE) + * when it is connected.So,we may sneak through the above check even + * if we are not a STA mode INFRA station. So, if we sneak through + * the above condition, we can use the following check if we are + * really in STA Mode.*/ + + if ( NULL != pSession->pCurRoamProfile ) + { + if ( pSession->pCurRoamProfile->csrPersona == VOS_STA_MODE ) + { + return eANI_BOOLEAN_TRUE; + } else { + smsLog(pMac, LOGE, FL(" %s: pCurRoamProfile is NULL\n"), __func__); + return eANI_BOOLEAN_FALSE; + } + } + + return eANI_BOOLEAN_FALSE; +} diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c b/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c index d842856c267..ec7518752c6 100755 --- a/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrApiScan.c @@ -114,10 +114,30 @@ RSSI *cannot* be more than 0xFF or less than 0 for meaningful WLAN operation #define CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) \ ( (pMac)->scan.nBssLimit <= (csrLLCount(&(pMac)->scan.scanResultList)) ) +/* Maximum number of channels per country can be ignored */ +#define MAX_CHANNELS_IGNORE 10 + +#define MAX_COUNTRY_IGNORE 3 +#define THIRTY_PERCENT(x) (x*30/100); + +/*struct to hold the ignored channel list based on country */ +typedef struct sCsrIgnoreChannels +{ + tANI_U8 countryCode[NV_FIELD_COUNTRY_CODE_SIZE]; + tANI_U16 channelList[MAX_CHANNELS_IGNORE]; + tANI_U16 channelCount; +}tCsrIgnoreChannels; + +static tCsrIgnoreChannels countryIgnoreList[MAX_COUNTRY_IGNORE] = { + { {'U','A'}, { 136, 140}, 2}, + { {'T','W'}, { 36, 40, 44, 48, 52}, 5}, + { {'I','D'}, { 165}, 1 } + }; + //*** This is temporary work around. It need to call CCM api to get to CFG later /// Get string parameter value extern tSirRetStatus wlan_cfgGetStr(tpAniSirGlobal, tANI_U16, tANI_U8*, tANI_U32*); - + void csrScanGetResultTimerHandler(void *); void csrScanResultAgingTimerHandler(void *pv); static void csrScanResultCfgAgingTimerHandler(void *pv); @@ -437,7 +457,7 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) tANI_BOOLEAN fNoCmdPending; tSmeCmd *pQueueScanCmd=NULL; tSmeCmd *pSendScanCmd=NULL; - + tANI_U8 nNumChanCombinedConc = 0; if (NULL == pScanCmd) { smsLog (pMac, LOGE, FL("Scan Req cmd is NULL")); @@ -452,6 +472,16 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) * the scan is delaying the time it takes for LFR to find * candidates and resulting in disconnects. */ + + if(csrIsStaSessionConnected(pMac) && + !csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + } + else if(csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; + } if ( (csrIsStaSessionConnected(pMac) && #ifdef FEATURE_WLAN_LFR (csrIsConcurrentInfraConnected(pMac) || @@ -494,7 +524,7 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) //Whenever we get a scan request with multiple channels we break it up into 2 requests //First request for first channel to scan and second request to scan remaining channels - if (numChn > pMac->roam.configParam.nNumChanCombinedConc) + if ( numChn > nNumChanCombinedConc) { palZeroMemory(pMac->hHdd, &scanReq, sizeof(tCsrScanRequest)); @@ -527,14 +557,14 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) scanReq.ChannelInfo.ChannelList = NULL; } - pChnInfo->numOfChannels = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels - pMac->roam.configParam.nNumChanCombinedConc; + pChnInfo->numOfChannels = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels - nNumChanCombinedConc; VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, - FL(" &channelToScan %0x pScanCmd(0x%X) pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList(0x%X)numChn(%d)"), - &channelToScan[0], (unsigned int)pScanCmd, - (unsigned int)pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, numChn); + FL(" &channelToScan %p pScanCmd(%p) pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList(%p)numChn(%d)"), + &channelToScan[0], pScanCmd, + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList, numChn); - palCopyMemory(pMac->hHdd, &channelToScan[0], &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[pMac->roam.configParam.nNumChanCombinedConc], + palCopyMemory(pMac->hHdd, &channelToScan[0], &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[nNumChanCombinedConc], pChnInfo->numOfChannels * sizeof(tANI_U8)); pChnInfo->ChannelList = &channelToScan[0]; @@ -571,7 +601,7 @@ eHalStatus csrQueueScanRequest( tpAniSirGlobal pMac, tSmeCmd *pScanCmd ) /* setup the command to scan 2 channels */ pSendScanCmd = pScanCmd; - pSendScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = pMac->roam.configParam.nNumChanCombinedConc; + pSendScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = nNumChanCombinedConc; pSendScanCmd->u.scanCmd.u.scanRequest.BSSType = eCSR_BSS_TYPE_ANY; pSendScanCmd->u.scanCmd.u.scanRequest.scanType = eSIR_ACTIVE_SCAN; //Use concurrency values for min/maxChnTime. @@ -950,6 +980,44 @@ eHalStatus csrScanRequestResult(tpAniSirGlobal pMac) return (status); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +eHalStatus csrScanRequestLfrResult(tpAniSirGlobal pMac, tANI_U32 sessionId, + csrScanCompleteCallback callback, void *pContext) +{ + eHalStatus status = eHAL_STATUS_SUCCESS; + tSmeCmd *pScanCmd; + + if (pMac->scan.fScanEnable) + { + pScanCmd = csrGetCommandBuffer(pMac); + if (pScanCmd) + { + pScanCmd->command = eSmeCommandScan; + pScanCmd->sessionId = sessionId; + palZeroMemory(pMac->hHdd, &pScanCmd->u.scanCmd, sizeof(tScanCmd)); + pScanCmd->u.scanCmd.callback = callback; + pScanCmd->u.scanCmd.pContext = pContext; + pScanCmd->u.scanCmd.reason = eCsrScanGetLfrResult; + //Need to make the following atomic + pScanCmd->u.scanCmd.scanID = pMac->scan.nextScanID; //let it wrap around + status = csrQueueSmeCommand(pMac, pScanCmd, eANI_BOOLEAN_TRUE); + if ( !HAL_STATUS_SUCCESS( status ) ) + { + smsLog( pMac, LOGE, FL(" fail to send message status = %d\n"), status ); + csrReleaseCommandScan(pMac, pScanCmd); + } + } + else + { + //log error + smsLog(pMac, LOGE, FL("can not obtain a common buffer\n")); + status = eHAL_STATUS_RESOURCES; + } + } + + return (status); +} +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD eHalStatus csrScanAllChannels(tpAniSirGlobal pMac, eCsrRequestType reqType) { @@ -2735,11 +2803,14 @@ tANI_BOOLEAN csrProcessBSSDescForBKIDList(tpAniSirGlobal pMac, tSirBssDescriptio #endif -static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) +static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac, tANI_U8 reason ) { tListElem *pEntry; + tListElem *pEntryTemp; + tListElem *pNext; tCsrScanResult *pBssDescription; tANI_S8 cand_Bss_rssi; + tANI_S8 rssi_of_current_country; tANI_BOOLEAN fDupBss; #ifdef FEATURE_WLAN_WAPI tANI_BOOLEAN fNewWapiBSSForCurConnection = eANI_BOOLEAN_FALSE; @@ -2748,9 +2819,11 @@ static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) tANI_U32 sessionId = CSR_SESSION_ID_INVALID; tAniSSID tmpSsid; v_TIME_t timer=0; + tCsrBssid bssid_temp = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; tmpSsid.length = 0; cand_Bss_rssi = -128; // RSSI coming from PE is -ve + rssi_of_current_country = -128; // remove the BSS descriptions from temporary list while( ( pEntry = csrLLRemoveTail( &pMac->scan.tempScanResults, LL_ACCESS_LOCK ) ) != NULL) @@ -2773,8 +2846,12 @@ static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) continue; } fDupBss = csrRemoveDupBssDescription( pMac, &pBssDescription->Result.BssDescriptor, pIesLocal, &tmpSsid , &timer ); - //Check whether we have reach out limit - if( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) ) + //Check whether we have reach out limit, but don't lose the LFR candidates came from FW + if( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !( eCsrScanGetLfrResult == reason ) +#endif + ) { //Limit reach smsLog(pMac, LOGW, FL(" BSS limit reached")); @@ -2827,14 +2904,34 @@ static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) if(pIesLocal->Country.present) { cand_Bss_rssi = pBssDescription->Result.BssDescriptor.rssi; - // learn country information - csrLearnCountryInformation( pMac, &pBssDescription->Result.BssDescriptor, - pIesLocal, eANI_BOOLEAN_FALSE ); + smsLog(pMac, LOGE, FL("11d AP Bssid " MAC_ADDRESS_STR + " chan= %d, rssi = -%d, countryCode %c%c"), + MAC_ADDR_ARRAY( pBssDescription->Result.BssDescriptor.bssId), + pBssDescription->Result.BssDescriptor.channelId, + pBssDescription->Result.BssDescriptor.rssi * (-1), + pIesLocal->Country.country[0],pIesLocal->Country.country[1] ); + //Getting BSSID for best AP in scan result. + palCopyMemory(pMac->hHdd, bssid_temp, + pBssDescription->Result.BssDescriptor.bssId, sizeof(tSirMacAddr)); + } } } - + //get current rssi for BSS from which country code is acquired. + if ( csrIs11dSupported(pMac) && (csrIsMacAddressEqual(pMac, + &pMac->scan.currentCountryBssid, + &pBssDescription->Result.BssDescriptor.bssId) )) + { + smsLog(pMac, LOGE, FL("Information about current country Bssid " + MAC_ADDRESS_STR + " chan= %d, rssi = -%d, countryCode %c%c"), + MAC_ADDR_ARRAY( pBssDescription->Result.BssDescriptor.bssId), + pBssDescription->Result.BssDescriptor.channelId, + pBssDescription->Result.BssDescriptor.rssi * (-1), + pIesLocal->Country.country[0],pIesLocal->Country.country[1] ); + rssi_of_current_country = pBssDescription->Result.BssDescriptor.rssi; + } // append to main list csrScanAddResult(pMac, pBssDescription, pIesLocal); @@ -2843,6 +2940,39 @@ static void csrMoveTempScanResultsToMainList( tpAniSirGlobal pMac ) palFreeMemory(pMac->hHdd, pIesLocal); } } + // calculating 30% of current rssi is an idea for not to change + // country code so freq. + if(rssi_of_current_country != -128) + { + rssi_of_current_country = rssi_of_current_country + - THIRTY_PERCENT(rssi_of_current_country); + } + + if ((rssi_of_current_country <= cand_Bss_rssi ) || rssi_of_current_country == -128) + { + csrLLLock(&pMac->scan.scanResultList); + pEntryTemp = csrLLPeekHead(&pMac->scan.scanResultList, LL_ACCESS_NOLOCK); + while ( NULL != pEntryTemp) + { + pNext = csrLLNext(&pMac->scan.scanResultList, pEntryTemp, + LL_ACCESS_NOLOCK); + pBssDescription = GET_BASE_ADDR( pEntryTemp, tCsrScanResult, Link ); + pIesLocal = (tDot11fBeaconIEs *)( pBssDescription->Result.pvIes ); + // Need to traverse whole scan list to get description for best 11d AP. + if (csrIsMacAddressEqual(pMac, (tCsrBssid *)&bssid_temp, + (tCsrBssid *) pBssDescription->Result.BssDescriptor.bssId)) + { + palCopyMemory(pMac->hHdd, pMac->scan.currentCountryBssid, + bssid_temp, sizeof(tSirMacAddr)); + // Best AP should be passed to update reg domain. + csrLearnCountryInformation( pMac, &pBssDescription->Result.BssDescriptor, + pIesLocal, eANI_BOOLEAN_FALSE ); + break; + } + pEntryTemp = pNext; + } + csrLLUnlock(&pMac->scan.scanResultList); + } //Tush: If we can find the current 11d info in any of the scan results, or // a good enough AP with the 11d info from the scan results then no need to @@ -3078,48 +3208,65 @@ void csrApplyPower2Current( tpAniSirGlobal pMac ) void csrApplyChannelPowerCountryInfo( tpAniSirGlobal pMac, tCsrChannel *pChannelList, tANI_U8 *countryCode, tANI_BOOLEAN updateRiva) { - int i; + int i, j, count, countryIndex = -1; eNVChannelEnabledType channelEnabledType; tANI_U8 numChannels = 0; tANI_U8 tempNumChannels = 0; + tANI_U8 channelIgnore = FALSE; tCsrChannel ChannelList; + if( pChannelList->numChannels ) { + for(count=0; count < MAX_COUNTRY_IGNORE; count++) + { + if(vos_mem_compare(countryCode, countryIgnoreList[count].countryCode, + VOS_COUNTRY_CODE_LEN)) + { + countryIndex = count; + break; + } + } tempNumChannels = CSR_MIN(pChannelList->numChannels, WNI_CFG_VALID_CHANNEL_LIST_LEN); /* If user doesn't want to scan the DFS channels lets trim them from the valid channel list*/ - for(i = 0; i< tempNumChannels; i++) + for(i=0; i < tempNumChannels; i++) { - if(FALSE == pMac->scan.fEnableDFSChnlScan) - { - channelEnabledType = - vos_nv_getChannelEnabledState(pChannelList->channelList[i]); - } - else - { + channelIgnore = FALSE; + if( FALSE == pMac->scan.fEnableDFSChnlScan ) + { + channelEnabledType = + vos_nv_getChannelEnabledState(pChannelList->channelList[i]); + } + else + { channelEnabledType = NV_CHANNEL_ENABLE; - } - if( NV_CHANNEL_ENABLE == channelEnabledType) - { - // Ignore the channel 165 for the country INDONESIA - if (( pChannelList->channelList[i] == 165 ) - && ( pMac->scan.fIgnore_chan165 == VOS_TRUE ) - && vos_mem_compare(countryCode, "ID", VOS_COUNTRY_CODE_LEN )) - { - continue; - } - else - { - ChannelList.channelList[numChannels] = pChannelList->channelList[i]; - numChannels++; - } - } + } + if( NV_CHANNEL_ENABLE == channelEnabledType ) + { + if( countryIndex != -1 ) + { + for(j=0; j < countryIgnoreList[countryIndex].channelCount; j++) + { + if( pChannelList->channelList[i] == + countryIgnoreList[countryIndex].channelList[j] ) + { + channelIgnore = TRUE; + break; + } + } + } + if( FALSE == channelIgnore ) + { + ChannelList.channelList[numChannels] = pChannelList->channelList[i]; + numChannels++; + } + } } - ChannelList.numChannels = numChannels; - + ChannelList.numChannels = numChannels; csrSetCfgValidChannelList(pMac, ChannelList.channelList, ChannelList.numChannels); // extend scan capability - csrSetCfgScanControlList(pMac, countryCode, &ChannelList); // build a scan list based on the channel list : channel# + active/passive scan + // build a scan list based on the channel list : channel# + active/passive scan + csrSetCfgScanControlList(pMac, countryCode, &ChannelList); /*Send msg to Lim to clear DFS channel list */ csrClearDfsChannelList(pMac); #ifdef FEATURE_WLAN_SCAN_PNO @@ -3383,13 +3530,8 @@ void csrApplyCountryInformation( tpAniSirGlobal pMac, tANI_BOOLEAN fForce ) #endif //#ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR if(pMac->scan.domainIdCurrent != domainId) { - /* Regulatory Domain Changed, Purge Only scan result - * which does not have channel number belong to 11d - * channel list - * */ smsLog(pMac, LOGW, FL("Domain Changed Old %d, new %d"), pMac->scan.domainIdCurrent, domainId); - csrScanFilter11dResult(pMac); status = WDA_SetRegDomain(pMac, domainId); } if (status != eHAL_STATUS_SUCCESS) @@ -3522,12 +3664,14 @@ void csrSetOppositeBandChannelInfo( tpAniSirGlobal pMac ) if ( CSR_IS_CHANNEL_5GHZ( pMac->scan.channelOf11dInfo ) ) { // and the 2.4 band is empty, then populate the 2.4 channel info + if ( !csrLLIsListEmpty( &pMac->scan.channelPowerInfoList24, LL_ACCESS_LOCK ) ) break; fPopulate5GBand = FALSE; } else { // else, we found channel info in the 2.4 GHz band. If the 5.0 band is empty // set the 5.0 band info from the 2.4 country code. + if ( !csrLLIsListEmpty( &pMac->scan.channelPowerInfoList5G, LL_ACCESS_LOCK ) ) break; fPopulate5GBand = TRUE; } csrSaveChannelPowerForBand( pMac, fPopulate5GBand ); @@ -3622,7 +3766,6 @@ void csrConstructCurrentValidChannelList( tpAniSirGlobal pMac, tDblLinkList *pCh tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription *pSirBssDesc, tDot11fBeaconIEs *pIes, tANI_BOOLEAN fForce) { - tANI_U8 Num2GChannels, bMaxNumChn; eHalStatus status; tANI_BOOLEAN fRet = eANI_BOOLEAN_FALSE; v_REGDOMAIN_t domainId; @@ -3742,54 +3885,66 @@ tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription } } smsLog(pMac, LOG3, FL(" %d sets each one is %d"), pIesLocal->Country.num_triplets, sizeof(tSirMacChanInfo)); - // save the channel/power information from the Channel IE. - //sizeof(tSirMacChanInfo) has to be 3 - if (eHAL_STATUS_SUCCESS != csrSaveToChannelPower2G_5G( pMac, pIesLocal->Country.num_triplets * sizeof(tSirMacChanInfo), - (tSirMacChanInfo *)(&pIesLocal->Country.triplets[0]) )) + + // set the indicator of the channel where the country IE was found... + pMac->scan.channelOf11dInfo = pSirBssDesc->channelId; + status = csrGetRegulatoryDomainForCountry(pMac, + pIesLocal->Country.country, &domainId ); + if ( status != eHAL_STATUS_SUCCESS ) { + smsLog( pMac, LOGE, FL(" fail to get regId %d"), domainId ); fRet = eANI_BOOLEAN_FALSE; return fRet; } - - // set the indicator of the channel where the country IE was found... - pMac->scan.channelOf11dInfo = pSirBssDesc->channelId; - csrGetRegulatoryDomainForCountry(pMac, pIesLocal->Country.country, &domainId ); // Checking for Domain Id change if ( domainId != pMac->scan.domainIdCurrent ) { - tSirMacChanInfo* pMacChnSet = (tSirMacChanInfo *)(&pIesLocal->Country.triplets[0]); - // Check whether AP provided the 2.4GHZ list or 5GHZ list - if(CSR_IS_CHANNEL_24GHZ(pMacChnSet[0].firstChanNum)) + vos_mem_copy(pMac->scan.countryCode11d, + pIesLocal->Country.country, + sizeof( pMac->scan.countryCode11d ) ); + /* Set Current Country code and Current Regulatory domain */ + status = csrSetRegulatoryDomain(pMac, domainId, NULL); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, "Set Reg Domain Fail %d", status); + fRet = eANI_BOOLEAN_FALSE; + return fRet; + } + //csrSetRegulatoryDomain will fail if the country doesn't fit our domain criteria. + vos_mem_copy(pMac->scan.countryCodeCurrent, + pIesLocal->Country.country, WNI_CFG_COUNTRY_CODE_LEN); + //Simply set it to cfg. + csrSetCfgCountryCode(pMac, pIesLocal->Country.country); + + /* overwrite the defualt country code */ + vos_mem_copy(pMac->scan.countryCodeDefault, + pMac->scan.countryCodeCurrent, + WNI_CFG_COUNTRY_CODE_LEN); + /* Set Current RegDomain */ + status = WDA_SetRegDomain(pMac, domainId); + if ( status != eHAL_STATUS_SUCCESS ) { - // AP Provided the 2.4 Channels, Update the 5GHz channels from nv.bin - csrGet5GChannels(pMac ); + smsLog( pMac, LOGE, FL(" fail to Set regId %d"), domainId ); + fRet = eANI_BOOLEAN_FALSE; + return fRet; } - else + /* set to default domain ID */ + pMac->scan.domainIdCurrent = domainId; + /* get the channels based on new cc */ + status = csrInitGetChannels( pMac ); + + if ( status != eHAL_STATUS_SUCCESS ) { - // AP Provided the 5G Channels, Update the 2.4GHZ channel list from nv.bin - csrGet24GChannels(pMac ); + smsLog( pMac, LOGE, FL(" fail to get Channels ")); + fRet = eANI_BOOLEAN_FALSE; + return fRet; } - csrSetCfgCountryCode(pMac, pIesLocal->Country.country); - WDA_SetRegDomain(pMac, domainId); - pMac->scan.domainIdCurrent = domainId; - } - // Populate both band channel lists based on what we found in the country information... - csrSetOppositeBandChannelInfo( pMac ); - bMaxNumChn = WNI_CFG_VALID_CHANNEL_LIST_LEN; - // construct 2GHz channel list first - csrConstructCurrentValidChannelList( pMac, &pMac->scan.channelPowerInfoList24, pMac->scan.channels11d.channelList, - bMaxNumChn, &Num2GChannels ); - // construct 5GHz channel list now - if(bMaxNumChn > Num2GChannels) - { - csrConstructCurrentValidChannelList( pMac, &pMac->scan.channelPowerInfoList5G, pMac->scan.channels11d.channelList + Num2GChannels, - bMaxNumChn - Num2GChannels, - &pMac->scan.channels11d.numChannels ); - } - pMac->scan.channels11d.numChannels += Num2GChannels; - fRet = eANI_BOOLEAN_TRUE; + /* reset info based on new cc, and we are done */ + csrResetCountryInformation(pMac, eANI_BOOLEAN_TRUE, eANI_BOOLEAN_TRUE); + fRet = eANI_BOOLEAN_TRUE; + } } while( 0 ); if( !pIes && pIesLocal ) @@ -3802,7 +3957,7 @@ tANI_BOOLEAN csrLearnCountryInformation( tpAniSirGlobal pMac, tSirBssDescription } -static void csrSaveScanResults( tpAniSirGlobal pMac ) +static void csrSaveScanResults( tpAniSirGlobal pMac, tANI_U8 reason ) { // initialize this to FALSE. profMoveInterimScanResultsToMainList() routine // will set this to the channel where an .11d beacon is seen @@ -3814,7 +3969,7 @@ static void csrSaveScanResults( tpAniSirGlobal pMac ) // only if the applied 11d info could be found in one of the scan results pMac->scan.fCurrent11dInfoMatch = eANI_BOOLEAN_FALSE; // move the scan results from interim list to the main scan list - csrMoveTempScanResultsToMainList( pMac ); + csrMoveTempScanResultsToMainList( pMac, reason ); // Now check if we gathered any domain/country specific information // If so, we should update channel list and apply Tx power settings @@ -4031,7 +4186,7 @@ tANI_BOOLEAN csrScanComplete( tpAniSirGlobal pMac, tSirSmeScanRsp *pScanRsp ) //This check only valid here because csrSaveScanresults is not yet called fSuccess = (!csrLLIsListEmpty(&pMac->scan.tempScanResults, LL_ACCESS_LOCK)); } - csrSaveScanResults(pMac); + csrSaveScanResults(pMac, pCommand->u.scanCmd.reason); #ifdef FEATURE_WLAN_DIAG_SUPPORT_CSR { @@ -4489,6 +4644,14 @@ static tANI_BOOLEAN csrScanProcessScanResults( tpAniSirGlobal pMac, tSmeCmd *pCo tANI_U8 cChannels = 0; //Different scan type can reach this point, we need to distinguish it +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if( eCsrScanGetLfrResult == pCommand->u.scanCmd.reason ) + { + pChannelList = NULL; + cChannels = 0; + } + else +#endif if( eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason ) { //eCsrScanSetBGScanParam uses different structure @@ -4577,6 +4740,9 @@ static tANI_BOOLEAN csrScanProcessScanResults( tpAniSirGlobal pMac, tSmeCmd *pCo //HO bg scan/probe failed no need to try autonomously if(eCsrScanBgScan == pCommand->u.scanCmd.reason || eCsrScanProbeBss == pCommand->u.scanCmd.reason || +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + eCsrScanGetLfrResult == pCommand->u.scanCmd.reason || +#endif eCsrScanSetBGScanParam == pCommand->u.scanCmd.reason) { fRemoveCommand = eANI_BOOLEAN_TRUE; @@ -4696,7 +4862,11 @@ eHalStatus csrScanSmeScanResponse( tpAniSirGlobal pMac, void *pMsgBuf ) { //Not to get channel info if the scan is not a wildcard scan because //it may cause scan results got aged out incorrectly. - if( csrScanIsWildCardScan( pMac, pCommand ) && (!pCommand->u.scanCmd.u.scanRequest.p2pSearch) ) + if( csrScanIsWildCardScan( pMac, pCommand ) && (!pCommand->u.scanCmd.u.scanRequest.p2pSearch) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (pCommand->u.scanCmd.reason != eCsrScanGetLfrResult) +#endif + ) { //Get the list of channels scanned if( pCommand->u.scanCmd.reason != eCsrScanUserRequest) @@ -5097,7 +5267,7 @@ eHalStatus csrSendMBScanReq( tpAniSirGlobal pMac, tANI_U16 sessionId, return( status ); } -eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tScanReqParam *pScanReqParam ) +eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tANI_U32 sessionId, tScanReqParam *pScanReqParam ) { eHalStatus status = eHAL_STATUS_SUCCESS; tSirSmeScanReq *pMsg; @@ -5110,12 +5280,18 @@ eHalStatus csrSendMBScanResultReq( tpAniSirGlobal pMac, tScanReqParam *pScanReqP palZeroMemory(pMac->hHdd, pMsg, msgLen); pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_SCAN_REQ); pMsg->length = pal_cpu_to_be16(msgLen); - pMsg->sessionId = 0; + pMsg->sessionId = sessionId; + pMsg->transactionId = 0; pMsg->returnFreshResults = pScanReqParam->freshScan; //Always ask for unique result pMsg->returnUniqueResults = pScanReqParam->fUniqueResult; pMsg->returnAfterFirstMatch = pScanReqParam->bReturnAfter1stMatch; status = palSendMBMessage(pMac->hHdd, pMsg); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog( pMac, LOGE, FL(" failed to send down scan req with status = %d\n"), status ); + } + } return( status ); @@ -5195,18 +5371,30 @@ eHalStatus csrScanChannels( tpAniSirGlobal pMac, tSmeCmd *pCommand ) } -eHalStatus csrScanRetrieveResult(tpAniSirGlobal pMac) +eHalStatus csrScanRetrieveResult(tpAniSirGlobal pMac, tSmeCmd *pCommand) { eHalStatus status = eHAL_STATUS_FAILURE; tScanReqParam scanReq; do { - //not a fresh scan - scanReq.freshScan = CSR_SME_SCAN_FLAGS_DELETE_CACHE; - scanReq.fUniqueResult = TRUE; - scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; - status = csrSendMBScanResultReq(pMac, &scanReq); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (eCsrScanGetLfrResult == pCommand->u.scanCmd.reason) + { + //to get the LFR candidates from PE cache + scanReq.freshScan = SIR_BG_SCAN_RETURN_LFR_CACHED_RESULTS|SIR_BG_SCAN_PURGE_LFR_RESULTS; + scanReq.fUniqueResult = TRUE; + scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; + } + else +#endif + { + //not a fresh scan + scanReq.freshScan = CSR_SME_SCAN_FLAGS_DELETE_CACHE; + scanReq.fUniqueResult = TRUE; + scanReq.bReturnAfter1stMatch = CSR_SCAN_RETURN_AFTER_ALL_CHANNELS; + } + status = csrSendMBScanResultReq(pMac, pCommand->sessionId, &scanReq); }while(0); return (status); @@ -5231,9 +5419,12 @@ eHalStatus csrProcessScanCommand( tpAniSirGlobal pMac, tSmeCmd *pCommand ) switch(pCommand->u.scanCmd.reason) { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif case eCsrScanGetResult: case eCsrScanForCapsChange: //For cap change, LIM already save BSS description - status = csrScanRetrieveResult(pMac); + status = csrScanRetrieveResult(pMac, pCommand); break; case eCsrScanSetBGScanParam: status = csrProcessSetBGScanParam(pMac, pCommand); @@ -5741,6 +5932,7 @@ static void csrStaApConcTimerHandler(void *pv) tCsrScanRequest scanReq; tSmeCmd *pSendScanCmd = NULL; tANI_U8 numChn = 0; + tANI_U8 nNumChanCombinedConc = 0; tANI_U8 i, j; tCsrChannelInfo *pChnInfo = &scanReq.ChannelInfo; tANI_U8 channelToScan[WNI_CFG_VALID_CHANNEL_LIST_LEN]; @@ -5764,7 +5956,18 @@ static void csrStaApConcTimerHandler(void *pv) * the scan is delaying the time it takes for LFR to find * candidates and resulting in disconnects. */ - if ( (numChn > pMac->roam.configParam.nNumChanCombinedConc) && + + if((csrIsStaSessionConnected(pMac) && + !csrIsP2pSessionConnected(pMac))) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumStaChanCombinedConc; + } + else if(csrIsP2pSessionConnected(pMac)) + { + nNumChanCombinedConc = pMac->roam.configParam.nNumP2PChanCombinedConc; + } + + if ( (numChn > nNumChanCombinedConc) && ((csrIsStaSessionConnected(pMac) && #ifdef FEATURE_WLAN_LFR (csrIsConcurrentInfraConnected(pMac) || @@ -5801,18 +6004,18 @@ static void csrStaApConcTimerHandler(void *pv) scanReq.ChannelInfo.ChannelList = NULL; } - pChnInfo->numOfChannels = pMac->roam.configParam.nNumChanCombinedConc; + pChnInfo->numOfChannels = nNumChanCombinedConc; palCopyMemory(pMac->hHdd, &channelToScan[0], &pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[0], pChnInfo->numOfChannels * sizeof(tANI_U8)); //just send one channel pChnInfo->ChannelList = &channelToScan[0]; - for (i = 0, j = pMac->roam.configParam.nNumChanCombinedConc; i < (numChn-pMac->roam.configParam.nNumChanCombinedConc); i++, j++) + for (i = 0, j = nNumChanCombinedConc; i < (numChn-nNumChanCombinedConc); i++, j++) { pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[i] = pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.ChannelList[j]; //Move all the channels one step } - pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn - pMac->roam.configParam.nNumChanCombinedConc; //reduce outstanding # of channels to be scanned + pScanCmd->u.scanCmd.u.scanRequest.ChannelInfo.numOfChannels = numChn - nNumChanCombinedConc; //reduce outstanding # of channels to be scanned scanReq.BSSType = eCSR_BSS_TYPE_ANY; //Modify callers parameters in case of concurrency @@ -6349,6 +6552,9 @@ tANI_BOOLEAN csrScanRemoveFreshScanCommand(tpAniSirGlobal pMac, tANI_U8 sessionI { switch(pCommand->u.scanCmd.reason) { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case eCsrScanGetLfrResult: +#endif case eCsrScanGetResult: case eCsrScanSetBGScanParam: case eCsrScanBGScanAbort: @@ -6579,7 +6785,7 @@ eHalStatus csrScanForSSID(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfi { pScanCmd->u.scanCmd.u.scanRequest.p2pSearch = 1; } - if(pProfile->pAddIEScan) + if(pProfile->nAddIEScanLength) { status = palAllocateMemory(pMac->hHdd, (void **)&pScanCmd->u.scanCmd.u.scanRequest.pIEField, @@ -6587,7 +6793,7 @@ eHalStatus csrScanForSSID(tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamProfi palZeroMemory(pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.pIEField, pProfile->nAddIEScanLength); if(HAL_STATUS_SUCCESS(status)) { - palCopyMemory(pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.pIEField, pProfile->pAddIEScan, pProfile->nAddIEScanLength); + palCopyMemory(pMac->hHdd, pScanCmd->u.scanCmd.u.scanRequest.pIEField, pProfile->addIEScan, pProfile->nAddIEScanLength); pScanCmd->u.scanCmd.u.scanRequest.uIEFieldLen = pProfile->nAddIEScanLength; } else @@ -7002,7 +7208,7 @@ void csrSetCfgScanControlList( tpAniSirGlobal pMac, tANI_U8 *countryCode, tCsrCh if (found) // insert a pair(channel#, flag) { - pControlList[j+1] = csrGetScanType(pMac, pControlList[j]); + pControlList[j+1] = csrGetScanType(pMac, pControlList[j]); found = FALSE; // reset the flag } @@ -7255,6 +7461,176 @@ tANI_BOOLEAN csrRoamIsValidChannel( tpAniSirGlobal pMac, tANI_U8 channel ) return fValid; } +eHalStatus csrScanSavePreferredNetworkFound(tpAniSirGlobal pMac, + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd) +{ + v_U32_t uLen = 0; + tpSirProbeRespBeacon pParsedFrame; + tCsrScanResult *pScanResult = NULL; + tSirBssDescription *pBssDescr = NULL; + tANI_BOOLEAN fDupBss; + tDot11fBeaconIEs *pIesLocal = NULL; + tAniSSID tmpSsid; + v_TIME_t timer=0; + tpSirMacMgmtHdr macHeader = (tpSirMacMgmtHdr)pPrefNetworkFoundInd->data; + + pParsedFrame = + (tpSirProbeRespBeacon) vos_mem_malloc(sizeof(tSirProbeRespBeacon)); + + if (NULL == pParsedFrame) + { + smsLog(pMac, LOGE, FL(" fail to allocate memory for frame")); + return eHAL_STATUS_RESOURCES; + } + + if ( pPrefNetworkFoundInd->frameLength <= SIR_MAC_HDR_LEN_3A ) + { + smsLog(pMac, LOGE, + FL("Not enough bytes in PNO indication probe resp frame! length=%d"), + pPrefNetworkFoundInd->frameLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + + if (sirConvertProbeFrame2Struct(pMac, + &pPrefNetworkFoundInd->data[SIR_MAC_HDR_LEN_3A], + pPrefNetworkFoundInd->frameLength - SIR_MAC_HDR_LEN_3A, + pParsedFrame) != eSIR_SUCCESS || + !pParsedFrame->ssidPresent) + { + smsLog(pMac, LOGE, + FL("Parse error ProbeResponse, length=%d"), + pPrefNetworkFoundInd->frameLength); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_FAILURE; + } + //24 byte MAC header and 12 byte to ssid IE + if (pPrefNetworkFoundInd->frameLength > + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET)) + { + uLen = pPrefNetworkFoundInd->frameLength - + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET); + } + + if ( !HAL_STATUS_SUCCESS(palAllocateMemory( pMac->hHdd, + (void **)&pScanResult, sizeof(tCsrScanResult) + uLen )) ) + { + smsLog(pMac, LOGE, FL(" fail to allocate memory for frame")); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + + palZeroMemory( pMac->hHdd, pScanResult, sizeof(tCsrScanResult) + uLen ); + pBssDescr = &pScanResult->Result.BssDescriptor; + /** + * Length of BSS desription is without length of + * length itself and length of pointer + * that holds the next BSS description + */ + pBssDescr->length = (tANI_U16)( + sizeof(tSirBssDescription) - sizeof(tANI_U16) - + sizeof(tANI_U32) + uLen); + if (pParsedFrame->dsParamsPresent) + { + pBssDescr->channelId = pParsedFrame->channelNumber; + } + else if (pParsedFrame->HTInfo.present) + { + pBssDescr->channelId = pParsedFrame->HTInfo.primaryChannel; + } + else + { + pBssDescr->channelId = pParsedFrame->channelNumber; + } + + if ((pBssDescr->channelId > 0) && (pBssDescr->channelId < 15)) + { + int i; + // 11b or 11g packet + // 11g iff extended Rate IE is present or + // if there is an A rate in suppRate IE + for (i = 0; i < pParsedFrame->supportedRates.numRates; i++) + { + if (sirIsArate(pParsedFrame->supportedRates.rate[i] & 0x7f)) + { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + break; + } + } + if (pParsedFrame->extendedRatesPresent) + { + pBssDescr->nwType = eSIR_11G_NW_TYPE; + } + } + else + { + // 11a packet + pBssDescr->nwType = eSIR_11A_NW_TYPE; + } + + pBssDescr->sinr = 0; + pBssDescr->rssi = -1 * pPrefNetworkFoundInd->rssi; + pBssDescr->beaconInterval = pParsedFrame->beaconInterval; + pBssDescr->timeStamp[0] = pParsedFrame->timeStamp[0]; + pBssDescr->timeStamp[1] = pParsedFrame->timeStamp[1]; + pBssDescr->capabilityInfo = *((tANI_U16 *)&pParsedFrame->capabilityInfo); + palCopyMemory( pMac->hHdd, (tANI_U8 *) &pBssDescr->bssId, + (tANI_U8 *) macHeader->bssId, + sizeof(tSirMacAddr)); + pBssDescr->nReceivedTime = (tANI_TIMESTAMP)palGetTickCount(pMac->hHdd); + + smsLog( pMac, LOG2, "(%s):Bssid= %02x-%02x-%02x-%02x-%02x-%02x " + "chan= %d, rssi = %d", __func__, + pBssDescr->bssId[ 0 ], pBssDescr->bssId[ 1 ], + pBssDescr->bssId[ 2 ], pBssDescr->bssId[ 3 ], + pBssDescr->bssId[ 4 ], pBssDescr->bssId[ 5 ], + pBssDescr->channelId, + pBssDescr->rssi ); + + //IEs + if (uLen) + { + vos_mem_copy( &pBssDescr->ieFields, + pPrefNetworkFoundInd->data + + (SIR_MAC_HDR_LEN_3A + SIR_MAC_B_PR_SSID_OFFSET), + uLen); + } + + pIesLocal = (tDot11fBeaconIEs *)( pScanResult->Result.pvIes ); + if ( !pIesLocal && + (!HAL_STATUS_SUCCESS(csrGetParsedBssDescriptionIEs(pMac, + &pScanResult->Result.BssDescriptor, &pIesLocal))) ) + { + smsLog(pMac, LOGE, FL(" Cannot parse IEs")); + csrFreeScanResultEntry(pMac, pScanResult); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + + fDupBss = csrRemoveDupBssDescription( pMac, + &pScanResult->Result.BssDescriptor, pIesLocal, &tmpSsid , &timer); + //Check whether we have reach out limit + if ( CSR_SCAN_IS_OVER_BSS_LIMIT(pMac) ) + { + //Limit reach + smsLog(pMac, LOGE, FL(" BSS limit reached")); + //Free the resources + if( (pScanResult->Result.pvIes == NULL) && pIesLocal ) + { + palFreeMemory(pMac->hHdd, pIesLocal); + } + csrFreeScanResultEntry(pMac, pScanResult); + vos_mem_free(pParsedFrame); + return eHAL_STATUS_RESOURCES; + } + //Add to scan cache + csrScanAddResult(pMac, pScanResult, pIesLocal); + + vos_mem_free(pParsedFrame); + + return eHAL_STATUS_SUCCESS; +} + #ifdef FEATURE_WLAN_LFR void csrInitOccupiedChannelsList(tpAniSirGlobal pMac) { diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h b/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h index 2a02e3ff80d..1a8d5cf8550 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h +++ b/drivers/staging/prima/CORE/SME/src/csr/csrInsideApi.h @@ -76,7 +76,8 @@ #define CSR_REST_TIME_CONC 100 -#define CSR_NUM_CHAN_COMBINED_CONC 1 +#define CSR_NUM_STA_CHAN_COMBINED_CONC 3 +#define CSR_NUM_P2P_CHAN_COMBINED_CONC 1 #endif #define CSR_MAX_NUM_SUPPORTED_CHANNELS 55 diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c index edbc954d683..6f487426c24 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrNeighborRoam.c @@ -270,7 +270,11 @@ static void csrNeighborRoamTriggerHandoff(tpAniSirGlobal pMac, tpCsrNeighborRoamControlInfo pNeighborRoamInfo) { #ifdef WLAN_FEATURE_VOWIFI_11R - if (pNeighborRoamInfo->is11rAssoc) + if ((pNeighborRoamInfo->is11rAssoc) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) { @@ -286,7 +290,11 @@ static void csrNeighborRoamTriggerHandoff(tpAniSirGlobal pMac, #endif #ifdef FEATURE_WLAN_CCX - if (pNeighborRoamInfo->isCCXAssoc) + if ((pNeighborRoamInfo->isCCXAssoc) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) { @@ -303,7 +311,11 @@ static void csrNeighborRoamTriggerHandoff(tpAniSirGlobal pMac, #ifdef FEATURE_WLAN_LFR if (csrRoamIsFastRoamEnabled(pMac, CSR_SESSION_ID_INVALID)) { - if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) + if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + || csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { csrNeighborRoamIssuePreauthReq(pMac); } @@ -337,6 +349,12 @@ VOS_STATUS csrNeighborRoamUpdateFastRoamingEnabled(tpAniSirGlobal pMac, const v_ { if (VOS_TRUE == fastRoamEnabled) { +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_START, REASON_CONNECT); + } else { +#endif NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold); /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ @@ -350,12 +368,24 @@ VOS_STATUS csrNeighborRoamUpdateFastRoamingEnabled(tpAniSirGlobal pMac, const v_ smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), vosStatus); vosStatus = VOS_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif } else if (VOS_FALSE == fastRoamEnabled) { NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Currently in CONNECTED state, so deregister all events")); /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED); + } else { +#endif csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif } } else if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) @@ -382,6 +412,12 @@ VOS_STATUS csrNeighborRoamUpdateCcxModeEnabled(tpAniSirGlobal pMac, const v_BOOL { NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_START, REASON_CONNECT); + } else { +#endif /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, (v_S7_t)pNeighborRoamInfo->currentNeighborLookupThreshold * (-1), WLANTL_HO_THRESHOLD_DOWN, @@ -393,12 +429,24 @@ VOS_STATUS csrNeighborRoamUpdateCcxModeEnabled(tpAniSirGlobal pMac, const v_BOOL smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), vosStatus); vosStatus = VOS_STATUS_E_FAILURE; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif } else if (VOS_FALSE == ccxMode) { NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Currently in CONNECTED state, so deregister all events")); /* De-register existing lookup UP/DOWN, Rssi indications */ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED); + } else { +#endif csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif } } else if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) @@ -858,6 +906,12 @@ tANI_BOOLEAN csrNeighborRoamIsPreauthCandidate(tpAniSirGlobal pMac, tSirMacAddr tANI_U8 i = 0; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (csrRoamIsRoamOffloadScanEnabled(pMac)) + { + return eANI_BOOLEAN_TRUE; + } +#endif if (0 == pNeighborRoamInfo->FTRoamInfo.preAuthFailList.numMACAddress) return eANI_BOOLEAN_TRUE; @@ -1053,32 +1107,43 @@ eHalStatus csrNeighborRoamPreauthRspHandler(tpAniSirGlobal pMac, tSirRetStatus l if (eHAL_STATUS_SUCCESS == csrNeighborRoamIssuePreauthReq(pMac)) goto DEQ_PREAUTH; - CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN); - - /* Register Neighbor Lookup threshold callback with TL for UP event now */ - NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("No more pre-auth candidates-" - "register UP indication with TL. RSSI = %d,"), NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); - - vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, - (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), - WLANTL_HO_THRESHOLD_UP, - csrNeighborRoamNeighborLookupUPCallback, - VOS_MODULE_ID_SME, pMac); - if(!VOS_IS_STATUS_SUCCESS(vosStatus)) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (csrRoamIsRoamOffloadScanEnabled(pMac)) { - //err msg - smsLog(pMac, LOGE, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback UP event with TL: Status = %d"), status); - } - - /* Start the neighbor results refresh timer and transition to REPORT_SCAN state to perform scan again */ - status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer, - pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * PAL_TIMER_TO_MS_UNIT, - eANI_BOOLEAN_FALSE); - if (eHAL_STATUS_SUCCESS != status) + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_RESTART, REASON_PREAUTH_FAILED_FOR_ALL); + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED); + } else { - smsLog(pMac, LOGE, FL("Neighbor results refresh timer start failed with status %d"), status); +#endif + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN); + + /* Register Neighbor Lookup threshold callback with TL for UP event now */ + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("No more pre-auth candidates-" + "register UP indication with TL. RSSI = %d,"), NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); + + vosStatus = WLANTL_RegRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME, pMac); + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + //err msg + smsLog(pMac, LOGE, FL(" Couldn't register csrNeighborRoamNeighborLookupCallback UP event with TL: Status = %d"), status); + } + + /* Start the neighbor results refresh timer and transition to REPORT_SCAN state to perform scan again */ + status = palTimerStart(pMac->hHdd, pNeighborRoamInfo->neighborResultsRefreshTimer, + pNeighborRoamInfo->cfgParams.neighborResultsRefreshPeriod * PAL_TIMER_TO_MS_UNIT, + eANI_BOOLEAN_FALSE); + if (eHAL_STATUS_SUCCESS != status) + { + smsLog(pMac, LOGE, FL("Neighbor results refresh timer start failed with status %d"), status); + } } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif DEQ_PREAUTH: csrRoamDequeuePreauth(pMac); @@ -1123,14 +1188,16 @@ eHalStatus csrNeighborRoamPrepareScanProfileFilter(tpAniSirGlobal pMac, tCsrScan smsLog(pMac, LOGE, FL("Scan Filter SSID mem alloc failed")); return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_zero(pScanFilter->SSIDs.SSIDList, sizeof(tCsrSSIDInfo)); pScanFilter->SSIDs.SSIDList->handoffPermitted = 1; pScanFilter->SSIDs.SSIDList->ssidHidden = 0; pScanFilter->SSIDs.SSIDList->SSID.length = pCurProfile->SSID.length; vos_mem_copy((void *)pScanFilter->SSIDs.SSIDList->SSID.ssId, (void *)pCurProfile->SSID.ssId, pCurProfile->SSID.length); - NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Filtering for SSID %s from scan results.. SSID Length = %d"), - pScanFilter->SSIDs.SSIDList->SSID.ssId, pScanFilter->SSIDs.SSIDList->SSID.length); + NEIGHBOR_ROAM_DEBUG(pMac, LOGE, FL("Filtering for SSID %.*s from scan results," + "length of SSID = %u"), + pScanFilter->SSIDs.SSIDList->SSID.length, + pScanFilter->SSIDs.SSIDList->SSID.ssId, + pScanFilter->SSIDs.SSIDList->SSID.length); pScanFilter->authType.numEntries = 1; pScanFilter->authType.authType[0] = pCurProfile->AuthType; @@ -1272,7 +1339,11 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, /* This condition is to ensure to roam to an AP with better RSSI. if the value of RoamRssiDiff is Zero, this feature * is disabled and we continue to roam without any check*/ - if(RoamRssiDiff > 0) + if ((RoamRssiDiff > 0) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { /* * If RSSI is lower than the lookup threshold, then continue. @@ -1328,51 +1399,58 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, #endif /* WLAN_FEATURE_VOWIFI_11R */ #ifdef FEATURE_WLAN_CCX - if (pNeighborRoamInfo->isCCXAssoc) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!csrRoamIsRoamOffloadScanEnabled(pMac)) { - if (!csrNeighborRoamIsPreauthCandidate(pMac, pScanResult->BssDescriptor.bssId)) - { - smsLog(pMac, LOGE, FL("BSSID present in pre-auth fail list.. Ignoring")); - continue; - } - } - if ((pScanResult->BssDescriptor.QBSSLoad_present) && - (pScanResult->BssDescriptor.QBSSLoad_avail)) - { - if (pNeighborRoamInfo->isVOAdmitted) - { - smsLog(pMac, LOG1, FL("New AP has %x BW available"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail); - smsLog(pMac, LOG1, FL("We need %x BW available"),(unsigned int)pNeighborRoamInfo->MinQBssLoadRequired); - if (pScanResult->BssDescriptor.QBSSLoad_avail < pNeighborRoamInfo->MinQBssLoadRequired) - { - VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no bandwidth ignoring..not adding to roam list", - pScanResult->BssDescriptor.bssId[0], - pScanResult->BssDescriptor.bssId[1], - pScanResult->BssDescriptor.bssId[2], - pScanResult->BssDescriptor.bssId[3], - pScanResult->BssDescriptor.bssId[4], - pScanResult->BssDescriptor.bssId[5]); - continue; - } - } - } - else - { - smsLog(pMac, LOGE, FL("No QBss %x %x"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail, (unsigned int)pScanResult->BssDescriptor.QBSSLoad_present); - if (pNeighborRoamInfo->isVOAdmitted) - { - VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no QBSSLoad IE, ignoring..not adding to roam list", - pScanResult->BssDescriptor.bssId[0], - pScanResult->BssDescriptor.bssId[1], - pScanResult->BssDescriptor.bssId[2], - pScanResult->BssDescriptor.bssId[3], - pScanResult->BssDescriptor.bssId[4], - pScanResult->BssDescriptor.bssId[5]); - continue; - } +#endif + if (pNeighborRoamInfo->isCCXAssoc) + { + if (!csrNeighborRoamIsPreauthCandidate(pMac, pScanResult->BssDescriptor.bssId)) + { + smsLog(pMac, LOGE, FL("BSSID present in pre-auth fail list.. Ignoring")); + continue; + } + } + if ((pScanResult->BssDescriptor.QBSSLoad_present) && + (pScanResult->BssDescriptor.QBSSLoad_avail)) + { + if (pNeighborRoamInfo->isVOAdmitted) + { + smsLog(pMac, LOG1, FL("New AP has %x BW available"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail); + smsLog(pMac, LOG1, FL("We need %x BW available"),(unsigned int)pNeighborRoamInfo->MinQBssLoadRequired); + if (pScanResult->BssDescriptor.QBSSLoad_avail < pNeighborRoamInfo->MinQBssLoadRequired) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no bandwidth ignoring..not adding to roam list", + pScanResult->BssDescriptor.bssId[0], + pScanResult->BssDescriptor.bssId[1], + pScanResult->BssDescriptor.bssId[2], + pScanResult->BssDescriptor.bssId[3], + pScanResult->BssDescriptor.bssId[4], + pScanResult->BssDescriptor.bssId[5]); + continue; + } + } + } + else + { + smsLog(pMac, LOGE, FL("No QBss %x %x"), (unsigned int)pScanResult->BssDescriptor.QBSSLoad_avail, (unsigned int)pScanResult->BssDescriptor.QBSSLoad_present); + if (pNeighborRoamInfo->isVOAdmitted) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "[INFOLOG]BSSID : %02x:%02x:%02x:%02x:%02x:%02x has no QBSSLoad IE, ignoring..not adding to roam list", + pScanResult->BssDescriptor.bssId[0], + pScanResult->BssDescriptor.bssId[1], + pScanResult->BssDescriptor.bssId[2], + pScanResult->BssDescriptor.bssId[3], + pScanResult->BssDescriptor.bssId[4], + pScanResult->BssDescriptor.bssId[5]); + continue; + } + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif #endif /* FEATURE_WLAN_CCX */ #ifdef FEATURE_WLAN_LFR @@ -1390,7 +1468,11 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, /* If the received timestamp in BSS description is earlier than the scan request timestamp, skip * this result */ - if (pNeighborRoamInfo->scanRequestTimeStamp >= pScanResult->BssDescriptor.nReceivedTime) + if ((pNeighborRoamInfo->scanRequestTimeStamp >= pScanResult->BssDescriptor.nReceivedTime) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { smsLog(pMac, LOGE, FL("Ignoring BSS as it is older than the scan request timestamp")); continue; @@ -1422,7 +1504,11 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, csrLLInsertTail(&pNeighborRoamInfo->roamableAPList, &pBssInfo->List, LL_ACCESS_LOCK); #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) - if (abs(abs(CurrAPRssi) - abs(pScanResult->BssDescriptor.rssi)) >= immediateRoamRssiDiff) + if ((abs(abs(CurrAPRssi) - abs(pScanResult->BssDescriptor.rssi)) >= immediateRoamRssiDiff) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && !csrRoamIsRoamOffloadScanEnabled(pMac) +#endif + ) { VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: [INFOLOG] potential candidate to roam immediately (diff=%d, expected=%d)", @@ -1430,6 +1516,14 @@ static tANI_BOOLEAN csrNeighborRoamProcessScanResults(tpAniSirGlobal pMac, immediateRoamRssiDiff); roamNow = eANI_BOOLEAN_TRUE; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /* If we are here means, FW already found candidates to roam, so we are + good to go with pre-auth */ + if(csrRoamIsRoamOffloadScanEnabled(pMac)) + { + roamNow = eANI_BOOLEAN_TRUE; + } +#endif #endif } @@ -1521,17 +1615,20 @@ static VOS_STATUS csrNeighborRoamHandleEmptyScanResult(tpAniSirGlobal pMac) { pNeighborRoamInfo->uEmptyScanCount = eFifthEmptyScan; } - if ((abs(pNeighborRoamInfo->lookupDOWNRssi) > - abs(pNeighborRoamInfo->cfgParams.neighborReassocThreshold)) && + if (((0 != pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels) || + (abs(pNeighborRoamInfo->lookupDOWNRssi) > + abs(pNeighborRoamInfo->cfgParams.neighborReassocThreshold))) && ((pNeighborRoamInfo->uEmptyScanCount == eSecondEmptyScan) || (pNeighborRoamInfo->uEmptyScanCount == eFourthEmptyScan))) { /* * If the scan was triggered due to lookupDOWNRssi > reassoc threshold, * then it would be a contiguous scan on all valid non-DFS channels. - * In this mode, there is no need to trigger an immediate scan upon - * empty scan results for the second and fourth time (which would - * be equivalent to scanning on channels in non-occupied list). + * If channels are configured in INI, then only those channels need + * to be scanned. + * In either of these modes, there is no need to trigger an immediate + * scan upon empty scan results for the second and fourth time (which + * would be equivalent to scanning on channels in non-occupied list). * Incrementing uEmptyScanCount will correspond to skipping this step. * NOTE: double increment of uEmptyScanCount corresponds to completion * of scans on all valid channels. @@ -1631,7 +1728,7 @@ static VOS_STATUS csrNeighborRoamHandleEmptyScanResult(tpAniSirGlobal pMac) (pNeighborRoamInfo->cfgParams.emptyScanRefreshPeriod)); } } - else + else if (eThirdEmptyScan == pNeighborRoamInfo->uEmptyScanCount) { /* Start neighbor scan results refresh timer */ if (eHAL_STATUS_SUCCESS != @@ -1673,7 +1770,11 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) #if defined (WLAN_FEATURE_VOWIFI_11R) || defined (FEATURE_WLAN_CCX) || defined(FEATURE_WLAN_LFR) /* If the state is REPORT_SCAN, then this must be the scan after the REPORT_QUERY state. So, we should use the BSSID filter made out of neighbor reports */ - if (eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) + if ((eCSR_NEIGHBOR_ROAM_STATE_REPORT_SCAN == pNeighborRoamInfo->neighborRoamState) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + && (!csrRoamIsRoamOffloadScanEnabled(pMac)) +#endif + ) { hstatus = csrNeighborRoamBssIdScanFilter(pMac, &scanFilter); NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("11R or CCX Association: Prepare scan filter status with neighbor AP = %d"), hstatus); @@ -1703,8 +1804,12 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) tempVal = csrLLCount(&pNeighborRoamInfo->roamableAPList); - switch(pNeighborRoamInfo->neighborRoamState) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!csrRoamIsRoamOffloadScanEnabled(pMac)) { +#endif + switch(pNeighborRoamInfo->neighborRoamState) + { case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: if (tempVal) { @@ -1783,7 +1888,10 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) // Lets just exit out silently. return eHAL_STATUS_SUCCESS; + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif if (tempVal) { @@ -1791,21 +1899,28 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) if (roamNow) { - NEIGHBOR_ROAM_DEBUG(pMac, LOG2, - FL("Immediate roam-deregister UP indication. RSSI = %d"), - NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); - - vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, - (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), - WLANTL_HO_THRESHOLD_UP, - csrNeighborRoamNeighborLookupUPCallback, - VOS_MODULE_ID_SME); - - if(!VOS_IS_STATUS_SUCCESS(vosStatus)) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!csrRoamIsRoamOffloadScanEnabled(pMac)) { - smsLog(pMac, LOGW, - FL("Couldn't deregister lookup UP callback with TL: Status = %d"), vosStatus); +#endif + NEIGHBOR_ROAM_DEBUG(pMac, LOG2, + FL("Immediate roam-deregister UP indication. RSSI = %d"), + NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1)); + + vosStatus = WLANTL_DeregRSSIIndicationCB(pMac->roam.gVosContext, + (v_S7_t)NEIGHBOR_ROAM_LOOKUP_UP_THRESHOLD * (-1), + WLANTL_HO_THRESHOLD_UP, + csrNeighborRoamNeighborLookupUPCallback, + VOS_MODULE_ID_SME); + + if(!VOS_IS_STATUS_SUCCESS(vosStatus)) + { + smsLog(pMac, LOGW, + FL("Couldn't deregister lookup UP callback with TL: Status = %d"), vosStatus); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD } +#endif csrNeighborRoamTriggerHandoff(pMac, pNeighborRoamInfo); return eHAL_STATUS_SUCCESS; @@ -1841,6 +1956,18 @@ static eHalStatus csrNeighborRoamProcessScanComplete (tpAniSirGlobal pMac) } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +if (csrRoamIsRoamOffloadScanEnabled(pMac)) + { + if (!tempVal || !roamNow) + { + /* There is no candidate or We are not roaming Now. + * Inform the FW to restart Roam Offload Scan */ + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_RESTART, REASON_NO_CAND_FOUND_OR_NOT_ROAMING_NOW); + CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED); + } + } +#endif return eHAL_STATUS_SUCCESS; } @@ -1872,13 +1999,28 @@ static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; tANI_U8 currentChanIndex; eHalStatus hstatus; +#ifdef FEATURE_WLAN_LFR + tANI_U32 sessionId = CSR_SESSION_ID_INVALID; + if (NULL != pContext) + { + sessionId = *((tANI_U32*)pContext); + if (!csrRoamIsFastRoamEnabled(pMac,sessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + } +#endif pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_FALSE; /* This can happen when we receive a UP event from TL in any of the scan states. Silently ignore it */ if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState) { smsLog(pMac, LOGE, FL("Received in CONNECTED state. Must be because a UP event from TL after issuing scan request. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_SUCCESS; } @@ -1893,6 +2035,8 @@ static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void else { smsLog(pMac, LOG1, FL("Received during clean-up. Silently ignore scan completion event.")); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_SUCCESS; } @@ -1910,6 +2054,8 @@ static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void if (eHAL_STATUS_SUCCESS != hstatus) { smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_FAILURE; } } @@ -1928,11 +2074,64 @@ static eHalStatus csrNeighborRoamScanRequestCallback(tHalHandle halHandle, void vos_mem_free(pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList); pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.ChannelList = NULL; pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo.numOfChannels = 0; + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_FAILURE; } } + + if (NULL != pContext) + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamScanResultRequestCallback + + \brief This function is the callback function registered in csrScanRequestLfrResult() to + indicate the completion of scan. If scan is completed for all the channels in + the channel list, this function gets the scan result and treats them as candidates + + \param halHandle - The handle returned by macOpen. + pContext - not used + scanId - not used + status - not used + + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +static eHalStatus csrNeighborRoamScanResultRequestCallback(tHalHandle halHandle, void *pContext, + tANI_U32 scanId, eCsrScanStatus status) +{ + tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; + eHalStatus hstatus; + + smsLog(pMac, LOG2, FL("called ")); + pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_FALSE; + + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGW, FL("Received in not CONNECTED state. Ignore it")); + return eHAL_STATUS_SUCCESS; + } + + /* Now we have completed scanning the channel list. We have get the result by applying appropriate filter + sort the results based on neighborScore and RSSI and select the best candidate out of the list */ + + hstatus = csrNeighborRoamProcessScanComplete(pMac); + + if (eHAL_STATUS_SUCCESS != hstatus) + { + smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); + return eHAL_STATUS_FAILURE; + } return eHAL_STATUS_SUCCESS; } +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD #ifdef FEATURE_WLAN_LFR static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHandle, @@ -1941,6 +2140,18 @@ static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHan tpAniSirGlobal pMac = (tpAniSirGlobal) halHandle; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; eHalStatus hstatus = eHAL_STATUS_SUCCESS; + tANI_U32 sessionId = CSR_SESSION_ID_INVALID; + + if (NULL != pContext) + { + sessionId = *((tANI_U32*)pContext); + if (!csrRoamIsFastRoamEnabled(pMac,sessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + vos_mem_free(pContext); + return eHAL_STATUS_SUCCESS; + } + } pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_FALSE; @@ -1948,12 +2159,16 @@ static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHan if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED == pNeighborRoamInfo->neighborRoamState) { smsLog(pMac, LOGE, FL("Received in CONNECTED state. Must be because a UP event from TL after issuing scan request. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_SUCCESS; } if (eCSR_NEIGHBOR_ROAM_STATE_INIT == pNeighborRoamInfo->neighborRoamState) { smsLog(pMac, LOGE, FL("Received in INIT state. Must have disconnected. Ignore it")); + if (NULL != pContext) + vos_mem_free(pContext); return eHAL_STATUS_SUCCESS; } @@ -1965,6 +2180,9 @@ static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHan smsLog(pMac, LOGE, FL("Neighbor scan process complete failed with status %d"), hstatus); } + if (NULL != pContext) + vos_mem_free(pContext); + return hstatus; } #endif @@ -1984,12 +2202,14 @@ static eHalStatus csrNeighborRoamContiguousScanRequestCallback(tHalHandle halHan ---------------------------------------------------------------------------*/ eHalStatus csrNeighborRoamIssueBgScanRequest(tpAniSirGlobal pMac, tCsrBGScanRequest *pBgScanParams, + tANI_U32 sessionId, csrScanCompleteCallback callbackfn) { eHalStatus status = eHAL_STATUS_SUCCESS; tANI_U32 scanId; tCsrScanRequest scanReq; tANI_U8 channel; + void * userData = NULL; if (1 == pBgScanParams->ChannelInfo.numOfChannels) NEIGHBOR_ROAM_DEBUG(pMac, LOGW, FL("Channel = %d, ChanIndex = %d"), @@ -2029,12 +2249,22 @@ eHalStatus csrNeighborRoamIssueBgScanRequest(tpAniSirGlobal pMac, scanReq.requestType = eCSR_SCAN_HO_BG_SCAN; scanReq.maxChnTime = pBgScanParams->maxChnTime; scanReq.minChnTime = pBgScanParams->minChnTime; + + userData = vos_mem_malloc(sizeof(tANI_U32)); + if (NULL == userData) + { + smsLog(pMac, LOGE, FL("Failed to allocate memory for scan request")); + vos_mem_free(scanReq.SSIDs.SSIDList); + return eHAL_STATUS_FAILURE; + } + *((tANI_U32*)userData) = sessionId; status = csrScanRequest(pMac, CSR_SESSION_ID_INVALID, &scanReq, - &scanId, callbackfn, NULL); + &scanId, callbackfn, (void *) userData); if (eHAL_STATUS_SUCCESS != status) { smsLog(pMac, LOGE, FL("CSR Scan Request failed with status %d"), status); vos_mem_free(scanReq.SSIDs.SSIDList); + vos_mem_free(userData); return status; } pMac->roam.neighborRoamInfo.scanRspPending = eANI_BOOLEAN_TRUE; @@ -2078,7 +2308,7 @@ static void csrNeighborRoamFillNonChannelBgScanParams (tpAniSirGlobal pMac, \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise ---------------------------------------------------------------------------*/ -eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac) +eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac, tANI_U32 sessionId) { eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; @@ -2120,8 +2350,8 @@ eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac) csrNeighborRoamFillNonChannelBgScanParams(pMac, &bgScanParams); - status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams, - csrNeighborRoamScanRequestCallback); + status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams, + sessionId, csrNeighborRoamScanRequestCallback); if (eHAL_STATUS_SUCCESS != status) { smsLog(pMac, LOGE, FL("Issue of BG Scan request failed: Status = %d"), status); @@ -2157,7 +2387,7 @@ eHalStatus csrNeighborRoamPerformBgScan(tpAniSirGlobal pMac) } #ifdef FEATURE_WLAN_LFR -eHalStatus csrNeighborRoamPerformContiguousBgScan(tpAniSirGlobal pMac) +eHalStatus csrNeighborRoamPerformContiguousBgScan(tpAniSirGlobal pMac, tANI_U32 sessionId) { eHalStatus status = eHAL_STATUS_SUCCESS; tCsrBGScanRequest bgScanParams; @@ -2221,7 +2451,7 @@ eHalStatus csrNeighborRoamPerformContiguousBgScan(tpAniSirGlobal pMac) csrNeighborRoamFillNonChannelBgScanParams(pMac, &bgScanParams); status = csrNeighborRoamIssueBgScanRequest(pMac, &bgScanParams, - csrNeighborRoamContiguousScanRequestCallback); + sessionId, csrNeighborRoamContiguousScanRequestCallback); vos_mem_free( channelList ); @@ -2270,7 +2500,7 @@ void csrNeighborRoamNeighborScanTimerCallback(void *pv) switch(pNeighborRoamInfo->prevNeighborRoamState) { case eCSR_NEIGHBOR_ROAM_STATE_REPORT_QUERY: - csrNeighborRoamPerformBgScan(pMac); + csrNeighborRoamPerformBgScan(pMac, sessionId); break; default: smsLog(pMac, LOGE, FL("Neighbor scan callback received in state %d, prev state = %d"), @@ -2280,7 +2510,7 @@ void csrNeighborRoamNeighborScanTimerCallback(void *pv) break; #endif /* WLAN_FEATURE_VOWIFI_11R */ case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: - csrNeighborRoamPerformBgScan(pMac); + csrNeighborRoamPerformBgScan(pMac, sessionId); break; default: break; @@ -2509,11 +2739,18 @@ VOS_STATUS csrNeighborRoamMergeChannelLists( int numChannels = outputNumOfChannels; // Check for NULL pointer - if (!pInputChannelList) return eHAL_STATUS_E_NULL_VALUE; + if (!pInputChannelList) return VOS_STATUS_E_INVAL; // Check for NULL pointer - if (!pOutputChannelList) return eHAL_STATUS_E_NULL_VALUE; + if (!pOutputChannelList) return VOS_STATUS_E_INVAL; + if (inputNumOfChannels > WNI_CFG_VALID_CHANNEL_LIST_LEN) + { + VOS_TRACE (VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: Wrong Number of Input Channels %d", + __func__, inputNumOfChannels); + return VOS_STATUS_E_INVAL; + } // Add the "new" channels in the input list to the end of the output list. for (i = 0; i < inputNumOfChannels; i++) { @@ -2538,7 +2775,7 @@ VOS_STATUS csrNeighborRoamMergeChannelLists( // Return final number of channels *pMergedOutputNumOfChannels = numChannels; - return eHAL_STATUS_SUCCESS; + return VOS_STATUS_SUCCESS; } /* --------------------------------------------------------------------------- @@ -2660,6 +2897,12 @@ VOS_STATUS csrNeighborRoamCreateChanListFromNeighborReport(tpAniSirGlobal pMac) smsLog(pMac, LOG1, FL("IAPP Neighbor list callback received as expected in state %d."), pNeighborRoamInfo->neighborRoamState); pNeighborRoamInfo->roamChannelInfo.IAPPNeighborListReceived = eANI_BOOLEAN_TRUE; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CHANNEL_LIST_CHANGED); + } +#endif } pNeighborRoamInfo->roamChannelInfo.currentChanIndex = 0; pNeighborRoamInfo->roamChannelInfo.chanListScanInProgress = eANI_BOOLEAN_TRUE; @@ -2863,8 +3106,6 @@ tANI_BOOLEAN csrNeighborRoamIsNewConnectedProfile( if (fNew) { smsLog(pMac, LOG1, FL("Prev roam profile did not match current")); - csrRoamFreeConnectProfile(pMac, pPrevProfile); - csrRoamGetConnectProfile(pMac, sessionId, pPrevProfile); } else { @@ -2972,7 +3213,9 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) int numOfChannels = 0; tANI_U8 channelList[WNI_CFG_VALID_CHANNEL_LIST_LEN]; tpCsrChannelInfo currChannelListInfo; - +#ifdef FEATURE_WLAN_LFR + tANI_U32 sessionId = pNeighborRoamInfo->csrSessionId; +#endif currChannelListInfo = &pNeighborRoamInfo->roamChannelInfo.currentChannelListInfo; if ( @@ -3022,13 +3265,16 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) currChannelListInfo->ChannelList = vos_mem_malloc(numOfChannels*sizeof(tANI_U8)); - if (NULL == currChannelListInfo->ChannelList) - { - smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); - return VOS_STATUS_E_RESOURCES; - } - - vos_mem_copy(currChannelListInfo->ChannelList, + if (NULL == currChannelListInfo->ChannelList) + { + smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); + return VOS_STATUS_E_RESOURCES; + } + if (WNI_CFG_VALID_CHANNEL_LIST_LEN < numOfChannels) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } + vos_mem_copy(currChannelListInfo->ChannelList, channelList, numOfChannels * sizeof(tANI_U8)); } #ifdef FEATURE_WLAN_LFR @@ -3055,7 +3301,7 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) * purge non-P2P results from the past */ csrScanFlushSelectiveResult(pMac, VOS_FALSE); - csrNeighborRoamPerformContiguousBgScan(pMac); + csrNeighborRoamPerformContiguousBgScan(pMac, sessionId); /* Transition to CFG_CHAN_LIST_SCAN */ CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN); @@ -3109,6 +3355,10 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) smsLog(pMac, LOGE, FL("Memory allocation for Channel list failed")); return VOS_STATUS_E_RESOURCES; } + if (WNI_CFG_VALID_CHANNEL_LIST_LEN < numOfChannels) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } vos_mem_copy(currChannelListInfo->ChannelList, channelList, numOfChannels * sizeof(tANI_U8)); @@ -3171,9 +3421,17 @@ VOS_STATUS csrNeighborRoamTransitToCFGChanScan(tpAniSirGlobal pMac) return VOS_STATUS_E_RESOURCES; } #ifdef FEATURE_WLAN_LFR + if (WNI_CFG_VALID_CHANNEL_LIST_LEN < numOfChannels) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } vos_mem_copy(currChannelListInfo->ChannelList, channelList, numOfChannels * sizeof(tANI_U8)); #else + if (WNI_CFG_VALID_CHANNEL_LIST_LEN < numOfChannels) + { + numOfChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN; + } vos_mem_copy(currChannelListInfo->ChannelList, (tANI_U8 *)pMac->roam.validChannelList, numOfChannels * sizeof(tANI_U8)); @@ -3251,7 +3509,13 @@ VOS_STATUS csrNeighborRoamNeighborLookupUpEvent(tpAniSirGlobal pMac) /* Recheck whether the below check is needed. */ if (pNeighborRoamInfo->neighborRoamState != eCSR_NEIGHBOR_ROAM_STATE_CONNECTED) CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_CONNECTED) - +#ifdef FEATURE_WLAN_LFR + if (!csrRoamIsFastRoamEnabled(pMac,pMac->roam.neighborRoamInfo.csrSessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + return eHAL_STATUS_SUCCESS; + } +#endif /* Reset all the neighbor roam info control variables. Free all the allocated memory. It is like we are just associated now */ csrNeighborRoamResetConnectedStateControlInfo(pMac); @@ -3312,7 +3576,13 @@ VOS_STATUS csrNeighborRoamNeighborLookupDownEvent(tpAniSirGlobal pMac) //err msg smsLog(pMac, LOGW, FL(" Couldn't Deregister csrNeighborRoamNeighborLookupCallback DOWN event from TL: Status = %d"), vosStatus); } - +#ifdef FEATURE_WLAN_LFR + if (!csrRoamIsFastRoamEnabled(pMac,pMac->roam.neighborRoamInfo.csrSessionId)) + { + smsLog(pMac, LOGE, FL("Received when fast roam is disabled. Ignore it")); + return eHAL_STATUS_SUCCESS; + } +#endif #if defined WLAN_FEATURE_VOWIFI_11R && defined WLAN_FEATURE_VOWIFI if ((pNeighborRoamInfo->is11rAssoc) && (pMac->rrm.rrmSmeContext.rrmConfig.rrmEnabled)) @@ -3464,14 +3734,35 @@ extern int dumpCmdRSSI; eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessionId) { tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; +#ifdef FEATURE_WLAN_LFR + tCsrRoamConnectedProfile *pPrevProfile = &pNeighborRoamInfo->prevConnProfile; +#endif + tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId); - smsLog(pMac, LOGE, FL("Disconnect indication on session %d in state %d (sub-state %d)"), - sessionId, pNeighborRoamInfo->neighborRoamState, - pMac->roam.curSubState[sessionId]); + smsLog(pMac, LOGE, FL("Disconnect indication on session %d in state %d"), + sessionId, pNeighborRoamInfo->neighborRoamState); +#ifdef FEATURE_WLAN_LFR + /*Free the current previous profile and move the current profile to prev profile.*/ + csrRoamFreeConnectProfile(pMac, pPrevProfile); + csrRoamGetConnectProfile(pMac, sessionId, pPrevProfile); +#endif + if (NULL != pSession) + { + if (NULL != pSession->pCurRoamProfile) + { + if (VOS_STA_MODE != pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona) + { + smsLog(pMac, LOGE, FL("Ignoring Disconnect indication received from a non STA persona." + "sessionId: %d, csrPersonna %d"), sessionId, + (int)pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona); + return eHAL_STATUS_SUCCESS; + } + } + } + #ifdef FEATURE_WLAN_CCX { - tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId); if (pSession->connectedProfile.isCCXAssoc) { vos_mem_copy(&pSession->prevApSSID, &pSession->connectedProfile.SSID, sizeof(tSirMacSSid)); @@ -3512,19 +3803,40 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio case eCSR_NEIGHBOR_ROAM_STATE_INIT: csrNeighborRoamResetInitStateControlInfo(pMac); - csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!pMac->roam.configParam.isRoamOffloadScanEnabled) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif break; case eCSR_NEIGHBOR_ROAM_STATE_CONNECTED: CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) csrNeighborRoamResetConnectedStateControlInfo(pMac); - csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if(!pMac->roam.configParam.isRoamOffloadScanEnabled) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif break; case eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN: CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT); csrNeighborRoamResetCfgListChanScanControlInfo(pMac); - csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!pMac->roam.configParam.isRoamOffloadScanEnabled) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif break; case eCSR_NEIGHBOR_ROAM_STATE_PREAUTH_DONE: @@ -3535,7 +3847,14 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) csrNeighborRoamResetPreauthControlInfo(pMac); csrNeighborRoamResetReportScanStateControlInfo(pMac); - csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (!pMac->roam.configParam.isRoamOffloadScanEnabled) + { +#endif + csrNeighborRoamDeregAllRssiIndication(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif break; default: @@ -3544,6 +3863,11 @@ eHalStatus csrNeighborRoamIndicateDisconnect(tpAniSirGlobal pMac, tANI_U8 sessio CSR_NEIGHBOR_ROAM_STATE_TRANSITION(eCSR_NEIGHBOR_ROAM_STATE_INIT) break; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + /*Inform the Firmware to STOP Scanning as the host has a disconnect.*/ + if (csrRoamIsStaMode(pMac, sessionId)) + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_STOP, REASON_DISCONNECTED); +#endif return eHAL_STATUS_SUCCESS; } @@ -3572,8 +3896,24 @@ eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, tANI_U8 sessionId int init_ft_flag = FALSE; #endif + if (NULL == pNeighborRoamInfo) + { + return eHAL_STATUS_FAILURE; + } smsLog(pMac, LOG2, FL("Connect indication received with session id %d in state %d"), sessionId, pNeighborRoamInfo->neighborRoamState); + // Bail out if this is NOT a STA persona or if a concurrent session is running + if ((pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona != VOS_STA_MODE)|| + csrIsConcurrentSessionRunning(pMac)) + { + smsLog(pMac, LOGE, FL("Ignoring Connect indication received from a non STA persona." + "sessionId: %d, csrPersonna %d, is multisession %d"), + sessionId, + (int)pMac->roam.roamSession[sessionId].pCurRoamProfile->csrPersona, + csrIsConcurrentSessionRunning(pMac)); + return eHAL_STATUS_SUCCESS; + } + switch (pNeighborRoamInfo->neighborRoamState) { case eCSR_NEIGHBOR_ROAM_STATE_REASSOCIATING: @@ -3662,6 +4002,16 @@ eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, tANI_U8 sessionId /* Initialize all the data structures needed for the 11r FT Preauth */ pNeighborRoamInfo->FTRoamInfo.currentNeighborRptRetryNum = 0; csrNeighborRoamPurgePreauthFailedList(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + /*If this is not a INFRA type BSS, then do not send the command + * down to firmware.Do not send the START command for other session + * connections.*/ + if(csrRoamIsStaMode(pMac, sessionId)) + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_START, REASON_CONNECT); + } else { +#endif NEIGHBOR_ROAM_DEBUG(pMac, LOG2, FL("Registering neighbor lookup DOWN event with TL, RSSI = %d"), pNeighborRoamInfo->currentNeighborLookupThreshold); /* Register Neighbor Lookup threshold callback with TL for DOWN event only */ @@ -3678,6 +4028,9 @@ eHalStatus csrNeighborRoamIndicateConnect(tpAniSirGlobal pMac, tANI_U8 sessionId smsLog(pMac, LOGW, FL(" Couldn't register csrNeighborRoamNeighborLookupDOWNCallback with TL: Status = %d"), vstatus); status = eHAL_STATUS_FAILURE; } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + } +#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */ } #endif break; @@ -4211,5 +4564,44 @@ tANI_BOOLEAN csrNeighborMiddleOfRoaming (tHalHandle hHal) (eCSR_NEIGHBOR_ROAM_STATE_CFG_CHAN_LIST_SCAN == pMac->roam.neighborRoamInfo.neighborRoamState); return (val); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* --------------------------------------------------------------------------- + + \fn csrNeighborRoamCandidateFoundIndHdlr + + \brief This function is called by CSR as soon as TL posts the candidate + found indication to SME via MC thread + + \param pMac - The handle returned by macOpen. + pMsg - Msg sent by PE + \return eHAL_STATUS_SUCCESS on success, corresponding error code otherwise + +---------------------------------------------------------------------------*/ +eHalStatus csrNeighborRoamCandidateFoundIndHdlr(tpAniSirGlobal pMac, void* pMsg) +{ + tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; + eHalStatus status = eHAL_STATUS_SUCCESS; + /* we must be in connected state, if not ignore it */ + if (eCSR_NEIGHBOR_ROAM_STATE_CONNECTED != pNeighborRoamInfo->neighborRoamState) + { + smsLog(pMac, LOGW, FL("Received in not CONNECTED state. Ignore it")); + status = eHAL_STATUS_FAILURE; + } + else + { + /* We are about to start a fresh scan cycle, + * purge non-P2P results from the past */ + csrScanFlushSelectiveResult(pMac, VOS_FALSE); + /* Once it gets the candidates found indication from PE, will issue a scan + - req to PE with “freshScan” in scanreq structure set as follows: + 0x42 - Return & purge LFR scan results + */ + status = csrScanRequestLfrResult(pMac, pNeighborRoamInfo->csrSessionId, + csrNeighborRoamScanResultRequestCallback, pMac); + } + + return status; +} +#endif //WLAN_FEATURE_ROAM_SCAN_OFFLOAD #endif /* WLAN_FEATURE_NEIGHBOR_ROAMING */ diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrTdlsProcess.c b/drivers/staging/prima/CORE/SME/src/csr/csrTdlsProcess.c index dccbd5e929c..697ae1f585e 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrTdlsProcess.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrTdlsProcess.c @@ -47,8 +47,12 @@ Implementation for the TDLS interface to PE. - Copyright (C) 2010 Qualcomm, Incorporated - + Copyright (c) 2013 Qualcomm Atheros, Inc.All Rights Reserved. + Qualcomm Atheros Confidential and Proprietary. + + Copyright (c) 2010 Qualcomm Technologies, Inc.All Rights Reserved. + Qualcomm Technologies Confidential and Proprietary + ========================================================================== */ @@ -207,11 +211,19 @@ eHalStatus csrTdlsChangePeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr pstaParams->extn_capability, sizeof(pstaParams->extn_capability)); - palCopyMemory(pMac->hHdd, &tdlsAddStaCmdInfo->HTCap, - &pstaParams->HTCap, sizeof(pstaParams->HTCap)); + tdlsAddStaCmdInfo->htcap_present = pstaParams->htcap_present; + if(pstaParams->htcap_present) + palCopyMemory(pMac->hHdd, &tdlsAddStaCmdInfo->HTCap, + &pstaParams->HTCap, sizeof(pstaParams->HTCap)); + else + palZeroMemory(pMac->hHdd, &tdlsAddStaCmdInfo->HTCap, sizeof(pstaParams->HTCap)); - palCopyMemory(pMac->hHdd, &tdlsAddStaCmdInfo->VHTCap, - &pstaParams->VHTCap, sizeof(pstaParams->VHTCap)); + tdlsAddStaCmdInfo->vhtcap_present = pstaParams->vhtcap_present; + if(pstaParams->vhtcap_present) + palCopyMemory(pMac->hHdd, &tdlsAddStaCmdInfo->VHTCap, + &pstaParams->VHTCap, sizeof(pstaParams->VHTCap)); + else + palZeroMemory(pMac->hHdd, &tdlsAddStaCmdInfo->VHTCap, sizeof(pstaParams->VHTCap)); tdlsAddStaCmdInfo->supportedRatesLen = pstaParams->supported_rates_len; @@ -436,12 +448,23 @@ eHalStatus csrTdlsProcessSendMgmt( tpAniSirGlobal pMac, tSmeCmd *cmd ) tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); eHalStatus status = eHAL_STATUS_FAILURE; + if (NULL == pSession) + { + return eHAL_STATUS_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS Description is not present") ); + return eHAL_STATUS_FAILURE; + } + status = palAllocateMemory( pMac->hHdd, (void **)&tdlsSendMgmtReq, (sizeof(tSirTdlsSendMgmtReq) + tdlsSendMgmtCmdInfo->len ) ); - if(!HAL_STATUS_SUCCESS( status ) ) + if (!HAL_STATUS_SUCCESS( status ) ) { - smsLog( pMac, LOGE, FL("alloc failed ") ); + smsLog( pMac, LOGE, FL("alloc failed") ); VOS_ASSERT(0) ; return status ; } @@ -452,16 +475,10 @@ eHalStatus csrTdlsProcessSendMgmt( tpAniSirGlobal pMac, tSmeCmd *cmd ) tdlsSendMgmtReq->dialog = tdlsSendMgmtCmdInfo->dialog ; tdlsSendMgmtReq->statusCode = tdlsSendMgmtCmdInfo->statusCode ; tdlsSendMgmtReq->responder = tdlsSendMgmtCmdInfo->responder; - if (pSession->pConnectBssDesc) - { - palCopyMemory(pMac->hHdd, tdlsSendMgmtReq->bssid, pSession->pConnectBssDesc->bssId, - sizeof (tSirMacAddr)); - } - else - { - smsLog( pMac, LOGE, FL("%s: BSS Description is not present\n"), __func__); - return eHAL_STATUS_FAILURE; - } + + palCopyMemory(pMac->hHdd, tdlsSendMgmtReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); + palCopyMemory(pMac->hHdd, tdlsSendMgmtReq->peerMac, tdlsSendMgmtCmdInfo->peerMac, sizeof(tSirMacAddr)) ; @@ -496,12 +513,23 @@ eHalStatus csrTdlsProcessAddSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); eHalStatus status = eHAL_STATUS_FAILURE; + if (NULL == pSession) + { + return eHAL_STATUS_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS description is not present") ); + return eHAL_STATUS_FAILURE; + } + status = palAllocateMemory( pMac->hHdd, (void **)&tdlsAddStaReq, (sizeof(tSirTdlsAddStaReq) ) ); - if(!HAL_STATUS_SUCCESS( status ) ) + if (!HAL_STATUS_SUCCESS( status ) ) { - smsLog( pMac, LOGE, FL("alloc failed ") ); + smsLog( pMac, LOGE, FL("alloc failed") ); VOS_ASSERT(0) ; return status ; } @@ -510,16 +538,8 @@ eHalStatus csrTdlsProcessAddSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) //Using dialog as transactionId. This can be used to match response with request tdlsAddStaReq->transactionId = 0; - if (pSession->pConnectBssDesc) - { - palCopyMemory(pMac->hHdd, tdlsAddStaReq->bssid, pSession->pConnectBssDesc->bssId, - sizeof (tSirMacAddr)); - } - else - { - smsLog( pMac, LOGE, FL("%s: BSS description is not present\n"), __func__); - return eHAL_STATUS_FAILURE; - } + palCopyMemory(pMac->hHdd, tdlsAddStaReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); palCopyMemory(pMac->hHdd, tdlsAddStaReq->peerMac, tdlsAddStaCmdInfo->peerMac, sizeof(tSirMacAddr)) ; @@ -531,8 +551,10 @@ eHalStatus csrTdlsProcessAddSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) palCopyMemory(pMac->hHdd, tdlsAddStaReq->extn_capability, tdlsAddStaCmdInfo->extnCapability, SIR_MAC_MAX_EXTN_CAP); + tdlsAddStaReq->htcap_present = tdlsAddStaCmdInfo->htcap_present; palCopyMemory(pMac->hHdd, &tdlsAddStaReq->htCap, &tdlsAddStaCmdInfo->HTCap, sizeof(tdlsAddStaCmdInfo->HTCap)); + tdlsAddStaReq->vhtcap_present = tdlsAddStaCmdInfo->vhtcap_present; palCopyMemory(pMac->hHdd, &tdlsAddStaReq->vhtCap, &tdlsAddStaCmdInfo->VHTCap, sizeof(tdlsAddStaCmdInfo->VHTCap)); tdlsAddStaReq->supported_rates_length = tdlsAddStaCmdInfo->supportedRatesLen; @@ -557,28 +579,33 @@ eHalStatus csrTdlsProcessDelSta( tpAniSirGlobal pMac, tSmeCmd *cmd ) tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, cmd->sessionId ); eHalStatus status = eHAL_STATUS_FAILURE; + if (NULL == pSession) + { + return eHAL_STATUS_FAILURE; + } + + if (NULL == pSession->pConnectBssDesc) + { + smsLog( pMac, LOGE, FL("BSS description is not present") ); + return eHAL_STATUS_FAILURE; + } + status = palAllocateMemory( pMac->hHdd, (void **)&tdlsDelStaReq, (sizeof(tSirTdlsDelStaReq) ) ); - if(!HAL_STATUS_SUCCESS( status ) ) + if (!HAL_STATUS_SUCCESS( status ) ) { - smsLog( pMac, LOGE, FL("alloc failed ") ); + smsLog( pMac, LOGE, FL("alloc failed") ); VOS_ASSERT(0) ; return status ; } tdlsDelStaReq->sessionId = cmd->sessionId; //Using dialog as transactionId. This can be used to match response with request tdlsDelStaReq->transactionId = 0; - if (pSession->pConnectBssDesc) - { - palCopyMemory(pMac->hHdd, tdlsDelStaReq->bssid, pSession->pConnectBssDesc->bssId, - sizeof (tSirMacAddr)); - } - else - { - smsLog( pMac, LOGE, FL("%s: BSS description is not present\n"), __func__); - return eHAL_STATUS_FAILURE; - } + + palCopyMemory(pMac->hHdd, tdlsDelStaReq->bssid, + pSession->pConnectBssDesc->bssId, sizeof (tSirMacAddr)); + palCopyMemory(pMac->hHdd, tdlsDelStaReq->peerMac, tdlsDelStaCmdInfo->peerMac, sizeof(tSirMacAddr)) ; @@ -912,12 +939,12 @@ eHalStatus tdlsMsgProcessor(tpAniSirGlobal pMac, v_U16_t msgType, */ if (addStaRsp->tdlsAddOper == TDLS_OPER_ADD) roamResult = eCSR_ROAM_RESULT_ADD_TDLS_PEER; - else if (addStaRsp->tdlsAddOper == TDLS_OPER_UPDATE) + else /* addStaRsp->tdlsAddOper must be TDLS_OPER_UPDATE */ roamResult = eCSR_ROAM_RESULT_UPDATE_TDLS_PEER; csrRoamCallCallback(pMac, addStaRsp->sessionId, &roamInfo, 0, - eCSR_ROAM_TDLS_STATUS_UPDATE, - roamResult); - + eCSR_ROAM_TDLS_STATUS_UPDATE, + roamResult); + /* remove pending eSmeCommandTdlsDiscovery command */ csrTdlsRemoveSmeCmd(pMac, eSmeCommandTdlsAddPeer) ; } diff --git a/drivers/staging/prima/CORE/SME/src/csr/csrUtil.c b/drivers/staging/prima/CORE/SME/src/csr/csrUtil.c index 51a4bb3a544..7e38dc47de4 100644 --- a/drivers/staging/prima/CORE/SME/src/csr/csrUtil.c +++ b/drivers/staging/prima/CORE/SME/src/csr/csrUtil.c @@ -1,8 +1,46 @@ /* -* Copyright (c) 2011-2013 Qualcomm Atheros, Inc. -* All Rights Reserved. -* Qualcomm Atheros Confidential and Proprietary. -*/ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + + + /** ------------------------------------------------------------------------- * ------------------------------------------------------------------------- * @@ -50,13 +88,8 @@ tANI_U8 csrRSNOui[][ CSR_RSN_OUI_SIZE ] = { { 0x00, 0x0F, 0xAC, 0x03 }, // Reserved { 0x00, 0x0F, 0xAC, 0x04 }, // AES-CCMP { 0x00, 0x0F, 0xAC, 0x05 }, // WEP-104 -#ifdef WLAN_FEATURE_11W - { 0x00, 0x0F, 0xAC, 0x06 }, // BIP(encryption type) or (RSN-PSK-SHA256(authentication type) -#endif -#ifdef FEATURE_WLAN_CCX - { 0x00, 0x40, 0x96, 0x00 } // CCKM -#endif /* FEATURE_WLAN_CCX */ - + { 0x00, 0x40, 0x96, 0x00 }, // CCKM + { 0x00, 0x0F, 0xAC, 0x06 } // BIP (encryption type) or RSN-PSK-SHA256 (authentication type) }; #ifdef FEATURE_WLAN_WAPI @@ -2674,9 +2707,6 @@ tANI_BOOLEAN csrIsProfileRSN( tCsrRoamProfile *pProfile ) #ifdef FEATURE_WLAN_CCX case eCSR_AUTH_TYPE_CCKM_RSN: #endif -#ifdef WLAN_FEATURE_11W - case eCSR_AUTH_TYPE_RSN_PSK_SHA256: -#endif fRSNProfile = TRUE; break; @@ -3349,23 +3379,13 @@ static tANI_BOOLEAN csrIsAuthRSN( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_R tANI_U8 cAllSuites, tANI_U8 Oui[] ) { -#ifdef WLAN_FEATURE_11W - return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[01], Oui ) || - csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui )); -#else return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[01], Oui ) ); -#endif } static tANI_BOOLEAN csrIsAuthRSNPsk( tpAniSirGlobal pMac, tANI_U8 AllSuites[][CSR_RSN_OUI_SIZE], tANI_U8 cAllSuites, tANI_U8 Oui[] ) { -#ifdef WLAN_FEATURE_11W - return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[02], Oui ) || - csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui ) ); -#else return( csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[02], Oui ) ); -#endif } #ifdef WLAN_FEATURE_11W @@ -3373,7 +3393,7 @@ static tANI_BOOLEAN csrIsAuthRSNPskSha256( tpAniSirGlobal pMac, tANI_U8 AllSuite tANI_U8 cAllSuites, tANI_U8 Oui[] ) { - return csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[06], Oui ); + return csrIsOuiMatch( pMac, AllSuites, cAllSuites, csrRSNOui[07], Oui ); } #endif @@ -3586,13 +3606,6 @@ tANI_BOOLEAN csrGetRSNInformation( tHalHandle hHal, tCsrAuthList *pAuthType, eCs if (eCSR_AUTH_TYPE_RSN_PSK == pAuthType->authType[i]) negAuthType = eCSR_AUTH_TYPE_RSN_PSK; } -#ifdef WLAN_FEATURE_11W - if ((negAuthType == eCSR_AUTH_TYPE_UNKNOWN) && csrIsAuthRSNPskSha256( pMac, AuthSuites, cAuthSuites, Authentication ) ) - { - if (eCSR_AUTH_TYPE_RSN_PSK_SHA256 == pAuthType->authType[i]) - negAuthType = eCSR_AUTH_TYPE_RSN_PSK_SHA256; - } -#endif // The 1st auth type in the APs RSN IE, to match stations connecting // profiles auth type will cause us to exit this loop @@ -3633,12 +3646,9 @@ tANI_BOOLEAN csrGetRSNInformation( tHalHandle hHal, tCsrAuthList *pAuthType, eCs Capabilities->PreAuthSupported = (pRSNIe->RSN_Cap[0] >> 0) & 0x1 ; // Bit 0 PreAuthentication Capabilities->NoPairwise = (pRSNIe->RSN_Cap[0] >> 1) & 0x1 ; // Bit 1 No Pairwise Capabilities->PTKSAReplayCounter = (pRSNIe->RSN_Cap[0] >> 2) & 0x3 ; // Bit 2, 3 PTKSA Replay Counter - Capabilities->GTKSAReplayCounter = (pRSNIe->RSN_Cap[0] >> 4) & 0x3 ; // Bit 4, 5 GTKSA Replay Counter -#ifdef WLAN_FEATURE_11W - Capabilities->MFPRequired = (pRSNIe->RSN_Cap[0] >> 6) & 0x1 ; // Bit 6 MFPR - Capabilities->MFPCapable = (pRSNIe->RSN_Cap[0] >> 7) & 0x1 ; // Bit 7 MFPC -#endif - Capabilities->Reserved = pRSNIe->RSN_Cap[1] & 0xff ; // remaining reserved + Capabilities->GTKSAReplayCounter = (pRSNIe->RSN_Cap[0] >> 4) & 0x3 ; // Bit 4,5 GTKSA Replay Counter + Capabilities->Reserved = (pRSNIe->RSN_Cap[0] >> 6) & 0x3 ; // remaining reserved + Capabilities->Reserved = (Capabilities->Reserved >> 2) | (pRSNIe->RSN_Cap[1] & 0xff) ; // remaining reserved } } return( fAcceptableCyphers ); @@ -3720,6 +3730,9 @@ tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile tCsrRSNCapabilities RSNCapabilities; tCsrRSNPMKIe *pPMK; tANI_U8 PMKId[CSR_RSN_PMKID_SIZE]; +#ifdef WLAN_FEATURE_11W + tANI_U8 *pGroupMgmtCipherSuite; +#endif tDot11fBeaconIEs *pIesLocal = pIes; smsLog(pMac, LOGW, "%s called...", __func__); @@ -3758,12 +3771,7 @@ tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile // !!REVIEW - What should STA put in RSN capabilities, currently // just putting back APs capabilities // For one, we shouldn't EVER be sending out "pre-auth supported". It is an AP only capability - // For another, we should use the Management Frame Protection values given by the supplicant RSNCapabilities.PreAuthSupported = 0; -#ifdef WLAN_FEATURE_11W - RSNCapabilities.MFPRequired = pProfile->MFPRequired; - RSNCapabilities.MFPCapable = pProfile->MFPCapable; -#endif *(tANI_U16 *)( &pAuthSuite->AuthOui[ 1 ] ) = *((tANI_U16 *)(&RSNCapabilities)); pPMK = (tCsrRSNPMKIe *)( ((tANI_U8 *)(&pAuthSuite->AuthOui[ 1 ])) + sizeof(tANI_U16) ); @@ -3779,10 +3787,20 @@ tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile pPMK->cPMKIDs = 0; } +#ifdef WLAN_FEATURE_11W + if ( pProfile->MFPEnabled ) + { + pGroupMgmtCipherSuite = (tANI_U8 *) pPMK + sizeof ( tANI_U16 ) + + ( pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE ); + palCopyMemory( pMac->hHdd, pGroupMgmtCipherSuite, csrRSNOui[07], CSR_WPA_OUI_SIZE ); + } +#endif + // Add in the fixed fields plus 1 Unicast cypher, less the IE Header length // Add in the size of the Auth suite (count plus a single OUI) // Add in the RSN caps field. // Add PMKID count and PMKID (if any) + // Add group management cipher suite pRSNIe->IeHeader.Length = (tANI_U8) (sizeof( *pRSNIe ) - sizeof ( pRSNIe->IeHeader ) + sizeof( *pAuthSuite ) + sizeof( tCsrRSNCapabilities )); @@ -3791,6 +3809,15 @@ tANI_U8 csrConstructRSNIe( tHalHandle hHal, tANI_U32 sessionId, tCsrRoamProfile pRSNIe->IeHeader.Length += (tANI_U8)(sizeof( tANI_U16 ) + (pPMK->cPMKIDs * CSR_RSN_PMKID_SIZE)); } +#ifdef WLAN_FEATURE_11W + if ( pProfile->MFPEnabled ) + { + if ( 0 == pPMK->cPMKIDs ) + pRSNIe->IeHeader.Length += sizeof( tANI_U16 ); + pRSNIe->IeHeader.Length += CSR_WPA_OUI_SIZE; + } +#endif + // return the size of the IE header (total) constructed... cbRSNIe = pRSNIe->IeHeader.Length + sizeof( pRSNIe->IeHeader ); @@ -4007,8 +4034,10 @@ tANI_U8 csrConstructWapiIe( tpAniSirGlobal pMac, tANI_U32 sessionId, tCsrRoamPro pWapi = (tANI_U8 *) (&pWapiIe->AuthOui[ 1 ]); - *pWapi = (tANI_U16)1; //cUnicastCyphers - pWapi+=2; + *pWapi = (tANI_U8)1; //cUnicastCyphers + pWapi+=1; + *pWapi = (tANI_U8)0; //cUnicastCyphers + pWapi+=1; palCopyMemory( pMac->hHdd, pWapi, UnicastCypher, sizeof( UnicastCypher ) ); pWapi += sizeof( UnicastCypher ); @@ -4603,6 +4632,7 @@ tAniEdType csrTranslateEncryptTypeToEdType( eCsrEncryptionType EncryptType ) #ifdef FEATURE_WLAN_WAPI case eCSR_ENCRYPT_TYPE_WPI: edType = eSIR_ED_WPI; + break ; #endif #ifdef WLAN_FEATURE_11W //11w BIP @@ -5729,11 +5759,10 @@ void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile) pProfile->pWAPIReqIE = NULL; } #endif /* FEATURE_WLAN_WAPI */ - - if(pProfile->pAddIEScan) + if (pProfile->nAddIEScanLength) { - palFreeMemory(pMac->hHdd, pProfile->pAddIEScan); - pProfile->pAddIEScan = NULL; + memset(pProfile->addIEScan, 0 , SIR_MAC_MAX_IE_LENGTH+2); + pProfile->nAddIEScanLength = 0; } if(pProfile->pAddIEAssoc) @@ -5741,10 +5770,6 @@ void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile) palFreeMemory(pMac->hHdd, pProfile->pAddIEAssoc); pProfile->pAddIEAssoc = NULL; } - { - palFreeMemory(pMac->hHdd, pProfile->pAddIEAssoc); - pProfile->pAddIEAssoc = NULL; - } if(pProfile->ChannelInfo.ChannelList) { @@ -5752,7 +5777,6 @@ void csrReleaseProfile(tpAniSirGlobal pMac, tCsrRoamProfile *pProfile) pProfile->ChannelInfo.ChannelList = NULL; } - palZeroMemory(pMac->hHdd, pProfile, sizeof(tCsrRoamProfile)); } } diff --git a/drivers/staging/prima/CORE/SME/src/pmc/pmc.c b/drivers/staging/prima/CORE/SME/src/pmc/pmc.c index 9fddc375761..d27e9a0ec48 100644 --- a/drivers/staging/prima/CORE/SME/src/pmc/pmc.c +++ b/drivers/staging/prima/CORE/SME/src/pmc/pmc.c @@ -18,6 +18,27 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ +/* + * Copyright (c) 2012, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + /****************************************************************************** * @@ -2107,7 +2128,7 @@ eHalStatus pmcIssueCommand( tpAniSirGlobal pMac, eSmeCommandType cmdType, void * { smePushCommand( pMac, pCommand, fPutToListHead ); } - else + else if( pCommand ) { pmcReleaseCommand( pMac, pCommand ); } @@ -2458,6 +2479,13 @@ eHalStatus pmcEnterImpsCheck( tpAniSirGlobal pMac ) return eHAL_STATUS_PMC_ALREADY_IN_IMPS; } + /* Check whether driver load unload is in progress */ + if(vos_is_load_unload_in_progress( VOS_MODULE_ID_VOSS, NULL)) + { + smsLog(pMac, LOGW, FL("Driver load/unload is in progress")); + return eHAL_STATUS_PMC_NOT_NOW; + } + return ( eHAL_STATUS_SUCCESS ); } diff --git a/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c b/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c index ad012c5f141..1e556f1932a 100644 --- a/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c +++ b/drivers/staging/prima/CORE/SME/src/pmc/pmcApi.c @@ -1,43 +1,23 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /****************************************************************************** * @@ -45,10 +25,6 @@ * * Description: Routines that make up the Power Management Control (PMC) API. * -* Copyright 2008 (c) Qualcomm, Incorporated. -* All Rights Reserved. -* Qualcomm Confidential and Proprietary. -* ******************************************************************************/ #include "palTypes.h" @@ -124,14 +100,14 @@ eHalStatus pmcOpen (tHalHandle hHal) /* Allocate a timer used in Full Power State to measure traffic levels and determine when to enter BMPS. */ - if (!VOS_IS_STATUS_SUCCESS(vos_timer_init(&pMac->pmc.hTrafficTimer, + if (!VOS_IS_STATUS_SUCCESS(vos_timer_init(&pMac->pmc.hTrafficTimer, VOS_TIMER_TYPE_SW, pmcTrafficTimerExpired, hHal))) { smsLog(pMac, LOGE, FL("Cannot allocate timer for traffic measurement")); return eHAL_STATUS_FAILURE; } -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT /* Allocate a timer used to report current PMC state through periodic DIAG event */ if (palTimerAlloc(pMac->hHdd, &pMac->pmc.hDiagEvtTimer, pmcDiagEvtTimerExpired, hHal) != eHAL_STATUS_SUCCESS) { @@ -140,7 +116,7 @@ eHalStatus pmcOpen (tHalHandle hHal) } #endif - //Initialize the default value for Bmps related config. + //Initialize the default value for Bmps related config. pMac->pmc.bmpsConfig.trafficMeasurePeriod = BMPS_TRAFFIC_TIMER_DEFAULT; pMac->pmc.bmpsConfig.bmpsPeriod = WNI_CFG_LISTEN_INTERVAL_STADEF; @@ -152,7 +128,7 @@ eHalStatus pmcOpen (tHalHandle hHal) PMC_ABORT; return eHAL_STATUS_FAILURE; } - + /* Initialize lists for power save check routines and request full power callback routines. */ if (csrLLOpen(pMac->hHdd, &pMac->pmc.powerSaveCheckList) != eHAL_STATUS_SUCCESS) { @@ -262,12 +238,12 @@ eHalStatus pmcStart (tHalHandle hHal) } else htMimoPowerSaveState = eSIR_HT_MIMO_PS_NO_LIMIT; - + if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState, sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) return eHAL_STATUS_FAILURE; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT if (pmcStartDiagEvtTimer(hHal) != eHAL_STATUS_SUCCESS) { return eHAL_STATUS_FAILURE; @@ -313,7 +289,7 @@ eHalStatus pmcStop (tHalHandle hHal) pmcStopTrafficTimer(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT pmcStopDiagEvtTimer(hHal); #endif @@ -376,7 +352,7 @@ eHalStatus pmcClose (tHalHandle hHal) { smsLog(pMac, LOGE, FL("Cannot deallocate traffic timer")); } -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT if (palTimerFree(pMac->hHdd, pMac->pmc.hDiagEvtTimer) != eHAL_STATUS_SUCCESS) { smsLog(pMac, LOGE, FL("Cannot deallocate timer for diag event reporting")); @@ -388,7 +364,7 @@ eHalStatus pmcClose (tHalHandle hHal) } /* - The following list's entries are dynamically allocated so they need their own + The following list's entries are dynamically allocated so they need their own cleanup function */ pmcClosePowerSaveCheckList(pMac); @@ -464,7 +440,7 @@ eHalStatus pmcSignalPowerEvent (tHalHandle hHal, tPmcPowerEvent event) if (pMac->pmc.smpsConfig.mode == ePMC_STATIC_SMPS) htMimoPowerSaveState = eSIR_HT_MIMO_PS_STATIC; if (pmcSendMessage(hHal, eWNI_PMC_SMPS_STATE_IND, &htMimoPowerSaveState, - sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) + sizeof(tSirMacHTMIMOPowerSaveState)) != eHAL_STATUS_SUCCESS) return eHAL_STATUS_FAILURE; } return eHAL_STATUS_SUCCESS; @@ -521,7 +497,7 @@ eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, v /* Configure the specified power saving mode. */ switch (psMode) { - + case ePMC_IDLE_MODE_POWER_SAVE: pMac->pmc.impsConfig = *(tpPmcImpsConfigParams)pConfigParams; smsLog(pMac, LOG3, FL("IMPS configuration")); @@ -555,13 +531,13 @@ eHalStatus pmcSetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, v smsLog(pMac, LOG3, " value of bcnEarlyTermWakeInterval: %d", pMac->pmc.bmpsConfig.bcnEarlyTermWakeInterval); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); psRequest.event_subtype = WLAN_BMPS_SET_CONFIG; /* possible loss of data due to mismatch but expectation is that values can reasonably be expected to fit in target widths */ psRequest.bmps_auto_timer_duration = (v_U16_t)pMac->pmc.bmpsConfig.trafficMeasurePeriod; - psRequest.bmps_period = (v_U16_t)pMac->pmc.bmpsConfig.bmpsPeriod; + psRequest.bmps_period = (v_U16_t)pMac->pmc.bmpsConfig.bmpsPeriod; WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); #endif @@ -621,7 +597,7 @@ eHalStatus pmcGetConfigPowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode, v /* Configure the specified power saving mode. */ switch (psMode) { - + case ePMC_IDLE_MODE_POWER_SAVE: *(tpPmcImpsConfigParams)pConfigParams = pMac->pmc.impsConfig; break; @@ -662,7 +638,7 @@ eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tSirMacHTMIMOPowerSaveState htMimoPowerSaveState; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -671,7 +647,7 @@ eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); #endif - + smsLog(pMac, LOG2, FL("Entering pmcEnablePowerSave, power save mode %d"), psMode); /* Enable the specified power saving mode. */ @@ -730,13 +706,13 @@ eHalStatus pmcEnablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) module for entry into Bmps mode. This timer is started only if BMPS is enabled and whenever the device is in full power. \param hHal - The handle returned by macOpen. - \return eHalStatus + \return eHalStatus ---------------------------------------------------------------------------*/ -eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) +eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -756,7 +732,7 @@ eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) pMac->pmc.autoBmpsEntryEnabled = TRUE; - /* Check if there is an Infra session. If there is no Infra session, timer will be started + /* Check if there is an Infra session. If there is no Infra session, timer will be started when STA associates to AP */ if (pmcShouldBmpsTimerRun(pMac)) @@ -776,13 +752,13 @@ eHalStatus pmcStartAutoBmpsTimer (tHalHandle hHal) Stopping the timer does not cause a device state change. Only the timer is stopped. If "Full Power" is desired, use the pmcRequestFullPower API \param hHal - The handle returned by macOpen. - \return eHalStatus + \return eHalStatus ---------------------------------------------------------------------------*/ eHalStatus pmcStopAutoBmpsTimer (tHalHandle hHal) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -822,7 +798,7 @@ eHalStatus pmcDisablePowerSave (tHalHandle hHal, tPmcPowerSavingMode psMode) tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tSirMacHTMIMOPowerSaveState htMimoPowerSaveState; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -911,7 +887,7 @@ eHalStatus pmcQueryPowerState (tHalHandle hHal, tPmcPowerState *pPowerState, /* Return current power state based on PMC state. */ switch (pMac->pmc.pmcState) { - + case FULL_POWER: *pPowerState = ePMC_FULL_POWER; break; @@ -960,7 +936,7 @@ tANI_BOOLEAN pmcIsPowerSaveEnabled (tHalHandle hHal, tPmcPowerSavingMode psMode) /* Check ability to enter based on the specified power saving mode. */ switch (psMode) { - + case ePMC_IDLE_MODE_POWER_SAVE: return pMac->pmc.impsEnabled && (pMac->pmc.powerSource != AC_POWER || pMac->pmc.impsConfig.enterOnAc); @@ -1021,13 +997,13 @@ eHalStatus pmcRequestFullPower (tHalHandle hHal, void (*callbackRoutine) (void * tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tpRequestFullPowerEntry pEntry; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); psRequest.event_subtype = WLAN_ENTER_FULL_POWER_REQ; psRequest.full_power_request_reason = fullPowerReason; - + WLAN_VOS_DIAG_EVENT_REPORT(&psRequest, EVENT_WLAN_POWERSAVE_GENERIC); #endif @@ -1125,7 +1101,7 @@ eHalStatus pmcRequestImps (tHalHandle hHal, tANI_U32 impsPeriod, tpAniSirGlobal pMac = PMAC_STRUCT(hHal); eHalStatus status; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1362,15 +1338,16 @@ static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg ) /* Check that we are in the correct state for this message. */ if (pMac->pmc.pmcState != REQUEST_FULL_POWER) { - smsLog(pMac, LOGE, FL("Got Exit IMPS Response Message while in state %d"), pMac->pmc.pmcState); + smsLog(pMac, LOGE, FL("Got Exit IMPS Response Message while " + "in state %d"), pMac->pmc.pmcState); break; } /* Enter Full Power State. */ if (pMsg->statusCode != eSIR_SME_SUCCESS) { - smsLog(pMac, LOGP, FL("Response message to request to exit IMPS indicates failure, status %x"), - pMsg->statusCode); + smsLog(pMac, LOGE, FL("Response message to request to exit " + "IMPS indicates failure, status %x"), pMsg->statusCode); } pmcEnterFullPowerState(pMac); break; @@ -1454,7 +1431,7 @@ static void pmcProcessResponse( tpAniSirGlobal pMac, tSirSmeRsp *pMsg ) } /* Enter UAPSD State if response indicates success. */ - if (pMsg->statusCode == eSIR_SME_SUCCESS) + if (pMsg->statusCode == eSIR_SME_SUCCESS) { pmcEnterUapsdState(pMac); pmcDoStartUapsdCallbacks(pMac, eHAL_STATUS_SUCCESS); @@ -1729,7 +1706,7 @@ eHalStatus pmcRequestBmps ( tpRequestBmpsEntry pEntry; eHalStatus status; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1747,7 +1724,7 @@ eHalStatus pmcRequestBmps ( pMac->pmc.bmpsRequestedByHdd = TRUE; return eHAL_STATUS_SUCCESS; } - + status = pmcEnterBmpsCheck( pMac ); if(HAL_STATUS_SUCCESS( status )) { @@ -1785,6 +1762,24 @@ eHalStatus pmcRequestBmps ( status = eHAL_STATUS_FAILURE; } } + /* Retry to enter the BMPS if the + status = eHAL_STATUS_PMC_NOT_NOW */ + else if (status == eHAL_STATUS_PMC_NOT_NOW) + { + pmcStopTrafficTimer(hHal); + smsLog(pMac, LOG1, FL("Can't enter BMPS+++")); + if (pmcShouldBmpsTimerRun(pMac)) + { + if (pmcStartTrafficTimer(pMac, + pMac->pmc.bmpsConfig.trafficMeasurePeriod) + != eHAL_STATUS_SUCCESS) + { + smsLog(pMac, LOG1, FL("Cannot start BMPS Retry timer")); + } + smsLog(pMac, LOG1, + FL("BMPS Retry Timer already running or started")); + } + } return status; } @@ -1817,7 +1812,7 @@ eHalStatus pmcStartUapsd ( tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tpStartUapsdEntry pEntry; -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1906,7 +1901,7 @@ eHalStatus pmcStopUapsd (tHalHandle hHal) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1942,7 +1937,7 @@ eHalStatus pmcStopUapsd (tHalHandle hHal) \param hHal - The handle returned by macOpen. \param callbackRoutine - Callback routine invoked in case of success/failure \param callbackContext - value to be passed as parameter to callback - \return eHalStatus + \return eHalStatus eHAL_STATUS_SUCCESS - device is in Standby mode eHAL_STATUS_FAILURE - device cannot be put in standby mode eHAL_STATUS_PMC_PENDING - device is being put in standby mode @@ -1954,7 +1949,7 @@ extern eHalStatus pmcRequestStandby ( { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(psRequest, vos_event_wlan_powersave_payload_type); vos_mem_zero(&psRequest, sizeof(vos_event_wlan_powersave_payload_type)); @@ -1984,10 +1979,10 @@ extern eHalStatus pmcRequestStandby ( if (pMac->pmc.pmcState == STANDBY) return eHAL_STATUS_SUCCESS; - + if (csrIsIBSSStarted(pMac) || csrIsBTAMPStarted(pMac)) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_FATAL, "WLAN: IBSS or BT-AMP session present. Cannot honor standby request"); return eHAL_STATUS_PMC_NOT_NOW; } @@ -2012,9 +2007,9 @@ extern eHalStatus pmcRequestStandby ( \param callbackContext - Cookie to be passed back during callback \return eHalStatus eHAL_STATUS_SUCCESS - successfully registered - eHAL_STATUS_FAILURE - not successfully registered + eHAL_STATUS_FAILURE - not successfully registered ---------------------------------------------------------------------------*/ -extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal, +extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, tPmcState pmcState), void *callbackContext) { @@ -2049,9 +2044,9 @@ extern eHalStatus pmcRegisterDeviceStateUpdateInd (tHalHandle hHal, \param callbackRoutine - Callback routine to be deregistered \return eHalStatus eHAL_STATUS_SUCCESS - successfully deregistered - eHAL_STATUS_FAILURE - not successfully deregistered + eHAL_STATUS_FAILURE - not successfully deregistered ---------------------------------------------------------------------------*/ -eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal, +eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal, void (*callbackRoutine) (void *callbackContext, tPmcState pmcState)) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); @@ -2093,7 +2088,7 @@ eHalStatus pmcDeregisterDeviceStateUpdateInd (tHalHandle hHal, \brief fn to inform PMC that eWNI_SME_SYS_READY_IND has been sent to PE. This acts as a trigger to send a message to PE to update the power save related conig to FW. Note that if HDD configures any power save - related stuff before this API is invoked, PMC will buffer all the + related stuff before this API is invoked, PMC will buffer all the configutaion. \param hHal - The handle returned by macOpen. \return eHalStatus @@ -2123,16 +2118,16 @@ eHalStatus pmcReady(tHalHandle hHal) \fn pmcWowlAddBcastPattern \brief Add a pattern for Pattern Byte Matching in Wowl mode. Firmware will do a pattern match on these patterns when Wowl is enabled during BMPS - mode. Note that Firmware performs the pattern matching only on + mode. Note that Firmware performs the pattern matching only on broadcast frames and while Libra is in BMPS mode. \param hHal - The handle returned by macOpen. \param pattern - Pointer to the pattern to be added \return eHalStatus eHAL_STATUS_FAILURE Cannot add pattern - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ eHalStatus pmcWowlAddBcastPattern ( - tHalHandle hHal, + tHalHandle hHal, tpSirWowlAddBcastPtrn pattern, tANI_U8 sessionId) { @@ -2192,14 +2187,14 @@ eHalStatus pmcWowlAddBcastPattern ( eHalStatus status; vos_mem_copy(pattern->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); //Wake up the chip first - status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN, + status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_ADD_BCAST_PTRN, pattern, sizeof(tSirWowlAddBcastPtrn) ); if( eHAL_STATUS_PMC_PENDING == status ) { return eHAL_STATUS_SUCCESS; } - else + else { //either fail or already in full power if( !HAL_STATUS_SUCCESS( status ) ) @@ -2227,22 +2222,22 @@ eHalStatus pmcWowlAddBcastPattern ( \param pattern - Pattern to be deleted \return eHalStatus eHAL_STATUS_FAILURE Cannot delete pattern - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ eHalStatus pmcWowlDelBcastPattern ( - tHalHandle hHal, + tHalHandle hHal, tpSirWowlDelBcastPtrn pattern, tANI_U8 sessionId) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); wowRequest.event_subtype = WLAN_WOW_DEL_PTRN_REQ; - wowRequest.wow_del_ptrn_id = pattern->ucPatternId; + wowRequest.wow_del_ptrn_id = pattern->ucPatternId; WLAN_VOS_DIAG_EVENT_REPORT(&wowRequest, EVENT_WLAN_POWERSAVE_WOW); #endif @@ -2275,14 +2270,14 @@ eHalStatus pmcWowlDelBcastPattern ( vos_mem_copy(pattern->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); //Wake up the chip first - status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN, + status = pmcDeferMsg( pMac, eWNI_PMC_WOWL_DEL_BCAST_PTRN, pattern, sizeof(tSirWowlDelBcastPtrn) ); if( eHAL_STATUS_PMC_PENDING == status ) { return eHAL_STATUS_SUCCESS; } - else + else { //either fail or already in full power if( !HAL_STATUS_SUCCESS( status ) ) @@ -2309,20 +2304,20 @@ eHalStatus pmcWowlDelBcastPattern ( Note 1: If "fullPowerReason" specificied in this API is set to eSME_FULL_PWR_NEEDED_BY_HDD, PMC will clear any "buffered wowl" requests and also clear any "buffered BMPS requests by HDD". Assumption is that since - HDD is requesting full power, we need to undo any previous HDD requests for + HDD is requesting full power, we need to undo any previous HDD requests for BMPS (using sme_RequestBmps) or WoWL (using sme_EnterWoWL). If the reason is specified anything other than above, the buffered requests for BMPS and WoWL will not be cleared. Note 2: Requesting full power (no matter what the fullPowerReason is) doesn't disable the "auto bmps timer" (if it is enabled) or clear any "buffered uapsd request". - Note 3: When the device finally enters Full Power PMC will start a timer + Note 3: When the device finally enters Full Power PMC will start a timer if any of the following holds true: - Auto BMPS mode is enabled - Uapsd request is pending - HDD's request for BMPS is pending - HDD's request for WoWL is pending - On timer expiry PMC will attempt to put the device in BMPS mode if following + On timer expiry PMC will attempt to put the device in BMPS mode if following (in addition to those listed above) holds true: - Polling of all modules through the Power Save Check routine passes - STA is associated to an access point @@ -2333,13 +2328,13 @@ eHalStatus pmcWowlDelBcastPattern ( \param - wakeReasonIndCBContext - Cookie to be passed back during callback \param - fullPowerReason - Reason why this API is being invoked. SME needs to distinguish between BAP and HDD requests - \return eHalStatus - status + \return eHalStatus - status eHAL_STATUS_SUCCESS - device brought to full power state eHAL_STATUS_FAILURE - device cannot be brought to full power state eHAL_STATUS_PMC_PENDING - device is being brought to full power state, ---------------------------------------------------------------------------*/ -eHalStatus pmcEnterWowl ( - tHalHandle hHal, +eHalStatus pmcEnterWowl ( + tHalHandle hHal, void (*enterWowlCallbackRoutine) (void *callbackContext, eHalStatus status), void *enterWowlCallbackContext, #ifdef WLAN_WAKEUP_EVENTS @@ -2351,7 +2346,7 @@ eHalStatus pmcEnterWowl ( tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); @@ -2379,7 +2374,7 @@ eHalStatus pmcEnterWowl ( return eHAL_STATUS_FAILURE; } - vos_mem_copy(wowlEnterParams->bssId, pSession->connectedProfile.bssid, + vos_mem_copy(wowlEnterParams->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); if( !PMC_IS_READY(pMac) ) @@ -2450,19 +2445,19 @@ eHalStatus pmcEnterWowl ( /* --------------------------------------------------------------------------- \fn pmcExitWowl - \brief This is the SME API exposed to HDD to request exit from WoWLAN mode. - SME will initiate exit from WoWLAN mode and device will be put in BMPS + \brief This is the SME API exposed to HDD to request exit from WoWLAN mode. + SME will initiate exit from WoWLAN mode and device will be put in BMPS mode. \param hHal - The handle returned by macOpen. \return eHalStatus eHAL_STATUS_FAILURE Device cannot exit WoWLAN mode. - eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode. + eHAL_STATUS_SUCCESS Request accepted to exit WoWLAN mode. ---------------------------------------------------------------------------*/ eHalStatus pmcExitWowl (tHalHandle hHal) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); -#ifdef FEATURE_WLAN_DIAG_SUPPORT +#ifdef FEATURE_WLAN_DIAG_SUPPORT WLAN_VOS_DIAG_EVENT_DEF(wowRequest, vos_event_wlan_powersave_wow_payload_type); vos_mem_zero(&wowRequest, sizeof(vos_event_wlan_powersave_wow_payload_type)); @@ -2496,9 +2491,9 @@ eHalStatus pmcExitWowl (tHalHandle hHal) \param pRequest - Pointer to the offload request. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the offload. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ -eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, +eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, tANI_U8 sessionId) { tpSirHostOffloadReq pRequestBuf; @@ -2547,7 +2542,7 @@ eHalStatus pmcSetHostOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, \param pRequest - Pointer to the Keep Alive. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the keepalive. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest, tANI_U8 sessionId) { @@ -2605,15 +2600,14 @@ eHalStatus pmcSetKeepAlive (tHalHandle hHal, tpSirKeepAliveReq pRequest, tANI_U8 \param pRequest - Pointer to the offload request. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the offload. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ -eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, +eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, tANI_U8 sessionId) { tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tpSirHostOffloadReq pRequestBuf; vos_msg_t msg; - int i; tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); if( NULL == pSession ) @@ -2622,7 +2616,7 @@ eHalStatus pmcSetNSOffload (tHalHandle hHal, tpSirHostOffloadReq pRequest, return eHAL_STATUS_FAILURE; } - vos_mem_copy(pRequest->bssId, pSession->connectedProfile.bssid, + vos_mem_copy(pRequest->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); pRequestBuf = vos_mem_malloc(sizeof(tSirHostOffloadReq)); @@ -2777,7 +2771,7 @@ void pmcCloseDeferredMsgList(tpAniSirGlobal pMac) #ifdef FEATURE_WLAN_SCAN_PNO -static tSirRetStatus +static tSirRetStatus pmcPopulateMacHeader( tpAniSirGlobal pMac, tANI_U8* pBD, tANI_U8 type, @@ -2787,7 +2781,7 @@ pmcPopulateMacHeader( tpAniSirGlobal pMac, { tSirRetStatus statusCode = eSIR_SUCCESS; tpSirMacMgmtHdr pMacHdr; - + /// Prepare MAC management header pMacHdr = (tpSirMacMgmtHdr) (pBD); @@ -2840,12 +2834,12 @@ pmcPrepareProbeReqTemplate(tpAniSirGlobal pMac, PopulateDot11fExtSuppRates1( pMac, nChannelNum, &pr.ExtSuppRates ); } - + if (IS_DOT11_MODE_HT(dot11mode)) { PopulateDot11fHTCaps( pMac, NULL, &pr.HTCaps ); } - + // That's it-- now we pack it. First, how much space are we going to // need? nStatus = dot11fGetPackedProbeRequestSize( pMac, &pr, &nPayload ); @@ -2867,7 +2861,7 @@ pmcPrepareProbeReqTemplate(tpAniSirGlobal pMac, } nBytes = nPayload + sizeof( tSirMacMgmtHdr ); - + /* Prepare outgoing frame*/ palZeroMemory( pMac->hHdd, pFrame, nBytes ); @@ -2895,21 +2889,21 @@ pmcPrepareProbeReqTemplate(tpAniSirGlobal pMac, } else if ( DOT11F_WARNED( nStatus ) ) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, - "There were warnings while packing a Probe Request (0x%08x)." ); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "There were warnings while packing a Probe Request" ); } - *pusLen = nPayload + sizeof(tSirMacMgmtHdr); + *pusLen = nPayload + sizeof(tSirMacMgmtHdr); return eSIR_SUCCESS; } // End pmcPrepareProbeReqTemplate. eHalStatus pmcSetPreferredNetworkList ( - tHalHandle hHal, - tpSirPNOScanReq pRequest, - tANI_U8 sessionId, - preferredNetworkFoundIndCallback callbackRoutine, + tHalHandle hHal, + tpSirPNOScanReq pRequest, + tANI_U8 sessionId, + preferredNetworkFoundIndCallback callbackRoutine, void *callbackContext ) { @@ -2950,15 +2944,15 @@ eHalStatus pmcSetPreferredNetworkList vos_mem_copy(pRequestBuf, pRequest, sizeof(tSirPNOScanReq)); /*Must translate the mode first*/ - ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, + ucDot11Mode = (tANI_U8) csrTranslateToWNICfgDot11Mode(pMac, csrFindBestPhyMode( pMac, pMac->roam.configParam.phyMode )); /*Prepare a probe request for 2.4GHz band and one for 5GHz band*/ - pmcPrepareProbeReqTemplate(pMac,SIR_PNO_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, - pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen); + pmcPrepareProbeReqTemplate(pMac,SIR_PNO_24G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p24GProbeTemplate, &pRequestBuf->us24GProbeTemplateLen); - pmcPrepareProbeReqTemplate(pMac,SIR_PNO_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, - pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen); + pmcPrepareProbeReqTemplate(pMac,SIR_PNO_5G_DEFAULT_CH, ucDot11Mode, pSession->selfMacAddr, + pRequestBuf->p5GProbeTemplate, &pRequestBuf->us5GProbeTemplateLen); msg.type = WDA_SET_PNO_REQ; @@ -2994,7 +2988,7 @@ eHalStatus pmcSetRssiFilter(tHalHandle hHal, v_U8_t rssiThreshold) } - pRequestBuf->rssiThreshold = rssiThreshold; + pRequestBuf->rssiThreshold = rssiThreshold; msg.type = WDA_SET_RSSI_FILTER_REQ; msg.reserved = 0; @@ -3025,18 +3019,18 @@ eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChanne return eHAL_STATUS_FAILED_ALLOC; } - // + // // Fill pRequestBuf structure from pRequest // pRequestBuf->b11dEnabled = pRequest->Is11eSupportEnabled; pRequestBuf->b11dResolved = b11dResolved; - pRequestBuf->ucChannelCount = + pRequestBuf->ucChannelCount = ( pChannelList->numChannels < SIR_PNO_MAX_NETW_CHANNELS_EX )? pChannelList->numChannels:SIR_PNO_MAX_NETW_CHANNELS_EX; for (i=0; i < pRequestBuf->ucChannelCount; i++) - { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: Channel List %d: %d", __FUNCTION__, i, pChannelList->channelList[i] ); pRequestBuf->aChannels[i] = pChannelList->channelList[i]; @@ -3044,7 +3038,7 @@ eHalStatus pmcUpdateScanParams(tHalHandle hHal, tCsrConfig *pRequest, tCsrChanne pRequestBuf->usPassiveMinChTime = pRequest->nPassiveMinChnTime; pRequestBuf->usPassiveMaxChTime = pRequest->nPassiveMaxChnTime; pRequestBuf->usActiveMinChTime = pRequest->nActiveMinChnTime; - pRequestBuf->usActiveMaxChTime = pRequest->nActiveMaxChnTime; + pRequestBuf->usActiveMaxChTime = pRequest->nActiveMaxChnTime; pRequestBuf->ucCBState = PHY_SINGLE_CHANNEL_CENTERED; msg.type = WDA_UPDATE_SCAN_PARAMS_REQ; @@ -3082,7 +3076,7 @@ eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams } - vos_mem_copy(pRequestBuf, pwParams, sizeof(*pRequestBuf)); + vos_mem_copy(pRequestBuf, pwParams, sizeof(*pRequestBuf)); msg.type = WDA_SET_POWER_PARAMS_REQ; @@ -3102,8 +3096,8 @@ eHalStatus pmcSetPowerParams(tHalHandle hHal, tSirSetPowerParamsReq* pwParams #ifdef WLAN_FEATURE_PACKET_FILTERING eHalStatus pmcGetFilterMatchCount ( - tHalHandle hHal, - FilterMatchCountCallback callbackRoutine, + tHalHandle hHal, + FilterMatchCountCallback callbackRoutine, void *callbackContext, tANI_U8 sessionId ) @@ -3113,8 +3107,8 @@ eHalStatus pmcGetFilterMatchCount tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); - VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, - "%s: filterId = %d", __func__); + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s", __func__); if(NULL == pSession ) { @@ -3132,7 +3126,7 @@ eHalStatus pmcGetFilterMatchCount return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); msg.type = WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ; msg.reserved = 0; @@ -3141,9 +3135,9 @@ eHalStatus pmcGetFilterMatchCount /* Cache the Packet Coalescing Filter Match Count callback information */ if (NULL != pMac->pmc.FilterMatchCountCB) { - // Do we need to check if the callback is in use? + // Do we need to check if the callback is in use? // Because we are not sending the same message again when it is pending, - // the only case when the callback is not NULL is that the previous message + // the only case when the callback is not NULL is that the previous message //was timed out or failed. // So, it will be safe to set the callback in this case. } @@ -3153,7 +3147,7 @@ eHalStatus pmcGetFilterMatchCount if(VOS_STATUS_SUCCESS != vos_mq_post_message(VOS_MODULE_ID_WDA, &msg)) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_PACKET_COALESCING_FILTER_MATCH_COUNT_REQ " "message to WDA", __func__); vos_mem_free(pRequestBuf); @@ -3172,9 +3166,9 @@ eHalStatus pmcGetFilterMatchCount \param pGtkOffload - Pointer to the GTK offload request. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the offload. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ -eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, +eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, tANI_U8 sessionId) { tpSirGtkOffloadParams pRequestBuf; @@ -3182,7 +3176,7 @@ eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); - VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: KeyReplayCounter: %d", + VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO, "%s: KeyReplayCounter: %d", __func__, pGtkOffload->ullKeyReplayCounter); if(NULL == pSession ) @@ -3200,7 +3194,7 @@ eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_copy(pGtkOffload->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy(pGtkOffload->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); vos_mem_copy(pRequestBuf, pGtkOffload, sizeof(tSirGtkOffloadParams)); @@ -3225,9 +3219,9 @@ eHalStatus pmcSetGTKOffload (tHalHandle hHal, tpSirGtkOffloadParams pGtkOffload, \param callbackRoutine - Pointer to the GTK Offload Get Info response callback routine. \return eHalStatus eHAL_STATUS_FAILURE Cannot set the offload. - eHAL_STATUS_SUCCESS Request accepted. + eHAL_STATUS_SUCCESS Request accepted. ---------------------------------------------------------------------------*/ -eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, +eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackRoutine, void *callbackContext, tANI_U8 sessionId) { tpSirGtkOffloadGetInfoRspParams pRequestBuf; @@ -3235,12 +3229,12 @@ eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackR tpAniSirGlobal pMac = PMAC_STRUCT(hHal); tCsrRoamSession *pSession = CSR_GET_SESSION( pMac, sessionId ); - VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterId = %d", + VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: filterId = %d", __func__); if(NULL == pSession ) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Session not found ", __func__); return eHAL_STATUS_FAILURE; } @@ -3254,7 +3248,7 @@ eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackR return eHAL_STATUS_FAILED_ALLOC; } - vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); + vos_mem_copy(pRequestBuf->bssId, pSession->connectedProfile.bssid, sizeof(tSirMacAddr)); msg.type = WDA_GTK_OFFLOAD_GETINFO_REQ; msg.reserved = 0; @@ -3263,7 +3257,7 @@ eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackR /* Cache the Get GTK Offload callback information */ if (NULL != pMac->pmc.GtkOffloadGetInfoCB) { - // Do we need to check if the callback is in use? + // Do we need to check if the callback is in use? // Because we are not sending the same message again when it is pending, // the only case when the callback is not NULL is that the previous message was timed out or failed. // So, it will be safe to set the callback in this case. @@ -3274,7 +3268,7 @@ eHalStatus pmcGetGTKOffload(tHalHandle hHal, GTKOffloadGetInfoCallback callbackR if (!VOS_IS_STATUS_SUCCESS(vos_mq_post_message(VOS_MODULE_ID_WDA, &msg))) { - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_GTK_OFFLOAD_GETINFO_REQ message to WDA", + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, "%s: Not able to post WDA_GTK_OFFLOAD_GETINFO_REQ message to WDA", __func__); vos_mem_free(pRequestBuf); return eHAL_STATUS_FAILURE; diff --git a/drivers/staging/prima/CORE/SME/src/rrm/sme_rrm.c b/drivers/staging/prima/CORE/SME/src/rrm/sme_rrm.c index 60dcda59680..c1934809d30 100644 --- a/drivers/staging/prima/CORE/SME/src/rrm/sme_rrm.c +++ b/drivers/staging/prima/CORE/SME/src/rrm/sme_rrm.c @@ -145,7 +145,7 @@ void rrmIndicateNeighborReportResult(tpAniSirGlobal pMac, VOS_STATUS vosStatus) /* Stop the timer if it is already running. The timer should be running only in the SUCCESS case. */ if (VOS_TIMER_STATE_RUNNING == vos_timer_getCurrentState(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer)) { - VOS_ASSERT(VOS_STATUS_SUCCESS == vosStatus); + smsLog( pMac, LOG1, FL("No entry in neighbor report cache")); vos_timer_stop(&pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspWaitTimer); } callback = pMac->rrm.rrmSmeContext.neighborReqControlInfo.neighborRspCallbackInfo.neighborRspCallback; @@ -236,6 +236,8 @@ static eHalStatus sme_RrmSendBeaconReportXmitInd( tpAniSirGlobal pMac, tCsrScanR pBssDesc = &pCurResult->BssDescriptor; ie_len = GET_IE_LEN_IN_BSS( pBssDesc->length ); pBeaconRep->pBssDescription[msgCounter] = vos_mem_malloc ( ie_len+sizeof(tSirBssDescription) ); + if (NULL == pBeaconRep->pBssDescription[msgCounter]) + break; vos_mem_copy( pBeaconRep->pBssDescription[msgCounter], pBssDesc, sizeof(tSirBssDescription) ); vos_mem_copy( &pBeaconRep->pBssDescription[msgCounter]->ieFields[0], pBssDesc->ieFields, ie_len ); @@ -259,9 +261,10 @@ static eHalStatus sme_RrmSendBeaconReportXmitInd( tpAniSirGlobal pMac, tCsrScanR pBeaconRep->fMeasureDone = (pCurResult)?false:measurementDone; - status = palSendMBMessage(pMac->hHdd, pBeaconRep); + smsLog(pMac, LOGW, "SME Sending BcnRepXmit to PE numBss %d", + pBeaconRep->numBssDesc); - smsLog( pMac, LOGW, "SME Sent BcnRepXmit to PE numBss %d", pBeaconRep->numBssDesc); + status = palSendMBMessage(pMac->hHdd, pBeaconRep); } while (pCurResult); @@ -767,8 +770,16 @@ static void rrmCalculateNeighborAPRoamScore(tpAniSirGlobal pMac, tpRrmNeighborRe tpSirNeighborBssDescripton pNeighborBssDesc; tANI_U32 roamScore = 0; - VOS_ASSERT(pNeighborReportDesc != NULL); - VOS_ASSERT(pNeighborReportDesc->pNeighborBssDescription != NULL); + if (NULL == pNeighborReportDesc) + { + VOS_ASSERT(0); + return; + } + if (NULL == pNeighborReportDesc->pNeighborBssDescription) + { + VOS_ASSERT(0); + return; + } pNeighborBssDesc = pNeighborReportDesc->pNeighborBssDescription; @@ -832,8 +843,16 @@ void rrmStoreNeighborRptByRoamScore(tpAniSirGlobal pMac, tpRrmNeighborReportDesc tListElem *pEntry; tRrmNeighborReportDesc *pTempNeighborReportDesc; - VOS_ASSERT(pNeighborReportDesc != NULL); - VOS_ASSERT(pNeighborReportDesc->pNeighborBssDescription != NULL); + if (NULL == pNeighborReportDesc) + { + VOS_ASSERT(0); + return; + } + if (NULL == pNeighborReportDesc->pNeighborBssDescription) + { + VOS_ASSERT(0); + return; + } if (csrLLIsListEmpty(&pSmeRrmContext->neighborReportCache, LL_ACCESS_LOCK)) { @@ -911,6 +930,7 @@ eHalStatus sme_RrmProcessNeighborReport(tpAniSirGlobal pMac, void *pMsgBuf) if (NULL == pNeighborReportDesc->pNeighborBssDescription) { smsLog( pMac, LOGE, "Failed to allocate memory for RRM Neighbor report BSS Description"); + vos_mem_free(pNeighborReportDesc); status = eHAL_STATUS_FAILED_ALLOC; goto end; } diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c old mode 100644 new mode 100755 index 43656a7bafa..ccedacffa44 --- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c +++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_Api.c @@ -118,11 +118,6 @@ eHalStatus sme_HandlePostChannelSwitchInd(tHalHandle hHal); tANI_BOOLEAN csrIsScanAllowed(tpAniSirGlobal pMac); #endif -#ifdef WLAN_FEATURE_11W -eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal, - tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm ); -#endif - //Internal SME APIs eHalStatus sme_AcquireGlobalLock( tSmeStruct *psSme) { @@ -898,6 +893,7 @@ eHalStatus sme_Open(tHalHandle hHal) do { pMac->sme.state = SME_STATE_STOP; + pMac->sme.currDeviceMode = VOS_STA_MODE; if( !VOS_IS_STATUS_SUCCESS( vos_lock_init( &pMac->sme.lkSmeGlobalLock ) ) ) { smsLog( pMac, LOGE, "sme_Open failed init lock" ); @@ -1405,34 +1401,6 @@ eHalStatus sme_PCFilterMatchCountResponseHandler(tHalHandle hHal, void* pMsg) #endif // WLAN_FEATURE_PACKET_FILTERING -#ifdef WLAN_FEATURE_11W -/*------------------------------------------------------------------ - * - * Handle the unprotected management frame indication from LIM and - * forward it to HDD. - * - *------------------------------------------------------------------*/ - -eHalStatus sme_UnprotectedMgmtFrmInd( tHalHandle hHal, - tpSirSmeUnprotMgmtFrameInd pSmeMgmtFrm) -{ - tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); - eHalStatus status = eHAL_STATUS_SUCCESS; - tCsrRoamInfo pRoamInfo = {0}; - tANI_U32 SessionId = pSmeMgmtFrm->sessionId; - - pRoamInfo.nFrameLength = pSmeMgmtFrm->frameLen; - pRoamInfo.pbFrames = pSmeMgmtFrm->frameBuf; - pRoamInfo.frameType = pSmeMgmtFrm->frameType; - - /* forward the mgmt frame to HDD */ - csrRoamCallCallback(pMac, SessionId, &pRoamInfo, 0, eCSR_ROAM_UNPROT_MGMT_FRAME_IND, 0); - - return status; -} -#endif - - /*-------------------------------------------------------------------------- \brief sme_ProcessMsg() - The main message processor for SME. @@ -1741,20 +1709,6 @@ eHalStatus sme_ProcessMsg(tHalHandle hHal, vos_msg_t* pMsg) } #endif -#ifdef WLAN_FEATURE_11W - case eWNI_SME_UNPROT_MGMT_FRM_IND: - if (pMsg->bodyptr) - { - sme_UnprotectedMgmtFrmInd(pMac, pMsg->bodyptr); - vos_mem_free(pMsg->bodyptr); - } - else - { - smsLog(pMac, LOGE, "Empty rsp message for meas (eWNI_SME_UNPROT_MGMT_FRM_IND), nothing to process"); - } - break; -#endif - default: if ( ( pMsg->type >= eWNI_SME_MSG_TYPES_BEGIN ) @@ -2360,6 +2314,38 @@ eHalStatus sme_RoamConnect(tHalHandle hHal, tANI_U8 sessionId, tCsrRoamProfile * return (status); } +/* --------------------------------------------------------------------------- + + \fn sme_SetPhyMode + + \brief Changes the PhyMode. + + \param hHal - The handle returned by macOpen. + + \param phyMode new phyMode which is to set + + \return eHalStatus SUCCESS. + + -------------------------------------------------------------------------------*/ +eHalStatus sme_SetPhyMode(tHalHandle hHal, eCsrPhyMode phyMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + if (NULL == pMac) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_ERROR, + "%s: invalid context", __func__); + return eHAL_STATUS_FAILURE; + } + + pMac->roam.configParam.phyMode = phyMode; + pMac->roam.configParam.uCfgDot11Mode = csrGetCfgDot11ModeFromCsrPhyMode(NULL, + pMac->roam.configParam.phyMode, + pMac->roam.configParam.ProprietaryRatesEnabled); + + return eHAL_STATUS_SUCCESS; +} + /* --------------------------------------------------------------------------- \fn sme_RoamReassoc \brief a wrapper function to request CSR to inititiate a re-association @@ -5032,8 +5018,9 @@ eHalStatus sme_OemDataReq(tHalHandle hHal, \sa --------------------------------------------------------------------------*/ -eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, void *pContext, - tANI_U8 *pSelfMacAddr, tANI_U8 *pbSessionId) +eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, + void *pContext, tANI_U8 *pSelfMacAddr, + tANI_U8 *pbSessionId) { eHalStatus status; tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); @@ -5047,7 +5034,8 @@ eHalStatus sme_OpenSession(tHalHandle hHal, csrRoamCompleteCallback callback, vo status = sme_AcquireGlobalLock( &pMac->sme ); if ( HAL_STATUS_SUCCESS( status ) ) { - status = csrRoamOpenSession( pMac, callback, pContext, pSelfMacAddr, pbSessionId ); + status = csrRoamOpenSession(pMac, callback, pContext, + pSelfMacAddr, pbSessionId); sme_ReleaseGlobalLock( &pMac->sme ); } @@ -5953,6 +5941,8 @@ eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg) tpAniSirGlobal pMac = PMAC_STRUCT(hHal); eHalStatus status = eHAL_STATUS_SUCCESS; tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = (tSirPrefNetworkFoundInd *)pMsg; + v_U8_t dumpSsId[SIR_MAC_MAX_SSID_LENGTH + 1]; + tANI_U8 ssIdLength = 0; if (NULL == pMsg) { @@ -5963,16 +5953,42 @@ eHalStatus sme_PreferredNetworkFoundInd (tHalHandle hHal, void* pMsg) { if (pPrefNetworkFoundInd->ssId.length > 0) { - smsLog(pMac, LOG1, "Preferred Network Found Indication in %s(), SSID=%s", - __func__, pPrefNetworkFoundInd->ssId.ssId); - + ssIdLength = CSR_MIN(SIR_MAC_MAX_SSID_LENGTH, + pPrefNetworkFoundInd->ssId.length); + vos_mem_copy(dumpSsId, pPrefNetworkFoundInd->ssId.ssId, ssIdLength); + dumpSsId[ssIdLength] = 0; + smsLog(pMac, LOG2, "%s:SSID=%s frame length %d", + __func__, dumpSsId, pPrefNetworkFoundInd->frameLength); + + /* Flush scan results, So as to avoid indication/updation of + * stale entries, which may not have aged out during APPS collapse + */ + sme_ScanFlushResult(hHal,0); + + //Save the frame to scan result + if (pPrefNetworkFoundInd->mesgLen > sizeof(tSirPrefNetworkFoundInd)) + { + //we may have a frame + status = csrScanSavePreferredNetworkFound(pMac, + pPrefNetworkFoundInd); + if (!HAL_STATUS_SUCCESS(status)) + { + smsLog(pMac, LOGE, FL(" fail to save preferred network")); + } + } + else + { + smsLog(pMac, LOGE, FL(" not enough data length %d needed %d"), + pPrefNetworkFoundInd->mesgLen, sizeof(tSirPrefNetworkFoundInd)); + } /* Call Preferred Netowrk Found Indication callback routine. */ - if (pMac->pmc.prefNetwFoundCB != NULL) - { - pMac->pmc.prefNetwFoundCB(pMac->pmc.preferredNetworkFoundIndCallbackContext, pPrefNetworkFoundInd); + if (HAL_STATUS_SUCCESS(status) && (pMac->pmc.prefNetwFoundCB != NULL)) + { + pMac->pmc.prefNetwFoundCB( + pMac->pmc.preferredNetworkFoundIndCallbackContext, + pPrefNetworkFoundInd); } - } else { @@ -6145,12 +6161,6 @@ eHalStatus sme_HandleChangeCountryCode(tpAniSirGlobal pMac, void *pMsgBuf) return status; } - /* purge current scan results - if i don't do this than I still get old ap's (of different country code) as available (even if they are powered off). - Looks like a bug in current scan sequence. - */ - csrScanFlushResult(pMac); - /* overwrite the defualt country code */ palCopyMemory(pMac->hHdd, pMac->scan.countryCodeDefault, pMac->scan.countryCodeCurrent, WNI_CFG_COUNTRY_CODE_LEN); @@ -6201,7 +6211,7 @@ eHalStatus sme_8023MulticastList (tHalHandle hHal, tANI_U8 sessionId, tpSirRcvFl tCsrRoamSession *pSession = NULL; VOS_TRACE( VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, "%s: " - "ulMulticastAddrCnt=%d, multicastAddr[0]=%d", __func__, + "ulMulticastAddrCnt=%d, multicastAddr[0]=%p", __func__, pMulticastAddrs->ulMulticastAddrCnt, pMulticastAddrs->multicastAddr[0]); @@ -6940,6 +6950,76 @@ eHalStatus sme_setRoamIntraBand(tHalHandle hHal, const v_BOOL_t nRoamIntraBand) return status ; } +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanNProbes + \brief function to update roam scan N probes + This function is called through dynamic setConfig callback function + to update roam scan N probes + \param hHal - HAL handle for device + \param nProbes number of probe requests to be sent out + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanNProbes(tHalHandle hHal, const v_U8_t nProbes) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanNProbes is changed from %d to %d", __func__, + pMac->roam.configParam.nProbes, + nProbes); + pMac->roam.configParam.nProbes = nProbes; + sme_ReleaseGlobalLock( &pMac->sme ); + } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_NPROBES_CHANGED); + } +#endif + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_UpdateRoamScanHomeAwayTime + \brief function to update roam scan Home away time + This function is called through dynamic setConfig callback function + to update roam scan home away time + \param hHal - HAL handle for device + \param nRoamScanAwayTime Scan home away time + \- return Success or failure + -------------------------------------------------------------------------*/ +eHalStatus sme_UpdateRoamScanHomeAwayTime(tHalHandle hHal, const v_U16_t nRoamScanHomeAwayTime) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanHomeAwayTime is changed from %d to %d", __func__, + pMac->roam.configParam.nRoamScanHomeAwayTime, + nRoamScanHomeAwayTime); + pMac->roam.configParam.nRoamScanHomeAwayTime = nRoamScanHomeAwayTime; + sme_ReleaseGlobalLock( &pMac->sme ); + } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_HOME_AWAY_TIME_CHANGED); + } +#endif + return status; +} + + /* --------------------------------------------------------------------------- \fn sme_getRoamIntraBand \brief get Intra band roaming @@ -6952,6 +7032,30 @@ v_BOOL_t sme_getRoamIntraBand(tHalHandle hHal) return pMac->roam.configParam.nRoamIntraBand; } +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanNProbes + \brief get N Probes + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U8_t sme_getRoamScanNProbes(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nProbes; +} + +/* --------------------------------------------------------------------------- + \fn sme_getRoamScanHomeAwayTime + \brief get Roam scan home away time + \param hHal - HAL handle for device + \- return Success or failure + -------------------------------------------------------------------------*/ +v_U16_t sme_getRoamScanHomeAwayTime(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nRoamScanHomeAwayTime; +} + /* --------------------------------------------------------------------------- \fn sme_UpdateImmediateRoamRssiDiff @@ -7013,7 +7117,12 @@ eHalStatus sme_UpdateRoamRssiDiff(tHalHandle hHal, v_U8_t RoamRssiDiff) pMac->roam.configParam.RoamRssiDiff = RoamRssiDiff; sme_ReleaseGlobalLock( &pMac->sme ); } - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_RSSI_DIFF_CHANGED); + } +#endif return status ; } @@ -7046,6 +7155,77 @@ eHalStatus sme_UpdateFastTransitionEnabled(tHalHandle hHal, return status ; } + +/* --------------------------------------------------------------------------- + \fn sme_UpdateWESMode + \brief Update WES Mode + This function is called through dynamic setConfig callback function + to configure isWESModeEnabled + \param hHal - HAL handle for device + \return eHAL_STATUS_SUCCESS - SME update isWESModeEnabled config successfully. + Other status means SME is failed to update isWESModeEnabled. + -------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateWESMode(tHalHandle hHal, v_BOOL_t isWESModeEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set WES Mode to %d - old value is %d - roam state is %d", + isWESModeEnabled, + pMac->roam.configParam.isWESModeEnabled, + pMac->roam.neighborRoamInfo.neighborRoamState); + pMac->roam.configParam.isWESModeEnabled = isWESModeEnabled; + sme_ReleaseGlobalLock( &pMac->sme ); + } + + return status ; +} + +/* --------------------------------------------------------------------------- + \fn sme_SetRoamScanControl + \brief Set roam scan control + This function is called to set roam scan control + if roam scan control is set to 0, roaming scan cache is cleared + any value other than 0 is treated as invalid value + \param hHal - HAL handle for device + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME failure to update + -------------------------------------------------------------------------*/ +eHalStatus sme_SetRoamScanControl(tHalHandle hHal, v_BOOL_t roamScanControl) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan control to %d - old value is %d - roam state is %d", + roamScanControl, + pMac->roam.configParam.nRoamScanControl, + pMac->roam.neighborRoamInfo.neighborRoamState); + pMac->roam.configParam.nRoamScanControl = roamScanControl; + if ( 0 == roamScanControl) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully cleared roam scan cache"); + csrFlushBgScanRoamChannelList(pMac); +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_FLUSH_CHANNEL_LIST); + } +#endif + } + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status ; +} #endif /* (WLAN_FEATURE_VOWIFI_11R) || (FEATURE_WLAN_CCX) || (FEATURE_WLAN_LFR) */ #ifdef FEATURE_WLAN_LFR @@ -7154,6 +7334,12 @@ eHalStatus sme_UpdateIsCcxFeatureEnabled(tHalHandle hHal, sme_UpdateConfigFwRssiMonitoring(hHal, FALSE); } } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CCX_INI_CFG_CHANGED); + } +#endif return eHAL_STATUS_SUCCESS; } #endif /* FEATURE_WLAN_CCX */ @@ -7217,6 +7403,12 @@ eHalStatus sme_setNeighborLookupRssiThreshold(tHalHandle hHal, sme_ReleaseGlobalLock( &pMac->sme ); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_LOOKUP_THRESH_CHANGED); + } +#endif return status; } @@ -7297,8 +7489,48 @@ eHalStatus sme_setNeighborScanRefreshPeriod(tHalHandle hHal, sme_ReleaseGlobalLock( &pMac->sme ); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, + REASON_NEIGHBOR_SCAN_REFRESH_PERIOD_CHANGED); + } +#endif + return status ; +} + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*-------------------------------------------------------------------------- + \brief sme_UpdateRoamScanOffloadEnabled() - enable/disable roam scan offload feaure + It is used at in the REG_DYNAMIC_VARIABLE macro definition of + gRoamScanOffloadEnabled. + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return eHAL_STATUS_SUCCESS - SME update config successfully. + Other status means SME is failed to update. + \sa + --------------------------------------------------------------------------*/ + +eHalStatus sme_UpdateRoamScanOffloadEnabled(tHalHandle hHal, + v_BOOL_t nRoamScanOffloadEnabled) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: gRoamScanOffloadEnabled is changed from %d to %d", __func__, + pMac->roam.configParam.isRoamOffloadScanEnabled, + nRoamScanOffloadEnabled); + pMac->roam.configParam.isRoamOffloadScanEnabled = nRoamScanOffloadEnabled; + sme_ReleaseGlobalLock( &pMac->sme ); + } + return status ; } +#endif /*-------------------------------------------------------------------------- \brief sme_getNeighborScanRefreshPeriod() - get neighbor scan results refresh period @@ -7519,7 +7751,7 @@ eHalStatus sme_ChangeRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); eHalStatus status = eHAL_STATUS_SUCCESS; tpCsrNeighborRoamControlInfo pNeighborRoamInfo = &pMac->roam.neighborRoamInfo; - tANI_U8 oldChannelList[128] = {0}; + tANI_U8 oldChannelList[WNI_CFG_VALID_CHANNEL_LIST_LEN*2] = {0}; tANI_U8 newChannelList[128] = {0}; tANI_U8 i = 0, j = 0; @@ -7534,25 +7766,36 @@ eHalStatus sme_ChangeRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); } } - csrFlushAndCreateBgScanRoamChannelList(pMac, pChannelList, numChannels); + csrFlushBgScanRoamChannelList(pMac); + csrCreateBgScanRoamChannelList(pMac, pChannelList, numChannels); status = csrUpdateBgScanConfigIniChannelList(pMac, csrGetCurrentBand(hHal)); - if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) + if ( HAL_STATUS_SUCCESS( status )) { - j = 0; - for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++) + sme_SetRoamScanControl(hHal, 1); + if (NULL != pNeighborRoamInfo->cfgParams.channelInfo.ChannelList) { - j += snprintf(newChannelList + j, sizeof(newChannelList) - j," %d", - pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); + j = 0; + for (i = 0; i < pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; i++) + { + j += snprintf(newChannelList + j, sizeof(newChannelList) - j," %d", + pNeighborRoamInfo->cfgParams.channelInfo.ChannelList[i]); + } } - } - VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, - "LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d", - newChannelList, oldChannelList, - pMac->roam.neighborRoamInfo.neighborRoamState); + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "LFR runtime successfully set roam scan channels to %s - old value is %s - roam state is %d", + newChannelList, oldChannelList, + pMac->roam.neighborRoamInfo.neighborRoamState); + } sme_ReleaseGlobalLock( &pMac->sme ); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_CHANNEL_LIST_CHANGED); + } +#endif return status ; } @@ -7584,6 +7827,12 @@ eHalStatus sme_ChangeCountryValidChannelListByRevision(tHalHandle hHal, csrInitCountryValidChannelList(pMac, Revision); sme_ReleaseGlobalLock( &pMac->sme ); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + if (pMac->roam.configParam.isRoamOffloadScanEnabled) + { + csrRoamOffloadScan(pMac, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_VALID_CHANNEL_LIST_CHANGED); + } +#endif return status ; } @@ -7628,8 +7877,9 @@ eHalStatus sme_getRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, { VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_WARN, "Roam Scan channel list is NOT yet initialized"); + *pNumChannels = 0; sme_ReleaseGlobalLock( &pMac->sme ); - return eHAL_STATUS_NOT_INITIALIZED; + return status; } *pNumChannels = pNeighborRoamInfo->cfgParams.channelInfo.numOfChannels; @@ -7640,7 +7890,6 @@ eHalStatus sme_getRoamScanChannelList(tHalHandle hHal, tANI_U8 *pChannelList, pOutPtr[i] = '\0'; sme_ReleaseGlobalLock( &pMac->sme ); } - return status ; } @@ -7664,6 +7913,32 @@ eHalStatus sme_GetCountryRevision(tHalHandle hHal, tANI_U8 *pRevision) return status; } +/*-------------------------------------------------------------------------- + \brief sme_GetWESMode() - get WES Mode + This is a synchronous call + \param hHal - The handle returned by macOpen + \return v_U8_t - WES Mode Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetWESMode(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.isWESModeEnabled; +} + +/*-------------------------------------------------------------------------- + \brief sme_GetRoamScanControl() - get scan control + This is a synchronous call + \param hHal - The handle returned by macOpen. + \return v_BOOL_t - Enabled(1)/Disabled(0) + \sa + --------------------------------------------------------------------------*/ +v_BOOL_t sme_GetRoamScanControl(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->roam.configParam.nRoamScanControl; +} + /*-------------------------------------------------------------------------- \brief sme_getIsCcxFeatureEnabled() - get CCX feature enabled or not This is a synchronuous call @@ -7843,16 +8118,6 @@ VOS_STATUS sme_DeleteTdlsPeerSta(tHalHandle hHal, tANI_U8 sessionId, tSirMacAddr return status ; } -/* --------------------------------------------------------------------------- - \fn sme_IsPmcBmps - \API to Check if PMC state is BMPS. - - \- return v_BOOL_t - -------------------------------------------------------------------------*/ -v_BOOL_t sme_IsPmcBmps(tHalHandle hHal) -{ - return (BMPS == pmcGetPmcState(hHal)); -} /* --------------------------------------------------------------------------- \fn sme_SetTdlsPowerSaveProhibited \API to set/reset the isTdlsPowerSaveProhibited. @@ -7867,6 +8132,17 @@ void sme_SetTdlsPowerSaveProhibited(tHalHandle hHal, v_BOOL_t val) return; } #endif +/* --------------------------------------------------------------------------- + \fn sme_IsPmcBmps + \API to Check if PMC state is BMPS. + + \- return v_BOOL_t + -------------------------------------------------------------------------*/ +v_BOOL_t sme_IsPmcBmps(tHalHandle hHal) +{ + return (BMPS == pmcGetPmcState(hHal)); +} + #ifdef FEATURE_WLAN_TDLS_INTERNAL /* * SME API to start TDLS discovery Procedure @@ -7969,3 +8245,90 @@ VOS_STATUS sme_StartTdlsLinkTeardownReq(tHalHandle hHal, tANI_U8 sessionId, tSir #endif /* FEATURE_WLAN_TDLS */ +eHalStatus sme_UpdateDfsSetting(tHalHandle hHal, tANI_U8 fUpdateEnableDFSChnlScan) +{ + eHalStatus status = eHAL_STATUS_FAILURE; + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + smsLog(pMac, LOG2, FL("enter")); + status = sme_AcquireGlobalLock( &pMac->sme ); + if ( HAL_STATUS_SUCCESS( status ) ) + { + pMac->scan.fEnableDFSChnlScan = fUpdateEnableDFSChnlScan; + sme_ReleaseGlobalLock( &pMac->sme ); + } + smsLog(pMac, LOG2, FL("exit status %d"), status); + + return (status); +} + +/* + * SME API to enable/disable WLAN driver initiated SSR + */ +void sme_UpdateEnableSSR(tHalHandle hHal, tANI_BOOLEAN enableSSR) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + eHalStatus status = eHAL_STATUS_SUCCESS; + + status = sme_AcquireGlobalLock(&pMac->sme); + if (HAL_STATUS_SUCCESS(status)) + { + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_DEBUG, + "SSR level is changed %d", enableSSR); + /* not serializing this messsage, as this is only going + * to set a variable in WDA/WDI + */ + WDA_SetEnableSSR(enableSSR); + sme_ReleaseGlobalLock(&pMac->sme); + } + return; +} + +/* + * SME API to check if there is any infra station or + * P2P client is connected + */ +VOS_STATUS sme_isSta_p2p_clientConnected(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + if(csrIsInfraConnected(pMac)) + { + return VOS_STATUS_SUCCESS; + } + return VOS_STATUS_E_FAILURE; +} + +/*-------------------------------------------------------------------------- + \brief sme_enable_disable_split_scan() - a wrapper function to set the split + scan parameter. + This is a synchronous call + \param hHal - The handle returned by macOpen + \return NONE. + \sa + --------------------------------------------------------------------------*/ +void sme_enable_disable_split_scan (tHalHandle hHal, tANI_U8 nNumStaChan, + tANI_U8 nNumP2PChan) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + + pMac->roam.configParam.nNumStaChanCombinedConc = nNumStaChan; + pMac->roam.configParam.nNumP2PChanCombinedConc = nNumP2PChan; + + VOS_TRACE(VOS_MODULE_ID_SME, VOS_TRACE_LEVEL_INFO, + "%s: SCAN nNumStaChanCombinedConc : %d," + "nNumP2PChanCombinedConc : %d ", + __func__, nNumStaChan, nNumP2PChan); + + return; +} +/*------------------------------------------------------------------------- + \brief sme_SetCurrDeviceMode() - Sets the current operating device mode. + \param hHal - The handle returned by macOpen. + \param currDeviceMode - Current operating device mode. + --------------------------------------------------------------------------*/ +void sme_SetCurrDeviceMode (tHalHandle hHal, tVOS_CON_MODE currDeviceMode) +{ + tpAniSirGlobal pMac = PMAC_STRUCT(hHal); + pMac->sme.currDeviceMode = currDeviceMode; + return; +} diff --git a/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c b/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c index 81219f6402b..929592b9d16 100644 --- a/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c +++ b/drivers/staging/prima/CORE/SME/src/sme_common/sme_FTApi.c @@ -70,7 +70,8 @@ void sme_FTOpen(tHalHandle hHal) pMac->ft.ftSmeContext.reassoc_ft_ies = NULL; pMac->ft.ftSmeContext.reassoc_ft_ies_length = 0; - + pMac->ft.ftSmeContext.setFTPreAuthState = FALSE; + pMac->ft.ftSmeContext.setFTPTKState = FALSE; status = palTimerAlloc(pMac->hHdd, &pMac->ft.ftSmeContext.preAuthReassocIntvlTimer, sme_PreauthReassocIntvlTimerCallback, (void *)pMac); @@ -81,6 +82,7 @@ void sme_FTOpen(tHalHandle hHal) } pMac->ft.ftSmeContext.psavedFTPreAuthRsp = NULL; + pMac->ft.ftSmeContext.pCsrFTKeyInfo = NULL; pMac->ft.ftSmeContext.FTState = eFT_START_READY; } @@ -130,6 +132,17 @@ void sme_FTClose(tHalHandle hHal) palTimerFree(pMac->hHdd, pMac->ft.ftSmeContext.preAuthReassocIntvlTimer); } +void sme_SetFTPreAuthState(tHalHandle hHal, v_BOOL_t state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + pMac->ft.ftSmeContext.setFTPreAuthState = state; +} + +v_BOOL_t sme_GetFTPreAuthState(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->ft.ftSmeContext.setFTPreAuthState; +} /*-------------------------------------------------------------------------- Each time the supplicant sends down the FT IEs to the driver. @@ -259,17 +272,17 @@ eHalStatus sme_FTSendUpdateKeyInd(tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo) tANI_U16 msgLen; eHalStatus status = eHAL_STATUS_FAILURE; tAniEdType tmpEdType; - tAniKeyDirection tmpDirection; - //tANI_U8 *pBuf; - tANI_U8 *p = NULL; + tSirKeyMaterial *keymaterial = NULL; tAniEdType edType; tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); +#if defined WLAN_FEATURE_VOWIFI_11R_DEBUG int i = 0; - smsLog(pMac, LOGE, FL("keyLength %d"), pFTKeyInfo->keyLength); + smsLog(pMac, LOG1, FL("keyLength %d"), pFTKeyInfo->keyLength); - for(i=0; ikeyLength; i++) - smsLog(pMac, LOGE, FL("%02x"), pFTKeyInfo->Key[i]); + for (i=0; ikeyLength; i++) + smsLog(pMac, LOG1, FL("%02x"), pFTKeyInfo->Key[i]); +#endif msgLen = sizeof( tANI_U16) + sizeof( tANI_U16 ) + sizeof( pMsg->keyMaterial.length ) + sizeof( pMsg->keyMaterial.edType ) + @@ -285,66 +298,78 @@ eHalStatus sme_FTSendUpdateKeyInd(tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo) pMsg->messageType = pal_cpu_to_be16((tANI_U16)eWNI_SME_FT_UPDATE_KEY); pMsg->length = pal_cpu_to_be16(msgLen); - p = (tANI_U8 *)&pMsg->keyMaterial; + keymaterial = &pMsg->keyMaterial; + + keymaterial->length = pFTKeyInfo->keyLength; - // Set the pMsg->keyMaterial.length field (this length is defined as all data that follows the edType field + edType = csrTranslateEncryptTypeToEdType( pFTKeyInfo->encType ); + tmpEdType = pal_cpu_to_be32(edType); + keymaterial->edType = tmpEdType; + + // Set the pMsg->keyMaterial.length field (this length is defined as all + // data that follows the edType field // in the tSirKeyMaterial keyMaterial; field). // - // !!NOTE: This keyMaterial.length contains the length of a MAX size key, though the keyLength can be + // !!NOTE: This keyMaterial.length contains the length of a MAX size key, + // though the keyLength can be // shorter than this max size. Is LIM interpreting this ok ? - p = pal_set_U16( p, pal_cpu_to_be16((tANI_U16)( sizeof( pMsg->keyMaterial.numKeys ) + - ( pMsg->keyMaterial.numKeys * sizeof( pMsg->keyMaterial.key ) ) )) ); + keymaterial->numKeys = 1; + keymaterial->key[ 0 ].keyId = pFTKeyInfo->keyId; + keymaterial->key[ 0 ].unicast = (tANI_U8)eANI_BOOLEAN_TRUE; + keymaterial->key[ 0 ].keyDirection = pFTKeyInfo->keyDirection; - // set pMsg->keyMaterial.edType - edType = csrTranslateEncryptTypeToEdType( pFTKeyInfo->encType ); - tmpEdType = pal_cpu_to_be32(edType); - palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpEdType, sizeof(tAniEdType) ); - p += sizeof( pMsg->keyMaterial.edType ); - - // set the pMsg->keyMaterial.numKeys field - *p = pMsg->keyMaterial.numKeys; - p += sizeof( pMsg->keyMaterial.numKeys ); - - // set pSirKey->keyId = keyId; - *p = pMsg->keyMaterial.key[ 0 ].keyId; - p += sizeof( pMsg->keyMaterial.key[ 0 ].keyId ); - - // set pSirKey->unicast = (tANI_U8)fUnicast; - *p = (tANI_U8)eANI_BOOLEAN_TRUE; - p += sizeof( pMsg->keyMaterial.key[ 0 ].unicast ); - - // set pSirKey->keyDirection = aniKeyDirection; - tmpDirection = pal_cpu_to_be32(pFTKeyInfo->keyDirection); - palCopyMemory( pMac->hHdd, p, (tANI_U8 *)&tmpDirection, sizeof(tAniKeyDirection) ); - p += sizeof(tAniKeyDirection); - // pSirKey->keyRsc = ;; - palCopyMemory( pMac->hHdd, p, pFTKeyInfo->keyRsc, CSR_MAX_RSC_LEN ); - p += sizeof( pMsg->keyMaterial.key[ 0 ].keyRsc ); - - // set pSirKey->paeRole - *p = pFTKeyInfo->paeRole; // 0 is Supplicant - p++; - - // set pSirKey->keyLength = keyLength; - p = pal_set_U16( p, pal_cpu_to_be16(pFTKeyInfo->keyLength) ); - - if ( pFTKeyInfo->keyLength && pFTKeyInfo->Key ) - { - palCopyMemory( pMac->hHdd, p, pFTKeyInfo->Key, pFTKeyInfo->keyLength ); + palCopyMemory( pMac->hHdd, &keymaterial->key[ 0 ].keyRsc, + pFTKeyInfo->keyRsc, CSR_MAX_RSC_LEN ); + + keymaterial->key[ 0 ].paeRole = pFTKeyInfo->paeRole; + + keymaterial->key[ 0 ].keyLength = pFTKeyInfo->keyLength; + + if ( pFTKeyInfo->keyLength && pFTKeyInfo->Key ) + { + palCopyMemory( pMac->hHdd, &keymaterial->key[ 0 ].key, + pFTKeyInfo->Key, pFTKeyInfo->keyLength ); if(pFTKeyInfo->keyLength == 16) { - smsLog(pMac, LOG1, " SME Set keyIdx (%d) encType(%d) key = %02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", - pFTKeyInfo->keyId, edType, pFTKeyInfo->Key[0], pFTKeyInfo->Key[1], pFTKeyInfo->Key[2], pFTKeyInfo->Key[3], pFTKeyInfo->Key[4], - pFTKeyInfo->Key[5], pFTKeyInfo->Key[6], pFTKeyInfo->Key[7], pFTKeyInfo->Key[8], - pFTKeyInfo->Key[9], pFTKeyInfo->Key[10], pFTKeyInfo->Key[11], pFTKeyInfo->Key[12], pFTKeyInfo->Key[13], pFTKeyInfo->Key[14], pFTKeyInfo->Key[15]); + smsLog(pMac, LOG1, "SME Set Update Ind keyIdx (%d) encType(%d) key = " + "%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X", + pMsg->keyMaterial.key[0].keyId, (tAniEdType)pMsg->keyMaterial.edType, + pMsg->keyMaterial.key[0].key[0], pMsg->keyMaterial.key[0].key[1], + pMsg->keyMaterial.key[0].key[2], pMsg->keyMaterial.key[0].key[3], + pMsg->keyMaterial.key[0].key[4], pMsg->keyMaterial.key[0].key[5], + pMsg->keyMaterial.key[0].key[6], pMsg->keyMaterial.key[0].key[7], + pMsg->keyMaterial.key[0].key[8], pMsg->keyMaterial.key[0].key[9], + pMsg->keyMaterial.key[0].key[10], pMsg->keyMaterial.key[0].key[11], + pMsg->keyMaterial.key[0].key[12], pMsg->keyMaterial.key[0].key[13], + pMsg->keyMaterial.key[0].key[14], pMsg->keyMaterial.key[0].key[15]); } } + vos_mem_copy( &pMsg->bssId[ 0 ], + &pFTKeyInfo->peerMac[ 0 ], + sizeof(tCsrBssid) ); + + smsLog(pMac, LOG1, "BSSID = %02X-%02X-%02X-%02X-%02X-%02X", + pMsg->bssId[0], pMsg->bssId[1], pMsg->bssId[2], + pMsg->bssId[3], pMsg->bssId[4], pMsg->bssId[5]); + status = palSendMBMessage(pMac->hHdd, pMsg); return( status ); } +v_BOOL_t sme_GetFTPTKState(tHalHandle hHal) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + return pMac->ft.ftSmeContext.setFTPTKState; +} + +void sme_SetFTPTKState(tHalHandle hHal, v_BOOL_t state) +{ + tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); + pMac->ft.ftSmeContext.setFTPTKState = state; +} + eHalStatus sme_FTUpdateKey( tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo ) { tpAniSirGlobal pMac = PMAC_STRUCT( hHal ); @@ -372,11 +397,28 @@ eHalStatus sme_FTUpdateKey( tHalHandle hHal, tCsrRoamSetKey * pFTKeyInfo ) switch(pMac->ft.ftSmeContext.FTState) { case eFT_SET_KEY_WAIT: - status = eHAL_STATUS_FT_PREAUTH_KEY_WAIT; - pMac->ft.ftSmeContext.FTState = eFT_START_READY; + if (sme_GetFTPreAuthState (hHal) == TRUE) + { + status = sme_FTSendUpdateKeyInd(pMac, pFTKeyInfo); + if (status != 0 ) + { + smsLog( pMac, LOGE, "%s: Key set failure %d", __func__, + status); + pMac->ft.ftSmeContext.setFTPTKState = FALSE; + status = eHAL_STATUS_FT_PREAUTH_KEY_FAILED; + } + else + { + pMac->ft.ftSmeContext.setFTPTKState = TRUE; + status = eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS; + smsLog( pMac, LOG1, "%s: Key set success", __func__); + } + sme_SetFTPreAuthState(hHal, FALSE); + } + pMac->ft.ftSmeContext.FTState = eFT_START_READY; #ifdef WLAN_FEATURE_VOWIFI_11R_DEBUG - smsLog( pMac, LOG1, "%s: state changed to %d", __func__, - pMac->ft.ftSmeContext.FTState); + smsLog( pMac, LOG1, "%s: state changed to %d status %d", __func__, + pMac->ft.ftSmeContext.FTState, status); #endif break; diff --git a/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c b/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c index b3a49dfb250..63c021ddf16 100644 --- a/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c +++ b/drivers/staging/prima/CORE/SVC/src/btc/wlan_btc_svc.c @@ -207,6 +207,7 @@ void send_btc_nlink_msg (int type, int dest_pid) default: VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR, "BTC: Attempt to send unknown nlink message %d\n", type); + kfree_skb(skb); return; } if(dest_pid == 0) diff --git a/drivers/staging/prima/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c b/drivers/staging/prima/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c index 7fa2185ecad..8e3e579d16a 100644 --- a/drivers/staging/prima/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c +++ b/drivers/staging/prima/CORE/SVC/src/ptt/wlan_ptt_sock_svc.c @@ -295,12 +295,12 @@ static int ptt_sock_rx_nlink_msg (struct sk_buff * skb) switch (type) { case ANI_NL_MSG_PUMAC: //Message from the PTT socket APP PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: Received ANI_NL_MSG_PUMAC Msg [0x%X]\n", - __func__, type, radio); + __func__, type); ptt_proc_pumac_msg(skb, &wnl->wmsg, radio); break; case ANI_NL_MSG_PTT: //Message from Quarky GUI PTT_TRACE(VOS_TRACE_LEVEL_INFO, "%s: Received ANI_NL_MSG_PTT Msg [0x%X]\n", - __func__, type, radio); + __func__, type); ptt_proc_quarky_msg(wnl, &wnl->wmsg, radio); break; default: diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palApi.h b/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palApi.h index 65f8d3571b2..f1d28159602 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palApi.h +++ b/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palApi.h @@ -18,67 +18,43 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ +/** ------------------------------------------------------------------------- * + ------------------------------------------------------------------------- * -/** ------------------------------------------------------------------------- * - ------------------------------------------------------------------------- * - \file palApi.h - + \brief Exports and types for the Platform Abstraction Layer interfaces. - - $Id$ - + + $Id$ + Copyright (C) 2006 Airgo Networks, Incorporated This file contains all the interfaces for thge Platform Abstration Layer - functions. It is intended to be included in all modules that are using + functions. It is intended to be included in all modules that are using the PAL interfaces. - + ========================================================================== */ #ifndef PALAPI_H__ #define PALAPI_H__ #include "halTypes.h" -#include "palPipes.h" -//#include "palErrIsr.h" -//#include "halFrameInfo.h" /** \mainpage Platform Abstraction Layer (PAL) - + \section intro Introduction - + palApi is the Platform Abstration Layer. - - This is the latest attempt to abstract the entire Platform, including the - hardware, chip, OS and Bus into a generic API. We are doing this to give + + This is the latest attempt to abstract the entire Platform, including the + hardware, chip, OS and Bus into a generic API. We are doing this to give the MAC the ability to call - generic APIs that will allow the MAC to function in an abstract manner + generic APIs that will allow the MAC to function in an abstract manner with any Airgo chipset, on any supported OS (Windows and Linux for now) across any system bus interface (PCI, PCIe, Cardbus, USB, etc.). - + \todo - - palReadRegister: register read + - palReadRegister: register read -# add an Open/Close abstraction to accomodate the PAL before the entire MAC is loaded. -# Review with Linux folks to see this basic scructure works for them. -# Figure out how to organize the directory structure @@ -87,10 +63,10 @@ - palTx: an abstraction for transmit frames that manages the Td and Tm rings - palRx: an abstracion for receiving frames from a chip across any of the supported buses - palInterrupt: abstract the interrupts into the HAL - - + + \section impl_notes Implementation Notes - + \subsection subsection_codeStructure Code strucure */ @@ -101,18 +77,18 @@ \fn palReadRegister \brief chip and bus agnostic funtion to read a register value - + \param hHdd - HDD context handle - + \param regAddress - address (offset) of the register to be read from the start of register space. - + \param pRegValue - pointer to the memory where the register contents are written - - \return eHalStatus - status of the register read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the register read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palReadRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 *pRegValue ); @@ -122,18 +98,18 @@ eHalStatus palReadRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 *pReg \fn palWriteRegister \brief chip and bus agnostic funtion to write a register value - + \param hHdd - HDD context handle - + \param regAddress - address (offset) of the register to be read from the start of register space. - + \param pRegValue - pointer to the value being written into the register - - \return eHalStatus - status of the register read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the register read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 regValue ); @@ -142,18 +118,18 @@ eHalStatus palWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 regV \fn palAsyncWriteRegister \brief chip and bus agnostic async funtion to write a register value - + \param hHdd - HDD context handle - + \param regAddress - address (offset) of the register to be written from the start of register space. - + \param regValue - value being written into the register - - \return eHalStatus - status of the register write. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the register write. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palAsyncWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 regValue ); @@ -164,21 +140,21 @@ eHalStatus palAsyncWriteRegister( tHddHandle hHdd, tANI_U32 regAddress, tANI_U32 \fn palReadDeviceMemory \brief chip and bus agnostic funtion to read memory from the chip - + \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the + + \param memOffset - address (offset) of the memory from the top of the memory map (as exposed to the host) where the memory will be read from. - + \param pBuffer - pointer to a buffer where the memory will be placed in host memory space after retreived from the chip. - + \param numBytes - the number of bytes to be read. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palReadDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); @@ -187,47 +163,47 @@ eHalStatus palReadDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pB \fn palWriteDeviceMemory \brief chip and bus agnostic funtion to write memory to the chip - + \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the on-chip + + \param memOffset - address (offset) of the memory from the top of the on-chip memory that will be written. - - \param pBuffer - pointer to a buffer that has the source data that will be + + \param pBuffer - pointer to a buffer that has the source data that will be written to the chip. - + \param numBytes - the number of bytes to be written. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ -eHalStatus palWriteDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); +eHalStatus palWriteDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); /** --------------------------------------------------------------------------- \fn palAllocateMemory - \brief OS agnostic funtion to allocate host memory. - - \note Host memory that needs to be shared between the host and the + \brief OS agnostic funtion to allocate host memory. + + \note Host memory that needs to be shared between the host and the device needs to be allocated with the palAllocateSharedMemory() and free'd with palFreeSharedMemory() functions. - + \param hHdd - HDD context handle - - \param ppMemory - pointer to a void pointer where the address of the + + \param ppMemory - pointer to a void pointer where the address of the memory allocated will be placed upon return from this function. - + \param numBytes - the number of bytes to allocate. - - \return eHalStatus - status of the register read. Note that this function - can fail. In the case of a failure, a non-successful return code will be + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be returned and no memory will be allocated (the *ppMemory will be NULL so don't try to use it unless the status returns success). - + -------------------------------------------------------------------------------*/ #ifdef MEMORY_DEBUG #define palAllocateMemory(hHdd, ppMemory, numBytes) palAllocateMemory_debug(hHdd, ppMemory, numBytes, __FILE__, __LINE__) @@ -241,22 +217,22 @@ eHalStatus palAllocateMemory( tHddHandle hHdd, void **ppMemory, tANI_U32 numByte \fn palFreeMemory - \brief OS agnostic funtion to free host memory that was allocated with + \brief OS agnostic funtion to free host memory that was allocated with palAllcoateMemory() calls. - - \note Host memory that needs to be shared between the host and the + + \note Host memory that needs to be shared between the host and the device needs to be allocated with the palAllocateSharedMemory() and free'd with palFreeSharedMemory() functions. - + \param hHdd - HDD context handle - + \param pMemory - pointer to memory that will be free'd. - - \return eHalStatus - status of the register read. Note that this function - can fail. In the case of a failure, a non-successful return code will be + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be returned and no memory will be allocated (the *ppMemory will be NULL so don't try to use it unless the status returns success). - + -------------------------------------------------------------------------------*/ eHalStatus palFreeMemory( tHddHandle hHdd, void *pMemory ); @@ -267,20 +243,20 @@ eHalStatus palFreeMemory( tHddHandle hHdd, void *pMemory ); \fn palFillMemory \brief OS agnostic funtion to fill host memory with a specified byte value - + \param hHdd - HDD context handle - + \param pMemory - pointer to memory that will be filled. - + \param numBytes - the number of bytes to be filled. - + \param fillValue - the byte to be written to fill the memory with. - - \return eHalStatus - status of the register read. Note that this function - can fail. In the case of a failure, a non-successful return code will be + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be returned and no memory will be allocated (the *ppMemory will be NULL so don't try to use it unless the status returns success). - + -------------------------------------------------------------------------------*/ eHalStatus palFillMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes, tANI_BYTE fillValue ); @@ -289,17 +265,17 @@ eHalStatus palFillMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes, tAN \fn palCopyMemory \brief OS agnostic funtion to copy host memory from one location to another - + \param hHdd - HDD context handle - + \param pSrc - pointer to source memory location (to copy from) \param pSrc - pointer to destination memory location (to copy to) - + \param numBytes - the number of bytes to be be copied. - - \return eHalStatus - status of the memory copy - + + \return eHalStatus - status of the memory copy + -------------------------------------------------------------------------------*/ eHalStatus palCopyMemory( tHddHandle hHdd, void *pDst, const void *pSrc, tANI_U32 numBytes ); @@ -308,76 +284,76 @@ eHalStatus palCopyMemory( tHddHandle hHdd, void *pDst, const void *pSrc, tANI_U3 \fn palFillMemory \brief OS agnostic funtion to fill host memory with a specified byte value - + \param hHdd - HDD context handle - + \param pMemory - pointer to memory that will be filled. - + \param numBytes - the number of bytes to be filled. - + \param fillValue - the byte to be written to fill the memory with. - - \return eHalStatus - status of the register read. Note that this function - can fail. In the case of a failure, a non-successful return code will be + + \return eHalStatus - status of the register read. Note that this function + can fail. In the case of a failure, a non-successful return code will be returned and no memory will be allocated (the *ppMemory will be NULL so don't try to use it unless the status returns success). - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION eHalStatus palZeroMemory( tHddHandle hHdd, void *pMemory, tANI_U32 numBytes ) { return( palFillMemory( hHdd, pMemory, numBytes, 0 ) ); -} +} /** --------------------------------------------------------------------------- \fn palEqualMemory - \brief OS agnostic funtion to compare two pieces of memory, similar to + \brief OS agnostic funtion to compare two pieces of memory, similar to memcmp function in standard C. - + \param hHdd - HDD context handle - + \param pMemory1 - pointer to one location in memory to compare. \param pMemory2 - pointer to second location in memory to compare. - + \param numBytes - the number of bytes to compare. - + \return tANI_BOOLEAN - returns a boolean value that tells if the memory - locations are equal or now equal. - + locations are equal or now equal. + -------------------------------------------------------------------------------*/ -tANI_BOOLEAN palEqualMemory( tHddHandle hHdd, void *pMemory1, void *pMemory2, tANI_U32 numBytes ); +tANI_BOOLEAN palEqualMemory( tHddHandle hHdd, void *pMemory1, void *pMemory2, tANI_U32 numBytes ); /** --------------------------------------------------------------------------- \fn palFillDeviceMemory - \brief OS agnostic funtion to fill device memory with a specified + \brief OS agnostic funtion to fill device memory with a specified 32bit value - + \param hHdd - HDD context handle - + \param memOffset - offset of the memory on the device to fill. - + \param numBytes - the number of bytes to be filled. - + \param fillValue - the byte pattern to fill into memory on the device - - \return eHalStatus - status of the register read. Note that this function - can fail. - - eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not + + \return eHalStatus - status of the register read. Note that this function + can fail. + + eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not a multiple of 4 bytes. - - eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a + + eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a 4 byte boundary. - - \note return failure if the memOffset is not 32bit aligned and not a + + \note return failure if the memOffset is not 32bit aligned and not a multiple of 4 bytes (the device does not support anything else). - + -------------------------------------------------------------------------------*/ eHalStatus palFillDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U32 numBytes, tANI_BYTE fillValue ); @@ -387,49 +363,49 @@ eHalStatus palFillDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U32 nu \fn palZeroDeviceMemory \brief OS agnostic funtion to fill device memory with a specified byte value - + \param hHdd - HDD context handle - + \param memOffset - offset of the memory on the device to fill. - + \param numBytes - the number of bytes to be filled. - + \param fillValue - the 32bit pattern to fill the memory with. - - \return eHalStatus - status of the register read. Note that this function - can fail. - - eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not + + \return eHalStatus - status of the register read. Note that this function + can fail. + + eHAL_STATUS_DEVICE_MEMORY_LENGTH_ERROR - length of the device memory is not a multiple of 4 bytes. - - eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a + + eHAL_STATUS_DEVICE_MEMORY_MISALIGNED - memory address is not aligned on a 4 byte boundary. - - \note return failure if the memOffset is not 32bit aligned and not a + + \note return failure if the memOffset is not 32bit aligned and not a multiple of 4 bytes (the device does not support anything else). - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION eHalStatus palZeroDeviceMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U32 numBytes ) { return( palFillDeviceMemory( hHdd, memOffset, numBytes, 0 ) ); -} +} /*---------------------------------------------------------------------------------- Allocate a packet for sending through the Tx APIs. \param hHdd - HDD context handle - + \param frmType - Frame type - + \param size \param data - - \param ppPacket - + \param ppPacket - - \return eHalStatus - + \return eHalStatus - ----------------------------------------------------------------------------------*/ eHalStatus palPktAlloc(tHddHandle hHdd, eFrameType frmType, tANI_U16 size, void **data, void **ppPacket) ; @@ -451,7 +427,7 @@ eHalStatus palSpinLockGive( tHddHandle hHdd, tPalSpinLockHandle hSpinLock ); //PAL lock functions end -//This function send a message to MAC, +//This function send a message to MAC, //pMsgBuf is a buffer allocated by caller. The actual structure varies base on message type //The beginning of the buffer can always map to tSirMbMsg //This function must take care of padding if it is required for the OS @@ -465,8 +441,8 @@ extern void palGetUnicastStats(tHddHandle hHdd, tANI_U32 *tx, tANI_U32 *rx); time difference. \param hHdd - HDD context handle - - \return tick count. + + \return tick count. ----------------------------------------------------------------------------------*/ tANI_U32 palGetTickCount(tHddHandle hHdd); @@ -476,21 +452,21 @@ tANI_U32 palGetTickCount(tHddHandle hHdd); \brief chip and bus agnostic function to read memory from the PHY register space as memory i.e. to read more than 4 bytes from the contiguous register space - + \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the + + \param memOffset - address (offset) of the memory from the top of the memory map (as exposed to the host) where the memory will be read from. - + \param pBuffer - pointer to a buffer where the memory will be placed in host memory space after retreived from the chip. - + \param numBytes - the number of bytes to be read. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palReadRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); @@ -503,19 +479,19 @@ eHalStatus palReadRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuff API does the write asynchronously. \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the on-chip + + \param memOffset - address (offset) of the memory from the top of the on-chip memory that will be written. - - \param pBuffer - pointer to a buffer that has the source data that will be + + \param pBuffer - pointer to a buffer that has the source data that will be written to the chip. - + \param numBytes - the number of bytes to be written. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palAsyncWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); @@ -524,23 +500,23 @@ eHalStatus palAsyncWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 \fn palWriteRegMemory \brief chip and bus agnostic function to write memory to the PHY register space as memory i.e. to write more than 4 bytes from the contiguous register space. The difference from the - above routine is, in USB interface, this routine performs the write synchronously where as + above routine is, in USB interface, this routine performs the write synchronously where as the above routine performs it asynchronously. \param hHdd - HDD context handle - - \param memOffset - address (offset) of the memory from the top of the on-chip + + \param memOffset - address (offset) of the memory from the top of the on-chip memory that will be written. - - \param pBuffer - pointer to a buffer that has the source data that will be + + \param pBuffer - pointer to a buffer that has the source data that will be written to the chip. - + \param numBytes - the number of bytes to be written. - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuffer, tANI_U32 numBytes ); @@ -549,15 +525,15 @@ eHalStatus palWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuf \fn palWaitRegVal - \brief is a blocking function which reads the register and waits for the given number of iterations + \brief is a blocking function which reads the register and waits for the given number of iterations until the read value matches the waitRegVal. The delay between is perIterWaitInNanoSec(in nanoseconds) - + \param hHdd - HDD context handle - + \param reg - address of the register to be read - + \param mask - mask to be applied for the read value - + \param waitRegVal - expected value from the register after applying the mask. \param perIterWaitInNanoSec - delay between the two iterations in nanoseconds @@ -565,14 +541,14 @@ eHalStatus palWriteRegMemory( tHddHandle hHdd, tANI_U32 memOffset, tANI_U8 *pBuf \param numIter - max number of reads before the timeout \param pReadRegVal - the value read from the register - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ -eHalStatus palWaitRegVal( tHddHandle hHdd, tANI_U32 reg, tANI_U32 mask, - tANI_U32 waitRegVal, tANI_U32 perIterWaitInNanoSec, +eHalStatus palWaitRegVal( tHddHandle hHdd, tANI_U32 reg, tANI_U32 mask, + tANI_U32 waitRegVal, tANI_U32 perIterWaitInNanoSec, tANI_U32 numIter, tANI_U32 *pReadRegVal ); /** --------------------------------------------------------------------------- @@ -583,17 +559,17 @@ eHalStatus palWaitRegVal( tHddHandle hHdd, tANI_U32 reg, tANI_U32 mask, and writes back the new value to the register \param hHdd - HDD context handle - + \param reg - address of the register to be modified. - + \param andMask - The value read will be ANDed with this mask \parma orMask - The value after applying the andMask will be ORed with this value - - \return eHalStatus - status of the memory read. Note that this function - can fail. In particular, when the card is removed, this function will return + + \return eHalStatus - status of the memory read. Note that this function + can fail. In particular, when the card is removed, this function will return a failure. - + -------------------------------------------------------------------------------*/ eHalStatus palReadModifyWriteReg( tHddHandle hHdd, tANI_U32 reg, tANI_U32 andMask, tANI_U32 orMask ); @@ -620,7 +596,7 @@ tANI_U16 pal_cpu_to_be16(tANI_U16 x) ; #if defined( ANI_LITTLE_BYTE_ENDIAN ) // Need to eliminate these and use the ani_cpu_to_le, etc. macros.... -ANI_INLINE_FUNCTION unsigned long i_htonl( unsigned long ul ) +ANI_INLINE_FUNCTION unsigned long i_htonl( unsigned long ul ) { return( ( ( ul & 0x000000ff ) << 24 ) | ( ( ul & 0x0000ff00 ) << 8 ) | @@ -653,14 +629,14 @@ ANI_INLINE_FUNCTION unsigned long i_ntohl( unsigned long ul ) \brief Assign 32-bit unsigned value to a byte array base on CPU's endianness. \note Caller must validate the byte array has enough space to hold the vlaue - + \param ptr - Starting address of a byte array - + \param value - The value to assign to the byte array - - \return - The address to the byte after the assignment. This may or may not + + \return - The address to the byte after the assignment. This may or may not be valid. Caller to verify. - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION tANI_U8 * pal_set_U32(tANI_U8 *ptr, tANI_U32 value) { @@ -687,14 +663,14 @@ ANI_INLINE_FUNCTION tANI_U8 * pal_set_U32(tANI_U8 *ptr, tANI_U32 value) \brief Assign 16-bit unsigned value to a byte array base on CPU's endianness. \note Caller must validate the byte array has enough space to hold the vlaue - + \param ptr - Starting address of a byte array - + \param value - The value to assign to the byte array - - \return - The address to the byte after the assignment. This may or may not + + \return - The address to the byte after the assignment. This may or may not be valid. Caller to verify. - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION tANI_U8 * pal_set_U16(tANI_U8 *ptr, tANI_U16 value) { @@ -717,15 +693,15 @@ ANI_INLINE_FUNCTION tANI_U8 * pal_set_U16(tANI_U8 *ptr, tANI_U16 value) \brief Retrieve a 16-bit unsigned value from a byte array base on CPU's endianness. \note Caller must validate the byte array has enough space to hold the vlaue - + \param ptr - Starting address of a byte array - - \param pValue - Pointer to a caller allocated buffer for 16 bit value. Value is to assign + + \param pValue - Pointer to a caller allocated buffer for 16 bit value. Value is to assign to this location. - - \return - The address to the byte after the assignment. This may or may not + + \return - The address to the byte after the assignment. This may or may not be valid. Caller to verify. - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION tANI_U8 * pal_get_U16(tANI_U8 *ptr, tANI_U16 *pValue) { @@ -748,15 +724,15 @@ ANI_INLINE_FUNCTION tANI_U8 * pal_get_U16(tANI_U8 *ptr, tANI_U16 *pValue) \brief Retrieve a 32-bit unsigned value from a byte array base on CPU's endianness. \note Caller must validate the byte array has enough space to hold the vlaue - + \param ptr - Starting address of a byte array - - \param pValue - Pointer to a caller allocated buffer for 32 bit value. Value is to assign + + \param pValue - Pointer to a caller allocated buffer for 32 bit value. Value is to assign to this location. - - \return - The address to the byte after the assignment. This may or may not + + \return - The address to the byte after the assignment. This may or may not be valid. Caller to verify. - + -------------------------------------------------------------------------------*/ ANI_INLINE_FUNCTION tANI_U8 * pal_get_U32(tANI_U8 *ptr, tANI_U32 *pValue) { diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palPipes.h b/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palPipes.h deleted file mode 100644 index b117ad7852e..00000000000 --- a/drivers/staging/prima/CORE/SYS/legacy/src/pal/inc/palPipes.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/** ------------------------------------------------------------------------- * - ------------------------------------------------------------------------- * - - - \file palPipes.h - - \brief Defines Pal pipes to transfer frames/memory to/from the device - - $Id$ - - Copyright (C) 2006 Airgo Networks, Incorporated - - ========================================================================== */ - -#ifndef PALPIPES_H -#define PALPIPES_H - -#include "halTypes.h" - - -typedef enum -{ - CSR_PIPE = 0, //CSR Endpoint for USB and non-DXE transfer for PCI/PCIe - - PIPE_TX_1 = 1, //lowest priority - PIPE_TX_2 = 2, - PIPE_TX_3 = 3, - PIPE_TX_4 = 4, - PIPE_TX_5 = 5, - PIPE_TX_6 = 6, - PIPE_TX_7 = 7, - - PIPE_RX_1 = 8, //lowest priority - PIPE_RX_2 = 9, - PIPE_RX_3 = 10, - PIPE_RX_4 = 11, - PIPE_RX_5 = 12, - PIPE_RX_6 = 13, - PIPE_RX_7 = 14, - - MAX_PIPE = PIPE_RX_7, - ANY_PIPE -}ePipes; - - -/* sHddMemSegment defines the structure that the HDD will use to transfer frames - down through the hal to the pal layer. -*/ -typedef struct tagHddMemSegment -{ - struct tagHddMemSegment *next; //linked list, NULL=no more segments linked - void *hddContext; //provides a place for the HDD layer to record information - void *addr; //either virtual or physical memory address. PCI will likely be physical addresses, USB will be virtual addresses - //pal layer will convert virtual memory addresses to physical for transfer with DXE. - tANI_U32 length; //number of bytes contained in segment for transfer. -}sHddMemSegment; - - - -/* sTxFrameTransfer defines the structure that Hal's transmit queueing will use to - keep frames in queues, ready for transfer to the pal layer. -*/ -typedef struct tagTxFrameTransfer -{ - struct tagTxFrameTransfer *next; //used by hal to queue transmit frames, Pal does nothing with this - sHddMemSegment *bd; //if NULL, the BD should be created during DXE transfer to asic - sHddMemSegment *segment; //all segments associated with an inidividual frame - tANI_U32 descCount; //number of descriptors needed to transfer -}sTxFrameTransfer; - - - - -#define PAL_RX_BUFFER_SIZE (16 * 1024) -typedef tANI_U8 *tRxBuffer; - -typedef struct -{ - tANI_U32 nBytes; //number of bytes transferred to the buffer - tRxBuffer pBbuffer; //rxBuffer virtual pointer - tANI_BUFFER_ADDR physAddr; //rxBuffer physical address - //it is assumed that the BD is present and we know how to interpret the whole buffer -}sRxFrame; - - - -/* sRxFrameTransfer defines the structure that Hal's receive queuing will use to - keep frames in receive queues. -*/ -typedef struct tagRxFrameTransfer -{ - struct tagRxFrameTransfer *next; //used by hal to queue transmit frames, Pal does nothing with this - ePipes pipe; //pipe the frame was received on - need to free the correct resources quickly - sRxFrame *rxFrame; //virtual memory pointer to raw frame data -}sRxFrameTransfer; - - - -typedef union -{ - sTxFrameTransfer txFrame; - sRxFrameTransfer rxFrame; -}uFrameTransfer; - - -typedef eHalStatus (*palXfrCompleteFPtr)(tHalHandle hHal, ePipes pipe, uFrameTransfer *frame); - - -typedef struct -{ - tANI_U32 nDescs; //number of URBs for USB or descriptors for DXE that can be queued for transfer at one time - tANI_U32 nRxBuffers; //maximum number of receive buffers from physical memory to use for this pipe - tANI_BOOLEAN preferCircular; //1 = use circular descriptor handling if available, linear otherwise - tANI_BOOLEAN bdPresent; //1 = BD attached to frames for this pipe - palXfrCompleteFPtr callback; //callback when transfer is complete, if not NULL - palXfrCompleteFPtr rxCallback; //Rx callback when transfer type is H2H, if not NULL - tANI_U32 refWQ; // Reference WQ - for H2B and B2H only - tANI_U32 xfrType; // H2B(Tx), B2H(Rx), H2H(SRAM<->HostMem R/W) - tANI_U32 chPriority; // Channel Priority 7(Highest) - 0(Lowest) - tANI_BOOLEAN bCfged; //whether the pipe has been configured - tANI_U32 indexEP; //This is for USB only, it is the index of TX/RX endpoint, TX_DATA_PIPE_OUT... - tANI_U32 bmuThreshold; //BMU threshold - // For PAL's internal use - void *pReserved1; - void *pReserved2; - - tANI_BOOLEAN use_lower_4g; /**< Added for Gen5 Prefetch */ - tANI_BOOLEAN use_short_desc_fmt; -}sPipeCfg; - - - - -#define PIPE_MEM_XFR_LIMIT (16 * 1024) //maximum single transfer size - - - - -// palPipes Functions.... -#define palIsPipeCfg(hHdd, pipeNum) ((hHdd)->PipeCfgInfo[(pipeNum)].bCfged) -eHalStatus palPipeCfg(tHddHandle, ePipes pipe, sPipeCfg *pPipeCfg); -eHalStatus palWriteFrame(tHddHandle, ePipes pipe, sTxFrameTransfer *frame); -eHalStatus palFreeRxFrame(tHddHandle, sRxFrameTransfer *frame); - - -#endif diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/pal/src/palApiComm.c b/drivers/staging/prima/CORE/SYS/legacy/src/pal/src/palApiComm.c index 9b4cf71c384..0dfce9b8ea5 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/pal/src/palApiComm.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/pal/src/palApiComm.c @@ -46,15 +46,6 @@ #include // needed for tSirMbMsg #include "wlan_qct_wda.h" - -// its not worth the time trying to get all the includes in place to get to -// halMmhForwardMBmsg. if I inlude halMnt.h, I get all kids of compile errros -// for things missing from palPipes.h (asicDxe.h is looking for these). palPipes -// is used only in Gen4 DVT code so why we would have it or need it is puzzling. -//#include - - - #ifdef MEMORY_DEBUG eHalStatus palAllocateMemory_debug( tHddHandle hHdd, void **ppMemory, tANI_U32 numBytes, char* fileName, tANI_U32 lineNum ) { diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c index cd4dbc045df..43a192a7f84 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/dot11f.c @@ -1,44 +1,23 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ /** * \file dot11f.c * @@ -50,7 +29,7 @@ * * * This file was automatically generated by 'framesc' - * Tue Mar 19 13:37:40 2013 from the following file(s): + * Fri Jun 7 17:41:21 2013 from the following file(s): * * dot11f.frms * @@ -949,16 +928,6 @@ void dot11fUnpackFfTimeStamp(tpAniSirGlobal pCtx, #define SigFfTimeStamp ( 0x001f ) -void dot11fUnpackFfTransactionId(tpAniSirGlobal pCtx, - tANI_U8 *pBuf, - tDot11fFfTransactionId *pDst) -{ - DOT11F_MEMCPY(pCtx, pDst->transId, pBuf, 2); - (void)pCtx; -} /* End dot11fUnpackFfTransactionId. */ - -#define SigFfTransactionId ( 0x0020 ) - void dot11fUnpackFfTxAntennaId(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tDot11fFfTxAntennaId *pDst) @@ -967,7 +936,7 @@ void dot11fUnpackFfTxAntennaId(tpAniSirGlobal pCtx, (void)pCtx; } /* End dot11fUnpackFfTxAntennaId. */ -#define SigFfTxAntennaId ( 0x0021 ) +#define SigFfTxAntennaId ( 0x0020 ) void dot11fUnpackFfTxPower(tpAniSirGlobal pCtx, tANI_U8 *pBuf, @@ -977,7 +946,7 @@ void dot11fUnpackFfTxPower(tpAniSirGlobal pCtx, (void)pCtx; } /* End dot11fUnpackFfTxPower. */ -#define SigFfTxPower ( 0x0022 ) +#define SigFfTxPower ( 0x0021 ) tANI_U32 dot11fUnpackTlvAuthorizedMACs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U16 tlvlen, tDot11fTLVAuthorizedMACs *pDst) { @@ -1625,6 +1594,29 @@ tANI_U32 dot11fUnpackIeGTK(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD #define SigIeHCF ( 0x0005 ) +tANI_U32 dot11fUnpackIeIGTK(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEIGTK *pDst) +{ + tANI_U32 status = DOT11F_PARSE_SUCCESS; + (void) pBuf; (void)ielen; /* Shutup the compiler */ + if (pDst->present) status = DOT11F_DUPLICATE_IE; + pDst->present = 1; + DOT11F_MEMCPY(pCtx, pDst->keyID, pBuf, 2); + pBuf += 2; + ielen -= (tANI_U8)2; + DOT11F_MEMCPY(pCtx, pDst->IPN, pBuf, 6); + pBuf += 6; + ielen -= (tANI_U8)6; + pDst->keyLength = *pBuf; + pBuf += 1; + ielen -= (tANI_U8)1; + DOT11F_MEMCPY(pCtx, pDst->key, pBuf, 24); + (void)pCtx; + return status; +} /* End dot11fUnpackIeIGTK. */ + +#define SigIeIGTK ( 0x0006 ) + + tANI_U32 dot11fUnpackIeLLAttr(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELLAttr *pDst) { tANI_U32 status = DOT11F_PARSE_SUCCESS; @@ -1636,7 +1628,7 @@ tANI_U32 dot11fUnpackIeLLAttr(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeLLAttr. */ -#define SigIeLLAttr ( 0x0006 ) +#define SigIeLLAttr ( 0x0007 ) tANI_U32 dot11fUnpackIeLoadBalance(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELoadBalance *pDst) @@ -1653,7 +1645,7 @@ tANI_U32 dot11fUnpackIeLoadBalance(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeLoadBalance. */ -#define SigIeLoadBalance ( 0x0007 ) +#define SigIeLoadBalance ( 0x0008 ) tANI_U32 dot11fUnpackIeLoadInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELoadInfo *pDst) @@ -1670,10 +1662,10 @@ tANI_U32 dot11fUnpackIeLoadInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeLoadInfo. */ -#define SigIeLoadInfo ( 0x0008 ) +#define SigIeLoadInfo ( 0x0009 ) -#define SigIePropAssocType ( 0x0009 ) +#define SigIePropAssocType ( 0x000a ) tANI_U32 dot11fUnpackIePropCapability(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropCapability *pDst) @@ -1687,7 +1679,7 @@ tANI_U32 dot11fUnpackIePropCapability(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIePropCapability. */ -#define SigIePropCapability ( 0x000a ) +#define SigIePropCapability ( 0x000b ) tANI_U32 dot11fUnpackIePropChannSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropChannSwitchAnn *pDst) @@ -1710,7 +1702,7 @@ tANI_U32 dot11fUnpackIePropChannSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIePropChannSwitchAnn. */ -#define SigIePropChannSwitchAnn ( 0x000b ) +#define SigIePropChannSwitchAnn ( 0x000c ) tANI_U32 dot11fUnpackIePropEDCAParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropEDCAParams *pDst) @@ -1795,7 +1787,7 @@ tANI_U32 dot11fUnpackIePropEDCAParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIePropEDCAParams. */ -#define SigIePropEDCAParams ( 0x000c ) +#define SigIePropEDCAParams ( 0x000d ) tANI_U32 dot11fUnpackIePropQuietBSS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropQuietBSS *pDst) @@ -1818,7 +1810,7 @@ tANI_U32 dot11fUnpackIePropQuietBSS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIePropQuietBSS. */ -#define SigIePropQuietBSS ( 0x000d ) +#define SigIePropQuietBSS ( 0x000e ) tANI_U32 dot11fUnpackIePropSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPropSuppRates *pDst) @@ -1846,7 +1838,7 @@ tANI_U32 dot11fUnpackIePropSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIePropSuppRates. */ -#define SigIePropSuppRates ( 0x000e ) +#define SigIePropSuppRates ( 0x000f ) tANI_U32 dot11fUnpackIeR0KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIER0KH_ID *pDst) @@ -1866,7 +1858,7 @@ tANI_U32 dot11fUnpackIeR0KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeR0KH_ID. */ -#define SigIeR0KH_ID ( 0x000f ) +#define SigIeR0KH_ID ( 0x0010 ) tANI_U32 dot11fUnpackIeR1KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIER1KH_ID *pDst) @@ -1880,7 +1872,7 @@ tANI_U32 dot11fUnpackIeR1KH_ID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeR1KH_ID. */ -#define SigIeR1KH_ID ( 0x0010 ) +#define SigIeR1KH_ID ( 0x0011 ) tANI_U32 dot11fUnpackIeTSFInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSFInfo *pDst) @@ -1897,7 +1889,7 @@ tANI_U32 dot11fUnpackIeTSFInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeTSFInfo. */ -#define SigIeTSFInfo ( 0x0011 ) +#define SigIeTSFInfo ( 0x0012 ) tANI_U32 dot11fUnpackIeTaurus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETaurus *pDst) @@ -1920,7 +1912,7 @@ tANI_U32 dot11fUnpackIeTaurus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeTaurus. */ -#define SigIeTaurus ( 0x0012 ) +#define SigIeTaurus ( 0x0013 ) tANI_U32 dot11fUnpackIeTitan(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETitan *pDst) @@ -1943,10 +1935,10 @@ tANI_U32 dot11fUnpackIeTitan(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeTitan. */ -#define SigIeTitan ( 0x0013 ) +#define SigIeTitan ( 0x0014 ) -#define SigIeTriggerStaBgScan ( 0x0014 ) +#define SigIeTriggerStaBgScan ( 0x0015 ) tANI_U32 dot11fUnpackIeVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVersion *pDst) @@ -1972,7 +1964,7 @@ tANI_U32 dot11fUnpackIeVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeVersion. */ -#define SigIeVersion ( 0x0015 ) +#define SigIeVersion ( 0x0016 ) tANI_U32 dot11fUnpackIeWDS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWDS *pDst) @@ -1992,7 +1984,7 @@ tANI_U32 dot11fUnpackIeWDS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeWDS. */ -#define SigIeWDS ( 0x0016 ) +#define SigIeWDS ( 0x0017 ) tANI_U32 dot11fUnpackIeAPChannelReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEAPChannelReport *pDst) @@ -2015,7 +2007,7 @@ tANI_U32 dot11fUnpackIeAPChannelReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_ return status; } /* End dot11fUnpackIeAPChannelReport. */ -#define SigIeAPChannelReport ( 0x0017 ) +#define SigIeAPChannelReport ( 0x0018 ) tANI_U32 dot11fUnpackIeBcnReportingDetail(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBcnReportingDetail *pDst) @@ -2029,7 +2021,7 @@ tANI_U32 dot11fUnpackIeBcnReportingDetail(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIeBcnReportingDetail. */ -#define SigIeBcnReportingDetail ( 0x0018 ) +#define SigIeBcnReportingDetail ( 0x0019 ) tANI_U32 dot11fUnpackIeBeaconReportFrmBody(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBeaconReportFrmBody *pDst) @@ -2049,7 +2041,7 @@ tANI_U32 dot11fUnpackIeBeaconReportFrmBody(tpAniSirGlobal pCtx, tANI_U8 *pBuf, t return status; } /* End dot11fUnpackIeBeaconReportFrmBody. */ -#define SigIeBeaconReportFrmBody ( 0x0019 ) +#define SigIeBeaconReportFrmBody ( 0x001a ) tANI_U32 dot11fUnpackIeBeaconReporting(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEBeaconReporting *pDst) @@ -2066,7 +2058,7 @@ tANI_U32 dot11fUnpackIeBeaconReporting(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_ return status; } /* End dot11fUnpackIeBeaconReporting. */ -#define SigIeBeaconReporting ( 0x001a ) +#define SigIeBeaconReporting ( 0x001b ) tANI_U32 dot11fUnpackIeMeasurementPilot(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMeasurementPilot *pDst) @@ -2084,7 +2076,7 @@ tANI_U32 dot11fUnpackIeMeasurementPilot(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI return status; } /* End dot11fUnpackIeMeasurementPilot. */ -#define SigIeMeasurementPilot ( 0x001b ) +#define SigIeMeasurementPilot ( 0x001c ) tANI_U32 dot11fUnpackIeMultiBssid(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMultiBssid *pDst) @@ -2102,7 +2094,7 @@ tANI_U32 dot11fUnpackIeMultiBssid(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeMultiBssid. */ -#define SigIeMultiBssid ( 0x001c ) +#define SigIeMultiBssid ( 0x001d ) tANI_U32 dot11fUnpackIeRICData(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERICData *pDst) @@ -2122,7 +2114,7 @@ tANI_U32 dot11fUnpackIeRICData(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeRICData. */ -#define SigIeRICData ( 0x001d ) +#define SigIeRICData ( 0x001e ) tANI_U32 dot11fUnpackIeRICDescriptor(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERICDescriptor *pDst) @@ -2140,7 +2132,7 @@ tANI_U32 dot11fUnpackIeRICDescriptor(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeRICDescriptor. */ -#define SigIeRICDescriptor ( 0x001e ) +#define SigIeRICDescriptor ( 0x001f ) tANI_U32 dot11fUnpackIeRRMEnabledCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERRMEnabledCap *pDst) @@ -2200,7 +2192,7 @@ tANI_U32 dot11fUnpackIeRRMEnabledCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeRRMEnabledCap. */ -#define SigIeRRMEnabledCap ( 0x001f ) +#define SigIeRRMEnabledCap ( 0x0020 ) tANI_U32 dot11fUnpackIeRequestedInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERequestedInfo *pDst) @@ -2215,7 +2207,7 @@ tANI_U32 dot11fUnpackIeRequestedInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeRequestedInfo. */ -#define SigIeRequestedInfo ( 0x0020 ) +#define SigIeRequestedInfo ( 0x0021 ) tANI_U32 dot11fUnpackIeSSID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESSID *pDst) @@ -2239,7 +2231,7 @@ tANI_U32 dot11fUnpackIeSSID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, t return status; } /* End dot11fUnpackIeSSID. */ -#define SigIeSSID ( 0x0021 ) +#define SigIeSSID ( 0x0022 ) tANI_U32 dot11fUnpackIeSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESchedule *pDst) @@ -2270,7 +2262,7 @@ tANI_U32 dot11fUnpackIeSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeSchedule. */ -#define SigIeSchedule ( 0x0022 ) +#define SigIeSchedule ( 0x0023 ) tANI_U32 dot11fUnpackIeTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETCLAS *pDst) @@ -2359,10 +2351,10 @@ tANI_U32 dot11fUnpackIeTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeTCLAS. */ -#define SigIeTCLAS ( 0x0023 ) +#define SigIeTCLAS ( 0x0024 ) -#define SigIeTCLASSPROC ( 0x0024 ) +#define SigIeTCLASSPROC ( 0x0025 ) tANI_U32 dot11fUnpackIeTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSDelay *pDst) @@ -2376,7 +2368,7 @@ tANI_U32 dot11fUnpackIeTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeTSDelay. */ -#define SigIeTSDelay ( 0x0025 ) +#define SigIeTSDelay ( 0x0026 ) tANI_U32 dot11fUnpackIeTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETSPEC *pDst) @@ -2453,7 +2445,7 @@ tANI_U32 dot11fUnpackIeTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeTSPEC. */ -#define SigIeTSPEC ( 0x0026 ) +#define SigIeTSPEC ( 0x0027 ) tANI_U32 dot11fUnpackIeWMMSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMSchedule *pDst) @@ -2492,7 +2484,7 @@ tANI_U32 dot11fUnpackIeWMMSchedule(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWMMSchedule. */ -#define SigIeWMMSchedule ( 0x0027 ) +#define SigIeWMMSchedule ( 0x0028 ) tANI_U32 dot11fUnpackIeWMMTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTCLAS *pDst) @@ -2589,7 +2581,7 @@ tANI_U32 dot11fUnpackIeWMMTCLAS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeWMMTCLAS. */ -#define SigIeWMMTCLAS ( 0x0028 ) +#define SigIeWMMTCLAS ( 0x0029 ) tANI_U32 dot11fUnpackIeWMMTCLASPROC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTCLASPROC *pDst) @@ -2611,7 +2603,7 @@ tANI_U32 dot11fUnpackIeWMMTCLASPROC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeWMMTCLASPROC. */ -#define SigIeWMMTCLASPROC ( 0x0029 ) +#define SigIeWMMTCLASPROC ( 0x002a ) tANI_U32 dot11fUnpackIeWMMTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTSDelay *pDst) @@ -2633,7 +2625,7 @@ tANI_U32 dot11fUnpackIeWMMTSDelay(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeWMMTSDelay. */ -#define SigIeWMMTSDelay ( 0x002a ) +#define SigIeWMMTSDelay ( 0x002b ) tANI_U32 dot11fUnpackIeWMMTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMTSPEC *pDst) @@ -2718,7 +2710,7 @@ tANI_U32 dot11fUnpackIeWMMTSPEC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeWMMTSPEC. */ -#define SigIeWMMTSPEC ( 0x002b ) +#define SigIeWMMTSPEC ( 0x002c ) tANI_U32 dot11fUnpackIeAID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEAID *pDst) @@ -2732,7 +2724,7 @@ tANI_U32 dot11fUnpackIeAID(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeAID. */ -#define SigIeAID ( 0x002c ) +#define SigIeAID ( 0x002d ) static const tFFDefn FFS_Airgo[ ] = { @@ -2777,7 +2769,7 @@ tANI_U32 dot11fUnpackIeAirgo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeAirgo. */ -#define SigIeAirgo ( 0x002d ) +#define SigIeAirgo ( 0x002e ) tANI_U32 dot11fUnpackIeCCXCckmOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXCckmOpaque *pDst) @@ -2797,7 +2789,7 @@ tANI_U32 dot11fUnpackIeCCXCckmOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeCCXCckmOpaque. */ -#define SigIeCCXCckmOpaque ( 0x002e ) +#define SigIeCCXCckmOpaque ( 0x002f ) tANI_U32 dot11fUnpackIeCCXRadMgmtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXRadMgmtCap *pDst) @@ -2817,7 +2809,7 @@ tANI_U32 dot11fUnpackIeCCXRadMgmtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeCCXRadMgmtCap. */ -#define SigIeCCXRadMgmtCap ( 0x002f ) +#define SigIeCCXRadMgmtCap ( 0x0030 ) tANI_U32 dot11fUnpackIeCCXTrafStrmMet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXTrafStrmMet *pDst) @@ -2837,7 +2829,7 @@ tANI_U32 dot11fUnpackIeCCXTrafStrmMet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeCCXTrafStrmMet. */ -#define SigIeCCXTrafStrmMet ( 0x0030 ) +#define SigIeCCXTrafStrmMet ( 0x0031 ) tANI_U32 dot11fUnpackIeCCXTrafStrmRateSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXTrafStrmRateSet *pDst) @@ -2860,7 +2852,7 @@ tANI_U32 dot11fUnpackIeCCXTrafStrmRateSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIeCCXTrafStrmRateSet. */ -#define SigIeCCXTrafStrmRateSet ( 0x0031 ) +#define SigIeCCXTrafStrmRateSet ( 0x0032 ) tANI_U32 dot11fUnpackIeCCXTxmitPower(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXTxmitPower *pDst) @@ -2877,7 +2869,7 @@ tANI_U32 dot11fUnpackIeCCXTxmitPower(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeCCXTxmitPower. */ -#define SigIeCCXTxmitPower ( 0x0032 ) +#define SigIeCCXTxmitPower ( 0x0033 ) tANI_U32 dot11fUnpackIeCCXVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECCXVersion *pDst) @@ -2891,7 +2883,7 @@ tANI_U32 dot11fUnpackIeCCXVersion(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeCCXVersion. */ -#define SigIeCCXVersion ( 0x0033 ) +#define SigIeCCXVersion ( 0x0034 ) tANI_U32 dot11fUnpackIeCFParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECFParams *pDst) @@ -2914,7 +2906,7 @@ tANI_U32 dot11fUnpackIeCFParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeCFParams. */ -#define SigIeCFParams ( 0x0034 ) +#define SigIeCFParams ( 0x0035 ) tANI_U32 dot11fUnpackIeChallengeText(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEChallengeText *pDst) @@ -2934,7 +2926,7 @@ tANI_U32 dot11fUnpackIeChallengeText(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeChallengeText. */ -#define SigIeChallengeText ( 0x0035 ) +#define SigIeChallengeText ( 0x0036 ) tANI_U32 dot11fUnpackIeChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEChanSwitchAnn *pDst) @@ -2954,7 +2946,7 @@ tANI_U32 dot11fUnpackIeChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeChanSwitchAnn. */ -#define SigIeChanSwitchAnn ( 0x0036 ) +#define SigIeChanSwitchAnn ( 0x0037 ) tANI_U32 dot11fUnpackIeCountry(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIECountry *pDst) @@ -2985,10 +2977,10 @@ tANI_U32 dot11fUnpackIeCountry(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeCountry. */ -#define SigIeCountry ( 0x0037 ) +#define SigIeCountry ( 0x0038 ) -#define SigIeDSParams ( 0x0038 ) +#define SigIeDSParams ( 0x0039 ) tANI_U32 dot11fUnpackIeEDCAParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEEDCAParamSet *pDst) @@ -3073,7 +3065,7 @@ tANI_U32 dot11fUnpackIeEDCAParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeEDCAParamSet. */ -#define SigIeEDCAParamSet ( 0x0039 ) +#define SigIeEDCAParamSet ( 0x003a ) tANI_U32 dot11fUnpackIeERPInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEERPInfo *pDst) @@ -3092,7 +3084,7 @@ tANI_U32 dot11fUnpackIeERPInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeERPInfo. */ -#define SigIeERPInfo ( 0x003a ) +#define SigIeERPInfo ( 0x003b ) tANI_U32 dot11fUnpackIeExtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEExtCap *pDst) @@ -3166,10 +3158,10 @@ tANI_U32 dot11fUnpackIeExtCap(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeExtCap. */ -#define SigIeExtCap ( 0x003b ) +#define SigIeExtCap ( 0x003c ) -#define SigIeExtChanSwitchAnn ( 0x003c ) +#define SigIeExtChanSwitchAnn ( 0x003d ) tANI_U32 dot11fUnpackIeExtSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEExtSuppRates *pDst) @@ -3197,7 +3189,7 @@ tANI_U32 dot11fUnpackIeExtSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeExtSuppRates. */ -#define SigIeExtSuppRates ( 0x003d ) +#define SigIeExtSuppRates ( 0x003e ) tANI_U32 dot11fUnpackIeFHParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHParamSet *pDst) @@ -3220,7 +3212,7 @@ tANI_U32 dot11fUnpackIeFHParamSet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeFHParamSet. */ -#define SigIeFHParamSet ( 0x003e ) +#define SigIeFHParamSet ( 0x003f ) tANI_U32 dot11fUnpackIeFHParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHParams *pDst) @@ -3237,7 +3229,7 @@ tANI_U32 dot11fUnpackIeFHParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeFHParams. */ -#define SigIeFHParams ( 0x003f ) +#define SigIeFHParams ( 0x0040 ) tANI_U32 dot11fUnpackIeFHPattTable(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFHPattTable *pDst) @@ -3269,7 +3261,7 @@ tANI_U32 dot11fUnpackIeFHPattTable(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeFHPattTable. */ -#define SigIeFHPattTable ( 0x0040 ) +#define SigIeFHPattTable ( 0x0041 ) static const tFFDefn FFS_FTInfo[ ] = { @@ -3280,6 +3272,7 @@ tANI_U32 dot11fUnpackIeFHPattTable(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i {offsetof(tDot11fIEFTInfo, R1KH_ID), offsetof(tDot11fIER1KH_ID, present), 0, "R1KH_ID" , 0, 8, 8, SigIeR1KH_ID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_R1KH_ID, 0, }, {offsetof(tDot11fIEFTInfo, GTK), offsetof(tDot11fIEGTK, present), 0, "GTK" , 0, 18, 45, SigIeGTK, {0, 0, 0, 0, 0}, 0, DOT11F_EID_GTK, 0, }, {offsetof(tDot11fIEFTInfo, R0KH_ID), offsetof(tDot11fIER0KH_ID, present), 0, "R0KH_ID" , 0, 3, 50, SigIeR0KH_ID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_R0KH_ID, 0, }, + {offsetof(tDot11fIEFTInfo, IGTK), offsetof(tDot11fIEIGTK, present), 0, "IGTK" , 0, 35, 35, SigIeIGTK, {0, 0, 0, 0, 0}, 0, DOT11F_EID_IGTK, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; @@ -3315,7 +3308,7 @@ tANI_U32 dot11fUnpackIeFTInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeFTInfo. */ -#define SigIeFTInfo ( 0x0041 ) +#define SigIeFTInfo ( 0x0042 ) tANI_U32 dot11fUnpackIeFTTimeoutInterval(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEFTTimeoutInterval *pDst) @@ -3332,7 +3325,7 @@ tANI_U32 dot11fUnpackIeFTTimeoutInterval(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tAN return status; } /* End dot11fUnpackIeFTTimeoutInterval. */ -#define SigIeFTTimeoutInterval ( 0x0042 ) +#define SigIeFTTimeoutInterval ( 0x0043 ) tANI_U32 dot11fUnpackIeHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEHTCaps *pDst) @@ -3421,7 +3414,7 @@ tANI_U32 dot11fUnpackIeHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeHTCaps. */ -#define SigIeHTCaps ( 0x0043 ) +#define SigIeHTCaps ( 0x0044 ) tANI_U32 dot11fUnpackIeHTInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEHTInfo *pDst) @@ -3476,7 +3469,7 @@ tANI_U32 dot11fUnpackIeHTInfo(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeHTInfo. */ -#define SigIeHTInfo ( 0x0044 ) +#define SigIeHTInfo ( 0x0045 ) tANI_U32 dot11fUnpackIeIBSSParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEIBSSParams *pDst) @@ -3490,7 +3483,7 @@ tANI_U32 dot11fUnpackIeIBSSParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeIBSSParams. */ -#define SigIeIBSSParams ( 0x0045 ) +#define SigIeIBSSParams ( 0x0046 ) tANI_U32 dot11fUnpackIeLinkIdentifier(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIELinkIdentifier *pDst) @@ -3510,7 +3503,7 @@ tANI_U32 dot11fUnpackIeLinkIdentifier(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeLinkIdentifier. */ -#define SigIeLinkIdentifier ( 0x0046 ) +#define SigIeLinkIdentifier ( 0x0047 ) static const tFFDefn FFS_reportBeacon[ ] = { @@ -3668,7 +3661,7 @@ tANI_U32 dot11fUnpackIeMeasurementReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tAN return status; } /* End dot11fUnpackIeMeasurementReport. */ -#define SigIeMeasurementReport ( 0x0047 ) +#define SigIeMeasurementReport ( 0x0048 ) static const tFFDefn FFS_measurement_requestBeacon[ ] = { @@ -3773,7 +3766,7 @@ tANI_U32 dot11fUnpackIeMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIeMeasurementRequest. */ -#define SigIeMeasurementRequest ( 0x0048 ) +#define SigIeMeasurementRequest ( 0x0049 ) tANI_U32 dot11fUnpackIeMobilityDomain(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEMobilityDomain *pDst) @@ -3794,7 +3787,7 @@ tANI_U32 dot11fUnpackIeMobilityDomain(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeMobilityDomain. */ -#define SigIeMobilityDomain ( 0x0049 ) +#define SigIeMobilityDomain ( 0x004a ) static const tFFDefn FFS_NeighborReport[ ] = { @@ -3861,7 +3854,7 @@ tANI_U32 dot11fUnpackIeNeighborReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeNeighborReport. */ -#define SigIeNeighborReport ( 0x004a ) +#define SigIeNeighborReport ( 0x004b ) tANI_U32 dot11fUnpackIeOperatingMode(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEOperatingMode *pDst) @@ -3880,7 +3873,7 @@ tANI_U32 dot11fUnpackIeOperatingMode(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeOperatingMode. */ -#define SigIeOperatingMode ( 0x004b ) +#define SigIeOperatingMode ( 0x004c ) static const tTLVDefn TLVS_P2PAssocReq[ ] = { @@ -3899,7 +3892,7 @@ tANI_U32 dot11fUnpackIeP2PAssocReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PAssocReq. */ -#define SigIeP2PAssocReq ( 0x004c ) +#define SigIeP2PAssocReq ( 0x004d ) static const tTLVDefn TLVS_P2PAssocRes[ ] = { @@ -3917,7 +3910,7 @@ tANI_U32 dot11fUnpackIeP2PAssocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PAssocRes. */ -#define SigIeP2PAssocRes ( 0x004d ) +#define SigIeP2PAssocRes ( 0x004e ) static const tTLVDefn TLVS_P2PBeacon[ ] = { @@ -3936,7 +3929,7 @@ tANI_U32 dot11fUnpackIeP2PBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeP2PBeacon. */ -#define SigIeP2PBeacon ( 0x004e ) +#define SigIeP2PBeacon ( 0x004f ) static const tTLVDefn TLVS_P2PBeaconProbeRes[ ] = { @@ -3958,7 +3951,7 @@ tANI_U32 dot11fUnpackIeP2PBeaconProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tAN return status; } /* End dot11fUnpackIeP2PBeaconProbeRes. */ -#define SigIeP2PBeaconProbeRes ( 0x004f ) +#define SigIeP2PBeaconProbeRes ( 0x0050 ) static const tTLVDefn TLVS_P2PDeAuth[ ] = { @@ -3975,7 +3968,7 @@ tANI_U32 dot11fUnpackIeP2PDeAuth(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeP2PDeAuth. */ -#define SigIeP2PDeAuth ( 0x0050 ) +#define SigIeP2PDeAuth ( 0x0051 ) static const tTLVDefn TLVS_P2PDeviceDiscoverabilityReq[ ] = { @@ -3993,7 +3986,7 @@ tANI_U32 dot11fUnpackIeP2PDeviceDiscoverabilityReq(tpAniSirGlobal pCtx, tANI_U8 return status; } /* End dot11fUnpackIeP2PDeviceDiscoverabilityReq. */ -#define SigIeP2PDeviceDiscoverabilityReq ( 0x0051 ) +#define SigIeP2PDeviceDiscoverabilityReq ( 0x0052 ) static const tTLVDefn TLVS_P2PDeviceDiscoverabilityRes[ ] = { @@ -4010,7 +4003,7 @@ tANI_U32 dot11fUnpackIeP2PDeviceDiscoverabilityRes(tpAniSirGlobal pCtx, tANI_U8 return status; } /* End dot11fUnpackIeP2PDeviceDiscoverabilityRes. */ -#define SigIeP2PDeviceDiscoverabilityRes ( 0x0052 ) +#define SigIeP2PDeviceDiscoverabilityRes ( 0x0053 ) static const tTLVDefn TLVS_P2PDisAssoc[ ] = { @@ -4027,7 +4020,7 @@ tANI_U32 dot11fUnpackIeP2PDisAssoc(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PDisAssoc. */ -#define SigIeP2PDisAssoc ( 0x0053 ) +#define SigIeP2PDisAssoc ( 0x0054 ) static const tTLVDefn TLVS_P2PGONegCnf[ ] = { @@ -4048,7 +4041,7 @@ tANI_U32 dot11fUnpackIeP2PGONegCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PGONegCnf. */ -#define SigIeP2PGONegCnf ( 0x0054 ) +#define SigIeP2PGONegCnf ( 0x0055 ) static const tTLVDefn TLVS_P2PGONegReq[ ] = { @@ -4073,7 +4066,7 @@ tANI_U32 dot11fUnpackIeP2PGONegReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PGONegReq. */ -#define SigIeP2PGONegReq ( 0x0055 ) +#define SigIeP2PGONegReq ( 0x0056 ) static const tTLVDefn TLVS_P2PGONegRes[ ] = { @@ -4098,7 +4091,7 @@ tANI_U32 dot11fUnpackIeP2PGONegRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PGONegRes. */ -#define SigIeP2PGONegRes ( 0x0056 ) +#define SigIeP2PGONegRes ( 0x0057 ) static const tTLVDefn TLVS_P2PGONegWPS[ ] = { @@ -4116,7 +4109,7 @@ tANI_U32 dot11fUnpackIeP2PGONegWPS(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PGONegWPS. */ -#define SigIeP2PGONegWPS ( 0x0057 ) +#define SigIeP2PGONegWPS ( 0x0058 ) tANI_U32 dot11fUnpackIeP2PIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEP2PIEOpaque *pDst) @@ -4136,7 +4129,7 @@ tANI_U32 dot11fUnpackIeP2PIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PIEOpaque. */ -#define SigIeP2PIEOpaque ( 0x0058 ) +#define SigIeP2PIEOpaque ( 0x0059 ) static const tTLVDefn TLVS_P2PInvitationReq[ ] = { @@ -4159,7 +4152,7 @@ tANI_U32 dot11fUnpackIeP2PInvitationReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI return status; } /* End dot11fUnpackIeP2PInvitationReq. */ -#define SigIeP2PInvitationReq ( 0x0059 ) +#define SigIeP2PInvitationReq ( 0x005a ) static const tTLVDefn TLVS_P2PInvitationRes[ ] = { @@ -4180,7 +4173,7 @@ tANI_U32 dot11fUnpackIeP2PInvitationRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI return status; } /* End dot11fUnpackIeP2PInvitationRes. */ -#define SigIeP2PInvitationRes ( 0x005a ) +#define SigIeP2PInvitationRes ( 0x005b ) static const tTLVDefn TLVS_P2PNoticeOfAbsence[ ] = { @@ -4197,7 +4190,7 @@ tANI_U32 dot11fUnpackIeP2PNoticeOfAbsence(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tA return status; } /* End dot11fUnpackIeP2PNoticeOfAbsence. */ -#define SigIeP2PNoticeOfAbsence ( 0x005b ) +#define SigIeP2PNoticeOfAbsence ( 0x005c ) static const tTLVDefn TLVS_P2PPresenceResponse[ ] = { @@ -4215,7 +4208,7 @@ tANI_U32 dot11fUnpackIeP2PPresenceResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, t return status; } /* End dot11fUnpackIeP2PPresenceResponse. */ -#define SigIeP2PPresenceResponse ( 0x005c ) +#define SigIeP2PPresenceResponse ( 0x005d ) static const tTLVDefn TLVS_P2PProbeReq[ ] = { @@ -4236,7 +4229,7 @@ tANI_U32 dot11fUnpackIeP2PProbeReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PProbeReq. */ -#define SigIeP2PProbeReq ( 0x005d ) +#define SigIeP2PProbeReq ( 0x005e ) static const tTLVDefn TLVS_P2PProbeRes[ ] = { @@ -4257,7 +4250,7 @@ tANI_U32 dot11fUnpackIeP2PProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeP2PProbeRes. */ -#define SigIeP2PProbeRes ( 0x005e ) +#define SigIeP2PProbeRes ( 0x005f ) static const tTLVDefn TLVS_P2PProvisionDiscoveryReq[ ] = { @@ -4276,7 +4269,7 @@ tANI_U32 dot11fUnpackIeP2PProvisionDiscoveryReq(tpAniSirGlobal pCtx, tANI_U8 *pB return status; } /* End dot11fUnpackIeP2PProvisionDiscoveryReq. */ -#define SigIeP2PProvisionDiscoveryReq ( 0x005f ) +#define SigIeP2PProvisionDiscoveryReq ( 0x0060 ) static const tTLVDefn TLVS_P2PWSCProvisionDiscoveryRes[ ] = { @@ -4293,7 +4286,7 @@ tANI_U32 dot11fUnpackIeP2PWSCProvisionDiscoveryRes(tpAniSirGlobal pCtx, tANI_U8 return status; } /* End dot11fUnpackIeP2PWSCProvisionDiscoveryRes. */ -#define SigIeP2PWSCProvisionDiscoveryRes ( 0x0060 ) +#define SigIeP2PWSCProvisionDiscoveryRes ( 0x0061 ) tANI_U32 dot11fUnpackIePTIControl(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPTIControl *pDst) @@ -4310,7 +4303,7 @@ tANI_U32 dot11fUnpackIePTIControl(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIePTIControl. */ -#define SigIePTIControl ( 0x0061 ) +#define SigIePTIControl ( 0x0062 ) tANI_U32 dot11fUnpackIePUBufferStatus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPUBufferStatus *pDst) @@ -4330,7 +4323,7 @@ tANI_U32 dot11fUnpackIePUBufferStatus(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIePUBufferStatus. */ -#define SigIePUBufferStatus ( 0x0062 ) +#define SigIePUBufferStatus ( 0x0063 ) tANI_U32 dot11fUnpackIePowerCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPowerCaps *pDst) @@ -4347,7 +4340,7 @@ tANI_U32 dot11fUnpackIePowerCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIePowerCaps. */ -#define SigIePowerCaps ( 0x0063 ) +#define SigIePowerCaps ( 0x0064 ) tANI_U32 dot11fUnpackIePowerConstraints(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEPowerConstraints *pDst) @@ -4361,7 +4354,7 @@ tANI_U32 dot11fUnpackIePowerConstraints(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI return status; } /* End dot11fUnpackIePowerConstraints. */ -#define SigIePowerConstraints ( 0x0064 ) +#define SigIePowerConstraints ( 0x0065 ) tANI_U32 dot11fUnpackIeQBSSLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQBSSLoad *pDst) @@ -4381,7 +4374,7 @@ tANI_U32 dot11fUnpackIeQBSSLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iele return status; } /* End dot11fUnpackIeQBSSLoad. */ -#define SigIeQBSSLoad ( 0x0065 ) +#define SigIeQBSSLoad ( 0x0066 ) tANI_U32 dot11fUnpackIeQOSCapsAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQOSCapsAp *pDst) @@ -4392,16 +4385,16 @@ tANI_U32 dot11fUnpackIeQOSCapsAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; tmp63__ = *pBuf; - pDst->reserved = tmp63__ >> 0 & 0x1; - pDst->txopreq = tmp63__ >> 1 & 0x1; - pDst->qreq = tmp63__ >> 2 & 0x1; - pDst->qack = tmp63__ >> 3 & 0x1; - pDst->count = tmp63__ >> 4 & 0xf; + pDst->count = tmp63__ >> 0 & 0xf; + pDst->qack = tmp63__ >> 4 & 0x1; + pDst->qreq = tmp63__ >> 5 & 0x1; + pDst->txopreq = tmp63__ >> 6 & 0x1; + pDst->reserved = tmp63__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11fUnpackIeQOSCapsAp. */ -#define SigIeQOSCapsAp ( 0x0066 ) +#define SigIeQOSCapsAp ( 0x0067 ) tANI_U32 dot11fUnpackIeQOSCapsStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQOSCapsStation *pDst) @@ -4412,18 +4405,18 @@ tANI_U32 dot11fUnpackIeQOSCapsStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U if (pDst->present) status = DOT11F_DUPLICATE_IE; pDst->present = 1; tmp64__ = *pBuf; - pDst->more_data_ack = tmp64__ >> 0 & 0x1; - pDst->max_sp_length = tmp64__ >> 1 & 0x3; - pDst->qack = tmp64__ >> 3 & 0x1; - pDst->acbe_uapsd = tmp64__ >> 4 & 0x1; - pDst->acbk_uapsd = tmp64__ >> 5 & 0x1; - pDst->acvi_uapsd = tmp64__ >> 6 & 0x1; - pDst->acvo_uapsd = tmp64__ >> 7 & 0x1; + pDst->acvo_uapsd = tmp64__ >> 0 & 0x1; + pDst->acvi_uapsd = tmp64__ >> 1 & 0x1; + pDst->acbk_uapsd = tmp64__ >> 2 & 0x1; + pDst->acbe_uapsd = tmp64__ >> 3 & 0x1; + pDst->qack = tmp64__ >> 4 & 0x1; + pDst->max_sp_length = tmp64__ >> 5 & 0x3; + pDst->more_data_ack = tmp64__ >> 7 & 0x1; (void)pCtx; return status; } /* End dot11fUnpackIeQOSCapsStation. */ -#define SigIeQOSCapsStation ( 0x0067 ) +#define SigIeQOSCapsStation ( 0x0068 ) tANI_U32 dot11fUnpackIeQuiet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEQuiet *pDst) @@ -4446,7 +4439,7 @@ tANI_U32 dot11fUnpackIeQuiet(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeQuiet. */ -#define SigIeQuiet ( 0x0068 ) +#define SigIeQuiet ( 0x0069 ) tANI_U32 dot11fUnpackIeRCPIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERCPIIE *pDst) @@ -4460,7 +4453,7 @@ tANI_U32 dot11fUnpackIeRCPIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeRCPIIE. */ -#define SigIeRCPIIE ( 0x0069 ) +#define SigIeRCPIIE ( 0x006a ) static const tFFDefn FFS_RICDataDesc[ ] = { @@ -4500,7 +4493,7 @@ tANI_U32 dot11fUnpackIeRICDataDesc(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeRICDataDesc. */ -#define SigIeRICDataDesc ( 0x006a ) +#define SigIeRICDataDesc ( 0x006b ) tANI_U32 dot11fUnpackIeRSN(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSN *pDst) @@ -4593,7 +4586,7 @@ tANI_U32 dot11fUnpackIeRSN(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeRSN. */ -#define SigIeRSN ( 0x006b ) +#define SigIeRSN ( 0x006c ) tANI_U32 dot11fUnpackIeRSNIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSNIIE *pDst) @@ -4607,7 +4600,7 @@ tANI_U32 dot11fUnpackIeRSNIIE(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeRSNIIE. */ -#define SigIeRSNIIE ( 0x006c ) +#define SigIeRSNIIE ( 0x006d ) tANI_U32 dot11fUnpackIeRSNOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIERSNOpaque *pDst) @@ -4627,7 +4620,7 @@ tANI_U32 dot11fUnpackIeRSNOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeRSNOpaque. */ -#define SigIeRSNOpaque ( 0x006d ) +#define SigIeRSNOpaque ( 0x006e ) tANI_U32 dot11fUnpackIeSuppChannels(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESuppChannels *pDst) @@ -4647,7 +4640,7 @@ tANI_U32 dot11fUnpackIeSuppChannels(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeSuppChannels. */ -#define SigIeSuppChannels ( 0x006e ) +#define SigIeSuppChannels ( 0x006f ) tANI_U32 dot11fUnpackIeSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIESuppRates *pDst) @@ -4675,7 +4668,7 @@ tANI_U32 dot11fUnpackIeSuppRates(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeSuppRates. */ -#define SigIeSuppRates ( 0x006f ) +#define SigIeSuppRates ( 0x0070 ) tANI_U32 dot11fUnpackIeTIM(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETIM *pDst) @@ -4704,7 +4697,7 @@ tANI_U32 dot11fUnpackIeTIM(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeTIM. */ -#define SigIeTIM ( 0x0070 ) +#define SigIeTIM ( 0x0071 ) tANI_U32 dot11fUnpackIeTPCReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETPCReport *pDst) @@ -4721,7 +4714,7 @@ tANI_U32 dot11fUnpackIeTPCReport(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeTPCReport. */ -#define SigIeTPCReport ( 0x0071 ) +#define SigIeTPCReport ( 0x0072 ) tANI_U32 dot11fUnpackIeTPCRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIETPCRequest *pDst) @@ -4734,7 +4727,7 @@ tANI_U32 dot11fUnpackIeTPCRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeTPCRequest. */ -#define SigIeTPCRequest ( 0x0072 ) +#define SigIeTPCRequest ( 0x0073 ) tANI_U32 dot11fUnpackIeVHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTCaps *pDst) @@ -4787,7 +4780,7 @@ tANI_U32 dot11fUnpackIeVHTCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeVHTCaps. */ -#define SigIeVHTCaps ( 0x0073 ) +#define SigIeVHTCaps ( 0x0074 ) tANI_U32 dot11fUnpackIeVHTExtBssLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTExtBssLoad *pDst) @@ -4813,7 +4806,7 @@ tANI_U32 dot11fUnpackIeVHTExtBssLoad(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeVHTExtBssLoad. */ -#define SigIeVHTExtBssLoad ( 0x0074 ) +#define SigIeVHTExtBssLoad ( 0x0075 ) tANI_U32 dot11fUnpackIeVHTOperation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEVHTOperation *pDst) @@ -4836,7 +4829,7 @@ tANI_U32 dot11fUnpackIeVHTOperation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeVHTOperation. */ -#define SigIeVHTOperation ( 0x0075 ) +#define SigIeVHTOperation ( 0x0076 ) tANI_U32 dot11fUnpackIeWAPI(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWAPI *pDst) @@ -4905,7 +4898,7 @@ tANI_U32 dot11fUnpackIeWAPI(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, t return status; } /* End dot11fUnpackIeWAPI. */ -#define SigIeWAPI ( 0x0076 ) +#define SigIeWAPI ( 0x0077 ) tANI_U32 dot11fUnpackIeWAPIOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWAPIOpaque *pDst) @@ -4925,7 +4918,7 @@ tANI_U32 dot11fUnpackIeWAPIOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ie return status; } /* End dot11fUnpackIeWAPIOpaque. */ -#define SigIeWAPIOpaque ( 0x0077 ) +#define SigIeWAPIOpaque ( 0x0078 ) tANI_U32 dot11fUnpackIeWFATPC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWFATPC *pDst) @@ -4942,7 +4935,7 @@ tANI_U32 dot11fUnpackIeWFATPC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, return status; } /* End dot11fUnpackIeWFATPC. */ -#define SigIeWFATPC ( 0x0078 ) +#define SigIeWFATPC ( 0x0079 ) tANI_U32 dot11fUnpackIeWFDIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWFDIEOpaque *pDst) @@ -4962,7 +4955,7 @@ tANI_U32 dot11fUnpackIeWFDIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWFDIEOpaque. */ -#define SigIeWFDIEOpaque ( 0x0079 ) +#define SigIeWFDIEOpaque ( 0x007a ) tANI_U32 dot11fUnpackIeWMMCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMCaps *pDst) @@ -4990,7 +4983,7 @@ tANI_U32 dot11fUnpackIeWMMCaps(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen return status; } /* End dot11fUnpackIeWMMCaps. */ -#define SigIeWMMCaps ( 0x007a ) +#define SigIeWMMCaps ( 0x007b ) tANI_U32 dot11fUnpackIeWMMInfoAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMInfoAp *pDst) @@ -5011,7 +5004,7 @@ tANI_U32 dot11fUnpackIeWMMInfoAp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeWMMInfoAp. */ -#define SigIeWMMInfoAp ( 0x007b ) +#define SigIeWMMInfoAp ( 0x007c ) tANI_U32 dot11fUnpackIeWMMInfoStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMInfoStation *pDst) @@ -5036,7 +5029,7 @@ tANI_U32 dot11fUnpackIeWMMInfoStation(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U return status; } /* End dot11fUnpackIeWMMInfoStation. */ -#define SigIeWMMInfoStation ( 0x007c ) +#define SigIeWMMInfoStation ( 0x007d ) tANI_U32 dot11fUnpackIeWMMParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWMMParams *pDst) @@ -5129,7 +5122,7 @@ tANI_U32 dot11fUnpackIeWMMParams(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeWMMParams. */ -#define SigIeWMMParams ( 0x007d ) +#define SigIeWMMParams ( 0x007e ) tANI_U32 dot11fUnpackIeWPA(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWPA *pDst) @@ -5211,7 +5204,7 @@ tANI_U32 dot11fUnpackIeWPA(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeWPA. */ -#define SigIeWPA ( 0x007e ) +#define SigIeWPA ( 0x007f ) tANI_U32 dot11fUnpackIeWPAOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWPAOpaque *pDst) @@ -5231,7 +5224,7 @@ tANI_U32 dot11fUnpackIeWPAOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeWPAOpaque. */ -#define SigIeWPAOpaque ( 0x007f ) +#define SigIeWPAOpaque ( 0x0080 ) static const tTLVDefn TLVS_WSC[ ] = { @@ -5269,7 +5262,7 @@ tANI_U32 dot11fUnpackIeWSC(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tD return status; } /* End dot11fUnpackIeWSC. */ -#define SigIeWSC ( 0x0080 ) +#define SigIeWSC ( 0x0081 ) tANI_U32 dot11fUnpackIeWiderBWChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWiderBWChanSwitchAnn *pDst) @@ -5289,7 +5282,7 @@ tANI_U32 dot11fUnpackIeWiderBWChanSwitchAnn(tpAniSirGlobal pCtx, tANI_U8 *pBuf, return status; } /* End dot11fUnpackIeWiderBWChanSwitchAnn. */ -#define SigIeWiderBWChanSwitchAnn ( 0x0081 ) +#define SigIeWiderBWChanSwitchAnn ( 0x0082 ) static const tTLVDefn TLVS_WscAssocReq[ ] = { @@ -5308,7 +5301,7 @@ tANI_U32 dot11fUnpackIeWscAssocReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscAssocReq. */ -#define SigIeWscAssocReq ( 0x0082 ) +#define SigIeWscAssocReq ( 0x0083 ) static const tTLVDefn TLVS_WscAssocRes[ ] = { @@ -5327,7 +5320,7 @@ tANI_U32 dot11fUnpackIeWscAssocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscAssocRes. */ -#define SigIeWscAssocRes ( 0x0083 ) +#define SigIeWscAssocRes ( 0x0084 ) static const tTLVDefn TLVS_WscBeacon[ ] = { @@ -5352,7 +5345,7 @@ tANI_U32 dot11fUnpackIeWscBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 iel return status; } /* End dot11fUnpackIeWscBeacon. */ -#define SigIeWscBeacon ( 0x0084 ) +#define SigIeWscBeacon ( 0x0085 ) static const tTLVDefn TLVS_WscBeaconProbeRes[ ] = { @@ -5385,7 +5378,7 @@ tANI_U32 dot11fUnpackIeWscBeaconProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tAN return status; } /* End dot11fUnpackIeWscBeaconProbeRes. */ -#define SigIeWscBeaconProbeRes ( 0x0085 ) +#define SigIeWscBeaconProbeRes ( 0x0086 ) tANI_U32 dot11fUnpackIeWscIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 ielen, tDot11fIEWscIEOpaque *pDst) @@ -5405,7 +5398,7 @@ tANI_U32 dot11fUnpackIeWscIEOpaque(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscIEOpaque. */ -#define SigIeWscIEOpaque ( 0x0086 ) +#define SigIeWscIEOpaque ( 0x0087 ) static const tTLVDefn TLVS_WscProbeReq[ ] = { @@ -5436,7 +5429,7 @@ tANI_U32 dot11fUnpackIeWscProbeReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscProbeReq. */ -#define SigIeWscProbeReq ( 0x0087 ) +#define SigIeWscProbeReq ( 0x0088 ) static const tTLVDefn TLVS_WscProbeRes[ ] = { @@ -5469,7 +5462,7 @@ tANI_U32 dot11fUnpackIeWscProbeRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 i return status; } /* End dot11fUnpackIeWscProbeRes. */ -#define SigIeWscProbeRes ( 0x0088 ) +#define SigIeWscProbeRes ( 0x0089 ) static const tTLVDefn TLVS_WscReassocRes[ ] = { @@ -5488,7 +5481,7 @@ tANI_U32 dot11fUnpackIeWscReassocRes(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U8 return status; } /* End dot11fUnpackIeWscReassocRes. */ -#define SigIeWscReassocRes ( 0x0089 ) +#define SigIeWscReassocRes ( 0x008a ) static const tFFDefn FFS_AddBAReq[] = { @@ -6248,13 +6241,13 @@ tANI_U32 dot11fUnpackAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RRMEnabledCap:\n")); if (!pFrm->RRMEnabledCap.present) @@ -6799,7 +6792,7 @@ tANI_U32 dot11fUnpackAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fAssocResponse, RSNIIE), offsetof(tDot11fIERSNIIE, present), 0, "RSNIIE" , 0, 3, 3, SigIeRSNIIE, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNIIE, 0, }, {offsetof(tDot11fAssocResponse, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, {offsetof(tDot11fAssocResponse, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, - {offsetof(tDot11fAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fAssocResponse, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fAssocResponse, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, {offsetof(tDot11fAssocResponse, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, {offsetof(tDot11fAssocResponse, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -7022,6 +7015,18 @@ tANI_U32 dot11fUnpackAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -7939,7 +7944,7 @@ tANI_U32 dot11fUnpackAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 {offsetof(tDot11fAuthentication, ChallengeText), offsetof(tDot11fIEChallengeText, present), 0, "ChallengeText" , 0, 3, 255, SigIeChallengeText, {0, 0, 0, 0, 0}, 0, DOT11F_EID_CHALLENGETEXT, 0, }, {offsetof(tDot11fAuthentication, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, {offsetof(tDot11fAuthentication, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, - {offsetof(tDot11fAuthentication, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fAuthentication, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fAuthentication, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fAuthentication, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fAuthentication, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; @@ -8040,6 +8045,18 @@ tANI_U32 dot11fUnpackAuthentication(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -8659,11 +8676,11 @@ tANI_U32 dot11fUnpackBeacon(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, t } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APChannelReport:\n")); if (!pFrm->APChannelReport.present) @@ -10850,11 +10867,11 @@ tANI_U32 dot11fUnpackBeaconIEs(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APChannelReport:\n")); if (!pFrm->APChannelReport.present) @@ -15554,7 +15571,7 @@ tANI_U32 dot11fUnpackRadioMeasurementRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, {offsetof(tDot11fReAssocRequest, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, {offsetof(tDot11fReAssocRequest, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, {offsetof(tDot11fReAssocRequest, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, - {offsetof(tDot11fReAssocRequest, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fReAssocRequest, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fReAssocRequest, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fReAssocRequest, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, {offsetof(tDot11fReAssocRequest, WPAOpaque), offsetof(tDot11fIEWPAOpaque, present), 0, "WPAOpaque" , 0, 8, 255, SigIeWPAOpaque, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPAOPAQUE, 0, }, {offsetof(tDot11fReAssocRequest, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -15676,13 +15693,13 @@ tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RRMEnabledCap:\n")); if (!pFrm->RRMEnabledCap.present) @@ -15778,6 +15795,18 @@ tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -16601,7 +16630,7 @@ tANI_U32 dot11fUnpackReAssocRequest(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 {offsetof(tDot11fReAssocResponse, RRMEnabledCap), offsetof(tDot11fIERRMEnabledCap, present), 0, "RRMEnabledCap" , 0, 7, 7, SigIeRRMEnabledCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RRMENABLEDCAP, 0, }, {offsetof(tDot11fReAssocResponse, RSNOpaque), offsetof(tDot11fIERSNOpaque, present), 0, "RSNOpaque" , 0, 8, 255, SigIeRSNOpaque, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSNOPAQUE, 0, }, {offsetof(tDot11fReAssocResponse, MobilityDomain), offsetof(tDot11fIEMobilityDomain, present), 0, "MobilityDomain" , 0, 5, 5, SigIeMobilityDomain, {0, 0, 0, 0, 0}, 0, DOT11F_EID_MOBILITYDOMAIN, 0, }, - {offsetof(tDot11fReAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fReAssocResponse, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fReAssocResponse, RICDataDesc), offsetof(tDot11fIERICDataDesc, present), offsetof(tDot11fReAssocResponse, num_RICDataDesc), "RICDataDesc" , 2, 2, 550, SigIeRICDataDesc, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATADESC, 0, }, {offsetof(tDot11fReAssocResponse, WPA), offsetof(tDot11fIEWPA, present), 0, "WPA" , 0, 8, 50, SigIeWPA, {0, 80, 242, 1, 0}, 4, DOT11F_EID_WPA, 0, }, {offsetof(tDot11fReAssocResponse, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -16834,6 +16863,18 @@ tANI_U32 dot11fUnpackReAssocResponse(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U3 FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -17774,41 +17815,6 @@ tANI_U32 dot11fUnpackSMPowerSave(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nB } /* End dot11fUnpackSMPowerSave. */ - static const tFFDefn FFS_SaQueryRsp[] = { - { "Category", offsetof(tDot11fSaQueryRsp, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, - { "Action", offsetof(tDot11fSaQueryRsp, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, - { "TransactionId", offsetof(tDot11fSaQueryRsp, TransactionId), SigFfTransactionId , DOT11F_FF_TRANSACTIONID_LEN, }, - { NULL, 0, 0, 0,}, - }; - - static const tIEDefn IES_SaQueryRsp[] = { - {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; - -tANI_U32 dot11fUnpackSaQueryRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fSaQueryRsp *pFrm) -{ - tANI_U32 i = 0; - tANI_U32 status = 0; - status = UnpackCore(pCtx, pBuf, nBuf, FFS_SaQueryRsp, IES_SaQueryRsp, ( tANI_U8* )pFrm, sizeof(*pFrm)); - - (void)i; -# ifdef DOT11F_DUMP_FRAMES - if (!DOT11F_FAILED(status)) - { - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Unpacked the SaQueryRsp:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), pBuf, nBuf); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("to:\n")); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Category:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Category.category, 1); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Action:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Action.action, 1); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("TransactionId:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->TransactionId.transId, 2); - } -# endif // DOT11F_DUMP_FRAMES - return status; - -} /* End dot11fUnpackSaQueryRsp. */ - static const tFFDefn FFS_TDLSDisReq[] = { { "Category", offsetof(tDot11fTDLSDisReq, Category), SigFfCategory , DOT11F_FF_CATEGORY_LEN, }, { "Action", offsetof(tDot11fTDLSDisReq, Action), SigFfAction , DOT11F_FF_ACTION_LEN, }, @@ -17870,7 +17876,7 @@ tANI_U32 dot11fUnpackTDLSDisReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBu {offsetof(tDot11fTDLSDisRsp, SuppChannels), offsetof(tDot11fIESuppChannels, present), 0, "SuppChannels" , 0, 4, 98, SigIeSuppChannels, {0, 0, 0, 0, 0}, 0, DOT11F_EID_SUPPCHANNELS, 0, }, {offsetof(tDot11fTDLSDisRsp, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 112, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, {offsetof(tDot11fTDLSDisRsp, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 10, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, - {offsetof(tDot11fTDLSDisRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSDisRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSDisRsp, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fTDLSDisRsp, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, {offsetof(tDot11fTDLSDisRsp, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -18065,6 +18071,18 @@ tANI_U32 dot11fUnpackTDLSDisRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBu FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -18325,12 +18343,13 @@ tANI_U32 dot11fUnpackTDLSPeerTrafficRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI static const tIEDefn IES_TDLSSetupCnf[] = { {offsetof(tDot11fTDLSSetupCnf, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 112, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, {offsetof(tDot11fTDLSSetupCnf, EDCAParamSet), offsetof(tDot11fIEEDCAParamSet, present), 0, "EDCAParamSet" , 0, 20, 20, SigIeEDCAParamSet, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EDCAPARAMSET, 0, }, - {offsetof(tDot11fTDLSSetupCnf, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupCnf, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSSetupCnf, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fTDLSSetupCnf, HTInfo), offsetof(tDot11fIEHTInfo, present), 0, "HTInfo" , 0, 24, 56, SigIeHTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTINFO, 0, }, {offsetof(tDot11fTDLSSetupCnf, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 0, }, {offsetof(tDot11fTDLSSetupCnf, WMMInfoStation), offsetof(tDot11fIEWMMInfoStation, present), 0, "WMMInfoStation" , 0, 9, 9, SigIeWMMInfoStation, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOSTATION, 0, }, {offsetof(tDot11fTDLSSetupCnf, VHTOperation), offsetof(tDot11fIEVHTOperation, present), 0, "VHTOperation" , 0, 7, 7, SigIeVHTOperation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTOPERATION, 0, }, + {offsetof(tDot11fTDLSSetupCnf, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupCnf *pFrm) @@ -18454,6 +18473,18 @@ tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -18533,6 +18564,18 @@ tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -18555,7 +18598,7 @@ tANI_U32 dot11fUnpackTDLSSetupCnf(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fTDLSSetupReq, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 112, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, {offsetof(tDot11fTDLSSetupReq, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 10, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, {offsetof(tDot11fTDLSSetupReq, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, - {offsetof(tDot11fTDLSSetupReq, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupReq, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSSetupReq, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fTDLSSetupReq, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, {offsetof(tDot11fTDLSSetupReq, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -18725,13 +18768,13 @@ tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTInfo:\n")); if (!pFrm->FTInfo.present) @@ -18778,6 +18821,18 @@ tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -18950,7 +19005,7 @@ tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fTDLSSetupRsp, RSN), offsetof(tDot11fIERSN, present), 0, "RSN" , 0, 8, 112, SigIeRSN, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RSN, 0, }, {offsetof(tDot11fTDLSSetupRsp, ExtCap), offsetof(tDot11fIEExtCap, present), 0, "ExtCap" , 0, 10, 10, SigIeExtCap, {0, 0, 0, 0, 0}, 0, DOT11F_EID_EXTCAP, 0, }, {offsetof(tDot11fTDLSSetupRsp, QOSCapsStation), offsetof(tDot11fIEQOSCapsStation, present), 0, "QOSCapsStation" , 0, 3, 3, SigIeQOSCapsStation, {0, 0, 0, 0, 0}, 0, DOT11F_EID_QOSCAPSSTATION, 0, }, - {offsetof(tDot11fTDLSSetupRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSSetupRsp, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSSetupRsp, FTTimeoutInterval), offsetof(tDot11fIEFTTimeoutInterval, present), 0, "FTTimeoutInterval" , 0, 7, 7, SigIeFTTimeoutInterval, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTTIMEOUTINTERVAL, 0, }, {offsetof(tDot11fTDLSSetupRsp, RICData), offsetof(tDot11fIERICData, present), 0, "RICData" , 0, 6, 6, SigIeRICData, {0, 0, 0, 0, 0}, 0, DOT11F_EID_RICDATA, 0, }, {offsetof(tDot11fTDLSSetupRsp, HTCaps), offsetof(tDot11fIEHTCaps, present), 0, "HTCaps" , 0, 28, 60, SigIeHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_HTCAPS, 0, }, @@ -18958,6 +19013,7 @@ tANI_U32 dot11fUnpackTDLSSetupReq(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n {offsetof(tDot11fTDLSSetupRsp, WMMInfoStation), offsetof(tDot11fIEWMMInfoStation, present), 0, "WMMInfoStation" , 0, 9, 9, SigIeWMMInfoStation, {0, 80, 242, 2, 0}, 5, DOT11F_EID_WMMINFOSTATION, 0, }, {offsetof(tDot11fTDLSSetupRsp, AID), offsetof(tDot11fIEAID, present), 0, "AID" , 0, 4, 4, SigIeAID, {0, 0, 0, 0, 0}, 0, DOT11F_EID_AID, 0, }, {offsetof(tDot11fTDLSSetupRsp, VHTCaps), offsetof(tDot11fIEVHTCaps, present), 0, "VHTCaps" , 0, 14, 14, SigIeVHTCaps, {0, 0, 0, 0, 0}, 0, DOT11F_EID_VHTCAPS, 0, }, + {offsetof(tDot11fTDLSSetupRsp, OperatingMode), offsetof(tDot11fIEOperatingMode, present), 0, "OperatingMode" , 0, 3, 3, SigIeOperatingMode, {0, 0, 0, 0, 0}, 0, DOT11F_EID_OPERATINGMODE, 0, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 nBuf, tDot11fTDLSSetupRsp *pFrm) @@ -19122,13 +19178,13 @@ tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTInfo:\n")); if (!pFrm->FTInfo.present) @@ -19175,6 +19231,18 @@ tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -19324,6 +19392,18 @@ tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } } # endif // DOT11F_DUMP_FRAMES return status; @@ -19338,7 +19418,7 @@ tANI_U32 dot11fUnpackTDLSSetupRsp(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n }; static const tIEDefn IES_TDLSTeardown[] = { - {offsetof(tDot11fTDLSTeardown, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 187, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, + {offsetof(tDot11fTDLSTeardown, FTInfo), offsetof(tDot11fIEFTInfo, present), 0, "FTInfo" , 0, 84, 222, SigIeFTInfo, {0, 0, 0, 0, 0}, 0, DOT11F_EID_FTINFO, 0, }, {offsetof(tDot11fTDLSTeardown, LinkIdentifier), offsetof(tDot11fIELinkIdentifier, present), 0, "LinkIdentifier" , 0, 20, 20, SigIeLinkIdentifier, {0, 0, 0, 0, 0}, 0, DOT11F_EID_LINKIDENTIFIER, 1, }, {0, 0, 0, NULL, 0, 0, 0, 0, {0, 0, 0, 0, 0}, 0, 0xff, 0, }, }; @@ -19406,6 +19486,18 @@ tANI_U32 dot11fUnpackTDLSTeardown(tpAniSirGlobal pCtx, tANI_U8 *pBuf, tANI_U32 n FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("LinkIdentifier:\n")); if (!pFrm->LinkIdentifier.present) @@ -19906,9 +19998,6 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, case SigFfTimeStamp: dot11fUnpackFfTimeStamp(pCtx, pBufRemaining, ( tDot11fFfTimeStamp* )(pFrm + pFf->offset )); break; - case SigFfTransactionId: - dot11fUnpackFfTransactionId(pCtx, pBufRemaining, ( tDot11fFfTransactionId* )(pFrm + pFf->offset )); - break; case SigFfTxAntennaId: dot11fUnpackFfTxAntennaId(pCtx, pBufRemaining, ( tDot11fFfTxAntennaId* )(pFrm + pFf->offset )); break; @@ -20019,6 +20108,9 @@ static tANI_U32 UnpackCore(tpAniSirGlobal pCtx, (tANI_U8*) &((( tDot11fIEHCF* )(pFrm + pIe->offset + sizeof( tDot11fIEHCF)*countOffset ) )->present), (tANI_U8*) &((( tDot11fIEHCF* )(pFrm + pIe->offset + sizeof(tDot11fIEHCF)*countOffset ) )->enabled) ); break; + case SigIeIGTK: + status |= dot11fUnpackIeIGTK(pCtx, pBufRemaining, len, ( tDot11fIEIGTK* )(pFrm + pIe->offset + sizeof(tDot11fIEIGTK)*countOffset) ); + break; case SigIeLLAttr: status |= dot11fUnpackIeLLAttr(pCtx, pBufRemaining, len, ( tDot11fIELLAttr* )(pFrm + pIe->offset + sizeof(tDot11fIELLAttr)*countOffset) ); break; @@ -21888,14 +21980,6 @@ tANI_U32 dot11fGetPackedSMPowerSaveSize(tpAniSirGlobal pCtx, tDot11fSMPowerSave return status; } /* End dot11fGetPackedSMPowerSaveSize. */ -tANI_U32 dot11fGetPackedSaQueryRspSize(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U32 *pnNeeded) -{ - tANI_U32 status = 0; - *pnNeeded = 4; - status = GetPackedSizeCore(pCtx, ( tANI_U8* )pFrm, pnNeeded, IES_SaQueryRsp); - return status; -} /* End dot11fGetPackedSaQueryRspSize. */ - tANI_U32 dot11fGetPackedTDLSDisReqSize(tpAniSirGlobal pCtx, tDot11fTDLSDisReq *pFrm, tANI_U32 *pnNeeded) { tANI_U32 status = 0; @@ -22057,6 +22141,11 @@ static tANI_U32 GetPackedSizeCore(tpAniSirGlobal pCtx, byteCount = 1; pIePresent = ( (tDot11fIEHCF* )(pFrm + pIe->offset + offset * i ))->present; break; + case SigIeIGTK: + offset = sizeof(tDot11fIEIGTK); + byteCount = 33; + pIePresent = ( (tDot11fIEIGTK* )(pFrm + pIe->offset + offset * i ))->present; + break; case SigIeLLAttr: offset = sizeof(tDot11fIELLAttr); byteCount = 4; @@ -23214,14 +23303,6 @@ void dot11fPackFfTimeStamp(tpAniSirGlobal pCtx, (void)pCtx; } /* End dot11fPackFfTimeStamp. */ -void dot11fPackFfTransactionId(tpAniSirGlobal pCtx, - tDot11fFfTransactionId *pSrc, - tANI_U8 *pBuf) -{ - DOT11F_MEMCPY(pCtx, pBuf, pSrc->transId, 2); - (void)pCtx; -} /* End dot11fPackFfTransactionId. */ - void dot11fPackFfTxAntennaId(tpAniSirGlobal pCtx, tDot11fFfTxAntennaId *pSrc, tANI_U8 *pBuf) @@ -24811,6 +24892,45 @@ tANI_U32 dot11fPackIeHCF(tpAniSirGlobal pCtx, return DOT11F_PARSE_SUCCESS; } /* End dot11fPackIeHCF. */ +tANI_U32 dot11fPackIeIGTK(tpAniSirGlobal pCtx, + tDot11fIEIGTK *pSrc, + tANI_U8 *pBuf, + tANI_U32 nBuf, + tANI_U32 *pnConsumed) +{ + tANI_U8* pIeLen = 0; + tANI_U32 nConsumedOnEntry = *pnConsumed; + tANI_U32 nNeeded = 0U; + nNeeded += 33; + while ( pSrc->present ) + { + if ( nNeeded > nBuf ) return DOT11F_BUFFER_OVERFLOW; + *pBuf = 4; + ++pBuf; ++(*pnConsumed); + pIeLen = pBuf; + ++pBuf; ++(*pnConsumed); + DOT11F_MEMCPY(pCtx, pBuf, pSrc->keyID, 2); + *pnConsumed += 2; + pBuf += 2; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->IPN, 6); + *pnConsumed += 6; + pBuf += 6; + *pBuf = pSrc->keyLength; + *pnConsumed += 1; + pBuf += 1; + DOT11F_MEMCPY(pCtx, pBuf, pSrc->key, 24); + *pnConsumed += 24; + // fieldsEndFlag = 1 + break; + } + (void)pCtx; + if (pIeLen) + { + *pIeLen = *pnConsumed - nConsumedOnEntry - 2; + } + return DOT11F_PARSE_SUCCESS; +} /* End dot11fPackIeIGTK. */ + tANI_U32 dot11fPackIeLLAttr(tpAniSirGlobal pCtx, tDot11fIELLAttr *pSrc, tANI_U8 *pBuf, @@ -24830,7 +24950,7 @@ tANI_U32 dot11fPackIeLLAttr(tpAniSirGlobal pCtx, ++pBuf; ++(*pnConsumed); frameshtonl(pCtx, pBuf, pSrc->defer_threshold, 1); *pnConsumed += 4; - // fieldsEndFlag = 1 + // fieldsEndFlag = 1 break; } (void)pCtx; @@ -29322,11 +29442,11 @@ tANI_U32 dot11fPackIeQOSCapsAp(tpAniSirGlobal pCtx, pIeLen = pBuf; ++pBuf; ++(*pnConsumed); tmp143__ = 0U; - tmp143__ |= ( pSrc->reserved << 0 ); - tmp143__ |= ( pSrc->txopreq << 1 ); - tmp143__ |= ( pSrc->qreq << 2 ); - tmp143__ |= ( pSrc->qack << 3 ); - tmp143__ |= ( pSrc->count << 4 ); + tmp143__ |= ( pSrc->count << 0 ); + tmp143__ |= ( pSrc->qack << 4 ); + tmp143__ |= ( pSrc->qreq << 5 ); + tmp143__ |= ( pSrc->txopreq << 6 ); + tmp143__ |= ( pSrc->reserved << 7 ); *pBuf = tmp143__; *pnConsumed += 1; // fieldsEndFlag = 1 @@ -29360,13 +29480,13 @@ tANI_U32 dot11fPackIeQOSCapsStation(tpAniSirGlobal pCtx, pIeLen = pBuf; ++pBuf; ++(*pnConsumed); tmp144__ = 0U; - tmp144__ |= ( pSrc->more_data_ack << 0 ); - tmp144__ |= ( pSrc->max_sp_length << 1 ); - tmp144__ |= ( pSrc->qack << 3 ); - tmp144__ |= ( pSrc->acbe_uapsd << 4 ); - tmp144__ |= ( pSrc->acbk_uapsd << 5 ); - tmp144__ |= ( pSrc->acvi_uapsd << 6 ); - tmp144__ |= ( pSrc->acvo_uapsd << 7 ); + tmp144__ |= ( pSrc->acvo_uapsd << 0 ); + tmp144__ |= ( pSrc->acvi_uapsd << 1 ); + tmp144__ |= ( pSrc->acbk_uapsd << 2 ); + tmp144__ |= ( pSrc->acbe_uapsd << 3 ); + tmp144__ |= ( pSrc->qack << 4 ); + tmp144__ |= ( pSrc->max_sp_length << 5 ); + tmp144__ |= ( pSrc->more_data_ack << 7 ); *pBuf = tmp144__; *pnConsumed += 1; // fieldsEndFlag = 1 @@ -31566,13 +31686,13 @@ tANI_U32 dot11fPackAssocRequest(tpAniSirGlobal pCtx, tDot11fAssocRequest *pFrm, } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCREQUEST), FRFL("RRMEnabledCap:\n")); if (!pFrm->RRMEnabledCap.present) @@ -32307,6 +32427,18 @@ tANI_U32 dot11fPackAssocResponse(tpAniSirGlobal pCtx, tDot11fAssocResponse *pFrm FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_ASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -33310,6 +33442,18 @@ tANI_U32 dot11fPackAuthentication(tpAniSirGlobal pCtx, tDot11fAuthentication *pF FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_AUTHENTICATION), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -33877,11 +34021,11 @@ tANI_U32 dot11fPackBeacon(tpAniSirGlobal pCtx, tDot11fBeacon *pFrm, tANI_U8 *pBu } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACON), FRFL("APChannelReport:\n")); if (!pFrm->APChannelReport.present) @@ -35967,11 +36111,11 @@ tANI_U32 dot11fPackBeaconIEs(tpAniSirGlobal pCtx, tDot11fBeaconIEs *pFrm, tANI_U } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("count (4): %d\n"), pFrm->QOSCapsAp.count); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qack (1): %d\n"), pFrm->QOSCapsAp.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("qreq (1): %d\n"), pFrm->QOSCapsAp.qreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("txopreq (1): %d\n"), pFrm->QOSCapsAp.txopreq); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("reserved (1): %d\n"), pFrm->QOSCapsAp.reserved); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_BEACONIES), FRFL("APChannelReport:\n")); if (!pFrm->APChannelReport.present) @@ -40394,13 +40538,13 @@ tANI_U32 dot11fPackReAssocRequest(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pF } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("RRMEnabledCap:\n")); if (!pFrm->RRMEnabledCap.present) @@ -40496,6 +40640,18 @@ tANI_U32 dot11fPackReAssocRequest(tpAniSirGlobal pCtx, tDot11fReAssocRequest *pF FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCREQUEST), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -41518,6 +41674,18 @@ tANI_U32 dot11fPackReAssocResponse(tpAniSirGlobal pCtx, tDot11fReAssocResponse * FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_REASSOCRESPONSE), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } for (i = 0; i < pFrm->num_RICDataDesc; ++i) { @@ -42451,32 +42619,6 @@ tANI_U32 dot11fPackSMPowerSave(tpAniSirGlobal pCtx, tDot11fSMPowerSave *pFrm, tA } /* End dot11fUnpackSMPowerSave. */ -tANI_U32 dot11fPackSaQueryRsp(tpAniSirGlobal pCtx, tDot11fSaQueryRsp *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) -{ - tANI_U32 i = 0; - tANI_U32 status = 0; - (void)i; - *pnConsumed = 0U; - status = PackCore(pCtx, (tANI_U8*)pFrm, pBuf, nBuf, pnConsumed, FFS_SaQueryRsp, IES_SaQueryRsp); - -# ifdef DOT11F_DUMP_FRAMES - if (!DOT11F_FAILED(status)) - { - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Packed the SaQueryRsp:\n")); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Category:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Category.category, 1); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("Action:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->Action.action, 1); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("TransactionId:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), ( tANI_U8* )&pFrm->TransactionId.transId, 2); - FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), FRFL("to:\n")); - FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_SAQUERYRSP), pBuf, nBuf); - } -# endif // DOT11F_DUMP_FRAMES - return status; - -} /* End dot11fUnpackSaQueryRsp. */ - tANI_U32 dot11fPackTDLSDisReq(tpAniSirGlobal pCtx, tDot11fTDLSDisReq *pFrm, tANI_U8 *pBuf, tANI_U32 nBuf, tANI_U32 *pnConsumed) { tANI_U32 i = 0; @@ -42700,6 +42842,18 @@ tANI_U32 dot11fPackTDLSDisRsp(tpAniSirGlobal pCtx, tDot11fTDLSDisRsp *pFrm, tANI FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSDISRSP), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -43049,6 +43203,18 @@ tANI_U32 dot11fPackTDLSSetupCnf(tpAniSirGlobal pCtx, tDot11fTDLSSetupCnf *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -43128,6 +43294,18 @@ tANI_U32 dot11fPackTDLSSetupCnf(tpAniSirGlobal pCtx, tDot11fTDLSSetupCnf *pFrm, FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.chanCenterFreqSeg2, 1); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), ( tANI_U8* )&pFrm->VHTOperation.basicMCSSet, 2); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPCNF), pBuf, nBuf); } @@ -43295,13 +43473,13 @@ tANI_U32 dot11fPackTDLSSetupReq(tpAniSirGlobal pCtx, tDot11fTDLSSetupReq *pFrm, } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTInfo:\n")); if (!pFrm->FTInfo.present) @@ -43348,6 +43526,18 @@ tANI_U32 dot11fPackTDLSSetupReq(tpAniSirGlobal pCtx, tDot11fTDLSSetupReq *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPREQ), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -43666,13 +43856,13 @@ tANI_U32 dot11fPackTDLSSetupRsp(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, } else { - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); - FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvo_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvo_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acvi_uapsd (1): %d\n"), pFrm->QOSCapsStation.acvi_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbk_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbk_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("acbe_uapsd (1): %d\n"), pFrm->QOSCapsStation.acbe_uapsd); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("qack (1): %d\n"), pFrm->QOSCapsStation.qack); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("max_sp_length (2): %d\n"), pFrm->QOSCapsStation.max_sp_length); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("more_data_ack (1): %d\n"), pFrm->QOSCapsStation.more_data_ack); } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTInfo:\n")); if (!pFrm->FTInfo.present) @@ -43719,6 +43909,18 @@ tANI_U32 dot11fPackTDLSSetupRsp(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("FTTimeoutInterval:\n")); if (!pFrm->FTTimeoutInterval.present) @@ -43868,6 +44070,18 @@ tANI_U32 dot11fPackTDLSSetupRsp(tpAniSirGlobal pCtx, tDot11fTDLSSetupRsp *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("txSupDataRate (13): %d\n"), pFrm->VHTCaps.txSupDataRate); FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved3 (3): %d\n"), pFrm->VHTCaps.reserved3); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("OperatingMode:\n")); + if (!pFrm->OperatingMode.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("Not present.\n")); + } + else + { + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("chanWidth (2): %d\n"), pFrm->OperatingMode.chanWidth); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("reserved (2): %d\n"), pFrm->OperatingMode.reserved); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSS (3): %d\n"), pFrm->OperatingMode.rxNSS); + FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("rxNSSType (1): %d\n"), pFrm->OperatingMode.rxNSSType); + } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), FRFL("to:\n")); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSSETUPRSP), pBuf, nBuf); } @@ -43939,6 +44153,18 @@ tANI_U32 dot11fPackTDLSTeardown(tpAniSirGlobal pCtx, tDot11fTDLSTeardown *pFrm, FRAMES_LOG1(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("num_PMK_R0_ID: %d.\n"), pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* ) pFrm->FTInfo.R0KH_ID.PMK_R0_ID, pFrm->FTInfo.R0KH_ID.num_PMK_R0_ID); } + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("IGTK:\n")); + if (!pFrm->FTInfo.IGTK.present) + { + FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("Not present.\n")); + } + else + { + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyID, 2); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.IPN, 6); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.keyLength, 1); + FRAMES_DUMP(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), ( tANI_U8* )&pFrm->FTInfo.IGTK.key, 24); + } } FRAMES_LOG0(pCtx, FRAMES_SEV_FOR_FRAME(pCtx, DOT11F_TDLSTEARDOWN), FRFL("LinkIdentifier:\n")); if (!pFrm->LinkIdentifier.present) @@ -44371,9 +44597,6 @@ static tANI_U32 PackCore(tpAniSirGlobal pCtx, case SigFfTimeStamp: dot11fPackFfTimeStamp(pCtx, (tDot11fFfTimeStamp* )(pSrc + pFf->offset), pBufRemaining); break; - case SigFfTransactionId: - dot11fPackFfTransactionId(pCtx, (tDot11fFfTransactionId* )(pSrc + pFf->offset), pBufRemaining); - break; case SigFfTxAntennaId: dot11fPackFfTxAntennaId(pCtx, (tDot11fFfTxAntennaId* )(pSrc + pFf->offset), pBufRemaining); break; @@ -44429,6 +44652,9 @@ static tANI_U32 PackCore(tpAniSirGlobal pCtx, case SigIeHCF: status |= dot11fPackIeHCF(pCtx, ( tDot11fIEHCF* )(pSrc + pIe->offset + sizeof(tDot11fIEHCF) * i ), pBufRemaining, nBufRemaining, &len); break; + case SigIeIGTK: + status |= dot11fPackIeIGTK(pCtx, ( tDot11fIEIGTK* )(pSrc + pIe->offset + sizeof(tDot11fIEIGTK) * i ), pBufRemaining, nBufRemaining, &len); + break; case SigIeLLAttr: status |= dot11fPackIeLLAttr(pCtx, ( tDot11fIELLAttr* )(pSrc + pIe->offset + sizeof(tDot11fIELLAttr) * i ), pBufRemaining, nBufRemaining, &len); break; diff --git a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c index 4ed519345ff..70efdaceaaf 100644 --- a/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c +++ b/drivers/staging/prima/CORE/SYS/legacy/src/utils/src/macTrace.c @@ -503,6 +503,9 @@ tANI_U8* macTraceGetWdaMsgString( tANI_U16 wdaMsg ) CASE_RETURN_STRING(WDA_UPDATE_SCAN_PARAMS_REQ); CASE_RETURN_STRING(WDA_SET_PNO_CHANGED_IND); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + CASE_RETURN_STRING(WDA_ROAM_SCAN_OFFLOAD_REQ); +#endif #ifdef WLAN_WAKEUP_EVENTS CASE_RETURN_STRING(WDA_WAKE_REASON_IND); #endif // WLAN_WAKEUP_EVENTS diff --git a/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h b/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h index 7bf957805ca..9e558f5c096 100644 --- a/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h +++ b/drivers/staging/prima/CORE/TL/inc/wlan_qct_tl.h @@ -51,17 +51,9 @@ DESCRIPTION This file contains the external API exposed by the wlan transport layer module. -<<<<<<< HEAD:CORE/TL/inc/wlan_qct_tl.h - - Copyright (c) 2008 QUALCOMM Incorporated. All Rights Reserved. - Qualcomm Confidential and Proprietary -======= - - Copyright (c) 2008 Qualcomm Technologies, Inc. All Rights Reserved. Qualcomm Technologies Confidential and Proprietary ->>>>>>> 326d6cf... wlan: remove obsolete ANI_CHIPSET_VOLANS featurization:prima/CORE/TL/inc/wlan_qct_tl.h ===========================================================================*/ @@ -107,7 +99,6 @@ when who what, where, why #include "sirApi.h" #include "csrApi.h" #include "sapApi.h" - /*---------------------------------------------------------------------------- * Preprocessor Definitions and Constants * -------------------------------------------------------------------------*/ @@ -134,10 +125,6 @@ when who what, where, why /*Maximum number of ACs */ #define WLANTL_MAX_AC 4 - -/* Bit Mask to represent All Stations */ -#define WLAN_ALL_STA 0xFF - /* Maximum number of station supported by TL, including BC. */ #define WLAN_MAX_STA_COUNT (HAL_NUM_STA) #define WLAN_NON32_STA_COUNT 14 @@ -442,6 +429,10 @@ typedef struct v_U16_t ucDesSTAId; /*Rssi based on the received packet */ v_S7_t rssiAvg; + #ifdef FEATURE_WLAN_TDLS + /* Packet received on direct link/AP link */ + v_U8_t isStaTdls; + #endif }WLANTL_RxMetaInfoType; @@ -2625,4 +2616,170 @@ WLANTL_ClearTxXmitPending v_PVOID_t pvosGCtx ); +/*========================================================================== + FUNCTION WLANTL_UpdateSTABssIdforIBSS + + DESCRIPTION + HDD will call this API to update the BSSID for this Station. + + DEPENDENCIES + The HDD Should registered the staID with TL before calling this function. + + PARAMETERS + + IN + pvosGCtx: Pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + IN + ucSTAId The Station ID for Bssid to be updated + IN + pBssid BSSID to be updated + + RETURN VALUE + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS +============================================================================*/ + +VOS_STATUS +WLANTL_UpdateSTABssIdforIBSS +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U8_t *pBssid +); + + + +/*=============================================================================== + FUNCTION WLANTL_UpdateLinkCapacity + + DESCRIPTION This function updates the STA's Link Capacity in TL + + DEPENDENCIES None + + PARAMETERS + + pvosGCtx VOS context VOS Global context + staId Station ID Station ID + linkCapacity linkCapacity Link Capacity + + RETURN None + + SIDE EFFECTS none + ===============================================================================*/ + +void +WLANTL_UpdateLinkCapacity +( + v_PVOID_t pvosGCtx, + v_U8_t staId, + v_U32_t linkCapacity); + +/*=========================================================================== + + FUNCTION WLANTL_GetSTALinkCapacity + + DESCRIPTION + + Returns Link Capacity of a particular STA. + + DEPENDENCIES + + A station must have been registered before its state can be retrieved. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station + + OUT + plinkCapacity: the current link capacity the connection to + the given station + + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ + +VOS_STATUS +WLANTL_GetSTALinkCapacity +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U32_t *plinkCapacity +); + +/*=========================================================================== + FUNCTION WLANTL_TxThreadDebugHandler + + DESCRIPTION + Printing TL Snapshot dump, processed under TxThread context, currently + information regarding the global TlCb struture. Dumps information related + to per active STA connection currently in use by TL. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + pvosGCtx: Pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + + RETURN VALUE None + + SIDE EFFECTS +============================================================================*/ + +v_VOID_t +WLANTL_TxThreadDebugHandler +( + v_PVOID_t *pvosGCtx +); + +/*========================================================================== + FUNCTION WLANTL_TLDebugMessage + + DESCRIPTION + Post a TL Snapshot request, posts message in TxThread. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + displaySnapshot Boolean showing whether to dump the snapshot or not. + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +v_VOID_t +WLANTL_TLDebugMessage +( + v_BOOL_t displaySnapshot +); + #endif /* #ifndef WLAN_QCT_WLANTL_H */ diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c index aa6aba8ebce..dde6092495f 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl.c @@ -155,9 +155,15 @@ #endif /*Enables debugging behavior in TL*/ #define TL_DEBUG +/*Enables debugging FC control frame in TL*/ +//#define TL_DEBUG_FC //#define WLAN_SOFTAP_FLOWCTRL_EN - //#define BTAMP_TEST +#ifdef TL_DEBUG_FC +#include +#include // wpalReadRegister +#endif + /*---------------------------------------------------------------------------- * Preprocessor Definitions and Constants * -------------------------------------------------------------------------*/ @@ -335,7 +341,6 @@ typedef struct #define WLAN_TL_INVALID_B_SIG 255 #define ENTER() VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "Enter:%s", __func__) - #define WLAN_TL_AC_ARRAY_2_MASK( _pSTA, _ucACMask, i ) \ do\ {\ @@ -491,7 +496,7 @@ WLANTL_Open if (( NULL == pTLCb ) || ( NULL == pTLConfig ) ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL, - "WLAN TL: Invalid input pointer on WLANTL_Open TL %x Config %x", pTLCb, pTLConfig )); + "WLAN TL: Invalid input pointer on WLANTL_Open TL %p Config %p", pTLCb, pTLConfig )); return VOS_STATUS_E_FAULT; } @@ -687,7 +692,6 @@ WLANTL_Start vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0); pTLCb->uResCount = uResCount; - return VOS_STATUS_SUCCESS; }/* WLANTL_Start */ @@ -3039,15 +3043,14 @@ WLANTL_TxMgmtFrm "WLAN TL:Failed while attempting to get addr2 %d", vosStatus)); return vosStatus; } -#ifdef FEATURE_WLAN_CCX - /* CCX IAPP Frame which are data frames but technically used + + /* CCX IAPP/TDLS Frame which are data frames but technically used * for management functionality comes through route. */ if (WLANTL_IS_QOS_DATA_FRAME(wFrmType)) \ { uQosHdr = VOS_TRUE; } -#endif /*---------------------------------------------------------------------- Call WDA to build TX header ----------------------------------------------------------------------*/ @@ -3223,8 +3226,6 @@ WLANTL_SuspendDataTx { WLANTL_CbType* pTLCb = NULL; vos_msg_t vosMsg; - v_U8_t ucTxSuspendReq, ucTxSuspended; - v_U32_t STAId = 0; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ @@ -3233,7 +3234,7 @@ WLANTL_SuspendDataTx Extract TL control block ------------------------------------------------------------------------*/ pTLCb = VOS_GET_TL_CB(pvosGCtx); - if ( NULL == pTLCb || NULL == pucSTAId ) + if ( NULL == pTLCb ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_SuspendDataTx")); @@ -3243,65 +3244,41 @@ WLANTL_SuspendDataTx /*------------------------------------------------------------------------ Check the type of request: generic suspend, or per station suspend ------------------------------------------------------------------------*/ - /* Station IDs for Suspend request are received as bitmap */ - ucTxSuspendReq = *pucSTAId; - ucTxSuspended = pTLCb->ucTxSuspended; - - if (WLAN_ALL_STA == ucTxSuspended) - { - /* All Stations are in Suspend mode. Nothing to do */ - TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN TL:All stations already suspended")); - return VOS_STATUS_E_EXISTS; - } - - if (WLAN_ALL_STA == *pucSTAId) + if (NULL == pucSTAId) { /* General Suspend Request received */ TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN TL:General suspend requested")); - vos_atomic_set_U8( &pTLCb->ucTxSuspended, WLAN_ALL_STA); + vos_atomic_set_U8( &pTLCb->ucTxSuspended, 1); vosMsg.reserved = WLAN_MAX_STA_COUNT; } else { - /* Station specific Suspend Request received */ - /* Update Station Id Bit map for suspend request */ - do + if ( WLANTL_STA_ID_INVALID( *pucSTAId ) ) { - /* If Bit set for this station with STAId */ - if (ucTxSuspendReq >> (STAId +1) ) - { - /* If it is Not a valid station ID */ - if ( WLANTL_STA_ID_INVALID( STAId ) ) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Invalid station id requested on WLANTL_SuspendDataTx")); - STAId++; - continue; - } - /* If this station is Not registered with TL */ - if( NULL == pTLCb->atlSTAClients[STAId] ) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Station memory was not previously allocated on WLANTL_SuspendDataTx")); - STAId++; - continue; - } - if ( 0 == pTLCb->atlSTAClients[STAId]->ucExists ) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Station was not previously registered on WLANTL_SuspendDataTx")); - STAId++; - continue; - } + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Invalid station id %d requested on WLANTL_SuspendDataTx", *pucSTAId)); + return VOS_STATUS_E_FAULT; + } - TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN TL:Suspend request for station: %d", STAId)); - vos_atomic_set_U8( &pTLCb->atlSTAClients[STAId]->ucTxSuspended, 1); - } - STAId++; - } while ( STAId < WLAN_MAX_STA_COUNT ); + if ( NULL == pTLCb->atlSTAClients[*pucSTAId] ) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Invalid pTLCb->atlSTAClients pointer for STA Id :%d on " + "WLANTL_SuspendDataTx", *pucSTAId)); + return VOS_STATUS_E_FAULT; + } + + if ( 0 == pTLCb->atlSTAClients[*pucSTAId]->ucExists ) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Station %d was not previously registered on WLANTL_SuspendDataTx", *pucSTAId)); + return VOS_STATUS_E_EXISTS; + } + + TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, + "WLAN TL:Suspend request for station: %d", *pucSTAId)); + vos_atomic_set_U8( &pTLCb->atlSTAClients[*pucSTAId]->ucTxSuspended, 1); vosMsg.reserved = *pucSTAId; } @@ -3360,8 +3337,6 @@ WLANTL_ResumeDataTx ) { WLANTL_CbType* pTLCb = NULL; - v_U8_t ucTxResumeReq; - v_U32_t STAId = 0; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ /*------------------------------------------------------------------------ @@ -3369,75 +3344,56 @@ WLANTL_ResumeDataTx Extract TL control block ------------------------------------------------------------------------*/ pTLCb = VOS_GET_TL_CB(pvosGCtx); - if ( NULL == pTLCb || NULL == pucSTAId) + if ( NULL == pTLCb ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_ResumeDataTx")); return VOS_STATUS_E_FAULT; } - ucTxResumeReq = *pucSTAId; /*------------------------------------------------------------------------ Check to see the type of resume ------------------------------------------------------------------------*/ - if ( WLAN_ALL_STA == *pucSTAId) + if ( NULL == pucSTAId ) { TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN TL:General resume requested")); vos_atomic_set_U8( &pTLCb->ucTxSuspended, 0); - - /* Set to Resume for all stations */ - for (STAId = 0; STAId < WLAN_MAX_STA_COUNT; STAId++) - { - if( NULL != pTLCb->atlSTAClients[STAId] ) - { - vos_atomic_set_U8( &pTLCb->atlSTAClients[STAId]->ucTxSuspended, 0); - } - } } else { - do + if ( WLANTL_STA_ID_INVALID( *pucSTAId )) { - /* If Bit Set for this station with STAId */ - if (ucTxResumeReq >> (STAId + 1)) - { - /* If it is Not a valid station ID */ - if ( WLANTL_STA_ID_INVALID( STAId )) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Invalid station id requested on WLANTL_ResumeDataTx")); - STAId++; - continue; - } - if ( NULL == pTLCb->atlSTAClients[STAId]) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Station was not allocated memory on WLANTL_ResumeDataTx")); - STAId++; - continue; - } - /* If this station is Not registered with TL */ - if ( 0 == pTLCb->atlSTAClients[STAId]->ucExists ) - { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Station was not previously registered on WLANTL_ResumeDataTx")); - STAId++; - continue; - } + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Invalid station id %d requested on WLANTL_ResumeDataTx", *pucSTAId)); + return VOS_STATUS_E_FAULT; + } - TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN TL:Resume request for station: %d", STAId)); - vos_atomic_set_U8( &pTLCb->atlSTAClients[STAId]->ucTxSuspended, 0); - } - STAId++; - } while ( STAId < WLAN_MAX_STA_COUNT ); + if ( NULL == pTLCb->atlSTAClients[*pucSTAId] ) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Invalid pTLCb->atlSTAClients pointer for STA Id :%d on " + "WLANTL_ResumeDataTx", *pucSTAId)); + return VOS_STATUS_E_FAULT; + } + + if ( 0 == pTLCb->atlSTAClients[*pucSTAId]->ucExists ) + { + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WLAN TL:Station %d was not previously registered on WLANTL_ResumeDataTx", *pucSTAId)); + return VOS_STATUS_E_EXISTS; + } + + TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, + "WLAN TL:Resume request for station: %d", *pucSTAId)); + vos_atomic_set_U8( &pTLCb->atlSTAClients[*pucSTAId]->ucTxSuspended, 0); } /*------------------------------------------------------------------------ Resuming transmission ------------------------------------------------------------------------*/ - if ( pTLCb->uResCount >= WDA_TLI_MIN_RES_MF ) + if (( pTLCb->uResCount >= WDA_TLI_MIN_RES_MF ) && + ( 0 == pTLCb->ucTxSuspended )) { TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, "WLAN TL:Resuming transmission")); @@ -4378,7 +4334,7 @@ WLANTL_TxComp } TLLOG2(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_HIGH, - "WLAN TL:Calling Tx complete for pkt %x in function %x", + "WLAN TL:Calling Tx complete for pkt %p in function %p", vosDataBuff, pfnTxComp)); vosTempTx = vosDataBuff; @@ -4456,8 +4412,8 @@ WLANTL_CacheSTAFrame if (( NULL == pTLCb ) || ( NULL == vosTempBuff ) ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL: Invalid input pointer on WLANTL_CacheSTAFrame TL %x" - " Packet %x", pTLCb, vosTempBuff )); + "WLAN TL: Invalid input pointer on WLANTL_CacheSTAFrame TL %p" + " Packet %p", pTLCb, vosTempBuff )); return VOS_STATUS_E_FAULT; } @@ -4651,7 +4607,7 @@ WLANTL_ForwardSTAFrames if ( NULL == pTLCb ) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL: Invalid input pointer on WLANTL_ForwardSTAFrames TL %x", + "WLAN TL: Invalid input pointer on WLANTL_ForwardSTAFrames TL %p", pTLCb )); return VOS_STATUS_E_FAULT; } @@ -5082,11 +5038,16 @@ WLANTL_ProcessFCFrame { #if 1 //enable processing of only fcStaTxDisabled bitmap for now. the else part is old better qos code. // need to revisit the old code for full implementation. - v_U8_t ucTxSuspended = 0, ucTxSuspendReq = 0, ucTxResumeReq = 0; - WLANTL_CbType* pTLCb = NULL; - + v_U8_t ucSTAId; + v_U16_t ucStaValidBitmap; + v_U16_t ucStaTxDisabledBitmap; + WLANTL_CbType* pTLCb = NULL; + #ifdef TL_DEBUG_FC + v_U32_t rxTimeStamp; + v_U32_t curTick; + #endif /*------------------------------------------------------------------------ - Extract TL control block + Extract TL control block ------------------------------------------------------------------------*/ pTLCb = VOS_GET_TL_CB(pvosGCtx); if ( NULL == pTLCb ) @@ -5095,27 +5056,30 @@ WLANTL_ProcessFCFrame "WLAN TL:Invalid TL pointer from pvosGCtx on WLANTL_SuspendDataTx")); return VOS_STATUS_E_FAULT; } + ucStaValidBitmap = WDA_GET_RX_FC_VALID_STA_MASK(pvBDHeader); + ucStaTxDisabledBitmap = WDA_GET_RX_FC_STA_TX_DISABLED_BITMAP(pvBDHeader); +#ifdef TL_DEBUG_FC + rxTimeStamp = WDA_GET_RX_TIMESTAMP(pvBDHeader); + /* hard code of MTU_GLOBAL_TIMER_ADDR to calculate the time between generated and processed */ + wpalReadRegister(0x03081400+0x1D4, &curTick); - /* Existing Stations with Tx suspended */ - ucTxSuspended = pTLCb->ucTxSuspended; - - /* Suspend Request Received */ - ucTxSuspendReq = (v_U8_t) WDA_GET_RX_FC_STA_TX_DISABLED_BITMAP(pvBDHeader); TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLANTL_ProcessFCFrame called for Stations:: Current: %x Requested: %x ", ucTxSuspended, ucTxSuspendReq)); - - ucTxResumeReq = ucTxSuspendReq ^ ( ucTxSuspended | ucTxSuspendReq ); - ucTxSuspendReq = ucTxSuspendReq ^ ( ucTxSuspended & ucTxSuspendReq ); - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "Station Suspend request processed :: Suspend: %x :Resume: %x ", ucTxSuspendReq, ucTxResumeReq)); - - if ( 0 != ucTxSuspendReq ) - { - WLANTL_SuspendDataTx(pvosGCtx, &ucTxSuspendReq, NULL); - } - if ( 0 != ucTxResumeReq ) + "%ld (%ld-%ld): Disabled %x Valid %x\n", curTick > rxTimeStamp ? curTick - rxTimeStamp : rxTimeStamp - (0xFFFFFFFF - curTick), + curTick, rxTimeStamp, ucStaTxDisabledBitmap, ucStaValidBitmap)); +#endif + for(ucSTAId = 0; ucStaValidBitmap != 0; ucStaValidBitmap >>=1, ucStaTxDisabledBitmap >>= 1, ucSTAId ++) { - WLANTL_ResumeDataTx(pvosGCtx, &ucTxResumeReq); + if ( (0 == (ucStaValidBitmap & 0x1)) || (pTLCb->atlSTAClients[ucSTAId] && (0 == pTLCb->atlSTAClients[ucSTAId]->ucExists)) ) + continue; + + if (ucStaTxDisabledBitmap & 0x1) + { + WLANTL_SuspendDataTx(pvosGCtx, &ucSTAId, NULL); + } + else + { + WLANTL_ResumeDataTx(pvosGCtx, &ucSTAId); + } } #else @@ -5512,6 +5476,13 @@ WLANTL_RxFrames } +#ifdef FEATURE_WLAN_TDLS + if (( pClientSTA->ucExists ) && + (WLAN_STA_TDLS == pClientSTA->wSTADesc.wSTAType) && + (pClientSTA->ucTxSuspended)) + vos_atomic_set_U8( &pClientSTA->ucTxSuspended, 0 ); +#endif + #ifdef FEATURE_WLAN_CCX if ((pClientSTA->wSTADesc.ucIsCcxSta)|| broadcast) { @@ -5792,12 +5763,12 @@ WLANTL_RxCachedFrames -------------------------------------------------------------------------*/ if ( !bSigMatch ) { - TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO_MED, "WLAN TL: Cached packet does not match DPU Sig of the new STA - drop " " DPU Sig %d UC %d BC %d B %d", uDPUSig, pClientSTA->wSTADesc.ucUcastSig, - pClientSTA->wSTADesc.ucUcastSig, + pClientSTA->wSTADesc.ucBcastSig, broadcast)); /* Drop packet */ @@ -6103,6 +6074,218 @@ WLANTL_ClearTxXmitPending return; }/*WLANTL_ClearTxXmitPending */ +/*========================================================================== + FUNCTION WLANTL_TxThreadDebugHandler + + DESCRIPTION + Printing TL Snapshot dump, processed under TxThread context, currently + information regarding the global TlCb struture. Dumps information related + to per active STA connection currently in use by TL. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + or WDA's control block can be extracted from its context + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +v_VOID_t +WLANTL_TxThreadDebugHandler +( + v_PVOID_t *pVosContext +) +{ + WLANTL_CbType* pTLCb = NULL; + WLANTL_STAClientType* pClientSTA = NULL; + int i = 0; + tWDA_CbContext *pWDA = NULL; + + TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL, + "WLAN TL: %s Enter ", __func__)); + + pTLCb = VOS_GET_TL_CB(pVosContext); + pWDA = (tWDA_CbContext *)vos_get_global_context(VOS_MODULE_ID_WDA, pVosContext); + + if ( NULL == pVosContext || NULL == pTLCb ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "Global VoS Context or TL Context are NULL")); + return; + } + + if (NULL != pWDA) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "WDA uTxFlowMask: %d", pWDA->uTxFlowMask)); + } + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "************************TL DUMP INFORMATION**************")); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "uDelayedTriggerFrmInt:%d\tuMinFramesProcThres:%d", + pTLCb->tlConfigInfo.uDelayedTriggerFrmInt, + pTLCb->tlConfigInfo.uMinFramesProcThres)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "Management Frame Client exists: %d", + pTLCb->tlMgmtFrmClient.ucExists)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "usPendingTxCompleteCount: %d\tucTxSuspended: %d", + pTLCb->usPendingTxCompleteCount, + pTLCb->ucTxSuspended)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "uResCount: %d", pTLCb->uResCount)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucRegisteredStaId: %d\tucCurrentSTA: %d", + pTLCb->ucRegisteredStaId, pTLCb->ucCurrentSTA)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "UrgentFrameProcessing: %s\tuFramesProcThres: %d", + (pTLCb->bUrgent?"True":"False"), pTLCb->uFramesProcThres)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "isTxTranmitMsgPending: %d\t isBMPS: %s", + pTLCb->isTxTranmitMsgPending, pTLCb->isBMPS?"True":"False")); + +#ifdef FEATURE_WLAN_TDLS + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TDLS Peer Count: %d", pTLCb->ucTdlsPeerCount)); +#endif + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "++++++++++++++++++++Registerd Client Information++++++++++")); + + for ( i =0; iatlSTAClients[i]; + if( NULL == pClientSTA || 0 == pClientSTA->ucExists) + { + continue; + } + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "######################STA Index: %d ############################",i)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN_STADescType:")); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "STAId: %d\t STA MAC Address: %pM", pClientSTA->wSTADesc.ucSTAId, + pClientSTA->wSTADesc.vSTAMACAddress.bytes)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "STA Type: %d\tProtectedFrame: %d", + pClientSTA->wSTADesc.wSTAType, pClientSTA->wSTADesc.ucProtectedFrame)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "QoS: %d\tRxFrameTrans: %d\tTxFrameTrans: %d", + pClientSTA->wSTADesc.ucQosEnabled, pClientSTA->wSTADesc.ucSwFrameRXXlation, + pClientSTA->wSTADesc.ucSwFrameTXXlation)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucUcastSig: %d\tucBcastSig: %d", pClientSTA->wSTADesc.ucUcastSig, + pClientSTA->wSTADesc.ucBcastSig)); + + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ClientIndex: %d\t Exists: %d", i, pClientSTA->ucExists)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TL State: %d\t TL Priority: %d", pClientSTA->tlState, + pClientSTA->tlPri)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucTxSuspended: %d\tucPktPending: %d", pClientSTA->ucTxSuspended, + pClientSTA->ucPktPending)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucEAPOLPktPending: %d\tucNoMoreData: %d", + pClientSTA->ucEapolPktPending, pClientSTA->ucNoMoreData)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucRxBlocked: %d\t fcStaTxDisabled: %d", pClientSTA->ucRxBlocked, + pClientSTA->fcStaTxDisabled)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucCurrentAC: %d\tucServicedAC: %d", pClientSTA->ucCurrentAC, + pClientSTA->ucServicedAC)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TID: %d\tautTxCount[0]: %d\tauRxCount[0]: %d",0, pClientSTA->auTxCount[0], + pClientSTA->auRxCount[0])); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "aucAcMask[0]: %d\taucAcMask[1]: %d\taucAcMask[2]: %d\taucAcMask[3]: %d\t", + pClientSTA->aucACMask[0], pClientSTA->aucACMask[1], + pClientSTA->aucACMask[2], pClientSTA->aucACMask[3])); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "ucCurrentWeight: %d", pClientSTA->ucCurrentWeight)); + + if( WLAN_STA_SOFTAP == pClientSTA->wSTADesc.wSTAType) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TrafficStatistics for SOFTAP Station:")); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "RUF=%d\tRMF=%d\tRBF=%d", pClientSTA->trafficStatistics.rxUCFcnt, + pClientSTA->trafficStatistics.rxMCFcnt, + pClientSTA->trafficStatistics.rxBCFcnt)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "RUB=%d\tRMB=%d\tRBB=%d", pClientSTA->trafficStatistics.rxUCBcnt, + pClientSTA->trafficStatistics.rxMCBcnt, + pClientSTA->trafficStatistics.rxBCBcnt)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TUF=%d\tTMF=%d\tTBF=%d", pClientSTA->trafficStatistics.txUCFcnt, + pClientSTA->trafficStatistics.txMCFcnt, + pClientSTA->trafficStatistics.txBCFcnt)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "TUB=%d\tTMB=%d\tTBB=%d", pClientSTA->trafficStatistics.txUCBcnt, + pClientSTA->trafficStatistics.txMCBcnt, + pClientSTA->trafficStatistics.txBCBcnt)); + } + } + return; +} + +/*========================================================================== + FUNCTION WLANTL_TLDebugMessage + + DESCRIPTION + Post a TL Snapshot request, posts message in TxThread. + + DEPENDENCIES + The TL must be initialized before this gets called. + + PARAMETERS + + IN + displaySnapshot Boolean showing whether to dump the snapshot or not. + + RETURN VALUE None + + SIDE EFFECTS + +============================================================================*/ + +v_VOID_t +WLANTL_TLDebugMessage +( + v_BOOL_t displaySnapshot +) +{ + vos_msg_t vosMsg; + VOS_STATUS status; + + if(displaySnapshot) + { + vosMsg.reserved = 0; + vosMsg.bodyptr = NULL; + vosMsg.type = WLANTL_TX_SNAPSHOT; + + status = vos_tx_mq_serialize( VOS_MODULE_ID_TL, &vosMsg); + if(status != VOS_STATUS_SUCCESS) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "TX Msg Posting Failed with status: %d",status)); + return; + } + } + return; +} /*============================================================================ TL STATE MACHINE @@ -6544,7 +6727,7 @@ WLANTL_STATxAuth if (( NULL == pTLCb ) || ( NULL == pvosDataBuff )) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "WLAN TL:Invalid input params on WLANTL_STATxAuth TL %x DB %x", + "WLAN TL:Invalid input params on WLANTL_STATxAuth TL %x DB %p", pTLCb, pvosDataBuff)); if (NULL != pvosDataBuff) { @@ -7407,7 +7590,7 @@ WLANTL_STARxAuth v_U16_t usActualHLen = 0; v_U8_t ucTid; #ifdef FEATURE_WLAN_WAPI - v_U16_t usEtherType; + v_U16_t usEtherType = 0; #endif v_U16_t usPktLen; vos_pkt_t* vosDataBuff ; @@ -7756,6 +7939,16 @@ if(0 == ucUnicastBroadcastType { wRxMetaInfo.ucUP = ucTid; wRxMetaInfo.rssiAvg = pClientSTA->rssiAvg; +#ifdef FEATURE_WLAN_TDLS + if (WLAN_STA_TDLS == pClientSTA->wSTADesc.wSTAType) + { + wRxMetaInfo.isStaTdls = TRUE; + } + else + { + wRxMetaInfo.isStaTdls = FALSE; + } +#endif pClientSTA->pfnSTARx( pvosGCtx, vosDataBuff, ucSTAId, &wRxMetaInfo ); } @@ -8190,10 +8383,8 @@ WLANTL_TxProcessMsg break; case WDA_DS_TX_START_XMIT: - - WLANTL_ClearTxXmitPending(pvosGCtx); - vosStatus = WDA_DS_TxFrames( pvosGCtx ); - + WLANTL_ClearTxXmitPending(pvosGCtx); + vosStatus = WDA_DS_TxFrames( pvosGCtx ); break; case WDA_DS_FINISH_ULA: @@ -8202,6 +8393,13 @@ WLANTL_TxProcessMsg callbackRoutine(callbackContext); break; + case WLANTL_TX_SNAPSHOT: + /*Dumping TL State and then continuing to print + the DXE Dump*/ + WLANTL_TxThreadDebugHandler(pvosGCtx); + WDA_TransportChannelDebug(NULL, VOS_TRUE, VOS_FALSE); + break; + default: /*no processing for now*/ break; @@ -8618,6 +8816,8 @@ WLANTL_Translate8023To80211Header for ( ucIndex = 0; ucIndex < WLAN_MAX_STA_COUNT ; ucIndex++) { if ( ucIndex != ucStaId && pTLCb->atlSTAClients[ucIndex] && pTLCb->atlSTAClients[ucIndex]->ucExists && + (pTLCb->atlSTAClients[ucIndex]->tlState == WLANTL_STA_AUTHENTICATED) && + (!pTLCb->atlSTAClients[ucIndex]->ucTxSuspended) && vos_mem_compare( (void*)pTLCb->atlSTAClients[ucIndex]->wSTADesc.vSTAMACAddress.bytes, (void*)w8023Header.vDA, 6) ) { @@ -10267,7 +10467,7 @@ WLANTL_CleanSTA ( NULL != ptlSTAClient->vosAMSDUChainRoot )) { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_FATAL, - "WLAN TL:Non NULL vosAMSDUChainRoot (=%x) on WLANTL_CleanSTA," + "WLAN TL:Non NULL vosAMSDUChainRoot (=%p) on WLANTL_CleanSTA," "suspecting a memory corruption")); } @@ -10404,7 +10604,7 @@ WLANTL_EnableUAPSDForAC { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Invalid input params on WLANTL_EnableUAPSDForAC" - " TL: %x STA: %d AC: %d SI: %d", + " TL: %p STA: %d AC: %d SI: %d", pTLCb, ucSTAId, ucAC, uServiceInt )); return VOS_STATUS_E_FAULT; } @@ -10491,7 +10691,7 @@ WLANTL_DisableUAPSDForAC { TLLOGE(VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, "WLAN TL:Invalid input params on WLANTL_DisableUAPSDForAC" - " TL: %x STA: %d AC: %d", pTLCb, ucSTAId, ucAC )); + " TL: %p STA: %d AC: %d", pTLCb, ucSTAId, ucAC )); return VOS_STATUS_E_FAULT; } @@ -11259,7 +11459,7 @@ void WLANTL_PowerStateChangedCB if (NULL == tlCtxt) { VOS_TRACE( VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, - "Invalid TL Control Block", __func__ ); + "%s: Invalid TL Control Block", __func__ ); return; } @@ -11675,3 +11875,131 @@ void WLANTL_UpdateRssiBmps(v_PVOID_t pvosGCtx, v_U8_t staId, v_S7_t rssi) pTLCb->atlSTAClients[staId]->rssiAvgBmps = rssi; } } + +/*=============================================================================== + FUNCTION WLANTL_UpdateLinkCapacity + + DESCRIPTION This function updates the STA's Link Capacity in TL + + DEPENDENCIES None + + PARAMETERS + + pvosGCtx VOS context VOS Global context + staId Station ID Station ID + linkCapacity linkCapacity Link Capacity + + RETURN None + + SIDE EFFECTS none + ===============================================================================*/ + +void WLANTL_UpdateLinkCapacity(v_PVOID_t pvosGCtx, v_U8_t staId, v_U32_t linkCapacity) +{ + WLANTL_CbType* pTLCb = VOS_GET_TL_CB(pvosGCtx); + + if (NULL != pTLCb && NULL != pTLCb->atlSTAClients[staId]) + { + pTLCb->atlSTAClients[staId]->linkCapacity = linkCapacity; + } +} + + +/*=========================================================================== + + FUNCTION WLANTL_GetSTALinkCapacity + + DESCRIPTION + + Returns Link Capacity of a particular STA. + + DEPENDENCIES + + A station must have been registered before its state can be retrieved. + + + PARAMETERS + + IN + pvosGCtx: pointer to the global vos context; a handle to TL's + control block can be extracted from its context + ucSTAId: identifier of the station + + OUT + plinkCapacity: the current link capacity the connection to + the given station + + + RETURN VALUE + + The result code associated with performing the operation + + VOS_STATUS_E_INVAL: Input parameters are invalid + VOS_STATUS_E_FAULT: Station ID is outside array boundaries or pointer to + TL cb is NULL ; access would cause a page fault + VOS_STATUS_E_EXISTS: Station was not registered + VOS_STATUS_SUCCESS: Everything is good :) + + SIDE EFFECTS + +============================================================================*/ +VOS_STATUS +WLANTL_GetSTALinkCapacity +( + v_PVOID_t pvosGCtx, + v_U8_t ucSTAId, + v_U32_t *plinkCapacity +) +{ + WLANTL_CbType* pTLCb = NULL; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/ + + /*------------------------------------------------------------------------ + Sanity check + ------------------------------------------------------------------------*/ + if ( NULL == plinkCapacity ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + FL("WLAN TL:Invalid parameter"))); + return VOS_STATUS_E_INVAL; + } + + if ( WLANTL_STA_ID_INVALID( ucSTAId ) ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + FL("WLAN TL:Invalid station id"))); + return VOS_STATUS_E_FAULT; + } + + /*------------------------------------------------------------------------ + Extract TL control block and check existance + ------------------------------------------------------------------------*/ + pTLCb = VOS_GET_TL_CB(pvosGCtx); + if ( NULL == pTLCb ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + FL("WLAN TL:Invalid TL pointer from pvosGCtx"))); + return VOS_STATUS_E_FAULT; + } + + if ( NULL == pTLCb->atlSTAClients[ucSTAId] ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + FL("WLAN TL:Client Memory was not allocated"))); + return VOS_STATUS_E_FAILURE; + } + + if ( 0 == pTLCb->atlSTAClients[ucSTAId]->ucExists ) + { + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_WARN, + FL("WLAN TL:Station was not previously registered"))); + return VOS_STATUS_E_EXISTS; + } + + /*------------------------------------------------------------------------ + Get STA state + ------------------------------------------------------------------------*/ + *plinkCapacity = pTLCb->atlSTAClients[ucSTAId]->linkCapacity; + + return VOS_STATUS_SUCCESS; +}/* WLANTL_GetSTALinkCapacity */ diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c index 7fa9d2f9720..25579713242 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_ba.c @@ -749,7 +749,7 @@ WLANTL_BaSessionDel vosStatus = vos_timer_stop(&reOrderInfo->agingTimer); if(!VOS_IS_STATUS_SUCCESS(vosStatus)) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer stop fail", vosStatus)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer stop fail: %d", vosStatus)); return vosStatus; } } @@ -1485,10 +1485,10 @@ VOS_STATUS WLANTL_MSDUReorder * Route all the Qed frames upper layer * Otherwise, RX thread could be stall */ vos_pkt_get_available_buffer_pool(VOS_PKT_TYPE_RX_RAW, &rxFree); - if(WLANTL_BA_MIN_FREE_RX_VOS_BUFFER > rxFree) + if(WLANTL_BA_MIN_FREE_RX_VOS_BUFFER >= rxFree) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"RX Free", rxFree)); - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"RX free buffer count is too low, Pending frame count is %d", + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "RX Free: %d", rxFree)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, "RX free buffer count is too low, Pending frame count is %d", currentReorderInfo->pendingFramesCount)); vosPktIdx = NULL; status = WLANTL_ChainFrontPkts(ucFwdIdx, @@ -1554,7 +1554,7 @@ VOS_STATUS WLANTL_MSDUReorder WLANTL_BA_REORDERING_AGING_TIMER); if(!VOS_IS_STATUS_SUCCESS(timerStatus)) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer start fail", timerStatus)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Timer start fail: %d", timerStatus)); lockStatus = vos_lock_release(¤tReorderInfo->reorderLock); if(!VOS_IS_STATUS_SUCCESS(lockStatus)) { diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_hosupport.c b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_hosupport.c index d6be98ab41c..22baa2dc327 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_hosupport.c +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tl_hosupport.c @@ -941,6 +941,8 @@ VOS_STATUS WLANTL_HSBMPSRSSIRegionChangedNotification return VOS_STATUS_E_INVAL; } + THSGETLOCK("WLANTL_HSBMPSRSSIRegionChangedNotification", + &tlCtxt->hoSupport.hosLock); currentHO = &(tlCtxt->hoSupport.currentHOState); hoSupport = &(tlCtxt->hoSupport); preFWNotification = currentHO->fwNotification; @@ -968,6 +970,8 @@ VOS_STATUS WLANTL_HSBMPSRSSIRegionChangedNotification } else if(preFWNotification == curFWNotification) { + THSRELEASELOCK("WLANTL_HSBMPSRSSIRegionChangedNotification", + &tlCtxt->hoSupport.hosLock); return status; } @@ -1003,12 +1007,13 @@ VOS_STATUS WLANTL_HSBMPSRSSIRegionChangedNotification nRegionNumber = 1; } - newRegionNumber = (nRegionNumber > pRegionNumber) ? nRegionNumber : pRegionNumber; if((currentHO->regionNumber) && (newRegionNumber == currentHO->regionNumber)) { TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"No Region Change with BMPS mode")); preFWNotification = curFWNotification; + THSRELEASELOCK("WLANTL_HSBMPSRSSIRegionChangedNotification", + &tlCtxt->hoSupport.hosLock); return status; } else if(newRegionNumber > currentHO->regionNumber) @@ -1066,6 +1071,8 @@ VOS_STATUS WLANTL_HSBMPSRSSIRegionChangedNotification TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"BMPS State, MSG from FW, Trigger Event %d, region index %d", evtType, currentHO->regionNumber)); + THSRELEASELOCK("WLANTL_HSBMPSRSSIRegionChangedNotification", + &tlCtxt->hoSupport.hosLock); return VOS_STATUS_SUCCESS; } @@ -1229,6 +1236,7 @@ VOS_STATUS WLANTL_HSHandleRXFrame return VOS_STATUS_E_INVAL; } + THSGETLOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); WLANTL_StatHandleRXFrame(pAdapter, pBDHeader, STAid, isBroadcast, dataBuffer); /* If this frame is not management frame increase frame count */ @@ -1258,12 +1266,14 @@ VOS_STATUS WLANTL_HSHandleRXFrame { WLANTL_HSGetRSSI(pAdapter, pBDHeader, STAid, ¤tAvgRSSI); currentHO->historyRSSI = currentAvgRSSI; + THSRELEASELOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); return status; } currentTimestamp = WDA_GET_RX_TIMESTAMP(pBDHeader); if((currentTimestamp - currentHO->sampleTime) < WLANTL_HO_SAMPLING_PERIOD) { + THSRELEASELOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); return status; } currentHO->sampleTime = currentTimestamp; @@ -1273,6 +1283,7 @@ VOS_STATUS WLANTL_HSHandleRXFrame if(!VOS_IS_STATUS_SUCCESS(status)) { TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Get RSSI Fail")); + THSRELEASELOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); return status; } #ifdef WLAN_ACTIVEMODE_OFFLOAD_FEATURE @@ -1291,11 +1302,14 @@ VOS_STATUS WLANTL_HSHandleRXFrame if(!VOS_IS_STATUS_SUCCESS(status)) { TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Handle new RSSI fail")); + THSRELEASELOCK("WLANTL_HSHandleRXFrame", + &tlCtxt->hoSupport.hosLock); return status; } } } + THSRELEASELOCK("WLANTL_HSHandleRXFrame", &tlCtxt->hoSupport.hosLock); return status; } @@ -1425,12 +1439,12 @@ VOS_STATUS WLANTL_HSRegRSSIIndicationCB { for(sIdx = 0; sIdx < WLANTL_HS_NUM_CLIENT; sIdx++) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Reg CB P 0x%x, registered CB P 0x%x", + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Reg CB P %p, registered CB P %p", crossCBFunction, hoSupport->registeredInd[idx].crossCBFunction[sIdx])); if(crossCBFunction == hoSupport->registeredInd[idx].crossCBFunction[sIdx]) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Same RSSI %d, Same CB 0x%x already registered", + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Same RSSI %d, Same CB %p already registered", rssiValue, crossCBFunction)); WLANTL_HSDebugDisplay(pAdapter); THSRELEASELOCK("WLANTL_HSRegRSSIIndicationCB", &tlCtxt->hoSupport.hosLock); @@ -1693,23 +1707,26 @@ VOS_STATUS WLANTL_HSDeregRSSIIndicationCB tlCtxt->hoSupport.registeredInd[currentHO->numThreshold - 1].numClient = 0; } - if((VOS_FALSE == tlCtxt->isBMPS) && (rssiValue >= currentHO->historyRSSI)) + if( ((VOS_FALSE == tlCtxt->isBMPS) && (rssiValue >= currentHO->historyRSSI)) + || ((VOS_TRUE == tlCtxt->isBMPS) && (VOS_TRUE == bmpsAbove)) ) { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Removed Threshold above current RSSI level, old RN %d", currentHO->regionNumber)); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "Removed Threshold above current RSSI level, old RN %d", + currentHO->regionNumber)); if(0 < currentHO->regionNumber) { currentHO->regionNumber--; } else { - TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR,"Current Region number is 0, cannot decrease anymore")); + TLLOGE(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_ERROR, + "Current Region number is 0, cannot decrease anymore")); } - TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO,"Decrease region number without notification %d", currentHO->regionNumber)); - } - else if((VOS_TRUE == tlCtxt->isBMPS) && (VOS_TRUE == bmpsAbove)) - { - currentHO->regionNumber--; + TLLOG1(VOS_TRACE(VOS_MODULE_ID_TL, VOS_TRACE_LEVEL_INFO, + "Decrease region number without notification %d", + currentHO->regionNumber)); } + /* Decrease number of thresholds */ tlCtxt->hoSupport.currentHOState.numThreshold--; /*Reset the FW notification*/ diff --git a/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h b/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h index a8fa010d1dc..2c7d9eaf59d 100644 --- a/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h +++ b/drivers/staging/prima/CORE/TL/src/wlan_qct_tli.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + #ifndef WLAN_QCT_TLI_H #define WLAN_QCT_TLI_H @@ -52,8 +53,6 @@ DESCRIPTION This file contains the internal declarations used within wlan transport layer module. - Copyright (c) 2008 QUALCOMM Incorporated. All Rights Reserved. - Qualcomm Confidential and Proprietary ===========================================================================*/ @@ -111,7 +110,6 @@ when who what, where, why #define STATIC static - /*---------------------------------------------------------------------------- * Preprocessor Definitions and Constants * -------------------------------------------------------------------------*/ @@ -278,6 +276,9 @@ typedef enum /* Serialzie Finish UL Authentication request */ WLANTL_FINISH_ULA = 5, + /* Serialized Snapshot request indication */ + WLANTL_TX_SNAPSHOT = 6, + WLANTL_TX_MAX }WLANTL_TxSignalsType; @@ -636,6 +637,8 @@ typedef struct 1 then we have to encrypt the data irrespective of TL state (CONNECTED/AUTHENTICATED) */ v_U8_t ptkInstalled; + + v_U32_t linkCapacity; }WLANTL_STAClientType; /*--------------------------------------------------------------------------- diff --git a/drivers/staging/prima/CORE/VOSS/inc/i_vos_packet.h b/drivers/staging/prima/CORE/VOSS/inc/i_vos_packet.h index 105c4e7b8bb..58ef385f129 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/i_vos_packet.h +++ b/drivers/staging/prima/CORE/VOSS/inc/i_vos_packet.h @@ -198,6 +198,10 @@ typedef struct vos_pkt_context_s //Add the field for a faster rx path v_SIZE_t rxRawFreeListCount; + // Number of RX Raw packets that will be reserved; this is a configurable + // value to the driver to save the memory usage. + v_SIZE_t numOfRxRawPackets; + // These are the structs to keep low-resource callback information. // There are separate low-resource callback information blocks for // RX_RAW, TX_DATA, and TX_MGMT. diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h b/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h index 89acfdd6e2c..c57912cc9bb 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_packet.h @@ -1115,4 +1115,20 @@ VOS_STATUS vos_pkt_get_available_buffer_pool v_SIZE_t *vosFreeBuffer ); +/** + @brief vos_pkt_get_num_of_rx_raw_pkts() - Get the number of RX packets + that should be allocated. + + This function is called by VOS packet module to know how many RX raw + packets it should allocate/reserve. This value can be configured thru + Kernel device tree to save memory usage. + + @param + NONE + @return + v_SIZE_t the number of packets to allocate + +*/ +v_SIZE_t vos_pkt_get_num_of_rx_raw_pkts(void); + #endif // !defined( __VOS_PKT_H ) diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h b/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h index f65502fe820..5703b5dd1b8 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_trace.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + #if !defined( __VOS_TRACE_H ) #define __VOS_TRACE_H @@ -50,10 +51,6 @@ Trace, logging, and debugging definitions and APIs - Copyright 2008 (c) Qualcomm, Incorporated. All Rights Reserved. - - Qualcomm Confidential and Proprietary. - ========================================================================*/ /* $Header$ */ @@ -105,6 +102,7 @@ typedef enum // below definition is obsolete and is no longer being used in BMP and WM // TODO: remove this once this is not used on Android #define VOS_ENABLE_TRACING +#define WCONN_TRACE_KMSG_LOG_BUFF #include @@ -153,4 +151,22 @@ void vos_trace_setLevel( VOS_MODULE_ID module, VOS_TRACE_LEVEL level ); --------------------------------------------------------------------------*/ v_BOOL_t vos_trace_getLevel( VOS_MODULE_ID module, VOS_TRACE_LEVEL level ); +#ifdef WCONN_TRACE_KMSG_LOG_BUFF +/*-------------------------------------------------------------------------- + \brief vos_wconn_trace_init(); - Initializing the spinlock, + Initialization would be called at the time of hdd_driver_init() + + \return - returns None + --------------------------------------------------------------------------*/ +void vos_wconn_trace_init(void); + +/*-------------------------------------------------------------------------- + \brief vos_wconn_trace_exit(); - De-Initializing the spinlock, + De-Initialization would be called at the time of hdd_driver_exit() + + \return - returns None + --------------------------------------------------------------------------*/ +void vos_wconn_trace_exit(void); +#endif + #endif diff --git a/drivers/staging/prima/CORE/VOSS/inc/vos_types.h b/drivers/staging/prima/CORE/VOSS/inc/vos_types.h index 58669cf98db..c2d5bb80b4c 100644 --- a/drivers/staging/prima/CORE/VOSS/inc/vos_types.h +++ b/drivers/staging/prima/CORE/VOSS/inc/vos_types.h @@ -168,6 +168,7 @@ typedef enum VOS_P2P_GO_MODE, VOS_MONITOR_MODE, VOS_FTM_MODE = 5, + VOS_P2P_DEVICE, VOS_MAX_NO_OF_MODE } tVOS_CON_MODE; diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_api.c b/drivers/staging/prima/CORE/VOSS/src/vos_api.c index 1106c4a0773..354dded7457 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_api.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_api.c @@ -1599,7 +1599,7 @@ VOS_STATUS vos_tx_mq_serialize( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) default: VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "Trying to queue msg into unknown Tx Msg queue ID %d", + "%s: Trying to queue msg into unknown Tx Msg queue ID %d", __func__, msgQueueId); return VOS_STATUS_E_FAILURE; @@ -1709,7 +1709,7 @@ VOS_STATUS vos_rx_mq_serialize( VOS_MQ_ID msgQueueId, vos_msg_t *pMsg ) default: VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "Trying to queue msg into unknown Rx Msg queue ID %d", + "%s: Trying to queue msg into unknown Rx Msg queue ID %d", __func__, msgQueueId); return VOS_STATUS_E_FAILURE; diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_nvitem.c b/drivers/staging/prima/CORE/VOSS/src/vos_nvitem.c index b192216c2fb..d002d714bfe 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_nvitem.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_nvitem.c @@ -119,7 +119,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'F'}}, //AFGHANISTAN { REGDOMAIN_WORLD, {'A', 'G'}}, //ANTIGUA AND BARBUDA { REGDOMAIN_FCC, {'A', 'I'}}, //ANGUILLA - { REGDOMAIN_NO_5GHZ, {'A', 'L'}}, //ALBANIA + { REGDOMAIN_ETSI, {'A', 'L'}}, //ALBANIA { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'M'}}, //ARMENIA { REGDOMAIN_ETSI, {'A', 'N'}}, //NETHERLANDS ANTILLES { REGDOMAIN_NO_5GHZ, {'A', 'O'}}, //ANGOLA @@ -127,13 +127,13 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_WORLD, {'A', 'R'}}, //ARGENTINA { REGDOMAIN_FCC, {'A', 'S'}}, //AMERICAN SOMOA { REGDOMAIN_ETSI, {'A', 'T'}}, //AUSTRIA - { REGDOMAIN_APAC, {'A', 'U'}}, //AUSTRALIA + { REGDOMAIN_WORLD, {'A', 'U'}}, //AUSTRALIA { REGDOMAIN_ETSI, {'A', 'W'}}, //ARUBA { REGDOMAIN_WORLD, {'A', 'X'}}, //ALAND ISLANDS { REGDOMAIN_N_AMER_EXC_FCC, {'A', 'Z'}}, //AZERBAIJAN { REGDOMAIN_ETSI, {'B', 'A'}}, //BOSNIA AND HERZEGOVINA { REGDOMAIN_APAC, {'B', 'B'}}, //BARBADOS - { REGDOMAIN_NO_5GHZ, {'B', 'D'}}, //BANGLADESH + { REGDOMAIN_HI_5GHZ, {'B', 'D'}}, //BANGLADESH { REGDOMAIN_ETSI, {'B', 'E'}}, //BELGIUM { REGDOMAIN_HI_5GHZ, {'B', 'F'}}, //BURKINA FASO { REGDOMAIN_ETSI, {'B', 'G'}}, //BULGARIA @@ -160,7 +160,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_WORLD, {'C', 'K'}}, //COOK ISLANDS { REGDOMAIN_APAC, {'C', 'L'}}, //CHILE { REGDOMAIN_NO_5GHZ, {'C', 'M'}}, //CAMEROON - { REGDOMAIN_HI_5GHZ, {'C', 'N'}}, //CHINA + { REGDOMAIN_APAC, {'C', 'N'}}, //CHINA { REGDOMAIN_APAC, {'C', 'O'}}, //COLOMBIA { REGDOMAIN_APAC, {'C', 'R'}}, //COSTA RICA { REGDOMAIN_NO_5GHZ, {'C', 'U'}}, //CUBA @@ -173,7 +173,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'D', 'K'}}, //DENMARK { REGDOMAIN_WORLD, {'D', 'M'}}, //DOMINICA { REGDOMAIN_APAC, {'D', 'O'}}, //DOMINICAN REPUBLIC - { REGDOMAIN_NO_5GHZ, {'D', 'Z'}}, //ALGERIA + { REGDOMAIN_ETSI, {'D', 'Z'}}, //ALGERIA { REGDOMAIN_APAC, {'E', 'C'}}, //ECUADOR { REGDOMAIN_ETSI, {'E', 'E'}}, //ESTONIA { REGDOMAIN_N_AMER_EXC_FCC, {'E', 'G'}}, //EGYPT @@ -204,7 +204,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'G', 'R'}}, //GREECE { REGDOMAIN_WORLD, {'G', 'S'}}, //SOUTH GEORGIA AND THE SOUTH SANDWICH ISLANDS { REGDOMAIN_APAC, {'G', 'T'}}, //GUATEMALA - { REGDOMAIN_APAC, {'G', 'U'}}, //GUAM + { REGDOMAIN_FCC, {'G', 'U'}}, //GUAM { REGDOMAIN_NO_5GHZ, {'G', 'W'}}, //GUINEA-BISSAU { REGDOMAIN_HI_5GHZ, {'G', 'Y'}}, //GUYANA { REGDOMAIN_WORLD, {'H', 'K'}}, //HONGKONG @@ -215,7 +215,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'H', 'U'}}, //HUNGARY { REGDOMAIN_HI_5GHZ, {'I', 'D'}}, //INDONESIA { REGDOMAIN_ETSI, {'I', 'E'}}, //IRELAND - { REGDOMAIN_NO_5GHZ, {'I', 'L'}}, //ISRAEL + { REGDOMAIN_N_AMER_EXC_FCC, {'I', 'L'}}, //ISRAEL { REGDOMAIN_WORLD, {'I', 'M'}}, //ISLE OF MAN { REGDOMAIN_APAC, {'I', 'N'}}, //INDIA { REGDOMAIN_WORLD, {'I', 'O'}}, //BRITISH INDIAN OCEAN TERRITORY @@ -230,13 +230,13 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_WORLD, {'J', '5'}}, //Japan alternate 5 { REGDOMAIN_WORLD, {'J', 'E'}}, //JERSEY { REGDOMAIN_WORLD, {'J', 'M'}}, //JAMAICA - { REGDOMAIN_WORLD, {'J', 'O'}}, //JORDAN + { REGDOMAIN_APAC, {'J', 'O'}}, //JORDAN { REGDOMAIN_WORLD, {'J', 'P'}}, //JAPAN { REGDOMAIN_KOREA, {'K', '1'}}, //Korea alternate 1 { REGDOMAIN_KOREA, {'K', '2'}}, //Korea alternate 2 { REGDOMAIN_KOREA, {'K', '3'}}, //Korea alternate 3 { REGDOMAIN_KOREA, {'K', '4'}}, //Korea alternate 4 - { REGDOMAIN_HI_5GHZ, {'K', 'E'}}, //KENYA + { REGDOMAIN_APAC, {'K', 'E'}}, //KENYA { REGDOMAIN_NO_5GHZ, {'K', 'G'}}, //KYRGYZSTAN { REGDOMAIN_ETSI, {'K', 'H'}}, //CAMBODIA { REGDOMAIN_WORLD, {'K', 'I'}}, //KIRIBATI @@ -246,9 +246,9 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_KOREA, {'K', 'R'}}, //KOREA, REPUBLIC OF { REGDOMAIN_N_AMER_EXC_FCC, {'K', 'W'}}, //KUWAIT { REGDOMAIN_FCC, {'K', 'Y'}}, //CAYMAN ISLANDS - { REGDOMAIN_NO_5GHZ, {'K', 'Z'}}, //KAZAKHSTAN + { REGDOMAIN_WORLD, {'K', 'Z'}}, //KAZAKHSTAN { REGDOMAIN_WORLD, {'L', 'A'}}, //LAO PEOPLE'S DEMOCRATIC REPUBLIC - { REGDOMAIN_HI_5GHZ, {'L', 'B'}}, //LEBANON + { REGDOMAIN_WORLD, {'L', 'B'}}, //LEBANON { REGDOMAIN_WORLD, {'L', 'C'}}, //SAINT LUCIA { REGDOMAIN_ETSI, {'L', 'I'}}, //LIECHTENSTEIN { REGDOMAIN_WORLD, {'L', 'K'}}, //SRI LANKA @@ -258,8 +258,8 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'L', 'U'}}, //LUXEMBOURG { REGDOMAIN_ETSI, {'L', 'V'}}, //LATVIA { REGDOMAIN_NO_5GHZ, {'L', 'Y'}}, //LIBYAN ARAB JAMAHIRIYA - { REGDOMAIN_NO_5GHZ, {'M', 'A'}}, //MOROCCO - { REGDOMAIN_N_AMER_EXC_FCC, {'M', 'C'}}, //MONACO + { REGDOMAIN_APAC, {'M', 'A'}}, //MOROCCO + { REGDOMAIN_ETSI, {'M', 'C'}}, //MONACO { REGDOMAIN_ETSI, {'M', 'D'}}, //MOLDOVA, REPUBLIC OF { REGDOMAIN_ETSI, {'M', 'E'}}, //MONTENEGRO { REGDOMAIN_NO_5GHZ, {'M', 'G'}}, //MADAGASCAR @@ -267,7 +267,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'M', 'K'}}, //MACEDONIA, THE FORMER YUGOSLAV REPUBLIC OF { REGDOMAIN_NO_5GHZ, {'M', 'L'}}, //MALI { REGDOMAIN_WORLD, {'M', 'M'}}, //MYANMAR - { REGDOMAIN_NO_5GHZ, {'M', 'N'}}, //MONGOLIA + { REGDOMAIN_WORLD, {'M', 'N'}}, //MONGOLIA { REGDOMAIN_APAC, {'M', 'O'}}, //MACAO { REGDOMAIN_FCC, {'M', 'P'}}, //NORTHERN MARIANA ISLANDS { REGDOMAIN_ETSI, {'M', 'Q'}}, //MARTINIQUE @@ -288,16 +288,16 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_WORLD, {'N', 'I'}}, //NICARAGUA { REGDOMAIN_ETSI, {'N', 'L'}}, //NETHERLANDS { REGDOMAIN_ETSI, {'N', 'O'}}, //NORWAY - { REGDOMAIN_HI_5GHZ, {'N', 'P'}}, //NEPAL + { REGDOMAIN_APAC, {'N', 'P'}}, //NEPAL { REGDOMAIN_NO_5GHZ, {'N', 'R'}}, //NAURU { REGDOMAIN_WORLD, {'N', 'U'}}, //NIUE { REGDOMAIN_APAC, {'N', 'Z'}}, //NEW ZEALAND - { REGDOMAIN_WORLD, {'O', 'M'}}, //OMAN + { REGDOMAIN_ETSI, {'O', 'M'}}, //OMAN { REGDOMAIN_APAC, {'P', 'A'}}, //PANAMA - { REGDOMAIN_HI_5GHZ, {'P', 'E'}}, //PERU + { REGDOMAIN_WORLD, {'P', 'E'}}, //PERU { REGDOMAIN_ETSI, {'P', 'F'}}, //FRENCH POLYNESIA - { REGDOMAIN_APAC, {'P', 'G'}}, //PAPUA NEW GUINEA - { REGDOMAIN_HI_5GHZ, {'P', 'H'}}, //PHILIPPINES + { REGDOMAIN_WORLD, {'P', 'G'}}, //PAPUA NEW GUINEA + { REGDOMAIN_WORLD, {'P', 'H'}}, //PHILIPPINES { REGDOMAIN_HI_5GHZ, {'P', 'K'}}, //PAKISTAN { REGDOMAIN_ETSI, {'P', 'L'}}, //POLAND { REGDOMAIN_WORLD, {'P', 'M'}}, //SAINT PIERRE AND MIQUELON @@ -311,9 +311,9 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'R', 'E'}}, //REUNION { REGDOMAIN_ETSI, {'R', 'O'}}, //ROMANIA { REGDOMAIN_ETSI, {'R', 'S'}}, //SERBIA - { REGDOMAIN_HI_5GHZ, {'R', 'U'}}, //RUSSIA - { REGDOMAIN_HI_5GHZ, {'R', 'W'}}, //RWANDA - { REGDOMAIN_APAC, {'S', 'A'}}, //SAUDI ARABIA + { REGDOMAIN_APAC, {'R', 'U'}}, //RUSSIA + { REGDOMAIN_WORLD, {'R', 'W'}}, //RWANDA + { REGDOMAIN_WORLD, {'S', 'A'}}, //SAUDI ARABIA { REGDOMAIN_NO_5GHZ, {'S', 'B'}}, //SOLOMON ISLANDS { REGDOMAIN_NO_5GHZ, {'S', 'C'}}, //SEYCHELLES { REGDOMAIN_WORLD, {'S', 'D'}}, //SUDAN @@ -343,22 +343,22 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_NO_5GHZ, {'T', 'M'}}, //TURKMENISTAN { REGDOMAIN_N_AMER_EXC_FCC, {'T', 'N'}}, //TUNISIA { REGDOMAIN_NO_5GHZ, {'T', 'O'}}, //TONGA - { REGDOMAIN_ETSI, {'T', 'R'}}, //TURKEY + { REGDOMAIN_ETSI, {'T', 'R'}}, //TURKEY { REGDOMAIN_WORLD, {'T', 'T'}}, //TRINIDAD AND TOBAGO { REGDOMAIN_NO_5GHZ, {'T', 'V'}}, //TUVALU { REGDOMAIN_JAPAN, {'T', 'W'}}, //TAIWAN, PROVINCE OF CHINA { REGDOMAIN_HI_5GHZ, {'T', 'Z'}}, //TANZANIA, UNITED REPUBLIC OF - { REGDOMAIN_NO_5GHZ, {'U', 'A'}}, //UKRAINE - { REGDOMAIN_WORLD, {'U', 'G'}}, //UGANDA + { REGDOMAIN_WORLD, {'U', 'A'}}, //UKRAINE + { REGDOMAIN_KOREA, {'U', 'G'}}, //UGANDA { REGDOMAIN_FCC, {'U', 'M'}}, //UNITED STATES MINOR OUTLYING ISLANDS { REGDOMAIN_WORLD, {'U', 'Y'}}, //URUGUAY - { REGDOMAIN_WORLD, {'U', 'Z'}}, //UZBEKISTAN + { REGDOMAIN_FCC, {'U', 'Z'}}, //UZBEKISTAN { REGDOMAIN_ETSI, {'V', 'A'}}, //HOLY SEE (VATICAN CITY STATE) { REGDOMAIN_WORLD, {'V', 'C'}}, //SAINT VINCENT AND THE GRENADINES { REGDOMAIN_HI_5GHZ, {'V', 'E'}}, //VENEZUELA { REGDOMAIN_ETSI, {'V', 'G'}}, //VIRGIN ISLANDS, BRITISH { REGDOMAIN_FCC, {'V', 'I'}}, //VIRGIN ISLANDS, US - { REGDOMAIN_WORLD, {'V', 'N'}}, //VIET NAM + { REGDOMAIN_FCC, {'V', 'N'}}, //VIET NAM { REGDOMAIN_NO_5GHZ, {'V', 'U'}}, //VANUATU { REGDOMAIN_WORLD, {'W', 'F'}}, //WALLIS AND FUTUNA { REGDOMAIN_N_AMER_EXC_FCC, {'W', 'S'}}, //SOMOA @@ -366,7 +366,7 @@ static CountryInfoTable_t countryInfoTable = { REGDOMAIN_ETSI, {'Y', 'T'}}, //MAYOTTE { REGDOMAIN_WORLD, {'Z', 'A'}}, //SOUTH AFRICA { REGDOMAIN_APAC, {'Z', 'M'}}, //ZAMBIA - { REGDOMAIN_NO_5GHZ, {'Z', 'W'}}, //ZIMBABWE + { REGDOMAIN_ETSI, {'Z', 'W'}}, //ZIMBABWE } }; typedef struct nvEFSTable_s @@ -1002,7 +1002,7 @@ VOS_STATUS vos_nv_readMultiMacAddress( v_U8_t *pMacAddress, (NULL == pMacAddress)) { VOS_TRACE( VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - " Invalid Parameter from NV Client macCount %d, pMacAddress 0x%x", + " Invalid Parameter from NV Client macCount %d, pMacAddress %p", macCount, pMacAddress); } @@ -1759,9 +1759,9 @@ VOS_STATUS vos_nv_getNVBuffer(v_VOID_t **pNvBuffer,v_SIZE_t *pSize) -------------------------------------------------------------------------*/ VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId) { - v_CONTEXT_t pVosContext = NULL; - hdd_context_t *pHddCtx = NULL; - struct wiphy *wiphy = NULL; + v_CONTEXT_t pVosContext = NULL; + hdd_context_t *pHddCtx = NULL; + struct wiphy *wiphy = NULL; /* Client Context Argumant not used for PRIMA */ if (regId >= REGDOMAIN_COUNT) { @@ -1781,8 +1781,8 @@ VOS_STATUS vos_nv_setRegDomain(void * clientCtxt, v_REGDOMAIN_t regId) /* when CRDA is not running then we are world roaming. In this case if 11d is enabled, then country code should be update on basis of world roaming */ - if (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode, - CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) == 0) + if ((NULL != pHddCtx) && (memcmp(pHddCtx->cfg_ini->crdaDefaultCountryCode, + CFG_CRDA_DEFAULT_COUNTRY_CODE_DEFAULT , 2) == 0)) { wiphy = pHddCtx->wiphy; regulatory_hint(wiphy, "00"); @@ -1866,6 +1866,68 @@ static int bw20_ch_index_to_bw40_ch_index(int k) return m; } +void crda_regulatory_entry_default(v_U8_t *countryCode, int domain_id) +{ + int k; + pr_info("Country %c%c domain_id %d\n enable ch 1 - 11.\n", + countryCode[0], countryCode[1], domain_id); + for (k = RF_CHAN_1; k <= RF_CHAN_11; k++) { + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled = + NV_CHANNEL_ENABLE; + /* Max Tx Power 20dBm */ + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 20; + } + /* enable ch 12 to ch 14 passive scan */ + pr_info(" enable ch 12 - 14 to scan passively by setting DFS flag.\n"); + for (k = RF_CHAN_12; k <= MAX_2_4GHZ_CHANNEL; k++) { + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled = + NV_CHANNEL_DFS; + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0; + } + pr_info(" enable 5GHz to scan passively by setting DFS flag.\n"); + for (k = MIN_5GHZ_CHANNEL; k <= MAX_5GHZ_CHANNEL; k++) { + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled = + NV_CHANNEL_DFS; + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0; + } +#ifdef PASSIVE_SCAN_4_9GHZ + pr_info(" enable 4.9 GHz to scan passively by setting DFS flag.\n"); + for (k = RF_CHAN_240; k <= RF_CHAN_216; k++) { + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].enabled = + NV_CHANNEL_DFS; + pnvEFSTable->halnv.tables.regDomains[domain_id].channels[k].pwrLimit = 0; + } +#endif + if (domain_id == NUM_REG_DOMAINS-1) + { /* init time */ + crda_alpha2[0] = countryCode[0]; + crda_alpha2[1] = countryCode[1]; + crda_regulatory_entry_valid = VOS_TRUE; + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[0] = countryCode[0]; + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[1] = countryCode[1]; + pnvEFSTable->halnv.tables.defaultCountryTable.countryCode[2] = 'I'; + pnvEFSTable->halnv.tables.defaultCountryTable.regDomain = NUM_REG_DOMAINS-1; + } + if (domain_id == NUM_REG_DOMAINS-2) + { /* none-default country */ + run_time_alpha2[0] = countryCode[0]; + run_time_alpha2[1] = countryCode[1]; + crda_regulatory_run_time_entry_valid = VOS_TRUE; + } +} + +static int crda_regulatory_entry_post_processing(struct wiphy *wiphy, + struct regulatory_request *request, + v_U8_t nBandCapability, + int domain_id) +{ + if (request->alpha2[0] == '0' && request->alpha2[1] == '0') { + pr_info("Country 00 special handling to enable passive scan.\n"); + crda_regulatory_entry_default(request->alpha2, domain_id); + } + return 0; +} + /* create_crda_regulatory_entry should be called from user command or 11d country IE */ static int create_crda_regulatory_entry(struct wiphy *wiphy, struct regulatory_request *request, @@ -1925,16 +1987,16 @@ static int create_crda_regulatory_entry(struct wiphy *wiphy, { pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].enabled = NV_CHANNEL_DFS; - // max_power is in mBm = 100 * d + // max_power is in mBm = 100 * dBm pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit = - (tANI_S8) (wiphy->bands[i]->channels[j].max_power); + (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100); if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0) { pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled = NV_CHANNEL_DFS; // 40MHz channel power is half of 20MHz (-3dB) ?? pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit = - (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)-3); + (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3); } } else // Enable is only last flag we support @@ -1943,14 +2005,14 @@ static int create_crda_regulatory_entry(struct wiphy *wiphy, NV_CHANNEL_ENABLE; // max_power is in dBm pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[k].pwrLimit = - (tANI_S8) (wiphy->bands[i]->channels[j].max_power); + (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)/100); if ((wiphy->bands[i]->channels[j].flags & IEEE80211_CHAN_NO_HT40) == 0) { pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].enabled = NV_CHANNEL_ENABLE; // 40MHz channel power is half of 20MHz (-3dB) ?? pnvEFSTable->halnv.tables.regDomains[NUM_REG_DOMAINS-2].channels[n].pwrLimit = - (tANI_S8) ((wiphy->bands[i]->channels[j].max_power)-3); + (tANI_S8) (((wiphy->bands[i]->channels[j].max_power)/100)-3); } } /* ignore CRDA max_antenna_gain typical is 3dBi, nv.bin antennaGain is @@ -1962,6 +2024,7 @@ static int create_crda_regulatory_entry(struct wiphy *wiphy, run_time_alpha2[0] = request->alpha2[0]; run_time_alpha2[1] = request->alpha2[1]; crda_regulatory_run_time_entry_valid = VOS_TRUE; + crda_regulatory_entry_post_processing(wiphy, request, nBandCapability, NUM_REG_DOMAINS-2); return 0; } v_BOOL_t is_crda_regulatory_entry_valid(void) @@ -2229,6 +2292,7 @@ static int create_crda_regulatory_entry_from_regd(struct wiphy *wiphy, run_time_alpha2[1] = request->alpha2[1]; crda_regulatory_run_time_entry_valid = VOS_TRUE; } + crda_regulatory_entry_post_processing(wiphy, request, nBandCapability, domain_id); return 0; } @@ -2246,8 +2310,8 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, v_REGDOMAIN_t domainIdCurrent; tANI_U8 ccode[WNI_CFG_COUNTRY_CODE_LEN]; tANI_U8 uBufLen = WNI_CFG_COUNTRY_CODE_LEN; - eCsrBand nBandCapability; - int i=0,j=0,k=0,m=0; + tANI_U8 nBandCapability; + int i,j,k,m; wiphy_dbg(wiphy, "info: cfg80211 reg_notifier callback for country" " %c%c\n", request->alpha2[0], request->alpha2[1]); if (request->initiator == NL80211_REGDOM_SET_BY_USER) @@ -2325,7 +2389,7 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, } else { - sme_GetFreqBand(pHddCtx->hHal, &nBandCapability); + nBandCapability = pHddCtx->cfg_ini->nBandCapability; for (i=0, m=0; ibands[i]) @@ -2343,21 +2407,7 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, } else { - if( wiphy->bands[i-1] == NULL) - { - m = 14; - } - else - { - if(eCSR_BAND_5G == nBandCapability) - { - m = wiphy->bands[i-1]->n_channels + 11; - } - else - { - m = wiphy->bands[i-1]->n_channels + m; - } - } + m = wiphy->bands[i-1]?wiphy->bands[i-1]->n_channels + m:m; } for (j=0; jbands[i]->n_channels; j++) @@ -2365,7 +2415,6 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, // k = (m + j) is internal current channel index for 20MHz channel // n is internal channel index for corresponding 40MHz channel k = m + j; - if (IEEE80211_BAND_2GHZ == i && eCSR_BAND_5G == nBandCapability) // 5G only { // Enable social channels for P2P @@ -2433,8 +2482,7 @@ int wlan_hdd_crda_reg_notifier(struct wiphy *wiphy, } } } - - if (request->initiator == NL80211_REGDOM_SET_BY_CORE || request->initiator == NL80211_REGDOM_SET_BY_DRIVER) + if (request->initiator == NL80211_REGDOM_SET_BY_CORE) { request->processed = 1; } diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_packet.c b/drivers/staging/prima/CORE/VOSS/src/vos_packet.c index 768754d127b..6d9436471d4 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_packet.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_packet.c @@ -63,6 +63,7 @@ #include #include #include +#include /*-------------------------------------------------------------------------- Preprocessor definitions and constants @@ -194,9 +195,9 @@ static void vos_pkti_replenish_raw_pool(void) mutex_lock(&gpVosPacketContext->mlock); - if ((gpVosPacketContext->rxReplenishListCount < VPKT_RX_REPLENISH_THRESHOLD) - && - (!list_empty(&gpVosPacketContext->rxRawFreeList))) + if ((gpVosPacketContext->rxReplenishListCount < + gpVosPacketContext->numOfRxRawPackets/4) && + (!list_empty(&gpVosPacketContext->rxRawFreeList))) { mutex_unlock(&gpVosPacketContext->mlock); return; @@ -398,8 +399,10 @@ VOS_STATUS vos_packet_open( v_VOID_t *pVosContext, pVosPacketContext->rxRawFreeListCount = 0; INIT_LIST_HEAD(pFreeList); + pVosPacketContext->numOfRxRawPackets = vos_pkt_get_num_of_rx_raw_pkts(); + // fill the rxRaw free list - for (idx = 0; idx < VPKT_NUM_RX_RAW_PACKETS; idx++) + for (idx = 0; idx < pVosPacketContext->numOfRxRawPackets; idx++) { pPkt = &pVosPacketContext->vosPktBuffers[freePacketIndex++]; vosStatus = vos_pkti_packet_init(pPkt, VOS_PKT_TYPE_RX_RAW); @@ -873,7 +876,7 @@ VOS_STATUS vos_pkt_wrap_data_packet( vos_pkt_t **ppPacket, if (unlikely(VOS_PKT_TYPE_TX_802_3_DATA != pktType)) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "VPKT [%d]: invalid pktType", __LINE__, pktType); + "VPKT [%d]: invalid pktType %d", __LINE__, pktType); return VOS_STATUS_E_INVAL; } @@ -2950,6 +2953,32 @@ VOS_STATUS vos_pkt_get_available_buffer_pool (VOS_PKT_TYPE pktType, return VOS_STATUS_SUCCESS; } +/** + @brief vos_pkt_get_num_of_rx_raw_pkts() - Get the number of RX packets + that should be allocated. + + This function is called by VOS packet module to know how many RX raw + packets it should allocate/reserve. This value can be configured thru + Kernel device tree to save memory usage. + + @param + NONE + @return + v_SIZE_t the number of packets to allocate + +*/ +v_SIZE_t vos_pkt_get_num_of_rx_raw_pkts(void) +{ +#ifdef HAVE_WCNSS_RX_BUFF_COUNT + v_SIZE_t buffCount; + + buffCount = wcnss_get_wlan_rx_buff_count(); + return (buffCount > VPKT_NUM_RX_RAW_PACKETS ? + VPKT_NUM_RX_RAW_PACKETS : buffCount); +#else + return VPKT_NUM_RX_RAW_PACKETS; +#endif +} #ifdef VOS_PACKET_UNIT_TEST #include "vos_packet_test.c" diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_sched.c b/drivers/staging/prima/CORE/VOSS/src/vos_sched.c index ded3bfceee7..32c8a0ba875 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_sched.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_sched.c @@ -626,7 +626,8 @@ VosMCThread "%s: MC Thread exiting!!!!", __func__); complete_and_exit(&pSchedContext->McShutdown, 0); } /* VosMCThread() */ -int isWDresetInProgress(void) + +v_BOOL_t isWDresetInProgress(void) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_INFO, "%s: Reset is in Progress...",__func__); @@ -636,7 +637,7 @@ int isWDresetInProgress(void) } else { - return 0; + return FALSE; } } /*--------------------------------------------------------------------------- @@ -1121,7 +1122,7 @@ static int VosRXThread ( void * Arg ) /* Rx Thread Suspended */ complete(&pHddCtx->rx_sus_event_var); - init_completion(&pSchedContext->ResumeRxEvent); + INIT_COMPLETION(pSchedContext->ResumeRxEvent); spin_unlock(&pSchedContext->RxThreadLock); /* Wait for Resume Indication */ diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_sched.h b/drivers/staging/prima/CORE/VOSS/src/vos_sched.h index 8426b2a3fb4..9bac9d4226e 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_sched.h +++ b/drivers/staging/prima/CORE/VOSS/src/vos_sched.h @@ -504,5 +504,6 @@ void clearWlanResetReason(void); void vos_timer_module_init( void ); VOS_STATUS vos_watchdog_wlan_shutdown(void); VOS_STATUS vos_watchdog_wlan_re_init(void); +v_BOOL_t isWDresetInProgress(void); #endif // #if !defined __VOSS_SCHED_H diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_timer.c b/drivers/staging/prima/CORE/VOSS/src/vos_timer.c index d28b6fc2d82..112f07b1bf2 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_timer.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_timer.c @@ -723,9 +723,12 @@ VOS_STATUS vos_timer_start( vos_timer_t *timer, v_U32_t expirationTime ) // Check if timer refers to an uninitialized object if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) { - VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: Cannot start uninitialized timer",__func__); - VOS_ASSERT(0); + VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, + "%s: Cannot start uninitialized timer",__func__); + if ( LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie ) + { + VOS_ASSERT(0); + } return VOS_STATUS_E_INVAL; } @@ -820,8 +823,11 @@ VOS_STATUS vos_timer_stop ( vos_timer_t *timer ) if ( LINUX_TIMER_COOKIE != timer->platformInfo.cookie ) { VOS_TRACE(VOS_MODULE_ID_VOSS, VOS_TRACE_LEVEL_ERROR, - "%s: Cannot stop uninitialized timer",__func__); - VOS_ASSERT(0); + "%s: Cannot stop uninitialized timer",__func__); + if ( LINUX_INVALID_TIMER_COOKIE != timer->platformInfo.cookie ) + { + VOS_ASSERT(0); + } return VOS_STATUS_E_INVAL; } diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_trace.c b/drivers/staging/prima/CORE/VOSS/src/vos_trace.c index 13ffded7a88..29604de6de9 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_trace.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_trace.c @@ -219,6 +219,72 @@ void vos_snprintf(char *strBuffer, unsigned int size, char *strFormat, ...) va_end( val ); } +#ifdef WCONN_TRACE_KMSG_LOG_BUFF + +/* 64k:: size should be power of 2 to + get serial 'wconnstrContBuffIdx' index */ +#define KMSG_WCONN_TRACE_LOG_MAX 65536 + +static char wconnStrLogBuff[KMSG_WCONN_TRACE_LOG_MAX]; +static unsigned int wconnstrContBuffIdx; +static void kmsgwconnstrlogchar(char c) +{ + wconnStrLogBuff[wconnstrContBuffIdx & (KMSG_WCONN_TRACE_LOG_MAX-1)] = c; + wconnstrContBuffIdx++; +} + +/****************************************************************************** + * function:: kmsgwconnBuffWrite() + * wconnlogstrRead -> Recieved the string(log msg) from vos_trace_msg() + * 1) Get the timetick, convert into HEX and store in wconnStrLogBuff[] + * 2) And 'pwconnlogstr' would be copied into wconnStrLogBuff[] character by + character + * 3) wconnStrLogBuff[] is been treated as circular buffer. + * + * Note:: In T32 simulator the content of wconnStrLogBuff[] will appear as + continuous string please use logparse.cmm file to extract into + readable format + *******************************************************************************/ + +void kmsgwconnBuffWrite(const char *wconnlogstrRead) +{ + const char *pwconnlogstr = wconnlogstrRead; + static const char num[16] = {'0','1','2','3','4','5','6','7','8','9','A', + 'B','C','D','E','F'}; + unsigned int timetick; + int bits; /*timetick for now returns 32 bit number*/ + + timetick = ( jiffies_to_msecs(jiffies) / 10 ); + bits = sizeof(timetick) * 8/*number of bits in a byte*/; + + kmsgwconnstrlogchar('['); + + for ( ; bits > 0; bits -= 4 ) + kmsgwconnstrlogchar( num[((timetick & (0xF << (bits-4)))>>(bits-4))] ); + + kmsgwconnstrlogchar(']'); + + for ( ; *pwconnlogstr; pwconnlogstr++) + { + kmsgwconnstrlogchar(*pwconnlogstr); + } + kmsgwconnstrlogchar('\n');/*log \n*/ +} + +spinlock_t gVosSpinLock; + +void vos_wconn_trace_init(void) +{ + spin_lock_init(&gVosSpinLock); +} + +void vos_wconn_trace_exit(void) +{ + /* does nothing */ +} + +#endif + #ifdef VOS_ENABLE_TRACING /*---------------------------------------------------------------------------- @@ -248,6 +314,7 @@ void vos_trace_msg( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, char *strFormat { char strBuffer[VOS_TRACE_BUFFER_SIZE]; int n; + unsigned long irq_flag; // Print the trace message when the desired level bit is set in the module // tracel level mask. @@ -269,12 +336,18 @@ void vos_trace_msg( VOS_MODULE_ID module, VOS_TRACE_LEVEL level, char *strFormat (char *) gVosTraceInfo[ module ].moduleNameStr ); // print the formatted log message after the prefix string. - if (n < VOS_TRACE_BUFFER_SIZE) + if ((n >= 0) && (n < VOS_TRACE_BUFFER_SIZE)) { vsnprintf(strBuffer + n, VOS_TRACE_BUFFER_SIZE - n, strFormat, val ); + +#ifdef WCONN_TRACE_KMSG_LOG_BUFF + spin_lock_irqsave (&gVosSpinLock, irq_flag); + kmsgwconnBuffWrite(strBuffer); + spin_unlock_irqrestore (&gVosSpinLock, irq_flag); +#endif pr_err("%s\n", strBuffer); } - va_end( val); + va_end(val); } } diff --git a/drivers/staging/prima/CORE/VOSS/src/vos_utils.c b/drivers/staging/prima/CORE/VOSS/src/vos_utils.c index 958b2cc1efe..27d5f874dd0 100644 --- a/drivers/staging/prima/CORE/VOSS/src/vos_utils.c +++ b/drivers/staging/prima/CORE/VOSS/src/vos_utils.c @@ -38,9 +38,6 @@ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. */ - -/* - * */ /*============================================================================ FILE: vos_utils.c @@ -303,7 +300,7 @@ int hmac_sha1(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, ahash_request_set_crypt(req, &sg, hash_result, psize); ret = wcnss_wlan_crypto_ahash_digest(req); - VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x"); + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret); switch (ret) { case 0: @@ -406,7 +403,7 @@ int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, struct crypto_ahash *tfm; struct scatterlist sg; struct ahash_request *req; - struct hmac_md5_result tresult; + struct hmac_md5_result tresult = {.err = 0}; void *hash_buff = NULL; unsigned char hash_result[64]; @@ -458,7 +455,7 @@ int hmac_md5(v_U8_t *key, v_U8_t ksize, char *plaintext, v_U8_t psize, ahash_request_set_crypt(req, &sg, hash_result, psize); ret = wcnss_wlan_crypto_ahash_digest(req); - VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x"); + VOS_TRACE(VOS_MODULE_ID_VOSS,VOS_TRACE_LEVEL_ERROR, "ret 0x%x", ret); switch (ret) { case 0: diff --git a/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h b/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h index 98a8bbdda6f..c8575ff05b8 100644 --- a/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h +++ b/drivers/staging/prima/CORE/WDA/inc/legacy/halMsgApi.h @@ -1296,7 +1296,7 @@ typedef struct sMaxTxPowerParams typedef struct sAddStaSelfParams { tSirMacAddr selfMacAddr; - + tVOS_CON_MODE currDeviceMode; tANI_U32 status; }tAddStaSelfParams, *tpAddStaSelfParams; diff --git a/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h b/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h index f3ca8abe211..2e729565559 100644 --- a/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h +++ b/drivers/staging/prima/CORE/WDA/inc/legacy/halTypes.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + /** ------------------------------------------------------------------------- * ------------------------------------------------------------------------- * @@ -230,7 +231,8 @@ typedef enum eHAL_STATUS_SET_CHAN_ALREADY_ON_REQUESTED_CHAN, #ifdef WLAN_FEATURE_VOWIFI_11R - eHAL_STATUS_FT_PREAUTH_KEY_WAIT, + eHAL_STATUS_FT_PREAUTH_KEY_SUCCESS, + eHAL_STATUS_FT_PREAUTH_KEY_FAILED, #endif // not a real status. Just a way to mark the maximum in the enum. diff --git a/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h b/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h index 658a0aaa22a..2eb8c743941 100644 --- a/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h +++ b/drivers/staging/prima/CORE/WDA/inc/wlan_qct_wda.h @@ -118,6 +118,30 @@ typedef enum WDA_INVALID_STA_INDEX, WDA_VALID_STA_INDEX }WDA_ValidStaIndex; +typedef enum +{ + eWDA_AUTH_TYPE_NONE, //never used + // MAC layer authentication types + eWDA_AUTH_TYPE_OPEN_SYSTEM, + // Upper layer authentication types + eWDA_AUTH_TYPE_WPA, + eWDA_AUTH_TYPE_WPA_PSK, + + eWDA_AUTH_TYPE_RSN, + eWDA_AUTH_TYPE_RSN_PSK, + eWDA_AUTH_TYPE_FT_RSN, + eWDA_AUTH_TYPE_FT_RSN_PSK, + eWDA_AUTH_TYPE_WAPI_WAI_CERTIFICATE, + eWDA_AUTH_TYPE_WAPI_WAI_PSK, + eWDA_AUTH_TYPE_CCKM_WPA, + eWDA_AUTH_TYPE_CCKM_RSN, + eWDA_AUTH_TYPE_WPA_NONE, + eWDA_AUTH_TYPE_AUTOSWITCH, + eWDA_AUTH_TYPE_SHARED_KEY, + eWDA_NUM_OF_SUPPORT_AUTH_TYPE, + eWDA_AUTH_TYPE_FAILED = 0xff, + eWDA_AUTH_TYPE_UNKNOWN = eCSR_AUTH_TYPE_FAILED, +}WDA_AuthType; /*-------------------------------------------------------------------------- Utilities @@ -137,6 +161,11 @@ typedef enum #define IS_ACTIVEMODE_OFFLOAD_FEATURE_ENABLE 0 #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE ((WDI_getHostWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD)) & (WDA_getFwWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD))) +#else +#define IS_ROAM_SCAN_OFFLOAD_FEATURE_ENABLE 0 +#endif /*-------------------------------------------------------------------------- Definitions for Data path APIs @@ -499,7 +528,6 @@ tBssSystemRole wdaGetGlobalSystemRole(tpAniSirGlobal pMac); // FIXME Temporary value for R33D integaration //#define WDA_TL_TX_FRAME_TIMEOUT 20000 /* in msec a very high upper limit */ -#define DPU_FEEDBACK_UNPROTECTED_ERROR 0x0F /* --------------------------------------------------------------------------- @@ -641,7 +669,12 @@ tBssSystemRole wdaGetGlobalSystemRole(tpAniSirGlobal pMac); /* WDA_IS_RX_IN_SCAN *********************************************************/ # define WDA_IS_RX_IN_SCAN(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->scan) - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* WDA_GET_OFFLOADSCANLEARN **************************************************/ +# define WDA_GET_OFFLOADSCANLEARN(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->offloadScanLearn) +/* WDA_GET_ROAMCANDIDATEIND **************************************************/ +# define WDA_GET_ROAMCANDIDATEIND(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->roamCandidateInd) +#endif /* WDA_GET_RX_RSSI_DB ********************************************************/ // Volans RF # define WDA_RSSI_OFFSET 100 @@ -696,10 +729,7 @@ tBssSystemRole wdaGetGlobalSystemRole(tpAniSirGlobal pMac); /* WDA_GETRSSI1 ***************************************************************/ # define WDA_GETRSSI1(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->rssi1) -/* WDA_GET_RX_RMF *****************************************************/ -#ifdef WLAN_FEATURE_11W -# define WDA_GET_RX_RMF(pRxMeta) (((WDI_DS_RxMetaInfoType*)(pRxMeta))->rmf) -#endif + /* --------------------------------------------------------------------*/ @@ -890,9 +920,6 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_TIMER_ADC_RSSI_STATS SIR_HAL_TIMER_ADC_RSSI_STATS #define WDA_TIMER_TRAFFIC_STATS_IND SIR_HAL_TRAFFIC_STATS_IND -#ifdef WLAN_FEATURE_11W -#define WDA_EXCLUDE_UNENCRYPTED_IND SIR_HAL_EXCLUDE_UNENCRYPTED_IND -#endif #ifdef FEATURE_WLAN_CCX #define WDA_TSM_STATS_REQ SIR_HAL_TSM_STATS_REQ @@ -1001,6 +1028,10 @@ tSirRetStatus uMacPostCtrlMsg(void* pSirGlobal, tSirMbMsg* pMb); #define WDA_SET_PNO_CHANGED_IND SIR_HAL_SET_PNO_CHANGED_IND #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define WDA_ROAM_SCAN_OFFLOAD_REQ SIR_HAL_ROAM_SCAN_OFFLOAD_REQ +#endif + #ifdef WLAN_WAKEUP_EVENTS #define WDA_WAKE_REASON_IND SIR_HAL_WAKE_REASON_IND #endif // WLAN_WAKEUP_EVENTS @@ -1081,6 +1112,9 @@ v_BOOL_t WDA_IsHwFrameTxTranslationCapable(v_PVOID_t pVosGCtx, #define WDA_UpdateRssiBmps(pvosGCtx, staId, rssi) \ WLANTL_UpdateRssiBmps(pvosGCtx, staId, rssi) +#define WDA_UpdateLinkCapacity(pvosGCtx, staId, linkCapacity) \ + WLANTL_UpdateLinkCapacity(pvosGCtx, staId, linkCapacity) + #ifdef WLAN_PERF /*========================================================================== FUNCTION WDA_TLI_FastHwFwdDataFrame @@ -1801,4 +1835,19 @@ void WDA_TransportChannelDebug ===========================================================================*/ void WDA_TrafficStatsTimerActivate(wpt_boolean activate); +/*========================================================================== + FUNCTION WDA_SetEnableSSR + + DESCRIPTION + API to enable/disable SSR on WDI timeout + + PARAMETERS + enableSSR : enable/disable SSR + + RETURN VALUE + NONE + +===========================================================================*/ +void WDA_SetEnableSSR(v_BOOL_t enableSSR); + #endif diff --git a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c index ef5953ac0d3..f26d559cf84 100644 --- a/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c +++ b/drivers/staging/prima/CORE/WDA/src/wlan_qct_wda.c @@ -180,6 +180,12 @@ static VOS_STATUS WDA_ProcessSetPrefNetworkReq(tWDA_CbContext *pWDA, tSirPNOScan static VOS_STATUS WDA_ProcessSetRssiFilterReq(tWDA_CbContext *pWDA, tSirSetRSSIFilterReq* pRssiFilterParams); static VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, tSirUpdateScanParams *pUpdateScanParams); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +VOS_STATUS WDA_ProcessRoamScanOffloadReq(tWDA_CbContext *pWDA,tSirRoamOffloadScanReq *pRoamOffloadScanReqParams); +void WDA_RoamOffloadScanReqCallback(WDI_Status status, void* pUserData); +void WDA_ConvertSirAuthToWDIAuth(WDI_AuthType *AuthType, v_U8_t csrAuthType); +void WDA_ConvertSirEncToWDIEnc(WDI_EdType *EncrType, v_U8_t csrEncrType); +#endif #ifdef WLAN_FEATURE_PACKET_FILTERING static VOS_STATUS WDA_Process8023MulticastListReq ( tWDA_CbContext *pWDA, @@ -1471,6 +1477,38 @@ VOS_STATUS WDA_prepareConfigTLV(v_PVOID_t pVosContext, tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + sizeof(tHalCfg) + tlvStruct->length) ; + /* QWLAN_HAL_CFG_RA_FILTER_ENABLE */ + tlvStruct->type = QWLAN_HAL_CFG_RA_FILTER_ENABLE ; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + + if (wlan_cfgGetInt(pMac, WNI_CFG_RA_FILTER_ENABLE, + configDataValue ) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_RA_FILTER_ENABLE"); + goto handle_failure; + } + + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length) ; + + /* QWLAN_HAL_CFG_RA_RATE_LIMIT_INTERVAL */ + tlvStruct->type = QWLAN_HAL_CFG_RA_RATE_LIMIT_INTERVAL ; + tlvStruct->length = sizeof(tANI_U32); + configDataValue = (tANI_U32 *)(tlvStruct + 1); + + if (wlan_cfgGetInt(pMac, WNI_CFG_RA_RATE_LIMIT_INTERVAL, + configDataValue ) != eSIR_SUCCESS) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failed to get value for WNI_CFG_RA_RATE_LIMIT_INTERVAL"); + goto handle_failure; + } + + tlvStruct = (tHalCfg *)( (tANI_U8 *) tlvStruct + + sizeof(tHalCfg) + tlvStruct->length) ; + wdiStartParams->usConfigBufferLen = (tANI_U8 *)tlvStruct - tlvStructStart ; #ifdef WLAN_DEBUG { @@ -1868,8 +1906,8 @@ VOS_STATUS WDA_WniCfgDnld(tWDA_CbContext *pWDA) v_SIZE_t cbFileImageSize = 0; v_VOID_t *pCfgBinary = NULL; v_SIZE_t cbCfgBinarySize = 0; - v_BOOL_t bStatus = VOS_FALSE; + if (NULL == pMac ) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -1926,16 +1964,12 @@ VOS_STATUS WDA_WniCfgDnld(tWDA_CbContext *pWDA) * for now calling the existing cfg download API */ processCfgDownloadReq(pMac,cbCfgBinarySize,pCfgBinary); - if( pFileImage != NULL ) - { - vos_mem_free( pFileImage ); - } - return vosStatus; + vosStatus = VOS_STATUS_SUCCESS; + + /* fall through to clean up and return success */ fail: - if(pCfgBinary != NULL) - vos_mem_free( pFileImage ); - + vos_mem_free( pFileImage ); return vosStatus; } /* ----------------------------------------------------------------- @@ -1995,7 +2029,6 @@ VOS_STATUS WDA_SuspendDataTx(tWDA_CbContext *pWDA) { VOS_STATUS status = VOS_STATUS_E_FAILURE; tANI_U8 eventIdx = 0; - tANI_U8 ucSTAId = 0; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "%s: Entered " ,__func__); @@ -2015,8 +2048,7 @@ VOS_STATUS WDA_SuspendDataTx(tWDA_CbContext *pWDA) return VOS_STATUS_E_FAILURE; } /*Indicate TL to suspend transmission for all Sta Id */ - ucSTAId = WLAN_ALL_STA; - status = WLANTL_SuspendDataTx(pWDA->pVosContext, &ucSTAId, + status = WLANTL_SuspendDataTx(pWDA->pVosContext, NULL, WDA_SuspendDataTxCallback); if(status != VOS_STATUS_SUCCESS) { @@ -2054,12 +2086,11 @@ VOS_STATUS WDA_SuspendDataTx(tWDA_CbContext *pWDA) VOS_STATUS WDA_ResumeDataTx(tWDA_CbContext *pWDA) { VOS_STATUS status = VOS_STATUS_SUCCESS; - tANI_U8 ucSTAId = 0; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "%s: Entered " ,__func__); - ucSTAId = WLAN_ALL_STA; - status = WLANTL_ResumeDataTx(pWDA->pVosContext, &ucSTAId); + + status = WLANTL_ResumeDataTx(pWDA->pVosContext, NULL); return status; } /* @@ -2898,12 +2929,20 @@ VOS_STATUS WDA_ProcessConfigBssReq(tWDA_CbContext *pWDA, tAddBssParams* configBssReqParam) { WDI_Status status = WDI_STATUS_SUCCESS ; - WDI_ConfigBSSReqParamsType *wdiConfigBssReqParam = - (WDI_ConfigBSSReqParamsType *)vos_mem_malloc( - sizeof(WDI_ConfigBSSReqParamsType)) ; + WDI_ConfigBSSReqParamsType *wdiConfigBssReqParam; tWDA_ReqParams *pWdaParams ; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "------> %s " ,__func__); + if (NULL == configBssReqParam) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_FATAL, + "%s: configBssReqParam is NULL", __func__); + return VOS_STATUS_E_INVAL; + } + + wdiConfigBssReqParam = (WDI_ConfigBSSReqParamsType *)vos_mem_malloc( + sizeof(WDI_ConfigBSSReqParamsType)) ; + if(NULL == wdiConfigBssReqParam) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -3430,6 +3469,7 @@ VOS_STATUS WDA_ProcessAddStaSelfReq( tWDA_CbContext *pWDA, tpAddStaSelfParams pA } wdiAddStaSelfReq->wdiReqStatusCB = NULL; vos_mem_copy( wdiAddStaSelfReq->wdiAddSTASelfInfo.selfMacAddr, pAddStaSelfReq->selfMacAddr, 6); + wdiAddStaSelfReq->wdiAddSTASelfInfo.currDeviceMode = pAddStaSelfReq->currDeviceMode; /* Store Init Req pointer, as this will be used for response */ /* store Params pass it to WDI */ pWdaParams->pWdaContext = pWDA; @@ -3492,7 +3532,7 @@ void WDA_DelSTASelfReqCallback(WDI_Status wdiStatus, tDelStaSelfParams *delStaSelfParams; VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "<------ %s, wdiStatus: %d pWdaParams: 0x%x", + "<------ %s, wdiStatus: %d pWdaParams: %p", __func__, wdiStatus, pWdaParams); if (NULL == pWdaParams) @@ -3642,8 +3682,6 @@ void WDA_UpdateBSSParams(tWDA_CbContext *pWDA, wdiBssParams->ucCurrentExtChannel = wdaBssParams->currentExtChannel ; wdiBssParams->bHiddenSSIDEn = wdaBssParams->bHiddenSSIDEn ; - wdiBssParams->ucRMFEnabled = wdaBssParams->rmfEnabled; - /* copy SSID into WDI structure */ wdiBssParams->wdiSSID.ucLength = wdaBssParams->ssId.length ; vos_mem_copy(wdiBssParams->wdiSSID.sSSID, @@ -4862,7 +4900,6 @@ void WDA_GetStatsReqParamsCallback( pGetPEStatsRspParams->msgType = wdiGetStatsRsp->usMsgType; pGetPEStatsRspParams->msgLen = sizeof(tAniGetPEStatsRsp) + (wdiGetStatsRsp->usMsgLen - sizeof(WDI_GetStatsRspParamsType)); - pGetPEStatsRspParams->msgLen = wdiGetStatsRsp->usMsgLen + sizeof(tANI_U8); //Fill the Session Id Properly in PE pGetPEStatsRspParams->sessionId = 0; @@ -5306,6 +5343,8 @@ VOS_STATUS WDA_ProcessAddBASessionReq(tWDA_CbContext *pWDA, (WDI_AddBASessionReqParamsType *)vos_mem_malloc( sizeof(WDI_AddBASessionReqParamsType)) ; tWDA_ReqParams *pWdaParams ; + WLANTL_STAStateType tlSTAState = 0; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "------> %s " ,__func__); if(NULL == wdiAddBASessionReqParam) @@ -5357,6 +5396,27 @@ VOS_STATUS WDA_ProcessAddBASessionReq(tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = (void *)pAddBAReqParams ; /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)wdiAddBASessionReqParam ; + + /* In TDLS case, there is a possibility that TL hasn't registered peer yet, but + the peer thinks that we already setup TDLS link, and send us ADDBA request packet + */ + if((VOS_STATUS_SUCCESS != WDA_TL_GET_STA_STATE(pWDA->pVosContext, pAddBAReqParams->staIdx, &tlSTAState)) || + ((WLANTL_STA_CONNECTED != tlSTAState) && (WLANTL_STA_AUTHENTICATED != tlSTAState))) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Peer staIdx %d hasn't established yet(%d). Send ADD BA failure to PE.\n", pAddBAReqParams->staIdx, tlSTAState ); + status = WDI_STATUS_E_NOT_ALLOWED; + pAddBAReqParams->status = + CONVERT_WDI2SIR_STATUS(status) ; + WDA_SendMsg(pWDA, WDA_ADDBA_RSP, (void *)pAddBAReqParams , 0) ; + /*Reset the WDA state to READY */ + pWDA->wdaState = WDA_READY_STATE; + vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; + vos_mem_free(pWdaParams); + + return CONVERT_WDI2VOS_STATUS(status) ; + } + status = WDI_AddBASessionReq(wdiAddBASessionReqParam, (WDI_AddBASessionRspCb)WDA_AddBASessionReqCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) @@ -5368,6 +5428,8 @@ VOS_STATUS WDA_ProcessAddBASessionReq(tWDA_CbContext *pWDA, pAddBAReqParams->status = CONVERT_WDI2SIR_STATUS(status) ; WDA_SendMsg(pWDA, WDA_ADDBA_RSP, (void *)pAddBAReqParams , 0) ; + /*Reset the WDA state to READY */ + pWDA->wdaState = WDA_READY_STATE; vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; vos_mem_free(pWdaParams); } @@ -6564,10 +6626,10 @@ VOS_STATUS WDA_ProcessExitImpsReq(tWDA_CbContext *pWDA) return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_EnterBmpsReqCallback + * FUNCTION: WDA_EnterBmpsRespCallback * send Enter BMPS RSP back to PE */ -void WDA_EnterBmpsReqCallback(WDI_EnterBmpsRspParamsType *pwdiEnterBmpsRsp, void* pUserData) +void WDA_EnterBmpsRespCallback(WDI_EnterBmpsRspParamsType *pwdiEnterBmpsRsp, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -6595,6 +6657,41 @@ void WDA_EnterBmpsReqCallback(WDI_EnterBmpsRspParamsType *pwdiEnterBmpsRsp, void return ; } +/* + * FUNCTION: WDA_EnterBmpsReqCallback + * Free memory and send Enter BMPS RSP back to PE. + * Invoked when Enter BMPS REQ failed in WDI and no RSP callback is generated. + */ +void WDA_EnterBmpsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tEnterBmpsParams *pEnterBmpsRspParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pEnterBmpsRspParams = (tEnterBmpsParams *)pWdaParams->wdaMsgParam; + pEnterBmpsRspParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_ENTER_BMPS_RSP, (void *)pEnterBmpsRspParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessEnterBmpsReq * Request to WDI to Enter BMPS power state. @@ -6643,7 +6740,8 @@ VOS_STATUS WDA_ProcessEnterBmpsReq(tWDA_CbContext *pWDA, wdiEnterBmpsReqParams->wdiEnterBmpsInfo.rssiFilterPeriod = (wpt_uint32)pEnterBmpsReqParams->rssiFilterPeriod; wdiEnterBmpsReqParams->wdiEnterBmpsInfo.numBeaconPerRssiAverage = (wpt_uint32)pEnterBmpsReqParams->numBeaconPerRssiAverage; wdiEnterBmpsReqParams->wdiEnterBmpsInfo.bRssiFilterEnable = (wpt_uint8)pEnterBmpsReqParams->bRssiFilterEnable; - wdiEnterBmpsReqParams->wdiReqStatusCB = NULL; + wdiEnterBmpsReqParams->wdiReqStatusCB = WDA_EnterBmpsReqCallback; + wdiEnterBmpsReqParams->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ @@ -6651,7 +6749,7 @@ VOS_STATUS WDA_ProcessEnterBmpsReq(tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = pEnterBmpsReqParams; pWdaParams->pWdaContext = pWDA; status = WDI_EnterBmpsReq(wdiEnterBmpsReqParams, - (WDI_EnterBmpsRspCb)WDA_EnterBmpsReqCallback, pWdaParams); + (WDI_EnterBmpsRspCb)WDA_EnterBmpsRespCallback, pWdaParams); if (IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -6676,10 +6774,10 @@ static void WDA_SendExitBmpsRsp(tWDA_CbContext *pWDA, /* - * FUNCTION: WDA_ExitBmpsReqCallback + * FUNCTION: WDA_ExitBmpsRespCallback * send Exit BMPS RSP back to PE */ -void WDA_ExitBmpsReqCallback(WDI_ExitBmpsRspParamsType *pwdiExitBmpsRsp, void* pUserData) +void WDA_ExitBmpsRespCallback(WDI_ExitBmpsRspParamsType *pwdiExitBmpsRsp, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -6707,6 +6805,41 @@ void WDA_ExitBmpsReqCallback(WDI_ExitBmpsRspParamsType *pwdiExitBmpsRsp, void* p WDA_SendMsg(pWDA, WDA_EXIT_BMPS_RSP, (void *)pExitBmpsRspParams , 0) ; return ; } +/* + * FUNCTION: WDA_ExitBmpsReqCallback + * Free memory and send Exit BMPS RSP back to PE. + * Invoked when Exit BMPS REQ failed in WDI and no RSP callback is generated. + */ +void WDA_ExitBmpsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tExitBmpsParams *pExitBmpsRspParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pExitBmpsRspParams = (tExitBmpsParams *)pWdaParams->wdaMsgParam; + pExitBmpsRspParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_EXIT_BMPS_RSP, (void *)pExitBmpsRspParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessExitBmpsReq * Request to WDI to Exit BMPS power state. @@ -6742,15 +6875,16 @@ VOS_STATUS WDA_ProcessExitBmpsReq(tWDA_CbContext *pWDA, wdiExitBmpsReqParams->wdiExitBmpsInfo.bssIdx = pExitBmpsReqParams->bssIdx; - wdiExitBmpsReqParams->wdiReqStatusCB = NULL; - + wdiExitBmpsReqParams->wdiReqStatusCB = WDA_ExitBmpsReqCallback; + wdiExitBmpsReqParams->pUserData = pWdaParams; + /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiExitBmpsReqParams; pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pExitBmpsReqParams; status = WDI_ExitBmpsReq(wdiExitBmpsReqParams, - (WDI_ExitBmpsRspCb)WDA_ExitBmpsReqCallback, pWdaParams); + (WDI_ExitBmpsRspCb)WDA_ExitBmpsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -6762,10 +6896,10 @@ VOS_STATUS WDA_ProcessExitBmpsReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_EnterUapsdReqCallback + * FUNCTION: WDA_EnterUapsdRespCallback * send Enter UAPSD RSP back to PE */ -void WDA_EnterUapsdReqCallback( WDI_EnterUapsdRspParamsType *pwdiEnterUapsdRspParams, void* pUserData) +void WDA_EnterUapsdRespCallback( WDI_EnterUapsdRspParamsType *pwdiEnterUapsdRspParams, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -6791,6 +6925,41 @@ void WDA_EnterUapsdReqCallback( WDI_EnterUapsdRspParamsType *pwdiEnterUapsdRspP WDA_SendMsg(pWDA, WDA_ENTER_UAPSD_RSP, (void *)pEnterUapsdRsqParams , 0) ; return ; } +/* + * FUNCTION: WDA_EnterUapsdReqCallback + * Free memory and send Enter UAPSD RSP back to PE. + * Invoked when Enter UAPSD REQ failed in WDI and no RSP callback is generated. + */ +void WDA_EnterUapsdReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tUapsdParams *pEnterUapsdRsqParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pEnterUapsdRsqParams = (tUapsdParams *)pWdaParams->wdaMsgParam; + pEnterUapsdRsqParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_ENTER_UAPSD_RSP, (void *)pEnterUapsdRsqParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessEnterUapsdReq * Request to WDI to Enter UAPSD power state. @@ -6839,7 +7008,8 @@ VOS_STATUS WDA_ProcessEnterUapsdReq(tWDA_CbContext *pWDA, pEnterUapsdReqParams->voTriggerEnabled; wdiEnterUapsdReqParams->wdiEnterUapsdInfo.bssIdx = pEnterUapsdReqParams->bssIdx; - wdiEnterUapsdReqParams->wdiReqStatusCB = NULL; + wdiEnterUapsdReqParams->wdiReqStatusCB = WDA_EnterUapsdReqCallback; + wdiEnterUapsdReqParams->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ @@ -6847,7 +7017,7 @@ VOS_STATUS WDA_ProcessEnterUapsdReq(tWDA_CbContext *pWDA, pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pEnterUapsdReqParams; status = WDI_EnterUapsdReq(wdiEnterUapsdReqParams, - (WDI_EnterUapsdRspCb)WDA_EnterUapsdReqCallback, pWdaParams); + (WDI_EnterUapsdRspCb)WDA_EnterUapsdRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -6859,10 +7029,10 @@ VOS_STATUS WDA_ProcessEnterUapsdReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_ExitUapsdReqCallback + * FUNCTION: WDA_ExitUapsdRespCallback * send Exit UAPSD RSP back to PE */ -void WDA_ExitUapsdReqCallback(WDI_ExitUapsdRspParamsType *pwdiExitRspParam, void* pUserData) +void WDA_ExitUapsdRespCallback(WDI_ExitUapsdRspParamsType *pwdiExitRspParam, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -6891,6 +7061,41 @@ void WDA_ExitUapsdReqCallback(WDI_ExitUapsdRspParamsType *pwdiExitRspParam, void WDA_SendMsg(pWDA, WDA_EXIT_UAPSD_RSP, (void *)pExitUapsdRspParams, 0) ; return ; } +/* + * FUNCTION: WDA_ExitUapsdReqCallback + * Free memory and send Exit UAPSD RSP back to PE. + * Invoked when Exit UAPSD REQ failed in WDI and no RSP callback is generated. + */ +void WDA_ExitUapsdReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tExitUapsdParams *pExitUapsdRspParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pExitUapsdRspParams = (tExitUapsdParams *)pWdaParams->wdaMsgParam; + pExitUapsdRspParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_EXIT_UAPSD_RSP, (void *)pExitUapsdRspParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessExitUapsdReq * Request to WDI to Exit UAPSD power state. @@ -6925,7 +7130,8 @@ VOS_STATUS WDA_ProcessExitUapsdReq(tWDA_CbContext *pWDA, } wdiExitUapsdReqParams->wdiExitUapsdInfo.bssIdx = pExitUapsdParams->bssIdx; - wdiExitUapsdReqParams->wdiReqStatusCB = NULL; + wdiExitUapsdReqParams->wdiReqStatusCB = WDA_ExitUapsdReqCallback; + wdiExitUapsdReqParams->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ @@ -6933,7 +7139,7 @@ VOS_STATUS WDA_ProcessExitUapsdReq(tWDA_CbContext *pWDA, pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pExitUapsdParams; - status = WDI_ExitUapsdReq(wdiExitUapsdReqParams, (WDI_ExitUapsdRspCb)WDA_ExitUapsdReqCallback, pWdaParams); + status = WDI_ExitUapsdReq(wdiExitUapsdReqParams, (WDI_ExitUapsdRspCb)WDA_ExitUapsdRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -7133,19 +7339,57 @@ VOS_STATUS WDA_ProcessSetPwrSaveCfgReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status); } /* - * FUNCTION: WDA_SetUapsdAcParamsReqCallback + * FUNCTION: WDA_SetUapsdAcParamsRespCallback * */ -void WDA_SetUapsdAcParamsReqCallback(WDI_Status status, void* pUserData) +void WDA_SetUapsdAcParamsRespCallback(WDI_Status status, void* pUserData) { - tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s " ,__func__); - vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return ; + } + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams); return ; } +/* + * FUNCTION: WDA_SetUapsdAcParamsReqCallback + * Free memory. + * Invoked when SetUAPSDACParams REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetUapsdAcParamsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_SetUapsdAcParamsReq * Request to WDI to set the UAPSD params for an ac (sta mode). @@ -7183,7 +7427,9 @@ VOS_STATUS WDA_SetUapsdAcParamsReq(v_PVOID_t pVosContext, v_U8_t staIdx, wdiUapsdParams->wdiUapsdInfo.ucSTAIdx = pUapsdInfo->staidx; wdiUapsdParams->wdiUapsdInfo.uSusInterval = pUapsdInfo->susInterval; wdiUapsdParams->wdiUapsdInfo.ucUp = pUapsdInfo->up; - wdiUapsdParams->wdiReqStatusCB = NULL; + wdiUapsdParams->wdiReqStatusCB = WDA_SetUapsdAcParamsReqCallback; + wdiUapsdParams->pUserData = pWdaParams; + pWDA = vos_get_context( VOS_MODULE_ID_WDA, pVosContext ); pWdaParams->pWdaContext = pWDA; /* Store param pointer as passed in by caller */ @@ -7191,7 +7437,7 @@ VOS_STATUS WDA_SetUapsdAcParamsReq(v_PVOID_t pVosContext, v_U8_t staIdx, /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)wdiUapsdParams; status = WDI_SetUapsdAcParamsReq(wdiUapsdParams, - (WDI_SetUapsdAcParamsCb)WDA_SetUapsdAcParamsReqCallback, + (WDI_SetUapsdAcParamsCb)WDA_SetUapsdAcParamsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -7220,10 +7466,10 @@ VOS_STATUS WDA_ClearUapsdAcParamsReq(v_PVOID_t pVosContext, v_U8_t staIdx, wpt_u return VOS_STATUS_SUCCESS; } /* - * FUNCTION: WDA_UpdateUapsdParamsReqCallback + * FUNCTION: WDA_UpdateUapsdParamsRespCallback * */ -void WDA_UpdateUapsdParamsReqCallback(WDI_Status status, void* pUserData) +void WDA_UpdateUapsdParamsRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; @@ -7244,9 +7490,38 @@ void WDA_UpdateUapsdParamsReqCallback(WDI_Status status, void* pUserData) //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_UpdateUapsdParamsReqCallback invoked " ); + "WDA_UpdateUapsdParamsRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_UpdateUapsdParamsReqCallback + * Free memory. + * Invoked when UpdateUAPSDParams REQ failed in WDI and no RSP callback is generated. + */ +void WDA_UpdateUapsdParamsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_UpdateUapsdParamsReq * Request to WDI to update UAPSD params (in softAP mode) for a station. @@ -7273,6 +7548,8 @@ VOS_STATUS WDA_UpdateUapsdParamsReq(tWDA_CbContext *pWDA, wdiUpdateUapsdParams->wdiUpdateUapsdInfo.uMaxSpLen = pUpdateUapsdInfo->maxSpLen; wdiUpdateUapsdParams->wdiUpdateUapsdInfo.ucSTAIdx = pUpdateUapsdInfo->staIdx; wdiUpdateUapsdParams->wdiUpdateUapsdInfo.ucUapsdACMask = pUpdateUapsdInfo->uapsdACMask; + wdiUpdateUapsdParams->wdiReqStatusCB = WDA_UpdateUapsdParamsReqCallback; + wdiUpdateUapsdParams->pUserData = pWdaParams; pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; if(NULL == pWdaParams) @@ -7291,7 +7568,7 @@ VOS_STATUS WDA_UpdateUapsdParamsReq(tWDA_CbContext *pWDA, pWdaParams->pWdaContext = pWDA; wstatus = WDI_UpdateUapsdParamsReq(wdiUpdateUapsdParams, - (WDI_UpdateUapsdParamsCb)WDA_UpdateUapsdParamsReqCallback, + (WDI_UpdateUapsdParamsCb)WDA_UpdateUapsdParamsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) @@ -7306,10 +7583,10 @@ VOS_STATUS WDA_UpdateUapsdParamsReq(tWDA_CbContext *pWDA, return status; } /* - * FUNCTION: WDA_ConfigureRxpFilterCallback + * FUNCTION: WDA_ConfigureRxpFilterRespCallback * */ -void WDA_ConfigureRxpFilterCallback(WDI_Status wdiStatus, void* pUserData) +void WDA_ConfigureRxpFilterRespCallback(WDI_Status wdiStatus, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -7332,22 +7609,51 @@ void WDA_ConfigureRxpFilterCallback(WDI_Status wdiStatus, void* pUserData) return ; } /* - * FUNCTION: WDA_ProcessConfigureRxpFilterReq - * - */ -VOS_STATUS WDA_ProcessConfigureRxpFilterReq(tWDA_CbContext *pWDA, - tSirWlanSetRxpFilters *pWlanSuspendParam) + * FUNCTION: WDA_ConfigureRxpFilterReqCallback + * Free memory. + * Invoked when ConfigureRXPFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_ConfigureRxpFilterReqCallback(WDI_Status wdiStatus, void* pUserData) { - VOS_STATUS status = VOS_STATUS_SUCCESS; - WDI_Status wstatus; - WDI_ConfigureRxpFilterReqParamsType *wdiRxpFilterParams = - (WDI_ConfigureRxpFilterReqParamsType *)vos_mem_malloc( - sizeof(WDI_ConfigureRxpFilterReqParamsType)) ; - tWDA_ReqParams *pWdaParams ; + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "------> %s " ,__func__); - if(NULL == wdiRxpFilterParams) - { + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} +/* + * FUNCTION: WDA_ProcessConfigureRxpFilterReq + * + */ +VOS_STATUS WDA_ProcessConfigureRxpFilterReq(tWDA_CbContext *pWDA, + tSirWlanSetRxpFilters *pWlanSuspendParam) +{ + VOS_STATUS status = VOS_STATUS_SUCCESS; + WDI_Status wstatus; + WDI_ConfigureRxpFilterReqParamsType *wdiRxpFilterParams = + (WDI_ConfigureRxpFilterReqParamsType *)vos_mem_malloc( + sizeof(WDI_ConfigureRxpFilterReqParamsType)) ; + tWDA_ReqParams *pWdaParams ; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "------> %s " ,__func__); + if(NULL == wdiRxpFilterParams) + { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "%s: VOS MEM Alloc Failure", __func__); VOS_ASSERT(0); @@ -7369,12 +7675,14 @@ VOS_STATUS WDA_ProcessConfigureRxpFilterReq(tWDA_CbContext *pWDA, wdiRxpFilterParams->wdiRxpFilterParam.ucSetMcstBcstFilterSetting = pWlanSuspendParam->configuredMcstBcstFilterSetting; - wdiRxpFilterParams->wdiReqStatusCB = NULL; + wdiRxpFilterParams->wdiReqStatusCB = WDA_ConfigureRxpFilterReqCallback; + wdiRxpFilterParams->pUserData = pWdaParams; + pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWlanSuspendParam; pWdaParams->wdaWdiApiMsgParam = (void *)wdiRxpFilterParams; wstatus = WDI_ConfigureRxpFilterReq(wdiRxpFilterParams, - (WDI_ConfigureRxpFilterCb)WDA_ConfigureRxpFilterCallback, + (WDI_ConfigureRxpFilterCb)WDA_ConfigureRxpFilterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { @@ -7428,42 +7736,6 @@ VOS_STATUS WDA_ProcessWlanSuspendInd(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(wdiStatus) ; } -#ifdef WLAN_FEATURE_11W -/* - * FUNCTION: WDA_ProcessExcludeUnecryptInd - * - */ -VOS_STATUS WDA_ProcessExcludeUnecryptInd(tWDA_CbContext *pWDA, - tSirWlanExcludeUnencryptParam *pExclUnencryptParam) -{ - WDI_Status wdiStatus; - WDI_ExcludeUnencryptIndType wdiExclUnencryptParams; - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "------> %s ", __func__); - - wdiExclUnencryptParams.bExcludeUnencrypt = pExclUnencryptParam->excludeUnencrypt; - vos_mem_copy(wdiExclUnencryptParams.bssid, pExclUnencryptParam->bssId, - sizeof(tSirMacAddr)); - - wdiExclUnencryptParams.wdiReqStatusCB = NULL; - wdiExclUnencryptParams.pUserData = pWDA; - - wdiStatus = WDI_ExcludeUnencryptedInd(&wdiExclUnencryptParams); - if(WDI_STATUS_PENDING == wdiStatus) - { - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "Pending received for %s:%d ", __func__, __LINE__ ); - } - else if( WDI_STATUS_SUCCESS_SYNC != wdiStatus ) - { - VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "Failure in %s:%d ", __func__, __LINE__ ); - } - vos_mem_free(pExclUnencryptParam); - return CONVERT_WDI2VOS_STATUS(wdiStatus) ; -} -#endif - /* * FUNCTION: WDA_ProcessWlanResumeCallback * @@ -7545,10 +7817,10 @@ VOS_STATUS WDA_ProcessWlanResumeReq(tWDA_CbContext *pWDA, } /* - * FUNCTION: WDA_SetBeaconFilterReqCallback + * FUNCTION: WDA_SetBeaconFilterRespCallback * */ -void WDA_SetBeaconFilterReqCallback(WDI_Status status, void* pUserData) +void WDA_SetBeaconFilterRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -7571,6 +7843,35 @@ void WDA_SetBeaconFilterReqCallback(WDI_Status status, void* pUserData) return ; } +/* + * FUNCTION: WDA_SetBeaconFilterReqCallback + * Free memory. + * Invoked when SetBeaconFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetBeaconFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_SetBeaconFilterReq * Request to WDI to send the beacon filtering related information. @@ -7623,7 +7924,9 @@ VOS_STATUS WDA_SetBeaconFilterReq(tWDA_CbContext *pWDA, filterLength = WDI_BEACON_FILTER_LEN; } vos_mem_copy(dstPtr, srcPtr, filterLength); - wdiBeaconFilterInfo->wdiReqStatusCB = NULL; + wdiBeaconFilterInfo->wdiReqStatusCB = WDA_SetBeaconFilterReqCallback; + wdiBeaconFilterInfo->pUserData = pWdaParams; + /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiBeaconFilterInfo; @@ -7631,7 +7934,7 @@ VOS_STATUS WDA_SetBeaconFilterReq(tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = pBeaconFilterInfo; status = WDI_SetBeaconFilterReq(wdiBeaconFilterInfo, - (WDI_SetBeaconFilterCb)WDA_SetBeaconFilterReqCallback, pWdaParams); + (WDI_SetBeaconFilterCb)WDA_SetBeaconFilterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -7643,10 +7946,10 @@ VOS_STATUS WDA_SetBeaconFilterReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_RemBeaconFilterReqCallback + * FUNCTION: WDA_RemBeaconFilterRespCallback * */ -void WDA_RemBeaconFilterReqCallback(WDI_Status status, void* pUserData) +void WDA_RemBeaconFilterRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; @@ -7667,8 +7970,37 @@ void WDA_RemBeaconFilterReqCallback(WDI_Status status, void* pUserData) //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_RemBeaconFilterReqCallback invoked " ); + "WDA_RemBeaconFilterRespCallback invoked " ); return ; +} +/* + * FUNCTION: WDA_RemBeaconFilterReqCallback + * Free memory. + * Invoked when RemBeaconFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_RemBeaconFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; } // TODO: PE does not have this feature for now implemented, // but the support for removing beacon filter exists between @@ -7697,14 +8029,6 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, VOS_ASSERT(0); return VOS_STATUS_E_NOMEM; } - wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucIeCount = - pBeaconFilterInfo->ucIeCount; - //Fill structure with info contained in the ucRemIeId - vos_mem_copy(wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucRemIeId, - pBeaconFilterInfo->ucRemIeId, - wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucIeCount); - wdiBeaconFilterInfo->wdiReqStatusCB = NULL; - pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; if(NULL == pWdaParams) { @@ -7715,6 +8039,15 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, vos_mem_free(pBeaconFilterInfo); return VOS_STATUS_E_NOMEM; } + + wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucIeCount = + pBeaconFilterInfo->ucIeCount; + //Fill structure with info contained in the ucRemIeId + vos_mem_copy(wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucRemIeId, + pBeaconFilterInfo->ucRemIeId, + wdiBeaconFilterInfo->wdiBeaconFilterInfo.ucIeCount); + wdiBeaconFilterInfo->wdiReqStatusCB = WDA_RemBeaconFilterReqCallback; + wdiBeaconFilterInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pBeaconFilterInfo; @@ -7724,7 +8057,7 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, pWdaParams->pWdaContext = pWDA; wstatus = WDI_RemBeaconFilterReq(wdiBeaconFilterInfo, - (WDI_RemBeaconFilterCb)WDA_RemBeaconFilterReqCallback, pWdaParams); + (WDI_RemBeaconFilterCb)WDA_RemBeaconFilterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -7737,10 +8070,10 @@ VOS_STATUS WDA_RemBeaconFilterReq(tWDA_CbContext *pWDA, return status; } /* - * FUNCTION: WDA_SetRSSIThresholdsReqCallback + * FUNCTION: WDA_SetRSSIThresholdsRespCallback * */ -void WDA_SetRSSIThresholdsReqCallback(WDI_Status status, void* pUserData) +void WDA_SetRSSIThresholdsRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -7758,6 +8091,34 @@ void WDA_SetRSSIThresholdsReqCallback(WDI_Status status, void* pUserData) return ; } +/* + * FUNCTION: WDA_SetRSSIThresholdsReqCallback + * Free memory. + * Invoked when SetRSSIThresholds REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetRSSIThresholdsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_SetRSSIThresholdsReq * Request to WDI to set the RSSI thresholds (sta mode). @@ -7800,7 +8161,8 @@ VOS_STATUS WDA_SetRSSIThresholdsReq(tpAniSirGlobal pMac, tSirRSSIThresholds *pBm wdiRSSIThresholdsInfo->wdiRSSIThresholdsInfo.bRssiThres1PosNotify = pBmpsThresholds->bRssiThres1PosNotify; wdiRSSIThresholdsInfo->wdiRSSIThresholdsInfo.bRssiThres2PosNotify = pBmpsThresholds->bRssiThres2PosNotify; wdiRSSIThresholdsInfo->wdiRSSIThresholdsInfo.bRssiThres3PosNotify = pBmpsThresholds->bRssiThres3PosNotify; - wdiRSSIThresholdsInfo->wdiReqStatusCB = NULL; + wdiRSSIThresholdsInfo->wdiReqStatusCB = WDA_SetRSSIThresholdsReqCallback; + wdiRSSIThresholdsInfo->pUserData = pWdaParams; pVosContext = vos_get_global_context(VOS_MODULE_ID_PE, (void *)pMac); pWDA = vos_get_context( VOS_MODULE_ID_WDA, pVosContext ); @@ -7810,7 +8172,7 @@ VOS_STATUS WDA_SetRSSIThresholdsReq(tpAniSirGlobal pMac, tSirRSSIThresholds *pBm pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pBmpsThresholds; wstatus = WDI_SetRSSIThresholdsReq(wdiRSSIThresholdsInfo, - (WDI_SetRSSIThresholdsCb)WDA_SetRSSIThresholdsReqCallback, pWdaParams); + (WDI_SetRSSIThresholdsCb)WDA_SetRSSIThresholdsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -7851,7 +8213,8 @@ void WDA_HostOffloadRespCallback(WDI_Status status, void* pUserData) } /* * FUNCTION: WDA_HostOffloadReqCallback - * + * Free memory. + * Invoked when HostOffload REQ failed in WDI and no RSP callback is generated. */ void WDA_HostOffloadReqCallback(WDI_Status wdiStatus, void* pUserData) { @@ -7982,6 +8345,8 @@ VOS_STATUS WDA_ProcessHostOffloadReq(tWDA_CbContext *pWDA, { wdiHostOffloadInfo->wdiNsOffloadParams.targetIPv6Addr2Valid = 0; } + wdiHostOffloadInfo->wdiNsOffloadParams.slotIdx = + pHostOffloadParams->nsOffloadInfo.slotIdx; break; #endif //WLAN_NS_OFFLOAD default: @@ -8018,10 +8383,10 @@ VOS_STATUS WDA_ProcessHostOffloadReq(tWDA_CbContext *pWDA, }/*WDA_HostOffloadReq*/ /* - * FUNCTION: WDA_KeepAliveReqCallback + * FUNCTION: WDA_KeepAliveRespCallback * */ -void WDA_KeepAliveReqCallback(WDI_Status status, void* pUserData) +void WDA_KeepAliveRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData ; @@ -8039,12 +8404,41 @@ void WDA_KeepAliveReqCallback(WDI_Status status, void* pUserData) vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams->wdaMsgParam); vos_mem_free(pWdaParams); - + //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_KeepAliveReqCallback invoked " ); + "WDA_KeepAliveRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_KeepAliveReqCallback + * Free memory. + * Invoked when KeepAlive REQ failed in WDI and no RSP callback is generated. + */ +void WDA_KeepAliveReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessKeepAliveReq * Request to WDI to send Keep Alive packets to minimize unnecessary host @@ -8115,7 +8509,8 @@ VOS_STATUS WDA_ProcessKeepAliveReq(tWDA_CbContext *pWDA, SIR_MAC_ADDR_LEN, 0); } - wdiKeepAliveInfo->wdiReqStatusCB = NULL; + wdiKeepAliveInfo->wdiReqStatusCB = WDA_KeepAliveReqCallback; + wdiKeepAliveInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pKeepAliveParams; @@ -8146,7 +8541,7 @@ VOS_STATUS WDA_ProcessKeepAliveReq(tWDA_CbContext *pWDA, wdiKeepAliveInfo->wdiKeepAliveInfo.ucTimePeriod, wdiKeepAliveInfo->wdiKeepAliveInfo.ucPacketType); wstatus = WDI_KeepAliveReq(wdiKeepAliveInfo, - (WDI_KeepAliveCb)WDA_KeepAliveReqCallback, pWdaParams); + (WDI_KeepAliveCb)WDA_KeepAliveRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { @@ -8161,10 +8556,10 @@ VOS_STATUS WDA_ProcessKeepAliveReq(tWDA_CbContext *pWDA, }/*WDA_KeepAliveReq*/ /* - * FUNCTION: WDA_WowlAddBcPtrnReqCallback + * FUNCTION: WDA_WowlAddBcPtrnRespCallback * */ -void WDA_WowlAddBcPtrnReqCallback( +void WDA_WowlAddBcPtrnRespCallback( WDI_WowlAddBcPtrnRspParamsType *pWdiWowlAddBcstPtrRsp, void* pUserData) { @@ -8183,6 +8578,36 @@ void WDA_WowlAddBcPtrnReqCallback( vos_mem_free(pWdaParams) ; return ; } +/* + * FUNCTION: WDA_WowlAddBcPtrnReqCallback + * Free memory. + * Invoked when WOWLAddBCPTRN REQ failed in WDI and no RSP callback is generated. + */ +void WDA_WowlAddBcPtrnReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} + /* * FUNCTION: WDA_ProcessWowlAddBcPtrnReq * Request to WDI to add WOWL Bcast pattern @@ -8251,14 +8676,15 @@ VOS_STATUS WDA_ProcessWowlAddBcPtrnReq(tWDA_CbContext *pWDA, vos_mem_copy(wdiWowlAddBcPtrnInfo->wdiWowlAddBcPtrnInfo.bssId, pWowlAddBcPtrnParams->bssId, sizeof(wpt_macAddr)); - wdiWowlAddBcPtrnInfo->wdiReqStatusCB = NULL; + wdiWowlAddBcPtrnInfo->wdiReqStatusCB = WDA_WowlAddBcPtrnReqCallback; + wdiWowlAddBcPtrnInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiWowlAddBcPtrnInfo; pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWowlAddBcPtrnParams; wstatus = WDI_WowlAddBcPtrnReq(wdiWowlAddBcPtrnInfo, - (WDI_WowlAddBcPtrnCb)WDA_WowlAddBcPtrnReqCallback, pWdaParams); + (WDI_WowlAddBcPtrnCb)WDA_WowlAddBcPtrnRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -8272,10 +8698,10 @@ VOS_STATUS WDA_ProcessWowlAddBcPtrnReq(tWDA_CbContext *pWDA, }/*WDA_ProcessWowlAddBcPtrnReq*/ /* - * FUNCTION: WDA_WowlDelBcPtrnReqCallback + * FUNCTION: WDA_WowlDelBcPtrnRespCallback * */ -void WDA_WowlDelBcPtrnReqCallback( +void WDA_WowlDelBcPtrnRespCallback( WDI_WowlDelBcPtrnRspParamsType *pWdiWowlDelBcstPtrRsp, void* pUserData) { @@ -8294,6 +8720,35 @@ void WDA_WowlDelBcPtrnReqCallback( vos_mem_free(pWdaParams) ; return ; } +/* + * FUNCTION: WDA_WowlDelBcPtrnReqCallback + * Free memory. + * Invoked when WOWLDelBCPTRN REQ failed in WDI and no RSP callback is generated. + */ +void WDA_WowlDelBcPtrnReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessWowlDelBcPtrnReq * Request to WDI to delete WOWL Bcast pattern @@ -8331,14 +8786,15 @@ VOS_STATUS WDA_ProcessWowlDelBcPtrnReq(tWDA_CbContext *pWDA, vos_mem_copy(wdiWowlDelBcPtrnInfo->wdiWowlDelBcPtrnInfo.bssId, pWowlDelBcPtrnParams->bssId, sizeof(wpt_macAddr)); - wdiWowlDelBcPtrnInfo->wdiReqStatusCB = NULL; + wdiWowlDelBcPtrnInfo->wdiReqStatusCB = WDA_WowlDelBcPtrnReqCallback; + wdiWowlDelBcPtrnInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiWowlDelBcPtrnInfo; pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWowlDelBcPtrnParams; wstatus = WDI_WowlDelBcPtrnReq(wdiWowlDelBcPtrnInfo, - (WDI_WowlDelBcPtrnCb)WDA_WowlDelBcPtrnReqCallback, pWdaParams); + (WDI_WowlDelBcPtrnCb)WDA_WowlDelBcPtrnRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -8352,10 +8808,10 @@ VOS_STATUS WDA_ProcessWowlDelBcPtrnReq(tWDA_CbContext *pWDA, }/*WDA_ProcessWowlDelBcPtrnReq*/ /* - * FUNCTION: WDA_WowlEnterReqCallback + * FUNCTION: WDA_WowlEnterRespCallback * */ -void WDA_WowlEnterReqCallback(WDI_WowlEnterRspParamsType *pwdiWowlEnterRspParam, void* pUserData) +void WDA_WowlEnterRespCallback(WDI_WowlEnterRspParamsType *pwdiWowlEnterRspParam, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -8377,10 +8833,45 @@ void WDA_WowlEnterReqCallback(WDI_WowlEnterRspParamsType *pwdiWowlEnterRspParam, vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams) ; - pWowlEnterParams->status = - (pwdiWowlEnterRspParam->status); - WDA_SendMsg(pWDA, WDA_WOWL_ENTER_RSP, (void *)pWowlEnterParams , 0) ; - return ; + pWowlEnterParams->status = + (pwdiWowlEnterRspParam->status); + WDA_SendMsg(pWDA, WDA_WOWL_ENTER_RSP, (void *)pWowlEnterParams , 0) ; + return ; +} +/* + * FUNCTION: WDA_WowlEnterReqCallback + * Free memory and send WOWL Enter RSP back to PE. + * Invoked when WOWL Enter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_WowlEnterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tSirHalWowlEnterParams *pWowlEnterParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pWowlEnterParams = (tSirHalWowlEnterParams *)pWdaParams->wdaMsgParam; + pWowlEnterParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_WOWL_ENTER_RSP, (void *)pWowlEnterParams , 0); + } + + return; } /* * FUNCTION: WDA_ProcessWowlEnterReq @@ -8452,14 +8943,15 @@ VOS_STATUS WDA_ProcessWowlEnterReq(tWDA_CbContext *pWDA, wdiWowlEnterInfo->wdiWowlEnterInfo.bssIdx = pWowlEnterParams->bssIdx; - wdiWowlEnterInfo->wdiReqStatusCB = NULL; + wdiWowlEnterInfo->wdiReqStatusCB = WDA_WowlEnterReqCallback; + wdiWowlEnterInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiWowlEnterInfo; pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pWowlEnterParams; wstatus = WDI_WowlEnterReq(wdiWowlEnterInfo, - (WDI_WowlEnterReqCb)WDA_WowlEnterReqCallback, pWdaParams); + (WDI_WowlEnterReqCb)WDA_WowlEnterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -8473,10 +8965,10 @@ VOS_STATUS WDA_ProcessWowlEnterReq(tWDA_CbContext *pWDA, }/*WDA_ProcessWowlEnterReq*/ /* - * FUNCTION: WDA_WowlExitReqCallback + * FUNCTION: WDA_WowlExitRespCallback * */ -void WDA_WowlExitReqCallback( WDI_WowlExitRspParamsType *pwdiWowlExitRsp, void* pUserData) +void WDA_WowlExitRespCallback( WDI_WowlExitRspParamsType *pwdiWowlExitRsp, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -8504,6 +8996,41 @@ void WDA_WowlExitReqCallback( WDI_WowlExitRspParamsType *pwdiWowlExitRsp, void* WDA_SendMsg(pWDA, WDA_WOWL_EXIT_RSP, (void *)pWowlExitParams, 0) ; return ; } +/* + * FUNCTION: WDA_WowlExitReqCallback + * Free memory and send WOWL Exit RSP back to PE. + * Invoked when WOWL Exit REQ failed in WDI and no RSP callback is generated. + */ +void WDA_WowlExitReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + tSirHalWowlExitParams *pWowlExitParams; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + pWowlExitParams = (tSirHalWowlExitParams *)pWdaParams->wdaMsgParam; + pWowlExitParams->status = wdiStatus; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams); + WDA_SendMsg(pWDA, WDA_WOWL_EXIT_RSP, (void *)pWowlExitParams, 0); + } + + return; +} /* * FUNCTION: WDA_ProcessWowlExitReq * Request to WDI to add WOWL Bcast pattern @@ -8539,7 +9066,8 @@ VOS_STATUS WDA_ProcessWowlExitReq(tWDA_CbContext *pWDA, wdiWowlExitInfo->wdiWowlExitInfo.bssIdx = pWowlExitParams->bssIdx; - wdiWowlExitInfo->wdiReqStatusCB = NULL; + wdiWowlExitInfo->wdiReqStatusCB = WDA_WowlExitReqCallback; + wdiWowlExitInfo->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI */ @@ -8548,7 +9076,7 @@ VOS_STATUS WDA_ProcessWowlExitReq(tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = pWowlExitParams; wstatus = WDI_WowlExitReq(wdiWowlExitInfo, - (WDI_WowlExitReqCb)WDA_WowlExitReqCallback, pWdaParams); + (WDI_WowlExitReqCb)WDA_WowlExitRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { @@ -8770,10 +9298,10 @@ VOS_STATUS WDA_ProcessFlushAcReq(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_BtAmpEventReqCallback + * FUNCTION: WDA_BtAmpEventRespCallback * */ -void WDA_BtAmpEventReqCallback(WDI_Status status, void* pUserData) +void WDA_BtAmpEventRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; @@ -8804,7 +9332,46 @@ void WDA_BtAmpEventReqCallback(WDI_Status status, void* pUserData) */ return ; } +/* + * FUNCTION: WDA_BtAmpEventReqCallback + * Free memory. + * Invoked when BTAMPEvent REQ failed in WDI and no RSP callback is generated. + */ +void WDA_BtAmpEventReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_CbContext *pWDA; + WDI_BtAmpEventParamsType *wdiBtAmpEventParam; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + pWDA = (tWDA_CbContext *)pWdaParams->pWdaContext; + wdiBtAmpEventParam = (WDI_BtAmpEventParamsType *)pWdaParams->wdaWdiApiMsgParam; + + if(BTAMP_EVENT_CONNECTION_TERMINATED == + wdiBtAmpEventParam->wdiBtAmpEventInfo.ucBtAmpEventType) + { + pWDA->wdaAmpSessionOn = VOS_FALSE; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + return; +} /* * FUNCTION: WDA_ProcessBtAmpEventReq * Request to WDI to Update with BT AMP events. @@ -8837,14 +9404,15 @@ VOS_STATUS WDA_ProcessBtAmpEventReq(tWDA_CbContext *pWDA, } wdiBtAmpEventParam->wdiBtAmpEventInfo.ucBtAmpEventType = pBtAmpEventParams->btAmpEventType; - wdiBtAmpEventParam->wdiReqStatusCB = NULL; + wdiBtAmpEventParam->wdiReqStatusCB = WDA_BtAmpEventReqCallback; + wdiBtAmpEventParam->pUserData = pWdaParams; /* Store BT AMP event pointer, as this will be used for response */ /* store Params pass it to WDI */ pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pBtAmpEventParams; pWdaParams->wdaWdiApiMsgParam = wdiBtAmpEventParam; status = WDI_BtAmpEventReq(wdiBtAmpEventParam, - (WDI_BtAmpEventRspCb)WDA_BtAmpEventReqCallback, pWdaParams); + (WDI_BtAmpEventRspCb)WDA_BtAmpEventRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -8872,7 +9440,7 @@ void WDA_FTMCommandReqCallback(void *ftmCmdRspData, if((NULL == pWDA) || (NULL == ftmCmdRspData)) { VOS_TRACE(VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s, invalid input 0x%x, 0x%x",__func__, pWDA, ftmCmdRspData); + "%s, invalid input %p, %p",__func__, pWDA, ftmCmdRspData); return; } /* Release Current FTM Command Request */ @@ -9032,10 +9600,10 @@ VOS_STATUS WDA_ProcessStartOemDataReq(tWDA_CbContext *pWDA, } #endif /* FEATURE_OEM_DATA_SUPPORT */ /* - * FUNCTION: WDA_SetTxPerTrackingReqCallback + * FUNCTION: WDA_SetTxPerTrackingRespCallback * */ -void WDA_SetTxPerTrackingReqCallback(WDI_Status status, void* pUserData) +void WDA_SetTxPerTrackingRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -9047,25 +9615,48 @@ void WDA_SetTxPerTrackingReqCallback(WDI_Status status, void* pUserData) VOS_ASSERT(0) ; return ; } - - if(NULL != pWdaParams->wdaMsgParam) + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + + return ; +} +/* + * FUNCTION: WDA_SetTxPerTrackingReqCallback + * Free memory. + * Invoked when SetTXPerTracking REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetTxPerTrackingReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) { - vos_mem_free(pWdaParams->wdaMsgParam); + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; } - if(NULL != pWdaParams->wdaWdiApiMsgParam) + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) { vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); } - - vos_mem_free(pWdaParams); - return ; + + return; } #ifdef WLAN_FEATURE_GTK_OFFLOAD /* - * FUNCTION: WDA_HostOffloadReqCallback + * FUNCTION: WDA_GTKOffloadRespCallback * */ -void WDA_GTKOffloadReqCallback( WDI_GtkOffloadRspParams *pwdiGtkOffloadRsparams, +void WDA_GTKOffloadRespCallback( WDI_GtkOffloadRspParams *pwdiGtkOffloadRsparams, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -9081,11 +9672,39 @@ void WDA_GTKOffloadReqCallback( WDI_GtkOffloadRspParams *pwdiGtkOffloadRsparams //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_GTKOffloadReqCallback invoked " ); + "WDA_GTKOffloadRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_GTKOffloadReqCallback + * Free memory. + * Invoked when GTKOffload REQ failed in WDI and no RSP callback is generated. + */ +void WDA_GTKOffloadReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + return; +} /* * FUNCTION: WDA_ProcessGTKOffloadReq * Request to WDI to set the filter to minimize unnecessary host wakeup due @@ -9137,7 +9756,8 @@ VOS_STATUS WDA_ProcessGTKOffloadReq(tWDA_CbContext *pWDA, vos_mem_copy(&(wdiGtkOffloadReqMsg->gtkOffloadReqParams.ullKeyReplayCounter), &(pGtkOffloadParams->ullKeyReplayCounter), sizeof(v_U64_t)); - wdiGtkOffloadReqMsg->wdiReqStatusCB = NULL; + wdiGtkOffloadReqMsg->wdiReqStatusCB = WDA_GTKOffloadReqCallback; + wdiGtkOffloadReqMsg->pUserData = pWdaParams; /* Store Params pass it to WDI */ @@ -9146,7 +9766,7 @@ VOS_STATUS WDA_ProcessGTKOffloadReq(tWDA_CbContext *pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pGtkOffloadParams; - status = WDI_GTKOffloadReq(wdiGtkOffloadReqMsg, (WDI_GtkOffloadCb)WDA_GTKOffloadReqCallback, pWdaParams); + status = WDI_GTKOffloadReq(wdiGtkOffloadReqMsg, (WDI_GtkOffloadCb)WDA_GTKOffloadRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -9161,16 +9781,16 @@ VOS_STATUS WDA_ProcessGTKOffloadReq(tWDA_CbContext *pWDA, } /* - * FUNCTION: WDA_GtkOffloadGetInfoCallback + * FUNCTION: WDA_GtkOffloadGetInfoRespCallback * */ -void WDA_GtkOffloadGetInfoCallback( WDI_GtkOffloadGetInfoRspParams *pwdiGtkOffloadGetInfoRsparams, +void WDA_GtkOffloadGetInfoRespCallback( WDI_GtkOffloadGetInfoRspParams *pwdiGtkOffloadGetInfoRsparams, void * pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; tWDA_CbContext *pWDA; tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoReq; - tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp = vos_mem_malloc(sizeof(tpSirGtkOffloadGetInfoRspParams)) ; + tpSirGtkOffloadGetInfoRspParams pGtkOffloadGetInfoRsp = vos_mem_malloc(sizeof(tSirGtkOffloadGetInfoRspParams)) ; vos_msg_t vosMsg; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, @@ -9211,6 +9831,44 @@ void WDA_GtkOffloadGetInfoCallback( WDI_GtkOffloadGetInfoRspParams *pwdiGtkOfflo vos_mem_free(pWdaParams->wdaMsgParam) ; vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams) ; + + return; +} +/* + * FUNCTION: WDA_GtkOffloadGetInfoReqCallback + * Free memory and send RSP back to SME. + * Invoked when GTKOffloadGetInfo REQ failed in WDI and no RSP callback is generated. + */ +void WDA_GtkOffloadGetInfoReqCallback(WDI_Status wdiStatus, void * pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + vos_msg_t vosMsg; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + /* VOS message wrapper */ + vosMsg.type = eWNI_PMC_GTK_OFFLOAD_GETINFO_RSP; + vosMsg.bodyptr = NULL; + vosMsg.bodyval = 0; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + vos_mq_post_message(VOS_MQ_ID_SME, (vos_msg_t*)&vosMsg); + } + + return; } #endif @@ -9254,7 +9912,8 @@ VOS_STATUS WDA_ProcessSetTxPerTrackingReq(tWDA_CbContext *pWDA, tSirTxPerTrackin pTxPerTrackingParams->ucTxPerTrackingRatio; pwdiSetTxPerTrackingReqParams->wdiTxPerTrackingParam.uTxPerTrackingWatermark = pTxPerTrackingParams->uTxPerTrackingWatermark; - pwdiSetTxPerTrackingReqParams->wdiReqStatusCB = NULL; + pwdiSetTxPerTrackingReqParams->wdiReqStatusCB = WDA_SetTxPerTrackingReqCallback; + pwdiSetTxPerTrackingReqParams->pUserData = pWdaParams; /* Store param pointer as passed in by caller */ /* store Params pass it to WDI Ideally, the memory allocated here will be free at WDA_SetTxPerTrackingReqCallback */ @@ -9262,7 +9921,7 @@ VOS_STATUS WDA_ProcessSetTxPerTrackingReq(tWDA_CbContext *pWDA, tSirTxPerTrackin pWdaParams->pWdaContext = pWDA; pWdaParams->wdaMsgParam = pTxPerTrackingParams; wstatus = WDI_SetTxPerTrackingReq(pwdiSetTxPerTrackingReqParams, - (WDI_SetTxPerTrackingRspCb)WDA_SetTxPerTrackingReqCallback, pWdaParams); + (WDI_SetTxPerTrackingRspCb)WDA_SetTxPerTrackingRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(wstatus)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -9407,7 +10066,8 @@ VOS_STATUS WDA_ProcessGTKOffloadGetInfoReq(tWDA_CbContext *pWDA, return VOS_STATUS_E_NOMEM; } - pwdiGtkOffloadGetInfoReqMsg->wdiReqStatusCB = NULL; + pwdiGtkOffloadGetInfoReqMsg->wdiReqStatusCB = WDA_GtkOffloadGetInfoReqCallback; + pwdiGtkOffloadGetInfoReqMsg->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiGtkOffloadGetInfoReqMsg; @@ -9418,7 +10078,7 @@ VOS_STATUS WDA_ProcessGTKOffloadGetInfoReq(tWDA_CbContext *pWDA, vos_mem_copy(pwdiGtkOffloadGetInfoReqMsg->WDI_GtkOffloadGetInfoReqParams.bssId, pGtkOffloadGetInfoRsp->bssId, sizeof (wpt_macAddr)); - status = WDI_GTKOffloadGetInfoReq(pwdiGtkOffloadGetInfoReqMsg, (WDI_GtkOffloadGetInfoCb)WDA_GtkOffloadGetInfoCallback, pWdaParams); + status = WDI_GTKOffloadGetInfoReq(pwdiGtkOffloadGetInfoReqMsg, (WDI_GtkOffloadGetInfoCb)WDA_GtkOffloadGetInfoRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -9483,7 +10143,7 @@ VOS_STATUS WDA_TxComplete( v_PVOID_t pVosContext, vos_pkt_t *pData, else { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_WARN, - "%s:packet (0x%X) is already freed", + "%s:packet (%p) is already freed", __func__, pData); //Return from here since we reaching here because the packet already timeout return status; @@ -9529,14 +10189,14 @@ VOS_STATUS WDA_TxPacket(tWDA_CbContext *pWDA, if((NULL == pWDA)||(NULL == pFrmBuf)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s:pWDA %x or pFrmBuf %x is NULL", + "%s:pWDA %p or pFrmBuf %p is NULL", __func__,pWDA,pFrmBuf); VOS_ASSERT(0); return VOS_STATUS_E_FAILURE; } VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO_HIGH, - "Tx Mgmt Frame Subtype: %d alloc(%x)\n", pFc->subType, pFrmBuf); + "Tx Mgmt Frame Subtype: %d alloc(%p)\n", pFc->subType, pFrmBuf); pMac = (tpAniSirGlobal )VOS_GET_MAC_CTXT(pWDA->pVosContext); if(NULL == pMac) { @@ -10255,6 +10915,13 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) break; } #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case WDA_ROAM_SCAN_OFFLOAD_REQ: + { + WDA_ProcessRoamScanOffloadReq(pWDA, (tSirRoamOffloadScanReq *)pMsg->bodyptr); + break; + } +#endif case WDA_SET_TX_PER_TRACKING_REQ: { WDA_ProcessSetTxPerTrackingReq(pWDA, (tSirTxPerTrackingParam *)pMsg->bodyptr); @@ -10330,13 +10997,6 @@ VOS_STATUS WDA_McProcessMsg( v_CONTEXT_t pVosContext, vos_msg_t *pMsg ) " 11AC Feature is Not Supported \n"); break; } -#endif -#ifdef WLAN_FEATURE_11W - case WDA_EXCLUDE_UNENCRYPTED_IND: - { - WDA_ProcessExcludeUnecryptInd(pWDA, (tSirWlanExcludeUnencryptParam *)pMsg->bodyptr); - break; - } #endif default: { @@ -10643,7 +11303,11 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, case WDI_PREF_NETWORK_FOUND_IND: { vos_msg_t vosMsg; - tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = (tSirPrefNetworkFoundInd *)vos_mem_malloc(sizeof(tSirPrefNetworkFoundInd)); + v_U32_t size = sizeof(tSirPrefNetworkFoundInd) + + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.frameLength; + tSirPrefNetworkFoundInd *pPrefNetworkFoundInd = + (tSirPrefNetworkFoundInd *)vos_mem_malloc(size); + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "Received WDI_PREF_NETWORK_FOUND_IND from WDI"); if (NULL == pPrefNetworkFoundInd) @@ -10655,7 +11319,7 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, } /* Message Header */ pPrefNetworkFoundInd->mesgType = eWNI_SME_PREF_NETWORK_FOUND_IND; - pPrefNetworkFoundInd->mesgLen = sizeof(*pPrefNetworkFoundInd); + pPrefNetworkFoundInd->mesgLen = size; /* Info from WDI Indication */ pPrefNetworkFoundInd->ssId.length = @@ -10664,6 +11328,21 @@ void WDA_lowLevelIndCallback(WDI_LowLevelIndType *wdiLowLevelInd, vos_mem_copy( pPrefNetworkFoundInd->ssId.ssId, wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.ssId.sSSID, pPrefNetworkFoundInd->ssId.length); + if (NULL != + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.pData) + { + pPrefNetworkFoundInd->frameLength = + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.frameLength; + vos_mem_copy( pPrefNetworkFoundInd->data, + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.pData, + pPrefNetworkFoundInd->frameLength); + wpalMemoryFree(wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.pData); + wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.pData = NULL; + } + else + { + pPrefNetworkFoundInd->frameLength = 0; + } pPrefNetworkFoundInd ->rssi = wdiLowLevelInd->wdiIndicationData.wdiPrefNetworkFoundInd.rssi; /* VOS message wrapper */ vosMsg.type = eWNI_SME_PREF_NETWORK_FOUND_IND; @@ -11284,66 +11963,108 @@ eHalStatus WDA_SetRegDomain(void * clientCtxt, v_REGDOMAIN_t regId) #ifdef FEATURE_WLAN_SCAN_PNO /* - * FUNCTION: WDA_PNOScanReqCallback + * FUNCTION: WDA_PNOScanRespCallback * */ -void WDA_PNOScanReqCallback(WDI_Status status, void* pUserData) +void WDA_PNOScanRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s " ,__func__); - if(NULL == pWdaParams) + if(NULL == pWdaParams) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "%s: pWdaParams received NULL", __func__); VOS_ASSERT(0) ; return ; } - if( pWdaParams != NULL ) + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + + return ; +} +/* + * FUNCTION: WDA_PNOScanReqCallback + * Free memory. + * Invoked when PNOScan REQ failed in WDI and no RSP callback is generated. + */ +void WDA_PNOScanReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) { - if( pWdaParams->wdaWdiApiMsgParam != NULL ) - { - vos_mem_free(pWdaParams->wdaWdiApiMsgParam); - } - if( pWdaParams->wdaMsgParam != NULL) - { - vos_mem_free(pWdaParams->wdaMsgParam); - } + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } - vos_mem_free(pWdaParams) ; + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); } - return ; + return; } /* - * FUNCTION: WDA_UpdateScanParamsCallback - * - */ -void WDA_UpdateScanParamsCallback(WDI_Status status, void* pUserData) + * FUNCTION: WDA_UpdateScanParamsRespCallback + * + */ +void WDA_UpdateScanParamsRespCallback(WDI_Status status, void* pUserData) { - tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, "<------ %s " ,__func__); - if(NULL == pWdaParams) + if(NULL == pWdaParams) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, "%s: pWdaParams received NULL", __func__); VOS_ASSERT(0) ; return ; } - if( pWdaParams != NULL ) + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + + return ; +} +/* + * FUNCTION: WDA_UpdateScanParamsReqCallback + * Free memory. + * Invoked when UpdateScanParams REQ failed in WDI and no RSP callback is generated. + */ +void WDA_UpdateScanParamsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) { - if( pWdaParams->wdaWdiApiMsgParam != NULL ) - { - vos_mem_free(pWdaParams->wdaWdiApiMsgParam); - } - if( pWdaParams->wdaMsgParam != NULL) - { - vos_mem_free(pWdaParams->wdaMsgParam); - } - vos_mem_free(pWdaParams) ; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; } - return ; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; } /* * FUNCTION: WDA_ProcessSetPreferredNetworkList @@ -11407,7 +12128,8 @@ VOS_STATUS WDA_ProcessSetPrefNetworkReq(tWDA_CbContext *pWDA, vos_mem_copy( &pwdiPNOScanReqInfo->wdiPNOScanInfo.a5GProbeTemplate, pPNOScanReqParams->p5GProbeTemplate, pwdiPNOScanReqInfo->wdiPNOScanInfo.us5GProbeSize); - pwdiPNOScanReqInfo->wdiReqStatusCB = NULL; + pwdiPNOScanReqInfo->wdiReqStatusCB = WDA_PNOScanReqCallback; + pwdiPNOScanReqInfo->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiPNOScanReqInfo; @@ -11415,7 +12137,7 @@ VOS_STATUS WDA_ProcessSetPrefNetworkReq(tWDA_CbContext *pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pPNOScanReqParams; status = WDI_SetPreferredNetworkReq(pwdiPNOScanReqInfo, - (WDI_PNOScanCb)WDA_PNOScanReqCallback, pWdaParams); + (WDI_PNOScanCb)WDA_PNOScanRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, @@ -11427,11 +12149,247 @@ VOS_STATUS WDA_ProcessSetPrefNetworkReq(tWDA_CbContext *pWDA, } return CONVERT_WDI2VOS_STATUS(status) ; } + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +void WDA_ConvertSirAuthToWDIAuth(WDI_AuthType *AuthType, v_U8_t csrAuthType) +{ + /*Convert the CSR Auth types to WDI Auth types */ + switch (csrAuthType) + { + case eCSR_AUTH_TYPE_OPEN_SYSTEM: + *AuthType = eWDA_AUTH_TYPE_OPEN_SYSTEM; + break; +#ifdef FEATURE_WLAN_CCX + case eCSR_AUTH_TYPE_CCKM_WPA: + *AuthType = eWDA_AUTH_TYPE_CCKM_WPA; + break; +#endif + case eCSR_AUTH_TYPE_WPA: + *AuthType = eWDA_AUTH_TYPE_WPA; + break; + case eCSR_AUTH_TYPE_WPA_PSK: + *AuthType = eWDA_AUTH_TYPE_WPA_PSK; + break; +#ifdef FEATURE_WLAN_CCX + case eCSR_AUTH_TYPE_CCKM_RSN: + *AuthType = eWDA_AUTH_TYPE_CCKM_RSN; + break; +#endif + case eCSR_AUTH_TYPE_RSN: + *AuthType = eWDA_AUTH_TYPE_RSN; + break; + case eCSR_AUTH_TYPE_RSN_PSK: + *AuthType = eWDA_AUTH_TYPE_RSN_PSK; + break; +#if defined WLAN_FEATURE_VOWIFI_11R + case eCSR_AUTH_TYPE_FT_RSN: + *AuthType = eWDA_AUTH_TYPE_FT_RSN; + break; + case eCSR_AUTH_TYPE_FT_RSN_PSK: + *AuthType = eWDA_AUTH_TYPE_FT_RSN_PSK; + break; +#endif +#ifdef FEATURE_WLAN_WAPI + case eCSR_AUTH_TYPE_WAPI_WAI_CERTIFICATE: + *AuthType = eWDA_AUTH_TYPE_WAPI_WAI_CERTIFICATE; + break; + case eCSR_AUTH_TYPE_WAPI_WAI_PSK: + *AuthType = eWDA_AUTH_TYPE_WAPI_WAI_PSK; + break; +#endif /* FEATURE_WLAN_WAPI */ + case eCSR_AUTH_TYPE_SHARED_KEY: + case eCSR_AUTH_TYPE_AUTOSWITCH: + *AuthType = eWDA_AUTH_TYPE_OPEN_SYSTEM; + break; +#if 0 + case eCSR_AUTH_TYPE_SHARED_KEY: + *AuthType = eWDA_AUTH_TYPE_SHARED_KEY; + break; + case eCSR_AUTH_TYPE_AUTOSWITCH: + *AuthType = eWDA_AUTH_TYPE_AUTOSWITCH; +#endif + default: + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Unknown Auth Type", __func__); + break; + } +} +void WDA_ConvertSirEncToWDIEnc(WDI_EdType *EncrType, v_U8_t csrEncrType) +{ + switch (csrEncrType) + { + case eCSR_ENCRYPT_TYPE_NONE: + *EncrType = WDI_ED_NONE; + break; + case eCSR_ENCRYPT_TYPE_WEP40_STATICKEY: + case eCSR_ENCRYPT_TYPE_WEP40: + *EncrType = WDI_ED_WEP40; + break; + case eCSR_ENCRYPT_TYPE_WEP104: + case eCSR_ENCRYPT_TYPE_WEP104_STATICKEY: + *EncrType = WDI_ED_WEP104; + break; + case eCSR_ENCRYPT_TYPE_TKIP: + *EncrType = WDI_ED_TKIP; + break; + case eCSR_ENCRYPT_TYPE_AES: + *EncrType = WDI_ED_CCMP; + break; +#ifdef WLAN_FEATURE_11W + case eCSR_ENCRYPT_TYPE_AES_CMAC: + *EncrType = WDI_ED_AES_128_CMAC; + break; +#endif +#ifdef FEATURE_WLAN_WAPI + case eCSR_ENCRYPT_TYPE_WPI: + *EncrType = WDI_ED_WPI; + break; +#endif + case eCSR_ENCRYPT_TYPE_ANY: + *EncrType = WDI_ED_ANY; + break; + + default: + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Unknown Encryption Type", __func__); + break; + } +} + +/* + * FUNCTION: WDA_ProcessRoamScanOffloadReq + * Request to WDI to set Roam Offload Scan + */ +VOS_STATUS WDA_ProcessRoamScanOffloadReq(tWDA_CbContext *pWDA, + tSirRoamOffloadScanReq *pRoamOffloadScanReqParams) +{ + WDI_Status status; + WDI_RoamScanOffloadReqParamsType *pwdiRoamScanOffloadReqParams = + (WDI_RoamScanOffloadReqParamsType *)vos_mem_malloc(sizeof(WDI_RoamScanOffloadReqParamsType)); + tWDA_ReqParams *pWdaParams ; + v_U8_t csrAuthType; + WDI_RoamNetworkType *pwdiRoamNetworkType; + WDI_RoamOffloadScanInfo *pwdiRoamOffloadScanInfo; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "------> %s " ,__func__); + if (NULL == pwdiRoamScanOffloadReqParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + return VOS_STATUS_E_NOMEM; + } + pWdaParams = (tWDA_ReqParams *)vos_mem_malloc(sizeof(tWDA_ReqParams)) ; + if (NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: VOS MEM Alloc Failure", __func__); + VOS_ASSERT(0); + vos_mem_free(pwdiRoamScanOffloadReqParams); + return VOS_STATUS_E_NOMEM; + } + + pwdiRoamNetworkType = + &pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork; + pwdiRoamOffloadScanInfo = + &pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo; + vos_mem_zero (pwdiRoamScanOffloadReqParams,sizeof(WDI_RoamScanOffloadReqParamsType)); + csrAuthType = pRoamOffloadScanReqParams->ConnectedNetwork.authentication; + pwdiRoamOffloadScanInfo->RoamScanOffloadEnabled = + pRoamOffloadScanReqParams->RoamScanOffloadEnabled; + vos_mem_copy(pwdiRoamNetworkType->currAPbssid, + pRoamOffloadScanReqParams->ConnectedNetwork.currAPbssid, + sizeof(pwdiRoamNetworkType->currAPbssid)); + WDA_ConvertSirAuthToWDIAuth(&pwdiRoamNetworkType->authentication, + csrAuthType); + WDA_ConvertSirEncToWDIEnc(&pwdiRoamNetworkType->encryption, + pRoamOffloadScanReqParams->ConnectedNetwork.encryption); + WDA_ConvertSirEncToWDIEnc(&pwdiRoamNetworkType->mcencryption, + pRoamOffloadScanReqParams->ConnectedNetwork.mcencryption); + pwdiRoamOffloadScanInfo->LookupThreshold = + pRoamOffloadScanReqParams->LookupThreshold ; + pwdiRoamOffloadScanInfo->RoamRssiDiff = + pRoamOffloadScanReqParams->RoamRssiDiff ; + pwdiRoamOffloadScanInfo->Command = + pRoamOffloadScanReqParams->Command ; + pwdiRoamOffloadScanInfo->StartScanReason = + pRoamOffloadScanReqParams->StartScanReason ; + pwdiRoamOffloadScanInfo->NeighborScanTimerPeriod = + pRoamOffloadScanReqParams->NeighborScanTimerPeriod ; + pwdiRoamOffloadScanInfo->NeighborRoamScanRefreshPeriod = + pRoamOffloadScanReqParams->NeighborRoamScanRefreshPeriod ; + pwdiRoamOffloadScanInfo->NeighborScanChannelMinTime = + pRoamOffloadScanReqParams->NeighborScanChannelMinTime ; + pwdiRoamOffloadScanInfo->NeighborScanChannelMaxTime = + pRoamOffloadScanReqParams->NeighborScanChannelMaxTime ; + pwdiRoamOffloadScanInfo->EmptyRefreshScanPeriod = + pRoamOffloadScanReqParams->EmptyRefreshScanPeriod ; + pwdiRoamOffloadScanInfo->IsCCXEnabled = + pRoamOffloadScanReqParams->IsCCXEnabled ; + vos_mem_copy(&pwdiRoamNetworkType->ssId.sSSID, + &pRoamOffloadScanReqParams->ConnectedNetwork.ssId.ssId, + pRoamOffloadScanReqParams->ConnectedNetwork.ssId.length); + pwdiRoamNetworkType->ssId.ucLength = + pRoamOffloadScanReqParams->ConnectedNetwork.ssId.length; + vos_mem_copy(pwdiRoamNetworkType->ChannelCache, + pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCache, + pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCount); + pwdiRoamNetworkType->ChannelCount = + pRoamOffloadScanReqParams->ConnectedNetwork.ChannelCount; + pwdiRoamOffloadScanInfo->ChannelCacheType = + pRoamOffloadScanReqParams->ChannelCacheType; + vos_mem_copy(pwdiRoamOffloadScanInfo->ValidChannelList, + pRoamOffloadScanReqParams->ValidChannelList, + pRoamOffloadScanReqParams->ValidChannelCount); + pwdiRoamOffloadScanInfo->ValidChannelCount = + pRoamOffloadScanReqParams->ValidChannelCount; + pwdiRoamOffloadScanInfo->us24GProbeSize = + (pRoamOffloadScanReqParams->us24GProbeTemplateLenus24GProbeTemplateLen:WDI_PNO_MAX_PROBE_SIZE; + vos_mem_copy(&pwdiRoamOffloadScanInfo->a24GProbeTemplate, + pRoamOffloadScanReqParams->p24GProbeTemplate, + pwdiRoamOffloadScanInfo->us24GProbeSize); + pwdiRoamOffloadScanInfo->us5GProbeSize = + (pRoamOffloadScanReqParams->us5GProbeTemplateLenus5GProbeTemplateLen:WDI_PNO_MAX_PROBE_SIZE; + vos_mem_copy(&pwdiRoamOffloadScanInfo->a5GProbeTemplate, + pRoamOffloadScanReqParams->p5GProbeTemplate, + pwdiRoamOffloadScanInfo->us5GProbeSize); + pwdiRoamOffloadScanInfo->MDID.mdiePresent = + pRoamOffloadScanReqParams->MDID.mdiePresent; + pwdiRoamOffloadScanInfo->MDID.mobilityDomain = + pRoamOffloadScanReqParams->MDID.mobilityDomain; + pwdiRoamOffloadScanInfo->nProbes = + pRoamOffloadScanReqParams->nProbes; + pwdiRoamOffloadScanInfo->HomeAwayTime = + pRoamOffloadScanReqParams->HomeAwayTime; + pwdiRoamScanOffloadReqParams->wdiReqStatusCB = NULL; + /* Store Params pass it to WDI */ + pWdaParams->wdaWdiApiMsgParam = (void *)pwdiRoamScanOffloadReqParams; + pWdaParams->pWdaContext = pWDA; + /* Store param pointer as passed in by caller */ + pWdaParams->wdaMsgParam = pRoamOffloadScanReqParams; + status = WDI_RoamScanOffloadReq(pwdiRoamScanOffloadReqParams, + (WDI_RoamOffloadScanCb)WDA_RoamOffloadScanReqCallback, pWdaParams); + if(IS_WDI_STATUS_FAILURE(status)) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "Failure in Start Roam Candidate Lookup Req WDI API, free all the memory " ); + vos_mem_free(pWdaParams->wdaWdiApiMsgParam) ; + vos_mem_free(pWdaParams->wdaMsgParam); + pWdaParams->wdaWdiApiMsgParam = NULL; + pWdaParams->wdaMsgParam = NULL; + } + return CONVERT_WDI2VOS_STATUS(status) ; +} +#endif + /* - * FUNCTION: WDA_RssiFilterCallback + * FUNCTION: WDA_RssiFilterRespCallback * */ -void WDA_RssiFilterCallback(WDI_Status status, void* pUserData) +void WDA_RssiFilterRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -11441,16 +12399,46 @@ void WDA_RssiFilterCallback(WDI_Status status, void* pUserData) if(NULL == pWdaParams) { VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, - "%s: pWdaParams is NULL", __func__); + "%s: pWdaParams received NULL", __func__); VOS_ASSERT(0); - return ; + return; } + vos_mem_free(pWdaParams->wdaMsgParam) ; vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams) ; return ; } +/* + * FUNCTION: WDA_RssiFilterReqCallback + * Free memory. + * Invoked when RSSIFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_RssiFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessSetPreferredNetworkList * Request to WDI to set Preferred Network List.Offload @@ -11481,7 +12469,8 @@ VOS_STATUS WDA_ProcessSetRssiFilterReq(tWDA_CbContext *pWDA, return VOS_STATUS_E_NOMEM; } pwdiSetRssiFilterReqInfo->rssiThreshold = pRssiFilterParams->rssiThreshold; - pwdiSetRssiFilterReqInfo->wdiReqStatusCB = NULL; + pwdiSetRssiFilterReqInfo->wdiReqStatusCB = WDA_RssiFilterReqCallback; + pwdiSetRssiFilterReqInfo->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiSetRssiFilterReqInfo; @@ -11489,7 +12478,7 @@ VOS_STATUS WDA_ProcessSetRssiFilterReq(tWDA_CbContext *pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pRssiFilterParams; status = WDI_SetRssiFilterReq( pwdiSetRssiFilterReqInfo, - (WDI_PNOScanCb)WDA_RssiFilterCallback, + (WDI_PNOScanCb)WDA_RssiFilterRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -11583,7 +12572,8 @@ VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, pUpdateScanParams->aChannels[i]; } - wdiUpdateScanParamsInfoType->wdiReqStatusCB = NULL; + wdiUpdateScanParamsInfoType->wdiReqStatusCB = WDA_UpdateScanParamsReqCallback; + wdiUpdateScanParamsInfoType->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = wdiUpdateScanParamsInfoType; @@ -11594,7 +12584,7 @@ VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, status = WDI_UpdateScanParamsReq(wdiUpdateScanParamsInfoType, - (WDI_UpdateScanParamsCb)WDA_UpdateScanParamsCallback, + (WDI_UpdateScanParamsCb)WDA_UpdateScanParamsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -11607,11 +12597,46 @@ VOS_STATUS WDA_ProcessUpdateScanParams(tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } #endif // FEATURE_WLAN_SCAN_PNO + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/* + * FUNCTION: WDA_RoamOffloadScanReqCallback + * + */ +void WDA_RoamOffloadScanReqCallback(WDI_Status status, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s " ,__func__); + if (NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0) ; + return ; + } + if ( pWdaParams != NULL ) + { + if ( pWdaParams->wdaWdiApiMsgParam != NULL ) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + } + if ( pWdaParams->wdaMsgParam != NULL) + { + vos_mem_free(pWdaParams->wdaMsgParam); + } + + vos_mem_free(pWdaParams) ; + } + return ; +} +#endif + /* - * FUNCTION: WDA_SetPowerParamsCallback + * FUNCTION: WDA_SetPowerParamsRespCallback * */ -void WDA_SetPowerParamsCallback(WDI_Status status, void* pUserData) +void WDA_SetPowerParamsRespCallback(WDI_Status status, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -11625,27 +12650,49 @@ void WDA_SetPowerParamsCallback(WDI_Status status, void* pUserData) VOS_ASSERT(0); return; } - if( pWdaParams != NULL ) + + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + + return; +} +/* + * FUNCTION: WDA_SetPowerParamsReqCallback + * Free memory. + * Invoked when SetPowerParams REQ failed in WDI and no RSP callback is generated. + */ +void WDA_SetPowerParamsReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) { - if( pWdaParams->wdaWdiApiMsgParam != NULL ) - { - vos_mem_free(pWdaParams->wdaWdiApiMsgParam); - } - if( pWdaParams->wdaMsgParam != NULL) - { - vos_mem_free(pWdaParams->wdaMsgParam); - } + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); vos_mem_free(pWdaParams); } + return; } #ifdef WLAN_FEATURE_PACKET_FILTERING /* - * FUNCTION: WDA_8023MulticastListReqCallback + * FUNCTION: WDA_8023MulticastListRespCallback * */ -void WDA_8023MulticastListReqCallback( +void WDA_8023MulticastListRespCallback( WDI_RcvFltPktSetMcListRspParamsType *pwdiRcvFltPktSetMcListRspInfo, void * pUserData) { @@ -11665,9 +12712,38 @@ void WDA_8023MulticastListReqCallback( vos_mem_free(pWdaParams) ; //print a msg, nothing else to do VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, - "WDA_8023MulticastListReqCallback invoked " ); + "WDA_8023MulticastListRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_8023MulticastListReqCallback + * Free memory. + * Invoked when 8023MulticastList REQ failed in WDI and no RSP callback is generated. + */ +void WDA_8023MulticastListReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_Process8023MulticastListReq * Request to WDI to add 8023 Multicast List @@ -11717,7 +12793,8 @@ VOS_STATUS WDA_Process8023MulticastListReq (tWDA_CbContext *pWDA, &(pRcvFltMcAddrList->multicastAddr[i]), sizeof(tSirMacAddr)); } - pwdiFltPktSetMcListReqParamsType->wdiReqStatusCB = NULL; + pwdiFltPktSetMcListReqParamsType->wdiReqStatusCB = WDA_8023MulticastListReqCallback; + pwdiFltPktSetMcListReqParamsType->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiFltPktSetMcListReqParamsType; @@ -11726,7 +12803,7 @@ VOS_STATUS WDA_Process8023MulticastListReq (tWDA_CbContext *pWDA, pWdaParams->wdaMsgParam = pRcvFltMcAddrList; status = WDI_8023MulticastListReq( pwdiFltPktSetMcListReqParamsType, - (WDI_8023MulticastListCb)WDA_8023MulticastListReqCallback, + (WDI_8023MulticastListCb)WDA_8023MulticastListRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -11768,10 +12845,11 @@ void WDA_ReceiveFilterSetFilterRespCallback( } /* - * FUNCTION: WDA_ReqCallback - * + * FUNCTION: WDA_ReceiveFilterSetFilterReqCallback + * Free memory. + * Invoked when ReceiveFilterSetFilter REQ failed in WDI and no RSP callback is generated. */ -void WDA_ReqCallback(WDI_Status wdiStatus, +void WDA_ReceiveFilterSetFilterReqCallback(WDI_Status wdiStatus, void* pUserData) { tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; @@ -11892,7 +12970,7 @@ VOS_STATUS WDA_ProcessReceiveFilterSetFilterReq (tWDA_CbContext *pWDA, pwdiSetRcvPktFilterReqParamsType-> wdiPktFilterCfg.paramsData[i].dataMask[5]); } - pwdiSetRcvPktFilterReqParamsType->wdiReqStatusCB = WDA_ReqCallback; + pwdiSetRcvPktFilterReqParamsType->wdiReqStatusCB = WDA_ReceiveFilterSetFilterReqCallback; pwdiSetRcvPktFilterReqParamsType->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiSetRcvPktFilterReqParamsType; @@ -11913,10 +12991,10 @@ VOS_STATUS WDA_ProcessReceiveFilterSetFilterReq (tWDA_CbContext *pWDA, return CONVERT_WDI2VOS_STATUS(status) ; } /* - * FUNCTION: WDA_FilterMatchCountReqCallback + * FUNCTION: WDA_FilterMatchCountRespCallback * */ -void WDA_FilterMatchCountReqCallback( +void WDA_FilterMatchCountRespCallback( WDI_RcvFltPktMatchCntRspParamsType *pwdiRcvFltPktMatchRspParams, void * pUserData) { @@ -11978,6 +13056,44 @@ void WDA_FilterMatchCountReqCallback( vos_mem_free(pWdaParams->wdaMsgParam) ; vos_mem_free(pWdaParams->wdaWdiApiMsgParam); vos_mem_free(pWdaParams) ; + + return; +} +/* + * FUNCTION: WDA_FilterMatchCountReqCallback + * Free memory and send RSP back to SME. + * Invoked when FilterMatchCount REQ failed in WDI and no RSP callback is generated. + */ +void WDA_FilterMatchCountReqCallback(WDI_Status wdiStatus, void * pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + vos_msg_t vosMsg; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: pWdaParams received NULL", __func__); + VOS_ASSERT(0); + return; + } + + /* VOS message wrapper */ + vosMsg.type = eWNI_PMC_PACKET_COALESCING_FILTER_MATCH_COUNT_RSP; + vosMsg.bodyptr = NULL; + vosMsg.bodyval = 0; + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + vos_mq_post_message(VOS_MQ_ID_SME, (vos_msg_t*)&vosMsg); + } + + return; } /* * FUNCTION: WDA_ProcessPacketFilterMatchCountReq @@ -12008,7 +13124,8 @@ VOS_STATUS WDA_ProcessPacketFilterMatchCountReq (tWDA_CbContext *pWDA, tpSirRcvF return VOS_STATUS_E_NOMEM; } - pwdiRcvFltPktMatchCntReqParamsType->wdiReqStatusCB = NULL; + pwdiRcvFltPktMatchCntReqParamsType->wdiReqStatusCB = WDA_FilterMatchCountReqCallback; + pwdiRcvFltPktMatchCntReqParamsType->pUserData = pWdaParams; vos_mem_copy( pwdiRcvFltPktMatchCntReqParamsType->bssId, pRcvFltPktMatchRsp->bssId, @@ -12020,7 +13137,7 @@ VOS_STATUS WDA_ProcessPacketFilterMatchCountReq (tWDA_CbContext *pWDA, tpSirRcvF /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pRcvFltPktMatchRsp; status = WDI_FilterMatchCountReq(pwdiRcvFltPktMatchCntReqParamsType, - (WDI_FilterMatchCountCb)WDA_FilterMatchCountReqCallback, + (WDI_FilterMatchCountCb)WDA_FilterMatchCountRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -12062,6 +13179,35 @@ void WDA_ReceiveFilterClearFilterRespCallback( "WDA_ReceiveFilterClearFilterRespCallback invoked " ); return ; } +/* + * FUNCTION: WDA_ReceiveFilterClearFilterReqCallback + * Free memory. + * Invoked when ReceiveFilterClearFilter REQ failed in WDI and no RSP callback is generated. + */ +void WDA_ReceiveFilterClearFilterReqCallback(WDI_Status wdiStatus, void* pUserData) +{ + tWDA_ReqParams *pWdaParams = (tWDA_ReqParams *)pUserData; + + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_INFO, + "<------ %s, wdiStatus: %d", __func__, wdiStatus); + + if(NULL == pWdaParams) + { + VOS_TRACE( VOS_MODULE_ID_WDA, VOS_TRACE_LEVEL_ERROR, + "%s: Invalid pWdaParams pointer", __func__); + VOS_ASSERT(0); + return; + } + + if(IS_WDI_STATUS_FAILURE(wdiStatus)) + { + vos_mem_free(pWdaParams->wdaWdiApiMsgParam); + vos_mem_free(pWdaParams->wdaMsgParam); + vos_mem_free(pWdaParams); + } + + return; +} /* * FUNCTION: WDA_ProcessReceiveFilterClearFilterReq * Request to WDI to clear Receive Filters @@ -12098,7 +13244,7 @@ VOS_STATUS WDA_ProcessReceiveFilterClearFilterReq (tWDA_CbContext *pWDA, vos_mem_copy(pwdiRcvFltPktClearReqParamsType->filterClearParam.bssId, pRcvFltPktClearParam->bssId, sizeof(wpt_macAddr)); - pwdiRcvFltPktClearReqParamsType->wdiReqStatusCB = WDA_ReqCallback; + pwdiRcvFltPktClearReqParamsType->wdiReqStatusCB = WDA_ReceiveFilterClearFilterReqCallback; pwdiRcvFltPktClearReqParamsType->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiRcvFltPktClearReqParamsType; @@ -12163,7 +13309,10 @@ VOS_STATUS WDA_ProcessSetPowerParamsReq(tWDA_CbContext *pWDA, pPowerParams->uEnableBET; pwdiSetPowerParamsReqInfo->wdiSetPowerParamsInfo.uBETInterval = pPowerParams->uBETInterval; - pwdiSetPowerParamsReqInfo->wdiReqStatusCB = NULL; + pwdiSetPowerParamsReqInfo->wdiSetPowerParamsInfo.uMaxLIModulatedDTIM = + pPowerParams->uMaxLIModulatedDTIM; + pwdiSetPowerParamsReqInfo->wdiReqStatusCB = WDA_SetPowerParamsReqCallback; + pwdiSetPowerParamsReqInfo->pUserData = pWdaParams; /* Store Params pass it to WDI */ pWdaParams->wdaWdiApiMsgParam = (void *)pwdiSetPowerParamsReqInfo; @@ -12171,7 +13320,7 @@ VOS_STATUS WDA_ProcessSetPowerParamsReq(tWDA_CbContext *pWDA, /* Store param pointer as passed in by caller */ pWdaParams->wdaMsgParam = pPowerParams; status = WDI_SetPowerParamsReq( pwdiSetPowerParamsReqInfo, - (WDI_SetPowerParamsCb)WDA_SetPowerParamsCallback, + (WDI_SetPowerParamsCb)WDA_SetPowerParamsRespCallback, pWdaParams); if(IS_WDI_STATUS_FAILURE(status)) { @@ -12563,3 +13712,21 @@ void WDA_TransportChannelDebug WDI_TransportChannelDebug(displaySnapshot, toggleStallDetect); return; } + +/*========================================================================== + FUNCTION WDA_SetEnableSSR + + DESCRIPTION + API to enable/disable SSR on WDI timeout + + PARAMETERS + enableSSR : enable/disable SSR + + RETURN VALUE + NONE + +===========================================================================*/ +void WDA_SetEnableSSR(v_BOOL_t enableSSR) +{ + WDI_SetEnableSSR(enableSSR); +} diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h index 84000536256..1706a9af62c 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi.h @@ -510,9 +510,11 @@ typedef struct typedef struct { /* Network that was found with the highest RSSI*/ - WDI_MacSSid ssId; + WDI_MacSSid ssId; /* Indicates the RSSI */ - wpt_uint8 rssi; + wpt_uint8 rssi; + wpt_uint16 frameLength; + wpt_uint8 *pData; } WDI_PrefNetworkFoundInd; #endif // FEATURE_WLAN_SCAN_PNO @@ -3059,6 +3061,9 @@ typedef struct /*Self Station MAC address*/ wpt_macAddr selfMacAddr; + /*Self STA device mode*/ + wpt_uint32 currDeviceMode; + /*Status of the operation*/ wpt_uint32 uStatus; }WDI_AddSTASelfInfoType; @@ -3520,6 +3525,7 @@ typedef struct wpt_uint8 srcIPv6AddrValid : 1; wpt_uint8 targetIPv6Addr1Valid : 1; wpt_uint8 targetIPv6Addr2Valid : 1; + wpt_uint8 slotIdx; } WDI_NSOffloadParams; #endif //WLAN_NS_OFFLOAD @@ -4084,23 +4090,6 @@ typedef struct void* pUserData; }WDI_TrafficStatsIndType; -#ifdef WLAN_FEATURE_11W -typedef struct -{ - - wpt_boolean bExcludeUnencrypt; - wpt_macAddr bssid; - /*Request status callback offered by UMAC - it is called if the current - req has returned PENDING as status; it delivers the status of sending - the message over the BUS */ - WDI_ReqStatusCb wdiReqStatusCB; - - /*The user data passed in by UMAC, it will be sent back when the above - function pointer will be called */ - void* pUserData; -}WDI_ExcludeUnencryptIndType; -#endif - /*--------------------------------------------------------------------------- WDI_WlanResumeInfoType ---------------------------------------------------------------------------*/ @@ -4259,6 +4248,11 @@ typedef struct #define WDI_PNO_MAX_PROBE_SIZE 450 +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define WDI_ROAM_SCAN_MAX_CHANNELS 80 /* NUM_RF_CHANNELS */ +#define WDI_ROAM_SCAN_MAX_PROBE_SIZE 450 +#define WDI_ROAM_SCAN_RESERVED_BYTES 61 +#endif /*--------------------------------------------------------------------------- WDI_AuthType @@ -4349,7 +4343,7 @@ typedef struct wpt_uint8 ucChannelCount; /*the actual channels*/ - wpt_uint8 aChannels[WDI_PNO_MAX_NETW_CHANNELS]; + wpt_uint8 aChannels[WDI_PNO_MAX_NETW_CHANNELS_EX]; /*rssi threshold that a network must meet to be considered, 0 - for any*/ wpt_uint8 rssiThreshold; @@ -4426,6 +4420,88 @@ typedef struct void* pUserData; } WDI_PNOScanReqParamsType; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + +typedef struct +{ + /*The SSID of the preferred network*/ + WDI_MacSSid ssId; + wpt_uint8 currAPbssid[WDI_MAC_ADDR_LEN]; + + /*The authentication method of the preferred network*/ + WDI_AuthType authentication; + + /*The encryption method of the preferred network*/ + WDI_EdType encryption; + WDI_EdType mcencryption; + + /*SSID broadcast type, normal, hidden or unknown*/ + //WDI_SSIDBcastType wdiBcastNetworkType; + + /*channel count - 0 for all channels*/ + wpt_uint8 ChannelCount; + + /*the actual channels*/ + wpt_uint8 ChannelCache[WDI_ROAM_SCAN_MAX_CHANNELS]; + +} WDI_RoamNetworkType; + +typedef struct WDIMobilityDomainInfo +{ + wpt_uint8 mdiePresent; + wpt_uint16 mobilityDomain; +} WDI_MobilityDomainInfo; + +/*--------------------------------------------------------------------------- + WDI_RoamOffloadScanInfo +---------------------------------------------------------------------------*/ +typedef struct +{ + wpt_boolean RoamScanOffloadEnabled; + wpt_uint8 LookupThreshold; + wpt_uint8 RoamRssiDiff; + wpt_uint8 ChannelCacheType; + wpt_uint8 Command; + wpt_uint8 StartScanReason; + wpt_uint16 NeighborScanTimerPeriod; + wpt_uint16 NeighborRoamScanRefreshPeriod; + wpt_uint16 NeighborScanChannelMinTime; + wpt_uint16 NeighborScanChannelMaxTime; + wpt_uint16 EmptyRefreshScanPeriod; + wpt_uint8 ValidChannelCount; + wpt_uint8 ValidChannelList[WDI_ROAM_SCAN_MAX_CHANNELS]; + wpt_boolean IsCCXEnabled; + /*Probe template for 2.4GHz band*/ + wpt_uint16 us24GProbeSize; + wpt_uint8 a24GProbeTemplate[WDI_ROAM_SCAN_MAX_PROBE_SIZE]; + + /*Probe template for 5GHz band*/ + wpt_uint16 us5GProbeSize; + wpt_uint8 a5GProbeTemplate[WDI_ROAM_SCAN_MAX_PROBE_SIZE]; + /*LFR BG Scan will currently look for only one network to which it is initially connected. + * As per requirement, later, the following structure can be used as an array of networks.*/ + WDI_RoamNetworkType ConnectedNetwork; + WDI_MobilityDomainInfo MDID; + wpt_uint8 nProbes; + wpt_uint16 HomeAwayTime; + wpt_uint8 ReservedBytes[WDI_ROAM_SCAN_RESERVED_BYTES]; +} WDI_RoamOffloadScanInfo; + +typedef struct +{ + /* Start Roam Candidate Lookup Offload Back Ground Info Type */ + WDI_RoamOffloadScanInfo wdiRoamOffloadScanInfo; + /* Request status callback offered by UMAC - it is called if the current req + has returned PENDING as status; it delivers the status of sending the message + over the BUS */ + WDI_ReqStatusCb wdiReqStatusCB; + /* The user data passed in by UMAC, it will be sent back when the above + function pointer will be called */ + void* pUserData; +} WDI_RoamScanOffloadReqParamsType; + +#endif + /*--------------------------------------------------------------------------- WDI_SetRssiFilterReqParamsType PNO info passed to WDI form WDA @@ -4517,6 +4593,9 @@ typedef struct /* Beacon Early Termination Interval */ wpt_uint32 uBETInterval; + /* MAX LI for modulated DTIM */ + wpt_uint32 uMaxLIModulatedDTIM; + } WDI_SetPowerParamsInfo; /*--------------------------------------------------------------------------- @@ -6334,6 +6413,30 @@ typedef void (*WDI_UpdateScanParamsCb)(WDI_Status wdiStatus, void* pUserData); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/*--------------------------------------------------------------------------- + WDI_RoamOffloadScanCb + + DESCRIPTION + + This callback is invoked by DAL when it has received a Start Roam Candidate Lookup Req + response from the underlying device. + + PARAMETERS + + IN + wdiStatus: response status received from HAL + pUserData: user data + + + + RETURN VALUE + The result code associated with performing the operation +---------------------------------------------------------------------------*/ +typedef void (*WDI_RoamOffloadScanCb)(WDI_Status wdiStatus, + void* pUserData); + +#endif /*--------------------------------------------------------------------------- WDI_SetTxPerTrackingRspCb @@ -8912,24 +9015,6 @@ WDI_TrafficStatsInd WDI_TrafficStatsIndType *pWdiTrafficStatsIndParams ); -#ifdef WLAN_FEATURE_11W -/** - @brief WDI_ExcludeUnencryptedInd - Register with HAL to receive/drop unencrypted frames - - @param WDI_ExcludeUnencryptIndType - - @see - - @return Status of the request -*/ -WDI_Status -WDI_ExcludeUnencryptedInd -( - WDI_ExcludeUnencryptIndType *pWdiExcUnencParams -); -#endif - #ifdef FEATURE_WLAN_SCAN_PNO /** @brief WDI_SetPreferredNetworkList @@ -9004,6 +9089,31 @@ WDI_UpdateScanParamsReq ); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + @brief WDI_RoamScanOffloadReq + + @param pwdiRoamScanOffloadReqParams: Start Roam Candidate Lookup Req as specified + by the Device Interface + + wdiRoamOffloadScanCb: callback for passing back the response + of the Start Roam Candidate Lookup operation received from the + device + + pUserData: user data will be passed back with the + callback + + @return Result of the function call +*/ +WDI_Status +WDI_RoamScanOffloadReq +( + WDI_RoamScanOffloadReqParamsType *pwdiRoamScanOffloadReqParams, + WDI_RoamOffloadScanCb wdiRoamOffloadScancb, + void* pUserData +); +#endif + /** @brief WDI_SetTxPerTrackingReq will be called when the upper MAC wants to set the Tx Per Tracking configurations. @@ -9399,6 +9509,17 @@ WDI_SsrTimerCB void *pUserData ); +/** + @brief WDI_SetEnableSSR - + This API is called to enable/disable SSR on WDI timeout. + + @param enableSSR : enable/disable SSR + + @see + @return none +*/ +void WDI_SetEnableSSR(wpt_boolean enableSSR); + #ifdef __cplusplus } #endif diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h index 22b2a421e08..10aef2a62ae 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_bd.h @@ -309,38 +309,51 @@ typedef struct /* 0x10 */ #ifdef WPT_BIG_BYTE_ENDIAN - - /** This is the length (in number of bytes) of the entire MPDU + + /** This is the length (in number of bytes) of the entire MPDU (header and data). Note that the length does not include FCS field. */ wpt_uint32 mpduLength:16; - + +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + wpt_uint32 offloadScanLearn:1; + wpt_uint32 roamCandidateInd:1; +#else + wpt_uint32 reserved22:2; +#endif + #ifdef WCN_PRONTO - wpt_uint32 reserved3: 3; - wpt_uint32 rxDXEPriorityRouting:1; + wpt_uint32 reserved3: 1; + wpt_uint32 rxDXEPriorityRouting:1; #else - wpt_uint32 reserved3:4; + wpt_uint32 reserved3:2; #endif //WCN_PRONTO - - + + /** Traffic Identifier Indicates the traffic class the frame belongs to. For non QoS frames, this field is set to zero. */ wpt_uint32 tid:4; - + wpt_uint32 reserved4:8; #else wpt_uint32 reserved4:8; wpt_uint32 tid:4; #ifdef WCN_PRONTO - wpt_uint32 rxDXEPriorityRouting:1; - wpt_uint32 reserved3: 3; + wpt_uint32 rxDXEPriorityRouting:1; + wpt_uint32 reserved3: 1; #else - wpt_uint32 reserved3:4; + wpt_uint32 reserved3:2; #endif //WCN_PRONTO - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + wpt_uint32 roamCandidateInd:1; + wpt_uint32 offloadScanLearn:1; +#else + wpt_uint32 reserved22:2; +#endif + wpt_uint32 mpduLength:16; #endif - + /* 0x14 */ #ifdef WPT_BIG_BYTE_ENDIAN diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h index 646ab576dd4..5472bbdc52b 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_dp.h @@ -299,6 +299,11 @@ when who what, where, why #define WDI_RX_FC_BD_GET_FC( _pvBDHeader ) (((WDI_FcRxBdType*)_pvBDHeader)->fc) #define WDI_RX_FC_BD_GET_STA_VALID_MASK( _pvBDHeader ) (((WDI_FcRxBdType*)_pvBDHeader)->fcSTAValidMask) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +//LFR scan related +#define WDI_RX_BD_GET_OFFLOADSCANLEARN( _pvBDHeader ) (((WDI_RxBdType*)_pvBDHeader)->offloadScanLearn) +#define WDI_RX_BD_GET_ROAMCANDIDATEIND( _pvBDHeader ) (((WDI_RxBdType*)_pvBDHeader)->roamCandidateInd) +#endif /*------------ RSSI and SNR Information extraction -------------*/ #define WDI_RX_BD_GET_RSSI0( _pvBDHeader ) \ @@ -346,10 +351,6 @@ when who what, where, why #define WDI_RX_BD_GET_PMICMD_24TO25(_pvBDHeader) (((WDI_RxBdType*)_pvBDHeader)->pmiCmd24to25) -#ifdef WLAN_FEATURE_11W -#define WDI_RX_BD_GET_RMF( _pvBDHeader ) (((WDI_RxBdType*)_pvBDHeader)->rmf) -#endif - #define WDI_RX_BD_ASF_SET 1 /*The value of the field when set and pkt is AMSDU*/ #define WDI_RX_BD_FSF_SET 1 diff --git a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h index e2fab24c62d..1acf6cb6edb 100644 --- a/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h +++ b/drivers/staging/prima/CORE/WDI/CP/inc/wlan_qct_wdi_i.h @@ -444,7 +444,7 @@ typedef enum /*WLAN DAL Set Tx Power Request*/ WDI_SET_TX_POWER_REQ = 82, - + WDI_ROAM_SCAN_OFFLOAD_REQ = 83, WDI_MAX_REQ, /*Send a suspend Indication down to HAL*/ @@ -453,9 +453,6 @@ typedef enum /* Send a traffic stats indication to HAL */ WDI_TRAFFIC_STATS_IND, - /* Drop/Receive unencrypted frames indication to HAL */ - WDI_EXCLUDE_UNENCRYPTED_IND, - /*Keep adding the indications to the max request such that we keep them sepparate */ @@ -710,7 +707,7 @@ typedef enum WDI_GET_ROAM_RSSI_RESP = 80, WDI_SET_TX_POWER_RESP = 81, - + WDI_ROAM_SCAN_OFFLOAD_RESP = 82, /*------------------------------------------------------------------------- Indications !! Keep these last in the enum if possible @@ -1088,6 +1085,9 @@ typedef struct /*timestamp when we get response timer event*/ wpt_uint32 uTimeStampRspTmrExp; + + /* enable/disable SSR on WDI timeout */ + wpt_boolean bEnableSSR; }WDI_ControlBlockType; @@ -2729,26 +2729,6 @@ WDI_ProcessTrafficStatsInd WDI_ControlBlockType* pWDICtx, WDI_EventInfoType* pEventData ); - -#ifdef WLAN_FEATURE_11W -/** - @brief Process Exclude Unencrypted Indications function (called - when Main FSM allows it) - - @param pWDICtx: pointer to the WLAN DAL context - pEventData: pointer to the event information structure - - @see - @return Result of the function call -*/ -WDI_Status -WDI_ProcessExcludeUnencryptInd -( - WDI_ControlBlockType* pWDICtx, - WDI_EventInfoType* pEventData -); -#endif - /*======================================================================== Main DAL Control Path Response Processing API ========================================================================*/ @@ -4866,6 +4846,40 @@ WDI_ProcessUpdateScanParamsRsp ); #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + @brief Process Start Roam Candidate Lookup Request function + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @see + @return Result of the function call +*/ +WDI_Status +WDI_ProcessRoamScanOffloadReq +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +); +/** + @brief Process Start Roam Candidate Lookup Response function (called when a + response is being received over the bus from HAL) + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @see + @return Result of the function call +*/ +WDI_Status +WDI_ProcessRoamScanOffloadRsp +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +); +#endif + #ifdef WLAN_FEATURE_PACKET_FILTERING /** @brief Process 8023 Multicast List Request function @@ -5119,6 +5133,23 @@ WDI_ProcessUpdateVHTOpModeRsp WDI_EventInfoType* pEventData ); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + * @brief WDI_wdiEdTypeEncToEdTypeEnc - + * The firmware expects the Encryption type to be in EdType. + * This function converts the WdiEdType encryption to EdType. + * @param tEdType : EdType to which the encryption needs to be converted. + * @param WDI_EdType : wdiEdType passed from the upper layer. + * @see + * @return none + * */ +void +WDI_wdiEdTypeEncToEdTypeEnc +( + tEdType *EdType, + WDI_EdType wdiEdType +); +#endif #endif /*WLAN_QCT_WDI_I_H*/ diff --git a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c index ab41e2dff2e..df0a01f6d20 100644 --- a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c +++ b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi.c @@ -112,7 +112,7 @@ #define MAC_ADDR_ARRAY(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] #define MAC_ADDRESS_STR "%02x:%02x:%02x:%02x:%02x:%02x" -#define FEATURE_NOT_SUPPORTED 128 +#define FEATURE_NOT_SUPPORTED 127 #ifdef FEATURE_WLAN_SCAN_PNO #define WDI_PNO_VERSION_MASK 0x8000 @@ -142,6 +142,11 @@ static placeHolderInCapBitmap supportEnabledFeatures[] = ,WLANACTIVE_OFFLOAD #else ,FEATURE_NOT_SUPPORTED +#endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + ,WLAN_ROAM_SCAN_OFFLOAD +#else + ,FEATURE_NOT_SUPPORTED #endif }; @@ -349,16 +354,16 @@ WDI_ReqProcFuncType pfnReqProcTbl[WDI_MAX_UMAC_IND] = NULL, #endif WDI_ProcessSetTxPowerReq, /* WDI_SET_TX_POWER_REQ*/ +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + WDI_ProcessRoamScanOffloadReq, /* WDI_ROAM_SCAN_OFFLOAD_REQ */ +#else + NULL, +#endif /* WLAN_FEATURE_ROAM_SCAN_OFFLOAD */ /*------------------------------------------------------------------------- Indications -------------------------------------------------------------------------*/ WDI_ProcessHostSuspendInd, /* WDI_HOST_SUSPEND_IND*/ WDI_ProcessTrafficStatsInd, /* WDI_TRAFFIC_STATS_IND*/ -#ifdef WLAN_FEATURE_11W - WDI_ProcessExcludeUnencryptInd, /* WDI_EXCLUDE_UNENCRYPTED_IND */ -#else - NULL, -#endif }; @@ -527,7 +532,11 @@ WDI_RspProcFuncType pfnRspProcTbl[WDI_MAX_RESP] = NULL, #endif WDI_ProcessSetTxPowerRsp, /* WDI_SET_TX_POWER_RESP */ - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + WDI_ProcessRoamScanOffloadRsp, /* WDI_ROAM_SCAN_OFFLOAD_RESP */ +#else + NULL, +#endif /*--------------------------------------------------------------------- Indications ---------------------------------------------------------------------*/ @@ -848,6 +857,9 @@ static char *WDI_getReqMsgString(wpt_uint16 wdiReqMsgId) CASE_RETURN_STRING( WDI_SET_RSSI_FILTER_REQ ); CASE_RETURN_STRING( WDI_UPDATE_SCAN_PARAMS_REQ ); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + CASE_RETURN_STRING( WDI_ROAM_SCAN_OFFLOAD_REQ ); +#endif CASE_RETURN_STRING( WDI_SET_TX_PER_TRACKING_REQ ); CASE_RETURN_STRING( WDI_8023_MULTICAST_LIST_REQ ); CASE_RETURN_STRING( WDI_RECEIVE_FILTER_SET_FILTER_REQ ); @@ -859,9 +871,6 @@ static char *WDI_getReqMsgString(wpt_uint16 wdiReqMsgId) CASE_RETURN_STRING( WDI_SET_POWER_PARAMS_REQ ); CASE_RETURN_STRING( WDI_TRAFFIC_STATS_IND ); CASE_RETURN_STRING( WDI_GET_ROAM_RSSI_REQ ); -#ifdef WLAN_FEATURE_11W - CASE_RETURN_STRING( WDI_EXCLUDE_UNENCRYPTED_IND ); -#endif default: return "Unknown WDI MessageId"; } @@ -949,6 +958,9 @@ static char *WDI_getRespMsgString(wpt_uint16 wdiRespMsgId) CASE_RETURN_STRING( WDI_SET_RSSI_FILTER_RESP ); CASE_RETURN_STRING( WDI_UPDATE_SCAN_PARAMS_RESP ); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + CASE_RETURN_STRING( WDI_ROAM_SCAN_OFFLOAD_RESP ); +#endif CASE_RETURN_STRING( WDI_SET_TX_PER_TRACKING_RESP ); CASE_RETURN_STRING( WDI_8023_MULTICAST_LIST_RESP ); CASE_RETURN_STRING( WDI_RECEIVE_FILTER_SET_FILTER_RESP ); @@ -5715,52 +5727,6 @@ WDI_TrafficStatsInd }/*WDI_TrafficStatsInd*/ -#ifdef WLAN_FEATURE_11W -/** - @brief WDI_ExcludeUnencryptedInd - Register with HAL to receive/drop unencrypted frames - - @param WDI_ExcludeUnencryptIndType - - @see - - @return Status of the request -*/ -WDI_Status -WDI_ExcludeUnencryptedInd -( - WDI_ExcludeUnencryptIndType *pWdiExcUnencParams -) -{ - - WDI_EventInfoType wdiEventData; - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - /*------------------------------------------------------------------------ - Sanity Check - ------------------------------------------------------------------------*/ - if ( eWLAN_PAL_FALSE == gWDIInitialized ) - { - WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, - "WDI API call before module is initialized - Fail request"); - - return WDI_STATUS_E_NOT_ALLOWED; - } - - /*------------------------------------------------------------------------ - Fill in Event data and post to the Main FSM - ------------------------------------------------------------------------*/ - wdiEventData.wdiRequest = WDI_EXCLUDE_UNENCRYPTED_IND; - wdiEventData.pEventData = pWdiExcUnencParams; - wdiEventData.uEventDataSize = sizeof(*pWdiExcUnencParams); - wdiEventData.pCBfnc = NULL; - wdiEventData.pUserData = NULL; - - return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); - -}/*WDI_TrafficStatsInd*/ -#endif - /** @brief WDI_HALDumpCmdReq Post HAL DUMP Command Event @@ -10049,7 +10015,7 @@ WDI_ProcessAddSTASelfReq wpt_uint8* pSendBuffer = NULL; wpt_uint16 usDataOffset = 0; wpt_uint16 usSendSize = 0; - tAddStaSelfParams halAddSTASelfParams; + tAddStaSelfParams_V1 halAddSTASelfParams; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /*------------------------------------------------------------------------- @@ -10074,9 +10040,9 @@ WDI_ProcessAddSTASelfReq -----------------------------------------------------------------------*/ if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, WDI_ADD_STA_SELF_REQ, - sizeof(tAddStaSelfParams), + sizeof(tAddStaSelfParams_V1), &pSendBuffer, &usDataOffset, &usSendSize))|| - ( usSendSize < (usDataOffset + sizeof(tAddStaSelfParams) ))) + ( usSendSize < (usDataOffset + sizeof(tAddStaSelfParams_V1) ))) { WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, "Unable to get send buffer in ADD STA SELF REQ %x %x %x", @@ -10090,10 +10056,22 @@ WDI_ProcessAddSTASelfReq sizeof(pWDICtx->wdiCacheAddSTASelfReq)); wpalMemoryCopy(halAddSTASelfParams.selfMacAddr, - pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.selfMacAddr, 6) ; + pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.selfMacAddr, 6); + halAddSTASelfParams.iface_persona = HAL_IFACE_UNKNOWN; + if (pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.currDeviceMode == VOS_STA_MODE) + { + halAddSTASelfParams.iface_persona = HAL_IFACE_STA_MODE; + } + else if ((pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.currDeviceMode == + VOS_P2P_CLIENT_MODE) || + (pwdiAddSTASelfReqParams->wdiAddSTASelfInfo.currDeviceMode == + VOS_P2P_DEVICE)) + { + halAddSTASelfParams.iface_persona = HAL_IFACE_P2P_MODE; + } wpalMemoryCopy( pSendBuffer+usDataOffset, &halAddSTASelfParams, - sizeof(tAddStaSelfParams)); + sizeof(tAddStaSelfParams_V1)); pWDICtx->wdiReqStatusCB = pwdiAddSTASelfReqParams->wdiReqStatusCB; pWDICtx->pReqStatusUserData = pwdiAddSTASelfReqParams->pUserData; @@ -10565,78 +10543,6 @@ WDI_ProcessTrafficStatsInd return ( wdiStatus != WDI_STATUS_SUCCESS )?wdiStatus:WDI_STATUS_SUCCESS_SYNC; }/*WDI_ProcessTrafficStatsInd*/ -#ifdef WLAN_FEATURE_11W -/** - @brief Process Exclude Unencrypted Indications function (called - when Main FSM allows it) - - @param pWDICtx: pointer to the WLAN DAL context - pEventData: pointer to the event information structure - - @see - @return Result of the function call -*/ -WDI_Status -WDI_ProcessExcludeUnencryptInd -( - WDI_ControlBlockType* pWDICtx, - WDI_EventInfoType* pEventData -) -{ - WDI_ExcludeUnencryptIndType* pWDIExcUnencIndParams; - wpt_uint8* pSendBuffer = NULL; - wpt_uint16 usDataOffset = 0; - wpt_uint16 usSendSize = 0; - WDI_Status wdiStatus; - tHalWlanExcludeUnEncryptedIndParam* pHalExcUnencIndParams; - /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - - /*------------------------------------------------------------------------- - Sanity check - -------------------------------------------------------------------------*/ - if (( NULL == pEventData ) || ( NULL == pEventData->pEventData )) - { - WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, - "%s: Invalid parameters in Exclude Unencrypted ind",__func__); - WDI_ASSERT(0); - return WDI_STATUS_E_FAILURE; - } - - pWDIExcUnencIndParams = (WDI_ExcludeUnencryptIndType *)pEventData->pEventData; - - /*----------------------------------------------------------------------- - Get message buffer - -----------------------------------------------------------------------*/ - if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, - WDI_EXCLUDE_UNENCRYPTED_IND, - sizeof(tHalWlanExcludeUnEncryptedIndParam), - &pSendBuffer, &usDataOffset, &usSendSize))|| - (usSendSize < (usDataOffset + sizeof(tHalWlanExcludeUnEncryptedIndParam)))) - { - WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, - "Unable to get send buffer in Exclude Unencrypted Ind "); - WDI_ASSERT(0); - return WDI_STATUS_E_FAILURE; - } - - pHalExcUnencIndParams = (tHalWlanExcludeUnEncryptedIndParam*)(pSendBuffer+usDataOffset); - - pHalExcUnencIndParams->bDot11ExcludeUnencrypted = pWDIExcUnencIndParams->bExcludeUnencrypt; - - wpalMemoryCopy(pHalExcUnencIndParams->bssId, - pWDIExcUnencIndParams->bssid, WDI_MAC_ADDR_LEN); - - /*------------------------------------------------------------------------- - Send Suspend Request to HAL - -------------------------------------------------------------------------*/ - pWDICtx->wdiReqStatusCB = pWDIExcUnencIndParams->wdiReqStatusCB; - pWDICtx->pReqStatusUserData = pWDIExcUnencIndParams->pUserData; - - wdiStatus = WDI_SendIndication( pWDICtx, pSendBuffer, usSendSize); - return ( wdiStatus != WDI_STATUS_SUCCESS )?wdiStatus:WDI_STATUS_SUCCESS_SYNC; -}/*WDI_ProcessExcludeUnencryptInd*/ -#endif - /*========================================================================== MISC CONTROL PROCESSING REQUEST API ==========================================================================*/ @@ -13274,7 +13180,8 @@ WDI_ProcessHostOffloadReq if ( NULL == pBSSSes ) { WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, - " %s : Association for this BSSID does not exist",__func__); + " %s : Association for this BSSID does not exist " MAC_ADDRESS_STR, + __func__, MAC_ADDR_ARRAY(pwdiHostOffloadParams->wdiHostOffloadInfo.bssId)); goto fail; } @@ -13312,9 +13219,17 @@ WDI_ProcessHostOffloadReq wpalMemoryCopy(nsOffloadParams.selfMacAddr, pwdiHostOffloadParams->wdiNsOffloadParams.selfMacAddr, 6); - nsOffloadParams.srcIPv6AddrValid = pwdiHostOffloadParams->wdiNsOffloadParams.srcIPv6AddrValid; - nsOffloadParams.targetIPv6Addr1Valid = pwdiHostOffloadParams->wdiNsOffloadParams.targetIPv6Addr1Valid; - nsOffloadParams.targetIPv6Addr2Valid = pwdiHostOffloadParams->wdiNsOffloadParams.targetIPv6Addr2Valid; + nsOffloadParams.srcIPv6AddrValid = + pwdiHostOffloadParams->wdiNsOffloadParams.srcIPv6AddrValid; + + nsOffloadParams.targetIPv6Addr1Valid = + pwdiHostOffloadParams->wdiNsOffloadParams.targetIPv6Addr1Valid; + + nsOffloadParams.targetIPv6Addr2Valid = + pwdiHostOffloadParams->wdiNsOffloadParams.targetIPv6Addr2Valid; + + nsOffloadParams.slotIndex = + pwdiHostOffloadParams->wdiNsOffloadParams.slotIdx; #endif // WLAN_NS_OFFLOAD } @@ -17642,6 +17557,10 @@ WDI_ProcessExitImpsRsp halStatus = *((eHalStatus*)pEventData->pEventData); wdiStatus = WDI_HAL_2_WDI_STATUS(halStatus); + if (halStatus != eHAL_STATUS_SUCCESS) + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "%s: Exit IMPS response is a failure with halStatus %d", __func__, halStatus); + // notify DTS that we are entering Full power wptStatus = WDTS_SetPowerState(pWDICtx, WDTS_POWER_STATE_FULL, NULL); if( eWLAN_PAL_STATUS_SUCCESS != wptStatus ) @@ -19780,7 +19699,7 @@ WDI_ProcessHALDumpCmdRsp wpalMemoryCopy( wdiHALDumpCmdRsp.pBuffer, &halDumpCmdRspParams.rspBuffer, - sizeof(wdiHALDumpCmdRsp.usBufferLen)); + halDumpCmdRspParams.rspLength); } /*Notify UMAC*/ @@ -20363,9 +20282,9 @@ WDI_ResponseTimerCB WDI_ControlBlockType* pWDICtx = (WDI_ControlBlockType*)pUserData; /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ - if (NULL == pWDICtx ) + if (NULL == pWDICtx) { - WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, "%s: Invalid parameters", __func__); WDI_ASSERT(0); return; @@ -20388,33 +20307,41 @@ WDI_ResponseTimerCB return; } - if ( WDI_MAX_RESP != pWDICtx->wdiExpectedResponse ) + if (WDI_MAX_RESP != pWDICtx->wdiExpectedResponse) { - WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, "Timeout occurred while waiting for %s (%d) message from device " " - catastrophic failure, timeStampTmrStart: %ld, timeStampTmrExp: %ld", WDI_getRespMsgString(pWDICtx->wdiExpectedResponse), pWDICtx->wdiExpectedResponse, pWDICtx->uTimeStampRspTmrStart, pWDICtx->uTimeStampRspTmrExp); - /* WDI timeout means Riva is not responding or SMD communication to Riva - * is not happening. The only possible way to recover from this error - * is to initiate SSR from APPS - * There is also an option to re-enable wifi, which will eventually - * trigger SSR - */ + + /* WDI timeout means Riva is not responding or SMD communication to Riva + * is not happening. The only possible way to recover from this error + * is to initiate SSR from APPS. + * There is also an option to re-enable wifi, which will eventually + * trigger SSR + */ + if (gWDICb.bEnableSSR == false) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, + "SSR is not enabled on WDI timeout"); + WDI_DetectedDeviceError(pWDICtx, WDI_ERR_BASIC_OP_FAILURE); + return; + } #ifndef WDI_RE_ENABLE_WIFI_ON_WDI_TIMEOUT - wpalWcnssResetIntr(); - /* if this timer fires, it means Riva did not receive the FIQ */ - wpalTimerStart(&pWDICtx->ssrTimer, WDI_SSR_TIMEOUT); + wpalWcnssResetIntr(); + /* if this timer fires, it means Riva did not receive the FIQ */ + wpalTimerStart(&pWDICtx->ssrTimer, WDI_SSR_TIMEOUT); #else - WDI_DetectedDeviceError( pWDICtx, WDI_ERR_BASIC_OP_FAILURE); - wpalWlanReload(); + WDI_DetectedDeviceError(pWDICtx, WDI_ERR_BASIC_OP_FAILURE); + wpalWlanReload(); #endif } else { - WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, "Timeout occurred but not waiting for any response %d " "timeStampTmrStart: %ld, timeStampTmrExp: %ld", pWDICtx->wdiExpectedResponse, pWDICtx->uTimeStampRspTmrStart, @@ -21744,13 +21671,12 @@ WDI_2_HAL_REQ_TYPE return WLAN_HAL_HOST_SUSPEND_IND; case WDI_TRAFFIC_STATS_IND: return WLAN_HAL_CLASS_B_STATS_IND; -#ifdef WLAN_FEATURE_11W - case WDI_EXCLUDE_UNENCRYPTED_IND: - return WLAN_HAL_EXCLUDE_UNENCRYPTED_IND; -#endif case WDI_KEEP_ALIVE_REQ: return WLAN_HAL_KEEP_ALIVE_REQ; - +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case WDI_ROAM_SCAN_OFFLOAD_REQ: + return WLAN_ROAM_SCAN_OFFLOAD_REQ; +#endif #ifdef FEATURE_WLAN_SCAN_PNO case WDI_SET_PREF_NETWORK_REQ: return WLAN_HAL_SET_PREF_NETWORK_REQ; @@ -21974,6 +21900,10 @@ case WLAN_HAL_DEL_STA_SELF_RSP: case WLAN_HAL_PREF_NETW_FOUND_IND: return WDI_HAL_PREF_NETWORK_FOUND_IND; #endif // FEATURE_WLAN_SCAN_PNO +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + case WLAN_ROAM_SCAN_OFFLOAD_RSP: + return WDI_ROAM_SCAN_OFFLOAD_RESP; +#endif case WLAN_HAL_SET_TX_PER_TRACKING_RSP: return WDI_SET_TX_PER_TRACKING_RESP; #ifdef WLAN_FEATURE_PACKET_FILTERING @@ -22062,8 +21992,8 @@ WDI_2_HAL_STOP_REASON { case WDI_STOP_TYPE_SYS_RESET: return HAL_STOP_TYPE_SYS_RESET; - case WDI_DRIVER_TYPE_MFG: - return WDI_STOP_TYPE_SYS_DEEP_SLEEP; + case WDI_STOP_TYPE_SYS_DEEP_SLEEP: + return HAL_STOP_TYPE_SYS_DEEP_SLEEP; case WDI_STOP_TYPE_RF_KILL: return HAL_STOP_TYPE_RF_KILL; } @@ -22907,6 +22837,14 @@ WDI_ExtractRequestCBFromEvent *ppfnReqCB = ((WDI_EnterUapsdReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_EnterUapsdReqParamsType*)pEvent->pEventData)->pUserData; break; + case WDI_EXIT_UAPSD_REQ: + *ppfnReqCB = ((WDI_ExitUapsdReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_ExitUapsdReqParamsType*)pEvent->pEventData)->pUserData; + break; + case WDI_SET_UAPSD_PARAM_REQ: + *ppfnReqCB = ((WDI_SetUapsdAcParamsReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_SetUapsdAcParamsReqParamsType*)pEvent->pEventData)->pUserData; + break; case WDI_UPDATE_UAPSD_PARAM_REQ: *ppfnReqCB = ((WDI_UpdateUapsdReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_UpdateUapsdReqParamsType*)pEvent->pEventData)->pUserData; @@ -22943,6 +22881,10 @@ WDI_ExtractRequestCBFromEvent *ppfnReqCB = ((WDI_WowlEnterReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_WowlEnterReqParamsType*)pEvent->pEventData)->pUserData; break; + case WDI_WOWL_EXIT_REQ: + *ppfnReqCB = ((WDI_WowlExitReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_WowlExitReqParamsType*)pEvent->pEventData)->pUserData; + break; case WDI_CONFIGURE_APPS_CPU_WAKEUP_STATE_REQ: *ppfnReqCB = ((WDI_ConfigureAppsCpuWakeupStateReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_ConfigureAppsCpuWakeupStateReqParamsType*)pEvent->pEventData)->pUserData; @@ -22959,10 +22901,29 @@ WDI_ExtractRequestCBFromEvent *ppfnReqCB = ((WDI_KeepAliveReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_KeepAliveReqParamsType*)pEvent->pEventData)->pUserData; break; +#if defined FEATURE_WLAN_SCAN_PNO + case WDI_SET_PREF_NETWORK_REQ: + *ppfnReqCB = ((WDI_PNOScanReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_PNOScanReqParamsType*)pEvent->pEventData)->pUserData; + break; + case WDI_SET_RSSI_FILTER_REQ: + *ppfnReqCB = ((WDI_SetRssiFilterReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_SetRssiFilterReqParamsType*)pEvent->pEventData)->pUserData; + break; + case WDI_UPDATE_SCAN_PARAMS_REQ: + *ppfnReqCB = ((WDI_UpdateScanParamsInfoType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_UpdateScanParamsInfoType*)pEvent->pEventData)->pUserData; + break; +#endif case WDI_SET_TX_PER_TRACKING_REQ: *ppfnReqCB = ((WDI_SetTxPerTrackingReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_SetTxPerTrackingReqParamsType*)pEvent->pEventData)->pUserData; break; +#if defined WLAN_FEATURE_PACKET_FILTERING + case WDI_8023_MULTICAST_LIST_REQ: + *ppfnReqCB = ((WDI_RcvFltPktSetMcListReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_RcvFltPktSetMcListReqParamsType*)pEvent->pEventData)->pUserData; + break; case WDI_RECEIVE_FILTER_SET_FILTER_REQ: *ppfnReqCB = ((WDI_SetRcvPktFilterReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_SetRcvPktFilterReqParamsType*)pEvent->pEventData)->pUserData; @@ -22975,6 +22936,21 @@ WDI_ExtractRequestCBFromEvent *ppfnReqCB = ((WDI_RcvFltPktClearReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; *ppUserData = ((WDI_RcvFltPktClearReqParamsType*)pEvent->pEventData)->pUserData; break; +#endif + case WDI_SET_POWER_PARAMS_REQ: + *ppfnReqCB = ((WDI_SetPowerParamsReqParamsType*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_SetPowerParamsReqParamsType*)pEvent->pEventData)->pUserData; + break; +#if defined WLAN_FEATURE_GTK_OFFLOAD + case WDI_GTK_OFFLOAD_REQ: + *ppfnReqCB = ((WDI_GtkOffloadReqMsg*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_GtkOffloadReqMsg*)pEvent->pEventData)->pUserData; + break; + case WDI_GTK_OFFLOAD_GETINFO_REQ: + *ppfnReqCB = ((WDI_GtkOffloadGetInfoReqMsg*)pEvent->pEventData)->wdiReqStatusCB; + *ppUserData = ((WDI_GtkOffloadGetInfoReqMsg*)pEvent->pEventData)->pUserData; + break; +#endif default: *ppfnReqCB = NULL; @@ -23624,7 +23600,338 @@ WDI_ProcessSetRssiFilterReq return WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize, wdiRssiFilterCb, pEventData->pUserData, WDI_SET_RSSI_FILTER_RESP); } +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +/** + @brief WDI_RoamScanOffloadReq + + @param pwdiRoamScanOffloadReqParams: the LookupReq as specified + by the Device Interface + + wdiRoamOffloadScancb: callback for passing back the response + of the Roam Candidate Lookup Req operation received from the + device + + pUserData: user data will be passed back with the + callback + @return Result of the function call +*/ +WDI_Status +WDI_RoamScanOffloadReq +( + WDI_RoamScanOffloadReqParamsType* pwdiRoamScanOffloadReqParams, + WDI_RoamOffloadScanCb wdiRoamOffloadScancb, + void* pUserData +) +{ + WDI_EventInfoType wdiEventData = {{0}}; + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + /*------------------------------------------------------------------------ + Sanity Check + ------------------------------------------------------------------------*/ + if ( eWLAN_PAL_FALSE == gWDIInitialized ) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "WDI API call before module is initialized - Fail request"); + + return WDI_STATUS_E_NOT_ALLOWED; + } + + /*------------------------------------------------------------------------ + Fill in Event data and post to the Main FSM + ------------------------------------------------------------------------*/ + wdiEventData.wdiRequest = WDI_ROAM_SCAN_OFFLOAD_REQ; + wdiEventData.pEventData = pwdiRoamScanOffloadReqParams; + wdiEventData.uEventDataSize = sizeof(*pwdiRoamScanOffloadReqParams); + wdiEventData.pCBfnc = wdiRoamOffloadScancb; + wdiEventData.pUserData = pUserData; + + return WDI_PostMainEvent(&gWDICb, WDI_REQUEST_EVENT, &wdiEventData); +} + +void +WDI_wdiEdTypeEncToEdTypeEnc(tEdType *EdType, WDI_EdType wdiEdType) +{ + switch (wdiEdType) + { + case WDI_ED_NONE: + *EdType = eED_NONE; + break; + case WDI_ED_WEP40: + case WDI_ED_WEP104: + *EdType = eED_WEP; + break; + case WDI_ED_TKIP: + *EdType = eED_TKIP; + break; + case WDI_ED_CCMP: +#ifdef WLAN_FEATURE_11W + case WDI_ED_AES_128_CMAC: +#endif + *EdType = eED_CCMP; + break; +#ifdef FEATURE_WLAN_WAPI + case WDI_ED_WPI: + *EdType = eED_WPI; + break; +#endif + case WDI_ED_ANY: + *EdType = eED_ANY; + break; + + default: + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Unknown Encryption Type", __func__); + break; + } +} + +/** + @brief Helper function to pack Start Roam Candidate Lookup + Request parameters + + @param pWDICtx: pointer to the WLAN DAL context + pwdiRoamScanOffloadReqParams: pointer to the info received + from upper layers + ppSendBuffer, pSize - out pointers of the packed buffer + and its size + + @return Result of the function call +*/ + +WDI_Status +WDI_PackRoamScanOffloadParams +( + WDI_ControlBlockType* pWDICtx, + WDI_RoamScanOffloadReqParamsType* pwdiRoamScanOffloadReqParams, + wpt_uint8** ppSendBuffer, + wpt_uint16* pSize +) +{ + wpt_uint8* pSendBuffer = NULL; + wpt_uint16 usDataOffset = 0; + wpt_uint16 usSendSize = 0; + tpRoamCandidateListParams pRoamCandidateListParams = NULL; + wpt_uint8 i; + /*----------------------------------------------------------------------- + Get message buffer + -----------------------------------------------------------------------*/ + if (( WDI_STATUS_SUCCESS != WDI_GetMessageBuffer( pWDICtx, WDI_ROAM_SCAN_OFFLOAD_REQ, + sizeof(tRoamCandidateListParams), + &pSendBuffer, &usDataOffset, &usSendSize))|| + ( usSendSize < (usDataOffset + sizeof(tpRoamCandidateListParams) ))) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "Unable to get send buffer in Start Roam Candidate Lookup Req %x ", + pwdiRoamScanOffloadReqParams); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + pRoamCandidateListParams = (tpRoamCandidateListParams)(pSendBuffer + usDataOffset); + wpalMemoryZero(pRoamCandidateListParams, sizeof(tpRoamCandidateListParams)); + pRoamCandidateListParams->RoamScanOffloadEnabled = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.RoamScanOffloadEnabled; + wpalMemoryCopy(pRoamCandidateListParams->ConnectedNetwork.currAPbssid, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.currAPbssid, + HAL_MAC_ADDR_LEN); + pRoamCandidateListParams->ConnectedNetwork.authentication = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.authentication; + WDI_wdiEdTypeEncToEdTypeEnc(&pRoamCandidateListParams->ConnectedNetwork.encryption, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.encryption); + WDI_wdiEdTypeEncToEdTypeEnc(&pRoamCandidateListParams->ConnectedNetwork.mcencryption, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.mcencryption); + + pRoamCandidateListParams->ConnectedNetwork.ssId.length + = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ssId.ucLength; + wpalMemoryCopy( pRoamCandidateListParams->ConnectedNetwork.ssId.ssId, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ssId.sSSID, + pRoamCandidateListParams->ConnectedNetwork.ssId.length); + wpalMemoryCopy(pRoamCandidateListParams->ConnectedNetwork.ChannelCache, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCache, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCount ); + pRoamCandidateListParams->ConnectedNetwork.ChannelCount = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ConnectedNetwork.ChannelCount; + pRoamCandidateListParams->ChannelCacheType = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ChannelCacheType ; + pRoamCandidateListParams->LookupThreshold = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.LookupThreshold; + pRoamCandidateListParams->RoamRssiDiff = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.RoamRssiDiff ; + pRoamCandidateListParams->Command = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.Command ; + pRoamCandidateListParams->StartScanReason = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.StartScanReason ; + pRoamCandidateListParams->NeighborScanTimerPeriod = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.NeighborScanTimerPeriod ; + pRoamCandidateListParams->NeighborRoamScanRefreshPeriod = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.NeighborRoamScanRefreshPeriod ; + pRoamCandidateListParams->NeighborScanChannelMinTime = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.NeighborScanChannelMinTime ; + pRoamCandidateListParams->NeighborScanChannelMaxTime = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.NeighborScanChannelMaxTime ; + pRoamCandidateListParams->EmptyRefreshScanPeriod = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.EmptyRefreshScanPeriod ; + pRoamCandidateListParams->IsCCXEnabled = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.IsCCXEnabled ; + wpalMemoryCopy(pRoamCandidateListParams->ValidChannelList, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelList, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelCount); + pRoamCandidateListParams->ValidChannelCount = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.ValidChannelCount; + + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH, + "Values are ssid = %s, RoamOffloadScan=%d,Command=%d," + "StartScanReason=%d,NeighborScanTimerPeriod=%d," + "NeighborRoamScanRefreshPeriod=%d,NeighborScanChannelMinTime=%d," + "NeighborScanChannelMaxTime = %d,EmptyRefreshScanPeriod=%d," + "mdiePresent=%d,MDID=%d, auth=%d, uce=%d, mce=%d, nProbes=%d," + "HomeAwayTime=%d\n", + pRoamCandidateListParams->ConnectedNetwork.ssId.ssId, + pRoamCandidateListParams->RoamScanOffloadEnabled, + pRoamCandidateListParams->Command, + pRoamCandidateListParams->StartScanReason, + pRoamCandidateListParams->NeighborScanTimerPeriod, + pRoamCandidateListParams->NeighborRoamScanRefreshPeriod, + pRoamCandidateListParams->NeighborScanChannelMinTime, + pRoamCandidateListParams->NeighborScanChannelMaxTime, + pRoamCandidateListParams->EmptyRefreshScanPeriod, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.MDID.mdiePresent, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.MDID.mobilityDomain, + pRoamCandidateListParams->ConnectedNetwork.authentication, + pRoamCandidateListParams->ConnectedNetwork.encryption, + pRoamCandidateListParams->ConnectedNetwork.mcencryption, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.nProbes, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.HomeAwayTime); + pRoamCandidateListParams->us24GProbeSize = + (pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us24GProbeSize< + WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE)? + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us24GProbeSize: + WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE; + wpalMemoryCopy(pRoamCandidateListParams->a24GProbeTemplate, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.a24GProbeTemplate, + pRoamCandidateListParams->us24GProbeSize); + pRoamCandidateListParams->us5GProbeSize = + (pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us5GProbeSize< + WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE)? + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.us5GProbeSize: + WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE; + wpalMemoryCopy(pRoamCandidateListParams->a5GProbeTemplate, + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.a5GProbeTemplate, + pRoamCandidateListParams->us5GProbeSize); + pRoamCandidateListParams->MDID.mdiePresent = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.MDID.mdiePresent; + pRoamCandidateListParams->MDID.mobilityDomain = pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.MDID.mobilityDomain; + pRoamCandidateListParams->nProbes = + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.nProbes; + pRoamCandidateListParams->HomeAwayTime = + pwdiRoamScanOffloadReqParams->wdiRoamOffloadScanInfo.HomeAwayTime; + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH,"Valid Channel List"); + for (i=0; iValidChannelCount ; i++) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO_HIGH,"%d", pRoamCandidateListParams->ValidChannelList[i]); + } + + + /*Set the output values*/ + *ppSendBuffer = pSendBuffer; + *pSize = usSendSize; + return WDI_STATUS_SUCCESS; +}/*WDI_PackRoamScanOffloadParams*/ + +/** + @brief Process Start Roam Candidate Lookup Request function + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @return Result of the function call +*/ +WDI_Status +WDI_ProcessRoamScanOffloadReq +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +) +{ + WDI_RoamScanOffloadReqParamsType* pwdiRoamScanOffloadReqParams = NULL; + WDI_RoamOffloadScanCb wdiRoamOffloadScancb = NULL; + wpt_uint8* pSendBuffer = NULL; + wpt_uint16 usSendSize = 0; + WDI_Status wdiStatus; + /*------------------------------------------------------------------------- + Sanity check + -------------------------------------------------------------------------*/ + if (( NULL == pEventData ) || + ( NULL == (pwdiRoamScanOffloadReqParams = (WDI_RoamScanOffloadReqParamsType*)pEventData->pEventData)) || + ( NULL == (wdiRoamOffloadScancb = (WDI_RoamOffloadScanCb)pEventData->pCBfnc))) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + + /*------------------------------------------------------------------------- + Pack the Start Roam Candidate Lookup request structure based on version + -------------------------------------------------------------------------*/ + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_INFO, + "%s: Packing Roam Candidate Lookup request ", __func__); + + wdiStatus = WDI_PackRoamScanOffloadParams( pWDICtx, pwdiRoamScanOffloadReqParams, + &pSendBuffer, &usSendSize); + + if (( WDI_STATUS_SUCCESS != wdiStatus )|| + ( NULL == pSendBuffer )||( 0 == usSendSize )) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: failed to pack request parameters", __func__); + WDI_ASSERT(0); + return wdiStatus; + } + + pWDICtx->wdiReqStatusCB = pwdiRoamScanOffloadReqParams->wdiReqStatusCB; + pWDICtx->pReqStatusUserData = pwdiRoamScanOffloadReqParams->pUserData; + + /*------------------------------------------------------------------------- + Send WDI_ROAM_SCAN_OFFLOAD_REQ to HAL + -------------------------------------------------------------------------*/ + return WDI_SendMsg( pWDICtx, pSendBuffer, usSendSize, + wdiRoamOffloadScancb, pEventData->pUserData, WDI_ROAM_SCAN_OFFLOAD_RESP); +} + +/** + @brief Process Start Roam Candidate Lookup Rsp function (called when a + response is being received over the bus from HAL) + + @param pWDICtx: pointer to the WLAN DAL context + pEventData: pointer to the event information structure + + @see + @return Result of the function call +*/ +WDI_Status +WDI_ProcessRoamScanOffloadRsp +( + WDI_ControlBlockType* pWDICtx, + WDI_EventInfoType* pEventData +) +{ + WDI_Status wdiStatus; + eHalStatus halStatus; + WDI_RoamOffloadScanCb wdiRoamOffloadScancb = NULL; + + /*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + /*------------------------------------------------------------------------- + Sanity check + -------------------------------------------------------------------------*/ + if (( NULL == pWDICtx ) || ( NULL == pEventData ) || + ( NULL == pEventData->pEventData )) + { + WPAL_TRACE(eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_WARN, + "%s: Invalid parameters", __func__); + WDI_ASSERT(0); + return WDI_STATUS_E_FAILURE; + } + wdiRoamOffloadScancb = (WDI_RoamOffloadScanCb)pWDICtx->pfncRspCB; + + /*------------------------------------------------------------------------- + Extract response and send it to UMAC + -------------------------------------------------------------------------*/ + halStatus = *((eHalStatus*)pEventData->pEventData); + wdiStatus = WDI_HAL_2_WDI_STATUS(halStatus); + + /*Notify UMAC*/ + wdiRoamOffloadScancb(wdiStatus, pWDICtx->pRspCBUserData); + + return WDI_STATUS_SUCCESS; +}/* WDI_ProcessRoamScanOffloadRsp */ +#endif /** @brief Process Update Scan Params function @@ -23867,8 +24174,9 @@ WDI_ProcessPrefNetworkFoundInd WDI_EventInfoType* pEventData ) { - WDI_LowLevelIndType wdiInd; - tPrefNetwFoundInd prefNetwFoundInd = {{0}}; + WDI_LowLevelIndType wdiInd; + tpPrefNetwFoundParams pNetwFoundParams; + wpt_uint32 msgsize; /*------------------------------------------------------------------------- @@ -23886,25 +24194,34 @@ WDI_ProcessPrefNetworkFoundInd /*------------------------------------------------------------------------- Extract indication and send it to UMAC -------------------------------------------------------------------------*/ - wpalMemoryCopy( (void *)&prefNetwFoundInd.prefNetwFoundParams, - pEventData->pEventData, - sizeof(tPrefNetwFoundParams)); + pNetwFoundParams = (tpPrefNetwFoundParams)(pEventData->pEventData); - /*Fill in the indication parameters*/ - wdiInd.wdiIndicationType = WDI_PREF_NETWORK_FOUND_IND; + msgsize = sizeof(tPrefNetwFoundParams) + pNetwFoundParams->frameLength; + wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.pData = + (wpt_uint8 *)wpalMemoryAllocate(msgsize); - wpalMemoryZero(wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.sSSID,32); + if (NULL == wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.pData) + { + WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "%s: fail to allocate memory", __func__); + return WDI_STATUS_MEM_FAILURE; + } wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.ucLength = - (prefNetwFoundInd.prefNetwFoundParams.ssId.length < 31 )? - prefNetwFoundInd.prefNetwFoundParams.ssId.length : 31; - + (pNetwFoundParams->ssId.length < 32 )? + pNetwFoundParams->ssId.length : 32; wpalMemoryCopy( wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.sSSID, - prefNetwFoundInd.prefNetwFoundParams.ssId.ssId, - wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.ucLength); + pNetwFoundParams->ssId.ssId, + wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.ssId.ucLength); + wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.rssi = pNetwFoundParams->rssi; + wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.frameLength = + pNetwFoundParams->frameLength; + wpalMemoryCopy( wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.pData, + (wpt_uint8 *)pEventData->pEventData + sizeof(tPrefNetwFoundParams), + pNetwFoundParams->frameLength); - wdiInd.wdiIndicationData.wdiPrefNetworkFoundInd.rssi = - prefNetwFoundInd.prefNetwFoundParams.rssi; + /*Fill in the indication parameters*/ + wdiInd.wdiIndicationType = WDI_PREF_NETWORK_FOUND_IND; // DEBUG WPAL_TRACE( eWLAN_MODULE_DAL_CTRL, eWLAN_PAL_TRACE_LEVEL_FATAL, @@ -24319,6 +24636,7 @@ WDI_Process8023MulticastListReq "WDI_Process8023MulticastListReq() %x %x %x", pEventData, pwdiFltPktSetMcListReqParamsType, wdi8023MulticastListCb); + wpalMemoryFree(pRcvFltMcAddrListType); WDI_ASSERT(0); return WDI_STATUS_E_FAILURE; } @@ -25243,6 +25561,9 @@ WDI_ProcessSetPowerParamsReq powerParams.uBETInterval = pwdiPowerParamsReqParams->wdiSetPowerParamsInfo.uBETInterval; + /* MAX LI for modulated DTIM */ + powerParams.uMaxLIModulatedDTIM = + pwdiPowerParamsReqParams->wdiSetPowerParamsInfo.uMaxLIModulatedDTIM; wpalMemoryCopy( pSendBuffer+usDataOffset, &powerParams, @@ -26478,3 +26799,17 @@ WDI_SsrTimerCB return; }/*WDI_SsrTimerCB*/ + +/** + @brief WDI_SetEnableSSR - + This API is called to enable/disable SSR on WDI timeout. + + @param enableSSR : enable/disable SSR + + @see + @return none +*/ +void WDI_SetEnableSSR(wpt_boolean enableSSR) +{ + gWDICb.bEnableSSR = enableSSR; +} diff --git a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c index 04b9db084b3..7cc3571c5f7 100644 --- a/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c +++ b/drivers/staging/prima/CORE/WDI/CP/src/wlan_qct_wdi_dp.c @@ -607,13 +607,21 @@ WDI_FillTxBd * Sanity: Force HW frame translation OFF for mgmt frames. --------------------------------------------------------------------*/ /* apply to both ucast/mcast mgmt frames */ - if (useStaRateForBcastFrames) + /* Probe requests are sent using BD rate */ + if( ucSubType == WDI_MAC_MGMT_PROBE_REQ ) { - pBd->bdRate = (ucUnicastDst)? WDI_BDRATE_BCMGMT_FRAME : WDI_TXBD_BDRATE_DEFAULT; + pBd->bdRate = WDI_BDRATE_BCMGMT_FRAME; } else { - pBd->bdRate = WDI_BDRATE_BCMGMT_FRAME; + if (useStaRateForBcastFrames) + { + pBd->bdRate = (ucUnicastDst)? WDI_BDRATE_BCMGMT_FRAME : WDI_TXBD_BDRATE_DEFAULT; + } + else + { + pBd->bdRate = WDI_BDRATE_BCMGMT_FRAME; + } } if ( ucTxFlag & WDI_USE_BD_RATE2_FOR_MANAGEMENT_FRAME) @@ -677,8 +685,6 @@ WDI_FillTxBd if (WDI_STATUS_SUCCESS != wdiStatus) { WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "WDI_STATableFindStaidByAddr failed"); - WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, "STA ID = %d " MAC_ADDRESS_STR, - ucStaId, MAC_ADDR_ARRAY(*(wpt_macAddr*)pAddr2)); return WDI_STATUS_E_NOT_ALLOWED; } #else @@ -844,25 +850,7 @@ WDI_FillTxBd if(!ucUnicastDst) pBd->dpuDescIdx = pSta->bcastMgmtDpuIndex; /* IGTK */ else - { - wpt_uint8 peerStaId; - - //We need to find the peer's station's DPU index to send this - //frame using PTK - wdiStatus = WDI_STATableFindStaidByAddr( pWDICtx, - *(wpt_macAddr*)pDestMacAddr, &peerStaId ); - if (WDI_STATUS_SUCCESS != wdiStatus) - { - WPAL_TRACE(eWLAN_MODULE_DAL_DATA, eWLAN_PAL_TRACE_LEVEL_ERROR, - "%s failed to find peer sta %02X-%02X-%02X-%02X-%02X-%02X", - __FUNCTION__, ((wpt_uint8 *)pDestMacAddr)[0], - ((wpt_uint8 *)pDestMacAddr)[1], ((wpt_uint8 *)pDestMacAddr)[5], - ((wpt_uint8 *)pDestMacAddr)[3], ((wpt_uint8 *)pDestMacAddr)[4], - ((wpt_uint8 *)pDestMacAddr)[5]); - return WDI_STATUS_E_FAILURE; - } - pBd->dpuDescIdx = ((WDI_StaStruct*)pWDICtx->staTable)[peerStaId].dpuIndex; /* PTK */ - } + pBd->dpuDescIdx = pSta->dpuIndex; /* PTK */ } else { diff --git a/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h b/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h index c23d2cb6230..53cc6cd7915 100644 --- a/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h +++ b/drivers/staging/prima/CORE/WDI/DP/inc/wlan_qct_wdi_ds.h @@ -166,6 +166,10 @@ typedef struct #ifdef WLAN_FEATURE_11W wpt_uint32 rmf:1; #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + wpt_uint32 offloadScanLearn; + wpt_uint32 roamCandidateInd; +#endif } WDI_DS_RxMetaInfoType; typedef struct sPktMetaInfo diff --git a/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c b/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c index 1c9b4e7ef5a..e6ff98fabaf 100644 --- a/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c +++ b/drivers/staging/prima/CORE/WDI/TRP/DTS/src/wlan_qct_wdi_dts.c @@ -614,6 +614,10 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c #ifdef WLAN_FEATURE_11W pRxMetadata->rmf = WDI_RX_BD_GET_RMF(pBDHeader); #endif +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD + pRxMetadata->offloadScanLearn = WDI_RX_BD_GET_OFFLOADSCANLEARN(pBDHeader); + pRxMetadata->roamCandidateInd = WDI_RX_BD_GET_ROAMCANDIDATEIND(pBDHeader); +#endif /* typeSubtype in BD doesn't look like correct. Fill from frame ctrl TL does it for Volans but TL does not know BD for Prima. WDI should do it */ @@ -690,6 +694,7 @@ wpt_status WDTS_RxPacket (void *pContext, wpt_packet *pFrame, WDTS_ChannelType c pRxMetadata = WDI_DS_ExtractRxMetaData(pFrame); //flow control related pRxMetadata->fc = isFcBd; + pRxMetadata->mclkRxTimestamp = WDI_RX_BD_GET_TIMESTAMP(pBDHeader); pRxMetadata->fcStaTxDisabledBitmap = WDI_RX_FC_BD_GET_STA_TX_DISABLED_BITMAP(pBDHeader); pRxMetadata->fcSTAValidMask = WDI_RX_FC_BD_GET_STA_VALID_MASK(pBDHeader); // Invoke Rx complete callback diff --git a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_os_trace.h b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_os_trace.h index 13c274cac6f..2af6fc2eab9 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_os_trace.h +++ b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_os_trace.h @@ -1,44 +1,23 @@ /* - * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ -/* - * Copyright (c) 2012, The Linux Foundation. All rights reserved. - * - * Previously licensed under the ISC license by Qualcomm Atheros, Inc. - * - * - * Permission to use, copy, modify, and/or distribute this software for - * any purpose with or without fee is hereby granted, provided that the - * above copyright notice and this permission notice appear in all - * copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL - * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE - * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - + * Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. + * + * Previously licensed under the ISC license by Qualcomm Atheros, Inc. + * + * + * Permission to use, copy, modify, and/or distribute this software for + * any purpose with or without fee is hereby granted, provided that the + * above copyright notice and this permission notice appear in all + * copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. +*/ #if !defined( __WLAN_QCT_OS_TRACE_H ) #define __WLAN_QCT_OS_TRACE_H @@ -96,9 +75,6 @@ void wpalTrace( wpt_moduleid module, wpt_tracelevel level, char *strFormat, ... void wpalDump( wpt_moduleid module, wpt_tracelevel level, wpt_uint8 *memory, wpt_uint32 length); -#define WPAL_TRACE wpalTrace -#define WPAL_DUMP wpalDump - #define WPAL_ASSERT( _condition ) do { \ if ( ! ( _condition ) ) \ { \ @@ -108,10 +84,18 @@ void wpalDump( wpt_moduleid module, wpt_tracelevel level, } while (0) #else //WLAN_DEBUG -#define WPAL_TRACE -#define WPAL_DUMP -#define WPAL_ASSERT +static inline void wpalTrace( wpt_moduleid module, wpt_tracelevel level, + char *strFormat, ... ){}; +static inline void wpalDump( wpt_moduleid module, wpt_tracelevel level, + wpt_uint8 *memory, wpt_uint32 length) {}; +static inline void wpalTraceSetLevel( wpt_moduleid module, + wpt_tracelevel level, wpt_boolean on ) {}; +static inline void wpalTraceDisplay(void) {}; +#define WPAL_ASSERT(x) do {} while (0); #endif //WLAN_DEBUG +#define WPAL_TRACE wpalTrace +#define WPAL_DUMP wpalDump + #endif // __WLAN_QCT_OS_TRACE_H diff --git a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h index 8c09035a262..46d548495b9 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h +++ b/drivers/staging/prima/CORE/WDI/WPAL/inc/wlan_qct_pal_packet.h @@ -39,6 +39,7 @@ * PERFORMANCE OF THIS SOFTWARE. */ + #if !defined( __WLAN_QCT_PAL_PACKET_H ) #define __WLAN_QCT_PAL_PACKET_H @@ -50,10 +51,6 @@ Definitions for platform independent. - Copyright 2010 (c) Qualcomm, Incorporated. All Rights Reserved. - - Qualcomm Confidential and Proprietary. - ========================================================================*/ #include "wlan_qct_pal_type.h" @@ -329,4 +326,14 @@ wpt_int32 wpalPacketGetFragCount(wpt_packet *pPkt); ---------------------------------------------------------------------------*/ wpt_status wpalIsPacketLocked( wpt_packet *pPacket); +/*--------------------------------------------------------------------------- + wpalGetNumRxRawPacket Query available RX RAW total buffer count + param: + numRxResource pointer of queried value + + return: + eWLAN_PAL_STATUS_SUCCESS +---------------------------------------------------------------------------*/ +wpt_status wpalGetNumRxRawPacket(wpt_uint32 *numRxResource); + #endif // __WLAN_QCT_PAL_PACKET_H diff --git a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_packet.c b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_packet.c index 1f13c6338af..43cbde7c09e 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_packet.c +++ b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_packet.c @@ -184,13 +184,16 @@ wpt_packet * wpalPacketAlloc(wpt_packet_type pktType, wpt_uint32 nPktSize, wpalPacketAvailableCB = rxLowCB; } #endif /* FEATURE_R33D */ - vos_pkt_get_packet_length(pVosPkt, &allocLen); - if (nPktSize != allocLen) + if((NULL != pVosPkt) && (VOS_STATUS_E_RESOURCES != vosStatus)) { - WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, - "RX packet alloc has problem, discard this frame, Len %d", allocLen); - vos_pkt_return_packet(pVosPkt); - return NULL; + vos_pkt_get_packet_length(pVosPkt, &allocLen); + if (nPktSize != allocLen) + { + WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, + "RX packet alloc has problem, discard this frame, Len %d", allocLen); + vos_pkt_return_packet(pVosPkt); + return NULL; + } } break; @@ -794,7 +797,7 @@ wpt_status wpalIsPacketLocked( wpt_packet *pPacket) /* Validate the parameter pointers */ if (NULL == pPacket) { - WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_ERROR, + WPAL_TRACE(eWLAN_MODULE_PAL, eWLAN_PAL_TRACE_LEVEL_WARN, "%s : NULL input pointer", __func__); return eWLAN_PAL_STATUS_E_INVAL; } @@ -805,3 +808,17 @@ wpt_status wpalIsPacketLocked( wpt_packet *pPacket) eWLAN_PAL_STATUS_SUCCESS; }/*wpalIsPacketLocked*/ +/*--------------------------------------------------------------------------- + wpalGetNumRxRawPacket Query available RX RAW total buffer count + param: + numRxResource pointer of queried value + + return: + eWLAN_PAL_STATUS_SUCCESS +---------------------------------------------------------------------------*/ +wpt_status wpalGetNumRxRawPacket(wpt_uint32 *numRxResource) +{ + *numRxResource = (wpt_uint32)vos_pkt_get_num_of_rx_raw_pkts(); + + return eWLAN_PAL_STATUS_SUCCESS; +} diff --git a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_trace.c b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_trace.c index 914e00fdff5..e2c86ace29c 100644 --- a/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_trace.c +++ b/drivers/staging/prima/CORE/WDI/WPAL/src/wlan_qct_pal_trace.c @@ -284,7 +284,7 @@ void wpalTrace( wpt_moduleid module, wpt_tracelevel level, char *strFormat, ... // print the formatted log message after the prefix string. // note we reserve space for the terminating NUL - if (n < WPAL_TRACE_BUFFER_SIZE) + if ((n >= 0) && (n < WPAL_TRACE_BUFFER_SIZE)) { vsnprintf(strBuffer + n, WPAL_TRACE_BUFFER_SIZE - n - 1, strFormat, val); wpalOutput(level, strBuffer); diff --git a/drivers/staging/prima/Kbuild b/drivers/staging/prima/Kbuild index f1e81846812..ce33a11b232 100644 --- a/drivers/staging/prima/Kbuild +++ b/drivers/staging/prima/Kbuild @@ -11,6 +11,8 @@ ifeq ($(KERNEL_BUILD),1) # Need to explicitly define for Kernel-based builds MODNAME := wlan WLAN_ROOT := drivers/staging/prima + #Flag to enable TDLS feature + CONFIG_QCOM_TDLS := y endif ifeq ($(KERNEL_BUILD),0) @@ -33,7 +35,7 @@ ifeq ($(KERNEL_BUILD),0) CONFIG_QCOM_TDLS := y #Flag to enable Fast Transition (11r) feature - CONFIG_QCOM_VOWIFI_11R := n + CONFIG_QCOM_VOWIFI_11R := y endif @@ -46,7 +48,7 @@ BUILD_DEBUG_VERSION := 1 BUILD_DIAG_VERSION := 0 #Do we panic on bug? default is to warn -PANIC_ON_BUG := 0 +PANIC_ON_BUG := 1 #Re-enable wifi on WDI timeout RE_ENABLE_WIFI_ON_WDI_TIMEOUT := 0 @@ -512,9 +514,11 @@ CDEFINES := -DANI_BUS_TYPE_PLATFORM=1 \ -DWLAN_FEATURE_P2P_DEBUG \ -DWLAN_ENABLE_AGEIE_ON_SCAN_RESULTS \ -DWLANTL_DEBUG\ + -DWLAN_NS_OFFLOAD \ -DWLAN_ACTIVEMODE_OFFLOAD_FEATURE \ -DWLAN_FEATURE_HOLD_RX_WAKELOCK \ - -DWLAN_SOFTAP_VSTA_FEATURE + -DWLAN_SOFTAP_VSTA_FEATURE \ + -DWLAN_FEATURE_ROAM_SCAN_OFFLOAD ifneq ($(CONFIG_PRONTO_WLAN),) CDEFINES += -DWCN_PRONTO @@ -538,6 +542,10 @@ endif ifeq ($(HAVE_CFG80211),1) CDEFINES += -DWLAN_FEATURE_P2P CDEFINES += -DWLAN_FEATURE_WFD +ifeq ($(CONFIG_QCOM_VOWIFI_11R),y) +CDEFINES += -DKERNEL_SUPPORT_11R_CFG80211 +CDEFINES += -DUSE_80211_WMMTSPEC_FOR_RIC +endif endif ifeq ($(CONFIG_QCOM_CCX),y) @@ -547,7 +555,9 @@ endif #normally, TDLS negative behavior is not needed ifeq ($(CONFIG_QCOM_TDLS),y) CDEFINES += -DFEATURE_WLAN_TDLS +ifeq ($(BUILD_DEBUG_VERSION),1) CDEFINES += -DWLAN_FEATURE_TDLS_DEBUG +endif CDEFINES += -DCONFIG_TDLS_IMPLICIT #CDEFINES += -DFEATURE_WLAN_TDLS_NEGATIVE #Code under FEATURE_WLAN_TDLS_INTERNAL is ported from volans, This code @@ -618,7 +628,7 @@ CDEFINES += -DWLAN_OPEN_SOURCE endif # Fix build for GCC 4.7 -EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function +EXTRA_CFLAGS += -Wno-maybe-uninitialized -Wno-unused-function -Wno-array-bounds KBUILD_CPPFLAGS += $(CDEFINES) diff --git a/drivers/staging/prima/Kconfig b/drivers/staging/prima/Kconfig index 64606d72975..7ba2fc4bbee 100644 --- a/drivers/staging/prima/Kconfig +++ b/drivers/staging/prima/Kconfig @@ -27,4 +27,8 @@ config PRIMA_WLAN_11AC_HIGH_TP bool "Enable the Prima WLAN 802.11ac High Throughput option (depends upon kernel support)" default n +config QCOM_VOWIFI_11R + bool "Enable Fast Transition (11r) feature" + default n + endif # PRIMA_WLAN diff --git a/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat b/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat index 297b3cd4722..16ba06f087a 100644 Binary files a/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat and b/drivers/staging/prima/firmware_bin/WCNSS_cfg.dat differ diff --git a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini index de53949c057..ae2894a18dd 100644 --- a/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini +++ b/drivers/staging/prima/firmware_bin/WCNSS_qcom_cfg.ini @@ -93,6 +93,10 @@ McastBcastFilter=3 hostArpOffload=1 +#Flag to enable HostNSOffload feature or not + +hostNSOffload=0 + #SoftAP Related Parameters # AP MAc addr @@ -353,12 +357,6 @@ gVhtTxMCS=2 # gPassiveMinChannelTime=60 # gActiveMaxChannelTime=40 # gActiveMinChannelTime=20 -gPassiveMaxChannelTimeConc=110 -gPassiveMinChannelTimeConc=60 -gActiveMaxChannelTimeConc=27 -gActiveMinChannelTimeConc=20 -gRestTimeConc=100 -gNumChanCombinedConc=1 #If set to 0, MCC is not allowed. gEnableMCCMode=1 @@ -381,6 +379,37 @@ isAndroidPsEn=0 #disable LDPC in STA mode if the AP is TXBF capable gDisableLDPCWithTxbfAP=1 + +#Enable thermal mitigation +gThermalMitigationEnable=1 + +#List of Country codes for which 11ac needs to be disabled +#Each country code must be delimited by comma(,) +gListOfNon11acCountryCode=RU,UA,ZA + +#Maxium Channel time in msec +gMaxMediumTime = 6000 + +# 802.11K support +gRrmEnable=1 +gRrmOperChanMax=8 +gRrmNonOperChanMax=8 +gRrmRandIntvl=100 + +# TDLS Support +gEnableTDLSSupport=1 +gEnableTDLSImplicitTrigger=1 +gTDLSExternalControl=1 +gTDLSTxStatsPeriod=500 +gTDLSTxPacketThreshold=10 +gTDLSDiscoveryPeriod=20000 +gTDLSMaxDiscoveryAttempt=5 +gTDLSIdleTimeout=40000 +gTDLSRssiHysteresis=100 +gTDLSRSSITriggerThreshold=-60 +gTDLSIdlePacketThreshold=5 +gTDLSRSSITeardownThreshold=-70 + END # Note: Configuration parser would not read anything past the END marker diff --git a/drivers/staging/prima/riva/inc/wlan_hal_cfg.h b/drivers/staging/prima/riva/inc/wlan_hal_cfg.h index 6d80cee6a92..899577e0b91 100644 --- a/drivers/staging/prima/riva/inc/wlan_hal_cfg.h +++ b/drivers/staging/prima/riva/inc/wlan_hal_cfg.h @@ -155,7 +155,9 @@ #define QWLAN_HAL_CFG_ENABLE_DETECT_PS_SUPPORT 101 #define QWLAN_HAL_CFG_AP_LINK_MONITOR_TIMEOUT 102 #define QWLAN_HAL_CFG_BTC_DWELL_TIME_MULTIPLIER 103 -#define QWLAN_HAL_CFG_MAX_PARAMS 104 +#define QWLAN_HAL_CFG_RA_FILTER_ENABLE 104 +#define QWLAN_HAL_CFG_RA_RATE_LIMIT_INTERVAL 105 +#define QWLAN_HAL_CFG_MAX_PARAMS 106 diff --git a/drivers/staging/prima/riva/inc/wlan_hal_msg.h b/drivers/staging/prima/riva/inc/wlan_hal_msg.h index 4c2758383c9..ff26657ce95 100644 --- a/drivers/staging/prima/riva/inc/wlan_hal_msg.h +++ b/drivers/staging/prima/riva/inc/wlan_hal_msg.h @@ -101,11 +101,21 @@ typedef tANI_U8 tHalIpv4Addr[4]; PARAM_llGCOEXIST_CHANGED|PARAM_HT20MHZCOEXIST_CHANGED|PARAM_NON_GF_DEVICES_PRESENT_CHANGED|PARAM_RIFS_MODE_CHANGED|PARAM_LSIG_TXOP_FULL_SUPPORT_CHANGED| PARAM_OBSS_MODE_CHANGED) /*Dump command response Buffer size*/ -#define DUMPCMD_RSP_BUFFER 100 +#define DUMPCMD_RSP_BUFFER 500 /*Version string max length (including NUL) */ #define WLAN_HAL_VERSION_LENGTH 64 +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define CHANNEL_LIST_STATIC 1 /* Occupied channel list remains static */ +#define CHANNEL_LIST_DYNAMIC_INIT 2 /* Occupied channel list can be learnt after init */ +#define CHANNEL_LIST_DYNAMIC_FLUSH 3 /* Occupied channel list can be learnt after flush */ +#define CHANNEL_LIST_DYNAMIC_UPDATE 4 /* Occupied channel list can be learnt after update */ +#define WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE 450 +#define WLAN_HAL_ROAM_SCAN_MAX_CHANNELS NUM_RF_CHANNELS +#define WLAN_HAL_ROAM_SCAN_RESERVED_BYTES 61 +#endif + /* Message types for messages exchanged between WDI and HAL */ typedef enum { @@ -362,7 +372,10 @@ typedef enum WLAN_HAL_DEL_BA_IND = 188, WLAN_HAL_DHCP_START_IND = 189, WLAN_HAL_DHCP_STOP_IND = 190, - + WLAN_ROAM_SCAN_OFFLOAD_REQ = 191, + WLAN_ROAM_SCAN_OFFLOAD_RSP = 192, + WLAN_HAL_WIFI_PROXIMITY_REQ = 193, + WLAN_HAL_WIFI_PROXIMITY_RSP = 194, WLAN_HAL_MSG_MAX = WLAN_HAL_MSG_TYPE_MAX_ENUM_SIZE }tHalHostMsgType; @@ -556,6 +569,7 @@ typedef enum eSriLinkState { eSIR_LINK_FINISH_CAL_STATE = 13, #ifdef WLAN_FEATURE_P2P eSIR_LINK_LISTEN_STATE = 14, + eSIR_LINK_SEND_ACTION_STATE = 15, #endif eSIR_LINK_MAX = WLAN_HAL_MAX_ENUM_SIZE } tSirLinkState; @@ -1618,6 +1632,15 @@ typedef enum HAL_MAX_CONCURRENCY_PERSONA=4 } tHalConcurrencyMode; +// IFACE PERSONA for different Operating modes +typedef enum +{ + HAL_IFACE_UNKNOWN=0, + HAL_IFACE_STA_MODE=1, + HAL_IFACE_P2P_MODE=2, + HAL_IFACE_MAX=0x7FFFFFFF, +}tHalIfacePersona; + typedef PACKED_PRE struct PACKED_POST { /* BSSID */ @@ -4537,11 +4560,20 @@ typedef PACKED_PRE struct PACKED_POST tANI_U32 status; }tAddStaSelfParams, *tpAddStaSelfParams; +typedef PACKED_PRE struct PACKED_POST +{ + tSirMacAddr selfMacAddr; + tANI_U32 status; + tHalIfacePersona iface_persona; +}tAddStaSelfParams_V1, *tpAddStaSelfParams_V1; typedef PACKED_PRE struct PACKED_POST { tHalMsgHeader header; + PACKED_PRE union PACKED_POST { tAddStaSelfParams addStaSelfParams; + tAddStaSelfParams_V1 addStaSelfParams_V1; + }uAddStaSelfParams; }tAddStaSelfReq, *tpAddStaSelfReq; /*--------------------------------------------------------------------------- @@ -4933,6 +4965,7 @@ typedef enum ePNO_MODE_IMMEDIATE, ePNO_MODE_ON_SUSPEND, ePNO_MODE_ON_RESUME, + ePNO_MODE_DELAY, ePNO_MODE_MAX = WLAN_HAL_MAX_ENUM_SIZE } ePNOMode; @@ -4952,6 +4985,8 @@ typedef enum eAUTH_TYPE_FT_RSN_PSK = 7, eAUTH_TYPE_WAPI_WAI_CERTIFICATE = 8, eAUTH_TYPE_WAPI_WAI_PSK = 9, + eAUTH_TYPE_CCKM_WPA = 10, + eAUTH_TYPE_CCKM_RSN = 11, eAUTH_TYPE_MAX = WLAN_HAL_MAX_ENUM_SIZE @@ -5149,16 +5184,18 @@ typedef PACKED_PRE struct PACKED_POST } tSetPrefNetwListResp, *tpSetPrefNetwListResp; /* - Preferred network indication parameters + Preferred network indication parameters */ typedef PACKED_PRE struct PACKED_POST { /*Network that was found with the highest RSSI*/ tSirMacSSid ssId; - + /*Indicates the RSSI */ tANI_U8 rssi; + tANI_U16 frameLength; + } tPrefNetwFoundParams, * tpPrefNetwFoundParams; /* @@ -5177,7 +5214,67 @@ typedef PACKED_PRE struct PACKED_POST { tANI_U8 ucRssiThreshold; } tRssiFilterParams, * tpRssiFilterParams; +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +typedef PACKED_PRE struct PACKED_POST +{ + tSirMacSSid ssId; + tANI_U8 currAPbssid[HAL_MAC_ADDR_LEN]; + tANI_U32 authentication; + tEdType encryption; + tEdType mcencryption; + tANI_U8 ChannelCount; + tANI_U8 ChannelCache[WLAN_HAL_ROAM_SCAN_MAX_CHANNELS]; +}tRoamNetworkType; +typedef PACKED_PRE struct PACKED_POST +{ + tANI_U8 mdiePresent; + tANI_U16 mobilityDomain; +}tMobilityDomainInfo; + +typedef PACKED_PRE struct PACKED_POST { + eAniBoolean RoamScanOffloadEnabled; + tANI_S8 LookupThreshold; + tANI_U8 RoamRssiDiff; + tANI_U8 ChannelCacheType; + tANI_U8 Command; + tANI_U8 StartScanReason; + tANI_U16 NeighborScanTimerPeriod; + tANI_U16 NeighborRoamScanRefreshPeriod; + tANI_U16 NeighborScanChannelMinTime; + tANI_U16 NeighborScanChannelMaxTime; + tANI_U16 EmptyRefreshScanPeriod; + tANI_U8 ValidChannelCount; + tANI_U8 ValidChannelList[WLAN_HAL_ROAM_SCAN_MAX_CHANNELS]; + eAniBoolean IsCCXEnabled; + + tANI_U16 us24GProbeSize; + tANI_U8 a24GProbeTemplate[WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE]; + tANI_U16 us5GProbeSize; + tANI_U8 a5GProbeTemplate[WLAN_HAL_ROAM_SCAN_MAX_PROBE_SIZE]; + /* Add Reserved bytes */ + tANI_U8 nProbes; + tANI_U16 HomeAwayTime; + tANI_U8 ReservedBytes[WLAN_HAL_ROAM_SCAN_RESERVED_BYTES]; + tRoamNetworkType ConnectedNetwork; + tMobilityDomainInfo MDID; +} tRoamCandidateListParams, * tpRoamCandidateListParams; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + tRoamCandidateListParams RoamScanOffloadNetwListParams; +} tSetRoamScanOffloadReq, *tpRoamScanOffloadReq; + +typedef PACKED_PRE struct PACKED_POST +{ + tHalMsgHeader header; + + /*status of the request - just to indicate that PNO has acknowledged + * the request and will start scanning*/ + tANI_U32 status; +} tSetRoamOffloadScanResp, *tpSetRoamOffloadScanResp; +#endif /* RSSI Filter request */ @@ -5520,6 +5617,9 @@ typedef PACKED_PRE struct PACKED_POST /* Beacon Early Termination Interval */ tANI_U32 uBETInterval; + + /* MAX LI for modulated DTIM */ + tANI_U32 uMaxLIModulatedDTIM; }tSetPowerParamsType, *tpSetPowerParamsType; typedef PACKED_PRE struct PACKED_POST @@ -5564,7 +5664,9 @@ typedef enum { BCN_FILTER = 19, RTT = 20, RATECTRL = 21, - WOW = 22 + WOW = 22, + WLAN_ROAM_SCAN_OFFLOAD = 23, + EXTENDED_NSOFFLOAD_SLOT = 24, //MAX_FEATURE_SUPPORTED = 128 } placeHolderInCapBitmap; @@ -5584,6 +5686,9 @@ typedef PACKED_PRE struct PACKED_POST{ #define IS_SLM_SESSIONIZATION_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(SLM_SESSIONIZATION))) #define IS_FEATURE_SUPPORTED_BY_HOST(featEnumValue) (!!halMsg_GetHostWlanFeatCaps(featEnumValue)) #define IS_WLANACTIVE_OFFLOAD_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(WLANACTIVE_OFFLOAD))) +#ifdef WLAN_FEATURE_ROAM_SCAN_OFFLOAD +#define IS_ROAM_SCAN_OFFLOAD_SUPPORTED_BY_HOST (!!(halMsg_GetHostWlanFeatCaps(WLAN_ROAM_SCAN_OFFLOAD))) +#endif tANI_U8 halMsg_GetHostWlanFeatCaps(tANI_U8 feat_enum_value); diff --git a/drivers/thermal/msm8960_tsens.c b/drivers/thermal/msm8960_tsens.c index c571de6acea..c826c8b9e00 100644 --- a/drivers/thermal/msm8960_tsens.c +++ b/drivers/thermal/msm8960_tsens.c @@ -145,7 +145,7 @@ struct tsens_tm_device_sensor { struct thermal_zone_device *tz_dev; enum thermal_device_mode mode; unsigned int sensor_num; - struct work_struct work; + struct work_struct *work; int offset; int calib_data; int calib_data_backup; @@ -232,6 +232,20 @@ static int tsens_tz_get_temp(struct thermal_zone_device *thermal, return 0; } +int tsens_get_sensor_temp(int sensor_num, unsigned long *temp) +{ + if (!tmdev) + return -ENODEV; + + if (sensor_num < 0 || sensor_num >= TSENS_MAX_SENSORS || !temp) + return -EINVAL; + + tsens8960_get_temp(sensor_num, temp); + + return 0; +} +EXPORT_SYMBOL(tsens_get_sensor_temp); + int tsens_get_temp(struct tsens_device *device, unsigned long *temp) { if (!tmdev) @@ -590,6 +604,42 @@ static int tsens_tz_set_trip_temp(struct thermal_zone_device *thermal, return 0; } +static int +tsens_set_tz_trip_temp_degC(int sensor_num, enum tsens_trip_type trip, int temp, struct work_struct *work) +{ + struct thermal_zone_device *thermal; + int ret; + + if (! tmdev || sensor_num < 0 || sensor_num >= tmdev->tsens_num_sensor) + return -EINVAL; + + thermal = tmdev->sensor[sensor_num].tz_dev; + + ret = tsens_tz_set_trip_temp(thermal, trip, temp); + if (ret < 0) + return ret; + + ret = tsens_tz_activate_trip_type(thermal, trip, THERMAL_TRIP_ACTIVATION_ENABLED); + if (ret < 0) + return ret; + + tmdev->sensor[sensor_num].work = work; + + return 0; +} + +int +tsens_set_tz_warm_temp_degC(int sensor_num, int temp, struct work_struct *work) +{ + return tsens_set_tz_trip_temp_degC(sensor_num, TSENS_TRIP_STAGE2, temp, work); +} + +int +tsens_set_tz_cool_temp_degC(int sensor_num, int temp, struct work_struct *work) +{ + return tsens_set_tz_trip_temp_degC(sensor_num, TSENS_TRIP_STAGE1, temp, work); +} + static struct thermal_zone_device_ops tsens_thermal_zone_ops = { .get_temp = tsens_tz_get_temp, .get_mode = tsens_tz_get_mode, @@ -602,15 +652,6 @@ static struct thermal_zone_device_ops tsens_thermal_zone_ops = { .notify = tsens_tz_notify, }; -static void notify_uspace_tsens_fn(struct work_struct *work) -{ - struct tsens_tm_device_sensor *tm = container_of(work, - struct tsens_tm_device_sensor, work); - - sysfs_notify(&tm->tz_dev->device.kobj, - NULL, "type"); -} - static void tsens_scheduler_fn(struct work_struct *work) { struct tsens_tm_device *tm = container_of(work, struct tsens_tm_device, @@ -618,7 +659,7 @@ static void tsens_scheduler_fn(struct work_struct *work) unsigned int threshold, threshold_low, i, code, reg, sensor, mask; unsigned int sensor_addr; bool upper_th_x, lower_th_x; - int adc_code; + unsigned triggered = 0; if (tmdev->hw_type == APQ_8064) { reg = readl_relaxed(TSENS_8064_STATUS_CNTL); @@ -649,7 +690,7 @@ static void tsens_scheduler_fn(struct work_struct *work) for (i = 0; i < tmdev->tsens_num_sensor; i++) { if (i == TSENS_8064_SEQ_SENSORS) sensor_addr += TSENS_8064_S4_S5_OFFSET; - if (sensor & TSENS_MASK1) { + if ((sensor & TSENS_MASK1) != 0 && tm->sensor[i].work) { code = readl_relaxed(sensor_addr); upper_th_x = code >= threshold; lower_th_x = code <= threshold_low; @@ -658,11 +699,7 @@ static void tsens_scheduler_fn(struct work_struct *work) if (lower_th_x) mask |= TSENS_LOWER_STATUS_CLR; if (upper_th_x || lower_th_x) { - /* Notify user space */ - schedule_work(&tm->sensor[i].work); - adc_code = readl_relaxed(sensor_addr); - pr_debug("Trigger (%d degrees) for sensor %d\n", - tsens_tz_code_to_degC(adc_code, i), i); + triggered |= (1 << i); } } sensor >>= 1; @@ -673,6 +710,26 @@ static void tsens_scheduler_fn(struct work_struct *work) else writel_relaxed(reg & mask, TSENS_CNTL_ADDR); mb(); + + /* Actually schedule the work after changing the masks so that + * we don't overwrite any changes that these callbacks want + * to make. + * + * Put a memory barrier before to ensure that we have actually + * made the change to the sensor. + */ + + if (triggered) + for (i = 0; i < tmdev->tsens_num_sensor; i++) + if ((triggered & (1 <sensor[i].work; + tm->sensor[i].work = NULL; + if (work) + schedule_work(work); + } } static irqreturn_t tsens_isr(int irq, void *data) @@ -872,8 +929,7 @@ static int tsens_calib_sensors8660(void) tmdev->sensor[TSENS_MAIN_SENSOR].calib_data; tmdev->prev_reading_avail = false; - INIT_WORK(&tmdev->sensor[TSENS_MAIN_SENSOR].work, - notify_uspace_tsens_fn); + tmdev->sensor[TSENS_MAIN_SENSOR].work = NULL; return 0; } @@ -901,7 +957,7 @@ static int tsens_calib_sensors8960(void) - (tmdev->sensor[i].calib_data * tmdev->sensor[i].slope_mul_tsens_factor); tmdev->prev_reading_avail = false; - INIT_WORK(&tmdev->sensor[i].work, notify_uspace_tsens_fn); + tmdev->sensor[i].work = NULL; } return 0; diff --git a/drivers/thermal/msm_thermal.c b/drivers/thermal/msm_thermal.c index 0e3daeb70ae..5540d9262ea 100644 --- a/drivers/thermal/msm_thermal.c +++ b/drivers/thermal/msm_thermal.c @@ -24,173 +24,171 @@ #include #include #include +#include -static int enabled; -static struct msm_thermal_data msm_thermal_info; -static uint32_t limited_max_freq = MSM_CPUFREQ_NO_LIMIT; -static struct delayed_work check_temp_work; +#define NO_RELEASE_TEMPERATURE 0 +#define NO_TRIGGER_TEMPERATURE -1 -static int limit_idx; -static int limit_idx_low; -static int limit_idx_high; -static struct cpufreq_frequency_table *table; +#define N_TEMP_LIMITS 4 -static int msm_thermal_get_freq_table(void) -{ - int ret = 0; - int i = 0; +static unsigned temp_hysteresis = 5; +static unsigned int limit_temp_degC[N_TEMP_LIMITS] = { 80, 85, 92, 102 }; +static unsigned int limit_freq[N_TEMP_LIMITS] = { 1512000, 1350000, 918000, 384000 }; - table = cpufreq_frequency_get_table(0); - if (table == NULL) { - pr_debug("%s: error reading cpufreq table\n", __func__); - ret = -EINVAL; - goto fail; - } +module_param_array(limit_temp_degC, uint, NULL, 0644); +module_param_array(limit_freq, uint, NULL, 0644); - while (table[i].frequency != CPUFREQ_TABLE_END) - i++; +int throttled_bin = -1; - limit_idx_low = 0; - limit_idx_high = limit_idx = i - 1; - BUG_ON(limit_idx_high <= 0 || limit_idx_high <= limit_idx_low); -fail: - return ret; +module_param(throttled_bin, int, 0444); + +static struct msm_thermal_data msm_thermal_info; +static struct delayed_work first_work; +static struct work_struct trip_work; + +static int max_freq(int throttled_bin) +{ + if (throttled_bin < 0) return MSM_CPUFREQ_NO_LIMIT; + else return limit_freq[throttled_bin]; } -static int update_cpu_max_freq(int cpu, uint32_t max_freq) +static int limit_temp(int throttled_bin) { - int ret = 0; + if (throttled_bin < 0) return limit_temp_degC[0]; + else if (throttled_bin == N_TEMP_LIMITS-1) return NO_TRIGGER_TEMPERATURE; + else return limit_temp_degC[throttled_bin+1]; +} + +static int release_temp(int throttled_bin) +{ + if (throttled_bin < 0) return NO_RELEASE_TEMPERATURE; + else return limit_temp_degC[throttled_bin] - temp_hysteresis; +} - ret = msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, max_freq); +static int update_cpu_max_freq(int cpu, int throttled_bin, unsigned temp) +{ + int ret; + int max_frequency = max_freq(throttled_bin); + + ret = msm_cpufreq_set_freq_limits(cpu, MSM_CPUFREQ_NO_LIMIT, max_frequency); if (ret) return ret; - limited_max_freq = max_freq; - if (max_freq != MSM_CPUFREQ_NO_LIMIT) - pr_info("msm_thermal: Limiting cpu%d max frequency to %d\n", - cpu, max_freq); - else - pr_info("msm_thermal: Max frequency reset for cpu%d\n", cpu); - ret = cpufreq_update_policy(cpu); + if (ret) + return ret; + + if (max_frequency != MSM_CPUFREQ_NO_LIMIT) { + struct cpufreq_policy policy; + + if ((ret = cpufreq_get_policy(&policy, cpu)) == 0) + ret = cpufreq_driver_target(&policy, max_frequency, CPUFREQ_RELATION_L); + } + + if (max_frequency != MSM_CPUFREQ_NO_LIMIT) + pr_info("msm_thermal: limiting cpu%d max frequency to %d at %u degC\n", + cpu, max_frequency, temp); + else + pr_info("msm_thermal: Max frequency reset for cpu%d at %u degC\n", cpu, temp); return ret; } -static void check_temp(struct work_struct *work) +static void +update_all_cpus_max_freq_if_changed(int new_throttled_bin, unsigned temp) { - static int limit_init; - struct tsens_device tsens_dev; - unsigned long temp = 0; - uint32_t max_freq = limited_max_freq; - int cpu = 0; - int ret = 0; + int cpu; + int ret; - tsens_dev.sensor_num = msm_thermal_info.sensor_id; - ret = tsens_get_temp(&tsens_dev, &temp); - if (ret) { - pr_debug("msm_thermal: Unable to read TSENS sensor %d\n", - tsens_dev.sensor_num); - goto reschedule; - } + if (throttled_bin == new_throttled_bin) + return; - if (!limit_init) { - ret = msm_thermal_get_freq_table(); - if (ret) - goto reschedule; - else - limit_init = 1; - } +#ifdef CONFIG_PERFLOCK_BOOT_LOCK + release_boot_lock(); +#endif - if (temp >= msm_thermal_info.limit_temp_degC) { - if (limit_idx == limit_idx_low) - goto reschedule; - - limit_idx -= msm_thermal_info.freq_step; - if (limit_idx < limit_idx_low) - limit_idx = limit_idx_low; - max_freq = table[limit_idx].frequency; - } else if (temp < msm_thermal_info.limit_temp_degC - - msm_thermal_info.temp_hysteresis_degC) { - if (limit_idx == limit_idx_high) - goto reschedule; - - limit_idx += msm_thermal_info.freq_step; - if (limit_idx >= limit_idx_high) { - limit_idx = limit_idx_high; - max_freq = MSM_CPUFREQ_NO_LIMIT; - } else - max_freq = table[limit_idx].frequency; - } - if (max_freq == limited_max_freq) - goto reschedule; + throttled_bin = new_throttled_bin; + - /* Update new limits */ for_each_possible_cpu(cpu) { - ret = update_cpu_max_freq(cpu, max_freq); + ret = update_cpu_max_freq(cpu, throttled_bin, temp); if (ret) - pr_debug("Unable to limit cpu%d max freq to %d\n", - cpu, max_freq); + pr_warn("Unable to limit cpu%d\n", cpu); } - -reschedule: - if (enabled) - schedule_delayed_work(&check_temp_work, - msecs_to_jiffies(msm_thermal_info.poll_ms)); } -static void disable_msm_thermal(void) +static void +configure_sensor_trip_points(void) { - int cpu = 0; + int trigger_temperature = limit_temp(throttled_bin); + int release_temperature = release_temp(throttled_bin); - /* make sure check_temp is no longer running */ - cancel_delayed_work(&check_temp_work); - flush_scheduled_work(); + pr_info("msm_thermal: setting trip range %d..%d on sensor %d.\n", release_temperature, trigger_temperature, msm_thermal_info.sensor_id); + if (trigger_temperature != NO_TRIGGER_TEMPERATURE) + tsens_set_tz_warm_temp_degC(msm_thermal_info.sensor_id, trigger_temperature, &trip_work); - if (limited_max_freq == MSM_CPUFREQ_NO_LIMIT) - return; + if (release_temperature != NO_RELEASE_TEMPERATURE) + tsens_set_tz_cool_temp_degC(msm_thermal_info.sensor_id, release_temperature, &trip_work); +} - for_each_possible_cpu(cpu) { - update_cpu_max_freq(cpu, MSM_CPUFREQ_NO_LIMIT); +static int +select_throttled_bin(unsigned temp) +{ + int i; + int new_bin = -1; + + for (i = 0; i < N_TEMP_LIMITS; i++) { + if (temp >= limit_temp_degC[i]) new_bin = i; } + + if (new_bin > throttled_bin) return new_bin; + if (temp <= release_temp(throttled_bin)) return new_bin; + return throttled_bin; } -static int set_enabled(const char *val, const struct kernel_param *kp) +static void check_temp_and_throttle_if_needed(struct work_struct *work) { - int ret = 0; + struct tsens_device tsens_dev; + unsigned long temp_ul = 0; + unsigned temp; + int new_bin; + int ret; - ret = param_set_bool(val, kp); - if (!enabled) - disable_msm_thermal(); - else - pr_info("msm_thermal: no action for enabled = %d\n", enabled); + tsens_dev.sensor_num = msm_thermal_info.sensor_id; + ret = tsens_get_temp(&tsens_dev, &temp_ul); + if (ret) { + pr_warn("msm_thermal: Unable to read TSENS sensor %d\n", + tsens_dev.sensor_num); + return; + } - pr_info("msm_thermal: enabled = %d\n", enabled); + temp = (unsigned) temp_ul; + new_bin = select_throttled_bin(temp); - return ret; + pr_debug("msm_thermal: TSENS sensor %d is %u degC old-bin %d new-bin %d\n", + tsens_dev.sensor_num, temp, throttled_bin, new_bin); + update_all_cpus_max_freq_if_changed(new_bin, temp); } -static struct kernel_param_ops module_ops = { - .set = set_enabled, - .get = param_get_bool, -}; - -module_param_cb(enabled, &module_ops, &enabled, 0644); -MODULE_PARM_DESC(enabled, "enforce thermal limit on cpu"); +static void check_temp(struct work_struct *work) +{ + check_temp_and_throttle_if_needed(work); + configure_sensor_trip_points(); +} int __devinit msm_thermal_init(struct msm_thermal_data *pdata) { - int ret = 0; BUG_ON(!pdata); BUG_ON(pdata->sensor_id >= TSENS_MAX_SENSORS); memcpy(&msm_thermal_info, pdata, sizeof(struct msm_thermal_data)); - enabled = 1; - INIT_DELAYED_WORK(&check_temp_work, check_temp); - schedule_delayed_work(&check_temp_work, 0); + INIT_DELAYED_WORK(&first_work, check_temp); + INIT_WORK(&trip_work, check_temp); - return ret; + schedule_delayed_work(&first_work, msecs_to_jiffies(5*1000)); + + return 0; } static int __devinit msm_thermal_dev_probe(struct platform_device *pdev) @@ -207,7 +205,7 @@ static int __devinit msm_thermal_dev_probe(struct platform_device *pdev) goto fail; WARN_ON(data.sensor_id >= TSENS_MAX_SENSORS); - key = "qcom,poll-ms"; +/* key = "qcom,poll-ms"; ret = of_property_read_u32(node, key, &data.poll_ms); if (ret) goto fail; @@ -223,7 +221,7 @@ static int __devinit msm_thermal_dev_probe(struct platform_device *pdev) goto fail; key = "qcom,freq-step"; - ret = of_property_read_u32(node, key, &data.freq_step); + ret = of_property_read_u32(node, key, &data.freq_step);*/ fail: if (ret) diff --git a/drivers/thermal/pm8xxx-tm.c b/drivers/thermal/pm8xxx-tm.c index ec043692a63..456893381f3 100644 --- a/drivers/thermal/pm8xxx-tm.c +++ b/drivers/thermal/pm8xxx-tm.c @@ -33,29 +33,32 @@ #include /* Register TEMP_ALARM_CTRL bits */ -#define TEMP_ALARM_CTRL_ST3_SD 0x80 -#define TEMP_ALARM_CTRL_ST2_SD 0x40 -#define TEMP_ALARM_CTRL_STATUS_MASK 0x30 -#define TEMP_ALARM_CTRL_STATUS_SHIFT 4 -#define TEMP_ALARM_CTRL_THRESH_MASK 0x0C -#define TEMP_ALARM_CTRL_THRESH_SHIFT 2 -#define TEMP_ALARM_CTRL_OVRD_ST3 0x02 -#define TEMP_ALARM_CTRL_OVRD_ST2 0x01 -#define TEMP_ALARM_CTRL_OVRD_MASK 0x03 - -#define TEMP_STAGE_STEP 20000 /* Stage step: 20.000 C */ -#define TEMP_STAGE_HYSTERESIS 2000 - -#define TEMP_THRESH_MIN 105000 /* Threshold Min: 105 C */ -#define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */ +#define TEMP_ALARM_CTRL_ST3_SD 0x80 +#define TEMP_ALARM_CTRL_ST2_SD 0x40 +#define TEMP_ALARM_CTRL_STATUS_MASK 0x30 +#define TEMP_ALARM_CTRL_STATUS_SHIFT 4 +#define TEMP_ALARM_CTRL_THRESH_MASK 0x0C +#define TEMP_ALARM_CTRL_THRESH_SHIFT 2 +#define TEMP_ALARM_CTRL_OVRD_ST3 0x02 +#define TEMP_ALARM_CTRL_OVRD_ST2 0x01 +#define TEMP_ALARM_CTRL_OVRD_MASK 0x03 + +#define TEMP_STAGE_STEP 20000 /* Stage step: 20.000 C */ +#define TEMP_STAGE_HYSTERESIS 2000 + +#define TEMP_THRESH_MIN 105000 /* Threshold Min: 105 C */ +#define TEMP_THRESH_STEP 5000 /* Threshold step: 5 C */ /* Register TEMP_ALARM_PWM bits */ -#define TEMP_ALARM_PWM_EN_MASK 0xC0 -#define TEMP_ALARM_PWM_EN_SHIFT 6 -#define TEMP_ALARM_PWM_PER_PRE_MASK 0x38 -#define TEMP_ALARM_PWM_PER_PRE_SHIFT 3 -#define TEMP_ALARM_PWM_PER_DIV_MASK 0x07 -#define TEMP_ALARM_PWM_PER_DIV_SHIFT 0 +#define TEMP_ALARM_PWM_EN_MASK 0xC0 +#define TEMP_ALARM_PWM_EN_NEVER 0x00 +#define TEMP_ALARM_PWM_EN_SLEEP_B 0x40 +#define TEMP_ALARM_PWM_EN_PWM 0x80 +#define TEMP_ALARM_PWM_EN_ALWAYS 0xC0 +#define TEMP_ALARM_PWM_PER_PRE_MASK 0x38 +#define TEMP_ALARM_PWM_PER_PRE_SHIFT 3 +#define TEMP_ALARM_PWM_PER_DIV_MASK 0x07 +#define TEMP_ALARM_PWM_PER_DIV_SHIFT 0 /* Trips: from critical to less critical */ #define TRIP_STAGE3 0 @@ -516,16 +519,15 @@ static int pm8xxx_tm_init_reg(struct pm8xxx_tm_chip *chip) return rc; /* - * Set the PMIC alarm module PWM to have a frequency of 8 Hz. This - * helps cut down on the number of unnecessary interrupts fired when - * changing between thermal stages. Also, Enable the over temperature - * PWM whenever the PMIC is enabled. + * Set the PMIC temperature alarm module to be always on. This ensures + * that die temperature monitoring is active even if CXO is disabled + * (i.e. when sleep_b is low). This is necessary since CXO can be + * disabled while the system is still heavily loaded. Also, using + * the alway-on instead of PWM-enabled configurations ensures that the + * die temperature can be measured by the PMIC ADC without reconfiguring + * the temperature alarm module first. */ - reg = (1 << TEMP_ALARM_PWM_EN_SHIFT) - | (3 << TEMP_ALARM_PWM_PER_PRE_SHIFT) - | (3 << TEMP_ALARM_PWM_PER_DIV_SHIFT); - - rc = pm8xxx_tm_write_pwm(chip, reg); + rc = pm8xxx_tm_write_pwm(chip, TEMP_ALARM_PWM_EN_ALWAYS); return rc; } diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c index 8760603e66d..6ac7a4528d2 100644 --- a/drivers/tty/n_smux.c +++ b/drivers/tty/n_smux.c @@ -3187,7 +3187,7 @@ int msm_smux_close(uint8_t lcid) int msm_smux_write(uint8_t lcid, void *pkt_priv, const void *data, int len) { struct smux_lch_t *ch; - struct smux_pkt_t *pkt; + struct smux_pkt_t *pkt = NULL; int tx_ready = 0; unsigned long flags; int ret; diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 94b6eda87af..2470b918aa2 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1987,7 +1987,9 @@ static ssize_t n_tty_write(struct tty_struct *tty, struct file *file, tty->ops->flush_chars(tty); } else { while (nr > 0) { + mutex_lock(&tty->output_lock); c = tty->ops->write(tty, b, nr); + mutex_unlock(&tty->output_lock); if (c < 0) { retval = c; goto break_out; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index d97d5480d93..4f3584e0d16 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -20,11 +20,12 @@ #include #include #include +#include #include #include #include #include -#include +#include #include #include @@ -2038,6 +2039,14 @@ int usb_new_device(struct usb_device *udev) /* Tell the world! */ announce_device(udev); + if (udev->serial) + add_device_randomness(udev->serial, strlen(udev->serial)); + if (udev->product) + add_device_randomness(udev->product, strlen(udev->product)); + if (udev->manufacturer) + add_device_randomness(udev->manufacturer, + strlen(udev->manufacturer)); + device_enable_async_suspend(&udev->dev); /* @@ -2735,7 +2744,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) struct usb_hub *hub = hdev_to_hub(udev->parent); int port1 = udev->portnum; int status; - u16 portchange, portstatus; + u16 portchange = 0, portstatus = 0; /* Skip the initial Clear-Suspend step for a remote wakeup */ status = hub_port_status(hub, port1, &portstatus, &portchange); diff --git a/drivers/usb/gadget/f_accessory.c b/drivers/usb/gadget/f_accessory.c index 42a6c43aaf1..61fd736bebb 100644 --- a/drivers/usb/gadget/f_accessory.c +++ b/drivers/usb/gadget/f_accessory.c @@ -261,8 +261,10 @@ static void acc_complete_in(struct usb_ep *ep, struct usb_request *req) { struct acc_dev *dev = _acc_dev; - if (req->status != 0) + if (req->status == -ESHUTDOWN) { + pr_debug("acc_complete_in set disconnected"); acc_set_disconnected(dev); + } req_put(dev, &dev->tx_idle, req); @@ -274,8 +276,10 @@ static void acc_complete_out(struct usb_ep *ep, struct usb_request *req) struct acc_dev *dev = _acc_dev; dev->rx_done = 1; - if (req->status != 0) + if (req->status == -ESHUTDOWN) { + pr_debug("acc_complete_out set disconnected"); acc_set_disconnected(dev); + } wake_up(&dev->read_wq); } @@ -557,8 +561,10 @@ static ssize_t acc_read(struct file *fp, char __user *buf, pr_debug("acc_read(%d)\n", count); - if (dev->disconnected) + if (dev->disconnected) { + pr_debug("acc_read disconnected"); return -ENODEV; + } if (count > BULK_BUFFER_SIZE) count = BULK_BUFFER_SIZE; @@ -571,6 +577,12 @@ static ssize_t acc_read(struct file *fp, char __user *buf, goto done; } + if (dev->rx_done) { + // last req cancelled. try to get it. + req = dev->rx_req[0]; + goto copy_data; + } + requeue_req: /* queue a request */ req = dev->rx_req[0]; @@ -588,9 +600,17 @@ static ssize_t acc_read(struct file *fp, char __user *buf, ret = wait_event_interruptible(dev->read_wq, dev->rx_done); if (ret < 0) { r = ret; - usb_ep_dequeue(dev->ep_out, req); + ret = usb_ep_dequeue(dev->ep_out, req); + if (ret != 0) { + // cancel failed. There can be a data already received. + // it will be retrieved in the next read. + pr_debug("acc_read: cancelling failed %d", ret); + } goto done; } + +copy_data: + dev->rx_done = 0; if (dev->online) { /* If we got a 0-len packet, throw it back and try again. */ if (req->actual == 0) @@ -619,8 +639,10 @@ static ssize_t acc_write(struct file *fp, const char __user *buf, pr_debug("acc_write(%d)\n", count); - if (!dev->online || dev->disconnected) + if (!dev->online || dev->disconnected) { + pr_debug("acc_write disconnected or not online"); return -ENODEV; + } while (count > 0) { if (!dev->online) { diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c index 26e4bd53642..e588849f961 100644 --- a/drivers/usb/gadget/f_qdss.c +++ b/drivers/usb/gadget/f_qdss.c @@ -583,7 +583,7 @@ static int qdss_bind_config(struct usb_configuration *c, const char *name) spin_lock_irqsave(&d_lock, flags); list_for_each_entry(ch, &usb_qdss_ch_list, list) { - if (!strncmp(name, ch->name, sizeof(ch->name))) { + if (!strncmp(name, ch->name, sizeof(*ch->name))) { found = 1; break; } @@ -737,7 +737,7 @@ struct usb_qdss_ch *usb_qdss_open(const char *name, void *priv, spin_lock_irqsave(&d_lock, flags); /* Check if we already have a channel with this name */ list_for_each_entry(ch, &usb_qdss_ch_list, list) { - if (!strncmp(name, ch->name, sizeof(ch->name))) { + if (!strncmp(name, ch->name, sizeof(*ch->name))) { found = 1; break; } diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index a60679cbbf8..9961c461a1b 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -829,7 +829,7 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) { int status; unsigned uframe; - __hc32 c_mask; + __hc32 c_mask = 0; unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ struct ehci_qh_hw *hw = qh->hw; diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c index 54603bb5932..afb88b6fe72 100755 --- a/drivers/usb/otg/msm_otg.c +++ b/drivers/usb/otg/msm_otg.c @@ -10,7 +10,7 @@ * GNU General Public License for more details. * */ - +#define DEBUG #include #include #include @@ -55,6 +55,11 @@ #include #include +#ifdef CONFIG_FORCE_FAST_CHARGE +#include +#define USB_FASTCHG_LOAD 1000 /* uA */ +#endif + #define MSM_USB_BASE (motg->regs) #define DRIVER_NAME "msm_otg" @@ -93,6 +98,10 @@ static struct workqueue_struct *msm_otg_id_pin_wq; static int global_vbus_suspend_status; static int global_id_pin_suspend_status; +//otg+charge: sysfs entry +static bool usbhost_charge_mode = false; +module_param(usbhost_charge_mode, bool, 0755); + /* APQ8064 GPIO pin definition */ #define APQ_AP_ACOK 23 #define APQ_OTG_ID_PIN 77 @@ -158,6 +167,9 @@ static void asus_chg_set_chg_mode(enum usb_chg_type chg_src) printk(KERN_INFO "The USB cable status = CHARGER_CDP\n"); break; case USB_ACA_A_CHARGER: + usb_cable_type_detect(CHARGER_ACA); + printk(KERN_INFO "The USB cable status = CHARGER_ACA\n"); + break; case USB_ACA_B_CHARGER: case USB_ACA_C_CHARGER: case USB_ACA_DOCK_CHARGER: @@ -1130,8 +1142,9 @@ static int msm_otg_notify_host_mode(struct msm_otg *motg, bool host_mode) if (!psy) goto psy_not_supported; - - if (host_mode) { + //otg+charge: need to set POWER_SUPPLY_SCOPE_DEVICE or else it doesn't + //detect vbus + if (host_mode && !usbhost_charge_mode) { ret = power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_SYSTEM); } else { ret = power_supply_set_scope(psy, POWER_SUPPLY_SCOPE_DEVICE); @@ -1228,7 +1241,14 @@ static void msm_otg_notify_charger(struct msm_otg *motg, unsigned mA) if (motg->cur_power == mA) return; - +#ifdef CONFIG_FORCE_FAST_CHARGE + if (force_fast_charge == 1) { + mA = USB_FASTCHG_LOAD; + pr_info("USB fast charging is ON - 1000mA.\n"); + } else { + pr_info("USB fast charging is OFF.\n"); + } +#endif dev_info(motg->phy.dev, "Avail curr from USB = %u\n", mA); pm8921_charger_vbus_draw(mA); @@ -1267,7 +1287,11 @@ static void msm_otg_start_host(struct usb_otg *otg, int on) if (on) { dev_dbg(otg->phy->dev, "host on\n"); - smb345_otg_status(true); + //otg+charge: don't use battery to power perhipherals in host mode + if (usbhost_charge_mode) + smb345_otg_status(false); + else + smb345_otg_status(true); otg_host_on = 1; // Reset to apply new parameter for host. @@ -1383,6 +1407,13 @@ static void msm_hsusb_vbus_power(struct msm_otg *motg, bool on) int ret; static bool vbus_is_on; + //otg+charge: just to be safe, turn off battery power to otg perhipheral + if (usbhost_charge_mode) { + printk("[usbhost_charge_mode]: Do not supply power in host mode\n"); + msm_otg_notify_host_mode(motg, on); + return; + } + if (vbus_is_on == on) return; @@ -2244,11 +2275,17 @@ static void msm_chg_detect_work(struct work_struct *w) break; } - if (line_state) /* DP > VLGC or/and DM > VLGC */ - motg->chg_type = USB_PROPRIETARY_CHARGER; - else + if (line_state) { /* DP > VLGC or/and DM > VLGC */ + //otg+charge + if (usbhost_charge_mode) { + motg->chg_type = USB_ACA_A_CHARGER; + } else { + motg->chg_type = USB_PROPRIETARY_CHARGER; + } + } else { motg->chg_type = USB_SDP_CHARGER; - + } + motg->chg_state = USB_CHG_STATE_DETECTED; delay = 0; } @@ -2400,6 +2437,7 @@ static void msm_otg_sm_work(struct work_struct *w) work = 1; break; } + clear_bit(B_BUS_REQ, &motg->inputs); set_bit(A_BUS_REQ, &motg->inputs); otg->phy->state = OTG_STATE_A_IDLE; @@ -2672,6 +2710,7 @@ static void msm_otg_sm_work(struct work_struct *w) msm_otg_notify_charger(motg, 0); else msm_hsusb_vbus_power(motg, 1); + msm_otg_start_timer(motg, TA_WAIT_VRISE, A_WAIT_VRISE); } else { pr_debug("No session requested\n"); @@ -2753,6 +2792,16 @@ static void msm_otg_sm_work(struct work_struct *w) } else if (test_bit(ID_A, &motg->inputs)) { msm_hsusb_vbus_power(motg, 0); } else if (!test_bit(A_BUS_REQ, &motg->inputs)) { + //otg+charge: if there is current, start charging + if (usbhost_charge_mode) { + if (test_bit(B_SESS_VLD, &motg->inputs)) { + pr_debug("b_sess_vld\n"); + usleep_range(10000, 12000); + if (motg->chg_state == USB_CHG_STATE_UNDEFINED) + msm_chg_detect_work(&motg->chg_work.work); + } + } + /* * If TA_WAIT_BCON is infinite, we don;t * turn off VBUS. Enter low power mode. @@ -3108,15 +3157,33 @@ static void msm_otg_set_vbus_state(int online) struct usb_otg *otg = motg->phy.otg; /* In A Host Mode, ignore received BSV interrupts */ - if (otg->phy->state >= OTG_STATE_A_IDLE) + //otg+charge: ignore unless usbhost_charge_mode, then we want to sense vbus + if (!usbhost_charge_mode && otg->phy->state >= OTG_STATE_A_IDLE) return; if (online) { pr_debug("PMIC: BSV set\n"); + //printk("connected charger\n"); set_bit(B_SESS_VLD, &motg->inputs); + if (otg->phy->state >= OTG_STATE_A_IDLE && usbhost_charge_mode) { + printk("[usbhost_charge_mode]: already in host mode, restart chg_work"); + msm_chg_detect_work(&motg->chg_work.work); + } + } else { pr_debug("PMIC: BSV clear\n"); + //printk("disconnected charger\n"); clear_bit(B_SESS_VLD, &motg->inputs); + + //otg+charge: cancel charging when power is disconnected + if (otg->phy->state >= OTG_STATE_A_IDLE && usbhost_charge_mode) { + printk("[usbhost_charge_mode]: chg_work cancel from set vbus state"); + cancel_delayed_work_sync(&motg->chg_work); + motg->chg_state = USB_CHG_STATE_UNDEFINED; + motg->chg_type = USB_INVALID_CHARGER; + asus_chg_set_chg_mode(USB_INVALID_CHARGER); + msm_otg_notify_charger(motg, 0); + } } if (!init) { @@ -3162,6 +3229,9 @@ static void id_pin_irq_work_function(struct work_struct *work) else { pr_debug("%s: gpio_get_value(APQ_OTG_ID_PIN) = %d\n", __func__, gpio_get_value(APQ_OTG_ID_PIN)); if (gpio == 0 && otg_host_on == 0) { + //otg+charge: this needs a slight delay or else it doesn't start charging + if (usbhost_charge_mode) + msleep(40); pr_info("%s: APQ_OTG_ID_PIN is low : Host mode\n", __func__); set_bit(A_BUS_REQ, &motg->inputs); clear_bit(ID, &motg->inputs); @@ -3195,7 +3265,7 @@ static irqreturn_t msm_otg_acok_irq(int irq, void *dev_id) struct msm_otg *motg = dev_id; queue_delayed_work(msm_otg_acok_wq, &motg->acok_irq_work, 0.6*HZ); - wake_lock_timeout(&motg->wlock, 1*HZ); + wake_lock_timeout(&motg->cable_lock, 1*HZ); return IRQ_HANDLED; } @@ -3205,7 +3275,7 @@ static irqreturn_t msm_otg_id_pin_irq(int irq, void *dev_id) struct msm_otg *motg = dev_id; queue_delayed_work(msm_otg_id_pin_wq, &motg->id_pin_irq_work, 0.6*HZ); - wake_lock_timeout(&motg->wlock, 1*HZ); + wake_lock_timeout(&motg->cable_lock, 1*HZ); return IRQ_HANDLED; } @@ -3972,6 +4042,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) if (ret) dev_dbg(&pdev->dev, "MHL can not be supported\n"); wake_lock_init(&motg->wlock, WAKE_LOCK_SUSPEND, "msm_otg"); + wake_lock_init(&motg->cable_lock, WAKE_LOCK_SUSPEND, "msm_cable_dectect"); msm_otg_init_timer(motg); INIT_WORK(&motg->sm_work, msm_otg_sm_work); INIT_DELAYED_WORK(&motg->chg_work, msm_chg_detect_work); @@ -4094,6 +4165,7 @@ static int __init msm_otg_probe(struct platform_device *pdev) free_irq(motg->irq, motg); destroy_wlock: wake_lock_destroy(&motg->wlock); + wake_lock_destroy(&motg->cable_lock); clk_disable_unprepare(motg->core_clk); msm_hsusb_ldo_enable(motg, 0); free_ldo_init: @@ -4152,6 +4224,7 @@ static int __devexit msm_otg_remove(struct platform_device *pdev) device_init_wakeup(&pdev->dev, 0); pm_runtime_disable(&pdev->dev); wake_lock_destroy(&motg->wlock); + wake_lock_destroy(&motg->cable_lock); msm_otg_id_pin_free(motg); msm_otg_acok_free(motg); @@ -4294,12 +4367,12 @@ static int msm_otg_pm_resume(struct device *dev) if (gpio_get_value(vbus_det_gpio) != global_vbus_suspend_status) { dev_info(dev, "%s: usb vbus change in suspend\n", __func__); - wake_lock_timeout(&motg->wlock, 1*HZ); + wake_lock_timeout(&motg->cable_lock, 1*HZ); } if (gpio_get_value(id_gpio) != global_id_pin_suspend_status) { dev_info(dev, "%s: usb id pin change in suspend\n", __func__); - wake_lock_timeout(&motg->wlock, 1*HZ); + wake_lock_timeout(&motg->cable_lock, 1*HZ); } return 0; @@ -4347,3 +4420,4 @@ module_exit(msm_otg_exit); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("MSM USB transceiver driver"); + diff --git a/drivers/usb/serial/usb-wwan.h b/drivers/usb/serial/usb-wwan.h index 98b399fe3d4..84336d61d82 100644 --- a/drivers/usb/serial/usb-wwan.h +++ b/drivers/usb/serial/usb-wwan.h @@ -33,10 +33,10 @@ extern int usb_wwan_resume(struct usb_serial *serial); /* per port private data */ -#define N_IN_URB 5 -#define N_OUT_URB 5 -#define IN_BUFLEN 16384 -#define OUT_BUFLEN 65536 +#define N_IN_URB 4 +#define N_OUT_URB 4 +#define IN_BUFLEN 4096 +#define OUT_BUFLEN 4096 struct usb_wwan_intf_private { spinlock_t susp_lock; diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index c70109e5d60..32a21c09d11 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -467,7 +467,7 @@ static int usb_stor_bulk_transfer_sglist(struct us_data *us, unsigned int pipe, int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, struct scsi_cmnd* srb) { - unsigned int partial; + unsigned int partial = 0; int result = usb_stor_bulk_transfer_sglist(us, pipe, scsi_sglist(srb), scsi_sg_count(srb), scsi_bufflen(srb), &partial); @@ -490,7 +490,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, void *buf, unsigned int length_left, int use_sg, int *residual) { int result; - unsigned int partial; + unsigned int partial = 0; /* are we scatter-gathering? */ if (use_sg) { diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c index a9e9af582ea..9c6b1778f81 100644 --- a/drivers/video/msm/mdp.c +++ b/drivers/video/msm/mdp.c @@ -171,10 +171,8 @@ static u32 mdp_irq; static uint32 mdp_prim_panel_type = NO_PANEL; #ifndef CONFIG_FB_MSM_MDP22 -#define MDP_HIST_LUT_SIZE (256) struct list_head mdp_hist_lut_list; DEFINE_MUTEX(mdp_hist_lut_list_mutex); -uint32_t last_lut[MDP_HIST_LUT_SIZE]; uint32_t mdp_block2base(uint32_t block) { @@ -301,15 +299,11 @@ static int mdp_hist_lut_destroy(void) static int mdp_hist_lut_init(void) { - int i; struct mdp_hist_lut_mgmt *temp; if (mdp_pp_initialized) return -EEXIST; - for (i = 0; i < MDP_HIST_LUT_SIZE; i++) - last_lut[i] = i | (i << 8) | (i << 16); - INIT_LIST_HEAD(&mdp_hist_lut_list); if (mdp_rev >= MDP_REV_30) { @@ -369,6 +363,7 @@ static int mdp_hist_lut_block2mgmt(uint32_t block, return ret; } +#define MDP_HIST_LUT_SIZE (256) static int mdp_hist_lut_write_off(struct mdp_hist_lut_data *data, struct mdp_hist_lut_info *info, uint32_t offset) { @@ -390,11 +385,9 @@ static int mdp_hist_lut_write_off(struct mdp_hist_lut_data *data, } mdp_clk_ctrl(1); mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE); - for (i = 0; i < MDP_HIST_LUT_SIZE; i++) { - last_lut[i] = element[i]; + for (i = 0; i < MDP_HIST_LUT_SIZE; i++) MDP_OUTP(MDP_BASE + base + offset + (0x400*(sel)) + (4*i), element[i]); - } mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE); mdp_clk_ctrl(0); @@ -565,14 +558,15 @@ static int mdp_lut_hw_update(struct fb_cmap *cmap) copy_from_user(&b, cmap->blue++, sizeof(b))) return -EFAULT; - last_lut[i] = ((g & 0xff) | ((b & 0xff) << 8) | - ((r & 0xff) << 16)); #ifdef CONFIG_FB_MSM_MDP40 MDP_OUTP(MDP_BASE + 0x94800 + #else MDP_OUTP(MDP_BASE + 0x93800 + #endif - (0x400*mdp_lut_i) + cmap->start*4 + i*4, last_lut[i]); + (0x400*mdp_lut_i) + cmap->start*4 + i*4, + ((g & 0xff) | + ((b & 0xff) << 8) | + ((r & 0xff) << 16))); } return 0; @@ -664,11 +658,11 @@ int mdp_preset_lut_update_lcdc(struct fb_cmap *cmap, uint32_t *internal_lut) r = lut2r(internal_lut[i]); g = lut2g(internal_lut[i]); b = lut2b(internal_lut[i]); -#ifdef CONFIG_LCD_KCAL + r = scaled_by_kcal(r, *(cmap->red)); g = scaled_by_kcal(g, *(cmap->green)); b = scaled_by_kcal(b, *(cmap->blue)); -#endif + MDP_OUTP(MDP_BASE + 0x94800 + (0x400*mdp_lut_i) + cmap->start*4 + i*4, ((g & 0xff) | @@ -685,6 +679,7 @@ int mdp_preset_lut_update_lcdc(struct fb_cmap *cmap, uint32_t *internal_lut) return 0; } +EXPORT_SYMBOL(mdp_preset_lut_update_lcdc); #endif static void mdp_lut_enable(void) @@ -2426,7 +2421,6 @@ static int mdp_on(struct platform_device *pdev) { int ret = 0; struct msm_fb_data_type *mfd; - int i; mfd = platform_get_drvdata(pdev); pr_debug("%s:+\n", __func__); @@ -2452,11 +2446,6 @@ static int mdp_on(struct platform_device *pdev) mdp_clk_ctrl(1); mdp_bus_scale_restore_request(); mdp4_hw_init(); - /* Initialize HistLUT to last LUT */ - for (i = 0; i < MDP_HIST_LUT_SIZE; i++) { - MDP_OUTP(MDP_BASE + 0x94800 + i*4, last_lut[i]); - MDP_OUTP(MDP_BASE + 0x94C00 + i*4, last_lut[i]); - } mdp_lut_status_restore(); outpdw(MDP_BASE + 0x0038, mdp4_display_intf); if (mfd->panel.type == MIPI_CMD_PANEL) { diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h index 4e6ab16c736..fffb67c6ac7 100644 --- a/drivers/video/msm/mdp.h +++ b/drivers/video/msm/mdp.h @@ -938,13 +938,11 @@ static inline void mdp_vid_quant_set(void) #define lut2g(lut) ((lut & G_MASK) >> G_SHIFT) #define lut2b(lut) ((lut & B_MASK) >> B_SHIFT) -#ifdef CONFIG_LCD_KCAL #define NUM_QLUT 256 #define MAX_KCAL_V (NUM_QLUT-1) #define scaled_by_kcal(rgb, kcal) \ (((((unsigned int)(rgb) * (unsigned int)(kcal)) << 16) / \ (unsigned int)MAX_KCAL_V) >> 16) -#endif int mdp_preset_lut_update_lcdc(struct fb_cmap *cmap, uint32_t *internal_lut); #endif #endif /* MDP_H */ diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h index b9305fb6842..653ea096340 100644 --- a/drivers/video/msm/mdp4.h +++ b/drivers/video/msm/mdp4.h @@ -298,8 +298,6 @@ struct mdp4_overlay_pipe { uint32 src_format; uint32 src_width; /* source img width */ uint32 src_height; /* source img height */ - uint32 prev_src_width; /* source img width */ - uint32 prev_src_height; /* source img height */ uint32 is_3d; uint32 src_width_3d; /* source img width */ uint32 src_height_3d; /* source img height */ diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c index 74ec84ed6a7..6f05e97a920 100644 --- a/drivers/video/msm/mdp4_overlay.c +++ b/drivers/video/msm/mdp4_overlay.c @@ -44,6 +44,8 @@ #define VERSION_KEY_MASK 0xFFFFFF00 +static u64 MDP_BUS_SCALE_MIN_IB_FOR_MAX_LAYERS = 0x60000000; + struct mdp4_overlay_ctrl { struct mdp4_overlay_pipe plist[OVERLAY_PIPE_MAX]; struct mdp4_overlay_pipe *stage[MDP4_MIXER_MAX][MDP4_MIXER_STAGE_MAX]; @@ -989,29 +991,8 @@ void mdp4_overlay_vg_setup(struct mdp4_overlay_pipe *pipe) outpdw(vg_base + 0x0008, dst_size); /* MDP_RGB_DST_SIZE */ outpdw(vg_base + 0x000c, dst_xy); /* MDP_RGB_DST_XY */ - if (pipe->frame_format != MDP4_FRAME_FORMAT_LINEAR) { - struct mdp4_overlay_pipe *real_pipe; - u32 psize, csize; - - /* - * video tile frame size register is NOT double buffered. - * when this register updated, it kicks in immediatly - * During transition from smaller resolution to higher - * resolution it may have possibility that mdp still fetch - * from smaller resolution buffer with new higher resolution - * frame size. This will cause iommu page fault. - */ - real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx); - psize = real_pipe->prev_src_height * real_pipe->prev_src_width; - csize = pipe->src_height * pipe->src_width; - if (psize && (csize > psize)) { - frame_size = (real_pipe->prev_src_height << 16 | - real_pipe->prev_src_width); - } + if (pipe->frame_format != MDP4_FRAME_FORMAT_LINEAR) outpdw(vg_base + 0x0048, frame_size); /* TILE frame size */ - real_pipe->prev_src_height = pipe->src_height; - real_pipe->prev_src_width = pipe->src_width; - } /* * Adjust src X offset to avoid MDP from overfetching pixels @@ -3048,6 +3029,13 @@ int mdp4_overlay_mdp_perf_req(struct msm_fb_data_type *mfd) } } + /* Flo specific change to increase IB request when we have >4 layers + * but not all of them are covering the whole screen */ + if (cnt > 4) { + ib_quota_total = max(ib_quota_total, + MDP_BUS_SCALE_MIN_IB_FOR_MAX_LAYERS); + } + perf_req->mdp_ab_bw = roundup(ab_quota_total, MDP_BUS_SCALE_AB_STEP); perf_req->mdp_ib_bw = roundup(ib_quota_total, MDP_BUS_SCALE_AB_STEP); diff --git a/drivers/video/msm/mipi_JDI.c b/drivers/video/msm/mipi_JDI.c index 343d0da00d7..1c39145d779 100644 --- a/drivers/video/msm/mipi_JDI.c +++ b/drivers/video/msm/mipi_JDI.c @@ -254,7 +254,7 @@ static void JDI_command_backlight(int level) cmdreq_JDI.cmds = backlight_cmd; cmdreq_JDI.cmds_cnt = ARRAY_SIZE(backlight_cmd); - cmdreq_JDI.flags = CMD_REQ_COMMIT; + cmdreq_JDI.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL; cmdreq_JDI.rlen = 0; cmdreq_JDI.cb = NULL; mipi_dsi_cmdlist_put(&cmdreq_JDI); @@ -369,7 +369,7 @@ static void mipi_JDI_lcd_shutdown(void) pr_info("%s, JDI display off command+\n", __func__); cmdreq_JDI.cmds = JDI_display_off_cmds; cmdreq_JDI.cmds_cnt = ARRAY_SIZE(JDI_display_off_cmds); - cmdreq_JDI.flags = CMD_REQ_COMMIT; + cmdreq_JDI.flags = CMD_REQ_COMMIT | CMD_CLK_CTRL; cmdreq_JDI.rlen = 0; cmdreq_JDI.cb = NULL; mipi_dsi_cmdlist_put(&cmdreq_JDI); diff --git a/drivers/video/msm/mipi_novatek.c b/drivers/video/msm/mipi_novatek.c index 09630531767..e5f343a6db4 100644 --- a/drivers/video/msm/mipi_novatek.c +++ b/drivers/video/msm/mipi_novatek.c @@ -680,7 +680,7 @@ static ssize_t mipi_dsi_3d_barrier_read(struct device *dev, struct device_attribute *attr, char *buf) { - return snprintf((char *)buf, sizeof(buf), "%u\n", barrier_mode); + return snprintf((char *)buf, sizeof(*buf), "%u\n", barrier_mode); } static ssize_t mipi_dsi_3d_barrier_write(struct device *dev, diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c index b6094b45081..5572c397948 100644 --- a/drivers/video/msm/msm_fb.c +++ b/drivers/video/msm/msm_fb.c @@ -46,6 +46,7 @@ #include #include #include +#include #define MSM_FB_C #include "msm_fb.h" @@ -62,6 +63,9 @@ #undef CONFIG_HAS_EARLYSUSPEND #endif +int backlight_dimmer = 0; +module_param(backlight_dimmer, int, 0755); + static unsigned char *fbram; static unsigned char *fbram_phys; static int fbram_size; @@ -200,11 +204,21 @@ static void msm_fb_set_bl_brightness(struct led_classdev *led_cdev, bl_lvl = 0; else if (value >= MAX_BACKLIGHT_BRIGHTNESS) bl_lvl = mfd->panel_info.bl_max; - else + else if (backlight_dimmer > 0) { + if (value <= backlight_dimmer) { + bl_lvl = 1; + } else { + bl_lvl = (mfd->panel_info.bl_min + ((value - 1) * 2 * + (mfd->panel_info.bl_max - mfd->panel_info.bl_min) + + MAX_BACKLIGHT_BRIGHTNESS - 1) / + (MAX_BACKLIGHT_BRIGHTNESS - 1) / 2) - backlight_dimmer; + } + } else { bl_lvl = mfd->panel_info.bl_min + ((value - 1) * 2 * (mfd->panel_info.bl_max - mfd->panel_info.bl_min) + MAX_BACKLIGHT_BRIGHTNESS - 1) / (MAX_BACKLIGHT_BRIGHTNESS - 1) / 2; + } down(&mfd->sem); msm_fb_set_backlight(mfd, bl_lvl); @@ -1604,6 +1618,11 @@ static int msm_fb_register(struct msm_fb_data_type *mfd) ("FrameBuffer[%d] %dx%d size=%d bytes is registered successfully!\n", mfd->index, fbi->var.xres, fbi->var.yres, fbi->fix.smem_len); +#ifdef CONFIG_UPDATE_LCDC_LUT + if (msm_fb_pdata->update_lcdc_lut) + msm_fb_pdata->update_lcdc_lut(); +#endif + #ifdef CONFIG_FB_MSM_LOGO /* Flip buffer */ if (!load_565rle_image(INIT_IMAGE_FILE, bf_supported)) diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c index 89fb312b61b..34b13a77f7b 100644 --- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c +++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c @@ -2003,14 +2003,19 @@ u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder, struct vcd_buffer_requirement *output_buf_req; u32 min_dpb, y_cb_cr_size; u32 frame_height_actual = 0; + u32 min_dpb_from_res_trk = 0; - if (!decoder->codec.codec) + if (!decoder->codec.codec) { + DDL_MSG_ERROR("%s: codec not set", __func__); return false; + } if (estimate) { - if (!decoder->cont_mode) - min_dpb = ddl_decoder_min_num_dpb(decoder); - else + if (decoder->cont_mode && + decoder->codec.codec == VCD_CODEC_H264) { min_dpb = res_trk_get_min_dpb_count(); + min_dpb_from_res_trk = 1; + } else + min_dpb = ddl_decoder_min_num_dpb(decoder); frame_size = &decoder->client_frame_size; output_buf_req = &decoder->client_output_buf_req; input_buf_req = &decoder->client_input_buf_req; @@ -2023,6 +2028,17 @@ u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder, output_buf_req = &decoder->actual_output_buf_req; input_buf_req = &decoder->actual_input_buf_req; min_dpb = decoder->min_dpb_num; + if (decoder->cont_mode && + decoder->codec.codec == VCD_CODEC_H264) { + min_dpb = res_trk_get_min_dpb_count(); + min_dpb_from_res_trk = 1; + if (min_dpb < decoder->min_dpb_num) { + DDL_MSG_HIGH("Warning: cont_mode dpb count"\ + "(%u) is less than decoder min dpb count(%u)", + min_dpb, decoder->min_dpb_num); + min_dpb = decoder->min_dpb_num; + } + } if ((decoder->buf_format.buffer_format == VCD_BUFFER_FORMAT_TILE_4x2) && (frame_size->height < MDP_MIN_TILE_HEIGHT)) { @@ -2041,14 +2057,13 @@ u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder, } memset(output_buf_req, 0, sizeof(struct vcd_buffer_requirement)); - if (!decoder->idr_only_decoding && !decoder->cont_mode) + if (!decoder->idr_only_decoding && !min_dpb_from_res_trk) output_buf_req->actual_count = min_dpb + 4; else output_buf_req->actual_count = min_dpb; output_buf_req->min_count = min_dpb; output_buf_req->max_count = DDL_MAX_BUFFER_COUNT; output_buf_req->sz = y_cb_cr_size; - DDL_MSG_LOW("output_buf_req->sz : %d", output_buf_req->sz); if (decoder->buf_format.buffer_format != VCD_BUFFER_FORMAT_NV12) output_buf_req->align = DDL_TILE_BUFFER_ALIGN_BYTES; else @@ -2057,6 +2072,14 @@ u32 ddl_set_default_decoder_buffer_req(struct ddl_decoder_data *decoder, output_buf_req); decoder->min_output_buf_req = *output_buf_req; + DDL_MSG_HIGH("out_buf_req: estimate = %u, WxH = %ux%u, "\ + "min_dpb = %u, sz = %d, act = %u, min = %u, max = %u, "\ + "align = %u, meta_buf_size = %d", estimate, + frame_size->width, frame_size->height, min_dpb, + output_buf_req->sz, output_buf_req->actual_count, + output_buf_req->min_count, output_buf_req->max_count, + output_buf_req->align, output_buf_req->meta_buffer_size); + memset(input_buf_req, 0, sizeof(struct vcd_buffer_requirement)); input_buf_req->min_count = 1; @@ -2173,8 +2196,8 @@ static u32 ddl_decoder_min_num_dpb(struct ddl_decoder_data *decoder) case VCD_CODEC_H264: { u32 yuv_size_in_mb = DDL_MIN(DDL_NO_OF_MB( - decoder->client_frame_size.stride, - decoder->client_frame_size.scan_lines), + decoder->client_frame_size.width, + decoder->client_frame_size.height), MAX_FRAME_SIZE_L4PT0_MBS); min_dpb = DDL_MIN((MAX_DPB_SIZE_L4PT0_MBS / yuv_size_in_mb), 16); diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c index 808ba7999f0..7418ac4e0ae 100644 --- a/drivers/video/msm/vidc/common/enc/venc_internal.c +++ b/drivers/video/msm/vidc/common/enc/venc_internal.c @@ -1584,7 +1584,12 @@ u32 vid_enc_set_buffer(struct video_client_ctx *client_ctx, enum vcd_buffer_type vcd_buffer_t = VCD_BUFFER_INPUT; enum buffer_dir dir_buffer = BUFFER_TYPE_INPUT; u32 vcd_status = VCD_ERR_FAIL; - unsigned long kernel_vaddr, length = 0; + unsigned long kernel_vaddr, length, user_vaddr, phy_addr = 0; + int pmem_fd = 0; + struct ion_handle *buff_handle = NULL; + u32 ion_flag = 0; + struct file *file = NULL; + s32 buffer_index = 0; if (!client_ctx || !buffer_info) return false; @@ -1606,6 +1611,39 @@ u32 vid_enc_set_buffer(struct video_client_ctx *client_ctx, return false; } + /* + * Invalidate output buffers explcitly once, during registration + * This ensures any pending CPU writes (eg. memset 0 after allocation) + * are not flushed _after_the hardware has written bitstream. + * rare bug, but can happen + */ + if (buffer == VEN_BUFFER_TYPE_OUTPUT) { + user_vaddr = (unsigned long)buffer_info->pbuffer; + if (!vidc_lookup_addr_table(client_ctx, BUFFER_TYPE_OUTPUT, + true, &user_vaddr, &kernel_vaddr, + &phy_addr, &pmem_fd, &file, + &buffer_index)) { + ERR("%s(): vidc_lookup_addr_table failed\n", + __func__); + return false; + } + + ion_flag = vidc_get_fd_info(client_ctx, BUFFER_TYPE_OUTPUT, + buffer_info->fd, kernel_vaddr, buffer_index, + &buff_handle); + + if (ion_flag == ION_FLAG_CACHED && buff_handle && + kernel_vaddr) { + msm_ion_do_cache_op( + client_ctx->user_ion_client, + buff_handle, + (unsigned long *) kernel_vaddr, + (unsigned long) length, + ION_IOC_INV_CACHES); + } + } + + vcd_status = vcd_set_buffer(client_ctx->vcd_handle, vcd_buffer_t, (u8 *) kernel_vaddr, buffer_info->sz); diff --git a/fs/Kconfig b/fs/Kconfig index 1dd49481854..4719f207985 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -103,6 +103,7 @@ menu "DOS/FAT/NT Filesystems" source "fs/fat/Kconfig" source "fs/ntfs/Kconfig" +source "fs/exfat/Kconfig" endmenu endif # BLOCK @@ -224,6 +225,7 @@ source "fs/pstore/Kconfig" source "fs/sysv/Kconfig" source "fs/ufs/Kconfig" source "fs/exofs/Kconfig" +source "fs/f2fs/Kconfig" endif # MISC_FILESYSTEMS @@ -280,4 +282,36 @@ endif # NETWORK_FILESYSTEMS source "fs/nls/Kconfig" source "fs/dlm/Kconfig" +config DYNAMIC_FSYNC + bool "dynamic file sync control" + default n + help + An experimental file sync control using Android's early suspend / late resume drivers + + +config RESTRICT_ROOTFS_SLAVE + bool "Android: Restrict rootfs slave mountspace to /storage" + help + Restrict slave mountspace so Dalvik apps can mount system-wide volumes + + Android 4.2 implements multi-user storage using per-process mount + namespaces. Everything under "/" (the entire filesystem hierarchy) is + marked as a recursive-slave mountspace for all zygote instances. This is + done so that user-storage sandbox mounts under /storage/emulated are hidden + from other apps and users. Unfortunately this means that any Dalvik app + (actually, any program whose clone/fork ancestry includes a Dalvik zygote, + which is everything except services spawned directly from init) cannot + mount system-wide volumes. + + This option restricts rootfs-slave calls to /storage (and + /mnt/shell/emulated) so that Dalvik apps can mount system-wide volumes + elsewhere (with appropriate permission, as in earlier versions of Android), + while retaining full multi-user storage compatibility. It is made + available as a kernel-based workaround for instances where libdvm can not + be modified. + + This option requires that a tmpfs volume is mounted as /storage in + Android init.rc. If this volume is unavailable, then we fall back to the + previous behavior of marking the entire filesystem hierarchy as slave. + endmenu diff --git a/fs/Makefile b/fs/Makefile index 95cf9de6ae0..c1f4306ea34 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -45,7 +45,7 @@ obj-$(CONFIG_BINFMT_SOM) += binfmt_som.o obj-$(CONFIG_BINFMT_FLAT) += binfmt_flat.o obj-$(CONFIG_FS_MBCACHE) += mbcache.o -obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o xattr_acl.o +obj-$(CONFIG_FS_POSIX_ACL) += posix_acl.o obj-$(CONFIG_NFS_COMMON) += nfs_common/ obj-$(CONFIG_GENERIC_ACL) += generic_acl.o @@ -94,6 +94,7 @@ obj-$(CONFIG_CIFS) += cifs/ obj-$(CONFIG_NCP_FS) += ncpfs/ obj-$(CONFIG_HPFS_FS) += hpfs/ obj-$(CONFIG_NTFS_FS) += ntfs/ +obj-$(CONFIG_EXFAT_FS) += exfat/ obj-$(CONFIG_UFS_FS) += ufs/ obj-$(CONFIG_EFS_FS) += efs/ obj-$(CONFIG_JFFS2_FS) += jffs2/ @@ -122,9 +123,12 @@ obj-$(CONFIG_DEBUG_FS) += debugfs/ obj-$(CONFIG_OCFS2_FS) += ocfs2/ obj-$(CONFIG_BTRFS_FS) += btrfs/ obj-$(CONFIG_GFS2_FS) += gfs2/ +obj-$(CONFIG_F2FS_FS) += f2fs/ obj-y += exofs/ # Multiple modules obj-$(CONFIG_CEPH_FS) += ceph/ obj-$(CONFIG_PSTORE) += pstore/ # Patched by YAFFS obj-$(CONFIG_YAFFS_FS) += yaffs2/ + +obj-$(CONFIG_DYNAMIC_FSYNC) += dyn_sync_cntrl.o diff --git a/fs/aio.c b/fs/aio.c index 67a6db3e1b6..de8a503a313 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1682,7 +1682,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, struct kioctx *ctx; long ret = 0; int i = 0; - struct blk_plug plug; struct kiocb_batch batch; if (unlikely(nr < 0)) @@ -1702,8 +1701,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, kiocb_batch_init(&batch, nr); - blk_start_plug(&plug); - /* * AKPM: should this return a partial result if some of the IOs were * successfully submitted? @@ -1726,7 +1723,6 @@ long do_io_submit(aio_context_t ctx_id, long nr, if (ret) break; } - blk_finish_plug(&plug); kiocb_batch_free(ctx, &batch); put_ioctx(ctx); diff --git a/fs/bio.c b/fs/bio.c index 84da8853904..1fa2f67bd76 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -679,6 +679,42 @@ struct bio_map_data { int is_our_pages; }; +struct submit_bio_ret { + struct completion event; + int error; +}; + +static void submit_bio_wait_endio(struct bio *bio, int error) +{ + struct submit_bio_ret *ret = bio->bi_private; + + ret->error = error; + complete(&ret->event); +} + +/** + * submit_bio_wait - submit a bio, and wait until it completes + * @rw: whether to %READ or %WRITE, or maybe to %READA (read ahead) + * @bio: The &struct bio which describes the I/O + * + * Simple wrapper around submit_bio(). Returns 0 on success, or the error from + * bio_endio() on failure. + */ +int submit_bio_wait(int rw, struct bio *bio) +{ + struct submit_bio_ret ret; + + rw |= REQ_SYNC; + init_completion(&ret.event); + bio->bi_private = &ret; + bio->bi_end_io = submit_bio_wait_endio; + submit_bio(rw, bio); + wait_for_completion(&ret.event); + + return ret.error; +} +EXPORT_SYMBOL(submit_bio_wait); + static void bio_set_map_data(struct bio_map_data *bmd, struct bio *bio, struct sg_iovec *iov, int iov_count, int is_our_pages) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index 2b243af70aa..f66cc162515 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -139,7 +139,8 @@ config CIFS_DFS_UPCALL points. If unsure, say N. config CIFS_FSCACHE - bool "Provide CIFS client caching support" + bool "Provide CIFS client caching support (EXPERIMENTAL)" + depends on EXPERIMENTAL depends on CIFS=m && FSCACHE || CIFS=y && FSCACHE=y help Makes CIFS FS-Cache capable. Say Y here if you want your CIFS data @@ -147,8 +148,8 @@ config CIFS_FSCACHE manager. If unsure, say N. config CIFS_ACL - bool "Provide CIFS ACL support" - depends on CIFS_XATTR && KEYS + bool "Provide CIFS ACL support (EXPERIMENTAL)" + depends on EXPERIMENTAL && CIFS_XATTR && KEYS help Allows to fetch CIFS/NTFS ACL from the server. The DACL blob is handed over to the application/caller. diff --git a/fs/cifs/README b/fs/cifs/README index b7d782bab79..c5c2c5e5f0f 100644 --- a/fs/cifs/README +++ b/fs/cifs/README @@ -745,14 +745,4 @@ installed and something like the following lines should be added to the create cifs.spnego * * /usr/local/sbin/cifs.upcall %k create dns_resolver * * /usr/local/sbin/cifs.upcall %k -CIFS kernel module parameters -============================= -These module parameters can be specified or modified either during the time of -module loading or during the runtime by using the interface - /proc/module/cifs/parameters/ - -i.e. echo "value" > /sys/module/cifs/parameters/ - -1. enable_oplocks - Enable or disable oplocks. Oplocks are enabled by default. - [Y/y/1]. To disable use any of [N/n/0]. diff --git a/fs/cifs/asn1.c b/fs/cifs/asn1.c index cfd1ce34e0b..1d36db11477 100644 --- a/fs/cifs/asn1.c +++ b/fs/cifs/asn1.c @@ -614,53 +614,10 @@ decode_negTokenInit(unsigned char *security_blob, int length, } } - /* mechlistMIC */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - /* Check if we have reached the end of the blob, but with - no mechListMic (e.g. NTLMSSP instead of KRB5) */ - if (ctx.error == ASN1_ERR_DEC_EMPTY) - goto decode_negtoken_exit; - cFYI(1, "Error decoding last part negTokenInit exit3"); - return 0; - } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { - /* tag = 3 indicating mechListMIC */ - cFYI(1, "Exit 4 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - - /* sequence */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit5"); - return 0; - } else if ((cls != ASN1_UNI) || (con != ASN1_CON) - || (tag != ASN1_SEQ)) { - cFYI(1, "cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - } - - /* sequence of */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit 7"); - return 0; - } else if ((cls != ASN1_CTX) || (con != ASN1_CON)) { - cFYI(1, "Exit 8 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - - /* general string */ - if (asn1_header_decode(&ctx, &end, &cls, &con, &tag) == 0) { - cFYI(1, "Error decoding last part negTokenInit exit9"); - return 0; - } else if ((cls != ASN1_UNI) || (con != ASN1_PRI) - || (tag != ASN1_GENSTR)) { - cFYI(1, "Exit10 cls = %d con = %d tag = %d end = %p (%d)", - cls, con, tag, end, *end); - return 0; - } - cFYI(1, "Need to call asn1_octets_decode() function for %s", - ctx.pointer); /* is this UTF-8 or ASCII? */ -decode_negtoken_exit: + /* + * We currently ignore anything at the end of the SPNEGO blob after + * the mechTypes have been parsed, since none of that info is + * used at the moment. + */ return 1; } diff --git a/fs/cifs/cifs_debug.c b/fs/cifs/cifs_debug.c index 27046462941..2fe3cf13b2e 100644 --- a/fs/cifs/cifs_debug.c +++ b/fs/cifs/cifs_debug.c @@ -58,16 +58,15 @@ cifs_dump_mem(char *label, void *data, int length) } #ifdef CONFIG_CIFS_DEBUG2 -void cifs_dump_detail(void *buf) +void cifs_dump_detail(struct smb_hdr *smb) { - struct smb_hdr *smb = (struct smb_hdr *)buf; - cERROR(1, "Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", smb->Command, smb->Status.CifsError, smb->Flags, smb->Flags2, smb->Mid, smb->Pid); cERROR(1, "smb buf %p len %d", smb, smbCalcSize(smb)); } + void cifs_dump_mids(struct TCP_Server_Info *server) { struct list_head *tmp; @@ -80,15 +79,15 @@ void cifs_dump_mids(struct TCP_Server_Info *server) spin_lock(&GlobalMid_Lock); list_for_each(tmp, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %llu", - mid_entry->mid_state, - le16_to_cpu(mid_entry->command), + cERROR(1, "State: %d Cmd: %d Pid: %d Cbdata: %p Mid %d", + mid_entry->midState, + (int)mid_entry->command, mid_entry->pid, mid_entry->callback_data, mid_entry->mid); #ifdef CONFIG_CIFS_STATS2 cERROR(1, "IsLarge: %d buf: %p time rcv: %ld now: %ld", - mid_entry->large_buf, + mid_entry->largeBuf, mid_entry->resp_buf, mid_entry->when_received, jiffies); @@ -172,11 +171,12 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) seq_printf(m, "TCP status: %d\n\tLocal Users To " "Server: %d SecMode: 0x%x Req On Wire: %d", server->tcpStatus, server->srv_count, - server->sec_mode, in_flight(server)); + server->sec_mode, + atomic_read(&server->inFlight)); #ifdef CONFIG_CIFS_STATS2 seq_printf(m, " In Send: %d In MaxReq Wait: %d", - atomic_read(&server->in_send), + atomic_read(&server->inSend), atomic_read(&server->num_waiters)); #endif @@ -218,12 +218,12 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v) mid_entry = list_entry(tmp3, struct mid_q_entry, qhead); seq_printf(m, "\tState: %d com: %d pid:" - " %d cbdata: %p mid %llu\n", - mid_entry->mid_state, - le16_to_cpu(mid_entry->command), - mid_entry->pid, - mid_entry->callback_data, - mid_entry->mid); + " %d cbdata: %p mid %d\n", + mid_entry->midState, + (int)mid_entry->command, + mid_entry->pid, + mid_entry->callback_data, + mid_entry->mid); } spin_unlock(&GlobalMid_Lock); } @@ -418,6 +418,7 @@ static const struct file_operations cifs_stats_proc_fops = { static struct proc_dir_entry *proc_fs_cifs; static const struct file_operations cifsFYI_proc_fops; +static const struct file_operations cifs_oplock_proc_fops; static const struct file_operations cifs_lookup_cache_proc_fops; static const struct file_operations traceSMB_proc_fops; static const struct file_operations cifs_multiuser_mount_proc_fops; @@ -438,6 +439,7 @@ cifs_proc_init(void) #endif /* STATS */ proc_create("cifsFYI", 0, proc_fs_cifs, &cifsFYI_proc_fops); proc_create("traceSMB", 0, proc_fs_cifs, &traceSMB_proc_fops); + proc_create("OplockEnabled", 0, proc_fs_cifs, &cifs_oplock_proc_fops); proc_create("LinuxExtensionsEnabled", 0, proc_fs_cifs, &cifs_linux_ext_proc_fops); proc_create("MultiuserMount", 0, proc_fs_cifs, @@ -461,6 +463,7 @@ cifs_proc_clean(void) remove_proc_entry("Stats", proc_fs_cifs); #endif remove_proc_entry("MultiuserMount", proc_fs_cifs); + remove_proc_entry("OplockEnabled", proc_fs_cifs); remove_proc_entry("SecurityFlags", proc_fs_cifs); remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs); remove_proc_entry("LookupCacheEnabled", proc_fs_cifs); @@ -506,6 +509,43 @@ static const struct file_operations cifsFYI_proc_fops = { .write = cifsFYI_proc_write, }; +static int cifs_oplock_proc_show(struct seq_file *m, void *v) +{ + seq_printf(m, "%d\n", oplockEnabled); + return 0; +} + +static int cifs_oplock_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, cifs_oplock_proc_show, NULL); +} + +static ssize_t cifs_oplock_proc_write(struct file *file, + const char __user *buffer, size_t count, loff_t *ppos) +{ + char c; + int rc; + + rc = get_user(c, buffer); + if (rc) + return rc; + if (c == '0' || c == 'n' || c == 'N') + oplockEnabled = 0; + else if (c == '1' || c == 'y' || c == 'Y') + oplockEnabled = 1; + + return count; +} + +static const struct file_operations cifs_oplock_proc_fops = { + .owner = THIS_MODULE, + .open = cifs_oplock_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = cifs_oplock_proc_write, +}; + static int cifs_linux_ext_proc_show(struct seq_file *m, void *v) { seq_printf(m, "%d\n", linuxExtEnabled); @@ -633,23 +673,14 @@ static ssize_t cifs_multiuser_mount_proc_write(struct file *file, { char c; int rc; - static bool warned; rc = get_user(c, buffer); if (rc) return rc; if (c == '0' || c == 'n' || c == 'N') multiuser_mount = 0; - else if (c == '1' || c == 'y' || c == 'Y') { + else if (c == '1' || c == 'y' || c == 'Y') multiuser_mount = 1; - if (!warned) { - warned = true; - printk(KERN_WARNING "CIFS VFS: The legacy multiuser " - "mount code is scheduled to be deprecated in " - "3.5. Please switch to using the multiuser " - "mount option."); - } - } return count; } diff --git a/fs/cifs/cifs_debug.h b/fs/cifs/cifs_debug.h index 566e0ae8dc2..8942b28cf80 100644 --- a/fs/cifs/cifs_debug.h +++ b/fs/cifs/cifs_debug.h @@ -26,13 +26,13 @@ void cifs_dump_mem(char *label, void *data, int length); #ifdef CONFIG_CIFS_DEBUG2 #define DBG2 2 -void cifs_dump_detail(void *); +void cifs_dump_detail(struct smb_hdr *); void cifs_dump_mids(struct TCP_Server_Info *); #else #define DBG2 0 #endif extern int traceSMB; /* flag which enables the function below */ -void dump_smb(void *, int); +void dump_smb(struct smb_hdr *, int); #define CIFS_INFO 0x01 #define CIFS_RC 0x02 #define CIFS_TIMER 0x04 diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c index 6873bb634a9..51feb1aff59 100644 --- a/fs/cifs/cifs_dfs_ref.c +++ b/fs/cifs/cifs_dfs_ref.c @@ -141,11 +141,10 @@ char *cifs_compose_mount_options(const char *sb_mountdata, rc = dns_resolve_server_name_to_ip(*devname, &srvIP); if (rc < 0) { - cFYI(1, "%s: Failed to resolve server part of %s to IP: %d", - __func__, *devname, rc); + cERROR(1, "%s: Failed to resolve server part of %s to IP: %d", + __func__, *devname, rc); goto compose_mount_options_err; } - /* md_len = strlen(...) + 12 for 'sep+prefixpath=' * assuming that we have 'unc=' and 'ip=' in * the original sb_mountdata @@ -226,6 +225,8 @@ char *cifs_compose_mount_options(const char *sb_mountdata, compose_mount_options_err: kfree(mountdata); mountdata = ERR_PTR(rc); + kfree(*devname); + *devname = NULL; goto compose_mount_options_out; } diff --git a/fs/cifs/cifs_fs_sb.h b/fs/cifs/cifs_fs_sb.h index c865bfdfe81..7260e11e21f 100644 --- a/fs/cifs/cifs_fs_sb.h +++ b/fs/cifs/cifs_fs_sb.h @@ -43,8 +43,6 @@ #define CIFS_MOUNT_STRICT_IO 0x40000 /* strict cache mode */ #define CIFS_MOUNT_RWPIDFORWARD 0x80000 /* use pid forwarding for rw */ #define CIFS_MOUNT_POSIXACL 0x100000 /* mirror of MS_POSIXACL in mnt_cifs_flags */ -#define CIFS_MOUNT_CIFS_BACKUPUID 0x200000 /* backup intent bit for a user */ -#define CIFS_MOUNT_CIFS_BACKUPGID 0x400000 /* backup intent bit for a group */ struct cifs_sb_info { struct rb_root tlink_tree; @@ -57,10 +55,8 @@ struct cifs_sb_info { atomic_t active; uid_t mnt_uid; gid_t mnt_gid; - uid_t mnt_backupuid; - gid_t mnt_backupgid; - umode_t mnt_file_mode; - umode_t mnt_dir_mode; + mode_t mnt_file_mode; + mode_t mnt_dir_mode; unsigned int mnt_cifs_flags; char *mountdata; /* options received at mount time or via DFS refs */ struct backing_dev_info bdi; diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index e622863b292..2272fd5fe5b 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c @@ -113,11 +113,9 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) MAX_MECH_STR_LEN + UID_KEY_LEN + (sizeof(uid_t) * 2) + CREDUID_KEY_LEN + (sizeof(uid_t) * 2) + + USER_KEY_LEN + strlen(sesInfo->user_name) + PID_KEY_LEN + (sizeof(pid_t) * 2) + 1; - if (sesInfo->user_name) - desc_len += USER_KEY_LEN + strlen(sesInfo->user_name); - spnego_key = ERR_PTR(-ENOMEM); description = kzalloc(desc_len, GFP_KERNEL); if (description == NULL) @@ -154,10 +152,8 @@ cifs_get_spnego_key(struct cifs_ses *sesInfo) dp = description + strlen(description); sprintf(dp, ";creduid=0x%x", sesInfo->cred_uid); - if (sesInfo->user_name) { - dp = description + strlen(description); - sprintf(dp, ";user=%s", sesInfo->user_name); - } + dp = description + strlen(description); + sprintf(dp, ";user=%s", sesInfo->user_name); dp = description + strlen(description); sprintf(dp, ";pid=0x%x", current->pid); diff --git a/fs/cifs/cifs_unicode.c b/fs/cifs/cifs_unicode.c index fbb9da95184..1b2e180b018 100644 --- a/fs/cifs/cifs_unicode.c +++ b/fs/cifs/cifs_unicode.c @@ -27,17 +27,17 @@ #include "cifs_debug.h" /* - * cifs_utf16_bytes - how long will a string be after conversion? - * @utf16 - pointer to input string + * cifs_ucs2_bytes - how long will a string be after conversion? + * @ucs - pointer to input string * @maxbytes - don't go past this many bytes of input string * @codepage - destination codepage * - * Walk a utf16le string and return the number of bytes that the string will + * Walk a ucs2le string and return the number of bytes that the string will * be after being converted to the given charset, not including any null * termination required. Don't walk past maxbytes in the source buffer. */ int -cifs_utf16_bytes(const __le16 *from, int maxbytes, +cifs_ucs2_bytes(const __le16 *from, int maxbytes, const struct nls_table *codepage) { int i; @@ -122,7 +122,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, } /* - * cifs_from_utf16 - convert utf16le string to local charset + * cifs_from_ucs2 - convert utf16le string to local charset * @to - destination buffer * @from - source buffer * @tolen - destination buffer size (in bytes) @@ -130,7 +130,7 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, * @codepage - codepage to which characters should be converted * @mapchar - should characters be remapped according to the mapchars option? * - * Convert a little-endian utf16le string (as sent by the server) to a string + * Convert a little-endian ucs2le string (as sent by the server) to a string * in the provided codepage. The tolen and fromlen parameters are to ensure * that the code doesn't walk off of the end of the buffer (which is always * a danger if the alignment of the source buffer is off). The destination @@ -139,12 +139,12 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, * null terminator). * * Note that some windows versions actually send multiword UTF-16 characters - * instead of straight UTF16-2. The linux nls routines however aren't able to + * instead of straight UCS-2. The linux nls routines however aren't able to * deal with those characters properly. In the event that we get some of * those characters, they won't be translated properly. */ int -cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, +cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, const struct nls_table *codepage, bool mapchar) { int i, charlen, safelen; @@ -190,13 +190,13 @@ cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, } /* - * NAME: cifs_strtoUTF16() + * NAME: cifs_strtoUCS() * * FUNCTION: Convert character string to unicode string * */ int -cifs_strtoUTF16(__le16 *to, const char *from, int len, +cifs_strtoUCS(__le16 *to, const char *from, int len, const struct nls_table *codepage) { int charlen; @@ -206,7 +206,7 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, for (i = 0; len && *from; i++, from += charlen, len -= charlen) { charlen = codepage->char2uni(from, len, &wchar_to); if (charlen < 1) { - cERROR(1, "strtoUTF16: char2uni of 0x%x returned %d", + cERROR(1, "strtoUCS: char2uni of 0x%x returned %d", *from, charlen); /* A question mark */ wchar_to = 0x003f; @@ -220,8 +220,7 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, } /* - * cifs_strndup_from_utf16 - copy a string from wire format to the local - * codepage + * cifs_strndup_from_ucs - copy a string from wire format to the local codepage * @src - source string * @maxlen - don't walk past this many bytes in the source string * @is_unicode - is this a unicode string? @@ -232,19 +231,19 @@ cifs_strtoUTF16(__le16 *to, const char *from, int len, * error. */ char * -cifs_strndup_from_utf16(const char *src, const int maxlen, - const bool is_unicode, const struct nls_table *codepage) +cifs_strndup_from_ucs(const char *src, const int maxlen, const bool is_unicode, + const struct nls_table *codepage) { int len; char *dst; if (is_unicode) { - len = cifs_utf16_bytes((__le16 *) src, maxlen, codepage); + len = cifs_ucs2_bytes((__le16 *) src, maxlen, codepage); len += nls_nullsize(codepage); dst = kmalloc(len, GFP_KERNEL); if (!dst) return NULL; - cifs_from_utf16(dst, (__le16 *) src, len, maxlen, codepage, + cifs_from_ucs2(dst, (__le16 *) src, len, maxlen, codepage, false); } else { len = strnlen(src, maxlen); @@ -265,7 +264,7 @@ cifs_strndup_from_utf16(const char *src, const int maxlen, * names are little endian 16 bit Unicode on the wire */ int -cifsConvertToUTF16(__le16 *target, const char *source, int srclen, +cifsConvertToUCS(__le16 *target, const char *source, int srclen, const struct nls_table *cp, int mapChars) { int i, j, charlen; @@ -274,7 +273,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, wchar_t tmp; if (!mapChars) - return cifs_strtoUTF16(target, source, PATH_MAX, cp); + return cifs_strtoUCS(target, source, PATH_MAX, cp); for (i = 0, j = 0; i < srclen; j++) { src_char = source[i]; @@ -282,7 +281,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, switch (src_char) { case 0: put_unaligned(0, &target[j]); - goto ctoUTF16_out; + goto ctoUCS_out; case ':': dst_char = cpu_to_le16(UNI_COLON); break; @@ -327,7 +326,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen, put_unaligned(dst_char, &target[j]); } -ctoUTF16_out: +ctoUCS_out: return i; } diff --git a/fs/cifs/cifs_unicode.h b/fs/cifs/cifs_unicode.h index a513a546700..6d02fd56056 100644 --- a/fs/cifs/cifs_unicode.h +++ b/fs/cifs/cifs_unicode.h @@ -74,16 +74,16 @@ extern const struct UniCaseRange CifsUniLowerRange[]; #endif /* UNIUPR_NOLOWER */ #ifdef __KERNEL__ -int cifs_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, - const struct nls_table *codepage, bool mapchar); -int cifs_utf16_bytes(const __le16 *from, int maxbytes, - const struct nls_table *codepage); -int cifs_strtoUTF16(__le16 *, const char *, int, const struct nls_table *); -char *cifs_strndup_from_utf16(const char *src, const int maxlen, - const bool is_unicode, - const struct nls_table *codepage); -extern int cifsConvertToUTF16(__le16 *target, const char *source, int maxlen, - const struct nls_table *cp, int mapChars); +int cifs_from_ucs2(char *to, const __le16 *from, int tolen, int fromlen, + const struct nls_table *codepage, bool mapchar); +int cifs_ucs2_bytes(const __le16 *from, int maxbytes, + const struct nls_table *codepage); +int cifs_strtoUCS(__le16 *, const char *, int, const struct nls_table *); +char *cifs_strndup_from_ucs(const char *src, const int maxlen, + const bool is_unicode, + const struct nls_table *codepage); +extern int cifsConvertToUCS(__le16 *target, const char *source, int maxlen, + const struct nls_table *cp, int mapChars); #endif diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 3cc1b251ca0..21de1d6d584 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c @@ -91,76 +91,9 @@ cifs_idmap_shrinker(struct shrinker *shrink, struct shrink_control *sc) shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); spin_unlock(&sidgidlock); - root = &siduidtree; - spin_lock(&uidsidlock); - shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); - spin_unlock(&uidsidlock); - - root = &sidgidtree; - spin_lock(&gidsidlock); - shrink_idmap_tree(root, nr_to_scan, &nr_rem, &nr_del); - spin_unlock(&gidsidlock); - return nr_rem; } -static void -sid_rb_insert(struct rb_root *root, unsigned long cid, - struct cifs_sid_id **psidid, char *typestr) -{ - char *strptr; - struct rb_node *node = root->rb_node; - struct rb_node *parent = NULL; - struct rb_node **linkto = &(root->rb_node); - struct cifs_sid_id *lsidid; - - while (node) { - lsidid = rb_entry(node, struct cifs_sid_id, rbnode); - parent = node; - if (cid > lsidid->id) { - linkto = &(node->rb_left); - node = node->rb_left; - } - if (cid < lsidid->id) { - linkto = &(node->rb_right); - node = node->rb_right; - } - } - - (*psidid)->id = cid; - (*psidid)->time = jiffies - (SID_MAP_RETRY + 1); - (*psidid)->refcount = 0; - - sprintf((*psidid)->sidstr, "%s", typestr); - strptr = (*psidid)->sidstr + strlen((*psidid)->sidstr); - sprintf(strptr, "%ld", cid); - - clear_bit(SID_ID_PENDING, &(*psidid)->state); - clear_bit(SID_ID_MAPPED, &(*psidid)->state); - - rb_link_node(&(*psidid)->rbnode, parent, linkto); - rb_insert_color(&(*psidid)->rbnode, root); -} - -static struct cifs_sid_id * -sid_rb_search(struct rb_root *root, unsigned long cid) -{ - struct rb_node *node = root->rb_node; - struct cifs_sid_id *lsidid; - - while (node) { - lsidid = rb_entry(node, struct cifs_sid_id, rbnode); - if (cid > lsidid->id) - node = node->rb_left; - else if (cid < lsidid->id) - node = node->rb_right; - else /* node found */ - return lsidid; - } - - return NULL; -} - static struct shrinker cifs_shrinker = { .shrink = cifs_idmap_shrinker, .seeks = DEFAULT_SEEKS, @@ -177,7 +110,6 @@ cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) memcpy(payload, data, datalen); key->payload.data = payload; - key->datalen = datalen; return 0; } @@ -291,120 +223,6 @@ sidid_pending_wait(void *unused) return signal_pending(current) ? -ERESTARTSYS : 0; } -static int -id_to_sid(unsigned long cid, uint sidtype, struct cifs_sid *ssid) -{ - int rc = 0; - struct key *sidkey; - const struct cred *saved_cred; - struct cifs_sid *lsid; - struct cifs_sid_id *psidid, *npsidid; - struct rb_root *cidtree; - spinlock_t *cidlock; - - if (sidtype == SIDOWNER) { - cidlock = &siduidlock; - cidtree = &uidtree; - } else if (sidtype == SIDGROUP) { - cidlock = &sidgidlock; - cidtree = &gidtree; - } else - return -EINVAL; - - spin_lock(cidlock); - psidid = sid_rb_search(cidtree, cid); - - if (!psidid) { /* node does not exist, allocate one & attempt adding */ - spin_unlock(cidlock); - npsidid = kzalloc(sizeof(struct cifs_sid_id), GFP_KERNEL); - if (!npsidid) - return -ENOMEM; - - npsidid->sidstr = kmalloc(SIDLEN, GFP_KERNEL); - if (!npsidid->sidstr) { - kfree(npsidid); - return -ENOMEM; - } - - spin_lock(cidlock); - psidid = sid_rb_search(cidtree, cid); - if (psidid) { /* node happened to get inserted meanwhile */ - ++psidid->refcount; - spin_unlock(cidlock); - kfree(npsidid->sidstr); - kfree(npsidid); - } else { - psidid = npsidid; - sid_rb_insert(cidtree, cid, &psidid, - sidtype == SIDOWNER ? "oi:" : "gi:"); - ++psidid->refcount; - spin_unlock(cidlock); - } - } else { - ++psidid->refcount; - spin_unlock(cidlock); - } - - /* - * If we are here, it is safe to access psidid and its fields - * since a reference was taken earlier while holding the spinlock. - * A reference on the node is put without holding the spinlock - * and it is OK to do so in this case, shrinker will not erase - * this node until all references are put and we do not access - * any fields of the node after a reference is put . - */ - if (test_bit(SID_ID_MAPPED, &psidid->state)) { - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); - psidid->time = jiffies; /* update ts for accessing */ - goto id_sid_out; - } - - if (time_after(psidid->time + SID_MAP_RETRY, jiffies)) { - rc = -EINVAL; - goto id_sid_out; - } - - if (!test_and_set_bit(SID_ID_PENDING, &psidid->state)) { - saved_cred = override_creds(root_cred); - sidkey = request_key(&cifs_idmap_key_type, psidid->sidstr, ""); - if (IS_ERR(sidkey)) { - rc = -EINVAL; - cFYI(1, "%s: Can't map and id to a SID", __func__); - } else { - lsid = (struct cifs_sid *)sidkey->payload.data; - memcpy(&psidid->sid, lsid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); - memcpy(ssid, &psidid->sid, - sidkey->datalen < sizeof(struct cifs_sid) ? - sidkey->datalen : sizeof(struct cifs_sid)); - set_bit(SID_ID_MAPPED, &psidid->state); - key_put(sidkey); - kfree(psidid->sidstr); - } - psidid->time = jiffies; /* update ts for accessing */ - revert_creds(saved_cred); - clear_bit(SID_ID_PENDING, &psidid->state); - wake_up_bit(&psidid->state, SID_ID_PENDING); - } else { - rc = wait_on_bit(&psidid->state, SID_ID_PENDING, - sidid_pending_wait, TASK_INTERRUPTIBLE); - if (rc) { - cFYI(1, "%s: sidid_pending_wait interrupted %d", - __func__, rc); - --psidid->refcount; - return rc; - } - if (test_bit(SID_ID_MAPPED, &psidid->state)) - memcpy(ssid, &psidid->sid, sizeof(struct cifs_sid)); - else - rc = -EINVAL; - } -id_sid_out: - --psidid->refcount; - return rc; -} - static int sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid, struct cifs_fattr *fattr, uint sidtype) @@ -556,7 +374,6 @@ init_cifs_idmap(void) /* instruct request_key() to use this special keyring as a cache for * the results it looks up */ - set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; root_cred = cred; @@ -566,10 +383,6 @@ init_cifs_idmap(void) spin_lock_init(&sidgidlock); gidtree = RB_ROOT; - spin_lock_init(&uidsidlock); - siduidtree = RB_ROOT; - spin_lock_init(&gidsidlock); - sidgidtree = RB_ROOT; register_shrinker(&cifs_shrinker); cFYI(1, "cifs idmap keyring: %d\n", key_serial(keyring)); @@ -609,18 +422,6 @@ cifs_destroy_idmaptrees(void) while ((node = rb_first(root))) rb_erase(node, root); spin_unlock(&sidgidlock); - - root = &siduidtree; - spin_lock(&uidsidlock); - while ((node = rb_first(root))) - rb_erase(node, root); - spin_unlock(&uidsidlock); - - root = &sidgidtree; - spin_lock(&gidsidlock); - while ((node = rb_first(root))) - rb_erase(node, root); - spin_unlock(&gidsidlock); } /* if the two SIDs (roughly equivalent to a UUID for a user or group) are @@ -905,13 +706,11 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl, acl_size = sizeof(struct cifs_acl); num_aces = le32_to_cpu(pdacl->num_aces); - if (num_aces > 0) { + if (num_aces > 0) { umode_t user_mask = S_IRWXU; umode_t group_mask = S_IRWXG; umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO; - if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *)) - return; ppace = kmalloc(num_aces * sizeof(struct cifs_ace *), GFP_KERNEL); if (!ppace) { @@ -1069,82 +868,52 @@ static int parse_sec_desc(struct cifs_sb_info *cifs_sb, else cFYI(1, "no ACL"); /* BB grant all or default perms? */ +/* cifscred->uid = owner_sid_ptr->rid; + cifscred->gid = group_sid_ptr->rid; + memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr, + sizeof(struct cifs_sid)); + memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr, + sizeof(struct cifs_sid)); */ + return rc; } + /* Convert permission bits from mode to equivalent CIFS ACL */ static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd, - __u32 secdesclen, __u64 nmode, uid_t uid, gid_t gid, int *aclflag) + struct inode *inode, __u64 nmode) { int rc = 0; __u32 dacloffset; __u32 ndacloffset; __u32 sidsoffset; struct cifs_sid *owner_sid_ptr, *group_sid_ptr; - struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr; struct cifs_acl *dacl_ptr = NULL; /* no need for SACL ptr */ struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */ - if (nmode != NO_CHANGE_64) { /* chmod */ - owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + + if ((inode == NULL) || (pntsd == NULL) || (pnntsd == NULL)) + return -EIO; + + owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->osidoffset)); - group_sid_ptr = (struct cifs_sid *)((char *)pntsd + + group_sid_ptr = (struct cifs_sid *)((char *)pntsd + le32_to_cpu(pntsd->gsidoffset)); - dacloffset = le32_to_cpu(pntsd->dacloffset); - dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); - ndacloffset = sizeof(struct cifs_ntsd); - ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset); - ndacl_ptr->revision = dacl_ptr->revision; - ndacl_ptr->size = 0; - ndacl_ptr->num_aces = 0; - - rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, - nmode); - sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); - /* copy sec desc control portion & owner and group sids */ - copy_sec_desc(pntsd, pnntsd, sidsoffset); - *aclflag = CIFS_ACL_DACL; - } else { - memcpy(pnntsd, pntsd, secdesclen); - if (uid != NO_CHANGE_32) { /* chown */ - owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + - le32_to_cpu(pnntsd->osidoffset)); - nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid), - GFP_KERNEL); - if (!nowner_sid_ptr) - return -ENOMEM; - rc = id_to_sid(uid, SIDOWNER, nowner_sid_ptr); - if (rc) { - cFYI(1, "%s: Mapping error %d for owner id %d", - __func__, rc, uid); - kfree(nowner_sid_ptr); - return rc; - } - memcpy(owner_sid_ptr, nowner_sid_ptr, - sizeof(struct cifs_sid)); - kfree(nowner_sid_ptr); - *aclflag = CIFS_ACL_OWNER; - } - if (gid != NO_CHANGE_32) { /* chgrp */ - group_sid_ptr = (struct cifs_sid *)((char *)pnntsd + - le32_to_cpu(pnntsd->gsidoffset)); - ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid), - GFP_KERNEL); - if (!ngroup_sid_ptr) - return -ENOMEM; - rc = id_to_sid(gid, SIDGROUP, ngroup_sid_ptr); - if (rc) { - cFYI(1, "%s: Mapping error %d for group id %d", - __func__, rc, gid); - kfree(ngroup_sid_ptr); - return rc; - } - memcpy(group_sid_ptr, ngroup_sid_ptr, - sizeof(struct cifs_sid)); - kfree(ngroup_sid_ptr); - *aclflag = CIFS_ACL_GROUP; - } - } + + dacloffset = le32_to_cpu(pntsd->dacloffset); + dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset); + + ndacloffset = sizeof(struct cifs_ntsd); + ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset); + ndacl_ptr->revision = dacl_ptr->revision; + ndacl_ptr->size = 0; + ndacl_ptr->num_aces = 0; + + rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr, nmode); + + sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size); + + /* copy security descriptor control portion and owner and group sid */ + copy_sec_desc(pntsd, pnntsd, sidsoffset); return rc; } @@ -1176,7 +945,7 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, { struct cifs_ntsd *pntsd = NULL; int oplock = 0; - int xid, rc, create_options = 0; + int xid, rc; __u16 fid; struct cifs_tcon *tcon; struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); @@ -1187,12 +956,9 @@ static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, tcon = tlink_tcon(tlink); xid = GetXid(); - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, - create_options, &fid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, READ_CONTROL, 0, + &fid, &oplock, NULL, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (!rc) { rc = CIFSSMBGetCIFSACL(xid, tcon, fid, &pntsd, pacllen); CIFSSMBClose(xid, tcon, fid); @@ -1225,15 +991,31 @@ struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb, return pntsd; } - /* Set an ACL on the server */ -int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, - struct inode *inode, const char *path, int aclflag) +static int set_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb, __u16 fid, + struct cifs_ntsd *pnntsd, u32 acllen) +{ + int xid, rc; + struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); + + if (IS_ERR(tlink)) + return PTR_ERR(tlink); + + xid = GetXid(); + rc = CIFSSMBSetCIFSACL(xid, tlink_tcon(tlink), fid, pnntsd, acllen); + FreeXid(xid); + cifs_put_tlink(tlink); + + cFYI(DBG2, "SetCIFSACL rc = %d", rc); + return rc; +} + +static int set_cifs_acl_by_path(struct cifs_sb_info *cifs_sb, const char *path, + struct cifs_ntsd *pnntsd, u32 acllen) { int oplock = 0; - int xid, rc, access_flags, create_options = 0; + int xid, rc; __u16 fid; struct cifs_tcon *tcon; - struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct tcon_link *tlink = cifs_sb_tlink(cifs_sb); if (IS_ERR(tlink)) @@ -1242,23 +1024,15 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, tcon = tlink_tcon(tlink); xid = GetXid(); - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - - if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP) - access_flags = WRITE_OWNER; - else - access_flags = WRITE_DAC; - - rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, access_flags, - create_options, &fid, &oplock, NULL, cifs_sb->local_nls, - cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); + rc = CIFSSMBOpen(xid, tcon, path, FILE_OPEN, WRITE_DAC, 0, + &fid, &oplock, NULL, cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { cERROR(1, "Unable to open file to set ACL"); goto out; } - rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen, aclflag); + rc = CIFSSMBSetCIFSACL(xid, tcon, fid, pnntsd, acllen); cFYI(DBG2, "SetCIFSACL rc = %d", rc); CIFSSMBClose(xid, tcon, fid); @@ -1268,6 +1042,25 @@ int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, return rc; } +/* Set an ACL on the server */ +int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen, + struct inode *inode, const char *path) +{ + struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); + struct cifsFileInfo *open_file; + int rc; + + cFYI(DBG2, "set ACL for %s from mode 0x%x", path, inode->i_mode); + + open_file = find_readable_file(CIFS_I(inode), true); + if (!open_file) + return set_cifs_acl_by_path(cifs_sb, path, pnntsd, acllen); + + rc = set_cifs_acl_by_fid(cifs_sb, open_file->netfid, pnntsd, acllen); + cifsFileInfo_put(open_file); + return rc; +} + /* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */ int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, @@ -1299,12 +1092,9 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, } /* Convert mode bits to an ACL so we can update the ACL on the server */ -int -id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, - uid_t uid, gid_t gid) +int mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode) { int rc = 0; - int aclflag = CIFS_ACL_DACL; /* default flag to set */ __u32 secdesclen = 0; struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */ struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */ @@ -1334,15 +1124,13 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode, return -ENOMEM; } - rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid, - &aclflag); + rc = build_sec_desc(pntsd, pnntsd, inode, nmode); cFYI(DBG2, "build_sec_desc rc: %d", rc); if (!rc) { /* Set the security descriptor */ - rc = set_cifs_acl(pnntsd, secdesclen, inode, - path, aclflag); + rc = set_cifs_acl(pnntsd, secdesclen, inode, path); cFYI(DBG2, "set_cifs_acl rc: %d", rc); } diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c index 63c460e503b..5a0ee7f2af0 100644 --- a/fs/cifs/cifsencrypt.c +++ b/fs/cifs/cifsencrypt.c @@ -37,13 +37,12 @@ * the sequence number before this function is called. Also, this function * should be called with the server->srv_mutex held. */ -static int cifs_calc_signature(const struct kvec *iov, int n_vec, - struct TCP_Server_Info *server, char *signature) +static int cifs_calculate_signature(const struct smb_hdr *cifs_pdu, + struct TCP_Server_Info *server, char *signature) { - int i; int rc; - if (iov == NULL || signature == NULL || server == NULL) + if (cifs_pdu == NULL || signature == NULL || server == NULL) return -EINVAL; if (!server->secmech.sdescmd5) { @@ -53,17 +52,73 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec, rc = crypto_shash_init(&server->secmech.sdescmd5->shash); if (rc) { - cERROR(1, "%s: Could not init md5\n", __func__); + cERROR(1, "%s: Oould not init md5\n", __func__); return rc; } - rc = crypto_shash_update(&server->secmech.sdescmd5->shash, + crypto_shash_update(&server->secmech.sdescmd5->shash, server->session_key.response, server->session_key.len); + + crypto_shash_update(&server->secmech.sdescmd5->shash, + cifs_pdu->Protocol, be32_to_cpu(cifs_pdu->smb_buf_length)); + + rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); + + return 0; +} + +/* must be called with server->srv_mutex held */ +int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, + __u32 *pexpected_response_sequence_number) +{ + int rc = 0; + char smb_signature[20]; + + if ((cifs_pdu == NULL) || (server == NULL)) + return -EINVAL; + + if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) + return rc; + + cifs_pdu->Signature.Sequence.SequenceNumber = + cpu_to_le32(server->sequence_number); + cifs_pdu->Signature.Sequence.Reserved = 0; + + *pexpected_response_sequence_number = server->sequence_number++; + server->sequence_number++; + + rc = cifs_calculate_signature(cifs_pdu, server, smb_signature); + if (rc) + memset(cifs_pdu->Signature.SecuritySignature, 0, 8); + else + memcpy(cifs_pdu->Signature.SecuritySignature, smb_signature, 8); + + return rc; +} + +static int cifs_calc_signature2(const struct kvec *iov, int n_vec, + struct TCP_Server_Info *server, char *signature) +{ + int i; + int rc; + + if (iov == NULL || signature == NULL || server == NULL) + return -EINVAL; + + if (!server->secmech.sdescmd5) { + cERROR(1, "%s: Can't generate signature\n", __func__); + return -1; + } + + rc = crypto_shash_init(&server->secmech.sdescmd5->shash); if (rc) { - cERROR(1, "%s: Could not update with response\n", __func__); + cERROR(1, "%s: Oould not init md5\n", __func__); return rc; } + crypto_shash_update(&server->secmech.sdescmd5->shash, + server->session_key.response, server->session_key.len); + for (i = 0; i < n_vec; i++) { if (iov[i].iov_len == 0) continue; @@ -76,24 +131,14 @@ static int cifs_calc_signature(const struct kvec *iov, int n_vec, if (i == 0) { if (iov[0].iov_len <= 8) /* cmd field at offset 9 */ break; /* nothing to sign or corrupt header */ - rc = crypto_shash_update(&server->secmech.sdescmd5->shash, iov[i].iov_base + 4, iov[i].iov_len - 4); - } else { - rc = + } else crypto_shash_update(&server->secmech.sdescmd5->shash, iov[i].iov_base, iov[i].iov_len); - } - if (rc) { - cERROR(1, "%s: Could not update with payload\n", - __func__); - return rc; - } } rc = crypto_shash_final(&server->secmech.sdescmd5->shash, signature); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); return rc; } @@ -104,19 +149,13 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, { int rc = 0; char smb_signature[20]; - struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; + struct smb_hdr *cifs_pdu = iov[0].iov_base; if ((cifs_pdu == NULL) || (server == NULL)) return -EINVAL; - if (!(cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) || - server->tcpStatus == CifsNeedNegotiate) - return rc; - - if (!server->session_estab) { - memcpy(cifs_pdu->Signature.SecuritySignature, "BSRSPYL", 8); + if ((cifs_pdu->Flags2 & SMBFLG2_SECURITY_SIGNATURE) == 0) return rc; - } cifs_pdu->Signature.Sequence.SequenceNumber = cpu_to_le32(server->sequence_number); @@ -125,7 +164,7 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, *pexpected_response_sequence_number = server->sequence_number++; server->sequence_number++; - rc = cifs_calc_signature(iov, n_vec, server, smb_signature); + rc = cifs_calc_signature2(iov, n_vec, server, smb_signature); if (rc) memset(cifs_pdu->Signature.SecuritySignature, 0, 8); else @@ -134,27 +173,13 @@ int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *server, return rc; } -/* must be called with server->srv_mutex held */ -int cifs_sign_smb(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, - __u32 *pexpected_response_sequence_number) -{ - struct kvec iov; - - iov.iov_base = cifs_pdu; - iov.iov_len = be32_to_cpu(cifs_pdu->smb_buf_length) + 4; - - return cifs_sign_smb2(&iov, 1, server, - pexpected_response_sequence_number); -} - -int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, +int cifs_verify_signature(struct smb_hdr *cifs_pdu, struct TCP_Server_Info *server, __u32 expected_sequence_number) { unsigned int rc; char server_response_sig[8]; char what_we_think_sig_should_be[20]; - struct smb_hdr *cifs_pdu = (struct smb_hdr *)iov[0].iov_base; if (cifs_pdu == NULL || server == NULL) return -EINVAL; @@ -186,8 +211,8 @@ int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, cifs_pdu->Signature.Sequence.Reserved = 0; mutex_lock(&server->srv_mutex); - rc = cifs_calc_signature(iov, nr_iov, server, - what_we_think_sig_should_be); + rc = cifs_calculate_signature(cifs_pdu, server, + what_we_think_sig_should_be); mutex_unlock(&server->srv_mutex); if (rc) @@ -204,7 +229,7 @@ int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, } /* first calculate 24 bytes ntlm response and then 16 byte session key */ -int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp) +int setup_ntlm_response(struct cifs_ses *ses) { int rc = 0; unsigned int temp_len = CIFS_SESS_KEY_SIZE + CIFS_AUTH_RESP_SIZE; @@ -221,14 +246,14 @@ int setup_ntlm_response(struct cifs_ses *ses, const struct nls_table *nls_cp) ses->auth_key.len = temp_len; rc = SMBNTencrypt(ses->password, ses->server->cryptkey, - ses->auth_key.response + CIFS_SESS_KEY_SIZE, nls_cp); + ses->auth_key.response + CIFS_SESS_KEY_SIZE); if (rc) { cFYI(1, "%s Can't generate NTLM response, error: %d", __func__, rc); return rc; } - rc = E_md4hash(ses->password, temp_key, nls_cp); + rc = E_md4hash(ses->password, temp_key); if (rc) { cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); return rc; @@ -290,7 +315,9 @@ static int build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp) { unsigned int dlen; - unsigned int size = 2 * sizeof(struct ntlmssp2_name); + unsigned int wlen; + unsigned int size = 6 * sizeof(struct ntlmssp2_name); + __le64 curtime; char *defdmname = "WORKGROUP"; unsigned char *blobptr; struct ntlmssp2_name *attrptr; @@ -302,14 +329,15 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp) } dlen = strlen(ses->domainName); + wlen = strlen(ses->server->hostname); - /* - * The length of this blob is two times the size of a - * structure (av pair) which holds name/size - * ( for NTLMSSP_AV_NB_DOMAIN_NAME followed by NTLMSSP_AV_EOL ) + - * unicode length of a netbios domain name + /* The length of this blob is a size which is + * six times the size of a structure which holds name/size + + * two times the unicode length of a domain name + + * two times the unicode length of a server name + + * size of a timestamp (which is 8 bytes). */ - ses->auth_key.len = size + 2 * dlen; + ses->auth_key.len = size + 2 * (2 * dlen) + 2 * (2 * wlen) + 8; ses->auth_key.response = kzalloc(ses->auth_key.len, GFP_KERNEL); if (!ses->auth_key.response) { ses->auth_key.len = 0; @@ -320,14 +348,43 @@ build_avpair_blob(struct cifs_ses *ses, const struct nls_table *nls_cp) blobptr = ses->auth_key.response; attrptr = (struct ntlmssp2_name *) blobptr; - /* - * As defined in MS-NTLM 3.3.2, just this av pair field - * is sufficient as part of the temp - */ attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_DOMAIN_NAME); attrptr->length = cpu_to_le16(2 * dlen); blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); - cifs_strtoUTF16((__le16 *)blobptr, ses->domainName, dlen, nls_cp); + cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp); + + blobptr += 2 * dlen; + attrptr = (struct ntlmssp2_name *) blobptr; + + attrptr->type = cpu_to_le16(NTLMSSP_AV_NB_COMPUTER_NAME); + attrptr->length = cpu_to_le16(2 * wlen); + blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); + cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp); + + blobptr += 2 * wlen; + attrptr = (struct ntlmssp2_name *) blobptr; + + attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_DOMAIN_NAME); + attrptr->length = cpu_to_le16(2 * dlen); + blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); + cifs_strtoUCS((__le16 *)blobptr, ses->domainName, dlen, nls_cp); + + blobptr += 2 * dlen; + attrptr = (struct ntlmssp2_name *) blobptr; + + attrptr->type = cpu_to_le16(NTLMSSP_AV_DNS_COMPUTER_NAME); + attrptr->length = cpu_to_le16(2 * wlen); + blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); + cifs_strtoUCS((__le16 *)blobptr, ses->server->hostname, wlen, nls_cp); + + blobptr += 2 * wlen; + attrptr = (struct ntlmssp2_name *) blobptr; + + attrptr->type = cpu_to_le16(NTLMSSP_AV_TIMESTAMP); + attrptr->length = cpu_to_le16(sizeof(__le64)); + blobptr = (unsigned char *)attrptr + sizeof(struct ntlmssp2_name); + curtime = cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME)); + memcpy(blobptr, &curtime, sizeof(__le64)); return 0; } @@ -376,7 +433,7 @@ find_domain_name(struct cifs_ses *ses, const struct nls_table *nls_cp) kmalloc(attrsize + 1, GFP_KERNEL); if (!ses->domainName) return -ENOMEM; - cifs_from_utf16(ses->domainName, + cifs_from_ucs2(ses->domainName, (__le16 *)blobptr, attrsize, attrsize, nls_cp, false); break; @@ -404,14 +461,10 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, } /* calculate md4 hash of password */ - E_md4hash(ses->password, nt_hash, nls_cp); + E_md4hash(ses->password, nt_hash); - rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash, + crypto_shash_setkey(ses->server->secmech.hmacmd5, nt_hash, CIFS_NTHASH_SIZE); - if (rc) { - cERROR(1, "%s: Could not set NT Hash as a key", __func__); - return rc; - } rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); if (rc) { @@ -420,28 +473,18 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, } /* convert ses->user_name to unicode and uppercase */ - len = ses->user_name ? strlen(ses->user_name) : 0; + len = strlen(ses->user_name); user = kmalloc(2 + (len * 2), GFP_KERNEL); if (user == NULL) { cERROR(1, "calc_ntlmv2_hash: user mem alloc failure\n"); rc = -ENOMEM; - return rc; - } - - if (len) { - len = cifs_strtoUTF16((__le16 *)user, ses->user_name, len, nls_cp); - UniStrupr(user); - } else { - memset(user, '\0', 2); + goto calc_exit_2; } + len = cifs_strtoUCS((__le16 *)user, ses->user_name, len, nls_cp); + UniStrupr(user); - rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, + crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, (char *)user, 2 * len); - kfree(user); - if (rc) { - cERROR(1, "%s: Could not update with user\n", __func__); - return rc; - } /* convert ses->domainName to unicode and uppercase */ if (ses->domainName) { @@ -451,19 +494,13 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, if (domain == NULL) { cERROR(1, "calc_ntlmv2_hash: domain mem alloc failure"); rc = -ENOMEM; - return rc; + goto calc_exit_1; } - len = cifs_strtoUTF16((__le16 *)domain, ses->domainName, len, - nls_cp); - rc = + len = cifs_strtoUCS((__le16 *)domain, ses->domainName, len, + nls_cp); crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, (char *)domain, 2 * len); kfree(domain); - if (rc) { - cERROR(1, "%s: Could not update with domain\n", - __func__); - return rc; - } } else if (ses->serverName) { len = strlen(ses->serverName); @@ -471,26 +508,21 @@ static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash, if (server == NULL) { cERROR(1, "calc_ntlmv2_hash: server mem alloc failure"); rc = -ENOMEM; - return rc; + goto calc_exit_1; } - len = cifs_strtoUTF16((__le16 *)server, ses->serverName, len, + len = cifs_strtoUCS((__le16 *)server, ses->serverName, len, nls_cp); - rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, (char *)server, 2 * len); kfree(server); - if (rc) { - cERROR(1, "%s: Could not update with server\n", - __func__); - return rc; - } } rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, ntlmv2_hash); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); +calc_exit_1: + kfree(user); +calc_exit_2: return rc; } @@ -505,12 +537,8 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) return -1; } - rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, + crypto_shash_setkey(ses->server->secmech.hmacmd5, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); - if (rc) { - cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__); - return rc; - } rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); if (rc) { @@ -524,17 +552,11 @@ CalcNTLMv2_response(const struct cifs_ses *ses, char *ntlmv2_hash) else memcpy(ses->auth_key.response + offset, ses->server->cryptkey, CIFS_SERVER_CHALLENGE_SIZE); - rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, + crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, ses->auth_key.response + offset, ses->auth_key.len - offset); - if (rc) { - cERROR(1, "%s: Could not update with response\n", __func__); - return rc; - } rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, ses->auth_key.response + CIFS_SESS_KEY_SIZE); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); return rc; } @@ -604,12 +626,8 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) } /* now calculate the session key for NTLMv2 */ - rc = crypto_shash_setkey(ses->server->secmech.hmacmd5, + crypto_shash_setkey(ses->server->secmech.hmacmd5, ntlmv2_hash, CIFS_HMAC_MD5_HASH_SIZE); - if (rc) { - cERROR(1, "%s: Could not set NTLMV2 Hash as a key", __func__); - goto setup_ntlmv2_rsp_ret; - } rc = crypto_shash_init(&ses->server->secmech.sdeschmacmd5->shash); if (rc) { @@ -617,18 +635,12 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp) goto setup_ntlmv2_rsp_ret; } - rc = crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, + crypto_shash_update(&ses->server->secmech.sdeschmacmd5->shash, ses->auth_key.response + CIFS_SESS_KEY_SIZE, CIFS_HMAC_MD5_HASH_SIZE); - if (rc) { - cERROR(1, "%s: Could not update with response\n", __func__); - goto setup_ntlmv2_rsp_ret; - } rc = crypto_shash_final(&ses->server->secmech.sdeschmacmd5->shash, ses->auth_key.response); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); setup_ntlmv2_rsp_ret: kfree(tiblob); @@ -656,12 +668,8 @@ calc_seckey(struct cifs_ses *ses) desc.tfm = tfm_arc4; - rc = crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response, + crypto_blkcipher_setkey(tfm_arc4, ses->auth_key.response, CIFS_SESS_KEY_SIZE); - if (rc) { - cERROR(1, "%s: Could not set response as a key", __func__); - return rc; - } sg_init_one(&sgin, sec_key, CIFS_SESS_KEY_SIZE); sg_init_one(&sgout, ses->ntlmssp->ciphertext, CIFS_CPHTXT_SIZE); @@ -680,7 +688,7 @@ calc_seckey(struct cifs_ses *ses) crypto_free_blkcipher(tfm_arc4); - return rc; + return 0; } void diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 541ef81f6ae..332c436c502 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -53,7 +53,7 @@ int cifsFYI = 0; int cifsERROR = 1; int traceSMB = 0; -bool enable_oplocks = true; +unsigned int oplockEnabled = 1; unsigned int linuxExtEnabled = 1; unsigned int lookupCacheEnabled = 1; unsigned int multiuser_mount = 0; @@ -74,18 +74,35 @@ module_param(cifs_min_small, int, 0); MODULE_PARM_DESC(cifs_min_small, "Small network buffers in pool. Default: 30 " "Range: 2 to 256"); unsigned int cifs_max_pending = CIFS_MAX_REQ; -module_param(cifs_max_pending, int, 0444); +module_param(cifs_max_pending, int, 0); MODULE_PARM_DESC(cifs_max_pending, "Simultaneous requests to server. " - "Default: 32767 Range: 2 to 32767."); -module_param(enable_oplocks, bool, 0644); -MODULE_PARM_DESC(enable_oplocks, "Enable or disable oplocks (bool). Default:" - "y/Y/1"); - + "Default: 50 Range: 2 to 256"); +unsigned short echo_retries = 5; +module_param(echo_retries, ushort, 0644); +MODULE_PARM_DESC(echo_retries, "Number of echo attempts before giving up and " + "reconnecting server. Default: 5. 0 means " + "never reconnect."); extern mempool_t *cifs_sm_req_poolp; extern mempool_t *cifs_req_poolp; extern mempool_t *cifs_mid_poolp; -struct workqueue_struct *cifsiod_wq; +void +cifs_sb_active(struct super_block *sb) +{ + struct cifs_sb_info *server = CIFS_SB(sb); + + if (atomic_inc_return(&server->active) == 1) + atomic_inc(&sb->s_active); +} + +void +cifs_sb_deactive(struct super_block *sb) +{ + struct cifs_sb_info *server = CIFS_SB(sb); + + if (atomic_dec_and_test(&server->active)) + deactivate_super(sb); +} static int cifs_read_super(struct super_block *sb) @@ -120,6 +137,7 @@ cifs_read_super(struct super_block *sb) } sb->s_root = d_make_root(inode); + if (!sb->s_root) { rc = -ENOMEM; goto out_no_root; @@ -131,17 +149,20 @@ cifs_read_super(struct super_block *sb) else sb->s_d_op = &cifs_dentry_ops; -#ifdef CONFIG_CIFS_NFSD_EXPORT +#ifdef CIFS_NFSD_EXPORT if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM) { cFYI(1, "export ops supported"); sb->s_export_op = &cifs_export_ops; } -#endif /* CONFIG_CIFS_NFSD_EXPORT */ +#endif /* CIFS_NFSD_EXPORT */ return 0; out_no_root: cERROR(1, "cifs_read_super: get root inode failed"); + if (inode) + iput(inode); + return rc; } @@ -370,13 +391,13 @@ cifs_show_options(struct seq_file *s, struct dentry *root) (int)(srcaddr->sa_family)); } - seq_printf(s, ",uid=%u", cifs_sb->mnt_uid); + seq_printf(s, ",uid=%d", cifs_sb->mnt_uid); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_UID) seq_printf(s, ",forceuid"); else seq_printf(s, ",noforceuid"); - seq_printf(s, ",gid=%u", cifs_sb->mnt_gid); + seq_printf(s, ",gid=%d", cifs_sb->mnt_gid); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_OVERR_GID) seq_printf(s, ",forcegid"); else @@ -385,7 +406,7 @@ cifs_show_options(struct seq_file *s, struct dentry *root) cifs_show_address(s, tcon->ses->server); if (!tcon->unix_ext) - seq_printf(s, ",file_mode=0%ho,dir_mode=0%ho", + seq_printf(s, ",file_mode=0%o,dir_mode=0%o", cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); if (tcon->seal) @@ -428,21 +449,11 @@ cifs_show_options(struct seq_file *s, struct dentry *root) seq_printf(s, ",mfsymlinks"); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_FSCACHE) seq_printf(s, ",fsc"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOSSYNC) - seq_printf(s, ",nostrictsync"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_PERM) - seq_printf(s, ",noperm"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_STRICT_IO) - seq_printf(s, ",strictcache"); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) - seq_printf(s, ",backupuid=%u", cifs_sb->mnt_backupuid); - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) - seq_printf(s, ",backupgid=%u", cifs_sb->mnt_backupgid); - - seq_printf(s, ",rsize=%u", cifs_sb->rsize); - seq_printf(s, ",wsize=%u", cifs_sb->wsize); + + seq_printf(s, ",rsize=%d", cifs_sb->rsize); + seq_printf(s, ",wsize=%d", cifs_sb->wsize); /* convert actimeo and display it in seconds */ - seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); + seq_printf(s, ",actimeo=%lu", cifs_sb->actimeo / HZ); return 0; } @@ -484,7 +495,7 @@ static void cifs_umount_begin(struct super_block *sb) } #ifdef CONFIG_CIFS_STATS2 -static int cifs_show_stats(struct seq_file *s, struct dentry *root) +static int cifs_show_stats(struct seq_file *s, struct vfsmount *mnt) { /* BB FIXME */ return 0; @@ -536,6 +547,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) char *full_path = NULL; char *s, *p; char sep; + int xid; full_path = cifs_build_path_to_root(vol, cifs_sb, cifs_sb_master_tcon(cifs_sb)); @@ -544,6 +556,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) cFYI(1, "Get root dentry for %s", full_path); + xid = GetXid(); sep = CIFS_DIR_SEP(cifs_sb); dentry = dget(sb->s_root); p = s = full_path; @@ -557,6 +570,11 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dentry = ERR_PTR(-ENOENT); break; } + if (!S_ISDIR(dir->i_mode)) { + dput(dentry); + dentry = ERR_PTR(-ENOTDIR); + break; + } /* skip separators */ while (*s == sep) @@ -574,6 +592,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb) dput(dentry); dentry = child; } while (!IS_ERR(dentry)); + _FreeXid(xid); kfree(full_path); return dentry; } @@ -695,11 +714,8 @@ static ssize_t cifs_file_aio_write(struct kiocb *iocb, const struct iovec *iov, static loff_t cifs_llseek(struct file *file, loff_t offset, int origin) { - /* - * origin == SEEK_END || SEEK_DATA || SEEK_HOLE => we must revalidate - * the cached file length - */ - if (origin != SEEK_SET && origin != SEEK_CUR) { + /* origin == SEEK_END => we must revalidate the cached file length */ + if (origin == SEEK_END) { int rc; struct inode *inode = file->f_path.dentry->d_inode; @@ -945,8 +961,7 @@ cifs_init_once(void *inode) struct cifsInodeInfo *cifsi = inode; inode_init_once(&cifsi->vfs_inode); - INIT_LIST_HEAD(&cifsi->llist); - mutex_init(&cifsi->lock_mutex); + INIT_LIST_HEAD(&cifsi->lockList); } static int @@ -1112,20 +1127,14 @@ init_cifs(void) if (cifs_max_pending < 2) { cifs_max_pending = 2; cFYI(1, "cifs_max_pending set to min of 2"); - } else if (cifs_max_pending > CIFS_MAX_REQ) { - cifs_max_pending = CIFS_MAX_REQ; - cFYI(1, "cifs_max_pending set to max of %u", CIFS_MAX_REQ); - } - - cifsiod_wq = alloc_workqueue("cifsiod", WQ_FREEZABLE|WQ_MEM_RECLAIM, 0); - if (!cifsiod_wq) { - rc = -ENOMEM; - goto out_clean_proc; + } else if (cifs_max_pending > 256) { + cifs_max_pending = 256; + cFYI(1, "cifs_max_pending set to max of 256"); } rc = cifs_fscache_register(); if (rc) - goto out_destroy_wq; + goto out_clean_proc; rc = cifs_init_inodecache(); if (rc) @@ -1173,8 +1182,6 @@ init_cifs(void) cifs_destroy_inodecache(); out_unreg_fscache: cifs_fscache_unregister(); -out_destroy_wq: - destroy_workqueue(cifsiod_wq); out_clean_proc: cifs_proc_clean(); return rc; @@ -1184,8 +1191,11 @@ static void __exit exit_cifs(void) { cFYI(DBG2, "exit_cifs"); - unregister_filesystem(&cifs_fs_type); + cifs_proc_clean(); + cifs_fscache_unregister(); +#ifdef CONFIG_CIFS_DFS_UPCALL cifs_dfs_release_automount_timer(); +#endif #ifdef CONFIG_CIFS_ACL cifs_destroy_idmaptrees(); exit_cifs_idmap(); @@ -1193,12 +1203,10 @@ exit_cifs(void) #ifdef CONFIG_CIFS_UPCALL unregister_key_type(&cifs_spnego_key_type); #endif - cifs_destroy_request_bufs(); - cifs_destroy_mids(); + unregister_filesystem(&cifs_fs_type); cifs_destroy_inodecache(); - cifs_fscache_unregister(); - destroy_workqueue(cifsiod_wq); - cifs_proc_clean(); + cifs_destroy_mids(); + cifs_destroy_request_bufs(); } MODULE_AUTHOR("Steve French "); diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 65365358c97..e052b097f04 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h @@ -41,6 +41,10 @@ extern struct file_system_type cifs_fs_type; extern const struct address_space_operations cifs_addr_ops; extern const struct address_space_operations cifs_addr_ops_smallbuf; +/* Functions related to super block operations */ +extern void cifs_sb_active(struct super_block *sb); +extern void cifs_sb_deactive(struct super_block *sb); + /* Functions related to inodes */ extern const struct inode_operations cifs_dir_inode_ops; extern struct inode *cifs_root_iget(struct super_block *); @@ -121,9 +125,9 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t); extern ssize_t cifs_listxattr(struct dentry *, char *, size_t); extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg); -#ifdef CONFIG_CIFS_NFSD_EXPORT +#ifdef CIFS_NFSD_EXPORT extern const struct export_operations cifs_export_ops; -#endif /* CONFIG_CIFS_NFSD_EXPORT */ +#endif /* CIFS_NFSD_EXPORT */ -#define CIFS_VERSION "1.78" +#define CIFS_VERSION "1.74" #endif /* _CIFSFS_H */ diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 4ff6313f0a9..7cb9dd22531 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -43,6 +43,7 @@ #define CIFS_MIN_RCV_POOL 4 +#define MAX_REOPEN_ATT 5 /* these many maximum attempts to reopen a file */ /* * default attribute cache timeout (jiffies) */ @@ -55,9 +56,14 @@ /* * MAX_REQ is the maximum number of requests that WE will send - * on one socket concurrently. + * on one socket concurrently. It also matches the most common + * value of max multiplex returned by servers. We may + * eventually want to use the negotiated value (in case + * future servers can handle more) when we are more confident that + * we will not have problems oveloading the socket with pending + * write data. */ -#define CIFS_MAX_REQ 32767 +#define CIFS_MAX_REQ 50 #define RFC1001_NAME_LEN 15 #define RFC1001_NAME_LEN_WITH_NULL (RFC1001_NAME_LEN + 1) @@ -162,10 +168,8 @@ struct smb_vol { uid_t cred_uid; uid_t linux_uid; gid_t linux_gid; - uid_t backupuid; - gid_t backupgid; - umode_t file_mode; - umode_t dir_mode; + mode_t file_mode; + mode_t dir_mode; unsigned secFlg; bool retry:1; bool intr:1; @@ -176,8 +180,6 @@ struct smb_vol { bool noperm:1; bool no_psx_acl:1; /* set if posix acl support should be disabled */ bool cifs_acl:1; - bool backupuid_specified; /* mount option backupuid is specified */ - bool backupgid_specified; /* mount option backupgid is specified */ bool no_xattr:1; /* set if xattr (EA) support should be disabled*/ bool server_ino:1; /* use inode numbers from server ie UniqueId */ bool direct_io:1; @@ -218,8 +220,7 @@ struct smb_vol { CIFS_MOUNT_OVERR_GID | CIFS_MOUNT_DYNPERM | \ CIFS_MOUNT_NOPOSIXBRL | CIFS_MOUNT_NOSSYNC | \ CIFS_MOUNT_FSCACHE | CIFS_MOUNT_MF_SYMLINKS | \ - CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO | \ - CIFS_MOUNT_CIFS_BACKUPUID | CIFS_MOUNT_CIFS_BACKUPGID) + CIFS_MOUNT_MULTIUSER | CIFS_MOUNT_STRICT_IO) #define CIFS_MS_MASK (MS_RDONLY | MS_MANDLOCK | MS_NOEXEC | MS_NOSUID | \ MS_NODEV | MS_SYNCHRONOUS) @@ -230,12 +231,6 @@ struct cifs_mnt_data { int flags; }; -static inline unsigned int -get_rfc1002_length(void *buf) -{ - return be32_to_cpu(*((__be32 *)buf)); -} - struct TCP_Server_Info { struct list_head tcp_ses_list; struct list_head smb_ses_list; @@ -256,9 +251,7 @@ struct TCP_Server_Info { bool noblocksnd; /* use blocking sendmsg */ bool noautotune; /* do not autotune send buf sizes */ bool tcp_nodelay; - int credits; /* send no more requests at once */ - unsigned int in_flight; /* number of requests on the wire to server */ - spinlock_t req_lock; /* protect the two values above */ + atomic_t inFlight; /* number of requests on the wire to server */ struct mutex srv_mutex; struct task_struct *tsk; char server_GUID[16]; @@ -266,7 +259,6 @@ struct TCP_Server_Info { bool session_estab; /* mark when very first sess is established */ u16 dialect; /* dialect index that server chose */ enum securityEnum secType; - bool oplocks:1; /* enable oplocks */ unsigned int maxReq; /* Clients should submit no more */ /* than maxReq distinct unanswered SMBs to the server when using */ /* multiplexed reads or writes */ @@ -282,7 +274,7 @@ struct TCP_Server_Info { vcnumbers */ int capabilities; /* allow selective disabling of caps by smb sess */ int timeAdj; /* Adjust for difference in server time zone in sec */ - __u64 CurrentMid; /* multiplex id - rotating counter */ + __u16 CurrentMid; /* multiplex id - rotating counter */ char cryptkey[CIFS_CRYPTO_KEY_SIZE]; /* used by ntlm, ntlmv2 etc */ /* 16th byte of RFC1001 workstation name is always null */ char workstation_RFC1001_name[RFC1001_NAME_LEN_WITH_NULL]; @@ -295,64 +287,16 @@ struct TCP_Server_Info { bool sec_kerberosu2u; /* supports U2U Kerberos */ bool sec_kerberos; /* supports plain Kerberos */ bool sec_mskerberos; /* supports legacy MS Kerberos */ - bool large_buf; /* is current buffer large? */ struct delayed_work echo; /* echo ping workqueue job */ - struct kvec *iov; /* reusable kvec array for receives */ - unsigned int nr_iov; /* number of kvecs in array */ - char *smallbuf; /* pointer to current "small" buffer */ - char *bigbuf; /* pointer to current "big" buffer */ - unsigned int total_read; /* total amount of data read in this pass */ #ifdef CONFIG_CIFS_FSCACHE struct fscache_cookie *fscache; /* client index cache cookie */ #endif #ifdef CONFIG_CIFS_STATS2 - atomic_t in_send; /* requests trying to send */ + atomic_t inSend; /* requests trying to send */ atomic_t num_waiters; /* blocked waiting to get in sendrecv */ #endif }; -static inline unsigned int -in_flight(struct TCP_Server_Info *server) -{ - unsigned int num; - spin_lock(&server->req_lock); - num = server->in_flight; - spin_unlock(&server->req_lock); - return num; -} - -static inline int* -get_credits_field(struct TCP_Server_Info *server) -{ - /* - * This will change to switch statement when we reserve slots for echos - * and oplock breaks. - */ - return &server->credits; -} - -static inline bool -has_credits(struct TCP_Server_Info *server, int *credits) -{ - int num; - spin_lock(&server->req_lock); - num = *credits; - spin_unlock(&server->req_lock); - return num > 0; -} - -static inline size_t -header_size(void) -{ - return sizeof(struct smb_hdr); -} - -static inline size_t -max_header_size(void) -{ - return MAX_CIFS_HDR_SIZE; -} - /* * Macros to allow the TCP_Server_Info->net field and related code to drop out * when CONFIG_NET_NS isn't set. @@ -542,13 +486,9 @@ extern struct cifs_tcon *cifs_sb_master_tcon(struct cifs_sb_info *cifs_sb); */ struct cifsLockInfo { struct list_head llist; /* pointer to next cifsLockInfo */ - struct list_head blist; /* pointer to locks blocked on this */ - wait_queue_head_t block_q; __u64 offset; __u64 length; - __u32 pid; __u8 type; - __u16 netfid; }; /* @@ -562,7 +502,7 @@ struct cifs_search_info { char *ntwrk_buf_start; char *srch_entries_start; char *last_entry; - const char *presume_name; + char *presume_name; unsigned int resume_name_len; bool endOfSearch:1; bool emptyDir:1; @@ -581,6 +521,8 @@ struct cifsFileInfo { struct dentry *dentry; unsigned int f_flags; struct tcon_link *tlink; + struct mutex lock_mutex; + struct list_head llist; /* list of byte range locks we have. */ bool invalidHandle:1; /* file closed via session abend */ bool oplock_break_cancelled:1; int count; /* refcount protected by cifs_file_list_lock */ @@ -601,11 +543,9 @@ struct cifs_io_parms { * Take a reference on the file private data. Must be called with * cifs_file_list_lock held. */ -static inline -struct cifsFileInfo *cifsFileInfo_get(struct cifsFileInfo *cifs_file) +static inline void cifsFileInfo_get(struct cifsFileInfo *cifs_file) { ++cifs_file->count; - return cifs_file; } void cifsFileInfo_put(struct cifsFileInfo *cifs_file); @@ -615,9 +555,7 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file); */ struct cifsInodeInfo { - struct list_head llist; /* brlocks for this inode */ - bool can_cache_brlcks; - struct mutex lock_mutex; /* protect two fields above */ + struct list_head lockList; /* BB add in lists for dirty pages i.e. write caching info for oplock */ struct list_head openFileList; __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */ @@ -626,7 +564,7 @@ struct cifsInodeInfo { bool delete_pending; /* DELETE_ON_CLOSE is set */ bool invalid_mapping; /* pagecache is invalid */ unsigned long time; /* jiffies of last update of inode */ - u64 server_eof; /* current file size on server -- protected by i_lock */ + u64 server_eof; /* current file size on server */ u64 uniqueid; /* server inode number */ u64 createtime; /* creation time on server */ #ifdef CONFIG_CIFS_FSCACHE @@ -706,24 +644,8 @@ static inline void cifs_stats_bytes_read(struct cifs_tcon *tcon, struct mid_q_entry; /* - * This is the prototype for the mid receive function. This function is for - * receiving the rest of the SMB frame, starting with the WordCount (which is - * just after the MID in struct smb_hdr). Note: - * - * - This will be called by cifsd, with no locks held. - * - The mid will still be on the pending_mid_q. - * - mid->resp_buf will point to the current buffer. - * - * Returns zero on a successful receive, or an error. The receive state in - * the TCP_Server_Info will also be updated. - */ -typedef int (mid_receive_t)(struct TCP_Server_Info *server, - struct mid_q_entry *mid); - -/* - * This is the prototype for the mid callback function. This is called once the - * mid has been received off of the socket. When creating one, take special - * care to avoid deadlocks. Things to bear in mind: + * This is the prototype for the mid callback function. When creating one, + * take special care to avoid deadlocks. Things to bear in mind: * * - it will be called by cifsd, with no locks held * - the mid will be removed from any lists @@ -733,73 +655,30 @@ typedef void (mid_callback_t)(struct mid_q_entry *mid); /* one of these for every pending CIFS request to the server */ struct mid_q_entry { struct list_head qhead; /* mids waiting on reply from this server */ - __u64 mid; /* multiplex id */ - __u32 pid; /* process id */ + __u16 mid; /* multiplex id */ + __u16 pid; /* process id */ __u32 sequence_number; /* for CIFS signing */ unsigned long when_alloc; /* when mid was created */ #ifdef CONFIG_CIFS_STATS2 unsigned long when_sent; /* time when smb send finished */ unsigned long when_received; /* when demux complete (taken off wire) */ #endif - mid_receive_t *receive; /* call receive callback */ mid_callback_t *callback; /* call completion callback */ void *callback_data; /* general purpose pointer for callback */ - void *resp_buf; /* pointer to received SMB header */ - int mid_state; /* wish this were enum but can not pass to wait_event */ - __le16 command; /* smb command code */ - bool large_buf:1; /* if valid response, is pointer to large buf */ + struct smb_hdr *resp_buf; /* response buffer */ + int midState; /* wish this were enum but can not pass to wait_event */ + __u8 command; /* smb command code */ + bool largeBuf:1; /* if valid response, is pointer to large buf */ bool multiRsp:1; /* multiple trans2 responses for one request */ bool multiEnd:1; /* both received */ }; -/* Make code in transport.c a little cleaner by moving - update of optional stats into function below */ -#ifdef CONFIG_CIFS_STATS2 - -static inline void cifs_in_send_inc(struct TCP_Server_Info *server) -{ - atomic_inc(&server->in_send); -} - -static inline void cifs_in_send_dec(struct TCP_Server_Info *server) -{ - atomic_dec(&server->in_send); -} - -static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server) -{ - atomic_inc(&server->num_waiters); -} - -static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server) -{ - atomic_dec(&server->num_waiters); -} - -static inline void cifs_save_when_sent(struct mid_q_entry *mid) -{ - mid->when_sent = jiffies; -} -#else -static inline void cifs_in_send_inc(struct TCP_Server_Info *server) -{ -} -static inline void cifs_in_send_dec(struct TCP_Server_Info *server) -{ -} - -static inline void cifs_num_waiters_inc(struct TCP_Server_Info *server) -{ -} - -static inline void cifs_num_waiters_dec(struct TCP_Server_Info *server) -{ -} - -static inline void cifs_save_when_sent(struct mid_q_entry *mid) -{ -} -#endif +struct oplock_q_entry { + struct list_head qhead; + struct inode *pinode; + struct cifs_tcon *tcon; + __u16 netfid; +}; /* for pending dnotify requests */ struct dir_notify_req { @@ -927,8 +806,6 @@ require use of the stronger protocol */ #define CIFSSEC_MASK 0xB70B7 /* current flags supported if weak */ #endif /* UPCALL */ #else /* do not allow weak pw hash */ -#define CIFSSEC_MUST_LANMAN 0 -#define CIFSSEC_MUST_PLNTXT 0 #ifdef CONFIG_CIFS_UPCALL #define CIFSSEC_MASK 0x8F08F /* flags supported if no weak allowed */ #else @@ -1046,8 +923,7 @@ GLOBAL_EXTERN unsigned int multiuser_mount; /* if enabled allows new sessions to be established on existing mount if we have the uid/password or Kerberos credential or equivalent for current user */ -/* enable or disable oplocks */ -GLOBAL_EXTERN bool enable_oplocks; +GLOBAL_EXTERN unsigned int oplockEnabled; GLOBAL_EXTERN unsigned int lookupCacheEnabled; GLOBAL_EXTERN unsigned int global_secflags; /* if on, session setup sent with more secure ntlmssp2 challenge/resp */ @@ -1058,20 +934,18 @@ GLOBAL_EXTERN unsigned int cifs_min_rcv; /* min size of big ntwrk buf pool */ GLOBAL_EXTERN unsigned int cifs_min_small; /* min size of small buf pool */ GLOBAL_EXTERN unsigned int cifs_max_pending; /* MAX requests at once to server*/ -#ifdef CONFIG_CIFS_ACL +/* reconnect after this many failed echo attempts */ +GLOBAL_EXTERN unsigned short echo_retries; + GLOBAL_EXTERN struct rb_root uidtree; GLOBAL_EXTERN struct rb_root gidtree; GLOBAL_EXTERN spinlock_t siduidlock; GLOBAL_EXTERN spinlock_t sidgidlock; -GLOBAL_EXTERN struct rb_root siduidtree; -GLOBAL_EXTERN struct rb_root sidgidtree; -GLOBAL_EXTERN spinlock_t uidsidlock; -GLOBAL_EXTERN spinlock_t gidsidlock; -#endif /* CONFIG_CIFS_ACL */ void cifs_oplock_break(struct work_struct *work); +void cifs_oplock_break_get(struct cifsFileInfo *cfile); +void cifs_oplock_break_put(struct cifsFileInfo *cfile); extern const struct slow_work_ops cifs_oplock_break_ops; -extern struct workqueue_struct *cifsiod_wq; #endif /* _CIFS_GLOB_H */ diff --git a/fs/cifs/cifspdu.h b/fs/cifs/cifspdu.h index 3fb03e2c8e8..de3aa285de0 100644 --- a/fs/cifs/cifspdu.h +++ b/fs/cifs/cifspdu.h @@ -1089,7 +1089,9 @@ typedef struct smb_com_read_rsp { __le16 DataLengthHigh; __u64 Reserved2; __u16 ByteCount; - /* read response data immediately follows */ + __u8 Pad; /* BB check for whether padded to DWORD + boundary and optimum performance here */ + char Data[1]; } __attribute__((packed)) READ_RSP; typedef struct locking_andx_range { @@ -1911,10 +1913,6 @@ typedef struct whoami_rsp_data { /* Query level 0x202 */ /* SETFSInfo Levels */ #define SMB_SET_CIFS_UNIX_INFO 0x200 -/* level 0x203 is defined above in list of QFS info levels */ -/* #define SMB_REQUEST_TRANSPORT_ENCRYPTION 0x203 */ - -/* Level 0x200 request structure follows */ typedef struct smb_com_transaction2_setfsi_req { struct smb_hdr hdr; /* wct = 15 */ __le16 TotalParameterCount; @@ -1942,39 +1940,13 @@ typedef struct smb_com_transaction2_setfsi_req { __le64 ClientUnixCap; /* Data end */ } __attribute__((packed)) TRANSACTION2_SETFSI_REQ; -/* level 0x203 request structure follows */ -typedef struct smb_com_transaction2_setfs_enc_req { - struct smb_hdr hdr; /* wct = 15 */ - __le16 TotalParameterCount; - __le16 TotalDataCount; - __le16 MaxParameterCount; - __le16 MaxDataCount; - __u8 MaxSetupCount; - __u8 Reserved; - __le16 Flags; - __le32 Timeout; - __u16 Reserved2; - __le16 ParameterCount; /* 4 */ - __le16 ParameterOffset; - __le16 DataCount; /* 12 */ - __le16 DataOffset; - __u8 SetupCount; /* one */ - __u8 Reserved3; - __le16 SubCommand; /* TRANS2_SET_FS_INFORMATION */ - __le16 ByteCount; - __u8 Pad; - __u16 Reserved4; /* Parameters start. */ - __le16 InformationLevel;/* Parameters end. */ - /* NTLMSSP Blob, Data start. */ -} __attribute__((packed)) TRANSACTION2_SETFSI_ENC_REQ; - -/* response for setfsinfo levels 0x200 and 0x203 */ typedef struct smb_com_transaction2_setfsi_rsp { struct smb_hdr hdr; /* wct = 10 */ struct trans2_resp t2; __u16 ByteCount; } __attribute__((packed)) TRANSACTION2_SETFSI_RSP; + typedef struct smb_com_transaction2_get_dfs_refer_req { struct smb_hdr hdr; /* wct = 15 */ __le16 TotalParameterCount; @@ -2126,13 +2098,13 @@ typedef struct { #define CIFS_UNIX_PROXY_CAP 0x00000400 /* Proxy cap: 0xACE ioctl and QFS PROXY call */ #ifdef CONFIG_CIFS_POSIX -/* presumably don't need the 0x20 POSIX_PATH_OPS_CAP since we never send - LockingX instead of posix locking call on unix sess (and we do not expect - LockingX to use different (ie Windows) semantics than posix locking on - the same session (if WINE needs to do this later, we can add this cap - back in later */ +/* Can not set pathnames cap yet until we send new posix create SMB since + otherwise server can treat such handles opened with older ntcreatex + (by a new client which knows how to send posix path ops) + as non-posix handles (can affect write behavior with byte range locks. + We can add back in POSIX_PATH_OPS cap when Posix Create/Mkdir finished */ /* #define CIFS_UNIX_CAP_MASK 0x000000fb */ -#define CIFS_UNIX_CAP_MASK 0x000003db +#define CIFS_UNIX_CAP_MASK 0x000000db #else #define CIFS_UNIX_CAP_MASK 0x00000013 #endif /* CONFIG_CIFS_POSIX */ diff --git a/fs/cifs/cifsproto.h b/fs/cifs/cifsproto.h index 96192c1e380..8df28e925e5 100644 --- a/fs/cifs/cifsproto.h +++ b/fs/cifs/cifsproto.h @@ -69,15 +69,14 @@ extern struct mid_q_entry *AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server); extern void DeleteMidQEntry(struct mid_q_entry *midEntry); extern int cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, - unsigned int nvec, mid_receive_t *receive, - mid_callback_t *callback, void *cbdata, - bool ignore_pend); + unsigned int nvec, mid_callback_t *callback, + void *cbdata, bool ignore_pend); extern int SendReceive(const unsigned int /* xid */ , struct cifs_ses *, struct smb_hdr * /* input */ , struct smb_hdr * /* out */ , int * /* bytes returned */ , const int long_op); extern int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, - char *in_buf, int flags); + struct smb_hdr *in_buf, int flags); extern int cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, bool log_error); extern int SendReceive2(const unsigned int /* xid */ , struct cifs_ses *, @@ -88,12 +87,9 @@ extern int SendReceiveBlockingLock(const unsigned int xid, struct smb_hdr *in_buf , struct smb_hdr *out_buf, int *bytes_returned); -extern void cifs_add_credits(struct TCP_Server_Info *server, - const unsigned int add); -extern void cifs_set_credits(struct TCP_Server_Info *server, const int val); -extern int checkSMB(char *buf, unsigned int length); -extern bool is_valid_oplock_break(char *, struct TCP_Server_Info *); -extern bool backup_cred(struct cifs_sb_info *); +extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length); +extern bool is_valid_oplock_break(struct smb_hdr *smb, + struct TCP_Server_Info *); extern bool is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof); extern void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, unsigned int bytes_written); @@ -106,7 +102,7 @@ extern int cifs_convert_address(struct sockaddr *dst, const char *src, int len); extern int cifs_set_port(struct sockaddr *addr, const unsigned short int port); extern int cifs_fill_sockaddr(struct sockaddr *dst, const char *src, int len, const unsigned short int port); -extern int map_smb_to_linux_error(char *buf, bool logErr); +extern int map_smb_to_linux_error(struct smb_hdr *smb, bool logErr); extern void header_assemble(struct smb_hdr *, char /* command */ , const struct cifs_tcon *, int /* length of fixed section (word count) in two byte units */); @@ -115,7 +111,7 @@ extern int small_smb_init_no_tc(const int smb_cmd, const int wct, void **request_buf); extern int CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, const struct nls_table *nls_cp); -extern __u64 GetNextMid(struct TCP_Server_Info *server); +extern __u16 GetNextMid(struct TCP_Server_Info *server); extern struct timespec cifs_NTtimeToUnix(__le64 utc_nanoseconds_since_1601); extern u64 cifs_UnixTimeToNT(struct timespec); extern struct timespec cnvrtDosUnixTm(__le16 le_date, __le16 le_time, @@ -149,19 +145,12 @@ extern int cifs_get_inode_info_unix(struct inode **pinode, extern int cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr, struct inode *inode, const char *path, const __u16 *pfid); -extern int id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64, - uid_t, gid_t); +extern int mode_to_cifs_acl(struct inode *inode, const char *path, __u64); extern struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *, struct inode *, const char *, u32 *); extern int set_cifs_acl(struct cifs_ntsd *, __u32, struct inode *, - const char *, int); + const char *); -extern void dequeue_mid(struct mid_q_entry *mid, bool malformed); -extern int cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, - unsigned int to_read); -extern int cifs_readv_from_socket(struct TCP_Server_Info *server, - struct kvec *iov_orig, unsigned int nr_segs, - unsigned int to_read); extern void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, struct cifs_sb_info *cifs_sb); extern int cifs_match_super(struct super_block *, void *); @@ -170,13 +159,7 @@ extern struct smb_vol *cifs_get_volume_info(char *mount_data, const char *devname); extern int cifs_mount(struct cifs_sb_info *, struct smb_vol *); extern void cifs_umount(struct cifs_sb_info *); - -#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) extern void cifs_dfs_release_automount_timer(void); -#else /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */ -#define cifs_dfs_release_automount_timer() do { } while (0) -#endif /* ! IS_ENABLED(CONFIG_CIFS_DFS_UPCALL) */ - void cifs_proc_init(void); void cifs_proc_clean(void); @@ -376,17 +359,14 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, const struct nls_table *nls_codepage, int remap_special_chars); -extern int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid, - const __u8 lock_type, const __u32 num_unlock, - const __u32 num_lock, LOCKING_ANDX_RANGE *buf); extern int CIFSSMBLock(const int xid, struct cifs_tcon *tcon, - const __u16 netfid, const __u32 netpid, const __u64 len, + const __u16 netfid, const __u64 len, const __u64 offset, const __u32 numUnlock, const __u32 numLock, const __u8 lockType, const bool waitFlag, const __u8 oplock_level); extern int CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon, - const __u16 smb_file_id, const __u32 netpid, - const int get_flag, const __u64 len, struct file_lock *, + const __u16 smb_file_id, const int get_flag, + const __u64 len, struct file_lock *, const __u16 lock_type, const bool waitFlag); extern int CIFSSMBTDis(const int xid, struct cifs_tcon *tcon); extern int CIFSSMBEcho(struct TCP_Server_Info *server); @@ -400,12 +380,11 @@ extern void tconInfoFree(struct cifs_tcon *); extern int cifs_sign_smb(struct smb_hdr *, struct TCP_Server_Info *, __u32 *); extern int cifs_sign_smb2(struct kvec *iov, int n_vec, struct TCP_Server_Info *, __u32 *); -extern int cifs_verify_signature(struct kvec *iov, unsigned int nr_iov, +extern int cifs_verify_signature(struct smb_hdr *, struct TCP_Server_Info *server, __u32 expected_sequence_number); -extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *, - const struct nls_table *); -extern int setup_ntlm_response(struct cifs_ses *, const struct nls_table *); +extern int SMBNTencrypt(unsigned char *, unsigned char *, unsigned char *); +extern int setup_ntlm_response(struct cifs_ses *); extern int setup_ntlmv2_rsp(struct cifs_ses *, const struct nls_table *); extern int cifs_crypto_shash_allocate(struct TCP_Server_Info *); extern void cifs_crypto_shash_release(struct TCP_Server_Info *); @@ -440,7 +419,7 @@ extern int CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, extern int CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen); extern int CIFSSMBSetCIFSACL(const int, struct cifs_tcon *, __u16, - struct cifs_ntsd *, __u32, int); + struct cifs_ntsd *, __u32); extern int CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon, const unsigned char *searchName, char *acl_inf, const int buflen, const int acl_type, @@ -457,51 +436,25 @@ extern int CIFSCheckMFSymlink(struct cifs_fattr *fattr, const unsigned char *path, struct cifs_sb_info *cifs_sb, int xid); extern int mdfour(unsigned char *, unsigned char *, int); -extern int E_md4hash(const unsigned char *passwd, unsigned char *p16, - const struct nls_table *codepage); +extern int E_md4hash(const unsigned char *passwd, unsigned char *p16); extern int SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24); -/* asynchronous read support */ -struct cifs_readdata { - struct cifsFileInfo *cfile; - struct address_space *mapping; - __u64 offset; - unsigned int bytes; - pid_t pid; - int result; - struct list_head pages; - struct work_struct work; - unsigned int nr_iov; - struct kvec iov[1]; -}; - -struct cifs_readdata *cifs_readdata_alloc(unsigned int nr_pages); -void cifs_readdata_free(struct cifs_readdata *rdata); -int cifs_async_readv(struct cifs_readdata *rdata); - /* asynchronous write support */ struct cifs_writedata { struct kref refcount; - struct list_head list; - struct completion done; enum writeback_sync_modes sync_mode; struct work_struct work; struct cifsFileInfo *cfile; __u64 offset; - pid_t pid; unsigned int bytes; int result; - void (*marshal_iov) (struct kvec *iov, - struct cifs_writedata *wdata); unsigned int nr_pages; struct page *pages[1]; }; int cifs_async_writev(struct cifs_writedata *wdata); -void cifs_writev_complete(struct work_struct *work); -struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages, - work_func_t complete); +struct cifs_writedata *cifs_writedata_alloc(unsigned int nr_pages); void cifs_writedata_release(struct kref *refcount); #endif /* _CIFSPROTO_H */ diff --git a/fs/cifs/cifssmb.c b/fs/cifs/cifssmb.c index da2f5446fa7..437430d0234 100644 --- a/fs/cifs/cifssmb.c +++ b/fs/cifs/cifssmb.c @@ -33,8 +33,6 @@ #include #include #include -#include -#include #include #include "cifspdu.h" #include "cifsglob.h" @@ -42,7 +40,6 @@ #include "cifsproto.h" #include "cifs_unicode.h" #include "cifs_debug.h" -#include "fscache.h" #ifdef CONFIG_CIFS_POSIX static struct { @@ -86,9 +83,6 @@ static struct { #endif /* CONFIG_CIFS_WEAK_PW_HASH */ #endif /* CIFS_POSIX */ -/* Forward declarations */ -static void cifs_readv_complete(struct work_struct *work); - /* Mark as invalid, all open files on tree connections since they were closed when session to server was lost */ static void mark_open_files_invalid(struct cifs_tcon *pTcon) @@ -113,7 +107,7 @@ static void mark_open_files_invalid(struct cifs_tcon *pTcon) static int cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command) { - int rc; + int rc = 0; struct cifs_ses *ses; struct TCP_Server_Info *server; struct nls_table *nls_codepage; @@ -458,11 +452,9 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses) goto neg_err_exit; } server->sec_mode = (__u8)le16_to_cpu(rsp->SecurityMode); - server->maxReq = min_t(unsigned int, - le16_to_cpu(rsp->MaxMpxCount), - cifs_max_pending); - cifs_set_credits(server, server->maxReq); - server->maxBuf = le16_to_cpu(rsp->MaxBufSize); + server->maxReq = le16_to_cpu(rsp->MaxMpxCount); + server->maxBuf = min((__u32)le16_to_cpu(rsp->MaxBufSize), + (__u32)CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); server->max_vcs = le16_to_cpu(rsp->MaxNumberVcs); /* even though we do not use raw we might as well set this accurately, in case we ever find a need for it */ @@ -567,11 +559,10 @@ CIFSSMBNegotiate(unsigned int xid, struct cifs_ses *ses) /* one byte, so no need to convert this or EncryptionKeyLen from little endian */ - server->maxReq = min_t(unsigned int, le16_to_cpu(pSMBr->MaxMpxCount), - cifs_max_pending); - cifs_set_credits(server, server->maxReq); + server->maxReq = le16_to_cpu(pSMBr->MaxMpxCount); /* probably no need to store and check maxvcs */ - server->maxBuf = le32_to_cpu(pSMBr->MaxBufferSize); + server->maxBuf = min(le32_to_cpu(pSMBr->MaxBufferSize), + (__u32) CIFSMaxBufSize + MAX_CIFS_HDR_SIZE); server->max_rw = le32_to_cpu(pSMBr->MaxRawSize); cFYI(DBG2, "Max buf = %d", ses->server->maxBuf); server->capabilities = le32_to_cpu(pSMBr->Capabilities); @@ -696,7 +687,7 @@ CIFSSMBTDis(const int xid, struct cifs_tcon *tcon) if (rc) return rc; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *)smb_buffer, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, smb_buffer, 0); if (rc) cFYI(1, "Tree disconnect failed %d", rc); @@ -721,7 +712,8 @@ cifs_echo_callback(struct mid_q_entry *mid) struct TCP_Server_Info *server = mid->callback_data; DeleteMidQEntry(mid); - cifs_add_credits(server, 1); + atomic_dec(&server->inFlight); + wake_up(&server->request_q); } int @@ -747,8 +739,7 @@ CIFSSMBEcho(struct TCP_Server_Info *server) iov.iov_base = smb; iov.iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; - rc = cifs_call_async(server, &iov, 1, NULL, cifs_echo_callback, - server, true); + rc = cifs_call_async(server, &iov, 1, cifs_echo_callback, server, true); if (rc) cFYI(1, "Echo request failed: %d", rc); @@ -792,7 +783,7 @@ CIFSSMBLogoff(const int xid, struct cifs_ses *ses) pSMB->hdr.Uid = ses->Suid; pSMB->AndXCommand = 0xFF; - rc = SendReceiveNoRsp(xid, ses, (char *) pSMB, 0); + rc = SendReceiveNoRsp(xid, ses, (struct smb_hdr *) pSMB, 0); session_already_dead: mutex_unlock(&ses->session_mutex); @@ -825,8 +816,8 @@ CIFSPOSIXDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB add path length overrun check */ @@ -897,8 +888,8 @@ CIFSSMBDelFile(const int xid, struct cifs_tcon *tcon, const char *fileName, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->fileName, fileName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->fileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve check for buffer overruns BB */ @@ -942,8 +933,8 @@ CIFSSMBRmDir(const int xid, struct cifs_tcon *tcon, const char *dirName, return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, dirName, - PATH_MAX, nls_codepage, remap); + name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, dirName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve check for buffer overruns BB */ @@ -985,8 +976,8 @@ CIFSSMBMkDir(const int xid, struct cifs_tcon *tcon, return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->DirName, name, - PATH_MAX, nls_codepage, remap); + name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve check for buffer overruns BB */ @@ -1034,8 +1025,8 @@ CIFSPOSIXCreate(const int xid, struct cifs_tcon *tcon, __u32 posix_flags, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, name, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, name, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -1201,8 +1192,8 @@ SMBLegacyOpen(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { count = 1; /* account for one byte pad to word boundary */ name_len = - cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), - fileName, PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) (pSMB->fileName + 1), + fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve check for buffer overruns BB */ @@ -1308,8 +1299,8 @@ CIFSSMBOpen(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { count = 1; /* account for one byte pad to word boundary */ name_len = - cifsConvertToUTF16((__le16 *) (pSMB->fileName + 1), - fileName, PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) (pSMB->fileName + 1), + fileName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; pSMB->NameLength = cpu_to_le16(name_len); @@ -1385,376 +1376,6 @@ CIFSSMBOpen(const int xid, struct cifs_tcon *tcon, return rc; } -struct cifs_readdata * -cifs_readdata_alloc(unsigned int nr_pages) -{ - struct cifs_readdata *rdata; - - /* readdata + 1 kvec for each page */ - rdata = kzalloc(sizeof(*rdata) + - sizeof(struct kvec) * nr_pages, GFP_KERNEL); - if (rdata != NULL) { - INIT_WORK(&rdata->work, cifs_readv_complete); - INIT_LIST_HEAD(&rdata->pages); - } - return rdata; -} - -void -cifs_readdata_free(struct cifs_readdata *rdata) -{ - cifsFileInfo_put(rdata->cfile); - kfree(rdata); -} - -/* - * Discard any remaining data in the current SMB. To do this, we borrow the - * current bigbuf. - */ -static int -cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid) -{ - unsigned int rfclen = get_rfc1002_length(server->smallbuf); - int remaining = rfclen + 4 - server->total_read; - struct cifs_readdata *rdata = mid->callback_data; - - while (remaining > 0) { - int length; - - length = cifs_read_from_socket(server, server->bigbuf, - min_t(unsigned int, remaining, - CIFSMaxBufSize + max_header_size())); - if (length < 0) - return length; - server->total_read += length; - remaining -= length; - } - - dequeue_mid(mid, rdata->result); - return 0; -} - -static inline size_t -read_rsp_size(void) -{ - return sizeof(READ_RSP); -} - -static inline unsigned int -read_data_offset(char *buf) -{ - READ_RSP *rsp = (READ_RSP *)buf; - return le16_to_cpu(rsp->DataOffset); -} - -static inline unsigned int -read_data_length(char *buf) -{ - READ_RSP *rsp = (READ_RSP *)buf; - return (le16_to_cpu(rsp->DataLengthHigh) << 16) + - le16_to_cpu(rsp->DataLength); -} - -static int -cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid) -{ - int length, len; - unsigned int data_offset, remaining, data_len; - struct cifs_readdata *rdata = mid->callback_data; - char *buf = server->smallbuf; - unsigned int buflen = get_rfc1002_length(buf) + 4; - u64 eof; - pgoff_t eof_index; - struct page *page, *tpage; - - cFYI(1, "%s: mid=%llu offset=%llu bytes=%u", __func__, - mid->mid, rdata->offset, rdata->bytes); - - /* - * read the rest of READ_RSP header (sans Data array), or whatever we - * can if there's not enough data. At this point, we've read down to - * the Mid. - */ - len = min_t(unsigned int, buflen, read_rsp_size()) - header_size() + 1; - - rdata->iov[0].iov_base = buf + header_size() - 1; - rdata->iov[0].iov_len = len; - - length = cifs_readv_from_socket(server, rdata->iov, 1, len); - if (length < 0) - return length; - server->total_read += length; - - /* Was the SMB read successful? */ - rdata->result = map_smb_to_linux_error(buf, false); - if (rdata->result != 0) { - cFYI(1, "%s: server returned error %d", __func__, - rdata->result); - return cifs_readv_discard(server, mid); - } - - /* Is there enough to get to the rest of the READ_RSP header? */ - if (server->total_read < read_rsp_size()) { - cFYI(1, "%s: server returned short header. got=%u expected=%zu", - __func__, server->total_read, read_rsp_size()); - rdata->result = -EIO; - return cifs_readv_discard(server, mid); - } - - data_offset = read_data_offset(buf) + 4; - if (data_offset < server->total_read) { - /* - * win2k8 sometimes sends an offset of 0 when the read - * is beyond the EOF. Treat it as if the data starts just after - * the header. - */ - cFYI(1, "%s: data offset (%u) inside read response header", - __func__, data_offset); - data_offset = server->total_read; - } else if (data_offset > MAX_CIFS_SMALL_BUFFER_SIZE) { - /* data_offset is beyond the end of smallbuf */ - cFYI(1, "%s: data offset (%u) beyond end of smallbuf", - __func__, data_offset); - rdata->result = -EIO; - return cifs_readv_discard(server, mid); - } - - cFYI(1, "%s: total_read=%u data_offset=%u", __func__, - server->total_read, data_offset); - - len = data_offset - server->total_read; - if (len > 0) { - /* read any junk before data into the rest of smallbuf */ - rdata->iov[0].iov_base = buf + server->total_read; - rdata->iov[0].iov_len = len; - length = cifs_readv_from_socket(server, rdata->iov, 1, len); - if (length < 0) - return length; - server->total_read += length; - } - - /* set up first iov for signature check */ - rdata->iov[0].iov_base = buf; - rdata->iov[0].iov_len = server->total_read; - cFYI(1, "0: iov_base=%p iov_len=%zu", - rdata->iov[0].iov_base, rdata->iov[0].iov_len); - - /* how much data is in the response? */ - data_len = read_data_length(buf); - if (data_offset + data_len > buflen) { - /* data_len is corrupt -- discard frame */ - rdata->result = -EIO; - return cifs_readv_discard(server, mid); - } - - /* marshal up the page array */ - len = 0; - remaining = data_len; - rdata->nr_iov = 1; - - /* determine the eof that the server (probably) has */ - eof = CIFS_I(rdata->mapping->host)->server_eof; - eof_index = eof ? (eof - 1) >> PAGE_CACHE_SHIFT : 0; - cFYI(1, "eof=%llu eof_index=%lu", eof, eof_index); - - list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { - if (remaining >= PAGE_CACHE_SIZE) { - /* enough data to fill the page */ - rdata->iov[rdata->nr_iov].iov_base = kmap(page); - rdata->iov[rdata->nr_iov].iov_len = PAGE_CACHE_SIZE; - cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", - rdata->nr_iov, page->index, - rdata->iov[rdata->nr_iov].iov_base, - rdata->iov[rdata->nr_iov].iov_len); - ++rdata->nr_iov; - len += PAGE_CACHE_SIZE; - remaining -= PAGE_CACHE_SIZE; - } else if (remaining > 0) { - /* enough for partial page, fill and zero the rest */ - rdata->iov[rdata->nr_iov].iov_base = kmap(page); - rdata->iov[rdata->nr_iov].iov_len = remaining; - cFYI(1, "%u: idx=%lu iov_base=%p iov_len=%zu", - rdata->nr_iov, page->index, - rdata->iov[rdata->nr_iov].iov_base, - rdata->iov[rdata->nr_iov].iov_len); - memset(rdata->iov[rdata->nr_iov].iov_base + remaining, - '\0', PAGE_CACHE_SIZE - remaining); - ++rdata->nr_iov; - len += remaining; - remaining = 0; - } else if (page->index > eof_index) { - /* - * The VFS will not try to do readahead past the - * i_size, but it's possible that we have outstanding - * writes with gaps in the middle and the i_size hasn't - * caught up yet. Populate those with zeroed out pages - * to prevent the VFS from repeatedly attempting to - * fill them until the writes are flushed. - */ - zero_user(page, 0, PAGE_CACHE_SIZE); - list_del(&page->lru); - lru_cache_add_file(page); - flush_dcache_page(page); - SetPageUptodate(page); - unlock_page(page); - page_cache_release(page); - } else { - /* no need to hold page hostage */ - list_del(&page->lru); - lru_cache_add_file(page); - unlock_page(page); - page_cache_release(page); - } - } - - /* issue the read if we have any iovecs left to fill */ - if (rdata->nr_iov > 1) { - length = cifs_readv_from_socket(server, &rdata->iov[1], - rdata->nr_iov - 1, len); - if (length < 0) - return length; - server->total_read += length; - } else { - length = 0; - } - - rdata->bytes = length; - - cFYI(1, "total_read=%u buflen=%u remaining=%u", server->total_read, - buflen, remaining); - - /* discard anything left over */ - if (server->total_read < buflen) - return cifs_readv_discard(server, mid); - - dequeue_mid(mid, false); - return length; -} - -static void -cifs_readv_complete(struct work_struct *work) -{ - struct cifs_readdata *rdata = container_of(work, - struct cifs_readdata, work); - struct page *page, *tpage; - - list_for_each_entry_safe(page, tpage, &rdata->pages, lru) { - list_del(&page->lru); - lru_cache_add_file(page); - - if (rdata->result == 0) { - kunmap(page); - flush_dcache_page(page); - SetPageUptodate(page); - } - - unlock_page(page); - - if (rdata->result == 0) - cifs_readpage_to_fscache(rdata->mapping->host, page); - - page_cache_release(page); - } - cifs_readdata_free(rdata); -} - -static void -cifs_readv_callback(struct mid_q_entry *mid) -{ - struct cifs_readdata *rdata = mid->callback_data; - struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); - struct TCP_Server_Info *server = tcon->ses->server; - - cFYI(1, "%s: mid=%llu state=%d result=%d bytes=%u", __func__, - mid->mid, mid->mid_state, rdata->result, rdata->bytes); - - switch (mid->mid_state) { - case MID_RESPONSE_RECEIVED: - /* result already set, check signature */ - if (server->sec_mode & - (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - if (cifs_verify_signature(rdata->iov, rdata->nr_iov, - server, mid->sequence_number + 1)) - cERROR(1, "Unexpected SMB signature"); - } - /* FIXME: should this be counted toward the initiating task? */ - task_io_account_read(rdata->bytes); - cifs_stats_bytes_read(tcon, rdata->bytes); - break; - case MID_REQUEST_SUBMITTED: - case MID_RETRY_NEEDED: - rdata->result = -EAGAIN; - break; - default: - rdata->result = -EIO; - } - - queue_work(cifsiod_wq, &rdata->work); - DeleteMidQEntry(mid); - cifs_add_credits(server, 1); -} - -/* cifs_async_readv - send an async write, and set up mid to handle result */ -int -cifs_async_readv(struct cifs_readdata *rdata) -{ - int rc; - READ_REQ *smb = NULL; - int wct; - struct cifs_tcon *tcon = tlink_tcon(rdata->cfile->tlink); - - cFYI(1, "%s: offset=%llu bytes=%u", __func__, - rdata->offset, rdata->bytes); - - if (tcon->ses->capabilities & CAP_LARGE_FILES) - wct = 12; - else { - wct = 10; /* old style read */ - if ((rdata->offset >> 32) > 0) { - /* can not handle this big offset for old */ - return -EIO; - } - } - - rc = small_smb_init(SMB_COM_READ_ANDX, wct, tcon, (void **)&smb); - if (rc) - return rc; - - smb->hdr.Pid = cpu_to_le16((__u16)rdata->pid); - smb->hdr.PidHigh = cpu_to_le16((__u16)(rdata->pid >> 16)); - - smb->AndXCommand = 0xFF; /* none */ - smb->Fid = rdata->cfile->netfid; - smb->OffsetLow = cpu_to_le32(rdata->offset & 0xFFFFFFFF); - if (wct == 12) - smb->OffsetHigh = cpu_to_le32(rdata->offset >> 32); - smb->Remaining = 0; - smb->MaxCount = cpu_to_le16(rdata->bytes & 0xFFFF); - smb->MaxCountHigh = cpu_to_le32(rdata->bytes >> 16); - if (wct == 12) - smb->ByteCount = 0; - else { - /* old style read */ - struct smb_com_readx_req *smbr = - (struct smb_com_readx_req *)smb; - smbr->ByteCount = 0; - } - - /* 4 for RFC1001 length + 1 for BCC */ - rdata->iov[0].iov_base = smb; - rdata->iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4; - - rc = cifs_call_async(tcon->ses->server, rdata->iov, 1, - cifs_readv_receive, cifs_readv_callback, - rdata, false); - - if (rc == 0) - cifs_stats_inc(&tcon->num_reads); - - cifs_small_buf_release(smb); - return rc; -} - int CIFSSMBRead(const int xid, struct cifs_io_parms *io_parms, unsigned int *nbytes, char **buf, int *pbuf_type) @@ -2035,7 +1656,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata) kref_put(&wdata->refcount, cifs_writedata_release); } -void +static void cifs_writev_complete(struct work_struct *work) { struct cifs_writedata *wdata = container_of(work, @@ -2044,9 +1665,7 @@ cifs_writev_complete(struct work_struct *work) int i = 0; if (wdata->result == 0) { - spin_lock(&inode->i_lock); cifs_update_eof(CIFS_I(inode), wdata->offset, wdata->bytes); - spin_unlock(&inode->i_lock); cifs_stats_bytes_written(tlink_tcon(wdata->cfile->tlink), wdata->bytes); } else if (wdata->sync_mode == WB_SYNC_ALL && wdata->result == -EAGAIN) @@ -2067,7 +1686,7 @@ cifs_writev_complete(struct work_struct *work) } struct cifs_writedata * -cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) +cifs_writedata_alloc(unsigned int nr_pages) { struct cifs_writedata *wdata; @@ -2081,16 +1700,14 @@ cifs_writedata_alloc(unsigned int nr_pages, work_func_t complete) wdata = kzalloc(sizeof(*wdata) + sizeof(struct page *) * (nr_pages - 1), GFP_NOFS); if (wdata != NULL) { + INIT_WORK(&wdata->work, cifs_writev_complete); kref_init(&wdata->refcount); - INIT_LIST_HEAD(&wdata->list); - init_completion(&wdata->done); - INIT_WORK(&wdata->work, complete); } return wdata; } /* - * Check the mid_state and signature on received buffer (if any), and queue the + * Check the midState and signature on received buffer (if any), and queue the * workqueue completion task. */ static void @@ -2101,7 +1718,7 @@ cifs_writev_callback(struct mid_q_entry *mid) unsigned int written; WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf; - switch (mid->mid_state) { + switch (mid->midState) { case MID_RESPONSE_RECEIVED: wdata->result = cifs_check_receive(mid, tcon->ses->server, 0); if (wdata->result != 0) @@ -2133,9 +1750,10 @@ cifs_writev_callback(struct mid_q_entry *mid) break; } - queue_work(cifsiod_wq, &wdata->work); + queue_work(system_nrt_wq, &wdata->work); DeleteMidQEntry(mid); - cifs_add_credits(tcon->ses->server, 1); + atomic_dec(&tcon->ses->server->inFlight); + wake_up(&tcon->ses->server->request_q); } /* cifs_async_writev - send an async write, and set up mid to handle result */ @@ -2146,6 +1764,7 @@ cifs_async_writev(struct cifs_writedata *wdata) WRITE_REQ *smb = NULL; int wct; struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink); + struct inode *inode = wdata->cfile->dentry->d_inode; struct kvec *iov = NULL; if (tcon->ses->capabilities & CAP_LARGE_FILES) { @@ -2169,8 +1788,8 @@ cifs_async_writev(struct cifs_writedata *wdata) goto async_writev_out; } - smb->hdr.Pid = cpu_to_le16((__u16)wdata->pid); - smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->pid >> 16)); + smb->hdr.Pid = cpu_to_le16((__u16)wdata->cfile->pid); + smb->hdr.PidHigh = cpu_to_le16((__u16)(wdata->cfile->pid >> 16)); smb->AndXCommand = 0xFF; /* none */ smb->Fid = wdata->cfile->netfid; @@ -2188,13 +1807,15 @@ cifs_async_writev(struct cifs_writedata *wdata) iov[0].iov_len = be32_to_cpu(smb->hdr.smb_buf_length) + 4 + 1; iov[0].iov_base = smb; - /* - * This function should marshal up the page array into the kvec - * array, reserving [0] for the header. It should kmap the pages - * and set the iov_len properly for each one. It may also set - * wdata->bytes too. - */ - wdata->marshal_iov(iov, wdata); + /* marshal up the pages into iov array */ + wdata->bytes = 0; + for (i = 0; i < wdata->nr_pages; i++) { + iov[i + 1].iov_len = min(inode->i_size - + page_offset(wdata->pages[i]), + (loff_t)PAGE_CACHE_SIZE); + iov[i + 1].iov_base = kmap(wdata->pages[i]); + wdata->bytes += iov[i + 1].iov_len; + } cFYI(1, "async write at %llu %u bytes", wdata->offset, wdata->bytes); @@ -2215,7 +1836,7 @@ cifs_async_writev(struct cifs_writedata *wdata) kref_get(&wdata->refcount); rc = cifs_call_async(tcon->ses->server, iov, wdata->nr_pages + 1, - NULL, cifs_writev_callback, wdata, false); + cifs_writev_callback, wdata, false); if (rc == 0) cifs_stats_inc(&tcon->num_writes); @@ -2341,50 +1962,10 @@ CIFSSMBWrite2(const int xid, struct cifs_io_parms *io_parms, return rc; } -int cifs_lockv(const int xid, struct cifs_tcon *tcon, const __u16 netfid, - const __u8 lock_type, const __u32 num_unlock, - const __u32 num_lock, LOCKING_ANDX_RANGE *buf) -{ - int rc = 0; - LOCK_REQ *pSMB = NULL; - struct kvec iov[2]; - int resp_buf_type; - __u16 count; - - cFYI(1, "cifs_lockv num lock %d num unlock %d", num_lock, num_unlock); - - rc = small_smb_init(SMB_COM_LOCKING_ANDX, 8, tcon, (void **) &pSMB); - if (rc) - return rc; - - pSMB->Timeout = 0; - pSMB->NumberOfLocks = cpu_to_le16(num_lock); - pSMB->NumberOfUnlocks = cpu_to_le16(num_unlock); - pSMB->LockType = lock_type; - pSMB->AndXCommand = 0xFF; /* none */ - pSMB->Fid = netfid; /* netfid stays le */ - - count = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); - inc_rfc1001_len(pSMB, count); - pSMB->ByteCount = cpu_to_le16(count); - - iov[0].iov_base = (char *)pSMB; - iov[0].iov_len = be32_to_cpu(pSMB->hdr.smb_buf_length) + 4 - - (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); - iov[1].iov_base = (char *)buf; - iov[1].iov_len = (num_unlock + num_lock) * sizeof(LOCKING_ANDX_RANGE); - - cifs_stats_inc(&tcon->num_locks); - rc = SendReceive2(xid, tcon->ses, iov, 2, &resp_buf_type, CIFS_NO_RESP); - if (rc) - cFYI(1, "Send error in cifs_lockv = %d", rc); - - return rc; -} int CIFSSMBLock(const int xid, struct cifs_tcon *tcon, - const __u16 smb_file_id, const __u32 netpid, const __u64 len, + const __u16 smb_file_id, const __u64 len, const __u64 offset, const __u32 numUnlock, const __u32 numLock, const __u8 lockType, const bool waitFlag, const __u8 oplock_level) @@ -2420,7 +2001,7 @@ CIFSSMBLock(const int xid, struct cifs_tcon *tcon, pSMB->Fid = smb_file_id; /* netfid stays le */ if ((numLock != 0) || (numUnlock != 0)) { - pSMB->Locks[0].Pid = cpu_to_le16(netpid); + pSMB->Locks[0].Pid = cpu_to_le16(current->tgid); /* BB where to store pid high? */ pSMB->Locks[0].LengthLow = cpu_to_le32((u32)len); pSMB->Locks[0].LengthHigh = cpu_to_le32((u32)(len>>32)); @@ -2439,7 +2020,8 @@ CIFSSMBLock(const int xid, struct cifs_tcon *tcon, (struct smb_hdr *) pSMB, &bytes_returned); cifs_small_buf_release(pSMB); } else { - rc = SendReceiveNoRsp(xid, tcon->ses, (char *)pSMB, timeout); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *)pSMB, + timeout); /* SMB buffer freed by function above */ } cifs_stats_inc(&tcon->num_locks); @@ -2453,9 +2035,9 @@ CIFSSMBLock(const int xid, struct cifs_tcon *tcon, int CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon, - const __u16 smb_file_id, const __u32 netpid, const int get_flag, - const __u64 len, struct file_lock *pLockData, - const __u16 lock_type, const bool waitFlag) + const __u16 smb_file_id, const int get_flag, const __u64 len, + struct file_lock *pLockData, const __u16 lock_type, + const bool waitFlag) { struct smb_com_transaction2_sfi_req *pSMB = NULL; struct smb_com_transaction2_sfi_rsp *pSMBr = NULL; @@ -2513,7 +2095,7 @@ CIFSSMBPosixLock(const int xid, struct cifs_tcon *tcon, } else pSMB->Timeout = 0; - parm_data->pid = cpu_to_le32(netpid); + parm_data->pid = cpu_to_le32(current->tgid); parm_data->start = cpu_to_le64(pLockData->fl_start); parm_data->length = cpu_to_le64(len); /* normalize negative numbers */ @@ -2606,7 +2188,7 @@ CIFSSMBClose(const int xid, struct cifs_tcon *tcon, int smb_file_id) pSMB->FileID = (__u16) smb_file_id; pSMB->LastWriteTime = 0xFFFFFFFF; pSMB->ByteCount = 0; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); cifs_stats_inc(&tcon->num_closes); if (rc) { if (rc != -EINTR) { @@ -2635,7 +2217,7 @@ CIFSSMBFlush(const int xid, struct cifs_tcon *tcon, int smb_file_id) pSMB->FileID = (__u16) smb_file_id; pSMB->ByteCount = 0; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); cifs_stats_inc(&tcon->num_flushes); if (rc) cERROR(1, "Send error in Flush = %d", rc); @@ -2669,16 +2251,16 @@ CIFSSMBRename(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; pSMB->OldFileName[name_len] = 0x04; /* pad */ /* protocol requires ASCII signature byte on Unicode string */ pSMB->OldFileName[name_len + 1] = 0x00; name_len2 = - cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], - toName, PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], + toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ @@ -2758,12 +2340,10 @@ int CIFSSMBRenameOpenFile(const int xid, struct cifs_tcon *pTcon, /* unicode only call */ if (target_name == NULL) { sprintf(dummy_string, "cifs%x", pSMB->hdr.Mid); - len_of_str = - cifsConvertToUTF16((__le16 *)rename_info->target_name, + len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name, dummy_string, 24, nls_codepage, remap); } else { - len_of_str = - cifsConvertToUTF16((__le16 *)rename_info->target_name, + len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name, target_name, PATH_MAX, nls_codepage, remap); } @@ -2817,17 +2397,17 @@ CIFSSMBCopy(const int xid, struct cifs_tcon *tcon, const char *fromName, pSMB->Flags = cpu_to_le16(flags & COPY_TREE); if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->OldFileName, - fromName, PATH_MAX, nls_codepage, - remap); + name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName, + fromName, PATH_MAX, nls_codepage, + remap); name_len++; /* trailing null */ name_len *= 2; pSMB->OldFileName[name_len] = 0x04; /* pad */ /* protocol requires ASCII signature byte on Unicode string */ pSMB->OldFileName[name_len + 1] = 0x00; name_len2 = - cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], - toName, PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], + toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ @@ -2883,9 +2463,9 @@ CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUTF16((__le16 *) pSMB->FileName, fromName, - /* find define for this maxpathcomponent */ - PATH_MAX, nls_codepage); + cifs_strtoUCS((__le16 *) pSMB->FileName, fromName, PATH_MAX + /* find define for this maxpathcomponent */ + , nls_codepage); name_len++; /* trailing null */ name_len *= 2; @@ -2907,9 +2487,9 @@ CIFSUnixCreateSymLink(const int xid, struct cifs_tcon *tcon, data_offset = (char *) (&pSMB->hdr.Protocol) + offset; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len_target = - cifs_strtoUTF16((__le16 *) data_offset, toName, PATH_MAX - /* find define for this maxpathcomponent */ - , nls_codepage); + cifs_strtoUCS((__le16 *) data_offset, toName, PATH_MAX + /* find define for this maxpathcomponent */ + , nls_codepage); name_len_target++; /* trailing null */ name_len_target *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -2971,8 +2551,8 @@ CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon, return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { - name_len = cifsConvertToUTF16((__le16 *) pSMB->FileName, toName, - PATH_MAX, nls_codepage, remap); + name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -2994,8 +2574,8 @@ CIFSUnixCreateHardLink(const int xid, struct cifs_tcon *tcon, data_offset = (char *) (&pSMB->hdr.Protocol) + offset; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len_target = - cifsConvertToUTF16((__le16 *) data_offset, fromName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX, + nls_codepage, remap); name_len_target++; /* trailing null */ name_len_target *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -3064,8 +2644,8 @@ CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->OldFileName, fromName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; @@ -3073,8 +2653,8 @@ CIFSCreateHardLink(const int xid, struct cifs_tcon *tcon, pSMB->OldFileName[name_len] = 0x04; pSMB->OldFileName[name_len + 1] = 0x00; /* pad */ name_len2 = - cifsConvertToUTF16((__le16 *)&pSMB->OldFileName[name_len+2], - toName, PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2], + toName, PATH_MAX, nls_codepage, remap); name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ; name_len2 *= 2; /* convert to bytes */ } else { /* BB improve the check for buffer overruns BB */ @@ -3130,8 +2710,8 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifs_strtoUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage); + cifs_strtoUCS((__le16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -3188,8 +2768,8 @@ CIFSSMBUnixQuerySymLink(const int xid, struct cifs_tcon *tcon, is_unicode = false; /* BB FIXME investigate remapping reserved chars here */ - *symlinkinfo = cifs_strndup_from_utf16(data_start, - count, is_unicode, nls_codepage); + *symlinkinfo = cifs_strndup_from_ucs(data_start, count, + is_unicode, nls_codepage); if (!*symlinkinfo) rc = -ENOMEM; } @@ -3232,7 +2812,8 @@ CIFSSMBQueryReparseLinkInfo(const int xid, struct cifs_tcon *tcon, pSMB->TotalDataCount = 0; pSMB->MaxParameterCount = cpu_to_le32(2); /* BB find exact data count max from sess structure BB */ - pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); + pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); pSMB->MaxSetupCount = 4; pSMB->Reserved = 0; pSMB->ParameterOffset = 0; @@ -3472,9 +3053,8 @@ CIFSSMBGetPosixACL(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, - searchName, PATH_MAX, nls_codepage, - remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; pSMB->FileName[name_len] = 0; @@ -3560,8 +3140,8 @@ CIFSSMBSetPosixACL(const int xid, struct cifs_tcon *tcon, return rc; if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -3726,7 +3306,8 @@ smb_init_nttransact(const __u16 sub_command, const int setup_count, pSMB->Reserved = 0; pSMB->TotalParameterCount = cpu_to_le32(parm_len); pSMB->TotalDataCount = 0; - pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); + pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); pSMB->ParameterCount = pSMB->TotalParameterCount; pSMB->DataCount = pSMB->TotalDataCount; temp_offset = offsetof(struct smb_com_ntransact_req, Parms) + @@ -3886,18 +3467,19 @@ CIFSSMBGetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, int CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, - struct cifs_ntsd *pntsd, __u32 acllen, int aclflag) + struct cifs_ntsd *pntsd, __u32 acllen) { __u16 byte_count, param_count, data_count, param_offset, data_offset; int rc = 0; int bytes_returned = 0; SET_SEC_DESC_REQ *pSMB = NULL; - void *pSMBr; + NTRANSACT_RSP *pSMBr = NULL; setCifsAclRetry: - rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, &pSMBr); + rc = smb_init(SMB_COM_NT_TRANSACT, 19, tcon, (void **) &pSMB, + (void **) &pSMBr); if (rc) - return rc; + return (rc); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; @@ -3922,11 +3504,12 @@ CIFSSMBSetCIFSACL(const int xid, struct cifs_tcon *tcon, __u16 fid, pSMB->Fid = fid; /* file handle always le */ pSMB->Reserved2 = 0; - pSMB->AclFlags = cpu_to_le32(aclflag); + pSMB->AclFlags = cpu_to_le32(CIFS_ACL_DACL); if (pntsd && acllen) { memcpy((char *)pSMBr + offsetof(struct smb_hdr, Protocol) + - data_offset, pntsd, acllen); + data_offset, pntsd, acllen); + inc_rfc1001_len(pSMB, byte_count + data_count); } else inc_rfc1001_len(pSMB, byte_count); @@ -3969,9 +3552,8 @@ int SMBQueryInformation(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, - searchName, PATH_MAX, nls_codepage, - remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { @@ -4108,8 +3690,8 @@ CIFSSMBQPathInfo(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -4277,8 +3859,8 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -4366,8 +3948,8 @@ CIFSFindFirst(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); /* We can not add the asterik earlier in case it got remapped to 0xF03A as if it were part of the directory name instead of a wildcard */ @@ -4395,7 +3977,8 @@ CIFSFindFirst(const int xid, struct cifs_tcon *tcon, params = 12 + name_len /* includes null */ ; pSMB->TotalDataCount = 0; /* no EAs */ pSMB->MaxParameterCount = cpu_to_le16(10); - pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00); + pSMB->MaxDataCount = cpu_to_le16((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -4469,7 +4052,8 @@ CIFSFindFirst(const int xid, struct cifs_tcon *tcon, psrch_inf->index_of_last_entry = 2 /* skip . and .. */ + psrch_inf->entries_in_buffer; lnoff = le16_to_cpu(parms->LastNameOffset); - if (CIFSMaxBufSize < lnoff) { + if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE < + lnoff) { cERROR(1, "ignoring corrupt resume name"); psrch_inf->last_entry = NULL; return rc; @@ -4513,7 +4097,9 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, byte_count = 0; pSMB->TotalDataCount = 0; /* no EAs */ pSMB->MaxParameterCount = cpu_to_le16(8); - pSMB->MaxDataCount = cpu_to_le16(CIFSMaxBufSize & 0xFFFFFF00); + pSMB->MaxDataCount = + cpu_to_le16((tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE) & + 0xFFFFFF00); pSMB->MaxSetupCount = 0; pSMB->Reserved = 0; pSMB->Flags = 0; @@ -4595,7 +4181,8 @@ int CIFSFindNext(const int xid, struct cifs_tcon *tcon, psrch_inf->index_of_last_entry += psrch_inf->entries_in_buffer; lnoff = le16_to_cpu(parms->LastNameOffset); - if (CIFSMaxBufSize < lnoff) { + if (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE < + lnoff) { cERROR(1, "ignoring corrupt resume name"); psrch_inf->last_entry = NULL; return rc; @@ -4641,7 +4228,7 @@ CIFSFindClose(const int xid, struct cifs_tcon *tcon, pSMB->FileID = searchHandle; pSMB->ByteCount = 0; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) cERROR(1, "Send error in FindClose = %d", rc); @@ -4678,9 +4265,8 @@ CIFSGetSrvInodeNumber(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, - searchName, PATH_MAX, nls_codepage, - remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -4817,9 +4403,9 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, rc = -ENOMEM; goto parse_DFS_referrals_exit; } - cifsConvertToUTF16((__le16 *) tmp, searchName, - PATH_MAX, nls_codepage, remap); - node->path_consumed = cifs_utf16_bytes(tmp, + cifsConvertToUCS((__le16 *) tmp, searchName, + PATH_MAX, nls_codepage, remap); + node->path_consumed = cifs_ucs2_bytes(tmp, le16_to_cpu(pSMBr->PathConsumed), nls_codepage); kfree(tmp); @@ -4832,8 +4418,8 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, /* copy DfsPath */ temp = (char *)ref + le16_to_cpu(ref->DfsPathOffset); max_len = data_end - temp; - node->path_name = cifs_strndup_from_utf16(temp, max_len, - is_unicode, nls_codepage); + node->path_name = cifs_strndup_from_ucs(temp, max_len, + is_unicode, nls_codepage); if (!node->path_name) { rc = -ENOMEM; goto parse_DFS_referrals_exit; @@ -4842,14 +4428,10 @@ parse_DFS_referrals(TRANSACTION2_GET_DFS_REFER_RSP *pSMBr, /* copy link target UNC */ temp = (char *)ref + le16_to_cpu(ref->NetworkAddressOffset); max_len = data_end - temp; - node->node_name = cifs_strndup_from_utf16(temp, max_len, - is_unicode, nls_codepage); - if (!node->node_name) { + node->node_name = cifs_strndup_from_ucs(temp, max_len, + is_unicode, nls_codepage); + if (!node->node_name) rc = -ENOMEM; - goto parse_DFS_referrals_exit; - } - - ref++; } parse_DFS_referrals_exit: @@ -4900,9 +4482,8 @@ CIFSGetDFSRefer(const int xid, struct cifs_ses *ses, if (ses->capabilities & CAP_UNICODE) { pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; name_len = - cifsConvertToUTF16((__le16 *) pSMB->RequestFileName, - searchName, PATH_MAX, nls_codepage, - remap); + cifsConvertToUCS((__le16 *) pSMB->RequestFileName, + searchName, PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -5534,8 +5115,8 @@ CIFSSMBSetEOF(const int xid, struct cifs_tcon *tcon, const char *fileName, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -5666,7 +5247,7 @@ CIFSSMBSetFileSize(const int xid, struct cifs_tcon *tcon, __u64 size, pSMB->Reserved4 = 0; inc_rfc1001_len(pSMB, byte_count); pSMB->ByteCount = cpu_to_le16(byte_count); - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) { cFYI(1, "Send error in SetFileInfo (SetFileSize) = %d", rc); } @@ -5710,8 +5291,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon, param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; - data_offset = (char *)pSMB + - offsetof(struct smb_hdr, Protocol) + offset; + data_offset = (char *)pSMB + offsetof(struct smb_hdr, Protocol) + offset; count = sizeof(FILE_BASIC_INFO); pSMB->MaxParameterCount = cpu_to_le16(2); @@ -5736,7 +5316,7 @@ CIFSSMBSetFileInfo(const int xid, struct cifs_tcon *tcon, inc_rfc1001_len(pSMB, byte_count); pSMB->ByteCount = cpu_to_le16(byte_count); memcpy(data_offset, data, sizeof(FILE_BASIC_INFO)); - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); @@ -5773,7 +5353,8 @@ CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon, param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; - data_offset = (char *) (&pSMB->hdr.Protocol) + offset; + data_offset = (char *)pSMB + + offsetof(struct smb_hdr, Protocol) + offset; count = 1; pSMB->MaxParameterCount = cpu_to_le16(2); @@ -5795,7 +5376,7 @@ CIFSSMBSetFileDisposition(const int xid, struct cifs_tcon *tcon, inc_rfc1001_len(pSMB, byte_count); pSMB->ByteCount = cpu_to_le16(byte_count); *data_offset = delete_file ? 1 : 0; - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) cFYI(1, "Send error in SetFileDisposition = %d", rc); @@ -5825,8 +5406,8 @@ CIFSSMBSetPathInfo(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -5906,8 +5487,8 @@ CIFSSMBSetAttrLegacy(int xid, struct cifs_tcon *tcon, char *fileName, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - ConvertToUTF16((__le16 *) pSMB->fileName, fileName, - PATH_MAX, nls_codepage); + ConvertToUCS((__le16 *) pSMB->fileName, fileName, + PATH_MAX, nls_codepage); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -5980,7 +5561,7 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, u16 fid, u32 pid_of_opener) { struct smb_com_transaction2_sfi_req *pSMB = NULL; - char *data_offset; + FILE_UNIX_BASIC_INFO *data_offset; int rc = 0; u16 params, param_offset, offset, byte_count, count; @@ -6002,9 +5583,8 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, param_offset = offsetof(struct smb_com_transaction2_sfi_req, Fid) - 4; offset = param_offset + params; - data_offset = (char *)pSMB + - offsetof(struct smb_hdr, Protocol) + offset; - + data_offset = (FILE_UNIX_BASIC_INFO *) + ((char *)(&pSMB->hdr.Protocol) + offset); count = sizeof(FILE_UNIX_BASIC_INFO); pSMB->MaxParameterCount = cpu_to_le16(2); @@ -6026,9 +5606,9 @@ CIFSSMBUnixSetFileInfo(const int xid, struct cifs_tcon *tcon, inc_rfc1001_len(pSMB, byte_count); pSMB->ByteCount = cpu_to_le16(byte_count); - cifs_fill_unix_set_info((FILE_UNIX_BASIC_INFO *)data_offset, args); + cifs_fill_unix_set_info(data_offset, args); - rc = SendReceiveNoRsp(xid, tcon->ses, (char *) pSMB, 0); + rc = SendReceiveNoRsp(xid, tcon->ses, (struct smb_hdr *) pSMB, 0); if (rc) cFYI(1, "Send error in Set Time (SetFileInfo) = %d", rc); @@ -6060,8 +5640,8 @@ CIFSSMBUnixSetPathInfo(const int xid, struct cifs_tcon *tcon, char *fileName, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -6142,7 +5722,6 @@ CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon, char *temp_ptr; char *end_of_smb; __u16 params, byte_count, data_offset; - unsigned int ea_name_len = ea_name ? strlen(ea_name) : 0; cFYI(1, "In Query All EAs path %s", searchName); QAllEAsRetry: @@ -6153,8 +5732,8 @@ CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { list_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, searchName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, + PATH_MAX, nls_codepage, remap); list_len++; /* trailing null */ list_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -6260,8 +5839,7 @@ CIFSSMBQAllEAs(const int xid, struct cifs_tcon *tcon, } if (ea_name) { - if (ea_name_len == name_len && - memcmp(ea_name, temp_ptr, name_len) == 0) { + if (strncmp(ea_name, temp_ptr, name_len) == 0) { temp_ptr += name_len + 1; rc = value_len; if (buf_size == 0) @@ -6331,8 +5909,8 @@ CIFSSMBSetEA(const int xid, struct cifs_tcon *tcon, const char *fileName, if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) { name_len = - cifsConvertToUTF16((__le16 *) pSMB->FileName, fileName, - PATH_MAX, nls_codepage, remap); + cifsConvertToUCS((__le16 *) pSMB->FileName, fileName, + PATH_MAX, nls_codepage, remap); name_len++; /* trailing null */ name_len *= 2; } else { /* BB improve the check for buffer overruns BB */ @@ -6456,7 +6034,12 @@ int CIFSSMBNotify(const int xid, struct cifs_tcon *tcon, pSMB->TotalParameterCount = 0 ; pSMB->TotalDataCount = 0; pSMB->MaxParameterCount = cpu_to_le32(2); - pSMB->MaxDataCount = cpu_to_le32(CIFSMaxBufSize & 0xFFFFFF00); + /* BB find exact data count max from sess structure BB */ + pSMB->MaxDataCount = 0; /* same in little endian or be */ +/* BB VERIFY verify which is correct for above BB */ + pSMB->MaxDataCount = cpu_to_le32((tcon->ses->server->maxBuf - + MAX_CIFS_HDR_SIZE) & 0xFFFFFF00); + pSMB->MaxSetupCount = 4; pSMB->Reserved = 0; pSMB->ParameterOffset = 0; diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index e0b56d7a19c..f0c8d12dcd4 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -41,7 +41,6 @@ #include #include #include - #include "cifspdu.h" #include "cifsglob.h" #include "cifsproto.h" @@ -65,202 +64,6 @@ extern mempool_t *cifs_req_poolp; #define TLINK_ERROR_EXPIRE (1 * HZ) #define TLINK_IDLE_EXPIRE (600 * HZ) -enum { - - /* Mount options that take no arguments */ - Opt_user_xattr, Opt_nouser_xattr, - Opt_forceuid, Opt_noforceuid, - Opt_noblocksend, Opt_noautotune, - Opt_hard, Opt_soft, Opt_perm, Opt_noperm, - Opt_mapchars, Opt_nomapchars, Opt_sfu, - Opt_nosfu, Opt_nodfs, Opt_posixpaths, - Opt_noposixpaths, Opt_nounix, - Opt_nocase, - Opt_brl, Opt_nobrl, - Opt_forcemandatorylock, Opt_setuids, - Opt_nosetuids, Opt_dynperm, Opt_nodynperm, - Opt_nohard, Opt_nosoft, - Opt_nointr, Opt_intr, - Opt_nostrictsync, Opt_strictsync, - Opt_serverino, Opt_noserverino, - Opt_rwpidforward, Opt_cifsacl, Opt_nocifsacl, - Opt_acl, Opt_noacl, Opt_locallease, - Opt_sign, Opt_seal, Opt_direct, - Opt_strictcache, Opt_noac, - Opt_fsc, Opt_mfsymlinks, - Opt_multiuser, Opt_sloppy, - - /* Mount options which take numeric value */ - Opt_backupuid, Opt_backupgid, Opt_uid, - Opt_cruid, Opt_gid, Opt_file_mode, - Opt_dirmode, Opt_port, - Opt_rsize, Opt_wsize, Opt_actimeo, - - /* Mount options which take string value */ - Opt_user, Opt_pass, Opt_ip, - Opt_unc, Opt_domain, - Opt_srcaddr, Opt_prefixpath, - Opt_iocharset, Opt_sockopt, - Opt_netbiosname, Opt_servern, - Opt_ver, Opt_sec, - - /* Mount options to be ignored */ - Opt_ignore, - - /* Options which could be blank */ - Opt_blank_pass, - Opt_blank_user, - Opt_blank_ip, - - Opt_err -}; - -static const match_table_t cifs_mount_option_tokens = { - - { Opt_user_xattr, "user_xattr" }, - { Opt_nouser_xattr, "nouser_xattr" }, - { Opt_forceuid, "forceuid" }, - { Opt_noforceuid, "noforceuid" }, - { Opt_noblocksend, "noblocksend" }, - { Opt_noautotune, "noautotune" }, - { Opt_hard, "hard" }, - { Opt_soft, "soft" }, - { Opt_perm, "perm" }, - { Opt_noperm, "noperm" }, - { Opt_mapchars, "mapchars" }, - { Opt_nomapchars, "nomapchars" }, - { Opt_sfu, "sfu" }, - { Opt_nosfu, "nosfu" }, - { Opt_nodfs, "nodfs" }, - { Opt_posixpaths, "posixpaths" }, - { Opt_noposixpaths, "noposixpaths" }, - { Opt_nounix, "nounix" }, - { Opt_nounix, "nolinux" }, - { Opt_nocase, "nocase" }, - { Opt_nocase, "ignorecase" }, - { Opt_brl, "brl" }, - { Opt_nobrl, "nobrl" }, - { Opt_nobrl, "nolock" }, - { Opt_forcemandatorylock, "forcemandatorylock" }, - { Opt_forcemandatorylock, "forcemand" }, - { Opt_setuids, "setuids" }, - { Opt_nosetuids, "nosetuids" }, - { Opt_dynperm, "dynperm" }, - { Opt_nodynperm, "nodynperm" }, - { Opt_nohard, "nohard" }, - { Opt_nosoft, "nosoft" }, - { Opt_nointr, "nointr" }, - { Opt_intr, "intr" }, - { Opt_nostrictsync, "nostrictsync" }, - { Opt_strictsync, "strictsync" }, - { Opt_serverino, "serverino" }, - { Opt_noserverino, "noserverino" }, - { Opt_rwpidforward, "rwpidforward" }, - { Opt_cifsacl, "cifsacl" }, - { Opt_nocifsacl, "nocifsacl" }, - { Opt_acl, "acl" }, - { Opt_noacl, "noacl" }, - { Opt_locallease, "locallease" }, - { Opt_sign, "sign" }, - { Opt_seal, "seal" }, - { Opt_direct, "direct" }, - { Opt_direct, "directio" }, - { Opt_direct, "forcedirectio" }, - { Opt_strictcache, "strictcache" }, - { Opt_noac, "noac" }, - { Opt_fsc, "fsc" }, - { Opt_mfsymlinks, "mfsymlinks" }, - { Opt_multiuser, "multiuser" }, - { Opt_sloppy, "sloppy" }, - - { Opt_backupuid, "backupuid=%s" }, - { Opt_backupgid, "backupgid=%s" }, - { Opt_uid, "uid=%s" }, - { Opt_cruid, "cruid=%s" }, - { Opt_gid, "gid=%s" }, - { Opt_file_mode, "file_mode=%s" }, - { Opt_dirmode, "dirmode=%s" }, - { Opt_dirmode, "dir_mode=%s" }, - { Opt_port, "port=%s" }, - { Opt_rsize, "rsize=%s" }, - { Opt_wsize, "wsize=%s" }, - { Opt_actimeo, "actimeo=%s" }, - - { Opt_blank_user, "user=" }, - { Opt_blank_user, "username=" }, - { Opt_user, "user=%s" }, - { Opt_user, "username=%s" }, - { Opt_blank_pass, "pass=" }, - { Opt_pass, "pass=%s" }, - { Opt_pass, "password=%s" }, - { Opt_blank_ip, "ip=" }, - { Opt_blank_ip, "addr=" }, - { Opt_ip, "ip=%s" }, - { Opt_ip, "addr=%s" }, - { Opt_unc, "unc=%s" }, - { Opt_unc, "target=%s" }, - { Opt_unc, "path=%s" }, - { Opt_domain, "dom=%s" }, - { Opt_domain, "domain=%s" }, - { Opt_domain, "workgroup=%s" }, - { Opt_srcaddr, "srcaddr=%s" }, - { Opt_prefixpath, "prefixpath=%s" }, - { Opt_iocharset, "iocharset=%s" }, - { Opt_sockopt, "sockopt=%s" }, - { Opt_netbiosname, "netbiosname=%s" }, - { Opt_servern, "servern=%s" }, - { Opt_ver, "ver=%s" }, - { Opt_ver, "vers=%s" }, - { Opt_ver, "version=%s" }, - { Opt_sec, "sec=%s" }, - - { Opt_ignore, "cred" }, - { Opt_ignore, "credentials" }, - { Opt_ignore, "cred=%s" }, - { Opt_ignore, "credentials=%s" }, - { Opt_ignore, "guest" }, - { Opt_ignore, "rw" }, - { Opt_ignore, "ro" }, - { Opt_ignore, "suid" }, - { Opt_ignore, "nosuid" }, - { Opt_ignore, "exec" }, - { Opt_ignore, "noexec" }, - { Opt_ignore, "nodev" }, - { Opt_ignore, "noauto" }, - { Opt_ignore, "dev" }, - { Opt_ignore, "mand" }, - { Opt_ignore, "nomand" }, - { Opt_ignore, "_netdev" }, - - { Opt_err, NULL } -}; - -enum { - Opt_sec_krb5, Opt_sec_krb5i, Opt_sec_krb5p, - Opt_sec_ntlmsspi, Opt_sec_ntlmssp, - Opt_ntlm, Opt_sec_ntlmi, Opt_sec_ntlmv2i, - Opt_sec_nontlm, Opt_sec_lanman, - Opt_sec_none, - - Opt_sec_err -}; - -static const match_table_t cifs_secflavor_tokens = { - { Opt_sec_krb5, "krb5" }, - { Opt_sec_krb5i, "krb5i" }, - { Opt_sec_krb5p, "krb5p" }, - { Opt_sec_ntlmsspi, "ntlmsspi" }, - { Opt_sec_ntlmssp, "ntlmssp" }, - { Opt_ntlm, "ntlm" }, - { Opt_sec_ntlmi, "ntlmi" }, - { Opt_sec_ntlmv2i, "ntlmv2i" }, - { Opt_sec_nontlm, "nontlm" }, - { Opt_sec_lanman, "lanman" }, - { Opt_sec_none, "none" }, - - { Opt_sec_err, NULL } -}; - static int ip_connect(struct TCP_Server_Info *server); static int generic_ip_connect(struct TCP_Server_Info *server); static void tlink_rb_insert(struct rb_root *root, struct tcon_link *new_tlink); @@ -341,8 +144,8 @@ cifs_reconnect(struct TCP_Server_Info *server) spin_lock(&GlobalMid_Lock); list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - if (mid_entry->mid_state == MID_REQUEST_SUBMITTED) - mid_entry->mid_state = MID_RETRY_NEEDED; + if (mid_entry->midState == MID_REQUEST_SUBMITTED) + mid_entry->midState = MID_RETRY_NEEDED; list_move(&mid_entry->qhead, &retry_list); } spin_unlock(&GlobalMid_Lock); @@ -381,9 +184,8 @@ cifs_reconnect(struct TCP_Server_Info *server) -EINVAL = invalid transact2 */ -static int check2ndT2(char *buf) +static int check2ndT2(struct smb_hdr *pSMB, unsigned int maxBufSize) { - struct smb_hdr *pSMB = (struct smb_hdr *)buf; struct smb_t2_rsp *pSMBt; int remaining; __u16 total_data_size, data_in_this_rsp; @@ -415,100 +217,84 @@ static int check2ndT2(char *buf) cFYI(1, "missing %d bytes from transact2, check next response", remaining); - if (total_data_size > CIFSMaxBufSize) { + if (total_data_size > maxBufSize) { cERROR(1, "TotalDataSize %d is over maximum buffer %d", - total_data_size, CIFSMaxBufSize); + total_data_size, maxBufSize); return -EINVAL; } return remaining; } -static int coalesce_t2(char *second_buf, struct smb_hdr *target_hdr) +static int coalesce_t2(struct smb_hdr *psecond, struct smb_hdr *pTargetSMB) { - struct smb_t2_rsp *pSMBs = (struct smb_t2_rsp *)second_buf; - struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)target_hdr; - char *data_area_of_tgt; - char *data_area_of_src; + struct smb_t2_rsp *pSMB2 = (struct smb_t2_rsp *)psecond; + struct smb_t2_rsp *pSMBt = (struct smb_t2_rsp *)pTargetSMB; + char *data_area_of_target; + char *data_area_of_buf2; int remaining; - unsigned int byte_count, total_in_tgt; - __u16 tgt_total_cnt, src_total_cnt, total_in_src; + unsigned int byte_count, total_in_buf; + __u16 total_data_size, total_in_buf2; - src_total_cnt = get_unaligned_le16(&pSMBs->t2_rsp.TotalDataCount); - tgt_total_cnt = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); + total_data_size = get_unaligned_le16(&pSMBt->t2_rsp.TotalDataCount); - if (tgt_total_cnt != src_total_cnt) - cFYI(1, "total data count of primary and secondary t2 differ " - "source=%hu target=%hu", src_total_cnt, tgt_total_cnt); + if (total_data_size != + get_unaligned_le16(&pSMB2->t2_rsp.TotalDataCount)) + cFYI(1, "total data size of primary and secondary t2 differ"); - total_in_tgt = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); + total_in_buf = get_unaligned_le16(&pSMBt->t2_rsp.DataCount); - remaining = tgt_total_cnt - total_in_tgt; + remaining = total_data_size - total_in_buf; - if (remaining < 0) { - cFYI(1, "Server sent too much data. tgt_total_cnt=%hu " - "total_in_tgt=%hu", tgt_total_cnt, total_in_tgt); + if (remaining < 0) return -EPROTO; - } - if (remaining == 0) { - /* nothing to do, ignore */ - cFYI(1, "no more data remains"); + if (remaining == 0) /* nothing to do, ignore */ return 0; - } - total_in_src = get_unaligned_le16(&pSMBs->t2_rsp.DataCount); - if (remaining < total_in_src) + total_in_buf2 = get_unaligned_le16(&pSMB2->t2_rsp.DataCount); + if (remaining < total_in_buf2) { cFYI(1, "transact2 2nd response contains too much data"); + } /* find end of first SMB data area */ - data_area_of_tgt = (char *)&pSMBt->hdr.Protocol + + data_area_of_target = (char *)&pSMBt->hdr.Protocol + get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); - /* validate target area */ - data_area_of_src = (char *)&pSMBs->hdr.Protocol + - get_unaligned_le16(&pSMBs->t2_rsp.DataOffset); - data_area_of_tgt += total_in_tgt; + data_area_of_buf2 = (char *)&pSMB2->hdr.Protocol + + get_unaligned_le16(&pSMB2->t2_rsp.DataOffset); + + data_area_of_target += total_in_buf; - total_in_tgt += total_in_src; + /* copy second buffer into end of first buffer */ + total_in_buf += total_in_buf2; /* is the result too big for the field? */ - if (total_in_tgt > USHRT_MAX) { - cFYI(1, "coalesced DataCount too large (%u)", total_in_tgt); + if (total_in_buf > USHRT_MAX) return -EPROTO; - } - put_unaligned_le16(total_in_tgt, &pSMBt->t2_rsp.DataCount); + put_unaligned_le16(total_in_buf, &pSMBt->t2_rsp.DataCount); /* fix up the BCC */ - byte_count = get_bcc(target_hdr); - byte_count += total_in_src; + byte_count = get_bcc(pTargetSMB); + byte_count += total_in_buf2; /* is the result too big for the field? */ - if (byte_count > USHRT_MAX) { - cFYI(1, "coalesced BCC too large (%u)", byte_count); + if (byte_count > USHRT_MAX) return -EPROTO; - } - put_bcc(byte_count, target_hdr); + put_bcc(byte_count, pTargetSMB); - byte_count = be32_to_cpu(target_hdr->smb_buf_length); - byte_count += total_in_src; + byte_count = be32_to_cpu(pTargetSMB->smb_buf_length); + byte_count += total_in_buf2; /* don't allow buffer to overflow */ - if (byte_count > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { - cFYI(1, "coalesced BCC exceeds buffer size (%u)", byte_count); + if (byte_count > CIFSMaxBufSize) return -ENOBUFS; - } - target_hdr->smb_buf_length = cpu_to_be32(byte_count); + pTargetSMB->smb_buf_length = cpu_to_be32(byte_count); - /* copy second buffer into end of first buffer */ - memcpy(data_area_of_tgt, data_area_of_src, total_in_src); + memcpy(data_area_of_target, data_area_of_buf2, total_in_buf2); - if (remaining != total_in_src) { - /* more responses to go */ - cFYI(1, "waiting for more secondary responses"); + if (remaining == total_in_buf2) { + cFYI(1, "found the last secondary response"); + return 0; /* we are done */ + } else /* more responses to go */ return 1; - } - - /* we are done */ - cFYI(1, "found the last secondary response"); - return 0; } static void @@ -533,314 +319,346 @@ cifs_echo_request(struct work_struct *work) server->hostname); requeue_echo: - queue_delayed_work(cifsiod_wq, &server->echo, SMB_ECHO_INTERVAL); -} - -static bool -allocate_buffers(struct TCP_Server_Info *server) -{ - if (!server->bigbuf) { - server->bigbuf = (char *)cifs_buf_get(); - if (!server->bigbuf) { - cERROR(1, "No memory for large SMB response"); - msleep(3000); - /* retry will check if exiting */ - return false; - } - } else if (server->large_buf) { - /* we are reusing a dirty large buf, clear its start */ - memset(server->bigbuf, 0, header_size()); - } - - if (!server->smallbuf) { - server->smallbuf = (char *)cifs_small_buf_get(); - if (!server->smallbuf) { - cERROR(1, "No memory for SMB response"); - msleep(1000); - /* retry will check if exiting */ - return false; - } - /* beginning of smb buffer is cleared in our buf_get */ - } else { - /* if existing small buf clear beginning */ - memset(server->smallbuf, 0, header_size()); - } - - return true; + queue_delayed_work(system_nrt_wq, &server->echo, SMB_ECHO_INTERVAL); } -static bool -server_unresponsive(struct TCP_Server_Info *server) +static int +cifs_demultiplex_thread(struct TCP_Server_Info *server) { - /* - * We need to wait 2 echo intervals to make sure we handle such - * situations right: - * 1s client sends a normal SMB request - * 2s client gets a response - * 30s echo workqueue job pops, and decides we got a response recently - * and don't need to send another - * ... - * 65s kernel_recvmsg times out, and we see that we haven't gotten - * a response in >60s. - */ - if (server->tcpStatus == CifsGood && - time_after(jiffies, server->lstrp + 2 * SMB_ECHO_INTERVAL)) { - cERROR(1, "Server %s has not responded in %d seconds. " - "Reconnecting...", server->hostname, - (2 * SMB_ECHO_INTERVAL) / HZ); - cifs_reconnect(server); - wake_up(&server->response_q); - return true; - } - - return false; -} + int length; + unsigned int pdu_length, total_read; + struct smb_hdr *smb_buffer = NULL; + struct smb_hdr *bigbuf = NULL; + struct smb_hdr *smallbuf = NULL; + struct msghdr smb_msg; + struct kvec iov; + struct socket *csocket = server->ssocket; + struct list_head *tmp, *tmp2; + struct task_struct *task_to_wake = NULL; + struct mid_q_entry *mid_entry; + char temp; + bool isLargeBuf = false; + bool isMultiRsp; + int reconnect; -/* - * kvec_array_init - clone a kvec array, and advance into it - * @new: pointer to memory for cloned array - * @iov: pointer to original array - * @nr_segs: number of members in original array - * @bytes: number of bytes to advance into the cloned array - * - * This function will copy the array provided in iov to a section of memory - * and advance the specified number of bytes into the new array. It returns - * the number of segments in the new array. "new" must be at least as big as - * the original iov array. - */ -static unsigned int -kvec_array_init(struct kvec *new, struct kvec *iov, unsigned int nr_segs, - size_t bytes) -{ - size_t base = 0; + current->flags |= PF_MEMALLOC; + cFYI(1, "Demultiplex PID: %d", task_pid_nr(current)); - while (bytes || !iov->iov_len) { - int copy = min(bytes, iov->iov_len); + length = atomic_inc_return(&tcpSesAllocCount); + if (length > 1) + mempool_resize(cifs_req_poolp, length + cifs_min_rcv, + GFP_KERNEL); - bytes -= copy; - base += copy; - if (iov->iov_len == base) { - iov++; - nr_segs--; - base = 0; + set_freezable(); + while (server->tcpStatus != CifsExiting) { + if (try_to_freeze()) + continue; + if (bigbuf == NULL) { + bigbuf = cifs_buf_get(); + if (!bigbuf) { + cERROR(1, "No memory for large SMB response"); + msleep(3000); + /* retry will check if exiting */ + continue; + } + } else if (isLargeBuf) { + /* we are reusing a dirty large buf, clear its start */ + memset(bigbuf, 0, sizeof(struct smb_hdr)); } - } - memcpy(new, iov, sizeof(*iov) * nr_segs); - new->iov_base += base; - new->iov_len -= base; - return nr_segs; -} -static struct kvec * -get_server_iovec(struct TCP_Server_Info *server, unsigned int nr_segs) -{ - struct kvec *new_iov; - - if (server->iov && nr_segs <= server->nr_iov) - return server->iov; - - /* not big enough -- allocate a new one and release the old */ - new_iov = kmalloc(sizeof(*new_iov) * nr_segs, GFP_NOFS); - if (new_iov) { - kfree(server->iov); - server->iov = new_iov; - server->nr_iov = nr_segs; - } - return new_iov; -} - -int -cifs_readv_from_socket(struct TCP_Server_Info *server, struct kvec *iov_orig, - unsigned int nr_segs, unsigned int to_read) -{ - int length = 0; - int total_read; - unsigned int segs; - struct msghdr smb_msg; - struct kvec *iov; - - iov = get_server_iovec(server, nr_segs); - if (!iov) - return -ENOMEM; - - smb_msg.msg_control = NULL; - smb_msg.msg_controllen = 0; - - for (total_read = 0; to_read; total_read += length, to_read -= length) { - try_to_freeze(); + if (smallbuf == NULL) { + smallbuf = cifs_small_buf_get(); + if (!smallbuf) { + cERROR(1, "No memory for SMB response"); + msleep(1000); + /* retry will check if exiting */ + continue; + } + /* beginning of smb buffer is cleared in our buf_get */ + } else /* if existing small buf clear beginning */ + memset(smallbuf, 0, sizeof(struct smb_hdr)); + + isLargeBuf = false; + isMultiRsp = false; + smb_buffer = smallbuf; + iov.iov_base = smb_buffer; + iov.iov_len = 4; + smb_msg.msg_control = NULL; + smb_msg.msg_controllen = 0; + pdu_length = 4; /* enough to get RFC1001 header */ - if (server_unresponsive(server)) { - total_read = -EAGAIN; - break; +incomplete_rcv: + if (echo_retries > 0 && server->tcpStatus == CifsGood && + time_after(jiffies, server->lstrp + + (echo_retries * SMB_ECHO_INTERVAL))) { + cERROR(1, "Server %s has not responded in %d seconds. " + "Reconnecting...", server->hostname, + (echo_retries * SMB_ECHO_INTERVAL / HZ)); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; } - segs = kvec_array_init(iov, iov_orig, nr_segs, total_read); - - length = kernel_recvmsg(server->ssocket, &smb_msg, - iov, segs, to_read, 0); + length = + kernel_recvmsg(csocket, &smb_msg, + &iov, 1, pdu_length, 0 /* BB other flags? */); if (server->tcpStatus == CifsExiting) { - total_read = -ESHUTDOWN; break; } else if (server->tcpStatus == CifsNeedReconnect) { + cFYI(1, "Reconnect after server stopped responding"); cifs_reconnect(server); - total_read = -EAGAIN; - break; + cFYI(1, "call to reconnect done"); + csocket = server->ssocket; + continue; } else if (length == -ERESTARTSYS || length == -EAGAIN || length == -EINTR) { - /* - * Minimum sleep to prevent looping, allowing socket - * to clear and app threads to set tcpStatus - * CifsNeedReconnect if server hung. + msleep(1); /* minimum sleep to prevent looping + allowing socket to clear and app threads to set + tcpStatus CifsNeedReconnect if server hung */ + if (pdu_length < 4) { + iov.iov_base = (4 - pdu_length) + + (char *)smb_buffer; + iov.iov_len = pdu_length; + smb_msg.msg_control = NULL; + smb_msg.msg_controllen = 0; + goto incomplete_rcv; + } else + continue; + } else if (length <= 0) { + cFYI(1, "Reconnect after unexpected peek error %d", + length); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; + } else if (length < pdu_length) { + cFYI(1, "requested %d bytes but only got %d bytes", + pdu_length, length); + pdu_length -= length; + msleep(1); + goto incomplete_rcv; + } + + /* The right amount was read from socket - 4 bytes */ + /* so we can now interpret the length field */ + + /* the first byte big endian of the length field, + is actually not part of the length but the type + with the most common, zero, as regular data */ + temp = *((char *) smb_buffer); + + /* Note that FC 1001 length is big endian on the wire, + but we convert it here so it is always manipulated + as host byte order */ + pdu_length = be32_to_cpu(smb_buffer->smb_buf_length); + + cFYI(1, "rfc1002 length 0x%x", pdu_length+4); + + if (temp == (char) RFC1002_SESSION_KEEP_ALIVE) { + continue; + } else if (temp == (char)RFC1002_POSITIVE_SESSION_RESPONSE) { + cFYI(1, "Good RFC 1002 session rsp"); + continue; + } else if (temp == (char)RFC1002_NEGATIVE_SESSION_RESPONSE) { + /* we get this from Windows 98 instead of + an error on SMB negprot response */ + cFYI(1, "Negative RFC1002 Session Response Error 0x%x)", + pdu_length); + /* give server a second to clean up */ + msleep(1000); + /* always try 445 first on reconnect since we get NACK + * on some if we ever connected to port 139 (the NACK + * is since we do not begin with RFC1001 session + * initialize frame) */ - usleep_range(1000, 2000); - length = 0; + cifs_set_port((struct sockaddr *) + &server->dstaddr, CIFS_PORT); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); continue; - } else if (length <= 0) { - cFYI(1, "Received no data or error: expecting %d " - "got %d", to_read, length); + } else if (temp != (char) 0) { + cERROR(1, "Unknown RFC 1002 frame"); + cifs_dump_mem(" Received Data: ", (char *)smb_buffer, + length); cifs_reconnect(server); - total_read = -EAGAIN; - break; + csocket = server->ssocket; + continue; } - } - return total_read; -} -int -cifs_read_from_socket(struct TCP_Server_Info *server, char *buf, - unsigned int to_read) -{ - struct kvec iov; + /* else we have an SMB response */ + if ((pdu_length > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) || + (pdu_length < sizeof(struct smb_hdr) - 1 - 4)) { + cERROR(1, "Invalid size SMB length %d pdu_length %d", + length, pdu_length+4); + cifs_reconnect(server); + csocket = server->ssocket; + wake_up(&server->response_q); + continue; + } - iov.iov_base = buf; - iov.iov_len = to_read; + /* else length ok */ + reconnect = 0; - return cifs_readv_from_socket(server, &iov, 1, to_read); -} + if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { + isLargeBuf = true; + memcpy(bigbuf, smallbuf, 4); + smb_buffer = bigbuf; + } + length = 0; + iov.iov_base = 4 + (char *)smb_buffer; + iov.iov_len = pdu_length; + for (total_read = 0; total_read < pdu_length; + total_read += length) { + length = kernel_recvmsg(csocket, &smb_msg, &iov, 1, + pdu_length - total_read, 0); + if (server->tcpStatus == CifsExiting) { + /* then will exit */ + reconnect = 2; + break; + } else if (server->tcpStatus == CifsNeedReconnect) { + cifs_reconnect(server); + csocket = server->ssocket; + /* Reconnect wakes up rspns q */ + /* Now we will reread sock */ + reconnect = 1; + break; + } else if (length == -ERESTARTSYS || + length == -EAGAIN || + length == -EINTR) { + msleep(1); /* minimum sleep to prevent looping, + allowing socket to clear and app + threads to set tcpStatus + CifsNeedReconnect if server hung*/ + length = 0; + continue; + } else if (length <= 0) { + cERROR(1, "Received no data, expecting %d", + pdu_length - total_read); + cifs_reconnect(server); + csocket = server->ssocket; + reconnect = 1; + break; + } + } + if (reconnect == 2) + break; + else if (reconnect == 1) + continue; + + total_read += 4; /* account for rfc1002 hdr */ + + dump_smb(smb_buffer, total_read); -static bool -is_smb_response(struct TCP_Server_Info *server, unsigned char type) -{ - /* - * The first byte big endian of the length field, - * is actually not part of the length but the type - * with the most common, zero, as regular data. - */ - switch (type) { - case RFC1002_SESSION_MESSAGE: - /* Regular SMB response */ - return true; - case RFC1002_SESSION_KEEP_ALIVE: - cFYI(1, "RFC 1002 session keep alive"); - break; - case RFC1002_POSITIVE_SESSION_RESPONSE: - cFYI(1, "RFC 1002 positive session response"); - break; - case RFC1002_NEGATIVE_SESSION_RESPONSE: - /* - * We get this from Windows 98 instead of an error on - * SMB negprot response. - */ - cFYI(1, "RFC 1002 negative session response"); - /* give server a second to clean up */ - msleep(1000); /* - * Always try 445 first on reconnect since we get NACK - * on some if we ever connected to port 139 (the NACK - * is since we do not begin with RFC1001 session - * initialize frame). + * We know that we received enough to get to the MID as we + * checked the pdu_length earlier. Now check to see + * if the rest of the header is OK. We borrow the length + * var for the rest of the loop to avoid a new stack var. + * + * 48 bytes is enough to display the header and a little bit + * into the payload for debugging purposes. */ - cifs_set_port((struct sockaddr *)&server->dstaddr, CIFS_PORT); - cifs_reconnect(server); - wake_up(&server->response_q); - break; - default: - cERROR(1, "RFC 1002 unknown response type 0x%x", type); - cifs_reconnect(server); - } + length = checkSMB(smb_buffer, smb_buffer->Mid, total_read); + if (length != 0) + cifs_dump_mem("Bad SMB: ", smb_buffer, + min_t(unsigned int, total_read, 48)); - return false; -} + mid_entry = NULL; + server->lstrp = jiffies; -static struct mid_q_entry * -find_mid(struct TCP_Server_Info *server, char *buffer) -{ - struct smb_hdr *buf = (struct smb_hdr *)buffer; - struct mid_q_entry *mid; + spin_lock(&GlobalMid_Lock); + list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { + mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - spin_lock(&GlobalMid_Lock); - list_for_each_entry(mid, &server->pending_mid_q, qhead) { - if (mid->mid == buf->Mid && - mid->mid_state == MID_REQUEST_SUBMITTED && - le16_to_cpu(mid->command) == buf->Command) { - spin_unlock(&GlobalMid_Lock); - return mid; - } - } - spin_unlock(&GlobalMid_Lock); - return NULL; -} + if (mid_entry->mid != smb_buffer->Mid || + mid_entry->midState != MID_REQUEST_SUBMITTED || + mid_entry->command != smb_buffer->Command) { + mid_entry = NULL; + continue; + } -void -dequeue_mid(struct mid_q_entry *mid, bool malformed) -{ + if (length == 0 && + check2ndT2(smb_buffer, server->maxBuf) > 0) { + /* We have a multipart transact2 resp */ + isMultiRsp = true; + if (mid_entry->resp_buf) { + /* merge response - fix up 1st*/ + length = coalesce_t2(smb_buffer, + mid_entry->resp_buf); + if (length > 0) { + length = 0; + mid_entry->multiRsp = true; + break; + } else { + /* all parts received or + * packet is malformed + */ + mid_entry->multiEnd = true; + goto multi_t2_fnd; + } + } else { + if (!isLargeBuf) { + /* + * FIXME: switch to already + * allocated largebuf? + */ + cERROR(1, "1st trans2 resp " + "needs bigbuf"); + } else { + /* Have first buffer */ + mid_entry->resp_buf = + smb_buffer; + mid_entry->largeBuf = true; + bigbuf = NULL; + } + } + break; + } + mid_entry->resp_buf = smb_buffer; + mid_entry->largeBuf = isLargeBuf; +multi_t2_fnd: + if (length == 0) + mid_entry->midState = MID_RESPONSE_RECEIVED; + else + mid_entry->midState = MID_RESPONSE_MALFORMED; #ifdef CONFIG_CIFS_STATS2 - mid->when_received = jiffies; + mid_entry->when_received = jiffies; #endif - spin_lock(&GlobalMid_Lock); - if (!malformed) - mid->mid_state = MID_RESPONSE_RECEIVED; - else - mid->mid_state = MID_RESPONSE_MALFORMED; - list_del_init(&mid->qhead); - spin_unlock(&GlobalMid_Lock); -} - -static void -handle_mid(struct mid_q_entry *mid, struct TCP_Server_Info *server, - char *buf, int malformed) -{ - if (malformed == 0 && check2ndT2(buf) > 0) { - mid->multiRsp = true; - if (mid->resp_buf) { - /* merge response - fix up 1st*/ - malformed = coalesce_t2(buf, mid->resp_buf); - if (malformed > 0) - return; - - /* All parts received or packet is malformed. */ - mid->multiEnd = true; - return dequeue_mid(mid, malformed); - } - if (!server->large_buf) { - /*FIXME: switch to already allocated largebuf?*/ - cERROR(1, "1st trans2 resp needs bigbuf"); - } else { - /* Have first buffer */ - mid->resp_buf = buf; - mid->large_buf = true; - server->bigbuf = NULL; + list_del_init(&mid_entry->qhead); + break; } - return; - } - mid->resp_buf = buf; - mid->large_buf = server->large_buf; - /* Was previous buf put in mpx struct for multi-rsp? */ - if (!mid->multiRsp) { - /* smb buffer will be freed by user thread */ - if (server->large_buf) - server->bigbuf = NULL; - else - server->smallbuf = NULL; - } - dequeue_mid(mid, malformed); -} + spin_unlock(&GlobalMid_Lock); -static void clean_demultiplex_info(struct TCP_Server_Info *server) -{ - int length; + if (mid_entry != NULL) { + mid_entry->callback(mid_entry); + /* Was previous buf put in mpx struct for multi-rsp? */ + if (!isMultiRsp) { + /* smb buffer will be freed by user thread */ + if (isLargeBuf) + bigbuf = NULL; + else + smallbuf = NULL; + } + } else if (length != 0) { + /* response sanity checks failed */ + continue; + } else if (!is_valid_oplock_break(smb_buffer, server) && + !isMultiRsp) { + cERROR(1, "No task to wake, unknown frame received! " + "NumMids %d", atomic_read(&midCount)); + cifs_dump_mem("Received Data is: ", (char *)smb_buffer, + sizeof(struct smb_hdr)); +#ifdef CONFIG_CIFS_DEBUG2 + cifs_dump_detail(smb_buffer); + cifs_dump_mids(server); +#endif /* CIFS_DEBUG2 */ + + } + } /* end while !EXITING */ /* take it off the list, if it's not already */ spin_lock(&cifs_tcp_ses_lock); @@ -853,37 +671,41 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) wake_up_all(&server->response_q); /* check if we have blocked requests that need to free */ - spin_lock(&server->req_lock); - if (server->credits <= 0) - server->credits = 1; - spin_unlock(&server->req_lock); - /* - * Although there should not be any requests blocked on this queue it - * can not hurt to be paranoid and try to wake up requests that may - * haven been blocked when more than 50 at time were on the wire to the - * same server - they now will see the session is in exit state and get - * out of SendReceive. - */ + /* Note that cifs_max_pending is normally 50, but + can be set at module install time to as little as two */ + spin_lock(&GlobalMid_Lock); + if (atomic_read(&server->inFlight) >= cifs_max_pending) + atomic_set(&server->inFlight, cifs_max_pending - 1); + /* We do not want to set the max_pending too low or we + could end up with the counter going negative */ + spin_unlock(&GlobalMid_Lock); + /* Although there should not be any requests blocked on + this queue it can not hurt to be paranoid and try to wake up requests + that may haven been blocked when more than 50 at time were on the wire + to the same server - they now will see the session is in exit state + and get out of SendReceive. */ wake_up_all(&server->request_q); /* give those requests time to exit */ msleep(125); if (server->ssocket) { - sock_release(server->ssocket); + sock_release(csocket); server->ssocket = NULL; } + /* buffer usually freed in free_mid - need to free it here on exit */ + cifs_buf_release(bigbuf); + if (smallbuf) /* no sense logging a debug message if NULL */ + cifs_small_buf_release(smallbuf); if (!list_empty(&server->pending_mid_q)) { struct list_head dispose_list; - struct mid_q_entry *mid_entry; - struct list_head *tmp, *tmp2; INIT_LIST_HEAD(&dispose_list); spin_lock(&GlobalMid_Lock); list_for_each_safe(tmp, tmp2, &server->pending_mid_q) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cFYI(1, "Clearing mid 0x%llx", mid_entry->mid); - mid_entry->mid_state = MID_SHUTDOWN; + cFYI(1, "Clearing mid 0x%x", mid_entry->mid); + mid_entry->midState = MID_SHUTDOWN; list_move(&mid_entry->qhead, &dispose_list); } spin_unlock(&GlobalMid_Lock); @@ -891,7 +713,7 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) /* now walk dispose list and issue callbacks */ list_for_each_safe(tmp, tmp2, &dispose_list) { mid_entry = list_entry(tmp, struct mid_q_entry, qhead); - cFYI(1, "Callback mid 0x%llx", mid_entry->mid); + cFYI(1, "Callback mid 0x%x", mid_entry->mid); list_del_init(&mid_entry->qhead); mid_entry->callback(mid_entry); } @@ -900,183 +722,27 @@ static void clean_demultiplex_info(struct TCP_Server_Info *server) } if (!list_empty(&server->pending_mid_q)) { - /* - * mpx threads have not exited yet give them at least the smb - * send timeout time for long ops. - * - * Due to delays on oplock break requests, we need to wait at - * least 45 seconds before giving up on a request getting a - * response and going ahead and killing cifsd. - */ + /* mpx threads have not exited yet give them + at least the smb send timeout time for long ops */ + /* due to delays on oplock break requests, we need + to wait at least 45 seconds before giving up + on a request getting a response and going ahead + and killing cifsd */ cFYI(1, "Wait for exit from demultiplex thread"); msleep(46000); - /* - * If threads still have not exited they are probably never - * coming home not much else we can do but free the memory. - */ + /* if threads still have not exited they are probably never + coming home not much else we can do but free the memory */ } kfree(server->hostname); - kfree(server->iov); + task_to_wake = xchg(&server->tsk, NULL); kfree(server); length = atomic_dec_return(&tcpSesAllocCount); - if (length > 0) - mempool_resize(cifs_req_poolp, length + cifs_min_rcv, - GFP_KERNEL); -} - -static int -standard_receive3(struct TCP_Server_Info *server, struct mid_q_entry *mid) -{ - int length; - char *buf = server->smallbuf; - unsigned int pdu_length = get_rfc1002_length(buf); - - /* make sure this will fit in a large buffer */ - if (pdu_length > CIFSMaxBufSize + max_header_size() - 4) { - cERROR(1, "SMB response too long (%u bytes)", - pdu_length); - cifs_reconnect(server); - wake_up(&server->response_q); - return -EAGAIN; - } - - /* switch to large buffer if too big for a small one */ - if (pdu_length > MAX_CIFS_SMALL_BUFFER_SIZE - 4) { - server->large_buf = true; - memcpy(server->bigbuf, buf, server->total_read); - buf = server->bigbuf; - } - - /* now read the rest */ - length = cifs_read_from_socket(server, buf + header_size() - 1, - pdu_length - header_size() + 1 + 4); - if (length < 0) - return length; - server->total_read += length; - - dump_smb(buf, server->total_read); - - /* - * We know that we received enough to get to the MID as we - * checked the pdu_length earlier. Now check to see - * if the rest of the header is OK. We borrow the length - * var for the rest of the loop to avoid a new stack var. - * - * 48 bytes is enough to display the header and a little bit - * into the payload for debugging purposes. - */ - length = checkSMB(buf, server->total_read); - if (length != 0) - cifs_dump_mem("Bad SMB: ", buf, - min_t(unsigned int, server->total_read, 48)); - - if (!mid) - return length; - - handle_mid(mid, server, buf, length); - return 0; -} - -static int -cifs_demultiplex_thread(void *p) -{ - int length; - struct TCP_Server_Info *server = p; - unsigned int pdu_length; - char *buf = NULL; - struct task_struct *task_to_wake = NULL; - struct mid_q_entry *mid_entry; - - current->flags |= PF_MEMALLOC; - cFYI(1, "Demultiplex PID: %d", task_pid_nr(current)); - - length = atomic_inc_return(&tcpSesAllocCount); - if (length > 1) + if (length > 0) mempool_resize(cifs_req_poolp, length + cifs_min_rcv, GFP_KERNEL); - set_freezable(); - while (server->tcpStatus != CifsExiting) { - if (try_to_freeze()) - continue; - - if (!allocate_buffers(server)) - continue; - - server->large_buf = false; - buf = server->smallbuf; - pdu_length = 4; /* enough to get RFC1001 header */ - - length = cifs_read_from_socket(server, buf, pdu_length); - if (length < 0) - continue; - server->total_read = length; - - /* - * The right amount was read from socket - 4 bytes, - * so we can now interpret the length field. - */ - pdu_length = get_rfc1002_length(buf); - - cFYI(1, "RFC1002 header 0x%x", pdu_length); - if (!is_smb_response(server, buf[0])) - continue; - - /* make sure we have enough to get to the MID */ - if (pdu_length < header_size() - 1 - 4) { - cERROR(1, "SMB response too short (%u bytes)", - pdu_length); - cifs_reconnect(server); - wake_up(&server->response_q); - continue; - } - - /* read down to the MID */ - length = cifs_read_from_socket(server, buf + 4, - header_size() - 1 - 4); - if (length < 0) - continue; - server->total_read += length; - - mid_entry = find_mid(server, buf); - - if (!mid_entry || !mid_entry->receive) - length = standard_receive3(server, mid_entry); - else - length = mid_entry->receive(server, mid_entry); - - if (length < 0) - continue; - - if (server->large_buf) - buf = server->bigbuf; - - server->lstrp = jiffies; - if (mid_entry != NULL) { - if (!mid_entry->multiRsp || mid_entry->multiEnd) - mid_entry->callback(mid_entry); - } else if (!is_valid_oplock_break(buf, server)) { - cERROR(1, "No task to wake, unknown frame received! " - "NumMids %d", atomic_read(&midCount)); - cifs_dump_mem("Received Data is: ", buf, header_size()); -#ifdef CONFIG_CIFS_DEBUG2 - cifs_dump_detail(buf); - cifs_dump_mids(server); -#endif /* CIFS_DEBUG2 */ - - } - } /* end while !EXITING */ - - /* buffer usually freed in free_mid - need to free it here on exit */ - cifs_buf_release(server->bigbuf); - if (server->smallbuf) /* no sense logging a debug message if NULL */ - cifs_small_buf_release(server->smallbuf); - - task_to_wake = xchg(&server->tsk, NULL); - clean_demultiplex_info(server); - /* if server->tsk was NULL then wait for a signal before exiting */ if (!task_to_wake) { set_current_state(TASK_INTERRUPTIBLE); @@ -1118,78 +784,11 @@ extract_hostname(const char *unc) return dst; } -static int get_option_ul(substring_t args[], unsigned long *option) -{ - int rc; - char *string; - - string = match_strdup(args); - if (string == NULL) - return -ENOMEM; - rc = kstrtoul(string, 0, option); - kfree(string); - - return rc; -} - - -static int cifs_parse_security_flavors(char *value, - struct smb_vol *vol) -{ - - substring_t args[MAX_OPT_ARGS]; - - switch (match_token(value, cifs_secflavor_tokens, args)) { - case Opt_sec_krb5: - vol->secFlg |= CIFSSEC_MAY_KRB5; - break; - case Opt_sec_krb5i: - vol->secFlg |= CIFSSEC_MAY_KRB5 | CIFSSEC_MUST_SIGN; - break; - case Opt_sec_krb5p: - /* vol->secFlg |= CIFSSEC_MUST_SEAL | CIFSSEC_MAY_KRB5; */ - cERROR(1, "Krb5 cifs privacy not supported"); - break; - case Opt_sec_ntlmssp: - vol->secFlg |= CIFSSEC_MAY_NTLMSSP; - break; - case Opt_sec_ntlmsspi: - vol->secFlg |= CIFSSEC_MAY_NTLMSSP | CIFSSEC_MUST_SIGN; - break; - case Opt_ntlm: - /* ntlm is default so can be turned off too */ - vol->secFlg |= CIFSSEC_MAY_NTLM; - break; - case Opt_sec_ntlmi: - vol->secFlg |= CIFSSEC_MAY_NTLM | CIFSSEC_MUST_SIGN; - break; - case Opt_sec_nontlm: - vol->secFlg |= CIFSSEC_MAY_NTLMV2; - break; - case Opt_sec_ntlmv2i: - vol->secFlg |= CIFSSEC_MAY_NTLMV2 | CIFSSEC_MUST_SIGN; - break; -#ifdef CONFIG_CIFS_WEAK_PW_HASH - case Opt_sec_lanman: - vol->secFlg |= CIFSSEC_MAY_LANMAN; - break; -#endif - case Opt_sec_none: - vol->nullauth = 1; - break; - default: - cERROR(1, "bad security option: %s", value); - return 1; - } - - return 0; -} - static int cifs_parse_mount_options(const char *mountdata, const char *devname, struct smb_vol *vol) { - char *data, *end; + char *value, *data, *end; char *mountdata_copy = NULL, *options; unsigned int temp_len, i, j; char separator[2]; @@ -1197,16 +796,10 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, short int override_gid = -1; bool uid_specified = false; bool gid_specified = false; - bool sloppy = false; - char *invalid = NULL; char *nodename = utsname()->nodename; - char *string = NULL; - char *tmp_end, *value; - char delim; separator[0] = ','; separator[1] = 0; - delim = separator[0]; /* * does not have to be perfect mapping since field is @@ -1245,7 +838,6 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, options = mountdata_copy; end = options + strlen(options); - if (strncmp(options, "sep=", 4) == 0) { if (options[4] != 0) { separator[0] = options[4]; @@ -1254,617 +846,602 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, cFYI(1, "Null separator not allowed"); } } - vol->backupuid_specified = false; /* no backup intent for a user */ - vol->backupgid_specified = false; /* no backup intent for a group */ while ((data = strsep(&options, separator)) != NULL) { - substring_t args[MAX_OPT_ARGS]; - unsigned long option; - int token; - if (!*data) continue; + if ((value = strchr(data, '=')) != NULL) + *value++ = '\0'; - token = match_token(data, cifs_mount_option_tokens, args); - - switch (token) { - - /* Ingnore the following */ - case Opt_ignore: - break; - - /* Boolean values */ - case Opt_user_xattr: + /* Have to parse this before we parse for "user" */ + if (strnicmp(data, "user_xattr", 10) == 0) { vol->no_xattr = 0; - break; - case Opt_nouser_xattr: + } else if (strnicmp(data, "nouser_xattr", 12) == 0) { vol->no_xattr = 1; - break; - case Opt_forceuid: - override_uid = 1; - break; - case Opt_noforceuid: - override_uid = 0; - break; - case Opt_noblocksend: - vol->noblocksnd = 1; - break; - case Opt_noautotune: - vol->noautotune = 1; - break; - case Opt_hard: - vol->retry = 1; - break; - case Opt_soft: - vol->retry = 0; - break; - case Opt_perm: - vol->noperm = 0; - break; - case Opt_noperm: - vol->noperm = 1; - break; - case Opt_mapchars: - vol->remap = 1; - break; - case Opt_nomapchars: - vol->remap = 0; - break; - case Opt_sfu: - vol->sfu_emul = 1; - break; - case Opt_nosfu: - vol->sfu_emul = 0; - break; - case Opt_nodfs: - vol->nodfs = 1; - break; - case Opt_posixpaths: - vol->posix_paths = 1; - break; - case Opt_noposixpaths: - vol->posix_paths = 0; - break; - case Opt_nounix: - vol->no_linux_ext = 1; - break; - case Opt_nocase: - vol->nocase = 1; - break; - case Opt_brl: - vol->nobrl = 0; - break; - case Opt_nobrl: - vol->nobrl = 1; - /* - * turn off mandatory locking in mode - * if remote locking is turned off since the - * local vfs will do advisory - */ - if (vol->file_mode == - (S_IALLUGO & ~(S_ISUID | S_IXGRP))) - vol->file_mode = S_IALLUGO; - break; - case Opt_forcemandatorylock: - vol->mand_lock = 1; - break; - case Opt_setuids: - vol->setuids = 1; - break; - case Opt_nosetuids: - vol->setuids = 0; - break; - case Opt_dynperm: - vol->dynperm = true; - break; - case Opt_nodynperm: - vol->dynperm = false; - break; - case Opt_nohard: - vol->retry = 0; - break; - case Opt_nosoft: - vol->retry = 1; - break; - case Opt_nointr: - vol->intr = 0; - break; - case Opt_intr: - vol->intr = 1; - break; - case Opt_nostrictsync: - vol->nostrictsync = 1; - break; - case Opt_strictsync: - vol->nostrictsync = 0; - break; - case Opt_serverino: - vol->server_ino = 1; - break; - case Opt_noserverino: - vol->server_ino = 0; - break; - case Opt_rwpidforward: - vol->rwpidforward = 1; - break; - case Opt_cifsacl: - vol->cifs_acl = 1; - break; - case Opt_nocifsacl: - vol->cifs_acl = 0; - break; - case Opt_acl: - vol->no_psx_acl = 0; - break; - case Opt_noacl: - vol->no_psx_acl = 1; - break; - case Opt_locallease: - vol->local_lease = 1; - break; - case Opt_sign: - vol->secFlg |= CIFSSEC_MUST_SIGN; - break; - case Opt_seal: - /* we do not do the following in secFlags because seal - * is a per tree connection (mount) not a per socket - * or per-smb connection option in the protocol - * vol->secFlg |= CIFSSEC_MUST_SEAL; - */ - vol->seal = 1; - break; - case Opt_direct: - vol->direct_io = 1; - break; - case Opt_strictcache: - vol->strict_io = 1; - break; - case Opt_noac: - printk(KERN_WARNING "CIFS: Mount option noac not " - "supported. Instead set " - "/proc/fs/cifs/LookupCacheEnabled to 0\n"); - break; - case Opt_fsc: -#ifndef CONFIG_CIFS_FSCACHE - cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE " - "kernel config option set"); - goto cifs_parse_mount_err; -#endif - vol->fsc = true; - break; - case Opt_mfsymlinks: - vol->mfsymlinks = true; - break; - case Opt_multiuser: - vol->multiuser = true; - break; - case Opt_sloppy: - sloppy = true; - break; - - /* Numeric Values */ - case Opt_backupuid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid backupuid value", - __func__); - goto cifs_parse_mount_err; - } - vol->backupuid = option; - vol->backupuid_specified = true; - break; - case Opt_backupgid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid backupgid value", - __func__); + } else if (strnicmp(data, "user", 4) == 0) { + if (!value) { + printk(KERN_WARNING + "CIFS: invalid or missing username\n"); goto cifs_parse_mount_err; + } else if (!*value) { + /* null user, ie anonymous, authentication */ + vol->nullauth = 1; } - vol->backupgid = option; - vol->backupgid_specified = true; - break; - case Opt_uid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid uid value", - __func__); - goto cifs_parse_mount_err; - } - vol->linux_uid = option; - uid_specified = true; - break; - case Opt_cruid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid cruid value", - __func__); - goto cifs_parse_mount_err; - } - vol->cred_uid = option; - break; - case Opt_gid: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid gid value", - __func__); - goto cifs_parse_mount_err; - } - vol->linux_gid = option; - gid_specified = true; - break; - case Opt_file_mode: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid file_mode value", - __func__); - goto cifs_parse_mount_err; - } - vol->file_mode = option; - break; - case Opt_dirmode: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid dir_mode value", - __func__); - goto cifs_parse_mount_err; - } - vol->dir_mode = option; - break; - case Opt_port: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid port value", - __func__); - goto cifs_parse_mount_err; - } - vol->port = option; - break; - case Opt_rsize: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid rsize value", - __func__); - goto cifs_parse_mount_err; - } - vol->rsize = option; - break; - case Opt_wsize: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid wsize value", - __func__); - goto cifs_parse_mount_err; - } - vol->wsize = option; - break; - case Opt_actimeo: - if (get_option_ul(args, &option)) { - cERROR(1, "%s: Invalid actimeo value", - __func__); - goto cifs_parse_mount_err; - } - vol->actimeo = HZ * option; - if (vol->actimeo > CIFS_MAX_ACTIMEO) { - cERROR(1, "CIFS: attribute cache" - "timeout too large"); - goto cifs_parse_mount_err; - } - break; - - /* String Arguments */ - - case Opt_blank_user: - /* null user, ie. anonymous authentication */ - vol->nullauth = 1; - vol->username = NULL; - break; - case Opt_user: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, MAX_USERNAME_SIZE) > - MAX_USERNAME_SIZE) { + if (strnlen(value, MAX_USERNAME_SIZE) < + MAX_USERNAME_SIZE) { + vol->username = kstrdup(value, GFP_KERNEL); + if (!vol->username) { + printk(KERN_WARNING "CIFS: no memory " + "for username\n"); + goto cifs_parse_mount_err; + } + } else { printk(KERN_WARNING "CIFS: username too long\n"); goto cifs_parse_mount_err; } - vol->username = kstrdup(string, GFP_KERNEL); - if (!vol->username) { - printk(KERN_WARNING "CIFS: no memory " - "for username\n"); - goto cifs_parse_mount_err; - } - break; - case Opt_blank_pass: - vol->password = NULL; - break; - case Opt_pass: - /* passwords have to be handled differently - * to allow the character used for deliminator - * to be passed within them - */ - - /* Obtain the value string */ - value = strchr(data, '='); - value++; - - /* Set tmp_end to end of the string */ - tmp_end = (char *) value + strlen(value); - - /* Check if following character is the deliminator - * If yes, we have encountered a double deliminator - * reset the NULL character to the deliminator - */ - if (tmp_end < end && tmp_end[1] == delim) - tmp_end[0] = delim; - - /* Keep iterating until we get to a single deliminator - * OR the end - */ - while ((tmp_end = strchr(tmp_end, delim)) != NULL && - (tmp_end[1] == delim)) { - tmp_end = (char *) &tmp_end[2]; + } else if (strnicmp(data, "pass", 4) == 0) { + if (!value) { + vol->password = NULL; + continue; + } else if (value[0] == 0) { + /* check if string begins with double comma + since that would mean the password really + does start with a comma, and would not + indicate an empty string */ + if (value[1] != separator[0]) { + vol->password = NULL; + continue; + } } - - /* Reset var options to point to next element */ - if (tmp_end) { - tmp_end[0] = '\0'; - options = (char *) &tmp_end[1]; - } else - /* Reached the end of the mount option string */ - options = end; - - /* Now build new password string */ temp_len = strlen(value); - vol->password = kzalloc(temp_len+1, GFP_KERNEL); - if (vol->password == NULL) { - printk(KERN_WARNING "CIFS: no memory " - "for password\n"); - goto cifs_parse_mount_err; - } - - for (i = 0, j = 0; i < temp_len; i++, j++) { - vol->password[j] = value[i]; - if ((value[i] == delim) && - value[i+1] == delim) - /* skip the second deliminator */ - i++; + /* removed password length check, NTLM passwords + can be arbitrarily long */ + + /* if comma in password, the string will be + prematurely null terminated. Commas in password are + specified across the cifs mount interface by a double + comma ie ,, and a comma used as in other cases ie ',' + as a parameter delimiter/separator is single and due + to the strsep above is temporarily zeroed. */ + + /* NB: password legally can have multiple commas and + the only illegal character in a password is null */ + + if ((value[temp_len] == 0) && + (value + temp_len < end) && + (value[temp_len+1] == separator[0])) { + /* reinsert comma */ + value[temp_len] = separator[0]; + temp_len += 2; /* move after second comma */ + while (value[temp_len] != 0) { + if (value[temp_len] == separator[0]) { + if (value[temp_len+1] == + separator[0]) { + /* skip second comma */ + temp_len++; + } else { + /* single comma indicating start + of next parm */ + break; + } + } + temp_len++; + } + if (value[temp_len] == 0) { + options = NULL; + } else { + value[temp_len] = 0; + /* point option to start of next parm */ + options = value + temp_len + 1; + } + /* go from value to value + temp_len condensing + double commas to singles. Note that this ends up + allocating a few bytes too many, which is ok */ + vol->password = kzalloc(temp_len, GFP_KERNEL); + if (vol->password == NULL) { + printk(KERN_WARNING "CIFS: no memory " + "for password\n"); + goto cifs_parse_mount_err; + } + for (i = 0, j = 0; i < temp_len; i++, j++) { + vol->password[j] = value[i]; + if (value[i] == separator[0] + && value[i+1] == separator[0]) { + /* skip second comma */ + i++; + } + } + vol->password[j] = 0; + } else { + vol->password = kzalloc(temp_len+1, GFP_KERNEL); + if (vol->password == NULL) { + printk(KERN_WARNING "CIFS: no memory " + "for password\n"); + goto cifs_parse_mount_err; + } + strcpy(vol->password, value); } - vol->password[j] = '\0'; - break; - case Opt_blank_ip: - vol->UNCip = NULL; - break; - case Opt_ip: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, INET6_ADDRSTRLEN) > - INET6_ADDRSTRLEN) { + } else if (!strnicmp(data, "ip", 2) || + !strnicmp(data, "addr", 4)) { + if (!value || !*value) { + vol->UNCip = NULL; + } else if (strnlen(value, INET6_ADDRSTRLEN) < + INET6_ADDRSTRLEN) { + vol->UNCip = kstrdup(value, GFP_KERNEL); + if (!vol->UNCip) { + printk(KERN_WARNING "CIFS: no memory " + "for UNC IP\n"); + goto cifs_parse_mount_err; + } + } else { printk(KERN_WARNING "CIFS: ip address " "too long\n"); goto cifs_parse_mount_err; } - vol->UNCip = kstrdup(string, GFP_KERNEL); - if (!vol->UNCip) { - printk(KERN_WARNING "CIFS: no memory " - "for UNC IP\n"); + } else if (strnicmp(data, "sec", 3) == 0) { + if (!value || !*value) { + cERROR(1, "no security value specified"); + continue; + } else if (strnicmp(value, "krb5i", 5) == 0) { + vol->secFlg |= CIFSSEC_MAY_KRB5 | + CIFSSEC_MUST_SIGN; + } else if (strnicmp(value, "krb5p", 5) == 0) { + /* vol->secFlg |= CIFSSEC_MUST_SEAL | + CIFSSEC_MAY_KRB5; */ + cERROR(1, "Krb5 cifs privacy not supported"); + goto cifs_parse_mount_err; + } else if (strnicmp(value, "krb5", 4) == 0) { + vol->secFlg |= CIFSSEC_MAY_KRB5; + } else if (strnicmp(value, "ntlmsspi", 8) == 0) { + vol->secFlg |= CIFSSEC_MAY_NTLMSSP | + CIFSSEC_MUST_SIGN; + } else if (strnicmp(value, "ntlmssp", 7) == 0) { + vol->secFlg |= CIFSSEC_MAY_NTLMSSP; + } else if (strnicmp(value, "ntlmv2i", 7) == 0) { + vol->secFlg |= CIFSSEC_MAY_NTLMV2 | + CIFSSEC_MUST_SIGN; + } else if (strnicmp(value, "ntlmv2", 6) == 0) { + vol->secFlg |= CIFSSEC_MAY_NTLMV2; + } else if (strnicmp(value, "ntlmi", 5) == 0) { + vol->secFlg |= CIFSSEC_MAY_NTLM | + CIFSSEC_MUST_SIGN; + } else if (strnicmp(value, "ntlm", 4) == 0) { + /* ntlm is default so can be turned off too */ + vol->secFlg |= CIFSSEC_MAY_NTLM; + } else if (strnicmp(value, "nontlm", 6) == 0) { + /* BB is there a better way to do this? */ + vol->secFlg |= CIFSSEC_MAY_NTLMV2; +#ifdef CONFIG_CIFS_WEAK_PW_HASH + } else if (strnicmp(value, "lanman", 6) == 0) { + vol->secFlg |= CIFSSEC_MAY_LANMAN; +#endif + } else if (strnicmp(value, "none", 4) == 0) { + vol->nullauth = 1; + } else { + cERROR(1, "bad security option: %s", value); + goto cifs_parse_mount_err; + } + } else if (strnicmp(data, "vers", 3) == 0) { + if (!value || !*value) { + cERROR(1, "no protocol version specified" + " after vers= mount option"); + } else if ((strnicmp(value, "cifs", 4) == 0) || + (strnicmp(value, "1", 1) == 0)) { + /* this is the default */ + continue; + } + } else if ((strnicmp(data, "unc", 3) == 0) + || (strnicmp(data, "target", 6) == 0) + || (strnicmp(data, "path", 4) == 0)) { + if (!value || !*value) { + printk(KERN_WARNING "CIFS: invalid path to " + "network resource\n"); goto cifs_parse_mount_err; } - break; - case Opt_unc: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - temp_len = strnlen(string, 300); - if (temp_len == 300) { + if ((temp_len = strnlen(value, 300)) < 300) { + vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); + if (vol->UNC == NULL) + goto cifs_parse_mount_err; + strcpy(vol->UNC, value); + if (strncmp(vol->UNC, "//", 2) == 0) { + vol->UNC[0] = '\\'; + vol->UNC[1] = '\\'; + } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { + printk(KERN_WARNING + "CIFS: UNC Path does not begin " + "with // or \\\\ \n"); + goto cifs_parse_mount_err; + } + } else { printk(KERN_WARNING "CIFS: UNC name too long\n"); goto cifs_parse_mount_err; } - - vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); - if (vol->UNC == NULL) { - printk(KERN_WARNING "CIFS: no memory for UNC\n"); + } else if ((strnicmp(data, "domain", 3) == 0) + || (strnicmp(data, "workgroup", 5) == 0)) { + if (!value || !*value) { + printk(KERN_WARNING "CIFS: invalid domain name\n"); goto cifs_parse_mount_err; } - strcpy(vol->UNC, string); - - if (strncmp(string, "//", 2) == 0) { - vol->UNC[0] = '\\'; - vol->UNC[1] = '\\'; - } else if (strncmp(string, "\\\\", 2) != 0) { - printk(KERN_WARNING "CIFS: UNC Path does not " - "begin with // or \\\\\n"); + /* BB are there cases in which a comma can be valid in + a domain name and need special handling? */ + if (strnlen(value, 256) < 256) { + vol->domainname = kstrdup(value, GFP_KERNEL); + if (!vol->domainname) { + printk(KERN_WARNING "CIFS: no memory " + "for domainname\n"); + goto cifs_parse_mount_err; + } + cFYI(1, "Domain name set"); + } else { + printk(KERN_WARNING "CIFS: domain name too " + "long\n"); goto cifs_parse_mount_err; } + } else if (strnicmp(data, "srcaddr", 7) == 0) { + vol->srcaddr.ss_family = AF_UNSPEC; - break; - case Opt_domain: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, 256) == 256) { - printk(KERN_WARNING "CIFS: domain name too" - " long\n"); + if (!value || !*value) { + printk(KERN_WARNING "CIFS: srcaddr value" + " not specified.\n"); goto cifs_parse_mount_err; } - - vol->domainname = kstrdup(string, GFP_KERNEL); - if (!vol->domainname) { - printk(KERN_WARNING "CIFS: no memory " - "for domainname\n"); + i = cifs_convert_address((struct sockaddr *)&vol->srcaddr, + value, strlen(value)); + if (i == 0) { + printk(KERN_WARNING "CIFS: Could not parse" + " srcaddr: %s\n", + value); goto cifs_parse_mount_err; } - cFYI(1, "Domain name set"); - break; - case Opt_srcaddr: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (!cifs_convert_address( - (struct sockaddr *)&vol->srcaddr, - string, strlen(string))) { - printk(KERN_WARNING "CIFS: Could not parse" - " srcaddr: %s\n", string); + } else if (strnicmp(data, "prefixpath", 10) == 0) { + if (!value || !*value) { + printk(KERN_WARNING + "CIFS: invalid path prefix\n"); goto cifs_parse_mount_err; } - break; - case Opt_prefixpath: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - temp_len = strnlen(string, 1024); - if (string[0] != '/') - temp_len++; /* missing leading slash */ - if (temp_len > 1024) { + if ((temp_len = strnlen(value, 1024)) < 1024) { + if (value[0] != '/') + temp_len++; /* missing leading slash */ + vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); + if (vol->prepath == NULL) + goto cifs_parse_mount_err; + if (value[0] != '/') { + vol->prepath[0] = '/'; + strcpy(vol->prepath+1, value); + } else + strcpy(vol->prepath, value); + cFYI(1, "prefix path %s", vol->prepath); + } else { printk(KERN_WARNING "CIFS: prefix too long\n"); goto cifs_parse_mount_err; } - - vol->prepath = kmalloc(temp_len+1, GFP_KERNEL); - if (vol->prepath == NULL) { - printk(KERN_WARNING "CIFS: no memory " - "for path prefix\n"); + } else if (strnicmp(data, "iocharset", 9) == 0) { + if (!value || !*value) { + printk(KERN_WARNING "CIFS: invalid iocharset " + "specified\n"); goto cifs_parse_mount_err; } - - if (string[0] != '/') { - vol->prepath[0] = '/'; - strcpy(vol->prepath+1, string); - } else - strcpy(vol->prepath, string); - - break; - case Opt_iocharset: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnlen(string, 1024) >= 65) { + if (strnlen(value, 65) < 65) { + if (strnicmp(value, "default", 7)) { + vol->iocharset = kstrdup(value, + GFP_KERNEL); + + if (!vol->iocharset) { + printk(KERN_WARNING "CIFS: no " + "memory for" + "charset\n"); + goto cifs_parse_mount_err; + } + } + /* if iocharset not set then load_nls_default + is used by caller */ + cFYI(1, "iocharset set to %s", value); + } else { printk(KERN_WARNING "CIFS: iocharset name " "too long.\n"); goto cifs_parse_mount_err; } - - if (strnicmp(string, "default", 7) != 0) { - vol->iocharset = kstrdup(string, - GFP_KERNEL); - if (!vol->iocharset) { - printk(KERN_WARNING "CIFS: no memory" - "for charset\n"); - goto cifs_parse_mount_err; - } + } else if (!strnicmp(data, "uid", 3) && value && *value) { + vol->linux_uid = simple_strtoul(value, &value, 0); + uid_specified = true; + } else if (!strnicmp(data, "cruid", 5) && value && *value) { + vol->cred_uid = simple_strtoul(value, &value, 0); + } else if (!strnicmp(data, "forceuid", 8)) { + override_uid = 1; + } else if (!strnicmp(data, "noforceuid", 10)) { + override_uid = 0; + } else if (!strnicmp(data, "gid", 3) && value && *value) { + vol->linux_gid = simple_strtoul(value, &value, 0); + gid_specified = true; + } else if (!strnicmp(data, "forcegid", 8)) { + override_gid = 1; + } else if (!strnicmp(data, "noforcegid", 10)) { + override_gid = 0; + } else if (strnicmp(data, "file_mode", 4) == 0) { + if (value && *value) { + vol->file_mode = + simple_strtoul(value, &value, 0); } - /* if iocharset not set then load_nls_default - * is used by caller - */ - cFYI(1, "iocharset set to %s", string); - break; - case Opt_sockopt: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnicmp(string, "TCP_NODELAY", 11) == 0) + } else if (strnicmp(data, "dir_mode", 4) == 0) { + if (value && *value) { + vol->dir_mode = + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "dirmode", 4) == 0) { + if (value && *value) { + vol->dir_mode = + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "port", 4) == 0) { + if (value && *value) { + vol->port = + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "rsize", 5) == 0) { + if (value && *value) { + vol->rsize = + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "wsize", 5) == 0) { + if (value && *value) { + vol->wsize = + simple_strtoul(value, &value, 0); + } + } else if (strnicmp(data, "sockopt", 5) == 0) { + if (!value || !*value) { + cERROR(1, "no socket option specified"); + continue; + } else if (strnicmp(value, "TCP_NODELAY", 11) == 0) { vol->sockopt_tcp_nodelay = 1; - break; - case Opt_netbiosname: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - memset(vol->source_rfc1001_name, 0x20, - RFC1001_NAME_LEN); - /* - * FIXME: are there cases in which a comma can - * be valid in workstation netbios name (and - * need special handling)? - */ - for (i = 0; i < RFC1001_NAME_LEN; i++) { - /* don't ucase netbiosname for user */ - if (string[i] == 0) - break; - vol->source_rfc1001_name[i] = string[i]; } - /* The string has 16th byte zero still from - * set at top of the function - */ - if (i == RFC1001_NAME_LEN && string[i] != 0) - printk(KERN_WARNING "CIFS: netbiosname" - " longer than 15 truncated.\n"); - - break; - case Opt_servern: + } else if (strnicmp(data, "netbiosname", 4) == 0) { + if (!value || !*value || (*value == ' ')) { + cFYI(1, "invalid (empty) netbiosname"); + } else { + memset(vol->source_rfc1001_name, 0x20, + RFC1001_NAME_LEN); + /* + * FIXME: are there cases in which a comma can + * be valid in workstation netbios name (and + * need special handling)? + */ + for (i = 0; i < RFC1001_NAME_LEN; i++) { + /* don't ucase netbiosname for user */ + if (value[i] == 0) + break; + vol->source_rfc1001_name[i] = value[i]; + } + /* The string has 16th byte zero still from + set at top of the function */ + if (i == RFC1001_NAME_LEN && value[i] != 0) + printk(KERN_WARNING "CIFS: netbiosname" + " longer than 15 truncated.\n"); + } + } else if (strnicmp(data, "servern", 7) == 0) { /* servernetbiosname specified override *SMBSERVER */ - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - /* last byte, type, is 0x20 for servr type */ - memset(vol->target_rfc1001_name, 0x20, - RFC1001_NAME_LEN_WITH_NULL); - - /* BB are there cases in which a comma can be - valid in this workstation netbios name - (and need special handling)? */ - - /* user or mount helper must uppercase the - netbios name */ - for (i = 0; i < 15; i++) { - if (string[i] == 0) - break; - vol->target_rfc1001_name[i] = string[i]; + if (!value || !*value || (*value == ' ')) { + cFYI(1, "empty server netbiosname specified"); + } else { + /* last byte, type, is 0x20 for servr type */ + memset(vol->target_rfc1001_name, 0x20, + RFC1001_NAME_LEN_WITH_NULL); + + for (i = 0; i < 15; i++) { + /* BB are there cases in which a comma can be + valid in this workstation netbios name + (and need special handling)? */ + + /* user or mount helper must uppercase + the netbiosname */ + if (value[i] == 0) + break; + else + vol->target_rfc1001_name[i] = + value[i]; + } + /* The string has 16th byte zero still from + set at top of the function */ + if (i == RFC1001_NAME_LEN && value[i] != 0) + printk(KERN_WARNING "CIFS: server net" + "biosname longer than 15 truncated.\n"); } - /* The string has 16th byte zero still from - set at top of the function */ - if (i == RFC1001_NAME_LEN && string[i] != 0) - printk(KERN_WARNING "CIFS: server net" - "biosname longer than 15 truncated.\n"); - break; - case Opt_ver: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (strnicmp(string, "cifs", 4) == 0 || - strnicmp(string, "1", 1) == 0) { - /* This is the default */ - break; + } else if (strnicmp(data, "actimeo", 7) == 0) { + if (value && *value) { + vol->actimeo = HZ * simple_strtoul(value, + &value, 0); + if (vol->actimeo > CIFS_MAX_ACTIMEO) { + cERROR(1, "CIFS: attribute cache" + "timeout too large"); + goto cifs_parse_mount_err; + } } - /* For all other value, error */ - printk(KERN_WARNING "CIFS: Invalid version" - " specified\n"); + } else if (strnicmp(data, "credentials", 4) == 0) { + /* ignore */ + } else if (strnicmp(data, "version", 3) == 0) { + /* ignore */ + } else if (strnicmp(data, "guest", 5) == 0) { + /* ignore */ + } else if (strnicmp(data, "rw", 2) == 0 && strlen(data) == 2) { + /* ignore */ + } else if (strnicmp(data, "ro", 2) == 0) { + /* ignore */ + } else if (strnicmp(data, "noblocksend", 11) == 0) { + vol->noblocksnd = 1; + } else if (strnicmp(data, "noautotune", 10) == 0) { + vol->noautotune = 1; + } else if ((strnicmp(data, "suid", 4) == 0) || + (strnicmp(data, "nosuid", 6) == 0) || + (strnicmp(data, "exec", 4) == 0) || + (strnicmp(data, "noexec", 6) == 0) || + (strnicmp(data, "nodev", 5) == 0) || + (strnicmp(data, "noauto", 6) == 0) || + (strnicmp(data, "dev", 3) == 0)) { + /* The mount tool or mount.cifs helper (if present) + uses these opts to set flags, and the flags are read + by the kernel vfs layer before we get here (ie + before read super) so there is no point trying to + parse these options again and set anything and it + is ok to just ignore them */ + continue; + } else if (strnicmp(data, "hard", 4) == 0) { + vol->retry = 1; + } else if (strnicmp(data, "soft", 4) == 0) { + vol->retry = 0; + } else if (strnicmp(data, "perm", 4) == 0) { + vol->noperm = 0; + } else if (strnicmp(data, "noperm", 6) == 0) { + vol->noperm = 1; + } else if (strnicmp(data, "mapchars", 8) == 0) { + vol->remap = 1; + } else if (strnicmp(data, "nomapchars", 10) == 0) { + vol->remap = 0; + } else if (strnicmp(data, "sfu", 3) == 0) { + vol->sfu_emul = 1; + } else if (strnicmp(data, "nosfu", 5) == 0) { + vol->sfu_emul = 0; + } else if (strnicmp(data, "nodfs", 5) == 0) { + vol->nodfs = 1; + } else if (strnicmp(data, "posixpaths", 10) == 0) { + vol->posix_paths = 1; + } else if (strnicmp(data, "noposixpaths", 12) == 0) { + vol->posix_paths = 0; + } else if (strnicmp(data, "nounix", 6) == 0) { + vol->no_linux_ext = 1; + } else if (strnicmp(data, "nolinux", 7) == 0) { + vol->no_linux_ext = 1; + } else if ((strnicmp(data, "nocase", 6) == 0) || + (strnicmp(data, "ignorecase", 10) == 0)) { + vol->nocase = 1; + } else if (strnicmp(data, "mand", 4) == 0) { + /* ignore */ + } else if (strnicmp(data, "nomand", 6) == 0) { + /* ignore */ + } else if (strnicmp(data, "_netdev", 7) == 0) { + /* ignore */ + } else if (strnicmp(data, "brl", 3) == 0) { + vol->nobrl = 0; + } else if ((strnicmp(data, "nobrl", 5) == 0) || + (strnicmp(data, "nolock", 6) == 0)) { + vol->nobrl = 1; + /* turn off mandatory locking in mode + if remote locking is turned off since the + local vfs will do advisory */ + if (vol->file_mode == + (S_IALLUGO & ~(S_ISUID | S_IXGRP))) + vol->file_mode = S_IALLUGO; + } else if (strnicmp(data, "forcemandatorylock", 9) == 0) { + /* will take the shorter form "forcemand" as well */ + /* This mount option will force use of mandatory + (DOS/Windows style) byte range locks, instead of + using posix advisory byte range locks, even if the + Unix extensions are available and posix locks would + be supported otherwise. If Unix extensions are not + negotiated this has no effect since mandatory locks + would be used (mandatory locks is all that those + those servers support) */ + vol->mand_lock = 1; + } else if (strnicmp(data, "setuids", 7) == 0) { + vol->setuids = 1; + } else if (strnicmp(data, "nosetuids", 9) == 0) { + vol->setuids = 0; + } else if (strnicmp(data, "dynperm", 7) == 0) { + vol->dynperm = true; + } else if (strnicmp(data, "nodynperm", 9) == 0) { + vol->dynperm = false; + } else if (strnicmp(data, "nohard", 6) == 0) { + vol->retry = 0; + } else if (strnicmp(data, "nosoft", 6) == 0) { + vol->retry = 1; + } else if (strnicmp(data, "nointr", 6) == 0) { + vol->intr = 0; + } else if (strnicmp(data, "intr", 4) == 0) { + vol->intr = 1; + } else if (strnicmp(data, "nostrictsync", 12) == 0) { + vol->nostrictsync = 1; + } else if (strnicmp(data, "strictsync", 10) == 0) { + vol->nostrictsync = 0; + } else if (strnicmp(data, "serverino", 7) == 0) { + vol->server_ino = 1; + } else if (strnicmp(data, "noserverino", 9) == 0) { + vol->server_ino = 0; + } else if (strnicmp(data, "rwpidforward", 12) == 0) { + vol->rwpidforward = 1; + } else if (strnicmp(data, "cifsacl", 7) == 0) { + vol->cifs_acl = 1; + } else if (strnicmp(data, "nocifsacl", 9) == 0) { + vol->cifs_acl = 0; + } else if (strnicmp(data, "acl", 3) == 0) { + vol->no_psx_acl = 0; + } else if (strnicmp(data, "noacl", 5) == 0) { + vol->no_psx_acl = 1; + } else if (strnicmp(data, "locallease", 6) == 0) { + vol->local_lease = 1; + } else if (strnicmp(data, "sign", 4) == 0) { + vol->secFlg |= CIFSSEC_MUST_SIGN; + } else if (strnicmp(data, "seal", 4) == 0) { + /* we do not do the following in secFlags because seal + is a per tree connection (mount) not a per socket + or per-smb connection option in the protocol */ + /* vol->secFlg |= CIFSSEC_MUST_SEAL; */ + vol->seal = 1; + } else if (strnicmp(data, "direct", 6) == 0) { + vol->direct_io = 1; + } else if (strnicmp(data, "forcedirectio", 13) == 0) { + vol->direct_io = 1; + } else if (strnicmp(data, "strictcache", 11) == 0) { + vol->strict_io = 1; + } else if (strnicmp(data, "noac", 4) == 0) { + printk(KERN_WARNING "CIFS: Mount option noac not " + "supported. Instead set " + "/proc/fs/cifs/LookupCacheEnabled to 0\n"); + } else if (strnicmp(data, "fsc", 3) == 0) { +#ifndef CONFIG_CIFS_FSCACHE + cERROR(1, "FS-Cache support needs CONFIG_CIFS_FSCACHE " + "kernel config option set"); goto cifs_parse_mount_err; - case Opt_sec: - string = match_strdup(args); - if (string == NULL) - goto out_nomem; - - if (cifs_parse_security_flavors(string, vol) != 0) +#endif + vol->fsc = true; + } else if (strnicmp(data, "mfsymlinks", 10) == 0) { + vol->mfsymlinks = true; + } else if (strnicmp(data, "multiuser", 8) == 0) { + vol->multiuser = true; + } else + printk(KERN_WARNING "CIFS: Unknown mount option %s\n", + data); + } + if (vol->UNC == NULL) { + if (devname == NULL) { + printk(KERN_WARNING "CIFS: Missing UNC name for mount " + "target\n"); + goto cifs_parse_mount_err; + } + if ((temp_len = strnlen(devname, 300)) < 300) { + vol->UNC = kmalloc(temp_len+1, GFP_KERNEL); + if (vol->UNC == NULL) goto cifs_parse_mount_err; - break; - default: - /* - * An option we don't recognize. Save it off for later - * if we haven't already found one - */ - if (!invalid) - invalid = data; - break; + strcpy(vol->UNC, devname); + if (strncmp(vol->UNC, "//", 2) == 0) { + vol->UNC[0] = '\\'; + vol->UNC[1] = '\\'; + } else if (strncmp(vol->UNC, "\\\\", 2) != 0) { + printk(KERN_WARNING "CIFS: UNC Path does not " + "begin with // or \\\\ \n"); + goto cifs_parse_mount_err; + } + value = strpbrk(vol->UNC+2, "/\\"); + if (value) + *value = '\\'; + } else { + printk(KERN_WARNING "CIFS: UNC name too long\n"); + goto cifs_parse_mount_err; } - /* Free up any allocated string */ - kfree(string); - string = NULL; - } - - if (!sloppy && invalid) { - printk(KERN_ERR "CIFS: Unknown mount option \"%s\"\n", invalid); - goto cifs_parse_mount_err; } -#ifndef CONFIG_KEYS - /* Muliuser mounts require CONFIG_KEYS support */ - if (vol->multiuser) { - cERROR(1, "Multiuser mounts require kernels with " - "CONFIG_KEYS enabled."); + if (vol->multiuser && !(vol->secFlg & CIFSSEC_MAY_KRB5)) { + cERROR(1, "Multiuser mounts currently require krb5 " + "authentication!"); goto cifs_parse_mount_err; } -#endif if (vol->UNCip == NULL) vol->UNCip = &vol->UNC[2]; @@ -1884,10 +1461,7 @@ cifs_parse_mount_options(const char *mountdata, const char *devname, kfree(mountdata_copy); return 0; -out_nomem: - printk(KERN_WARNING "Could not allocate temporary buffer\n"); cifs_parse_mount_err: - kfree(string); kfree(mountdata_copy); return 1; } @@ -2173,8 +1747,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) tcp_ses->noblocksnd = volume_info->noblocksnd; tcp_ses->noautotune = volume_info->noautotune; tcp_ses->tcp_nodelay = volume_info->sockopt_tcp_nodelay; - tcp_ses->in_flight = 0; - tcp_ses->credits = 1; + atomic_set(&tcp_ses->inFlight, 0); init_waitqueue_head(&tcp_ses->response_q); init_waitqueue_head(&tcp_ses->request_q); INIT_LIST_HEAD(&tcp_ses->pending_mid_q); @@ -2186,7 +1759,6 @@ cifs_get_tcp_session(struct smb_vol *volume_info) tcp_ses->session_estab = false; tcp_ses->sequence_number = 0; tcp_ses->lstrp = jiffies; - spin_lock_init(&tcp_ses->req_lock); INIT_LIST_HEAD(&tcp_ses->tcp_ses_list); INIT_LIST_HEAD(&tcp_ses->smb_ses_list); INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request); @@ -2222,7 +1794,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) * this will succeed. No need for try_module_get(). */ __module_get(THIS_MODULE); - tcp_ses->tsk = kthread_run(cifs_demultiplex_thread, + tcp_ses->tsk = kthread_run((void *)(void *)cifs_demultiplex_thread, tcp_ses, "cifsd"); if (IS_ERR(tcp_ses->tsk)) { rc = PTR_ERR(tcp_ses->tsk); @@ -2240,7 +1812,7 @@ cifs_get_tcp_session(struct smb_vol *volume_info) cifs_fscache_get_client_cookie(tcp_ses); /* queue echo request delayed work */ - queue_delayed_work(cifsiod_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL); + queue_delayed_work(system_nrt_wq, &tcp_ses->echo, SMB_ECHO_INTERVAL); return tcp_ses; @@ -2268,16 +1840,10 @@ static int match_session(struct cifs_ses *ses, struct smb_vol *vol) return 0; break; default: - /* NULL username means anonymous session */ - if (ses->user_name == NULL) { - if (!vol->nullauth) - return 0; - break; - } - /* anything else takes username/password */ - if (strncmp(ses->user_name, - vol->username ? vol->username : "", + if (ses->user_name == NULL) + return 0; + if (strncmp(ses->user_name, vol->username, MAX_USERNAME_SIZE)) return 0; if (strlen(vol->username) != 0 && @@ -2332,132 +1898,6 @@ cifs_put_smb_ses(struct cifs_ses *ses) cifs_put_tcp_session(server); } -#ifdef CONFIG_KEYS - -/* strlen("cifs:a:") + INET6_ADDRSTRLEN + 1 */ -#define CIFSCREDS_DESC_SIZE (7 + INET6_ADDRSTRLEN + 1) - -/* Populate username and pw fields from keyring if possible */ -static int -cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) -{ - int rc = 0; - char *desc, *delim, *payload; - ssize_t len; - struct key *key; - struct TCP_Server_Info *server = ses->server; - struct sockaddr_in *sa; - struct sockaddr_in6 *sa6; - struct user_key_payload *upayload; - - desc = kmalloc(CIFSCREDS_DESC_SIZE, GFP_KERNEL); - if (!desc) - return -ENOMEM; - - /* try to find an address key first */ - switch (server->dstaddr.ss_family) { - case AF_INET: - sa = (struct sockaddr_in *)&server->dstaddr; - sprintf(desc, "cifs:a:%pI4", &sa->sin_addr.s_addr); - break; - case AF_INET6: - sa6 = (struct sockaddr_in6 *)&server->dstaddr; - sprintf(desc, "cifs:a:%pI6c", &sa6->sin6_addr.s6_addr); - break; - default: - cFYI(1, "Bad ss_family (%hu)", server->dstaddr.ss_family); - rc = -EINVAL; - goto out_err; - } - - cFYI(1, "%s: desc=%s", __func__, desc); - key = request_key(&key_type_logon, desc, ""); - if (IS_ERR(key)) { - if (!ses->domainName) { - cFYI(1, "domainName is NULL"); - rc = PTR_ERR(key); - goto out_err; - } - - /* didn't work, try to find a domain key */ - sprintf(desc, "cifs:d:%s", ses->domainName); - cFYI(1, "%s: desc=%s", __func__, desc); - key = request_key(&key_type_logon, desc, ""); - if (IS_ERR(key)) { - rc = PTR_ERR(key); - goto out_err; - } - } - - down_read(&key->sem); - upayload = key->payload.data; - if (IS_ERR_OR_NULL(upayload)) { - rc = upayload ? PTR_ERR(upayload) : -EINVAL; - goto out_key_put; - } - - /* find first : in payload */ - payload = (char *)upayload->data; - delim = strnchr(payload, upayload->datalen, ':'); - cFYI(1, "payload=%s", payload); - if (!delim) { - cFYI(1, "Unable to find ':' in payload (datalen=%d)", - upayload->datalen); - rc = -EINVAL; - goto out_key_put; - } - - len = delim - payload; - if (len > MAX_USERNAME_SIZE || len <= 0) { - cFYI(1, "Bad value from username search (len=%zd)", len); - rc = -EINVAL; - goto out_key_put; - } - - vol->username = kstrndup(payload, len, GFP_KERNEL); - if (!vol->username) { - cFYI(1, "Unable to allocate %zd bytes for username", len); - rc = -ENOMEM; - goto out_key_put; - } - cFYI(1, "%s: username=%s", __func__, vol->username); - - len = key->datalen - (len + 1); - if (len > MAX_PASSWORD_SIZE || len <= 0) { - cFYI(1, "Bad len for password search (len=%zd)", len); - rc = -EINVAL; - kfree(vol->username); - vol->username = NULL; - goto out_key_put; - } - - ++delim; - vol->password = kstrndup(delim, len, GFP_KERNEL); - if (!vol->password) { - cFYI(1, "Unable to allocate %zd bytes for password", len); - rc = -ENOMEM; - kfree(vol->username); - vol->username = NULL; - goto out_key_put; - } - -out_key_put: - up_read(&key->sem); - key_put(key); -out_err: - kfree(desc); - cFYI(1, "%s: returning %d", __func__, rc); - return rc; -} -#else /* ! CONFIG_KEYS */ -static inline int -cifs_set_cifscreds(struct smb_vol *vol __attribute__((unused)), - struct cifs_ses *ses __attribute__((unused))) -{ - return -ENOSYS; -} -#endif /* CONFIG_KEYS */ - static bool warned_on_ntlm; /* globals init to false automatically */ static struct cifs_ses * @@ -2541,7 +1981,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info) warned_on_ntlm = true; cERROR(1, "default security mechanism requested. The default " "security mechanism will be upgraded from ntlm to " - "ntlmv2 in kernel release 3.3"); + "ntlmv2 in kernel release 3.1"); } ses->overrideSecFlg = volume_info->secFlg; @@ -2732,16 +2172,16 @@ compare_mount_options(struct super_block *sb, struct cifs_mnt_data *mnt_data) (new->mnt_cifs_flags & CIFS_MOUNT_MASK)) return 0; + if (old->rsize != new->rsize) + return 0; + /* - * We want to share sb only if we don't specify an r/wsize or - * specified r/wsize is greater than or equal to existing one. + * We want to share sb only if we don't specify wsize or specified wsize + * is greater or equal than existing one. */ if (new->wsize && new->wsize < old->wsize) return 0; - if (new->rsize && new->rsize < old->rsize) - return 0; - if (old->mnt_uid != new->mnt_uid || old->mnt_gid != new->mnt_gid) return 0; @@ -3179,6 +2619,14 @@ void reset_cifs_unix_caps(int xid, struct cifs_tcon *tcon, CIFS_MOUNT_POSIX_PATHS; } + if (cifs_sb && (cifs_sb->rsize > 127 * 1024)) { + if ((cap & CIFS_UNIX_LARGE_READ_CAP) == 0) { + cifs_sb->rsize = 127 * 1024; + cFYI(DBG2, "larger reads not supported by srv"); + } + } + + cFYI(1, "Negotiate caps 0x%x", (int)cap); #ifdef CONFIG_CIFS_DEBUG2 if (cap & CIFS_UNIX_FCNTL_CAP) @@ -3223,18 +2671,34 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, spin_lock_init(&cifs_sb->tlink_tree_lock); cifs_sb->tlink_tree = RB_ROOT; + if (pvolume_info->rsize > CIFSMaxBufSize) { + cERROR(1, "rsize %d too large, using MaxBufSize", + pvolume_info->rsize); + cifs_sb->rsize = CIFSMaxBufSize; + } else if ((pvolume_info->rsize) && + (pvolume_info->rsize <= CIFSMaxBufSize)) + cifs_sb->rsize = pvolume_info->rsize; + else /* default */ + cifs_sb->rsize = CIFSMaxBufSize; + + if (cifs_sb->rsize < 2048) { + cifs_sb->rsize = 2048; + /* Windows ME may prefer this */ + cFYI(1, "readsize set to minimum: 2048"); + } + /* - * Temporarily set r/wsize for matching superblock. If we end up using - * new sb then client will later negotiate it downward if needed. + * Temporarily set wsize for matching superblock. If we end up using + * new sb then cifs_negotiate_wsize will later negotiate it downward + * if needed. */ - cifs_sb->rsize = pvolume_info->rsize; cifs_sb->wsize = pvolume_info->wsize; cifs_sb->mnt_uid = pvolume_info->linux_uid; cifs_sb->mnt_gid = pvolume_info->linux_gid; cifs_sb->mnt_file_mode = pvolume_info->file_mode; cifs_sb->mnt_dir_mode = pvolume_info->dir_mode; - cFYI(1, "file mode: 0x%hx dir mode: 0x%hx", + cFYI(1, "file mode: 0x%x dir mode: 0x%x", cifs_sb->mnt_file_mode, cifs_sb->mnt_dir_mode); cifs_sb->actimeo = pvolume_info->actimeo; @@ -3262,14 +2726,6 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_RWPIDFORWARD; if (pvolume_info->cifs_acl) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_ACL; - if (pvolume_info->backupuid_specified) { - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPUID; - cifs_sb->mnt_backupuid = pvolume_info->backupuid; - } - if (pvolume_info->backupgid_specified) { - cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_CIFS_BACKUPGID; - cifs_sb->mnt_backupgid = pvolume_info->backupgid; - } if (pvolume_info->override_uid) cifs_sb->mnt_cifs_flags |= CIFS_MOUNT_OVERR_UID; if (pvolume_info->override_gid) @@ -3302,64 +2758,37 @@ void cifs_setup_cifs_sb(struct smb_vol *pvolume_info, } /* - * When the server supports very large reads and writes via POSIX extensions, - * we can allow up to 2^24-1, minus the size of a READ/WRITE_AND_X header, not - * including the RFC1001 length. + * When the server supports very large writes via POSIX extensions, we can + * allow up to 2^24-1, minus the size of a WRITE_AND_X header, not including + * the RFC1001 length. * * Note that this might make for "interesting" allocation problems during * writeback however as we have to allocate an array of pointers for the * pages. A 16M write means ~32kb page array with PAGE_CACHE_SIZE == 4096. - * - * For reads, there is a similar problem as we need to allocate an array - * of kvecs to handle the receive, though that should only need to be done - * once. */ #define CIFS_MAX_WSIZE ((1<<24) - 1 - sizeof(WRITE_REQ) + 4) -#define CIFS_MAX_RSIZE ((1<<24) - sizeof(READ_RSP) + 4) /* - * When the server doesn't allow large posix writes, only allow a rsize/wsize - * of 2^17-1 minus the size of the call header. That allows for a read or - * write up to the maximum size described by RFC1002. + * When the server doesn't allow large posix writes, only allow a wsize of + * 2^17-1 minus the size of the WRITE_AND_X header. That allows for a write up + * to the maximum size described by RFC1002. */ #define CIFS_MAX_RFC1002_WSIZE ((1<<17) - 1 - sizeof(WRITE_REQ) + 4) -#define CIFS_MAX_RFC1002_RSIZE ((1<<17) - 1 - sizeof(READ_RSP) + 4) /* * The default wsize is 1M. find_get_pages seems to return a maximum of 256 * pages in a single call. With PAGE_CACHE_SIZE == 4k, this means we can fill * a single wsize request with a single call. */ -#define CIFS_DEFAULT_IOSIZE (1024 * 1024) - -/* - * Windows only supports a max of 60kb reads and 65535 byte writes. Default to - * those values when posix extensions aren't in force. In actuality here, we - * use 65536 to allow for a write that is a multiple of 4k. Most servers seem - * to be ok with the extra byte even though Windows doesn't send writes that - * are that large. - * - * Citation: - * - * http://blogs.msdn.com/b/openspecification/archive/2009/04/10/smb-maximum-transmit-buffer-size-and-performance-tuning.aspx - */ -#define CIFS_DEFAULT_NON_POSIX_RSIZE (60 * 1024) -#define CIFS_DEFAULT_NON_POSIX_WSIZE (65536) +#define CIFS_DEFAULT_WSIZE (1024 * 1024) static unsigned int cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) { __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); struct TCP_Server_Info *server = tcon->ses->server; - unsigned int wsize; - - /* start with specified wsize, or default */ - if (pvolume_info->wsize) - wsize = pvolume_info->wsize; - else if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) - wsize = CIFS_DEFAULT_IOSIZE; - else - wsize = CIFS_DEFAULT_NON_POSIX_WSIZE; + unsigned int wsize = pvolume_info->wsize ? pvolume_info->wsize : + CIFS_DEFAULT_WSIZE; /* can server support 24-bit write sizes? (via UNIX extensions) */ if (!tcon->unix_ext || !(unix_cap & CIFS_UNIX_LARGE_WRITE_CAP)) @@ -3382,50 +2811,6 @@ cifs_negotiate_wsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) return wsize; } -static unsigned int -cifs_negotiate_rsize(struct cifs_tcon *tcon, struct smb_vol *pvolume_info) -{ - __u64 unix_cap = le64_to_cpu(tcon->fsUnixInfo.Capability); - struct TCP_Server_Info *server = tcon->ses->server; - unsigned int rsize, defsize; - - /* - * Set default value... - * - * HACK alert! Ancient servers have very small buffers. Even though - * MS-CIFS indicates that servers are only limited by the client's - * bufsize for reads, testing against win98se shows that it throws - * INVALID_PARAMETER errors if you try to request too large a read. - * - * If the server advertises a MaxBufferSize of less than one page, - * assume that it also can't satisfy reads larger than that either. - * - * FIXME: Is there a better heuristic for this? - */ - if (tcon->unix_ext && (unix_cap & CIFS_UNIX_LARGE_READ_CAP)) - defsize = CIFS_DEFAULT_IOSIZE; - else if (server->capabilities & CAP_LARGE_READ_X) - defsize = CIFS_DEFAULT_NON_POSIX_RSIZE; - else if (server->maxBuf >= PAGE_CACHE_SIZE) - defsize = CIFSMaxBufSize; - else - defsize = server->maxBuf - sizeof(READ_RSP); - - rsize = pvolume_info->rsize ? pvolume_info->rsize : defsize; - - /* - * no CAP_LARGE_READ_X? Then MS-CIFS states that we must limit this to - * the client's MaxBufferSize. - */ - if (!(server->capabilities & CAP_LARGE_READ_X)) - rsize = min_t(unsigned int, CIFSMaxBufSize, rsize); - - /* hard limit of CIFS_MAX_RSIZE */ - rsize = min_t(unsigned int, rsize, CIFS_MAX_RSIZE); - - return rsize; -} - static int is_path_accessible(int xid, struct cifs_tcon *tcon, struct cifs_sb_info *cifs_sb, const char *full_path) @@ -3455,9 +2840,9 @@ cleanup_volume_info_contents(struct smb_vol *volume_info) { kfree(volume_info->username); kzfree(volume_info->password); + kfree(volume_info->UNC); if (volume_info->UNCip != volume_info->UNC + 2) kfree(volume_info->UNCip); - kfree(volume_info->UNC); kfree(volume_info->domainname); kfree(volume_info->iocharset); kfree(volume_info->prepath); @@ -3570,9 +2955,10 @@ cifs_setup_volume_info(struct smb_vol *volume_info, char *mount_data, return -EINVAL; if (volume_info->nullauth) { - cFYI(1, "Anonymous login"); - kfree(volume_info->username); - volume_info->username = NULL; + cFYI(1, "null user"); + volume_info->username = kzalloc(1, GFP_KERNEL); + if (volume_info->username == NULL) + return -ENOMEM; } else if (volume_info->username) { /* BB fixme parse for domain name here */ cFYI(1, "Username: %s", volume_info->username); @@ -3636,6 +3022,8 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) if (rc) return rc; + cifs_sb->bdi.ra_pages = default_backing_dev_info.ra_pages; + #ifdef CONFIG_CIFS_DFS_UPCALL try_mount_again: /* cleanup activities if we're chasing a referral */ @@ -3701,11 +3089,15 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) CIFSSMBQFSAttributeInfo(xid, tcon); } - cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info); - cifs_sb->rsize = cifs_negotiate_rsize(tcon, volume_info); + if ((tcon->unix_ext == 0) && (cifs_sb->rsize > (1024 * 127))) { + cifs_sb->rsize = 1024 * 127; + cFYI(DBG2, "no very large read support, rsize now 127K"); + } + if (!(tcon->ses->capabilities & CAP_LARGE_READ_X)) + cifs_sb->rsize = min(cifs_sb->rsize, + (tcon->ses->server->maxBuf - MAX_CIFS_HDR_SIZE)); - /* tune readahead according to rsize */ - cifs_sb->bdi.ra_pages = cifs_sb->rsize / PAGE_CACHE_SIZE; + cifs_sb->wsize = cifs_negotiate_wsize(tcon, volume_info); remote_path_check: #ifdef CONFIG_CIFS_DFS_UPCALL @@ -3790,7 +3182,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) tlink_rb_insert(&cifs_sb->tlink_tree, tlink); spin_unlock(&cifs_sb->tlink_tree_lock); - queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, + queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks, TLINK_IDLE_EXPIRE); mount_fail_check: @@ -3805,9 +3197,15 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info) else cifs_put_tcp_session(srvTcp); bdi_destroy(&cifs_sb->bdi); + goto out; } + /* volume_info->password is freed above when existing session found + (in which case it is not needed anymore) but when new sesion is created + the password ptr is put in the new session structure (in which case the + password will be freed at unmount time) */ out: + /* zero out password before freeing */ FreeXid(xid); return rc; } @@ -3873,7 +3271,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, else #endif /* CIFS_WEAK_PW_HASH */ rc = SMBNTencrypt(tcon->password, ses->server->cryptkey, - bcc_ptr, nls_codepage); + bcc_ptr); bcc_ptr += CIFS_AUTH_RESP_SIZE; if (ses->capabilities & CAP_UNICODE) { @@ -3896,7 +3294,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, if (ses->capabilities & CAP_UNICODE) { smb_buffer->Flags2 |= SMBFLG2_UNICODE; length = - cifs_strtoUTF16((__le16 *) bcc_ptr, tree, + cifs_strtoUCS((__le16 *) bcc_ptr, tree, 6 /* max utf8 char length in bytes */ * (/* server len*/ + 256 /* share len */), nls_codepage); bcc_ptr += 2 * length; /* convert num 16 bit words to bytes */ @@ -3951,7 +3349,7 @@ CIFSTCon(unsigned int xid, struct cifs_ses *ses, /* mostly informational -- no need to fail on error here */ kfree(tcon->nativeFileSystem); - tcon->nativeFileSystem = cifs_strndup_from_utf16(bcc_ptr, + tcon->nativeFileSystem = cifs_strndup_from_ucs(bcc_ptr, bytes_left, is_unicode, nls_codepage); @@ -4010,11 +3408,9 @@ int cifs_negotiate_protocol(unsigned int xid, struct cifs_ses *ses) if (server->maxBuf != 0) return 0; - cifs_set_credits(server, 1); rc = CIFSSMBNegotiate(xid, ses); if (rc == -EAGAIN) { /* retry only once on 1st time connection */ - cifs_set_credits(server, 1); rc = CIFSSMBNegotiate(xid, ses); if (rc == -EAGAIN) rc = -EHOSTDOWN; @@ -4077,43 +3473,25 @@ int cifs_setup_session(unsigned int xid, struct cifs_ses *ses, return rc; } -static int -cifs_set_vol_auth(struct smb_vol *vol, struct cifs_ses *ses) -{ - switch (ses->server->secType) { - case Kerberos: - vol->secFlg = CIFSSEC_MUST_KRB5; - return 0; - case NTLMv2: - vol->secFlg = CIFSSEC_MUST_NTLMV2; - break; - case NTLM: - vol->secFlg = CIFSSEC_MUST_NTLM; - break; - case RawNTLMSSP: - vol->secFlg = CIFSSEC_MUST_NTLMSSP; - break; - case LANMAN: - vol->secFlg = CIFSSEC_MUST_LANMAN; - break; - } - - return cifs_set_cifscreds(vol, ses); -} - static struct cifs_tcon * cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) { - int rc; struct cifs_tcon *master_tcon = cifs_sb_master_tcon(cifs_sb); struct cifs_ses *ses; struct cifs_tcon *tcon = NULL; struct smb_vol *vol_info; + char username[28]; /* big enough for "krb50x" + hex of ULONG_MAX 6+16 */ + /* We used to have this as MAX_USERNAME which is */ + /* way too big now (256 instead of 32) */ vol_info = kzalloc(sizeof(*vol_info), GFP_KERNEL); - if (vol_info == NULL) - return ERR_PTR(-ENOMEM); + if (vol_info == NULL) { + tcon = ERR_PTR(-ENOMEM); + goto out; + } + snprintf(username, sizeof(username), "krb50x%x", fsuid); + vol_info->username = username; vol_info->local_nls = cifs_sb->local_nls; vol_info->linux_uid = fsuid; vol_info->cred_uid = fsuid; @@ -4123,11 +3501,8 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) vol_info->local_lease = master_tcon->local_lease; vol_info->no_linux_ext = !master_tcon->unix_ext; - rc = cifs_set_vol_auth(vol_info, master_tcon->ses); - if (rc) { - tcon = ERR_PTR(rc); - goto out; - } + /* FIXME: allow for other secFlg settings */ + vol_info->secFlg = CIFSSEC_MUST_KRB5; /* get a reference for the same TCP session */ spin_lock(&cifs_tcp_ses_lock); @@ -4150,8 +3525,6 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, uid_t fsuid) if (ses->capabilities & CAP_UNIX) reset_cifs_unix_caps(0, tcon, NULL, vol_info); out: - kfree(vol_info->username); - kfree(vol_info->password); kfree(vol_info); return tcon; @@ -4344,6 +3717,6 @@ cifs_prune_tlinks(struct work_struct *work) } spin_unlock(&cifs_sb->tlink_tree_lock); - queue_delayed_work(cifsiod_wq, &cifs_sb->prune_tlinks, + queue_delayed_work(system_nrt_wq, &cifs_sb->prune_tlinks, TLINK_IDLE_EXPIRE); } diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index ec4e9a2a12f..c305fb01044 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -57,6 +57,11 @@ build_path_from_dentry(struct dentry *direntry) struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb); unsigned seq; + if (direntry == NULL) + return NULL; /* not much we can do if dentry is freed and + we need to reopen the file after it was closed implicitly + when the server crashed */ + dirsep = CIFS_DIR_SEP(cifs_sb); if (tcon->Flags & SMB_SHARE_IS_IN_DFS) dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1); @@ -171,10 +176,10 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, } tcon = tlink_tcon(tlink); - if (tcon->ses->server->oplocks) + if (oplockEnabled) oplock = REQ_OPLOCK; - if (nd) + if (nd && (nd->flags & LOOKUP_OPEN)) oflags = nd->intent.open.file->f_flags; else oflags = O_RDONLY | O_CREAT; @@ -209,7 +214,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, which should be rare for path not covered on files) */ } - if (nd) { + if (nd && (nd->flags & LOOKUP_OPEN)) { /* if the file is going to stay open, then we need to set the desired access properly */ desiredAccess = 0; @@ -244,9 +249,6 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, if (!tcon->unix_ext && (mode & S_IWUGO) == 0) create_options |= CREATE_OPTION_READONLY; - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - if (tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, create_options, @@ -326,7 +328,7 @@ cifs_create(struct inode *inode, struct dentry *direntry, umode_t mode, else cFYI(1, "Create worked, get_inode_info failed rc = %d", rc); - if (newinode && nd) { + if (newinode && nd && (nd->flags & LOOKUP_OPEN)) { struct cifsFileInfo *pfile_info; struct file *filp; @@ -360,7 +362,6 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, { int rc = -EPERM; int xid; - int create_options = CREATE_NOT_DIR | CREATE_OPTION_SPECIAL; struct cifs_sb_info *cifs_sb; struct tcon_link *tlink; struct cifs_tcon *pTcon; @@ -435,11 +436,9 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, umode_t mode, return rc; } - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - + /* FIXME: would WRITE_OWNER | WRITE_DAC be better? */ rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_CREATE, - GENERIC_WRITE, create_options, + GENERIC_WRITE, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, &fileHandle, &oplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) @@ -492,7 +491,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, { int xid; int rc = 0; /* to get around spurious gcc warning, set to zero here */ - __u32 oplock; + __u32 oplock = 0; __u16 fileHandle = 0; bool posix_open = false; struct cifs_sb_info *cifs_sb; @@ -518,8 +517,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, } pTcon = tlink_tcon(tlink); - oplock = pTcon->ses->server->oplocks ? REQ_OPLOCK : 0; - /* * Don't allow the separator character in a path component. * The VFS will not allow "/", but "\" is allowed by posix. @@ -571,7 +568,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, * reduction in network traffic in the other paths. */ if (pTcon->unix_ext) { - if (nd && !(nd->flags & LOOKUP_DIRECTORY) && + if (nd && !(nd->flags & (LOOKUP_PARENT | LOOKUP_DIRECTORY)) && (nd->flags & LOOKUP_OPEN) && !pTcon->broken_posix_open && (nd->intent.open.file->f_flags & O_CREAT)) { rc = cifs_posix_open(full_path, &newInode, @@ -666,23 +663,8 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) if (direntry->d_inode) { if (cifs_revalidate_dentry(direntry)) return 0; - else { - /* - * If the inode wasn't known to be a dfs entry when - * the dentry was instantiated, such as when created - * via ->readdir(), it needs to be set now since the - * attributes will have been updated by - * cifs_revalidate_dentry(). - */ - if (IS_AUTOMOUNT(direntry->d_inode) && - !(direntry->d_flags & DCACHE_NEED_AUTOMOUNT)) { - spin_lock(&direntry->d_lock); - direntry->d_flags |= DCACHE_NEED_AUTOMOUNT; - spin_unlock(&direntry->d_lock); - } - + else return 1; - } } /* diff --git a/fs/cifs/dns_resolve.c b/fs/cifs/dns_resolve.c index 1d2d91d9bf6..548f06230a6 100644 --- a/fs/cifs/dns_resolve.c +++ b/fs/cifs/dns_resolve.c @@ -79,8 +79,8 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) /* Perform the upcall */ rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL); if (rc < 0) - cFYI(1, "%s: unable to resolve: %*.*s", - __func__, len, len, hostname); + cERROR(1, "%s: unable to resolve: %*.*s", + __func__, len, len, hostname); else cFYI(1, "%s: resolved: %*.*s to %s", __func__, len, len, hostname, *ip_addr); diff --git a/fs/cifs/export.c b/fs/cifs/export.c index 9c7ecdccf2f..55d87ac5200 100644 --- a/fs/cifs/export.c +++ b/fs/cifs/export.c @@ -45,7 +45,7 @@ #include "cifs_debug.h" #include "cifsfs.h" -#ifdef CONFIG_CIFS_NFSD_EXPORT +#ifdef CIFS_NFSD_EXPORT static struct dentry *cifs_get_parent(struct dentry *dentry) { /* BB need to add code here eventually to enable export via NFSD */ @@ -63,5 +63,5 @@ const struct export_operations cifs_export_ops = { .encode_fs = */ }; -#endif /* CONFIG_CIFS_NFSD_EXPORT */ +#endif /* CIFS_NFSD_EXPORT */ diff --git a/fs/cifs/file.c b/fs/cifs/file.c index 81725e9286e..17802617567 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include "cifsfs.h" #include "cifspdu.h" @@ -175,7 +174,6 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, int rc; int desiredAccess; int disposition; - int create_options = CREATE_NOT_DIR; FILE_ALL_INFO *buf; desiredAccess = cifs_convert_flags(f_flags); @@ -212,12 +210,9 @@ cifs_nt_open(char *full_path, struct inode *inode, struct cifs_sb_info *cifs_sb, if (!buf) return -ENOMEM; - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - if (tcon->ses->capabilities & CAP_NT_SMBS) rc = CIFSSMBOpen(xid, tcon, full_path, disposition, - desiredAccess, create_options, pnetfid, poplock, buf, + desiredAccess, CREATE_NOT_DIR, pnetfid, poplock, buf, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); else @@ -263,6 +258,8 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, pCifsFile->invalidHandle = false; pCifsFile->tlink = cifs_get_tlink(tlink); mutex_init(&pCifsFile->fh_mutex); + mutex_init(&pCifsFile->lock_mutex); + INIT_LIST_HEAD(&pCifsFile->llist); INIT_WORK(&pCifsFile->oplock_break, cifs_oplock_break); spin_lock(&cifs_file_list_lock); @@ -275,14 +272,11 @@ cifs_new_fileinfo(__u16 fileHandle, struct file *file, spin_unlock(&cifs_file_list_lock); cifs_set_oplock_level(pCifsInode, oplock); - pCifsInode->can_cache_brlcks = pCifsInode->clientCanCacheAll; file->private_data = pCifsFile; return pCifsFile; } -static void cifs_del_lock_waiters(struct cifsLockInfo *lock); - /* * Release a reference on the file private data. This may involve closing * the filehandle out on the server. Must be called without holding @@ -320,8 +314,6 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) } spin_unlock(&cifs_file_list_lock); - cancel_work_sync(&cifs_file->oplock_break); - if (!tcon->need_reconnect && !cifs_file->invalidHandle) { int xid, rc; @@ -333,15 +325,12 @@ void cifsFileInfo_put(struct cifsFileInfo *cifs_file) /* Delete any outstanding lock records. We'll lose them when the file * is closed anyway. */ - mutex_lock(&cifsi->lock_mutex); - list_for_each_entry_safe(li, tmp, &cifsi->llist, llist) { - if (li->netfid != cifs_file->netfid) - continue; + mutex_lock(&cifs_file->lock_mutex); + list_for_each_entry_safe(li, tmp, &cifs_file->llist, llist) { list_del(&li->llist); - cifs_del_lock_waiters(li); kfree(li); } - mutex_unlock(&cifsi->lock_mutex); + mutex_unlock(&cifs_file->lock_mutex); cifs_put_tlink(cifs_file->tlink); dput(cifs_file->dentry); @@ -380,7 +369,7 @@ int cifs_open(struct inode *inode, struct file *file) cFYI(1, "inode = 0x%p file flags are 0x%x for %s", inode, file->f_flags, full_path); - if (tcon->ses->server->oplocks) + if (oplockEnabled) oplock = REQ_OPLOCK; else oplock = 0; @@ -474,7 +463,6 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) char *full_path = NULL; int desiredAccess; int disposition = FILE_OPEN; - int create_options = CREATE_NOT_DIR; __u16 netfid; xid = GetXid(); @@ -505,7 +493,7 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) cFYI(1, "inode = 0x%p file flags 0x%x for %s", inode, pCifsFile->f_flags, full_path); - if (tcon->ses->server->oplocks) + if (oplockEnabled) oplock = REQ_OPLOCK; else oplock = 0; @@ -534,9 +522,6 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) desiredAccess = cifs_convert_flags(pCifsFile->f_flags); - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - /* Can not refresh inode by passing in file_info buf to be returned by SMBOpen and then calling get_inode_info with returned buf since file might have write behind data that needs to be flushed @@ -544,7 +529,7 @@ static int cifs_reopen_file(struct cifsFileInfo *pCifsFile, bool can_flush) that inode was not dirty locally we could do this */ rc = CIFSSMBOpen(xid, tcon, full_path, disposition, desiredAccess, - create_options, &netfid, &oplock, NULL, + CREATE_NOT_DIR, &netfid, &oplock, NULL, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); if (rc) { @@ -644,773 +629,224 @@ int cifs_closedir(struct inode *inode, struct file *file) return rc; } -static struct cifsLockInfo * -cifs_lock_init(__u64 offset, __u64 length, __u8 type, __u16 netfid) +static int store_file_lock(struct cifsFileInfo *fid, __u64 len, + __u64 offset, __u8 lockType) { - struct cifsLockInfo *lock = + struct cifsLockInfo *li = kmalloc(sizeof(struct cifsLockInfo), GFP_KERNEL); - if (!lock) - return lock; - lock->offset = offset; - lock->length = length; - lock->type = type; - lock->netfid = netfid; - lock->pid = current->tgid; - INIT_LIST_HEAD(&lock->blist); - init_waitqueue_head(&lock->block_q); - return lock; -} - -static void -cifs_del_lock_waiters(struct cifsLockInfo *lock) -{ - struct cifsLockInfo *li, *tmp; - list_for_each_entry_safe(li, tmp, &lock->blist, blist) { - list_del_init(&li->blist); - wake_up(&li->block_q); - } -} - -static bool -__cifs_find_lock_conflict(struct cifsInodeInfo *cinode, __u64 offset, - __u64 length, __u8 type, __u16 netfid, - struct cifsLockInfo **conf_lock) -{ - struct cifsLockInfo *li, *tmp; - - list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { - if (offset + length <= li->offset || - offset >= li->offset + li->length) - continue; - else if ((type & LOCKING_ANDX_SHARED_LOCK) && - ((netfid == li->netfid && current->tgid == li->pid) || - type == li->type)) - continue; - else { - *conf_lock = li; - return true; - } - } - return false; -} - -static bool -cifs_find_lock_conflict(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, - struct cifsLockInfo **conf_lock) -{ - return __cifs_find_lock_conflict(cinode, lock->offset, lock->length, - lock->type, lock->netfid, conf_lock); -} - -/* - * Check if there is another lock that prevents us to set the lock (mandatory - * style). If such a lock exists, update the flock structure with its - * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks - * or leave it the same if we can't. Returns 0 if we don't need to request to - * the server or 1 otherwise. - */ -static int -cifs_lock_test(struct cifsInodeInfo *cinode, __u64 offset, __u64 length, - __u8 type, __u16 netfid, struct file_lock *flock) -{ - int rc = 0; - struct cifsLockInfo *conf_lock; - bool exist; - - mutex_lock(&cinode->lock_mutex); - - exist = __cifs_find_lock_conflict(cinode, offset, length, type, netfid, - &conf_lock); - if (exist) { - flock->fl_start = conf_lock->offset; - flock->fl_end = conf_lock->offset + conf_lock->length - 1; - flock->fl_pid = conf_lock->pid; - if (conf_lock->type & LOCKING_ANDX_SHARED_LOCK) - flock->fl_type = F_RDLCK; - else - flock->fl_type = F_WRLCK; - } else if (!cinode->can_cache_brlcks) - rc = 1; - else - flock->fl_type = F_UNLCK; - - mutex_unlock(&cinode->lock_mutex); - return rc; -} - -static void -cifs_lock_add(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock) -{ - mutex_lock(&cinode->lock_mutex); - list_add_tail(&lock->llist, &cinode->llist); - mutex_unlock(&cinode->lock_mutex); -} - -/* - * Set the byte-range lock (mandatory style). Returns: - * 1) 0, if we set the lock and don't need to request to the server; - * 2) 1, if no locks prevent us but we need to request to the server; - * 3) -EACCESS, if there is a lock that prevents us and wait is false. - */ -static int -cifs_lock_add_if(struct cifsInodeInfo *cinode, struct cifsLockInfo *lock, - bool wait) -{ - struct cifsLockInfo *conf_lock; - bool exist; - int rc = 0; - -try_again: - exist = false; - mutex_lock(&cinode->lock_mutex); - - exist = cifs_find_lock_conflict(cinode, lock, &conf_lock); - if (!exist && cinode->can_cache_brlcks) { - list_add_tail(&lock->llist, &cinode->llist); - mutex_unlock(&cinode->lock_mutex); - return rc; - } - - if (!exist) - rc = 1; - else if (!wait) - rc = -EACCES; - else { - list_add_tail(&lock->blist, &conf_lock->blist); - mutex_unlock(&cinode->lock_mutex); - rc = wait_event_interruptible(lock->block_q, - (lock->blist.prev == &lock->blist) && - (lock->blist.next == &lock->blist)); - if (!rc) - goto try_again; - mutex_lock(&cinode->lock_mutex); - list_del_init(&lock->blist); - } - - mutex_unlock(&cinode->lock_mutex); - return rc; -} - -/* - * Check if there is another lock that prevents us to set the lock (posix - * style). If such a lock exists, update the flock structure with its - * properties. Otherwise, set the flock type to F_UNLCK if we can cache brlocks - * or leave it the same if we can't. Returns 0 if we don't need to request to - * the server or 1 otherwise. - */ -static int -cifs_posix_lock_test(struct file *file, struct file_lock *flock) -{ - int rc = 0; - struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); - unsigned char saved_type = flock->fl_type; - - if ((flock->fl_flags & FL_POSIX) == 0) - return 1; - - mutex_lock(&cinode->lock_mutex); - posix_test_lock(file, flock); - - if (flock->fl_type == F_UNLCK && !cinode->can_cache_brlcks) { - flock->fl_type = saved_type; - rc = 1; - } - - mutex_unlock(&cinode->lock_mutex); - return rc; -} - -/* - * Set the byte-range lock (posix style). Returns: - * 1) 0, if we set the lock and don't need to request to the server; - * 2) 1, if we need to request to the server; - * 3) <0, if the error occurs while setting the lock. - */ -static int -cifs_posix_lock_set(struct file *file, struct file_lock *flock) -{ - struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); - int rc = 1; - - if ((flock->fl_flags & FL_POSIX) == 0) - return rc; - -try_again: - mutex_lock(&cinode->lock_mutex); - if (!cinode->can_cache_brlcks) { - mutex_unlock(&cinode->lock_mutex); - return rc; - } - - rc = posix_lock_file(file, flock, NULL); - mutex_unlock(&cinode->lock_mutex); - if (rc == FILE_LOCK_DEFERRED) { - rc = wait_event_interruptible(flock->fl_wait, !flock->fl_next); - if (!rc) - goto try_again; - locks_delete_block(flock); - } - return rc; + if (li == NULL) + return -ENOMEM; + li->offset = offset; + li->length = len; + li->type = lockType; + mutex_lock(&fid->lock_mutex); + list_add(&li->llist, &fid->llist); + mutex_unlock(&fid->lock_mutex); + return 0; } -static int -cifs_push_mandatory_locks(struct cifsFileInfo *cfile) +int cifs_lock(struct file *file, int cmd, struct file_lock *pfLock) { - int xid, rc = 0, stored_rc; - struct cifsLockInfo *li, *tmp; - struct cifs_tcon *tcon; - struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - unsigned int num, max_num; - LOCKING_ANDX_RANGE *buf, *cur; - int types[] = {LOCKING_ANDX_LARGE_FILES, - LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; - int i; - - xid = GetXid(); - tcon = tlink_tcon(cfile->tlink); - - mutex_lock(&cinode->lock_mutex); - if (!cinode->can_cache_brlcks) { - mutex_unlock(&cinode->lock_mutex); - FreeXid(xid); - return rc; - } - - max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) / - sizeof(LOCKING_ANDX_RANGE); - buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); - if (!buf) { - mutex_unlock(&cinode->lock_mutex); - FreeXid(xid); - return rc; - } - - for (i = 0; i < 2; i++) { - cur = buf; - num = 0; - list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { - if (li->type != types[i]) - continue; - cur->Pid = cpu_to_le16(li->pid); - cur->LengthLow = cpu_to_le32((u32)li->length); - cur->LengthHigh = cpu_to_le32((u32)(li->length>>32)); - cur->OffsetLow = cpu_to_le32((u32)li->offset); - cur->OffsetHigh = cpu_to_le32((u32)(li->offset>>32)); - if (++num == max_num) { - stored_rc = cifs_lockv(xid, tcon, cfile->netfid, - li->type, 0, num, buf); - if (stored_rc) - rc = stored_rc; - cur = buf; - num = 0; - } else - cur++; - } - - if (num) { - stored_rc = cifs_lockv(xid, tcon, cfile->netfid, - types[i], 0, num, buf); - if (stored_rc) - rc = stored_rc; - } - } - - cinode->can_cache_brlcks = false; - mutex_unlock(&cinode->lock_mutex); - - kfree(buf); - FreeXid(xid); - return rc; -} - -/* copied from fs/locks.c with a name change */ -#define cifs_for_each_lock(inode, lockp) \ - for (lockp = &inode->i_flock; *lockp != NULL; \ - lockp = &(*lockp)->fl_next) - -struct lock_to_push { - struct list_head llist; - __u64 offset; + int rc, xid; + __u32 numLock = 0; + __u32 numUnlock = 0; __u64 length; - __u32 pid; + bool wait_flag = false; + struct cifs_sb_info *cifs_sb; + struct cifs_tcon *tcon; __u16 netfid; - __u8 type; -}; - -static int -cifs_push_posix_locks(struct cifsFileInfo *cfile) -{ - struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct file_lock *flock, **before; - unsigned int count = 0, i = 0; - int rc = 0, xid, type; - struct list_head locks_to_send, *el; - struct lock_to_push *lck, *tmp; - __u64 length; + __u8 lockType = LOCKING_ANDX_LARGE_FILES; + bool posix_locking = 0; + length = 1 + pfLock->fl_end - pfLock->fl_start; + rc = -EACCES; xid = GetXid(); - mutex_lock(&cinode->lock_mutex); - if (!cinode->can_cache_brlcks) { - mutex_unlock(&cinode->lock_mutex); - FreeXid(xid); - return rc; - } - - lock_flocks(); - cifs_for_each_lock(cfile->dentry->d_inode, before) { - if ((*before)->fl_flags & FL_POSIX) - count++; - } - unlock_flocks(); - - INIT_LIST_HEAD(&locks_to_send); + cFYI(1, "Lock parm: 0x%x flockflags: " + "0x%x flocktype: 0x%x start: %lld end: %lld", + cmd, pfLock->fl_flags, pfLock->fl_type, pfLock->fl_start, + pfLock->fl_end); - /* - * Allocating count locks is enough because no FL_POSIX locks can be - * added to the list while we are holding cinode->lock_mutex that - * protects locking operations of this inode. - */ - for (; i < count; i++) { - lck = kmalloc(sizeof(struct lock_to_push), GFP_KERNEL); - if (!lck) { - rc = -ENOMEM; - goto err_out; - } - list_add_tail(&lck->llist, &locks_to_send); - } - - el = locks_to_send.next; - lock_flocks(); - cifs_for_each_lock(cfile->dentry->d_inode, before) { - flock = *before; - if ((flock->fl_flags & FL_POSIX) == 0) - continue; - if (el == &locks_to_send) { - /* - * The list ended. We don't have enough allocated - * structures - something is really wrong. - */ - cERROR(1, "Can't push all brlocks!"); - break; - } - length = 1 + flock->fl_end - flock->fl_start; - if (flock->fl_type == F_RDLCK || flock->fl_type == F_SHLCK) - type = CIFS_RDLCK; - else - type = CIFS_WRLCK; - lck = list_entry(el, struct lock_to_push, llist); - lck->pid = flock->fl_pid; - lck->netfid = cfile->netfid; - lck->length = length; - lck->type = type; - lck->offset = flock->fl_start; - el = el->next; - } - unlock_flocks(); - - list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { - struct file_lock tmp_lock; - int stored_rc; - - tmp_lock.fl_start = lck->offset; - stored_rc = CIFSSMBPosixLock(xid, tcon, lck->netfid, lck->pid, - 0, lck->length, &tmp_lock, - lck->type, 0); - if (stored_rc) - rc = stored_rc; - list_del(&lck->llist); - kfree(lck); - } - -out: - cinode->can_cache_brlcks = false; - mutex_unlock(&cinode->lock_mutex); - - FreeXid(xid); - return rc; -err_out: - list_for_each_entry_safe(lck, tmp, &locks_to_send, llist) { - list_del(&lck->llist); - kfree(lck); - } - goto out; -} - -static int -cifs_push_locks(struct cifsFileInfo *cfile) -{ - struct cifs_sb_info *cifs_sb = CIFS_SB(cfile->dentry->d_sb); - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - - if ((tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && - ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) - return cifs_push_posix_locks(cfile); - - return cifs_push_mandatory_locks(cfile); -} - -static void -cifs_read_flock(struct file_lock *flock, __u8 *type, int *lock, int *unlock, - bool *wait_flag) -{ - if (flock->fl_flags & FL_POSIX) + if (pfLock->fl_flags & FL_POSIX) cFYI(1, "Posix"); - if (flock->fl_flags & FL_FLOCK) + if (pfLock->fl_flags & FL_FLOCK) cFYI(1, "Flock"); - if (flock->fl_flags & FL_SLEEP) { + if (pfLock->fl_flags & FL_SLEEP) { cFYI(1, "Blocking lock"); - *wait_flag = true; + wait_flag = true; } - if (flock->fl_flags & FL_ACCESS) + if (pfLock->fl_flags & FL_ACCESS) cFYI(1, "Process suspended by mandatory locking - " - "not implemented yet"); - if (flock->fl_flags & FL_LEASE) + "not implemented yet"); + if (pfLock->fl_flags & FL_LEASE) cFYI(1, "Lease on file - not implemented yet"); - if (flock->fl_flags & + if (pfLock->fl_flags & (~(FL_POSIX | FL_FLOCK | FL_SLEEP | FL_ACCESS | FL_LEASE))) - cFYI(1, "Unknown lock flags 0x%x", flock->fl_flags); + cFYI(1, "Unknown lock flags 0x%x", pfLock->fl_flags); - *type = LOCKING_ANDX_LARGE_FILES; - if (flock->fl_type == F_WRLCK) { + if (pfLock->fl_type == F_WRLCK) { cFYI(1, "F_WRLCK "); - *lock = 1; - } else if (flock->fl_type == F_UNLCK) { + numLock = 1; + } else if (pfLock->fl_type == F_UNLCK) { cFYI(1, "F_UNLCK"); - *unlock = 1; - /* Check if unlock includes more than one lock range */ - } else if (flock->fl_type == F_RDLCK) { + numUnlock = 1; + /* Check if unlock includes more than + one lock range */ + } else if (pfLock->fl_type == F_RDLCK) { cFYI(1, "F_RDLCK"); - *type |= LOCKING_ANDX_SHARED_LOCK; - *lock = 1; - } else if (flock->fl_type == F_EXLCK) { + lockType |= LOCKING_ANDX_SHARED_LOCK; + numLock = 1; + } else if (pfLock->fl_type == F_EXLCK) { cFYI(1, "F_EXLCK"); - *lock = 1; - } else if (flock->fl_type == F_SHLCK) { + numLock = 1; + } else if (pfLock->fl_type == F_SHLCK) { cFYI(1, "F_SHLCK"); - *type |= LOCKING_ANDX_SHARED_LOCK; - *lock = 1; + lockType |= LOCKING_ANDX_SHARED_LOCK; + numLock = 1; } else cFYI(1, "Unknown type of lock"); -} -static int -cifs_getlk(struct file *file, struct file_lock *flock, __u8 type, - bool wait_flag, bool posix_lck, int xid) -{ - int rc = 0; - __u64 length = 1 + flock->fl_end - flock->fl_start; - struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - __u16 netfid = cfile->netfid; - - if (posix_lck) { - int posix_lock_type; + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); + tcon = tlink_tcon(((struct cifsFileInfo *)file->private_data)->tlink); + netfid = ((struct cifsFileInfo *)file->private_data)->netfid; - rc = cifs_posix_lock_test(file, flock); - if (!rc) + if ((tcon->ses->capabilities & CAP_UNIX) && + (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && + ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) + posix_locking = 1; + /* BB add code here to normalize offset and length to + account for negative length which we can not accept over the + wire */ + if (IS_GETLK(cmd)) { + if (posix_locking) { + int posix_lock_type; + if (lockType & LOCKING_ANDX_SHARED_LOCK) + posix_lock_type = CIFS_RDLCK; + else + posix_lock_type = CIFS_WRLCK; + rc = CIFSSMBPosixLock(xid, tcon, netfid, 1 /* get */, + length, pfLock, posix_lock_type, + wait_flag); + FreeXid(xid); return rc; + } - if (type & LOCKING_ANDX_SHARED_LOCK) - posix_lock_type = CIFS_RDLCK; - else - posix_lock_type = CIFS_WRLCK; - rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid, - 1 /* get */, length, flock, - posix_lock_type, wait_flag); - return rc; - } - - rc = cifs_lock_test(cinode, flock->fl_start, length, type, netfid, - flock); - if (!rc) - return rc; - - /* BB we could chain these into one lock request BB */ - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, - flock->fl_start, 0, 1, type, 0, 0); - if (rc == 0) { - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, - length, flock->fl_start, 1, 0, - type, 0, 0); - flock->fl_type = F_UNLCK; - if (rc != 0) - cERROR(1, "Error unlocking previously locked " - "range %d during test of lock", rc); - return 0; - } - - if (type & LOCKING_ANDX_SHARED_LOCK) { - flock->fl_type = F_WRLCK; - return 0; - } - - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, - flock->fl_start, 0, 1, - type | LOCKING_ANDX_SHARED_LOCK, 0, 0); - if (rc == 0) { - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, - length, flock->fl_start, 1, 0, - type | LOCKING_ANDX_SHARED_LOCK, - 0, 0); - flock->fl_type = F_RDLCK; - if (rc != 0) - cERROR(1, "Error unlocking previously locked " - "range %d during test of lock", rc); - } else - flock->fl_type = F_WRLCK; - - return 0; -} - -static void -cifs_move_llist(struct list_head *source, struct list_head *dest) -{ - struct list_head *li, *tmp; - list_for_each_safe(li, tmp, source) - list_move(li, dest); -} - -static void -cifs_free_llist(struct list_head *llist) -{ - struct cifsLockInfo *li, *tmp; - list_for_each_entry_safe(li, tmp, llist, llist) { - cifs_del_lock_waiters(li); - list_del(&li->llist); - kfree(li); - } -} - -static int -cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock, int xid) -{ - int rc = 0, stored_rc; - int types[] = {LOCKING_ANDX_LARGE_FILES, - LOCKING_ANDX_SHARED_LOCK | LOCKING_ANDX_LARGE_FILES}; - unsigned int i; - unsigned int max_num, num; - LOCKING_ANDX_RANGE *buf, *cur; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct cifsInodeInfo *cinode = CIFS_I(cfile->dentry->d_inode); - struct cifsLockInfo *li, *tmp; - __u64 length = 1 + flock->fl_end - flock->fl_start; - struct list_head tmp_llist; - - INIT_LIST_HEAD(&tmp_llist); + /* BB we could chain these into one lock request BB */ + rc = CIFSSMBLock(xid, tcon, netfid, length, pfLock->fl_start, + 0, 1, lockType, 0 /* wait flag */, 0); + if (rc == 0) { + rc = CIFSSMBLock(xid, tcon, netfid, length, + pfLock->fl_start, 1 /* numUnlock */ , + 0 /* numLock */ , lockType, + 0 /* wait flag */, 0); + pfLock->fl_type = F_UNLCK; + if (rc != 0) + cERROR(1, "Error unlocking previously locked " + "range %d during test of lock", rc); + rc = 0; - max_num = (tcon->ses->server->maxBuf - sizeof(struct smb_hdr)) / - sizeof(LOCKING_ANDX_RANGE); - buf = kzalloc(max_num * sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL); - if (!buf) - return -ENOMEM; + } else { + /* if rc == ERR_SHARING_VIOLATION ? */ + rc = 0; - mutex_lock(&cinode->lock_mutex); - for (i = 0; i < 2; i++) { - cur = buf; - num = 0; - list_for_each_entry_safe(li, tmp, &cinode->llist, llist) { - if (flock->fl_start > li->offset || - (flock->fl_start + length) < - (li->offset + li->length)) - continue; - if (current->tgid != li->pid) - continue; - if (cfile->netfid != li->netfid) - continue; - if (types[i] != li->type) - continue; - if (!cinode->can_cache_brlcks) { - cur->Pid = cpu_to_le16(li->pid); - cur->LengthLow = cpu_to_le32((u32)li->length); - cur->LengthHigh = - cpu_to_le32((u32)(li->length>>32)); - cur->OffsetLow = cpu_to_le32((u32)li->offset); - cur->OffsetHigh = - cpu_to_le32((u32)(li->offset>>32)); - /* - * We need to save a lock here to let us add - * it again to the inode list if the unlock - * range request fails on the server. - */ - list_move(&li->llist, &tmp_llist); - if (++num == max_num) { - stored_rc = cifs_lockv(xid, tcon, - cfile->netfid, - li->type, num, - 0, buf); - if (stored_rc) { - /* - * We failed on the unlock range - * request - add all locks from - * the tmp list to the head of - * the inode list. - */ - cifs_move_llist(&tmp_llist, - &cinode->llist); - rc = stored_rc; - } else - /* - * The unlock range request - * succeed - free the tmp list. - */ - cifs_free_llist(&tmp_llist); - cur = buf; - num = 0; - } else - cur++; + if (lockType & LOCKING_ANDX_SHARED_LOCK) { + pfLock->fl_type = F_WRLCK; } else { - /* - * We can cache brlock requests - simply remove - * a lock from the inode list. - */ - list_del(&li->llist); - cifs_del_lock_waiters(li); - kfree(li); + rc = CIFSSMBLock(xid, tcon, netfid, length, + pfLock->fl_start, 0, 1, + lockType | LOCKING_ANDX_SHARED_LOCK, + 0 /* wait flag */, 0); + if (rc == 0) { + rc = CIFSSMBLock(xid, tcon, netfid, + length, pfLock->fl_start, 1, 0, + lockType | + LOCKING_ANDX_SHARED_LOCK, + 0 /* wait flag */, 0); + pfLock->fl_type = F_RDLCK; + if (rc != 0) + cERROR(1, "Error unlocking " + "previously locked range %d " + "during test of lock", rc); + rc = 0; + } else { + pfLock->fl_type = F_WRLCK; + rc = 0; + } } } - if (num) { - stored_rc = cifs_lockv(xid, tcon, cfile->netfid, - types[i], num, 0, buf); - if (stored_rc) { - cifs_move_llist(&tmp_llist, &cinode->llist); - rc = stored_rc; - } else - cifs_free_llist(&tmp_llist); - } - } - mutex_unlock(&cinode->lock_mutex); - kfree(buf); - return rc; -} + FreeXid(xid); + return rc; + } -static int -cifs_setlk(struct file *file, struct file_lock *flock, __u8 type, - bool wait_flag, bool posix_lck, int lock, int unlock, int xid) -{ - int rc = 0; - __u64 length = 1 + flock->fl_end - flock->fl_start; - struct cifsFileInfo *cfile = (struct cifsFileInfo *)file->private_data; - struct cifs_tcon *tcon = tlink_tcon(cfile->tlink); - struct cifsInodeInfo *cinode = CIFS_I(file->f_path.dentry->d_inode); - __u16 netfid = cfile->netfid; + if (!numLock && !numUnlock) { + /* if no lock or unlock then nothing + to do since we do not know what it is */ + FreeXid(xid); + return -EOPNOTSUPP; + } - if (posix_lck) { + if (posix_locking) { int posix_lock_type; - - rc = cifs_posix_lock_set(file, flock); - if (!rc || rc < 0) - return rc; - - if (type & LOCKING_ANDX_SHARED_LOCK) + if (lockType & LOCKING_ANDX_SHARED_LOCK) posix_lock_type = CIFS_RDLCK; else posix_lock_type = CIFS_WRLCK; - if (unlock == 1) + if (numUnlock == 1) posix_lock_type = CIFS_UNLCK; - rc = CIFSSMBPosixLock(xid, tcon, netfid, current->tgid, - 0 /* set */, length, flock, - posix_lock_type, wait_flag); - goto out; - } - - if (lock) { - struct cifsLockInfo *lock; - - lock = cifs_lock_init(flock->fl_start, length, type, netfid); - if (!lock) - return -ENOMEM; - - rc = cifs_lock_add_if(cinode, lock, wait_flag); - if (rc < 0) - kfree(lock); - if (rc <= 0) - goto out; - - rc = CIFSSMBLock(xid, tcon, netfid, current->tgid, length, - flock->fl_start, 0, 1, type, wait_flag, 0); - if (rc) { - kfree(lock); - goto out; - } - - cifs_lock_add(cinode, lock); - } else if (unlock) - rc = cifs_unlock_range(cfile, flock, xid); - -out: - if (flock->fl_flags & FL_POSIX) - posix_lock_file_wait(file, flock); - return rc; -} - -int cifs_lock(struct file *file, int cmd, struct file_lock *flock) -{ - int rc, xid; - int lock = 0, unlock = 0; - bool wait_flag = false; - bool posix_lck = false; - struct cifs_sb_info *cifs_sb; - struct cifs_tcon *tcon; - struct cifsInodeInfo *cinode; - struct cifsFileInfo *cfile; - __u16 netfid; - __u8 type; - - rc = -EACCES; - xid = GetXid(); - - cFYI(1, "Lock parm: 0x%x flockflags: 0x%x flocktype: 0x%x start: %lld " - "end: %lld", cmd, flock->fl_flags, flock->fl_type, - flock->fl_start, flock->fl_end); - - cifs_read_flock(flock, &type, &lock, &unlock, &wait_flag); + rc = CIFSSMBPosixLock(xid, tcon, netfid, 0 /* set */, + length, pfLock, posix_lock_type, + wait_flag); + } else { + struct cifsFileInfo *fid = file->private_data; - cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - cfile = (struct cifsFileInfo *)file->private_data; - tcon = tlink_tcon(cfile->tlink); - netfid = cfile->netfid; - cinode = CIFS_I(file->f_path.dentry->d_inode); + if (numLock) { + rc = CIFSSMBLock(xid, tcon, netfid, length, + pfLock->fl_start, 0, numLock, lockType, + wait_flag, 0); - if ((tcon->ses->capabilities & CAP_UNIX) && - (CIFS_UNIX_FCNTL_CAP & le64_to_cpu(tcon->fsUnixInfo.Capability)) && - ((cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NOPOSIXBRL) == 0)) - posix_lck = true; - /* - * BB add code here to normalize offset and length to account for - * negative length which we can not accept over the wire. - */ - if (IS_GETLK(cmd)) { - rc = cifs_getlk(file, flock, type, wait_flag, posix_lck, xid); - FreeXid(xid); - return rc; - } + if (rc == 0) { + /* For Windows locks we must store them. */ + rc = store_file_lock(fid, length, + pfLock->fl_start, lockType); + } + } else if (numUnlock) { + /* For each stored lock that this unlock overlaps + completely, unlock it. */ + int stored_rc = 0; + struct cifsLockInfo *li, *tmp; - if (!lock && !unlock) { - /* - * if no lock or unlock then nothing to do since we do not - * know what it is - */ - FreeXid(xid); - return -EOPNOTSUPP; + rc = 0; + mutex_lock(&fid->lock_mutex); + list_for_each_entry_safe(li, tmp, &fid->llist, llist) { + if (pfLock->fl_start <= li->offset && + (pfLock->fl_start + length) >= + (li->offset + li->length)) { + stored_rc = CIFSSMBLock(xid, tcon, + netfid, li->length, + li->offset, 1, 0, + li->type, false, 0); + if (stored_rc) + rc = stored_rc; + else { + list_del(&li->llist); + kfree(li); + } + } + } + mutex_unlock(&fid->lock_mutex); + } } - rc = cifs_setlk(file, flock, type, wait_flag, posix_lck, lock, unlock, - xid); + if (pfLock->fl_flags & FL_POSIX) + posix_lock_file_wait(file, pfLock); FreeXid(xid); return rc; } -/* - * update the file size (if needed) after a write. Should be called with - * the inode->i_lock held - */ +/* update the file size (if needed) after a write */ void cifs_update_eof(struct cifsInodeInfo *cifsi, loff_t offset, unsigned int bytes_written) @@ -1482,9 +918,7 @@ static ssize_t cifs_write(struct cifsFileInfo *open_file, __u32 pid, return rc; } } else { - spin_lock(&dentry->d_inode->i_lock); cifs_update_eof(cifsi, *poffset, bytes_written); - spin_unlock(&dentry->d_inode->i_lock); *poffset += bytes_written; } } @@ -1539,10 +973,11 @@ struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode, struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only) { - struct cifsFileInfo *open_file; + struct cifsFileInfo *open_file, *inv_file = NULL; struct cifs_sb_info *cifs_sb; bool any_available = false; int rc; + unsigned int refind = 0; /* Having a null inode here (because mapping->host was set to zero by the VFS or MM) should not happen but we had reports of on oops (due to @@ -1562,40 +997,25 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, spin_lock(&cifs_file_list_lock); refind_writable: + if (refind > MAX_REOPEN_ATT) { + spin_unlock(&cifs_file_list_lock); + return NULL; + } list_for_each_entry(open_file, &cifs_inode->openFileList, flist) { if (!any_available && open_file->pid != current->tgid) continue; if (fsuid_only && open_file->uid != current_fsuid()) continue; if (OPEN_FMODE(open_file->f_flags) & FMODE_WRITE) { - cifsFileInfo_get(open_file); - if (!open_file->invalidHandle) { /* found a good writable file */ + cifsFileInfo_get(open_file); spin_unlock(&cifs_file_list_lock); return open_file; + } else { + if (!inv_file) + inv_file = open_file; } - - spin_unlock(&cifs_file_list_lock); - - /* Had to unlock since following call can block */ - rc = cifs_reopen_file(open_file, false); - if (!rc) - return open_file; - - /* if it fails, try another handle if possible */ - cFYI(1, "wp failed on reopen file"); - cifsFileInfo_put(open_file); - - spin_lock(&cifs_file_list_lock); - - /* else we simply continue to the next entry. Thus - we do not loop on reopen errors. If we - can not reopen the file, for example if we - reconnected to a server with another client - racing to delete or lock the file we would not - make progress if we restarted before the beginning - of the loop here. */ } } /* couldn't find useable FH with same pid, try any available */ @@ -1603,7 +1023,30 @@ struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode, any_available = true; goto refind_writable; } + + if (inv_file) { + any_available = false; + cifsFileInfo_get(inv_file); + } + spin_unlock(&cifs_file_list_lock); + + if (inv_file) { + rc = cifs_reopen_file(inv_file, false); + if (!rc) + return inv_file; + else { + spin_lock(&cifs_file_list_lock); + list_move_tail(&inv_file->flist, + &cifs_inode->openFileList); + spin_unlock(&cifs_file_list_lock); + cifsFileInfo_put(inv_file); + spin_lock(&cifs_file_list_lock); + ++refind; + goto refind_writable; + } + } + return NULL; } @@ -1661,27 +1104,6 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) return rc; } -/* - * Marshal up the iov array, reserving the first one for the header. Also, - * set wdata->bytes. - */ -static void -cifs_writepages_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) -{ - int i; - struct inode *inode = wdata->cfile->dentry->d_inode; - loff_t size = i_size_read(inode); - - /* marshal up the pages into iov array */ - wdata->bytes = 0; - for (i = 0; i < wdata->nr_pages; i++) { - iov[i + 1].iov_len = min(size - page_offset(wdata->pages[i]), - (loff_t)PAGE_CACHE_SIZE); - iov[i + 1].iov_base = kmap(wdata->pages[i]); - wdata->bytes += iov[i + 1].iov_len; - } -} - static int cifs_writepages(struct address_space *mapping, struct writeback_control *wbc) { @@ -1718,8 +1140,7 @@ static int cifs_writepages(struct address_space *mapping, tofind = min((cifs_sb->wsize / PAGE_CACHE_SIZE) - 1, end - index) + 1; - wdata = cifs_writedata_alloc((unsigned int)tofind, - cifs_writev_complete); + wdata = cifs_writedata_alloc((unsigned int)tofind); if (!wdata) { rc = -ENOMEM; break; @@ -1826,7 +1247,6 @@ static int cifs_writepages(struct address_space *mapping, wdata->sync_mode = wbc->sync_mode; wdata->nr_pages = nr_pages; wdata->offset = page_offset(wdata->pages[0]); - wdata->marshal_iov = cifs_writepages_marshal_iov; do { if (wdata->cfile != NULL) @@ -1838,7 +1258,6 @@ static int cifs_writepages(struct address_space *mapping, rc = -EBADF; break; } - wdata->pid = wdata->cfile->pid; rc = cifs_async_writev(wdata); } while (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN); @@ -2001,11 +1420,6 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, struct inode *inode = file->f_path.dentry->d_inode; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); - rc = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (rc) - return rc; - mutex_lock(&inode->i_mutex); - xid = GetXid(); cFYI(1, "Sync file - name: %s datasync: 0x%x", @@ -2024,7 +1438,6 @@ int cifs_strict_fsync(struct file *file, loff_t start, loff_t end, rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); FreeXid(xid); - mutex_unlock(&inode->i_mutex); return rc; } @@ -2035,12 +1448,6 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) struct cifs_tcon *tcon; struct cifsFileInfo *smbfile = file->private_data; struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - struct inode *inode = file->f_mapping->host; - - rc = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (rc) - return rc; - mutex_lock(&inode->i_mutex); xid = GetXid(); @@ -2052,7 +1459,6 @@ int cifs_fsync(struct file *file, loff_t start, loff_t end, int datasync) rc = CIFSSMBFlush(xid, tcon, smbfile->netfid); FreeXid(xid); - mutex_unlock(&inode->i_mutex); return rc; } @@ -2080,7 +1486,7 @@ cifs_write_allocate_pages(struct page **pages, unsigned long num_pages) unsigned long i; for (i = 0; i < num_pages; i++) { - pages[i] = alloc_page(GFP_KERNEL|__GFP_HIGHMEM); + pages[i] = alloc_page(__GFP_HIGHMEM); if (!pages[i]) { /* * save number of pages we have already allocated and @@ -2088,14 +1494,15 @@ cifs_write_allocate_pages(struct page **pages, unsigned long num_pages) */ num_pages = i; rc = -ENOMEM; - break; + goto error; } } - if (rc) { - for (i = 0; i < num_pages; i++) - put_page(pages[i]); - } + return rc; + +error: + for (i = 0; i < num_pages; i++) + put_page(pages[i]); return rc; } @@ -2106,7 +1513,9 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) size_t clen; clen = min_t(const size_t, len, wsize); - num_pages = DIV_ROUND_UP(clen, PAGE_SIZE); + num_pages = clen / PAGE_CACHE_SIZE; + if (clen % PAGE_CACHE_SIZE) + num_pages++; if (cur_len) *cur_len = clen; @@ -2114,79 +1523,24 @@ size_t get_numpages(const size_t wsize, const size_t len, size_t *cur_len) return num_pages; } -static void -cifs_uncached_marshal_iov(struct kvec *iov, struct cifs_writedata *wdata) -{ - int i; - size_t bytes = wdata->bytes; - - /* marshal up the pages into iov array */ - for (i = 0; i < wdata->nr_pages; i++) { - iov[i + 1].iov_len = min_t(size_t, bytes, PAGE_SIZE); - iov[i + 1].iov_base = kmap(wdata->pages[i]); - bytes -= iov[i + 1].iov_len; - } -} - -static void -cifs_uncached_writev_complete(struct work_struct *work) -{ - int i; - struct cifs_writedata *wdata = container_of(work, - struct cifs_writedata, work); - struct inode *inode = wdata->cfile->dentry->d_inode; - struct cifsInodeInfo *cifsi = CIFS_I(inode); - - spin_lock(&inode->i_lock); - cifs_update_eof(cifsi, wdata->offset, wdata->bytes); - if (cifsi->server_eof > inode->i_size) - i_size_write(inode, cifsi->server_eof); - spin_unlock(&inode->i_lock); - - complete(&wdata->done); - - if (wdata->result != -EAGAIN) { - for (i = 0; i < wdata->nr_pages; i++) - put_page(wdata->pages[i]); - } - - kref_put(&wdata->refcount, cifs_writedata_release); -} - -/* attempt to send write to server, retry on any -EAGAIN errors */ -static int -cifs_uncached_retry_writev(struct cifs_writedata *wdata) -{ - int rc; - - do { - if (wdata->cfile->invalidHandle) { - rc = cifs_reopen_file(wdata->cfile, false); - if (rc != 0) - continue; - } - rc = cifs_async_writev(wdata); - } while (rc == -EAGAIN); - - return rc; -} - static ssize_t cifs_iovec_write(struct file *file, const struct iovec *iov, unsigned long nr_segs, loff_t *poffset) { - unsigned long nr_pages, i; + unsigned int written; + unsigned long num_pages, npages, i; size_t copied, len, cur_len; ssize_t total_written = 0; - loff_t offset; + struct kvec *to_send; + struct page **pages; struct iov_iter it; + struct inode *inode; struct cifsFileInfo *open_file; - struct cifs_tcon *tcon; + struct cifs_tcon *pTcon; struct cifs_sb_info *cifs_sb; - struct cifs_writedata *wdata, *tmp; - struct list_head wdata_list; - int rc; - pid_t pid; + struct cifs_io_parms io_parms; + int xid, rc; + __u32 pid; len = iov_length(iov, nr_segs); if (!len) @@ -2196,104 +1550,103 @@ cifs_iovec_write(struct file *file, const struct iovec *iov, if (rc) return rc; - INIT_LIST_HEAD(&wdata_list); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); + num_pages = get_numpages(cifs_sb->wsize, len, &cur_len); + + pages = kmalloc(sizeof(struct pages *)*num_pages, GFP_KERNEL); + if (!pages) + return -ENOMEM; + + to_send = kmalloc(sizeof(struct kvec)*(num_pages + 1), GFP_KERNEL); + if (!to_send) { + kfree(pages); + return -ENOMEM; + } + + rc = cifs_write_allocate_pages(pages, num_pages); + if (rc) { + kfree(pages); + kfree(to_send); + return rc; + } + + xid = GetXid(); open_file = file->private_data; - tcon = tlink_tcon(open_file->tlink); - offset = *poffset; if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) pid = open_file->pid; else pid = current->tgid; - iov_iter_init(&it, iov, nr_segs, len, 0); - do { - size_t save_len; - - nr_pages = get_numpages(cifs_sb->wsize, len, &cur_len); - wdata = cifs_writedata_alloc(nr_pages, - cifs_uncached_writev_complete); - if (!wdata) { - rc = -ENOMEM; - break; - } + pTcon = tlink_tcon(open_file->tlink); + inode = file->f_path.dentry->d_inode; - rc = cifs_write_allocate_pages(wdata->pages, nr_pages); - if (rc) { - kfree(wdata); - break; - } + iov_iter_init(&it, iov, nr_segs, len, 0); + npages = num_pages; - save_len = cur_len; - for (i = 0; i < nr_pages; i++) { - copied = min_t(const size_t, cur_len, PAGE_SIZE); - copied = iov_iter_copy_from_user(wdata->pages[i], &it, - 0, copied); + do { + size_t save_len = cur_len; + for (i = 0; i < npages; i++) { + copied = min_t(const size_t, cur_len, PAGE_CACHE_SIZE); + copied = iov_iter_copy_from_user(pages[i], &it, 0, + copied); cur_len -= copied; iov_iter_advance(&it, copied); + to_send[i+1].iov_base = kmap(pages[i]); + to_send[i+1].iov_len = copied; } + cur_len = save_len - cur_len; - wdata->sync_mode = WB_SYNC_ALL; - wdata->nr_pages = nr_pages; - wdata->offset = (__u64)offset; - wdata->cfile = cifsFileInfo_get(open_file); - wdata->pid = pid; - wdata->bytes = cur_len; - wdata->marshal_iov = cifs_uncached_marshal_iov; - rc = cifs_uncached_retry_writev(wdata); - if (rc) { - kref_put(&wdata->refcount, cifs_writedata_release); + do { + if (open_file->invalidHandle) { + rc = cifs_reopen_file(open_file, false); + if (rc != 0) + break; + } + io_parms.netfid = open_file->netfid; + io_parms.pid = pid; + io_parms.tcon = pTcon; + io_parms.offset = *poffset; + io_parms.length = cur_len; + rc = CIFSSMBWrite2(xid, &io_parms, &written, to_send, + npages, 0); + } while (rc == -EAGAIN); + + for (i = 0; i < npages; i++) + kunmap(pages[i]); + + if (written) { + len -= written; + total_written += written; + cifs_update_eof(CIFS_I(inode), *poffset, written); + *poffset += written; + } else if (rc < 0) { + if (!total_written) + total_written = rc; break; } - list_add_tail(&wdata->list, &wdata_list); - offset += cur_len; - len -= cur_len; + /* get length and number of kvecs of the next write */ + npages = get_numpages(cifs_sb->wsize, len, &cur_len); } while (len > 0); - /* - * If at least one write was successfully sent, then discard any rc - * value from the later writes. If the other write succeeds, then - * we'll end up returning whatever was written. If it fails, then - * we'll get a new rc value from that. - */ - if (!list_empty(&wdata_list)) - rc = 0; - - /* - * Wait for and collect replies for any successful sends in order of - * increasing offset. Once an error is hit or we get a fatal signal - * while waiting, then return without waiting for any more replies. - */ -restart_loop: - list_for_each_entry_safe(wdata, tmp, &wdata_list, list) { - if (!rc) { - /* FIXME: freezable too? */ - rc = wait_for_completion_killable(&wdata->done); - if (rc) - rc = -EINTR; - else if (wdata->result) - rc = wdata->result; - else - total_written += wdata->bytes; - - /* resend call if it's a retryable error */ - if (rc == -EAGAIN) { - rc = cifs_uncached_retry_writev(wdata); - goto restart_loop; - } - } - list_del_init(&wdata->list); - kref_put(&wdata->refcount, cifs_writedata_release); + if (total_written > 0) { + spin_lock(&inode->i_lock); + if (*poffset > inode->i_size) + i_size_write(inode, *poffset); + spin_unlock(&inode->i_lock); } - if (total_written > 0) - *poffset += total_written; + cifs_stats_bytes_written(pTcon, total_written); + mark_inode_dirty_sync(inode); - cifs_stats_bytes_written(tcon, total_written); - return total_written ? total_written : (ssize_t)rc; + for (i = 0; i < num_pages; i++) + put_page(pages[i]); + kfree(to_send); + kfree(pages); + FreeXid(xid); + return total_written; } ssize_t cifs_user_writev(struct kiocb *iocb, const struct iovec *iov, @@ -2355,7 +1708,6 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, struct smb_com_read_rsp *pSMBr; struct cifs_io_parms io_parms; char *read_data; - unsigned int rsize; __u32 pid; if (!nr_segs) @@ -2368,9 +1720,6 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, xid = GetXid(); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - /* FIXME: set up handlers for larger reads and/or convert to async */ - rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize); - open_file = file->private_data; pTcon = tlink_tcon(open_file->tlink); @@ -2383,7 +1732,7 @@ cifs_iovec_read(struct file *file, const struct iovec *iov, cFYI(1, "attempting read on write only file instance"); for (total_read = 0; total_read < len; total_read += bytes_read) { - cur_len = min_t(const size_t, len - total_read, rsize); + cur_len = min_t(const size_t, len - total_read, cifs_sb->rsize); rc = -EAGAIN; read_data = NULL; @@ -2475,7 +1824,6 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, unsigned int bytes_read = 0; unsigned int total_read; unsigned int current_read_size; - unsigned int rsize; struct cifs_sb_info *cifs_sb; struct cifs_tcon *pTcon; int xid; @@ -2488,9 +1836,6 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, xid = GetXid(); cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - /* FIXME: set up handlers for larger reads and/or convert to async */ - rsize = min_t(unsigned int, cifs_sb->rsize, CIFSMaxBufSize); - if (file->private_data == NULL) { rc = -EBADF; FreeXid(xid); @@ -2510,14 +1855,14 @@ static ssize_t cifs_read(struct file *file, char *read_data, size_t read_size, for (total_read = 0, current_offset = read_data; read_size > total_read; total_read += bytes_read, current_offset += bytes_read) { - current_read_size = min_t(uint, read_size - total_read, rsize); - + current_read_size = min_t(const int, read_size - total_read, + cifs_sb->rsize); /* For windows me and 9x we do not want to request more than it negotiated since it will refuse the read then */ if ((pTcon->ses) && !(pTcon->ses->capabilities & CAP_LARGE_FILES)) { - current_read_size = min_t(uint, current_read_size, - CIFSMaxBufSize); + current_read_size = min_t(const int, current_read_size, + pTcon->ses->server->maxBuf - 128); } rc = -EAGAIN; while (rc == -EAGAIN) { @@ -2606,24 +1951,82 @@ int cifs_file_mmap(struct file *file, struct vm_area_struct *vma) return rc; } + +static void cifs_copy_cache_pages(struct address_space *mapping, + struct list_head *pages, int bytes_read, char *data) +{ + struct page *page; + char *target; + + while (bytes_read > 0) { + if (list_empty(pages)) + break; + + page = list_entry(pages->prev, struct page, lru); + list_del(&page->lru); + + if (add_to_page_cache_lru(page, mapping, page->index, + GFP_KERNEL)) { + page_cache_release(page); + cFYI(1, "Add page cache failed"); + data += PAGE_CACHE_SIZE; + bytes_read -= PAGE_CACHE_SIZE; + continue; + } + page_cache_release(page); + + target = kmap_atomic(page); + + if (PAGE_CACHE_SIZE > bytes_read) { + memcpy(target, data, bytes_read); + /* zero the tail end of this partial page */ + memset(target + bytes_read, 0, + PAGE_CACHE_SIZE - bytes_read); + bytes_read = 0; + } else { + memcpy(target, data, PAGE_CACHE_SIZE); + bytes_read -= PAGE_CACHE_SIZE; + } + kunmap_atomic(target); + + flush_dcache_page(page); + SetPageUptodate(page); + unlock_page(page); + data += PAGE_CACHE_SIZE; + + /* add page to FS-Cache */ + cifs_readpage_to_fscache(mapping->host, page); + } + return; +} + static int cifs_readpages(struct file *file, struct address_space *mapping, struct list_head *page_list, unsigned num_pages) { - int rc; - struct list_head tmplist; - struct cifsFileInfo *open_file = file->private_data; - struct cifs_sb_info *cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); - unsigned int rsize = cifs_sb->rsize; - pid_t pid; + int rc = -EACCES; + int xid; + loff_t offset; + struct page *page; + struct cifs_sb_info *cifs_sb; + struct cifs_tcon *pTcon; + unsigned int bytes_read = 0; + unsigned int read_size, i; + char *smb_read_data = NULL; + struct smb_com_read_rsp *pSMBr; + struct cifsFileInfo *open_file; + struct cifs_io_parms io_parms; + int buf_type = CIFS_NO_BUFFER; + __u32 pid; - /* - * Give up immediately if rsize is too small to read an entire page. - * The VFS will fall back to readpage. We should never reach this - * point however since we set ra_pages to 0 when the rsize is smaller - * than a cache page. - */ - if (unlikely(rsize < PAGE_CACHE_SIZE)) - return 0; + xid = GetXid(); + if (file->private_data == NULL) { + rc = -EBADF; + FreeXid(xid); + return rc; + } + open_file = file->private_data; + cifs_sb = CIFS_SB(file->f_path.dentry->d_sb); + pTcon = tlink_tcon(open_file->tlink); /* * Reads as many pages as possible from fscache. Returns -ENOBUFS @@ -2632,127 +2035,125 @@ static int cifs_readpages(struct file *file, struct address_space *mapping, rc = cifs_readpages_from_fscache(mapping->host, mapping, page_list, &num_pages); if (rc == 0) - return rc; + goto read_complete; + cFYI(DBG2, "rpages: num pages %d", num_pages); if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_RWPIDFORWARD) pid = open_file->pid; else pid = current->tgid; - rc = 0; - INIT_LIST_HEAD(&tmplist); - - cFYI(1, "%s: file=%p mapping=%p num_pages=%u", __func__, file, - mapping, num_pages); - - /* - * Start with the page at end of list and move it to private - * list. Do the same with any following pages until we hit - * the rsize limit, hit an index discontinuity, or run out of - * pages. Issue the async read and then start the loop again - * until the list is empty. - * - * Note that list order is important. The page_list is in - * the order of declining indexes. When we put the pages in - * the rdata->pages, then we want them in increasing order. - */ - while (!list_empty(page_list)) { - unsigned int bytes = PAGE_CACHE_SIZE; - unsigned int expected_index; - unsigned int nr_pages = 1; - loff_t offset; - struct page *page, *tpage; - struct cifs_readdata *rdata; - - page = list_entry(page_list->prev, struct page, lru); - - /* - * Lock the page and put it in the cache. Since no one else - * should have access to this page, we're safe to simply set - * PG_locked without checking it first. - */ - __set_page_locked(page); - rc = add_to_page_cache_locked(page, mapping, - page->index, GFP_KERNEL); + for (i = 0; i < num_pages; ) { + unsigned contig_pages; + struct page *tmp_page; + unsigned long expected_index; - /* give up if we can't stick it in the cache */ - if (rc) { - __clear_page_locked(page); + if (list_empty(page_list)) break; - } - /* move first page to the tmplist */ + page = list_entry(page_list->prev, struct page, lru); offset = (loff_t)page->index << PAGE_CACHE_SHIFT; - list_move_tail(&page->lru, &tmplist); - - /* now try and add more pages onto the request */ - expected_index = page->index + 1; - list_for_each_entry_safe_reverse(page, tpage, page_list, lru) { - /* discontinuity ? */ - if (page->index != expected_index) - break; - /* would this page push the read over the rsize? */ - if (bytes + PAGE_CACHE_SIZE > rsize) - break; - - __set_page_locked(page); - if (add_to_page_cache_locked(page, mapping, - page->index, GFP_KERNEL)) { - __clear_page_locked(page); + /* count adjacent pages that we will read into */ + contig_pages = 0; + expected_index = + list_entry(page_list->prev, struct page, lru)->index; + list_for_each_entry_reverse(tmp_page, page_list, lru) { + if (tmp_page->index == expected_index) { + contig_pages++; + expected_index++; + } else break; - } - list_move_tail(&page->lru, &tmplist); - bytes += PAGE_CACHE_SIZE; - expected_index++; - nr_pages++; } - - rdata = cifs_readdata_alloc(nr_pages); - if (!rdata) { - /* best to give up if we're out of mem */ - list_for_each_entry_safe(page, tpage, &tmplist, lru) { - list_del(&page->lru); - lru_cache_add_file(page); - unlock_page(page); - page_cache_release(page); - } - rc = -ENOMEM; - break; - } - - spin_lock(&cifs_file_list_lock); - cifsFileInfo_get(open_file); - spin_unlock(&cifs_file_list_lock); - rdata->cfile = open_file; - rdata->mapping = mapping; - rdata->offset = offset; - rdata->bytes = bytes; - rdata->pid = pid; - list_splice_init(&tmplist, &rdata->pages); - - do { + if (contig_pages + i > num_pages) + contig_pages = num_pages - i; + + /* for reads over a certain size could initiate async + read ahead */ + + read_size = contig_pages * PAGE_CACHE_SIZE; + /* Read size needs to be in multiples of one page */ + read_size = min_t(const unsigned int, read_size, + cifs_sb->rsize & PAGE_CACHE_MASK); + cFYI(DBG2, "rpages: read size 0x%x contiguous pages %d", + read_size, contig_pages); + rc = -EAGAIN; + while (rc == -EAGAIN) { if (open_file->invalidHandle) { rc = cifs_reopen_file(open_file, true); if (rc != 0) - continue; + break; } - rc = cifs_async_readv(rdata); - } while (rc == -EAGAIN); + io_parms.netfid = open_file->netfid; + io_parms.pid = pid; + io_parms.tcon = pTcon; + io_parms.offset = offset; + io_parms.length = read_size; + rc = CIFSSMBRead(xid, &io_parms, &bytes_read, + &smb_read_data, &buf_type); + /* BB more RC checks ? */ + if (rc == -EAGAIN) { + if (smb_read_data) { + if (buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(smb_read_data); + else if (buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(smb_read_data); + smb_read_data = NULL; + } + } + } + if ((rc < 0) || (smb_read_data == NULL)) { + cFYI(1, "Read error in readpages: %d", rc); + break; + } else if (bytes_read > 0) { + task_io_account_read(bytes_read); + pSMBr = (struct smb_com_read_rsp *)smb_read_data; + cifs_copy_cache_pages(mapping, page_list, bytes_read, + smb_read_data + 4 /* RFC1001 hdr */ + + le16_to_cpu(pSMBr->DataOffset)); + + i += bytes_read >> PAGE_CACHE_SHIFT; + cifs_stats_bytes_read(pTcon, bytes_read); + if ((bytes_read & PAGE_CACHE_MASK) != bytes_read) { + i++; /* account for partial page */ - if (rc != 0) { - list_for_each_entry_safe(page, tpage, &rdata->pages, - lru) { - list_del(&page->lru); - lru_cache_add_file(page); - unlock_page(page); - page_cache_release(page); + /* server copy of file can have smaller size + than client */ + /* BB do we need to verify this common case ? + this case is ok - if we are at server EOF + we will hit it on next read */ + + /* break; */ } - cifs_readdata_free(rdata); + } else { + cFYI(1, "No bytes read (%d) at offset %lld . " + "Cleaning remaining pages from readahead list", + bytes_read, offset); + /* BB turn off caching and do new lookup on + file size at server? */ break; } + if (smb_read_data) { + if (buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(smb_read_data); + else if (buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(smb_read_data); + smb_read_data = NULL; + } + bytes_read = 0; + } + +/* need to free smb_read_data buf before exit */ + if (smb_read_data) { + if (buf_type == CIFS_SMALL_BUFFER) + cifs_small_buf_release(smb_read_data); + else if (buf_type == CIFS_LARGE_BUFFER) + cifs_buf_release(smb_read_data); + smb_read_data = NULL; } +read_complete: + FreeXid(xid); return rc; } @@ -3001,10 +2402,6 @@ void cifs_oplock_break(struct work_struct *work) cFYI(1, "Oplock flush inode %p rc %d", inode, rc); } - rc = cifs_push_locks(cfile); - if (rc) - cERROR(1, "Push locks rc = %d", rc); - /* * releasing stale oplock after recent reconnect of smb session using * a now incorrect file handle is not a data integrity issue but do @@ -3012,12 +2409,36 @@ void cifs_oplock_break(struct work_struct *work) * disconnected since oplock already released by the server */ if (!cfile->oplock_break_cancelled) { - rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, - current->tgid, 0, 0, 0, 0, - LOCKING_ANDX_OPLOCK_RELEASE, false, + rc = CIFSSMBLock(0, tlink_tcon(cfile->tlink), cfile->netfid, 0, + 0, 0, 0, LOCKING_ANDX_OPLOCK_RELEASE, false, cinode->clientCanCacheRead ? 1 : 0); cFYI(1, "Oplock release rc = %d", rc); } + + /* + * We might have kicked in before is_valid_oplock_break() + * finished grabbing reference for us. Make sure it's done by + * waiting for cifs_file_list_lock. + */ + spin_lock(&cifs_file_list_lock); + spin_unlock(&cifs_file_list_lock); + + cifs_oplock_break_put(cfile); +} + +/* must be called while holding cifs_file_list_lock */ +void cifs_oplock_break_get(struct cifsFileInfo *cfile) +{ + cifs_sb_active(cfile->dentry->d_sb); + cifsFileInfo_get(cfile); +} + +void cifs_oplock_break_put(struct cifsFileInfo *cfile) +{ + struct super_block *sb = cfile->dentry->d_sb; + + cifsFileInfo_put(cfile); + cifs_sb_deactive(sb); } const struct address_space_operations cifs_addr_ops = { diff --git a/fs/cifs/inode.c b/fs/cifs/inode.c index 745da3d0653..2f3b83cdf54 100644 --- a/fs/cifs/inode.c +++ b/fs/cifs/inode.c @@ -534,11 +534,6 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, if (fattr->cf_cifsattrs & ATTR_DIRECTORY) { fattr->cf_mode = S_IFDIR | cifs_sb->mnt_dir_mode; fattr->cf_dtype = DT_DIR; - /* - * Server can return wrong NumberOfLinks value for directories - * when Unix extensions are disabled - fake it. - */ - fattr->cf_nlink = 2; } else { fattr->cf_mode = S_IFREG | cifs_sb->mnt_file_mode; fattr->cf_dtype = DT_REG; @@ -546,10 +541,10 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info, /* clear write bits if ATTR_READONLY is set */ if (fattr->cf_cifsattrs & ATTR_READONLY) fattr->cf_mode &= ~(S_IWUGO); - - fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); } + fattr->cf_nlink = le32_to_cpu(info->NumberOfLinks); + fattr->cf_uid = cifs_sb->mnt_uid; fattr->cf_gid = cifs_sb->mnt_gid; } @@ -1327,6 +1322,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) } /*BB check (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID ) to see if need to set uid/gid */ + inc_nlink(inode); cifs_unix_basic_to_fattr(&fattr, pInfo, cifs_sb); cifs_fill_uniqueid(inode->i_sb, &fattr); @@ -1359,6 +1355,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) d_drop(direntry); } else { mkdir_get_info: + inc_nlink(inode); if (pTcon->unix_ext) rc = cifs_get_inode_info_unix(&newinode, full_path, inode->i_sb, xid); @@ -1439,11 +1436,6 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, umode_t mode) } } mkdir_out: - /* - * Force revalidate to get parent dir info when needed since cached - * attributes are invalid now. - */ - CIFS_I(inode)->time = 0; kfree(full_path); FreeXid(xid); cifs_put_tlink(tlink); @@ -1483,6 +1475,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) cifs_put_tlink(tlink); if (!rc) { + drop_nlink(inode); spin_lock(&direntry->d_inode->i_lock); i_size_write(direntry->d_inode, 0); clear_nlink(direntry->d_inode); @@ -1490,15 +1483,12 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) } cifsInode = CIFS_I(direntry->d_inode); - /* force revalidate to go get info when needed */ - cifsInode->time = 0; + cifsInode->time = 0; /* force revalidate to go get info when + needed */ cifsInode = CIFS_I(inode); - /* - * Force revalidate to get parent dir info when needed since cached - * attributes are invalid now. - */ - cifsInode->time = 0; + cifsInode->time = 0; /* force revalidate to get parent dir info + since cached search results now invalid */ direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb); @@ -2111,8 +2101,6 @@ static int cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) { int xid; - uid_t uid = NO_CHANGE_32; - gid_t gid = NO_CHANGE_32; struct inode *inode = direntry->d_inode; struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb); struct cifsInodeInfo *cifsInode = CIFS_I(inode); @@ -2163,25 +2151,13 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) goto cifs_setattr_exit; } - if (attrs->ia_valid & ATTR_UID) - uid = attrs->ia_uid; - - if (attrs->ia_valid & ATTR_GID) - gid = attrs->ia_gid; - -#ifdef CONFIG_CIFS_ACL - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - if (uid != NO_CHANGE_32 || gid != NO_CHANGE_32) { - rc = id_mode_to_cifs_acl(inode, full_path, NO_CHANGE_64, - uid, gid); - if (rc) { - cFYI(1, "%s: Setting id failed with error: %d", - __func__, rc); - goto cifs_setattr_exit; - } - } - } else -#endif /* CONFIG_CIFS_ACL */ + /* + * Without unix extensions we can't send ownership changes to the + * server, so silently ignore them. This is consistent with how + * local DOS/Windows filesystems behave (VFAT, NTFS, etc). With + * CIFSACL support + proper Windows to Unix idmapping, we may be + * able to support this in the future. + */ if (!(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) attrs->ia_valid &= ~(ATTR_UID | ATTR_GID); @@ -2190,12 +2166,15 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs) attrs->ia_valid &= ~ATTR_MODE; if (attrs->ia_valid & ATTR_MODE) { + cFYI(1, "Mode changed to 0%o", attrs->ia_mode); mode = attrs->ia_mode; + } + + if (attrs->ia_valid & ATTR_MODE) { rc = 0; #ifdef CONFIG_CIFS_ACL if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) { - rc = id_mode_to_cifs_acl(inode, full_path, mode, - NO_CHANGE_32, NO_CHANGE_32); + rc = mode_to_cifs_acl(inode, full_path, mode); if (rc) { cFYI(1, "%s: Setting ACL failed with error: %d", __func__, rc); diff --git a/fs/cifs/link.c b/fs/cifs/link.c index 6b0e0643439..748f52201ae 100644 --- a/fs/cifs/link.c +++ b/fs/cifs/link.c @@ -74,14 +74,8 @@ symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash) cERROR(1, "%s: Could not init md5 shash\n", __func__); goto symlink_hash_err; } - rc = crypto_shash_update(&sdescmd5->shash, link_str, link_len); - if (rc) { - cERROR(1, "%s: Could not update iwth link_str\n", __func__); - goto symlink_hash_err; - } + crypto_shash_update(&sdescmd5->shash, link_str, link_len); rc = crypto_shash_final(&sdescmd5->shash, md5_hash); - if (rc) - cERROR(1, "%s: Could not generate md5 hash\n", __func__); symlink_hash_err: crypto_free_shash(md5); @@ -183,20 +177,14 @@ CIFSFormatMFSymlink(u8 *buf, unsigned int buf_len, const char *link_str) static int CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, const char *fromName, const char *toName, - struct cifs_sb_info *cifs_sb) + const struct nls_table *nls_codepage, int remap) { int rc; int oplock = 0; - int remap; - int create_options = CREATE_NOT_DIR; __u16 netfid = 0; u8 *buf; unsigned int bytes_written = 0; struct cifs_io_parms io_parms; - struct nls_table *nls_codepage; - - nls_codepage = cifs_sb->local_nls; - remap = cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR; buf = kmalloc(CIFS_MF_SYMLINK_FILE_SIZE, GFP_KERNEL); if (!buf) @@ -208,11 +196,8 @@ CIFSCreateMFSymLink(const int xid, struct cifs_tcon *tcon, return rc; } - if (backup_cred(cifs_sb)) - create_options |= CREATE_OPEN_BACKUP_INTENT; - rc = CIFSSMBOpen(xid, tcon, fromName, FILE_CREATE, GENERIC_WRITE, - create_options, &netfid, &oplock, NULL, + CREATE_NOT_DIR, &netfid, &oplock, NULL, nls_codepage, remap); if (rc != 0) { kfree(buf); @@ -568,7 +553,9 @@ cifs_symlink(struct inode *inode, struct dentry *direntry, const char *symname) /* BB what if DFS and this volume is on different share? BB */ if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MF_SYMLINKS) rc = CIFSCreateMFSymLink(xid, pTcon, full_path, symname, - cifs_sb); + cifs_sb->local_nls, + cifs_sb->mnt_cifs_flags & + CIFS_MOUNT_MAP_SPECIAL_CHR); else if (pTcon->unix_ext) rc = CIFSUnixCreateSymLink(xid, pTcon, full_path, symname, cifs_sb->local_nls); diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c index c29d1aa2c54..03a1f491d39 100644 --- a/fs/cifs/misc.c +++ b/fs/cifs/misc.c @@ -213,62 +213,55 @@ cifs_small_buf_release(void *buf_to_free) } /* - * Find a free multiplex id (SMB mid). Otherwise there could be - * mid collisions which might cause problems, demultiplexing the - * wrong response to this request. Multiplex ids could collide if - * one of a series requests takes much longer than the others, or - * if a very large number of long lived requests (byte range - * locks or FindNotify requests) are pending. No more than - * 64K-1 requests can be outstanding at one time. If no - * mids are available, return zero. A future optimization - * could make the combination of mids and uid the key we use - * to demultiplex on (rather than mid alone). - * In addition to the above check, the cifs demultiplex - * code already used the command code as a secondary - * check of the frame and if signing is negotiated the - * response would be discarded if the mid were the same - * but the signature was wrong. Since the mid is not put in the - * pending queue until later (when it is about to be dispatched) - * we do have to limit the number of outstanding requests - * to somewhat less than 64K-1 although it is hard to imagine - * so many threads being in the vfs at one time. - */ -__u64 GetNextMid(struct TCP_Server_Info *server) + Find a free multiplex id (SMB mid). Otherwise there could be + mid collisions which might cause problems, demultiplexing the + wrong response to this request. Multiplex ids could collide if + one of a series requests takes much longer than the others, or + if a very large number of long lived requests (byte range + locks or FindNotify requests) are pending. No more than + 64K-1 requests can be outstanding at one time. If no + mids are available, return zero. A future optimization + could make the combination of mids and uid the key we use + to demultiplex on (rather than mid alone). + In addition to the above check, the cifs demultiplex + code already used the command code as a secondary + check of the frame and if signing is negotiated the + response would be discarded if the mid were the same + but the signature was wrong. Since the mid is not put in the + pending queue until later (when it is about to be dispatched) + we do have to limit the number of outstanding requests + to somewhat less than 64K-1 although it is hard to imagine + so many threads being in the vfs at one time. +*/ +__u16 GetNextMid(struct TCP_Server_Info *server) { - __u64 mid = 0; - __u16 last_mid, cur_mid; + __u16 mid = 0; + __u16 last_mid; bool collision; spin_lock(&GlobalMid_Lock); - - /* mid is 16 bit only for CIFS/SMB */ - cur_mid = (__u16)((server->CurrentMid) & 0xffff); - /* we do not want to loop forever */ - last_mid = cur_mid; - cur_mid++; - - /* - * This nested loop looks more expensive than it is. - * In practice the list of pending requests is short, - * fewer than 50, and the mids are likely to be unique - * on the first pass through the loop unless some request - * takes longer than the 64 thousand requests before it - * (and it would also have to have been a request that - * did not time out). - */ - while (cur_mid != last_mid) { + last_mid = server->CurrentMid; /* we do not want to loop forever */ + server->CurrentMid++; + /* This nested loop looks more expensive than it is. + In practice the list of pending requests is short, + fewer than 50, and the mids are likely to be unique + on the first pass through the loop unless some request + takes longer than the 64 thousand requests before it + (and it would also have to have been a request that + did not time out) */ + while (server->CurrentMid != last_mid) { struct mid_q_entry *mid_entry; unsigned int num_mids; collision = false; - if (cur_mid == 0) - cur_mid++; + if (server->CurrentMid == 0) + server->CurrentMid++; num_mids = 0; list_for_each_entry(mid_entry, &server->pending_mid_q, qhead) { ++num_mids; - if (mid_entry->mid == cur_mid && - mid_entry->mid_state == MID_REQUEST_SUBMITTED) { + if (mid_entry->mid == server->CurrentMid && + mid_entry->midState == MID_REQUEST_SUBMITTED) { /* This mid is in use, try a different one */ collision = true; break; @@ -289,11 +282,10 @@ __u64 GetNextMid(struct TCP_Server_Info *server) server->tcpStatus = CifsNeedReconnect; if (!collision) { - mid = (__u64)cur_mid; - server->CurrentMid = mid; + mid = server->CurrentMid; break; } - cur_mid++; + server->CurrentMid++; } spin_unlock(&GlobalMid_Lock); return mid; @@ -428,24 +420,19 @@ check_smb_hdr(struct smb_hdr *smb, __u16 mid) } int -checkSMB(char *buf, unsigned int total_read) +checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length) { - struct smb_hdr *smb = (struct smb_hdr *)buf; - __u16 mid = smb->Mid; - __u32 rfclen = be32_to_cpu(smb->smb_buf_length); + __u32 len = be32_to_cpu(smb->smb_buf_length); __u32 clc_len; /* calculated length */ - cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", - total_read, rfclen); + cFYI(0, "checkSMB Length: 0x%x, smb_buf_length: 0x%x", length, len); - /* is this frame too small to even get to a BCC? */ - if (total_read < 2 + sizeof(struct smb_hdr)) { - if ((total_read >= sizeof(struct smb_hdr) - 1) + if (length < 2 + sizeof(struct smb_hdr)) { + if ((length >= sizeof(struct smb_hdr) - 1) && (smb->Status.CifsError != 0)) { - /* it's an error return */ smb->WordCount = 0; /* some error cases do not return wct and bcc */ return 0; - } else if ((total_read == sizeof(struct smb_hdr) + 1) && + } else if ((length == sizeof(struct smb_hdr) + 1) && (smb->WordCount == 0)) { char *tmp = (char *)smb; /* Need to work around a bug in two servers here */ @@ -465,35 +452,39 @@ checkSMB(char *buf, unsigned int total_read) } else { cERROR(1, "Length less than smb header size"); } - return -EIO; + return 1; + } + if (len > CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4) { + cERROR(1, "smb length greater than MaxBufSize, mid=%d", + smb->Mid); + return 1; } - /* otherwise, there is enough to get to the BCC */ if (check_smb_hdr(smb, mid)) - return -EIO; + return 1; clc_len = smbCalcSize(smb); - if (4 + rfclen != total_read) { + if (4 + len != length) { cERROR(1, "Length read does not match RFC1001 length %d", - rfclen); - return -EIO; + len); + return 1; } - if (4 + rfclen != clc_len) { + if (4 + len != clc_len) { /* check if bcc wrapped around for large read responses */ - if ((rfclen > 64 * 1024) && (rfclen > clc_len)) { + if ((len > 64 * 1024) && (len > clc_len)) { /* check if lengths match mod 64K */ - if (((4 + rfclen) & 0xFFFF) == (clc_len & 0xFFFF)) + if (((4 + len) & 0xFFFF) == (clc_len & 0xFFFF)) return 0; /* bcc wrapped */ } cFYI(1, "Calculated size %u vs length %u mismatch for mid=%u", - clc_len, 4 + rfclen, smb->Mid); + clc_len, 4 + len, smb->Mid); - if (4 + rfclen < clc_len) { + if (4 + len < clc_len) { cERROR(1, "RFC1001 size %u smaller than SMB for mid=%u", - rfclen, smb->Mid); - return -EIO; - } else if (rfclen > clc_len + 512) { + len, smb->Mid); + return 1; + } else if (len > clc_len + 512) { /* * Some servers (Windows XP in particular) send more * data than the lengths in the SMB packet would @@ -504,17 +495,16 @@ checkSMB(char *buf, unsigned int total_read) * data to 512 bytes. */ cERROR(1, "RFC1001 size %u more than 512 bytes larger " - "than SMB for mid=%u", rfclen, smb->Mid); - return -EIO; + "than SMB for mid=%u", len, smb->Mid); + return 1; } } return 0; } bool -is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) +is_valid_oplock_break(struct smb_hdr *buf, struct TCP_Server_Info *srv) { - struct smb_hdr *buf = (struct smb_hdr *)buffer; struct smb_com_lock_req *pSMB = (struct smb_com_lock_req *)buf; struct list_head *tmp, *tmp1, *tmp2; struct cifs_ses *ses; @@ -595,8 +585,15 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) cifs_set_oplock_level(pCifsInode, pSMB->OplockLevel ? OPLOCK_READ : 0); - queue_work(cifsiod_wq, - &netfile->oplock_break); + /* + * cifs_oplock_break_put() can't be called + * from here. Get reference after queueing + * succeeded. cifs_oplock_break() will + * synchronize using cifs_file_list_lock. + */ + if (queue_work(system_nrt_wq, + &netfile->oplock_break)) + cifs_oplock_break_get(netfile); netfile->oplock_break_cancelled = false; spin_unlock(&cifs_file_list_lock); @@ -615,15 +612,16 @@ is_valid_oplock_break(char *buffer, struct TCP_Server_Info *srv) } void -dump_smb(void *buf, int smb_buf_length) +dump_smb(struct smb_hdr *smb_buf, int smb_buf_length) { int i, j; char debug_line[17]; - unsigned char *buffer = buf; + unsigned char *buffer; if (traceSMB == 0) return; + buffer = (unsigned char *) smb_buf; for (i = 0, j = 0; i < smb_buf_length; i++, j++) { if (i % 8 == 0) { /* have reached the beginning of line */ @@ -685,37 +683,3 @@ void cifs_set_oplock_level(struct cifsInodeInfo *cinode, __u32 oplock) cinode->clientCanCacheRead = false; } } - -bool -backup_cred(struct cifs_sb_info *cifs_sb) -{ - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPUID) { - if (cifs_sb->mnt_backupuid == current_fsuid()) - return true; - } - if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_BACKUPGID) { - if (in_group_p(cifs_sb->mnt_backupgid)) - return true; - } - - return false; -} - -void -cifs_add_credits(struct TCP_Server_Info *server, const unsigned int add) -{ - spin_lock(&server->req_lock); - server->credits += add; - server->in_flight--; - spin_unlock(&server->req_lock); - wake_up(&server->request_q); -} - -void -cifs_set_credits(struct TCP_Server_Info *server, const int val) -{ - spin_lock(&server->req_lock); - server->credits = val; - server->oplocks = val > 1 ? enable_oplocks : false; - spin_unlock(&server->req_lock); -} diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 581c225f7f5..73e47e84b61 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c @@ -197,7 +197,8 @@ cifs_convert_address(struct sockaddr *dst, const char *src, int len) memcpy(scope_id, pct + 1, slen); scope_id[slen] = '\0'; - rc = kstrtouint(scope_id, 0, &s6->sin6_scope_id); + rc = strict_strtoul(scope_id, 0, + (unsigned long *)&s6->sin6_scope_id); rc = (rc == 0) ? 1 : 0; } @@ -835,9 +836,8 @@ ntstatus_to_dos(__u32 ntstatus, __u8 *eclass, __u16 *ecode) } int -map_smb_to_linux_error(char *buf, bool logErr) +map_smb_to_linux_error(struct smb_hdr *smb, bool logErr) { - struct smb_hdr *smb = (struct smb_hdr *)buf; unsigned int i; int rc = -EIO; /* if transport error smb error may not be set */ __u8 smberrclass; diff --git a/fs/cifs/readdir.c b/fs/cifs/readdir.c index e2bbc683e01..c71032ba5b7 100644 --- a/fs/cifs/readdir.c +++ b/fs/cifs/readdir.c @@ -4,7 +4,6 @@ * Directory search handling * * Copyright (C) International Business Machines Corp., 2004, 2008 - * Copyright (C) Red Hat, Inc., 2011 * Author(s): Steve French (sfrench@us.ibm.com) * * This library is free software; you can redistribute it and/or modify @@ -86,9 +85,12 @@ cifs_readdir_lookup(struct dentry *parent, struct qstr *name, dentry = d_lookup(parent, name); if (dentry) { - /* FIXME: check for inode number changes? */ - if (dentry->d_inode != NULL) + inode = dentry->d_inode; + /* update inode in place if i_ino didn't change */ + if (inode && CIFS_I(inode)->uniqueid == fattr->cf_uniqueid) { + cifs_fattr_to_inode(inode, fattr); return dentry; + } d_drop(dentry); dput(dentry); } @@ -291,10 +293,10 @@ static int initiate_cifs_search(const int xid, struct file *file) } /* return length of unicode string in bytes */ -static int cifs_unicode_bytelen(const char *str) +static int cifs_unicode_bytelen(char *str) { int len; - const __le16 *ustr = (const __le16 *)str; + __le16 *ustr = (__le16 *)str; for (len = 0; len <= PATH_MAX; len++) { if (ustr[len] == 0) @@ -335,128 +337,78 @@ static char *nxt_dir_entry(char *old_entry, char *end_of_smb, int level) } -struct cifs_dirent { - const char *name; - size_t namelen; - u32 resume_key; - u64 ino; -}; - -static void cifs_fill_dirent_unix(struct cifs_dirent *de, - const FILE_UNIX_INFO *info, bool is_unicode) -{ - de->name = &info->FileName[0]; - if (is_unicode) - de->namelen = cifs_unicode_bytelen(de->name); - else - de->namelen = strnlen(de->name, PATH_MAX); - de->resume_key = info->ResumeKey; - de->ino = le64_to_cpu(info->basic.UniqueId); -} - -static void cifs_fill_dirent_dir(struct cifs_dirent *de, - const FILE_DIRECTORY_INFO *info) -{ - de->name = &info->FileName[0]; - de->namelen = le32_to_cpu(info->FileNameLength); - de->resume_key = info->FileIndex; -} - -static void cifs_fill_dirent_full(struct cifs_dirent *de, - const FILE_FULL_DIRECTORY_INFO *info) -{ - de->name = &info->FileName[0]; - de->namelen = le32_to_cpu(info->FileNameLength); - de->resume_key = info->FileIndex; -} - -static void cifs_fill_dirent_search(struct cifs_dirent *de, - const SEARCH_ID_FULL_DIR_INFO *info) -{ - de->name = &info->FileName[0]; - de->namelen = le32_to_cpu(info->FileNameLength); - de->resume_key = info->FileIndex; - de->ino = le64_to_cpu(info->UniqueId); -} - -static void cifs_fill_dirent_both(struct cifs_dirent *de, - const FILE_BOTH_DIRECTORY_INFO *info) -{ - de->name = &info->FileName[0]; - de->namelen = le32_to_cpu(info->FileNameLength); - de->resume_key = info->FileIndex; -} - -static void cifs_fill_dirent_std(struct cifs_dirent *de, - const FIND_FILE_STANDARD_INFO *info) -{ - de->name = &info->FileName[0]; - /* one byte length, no endianess conversion */ - de->namelen = info->FileNameLength; - de->resume_key = info->ResumeKey; -} - -static int cifs_fill_dirent(struct cifs_dirent *de, const void *info, - u16 level, bool is_unicode) -{ - memset(de, 0, sizeof(*de)); - - switch (level) { - case SMB_FIND_FILE_UNIX: - cifs_fill_dirent_unix(de, info, is_unicode); - break; - case SMB_FIND_FILE_DIRECTORY_INFO: - cifs_fill_dirent_dir(de, info); - break; - case SMB_FIND_FILE_FULL_DIRECTORY_INFO: - cifs_fill_dirent_full(de, info); - break; - case SMB_FIND_FILE_ID_FULL_DIR_INFO: - cifs_fill_dirent_search(de, info); - break; - case SMB_FIND_FILE_BOTH_DIRECTORY_INFO: - cifs_fill_dirent_both(de, info); - break; - case SMB_FIND_FILE_INFO_STANDARD: - cifs_fill_dirent_std(de, info); - break; - default: - cFYI(1, "Unknown findfirst level %d", level); - return -EINVAL; - } - - return 0; -} - #define UNICODE_DOT cpu_to_le16(0x2e) /* return 0 if no match and 1 for . (current directory) and 2 for .. (parent) */ -static int cifs_entry_is_dot(struct cifs_dirent *de, bool is_unicode) +static int cifs_entry_is_dot(char *current_entry, struct cifsFileInfo *cfile) { int rc = 0; - - if (!de->name) - return 0; - - if (is_unicode) { - __le16 *ufilename = (__le16 *)de->name; - if (de->namelen == 2) { - /* check for . */ - if (ufilename[0] == UNICODE_DOT) - rc = 1; - } else if (de->namelen == 4) { - /* check for .. */ - if (ufilename[0] == UNICODE_DOT && - ufilename[1] == UNICODE_DOT) - rc = 2; + char *filename = NULL; + int len = 0; + + if (cfile->srch_inf.info_level == SMB_FIND_FILE_UNIX) { + FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry; + filename = &pFindData->FileName[0]; + if (cfile->srch_inf.unicode) { + len = cifs_unicode_bytelen(filename); + } else { + /* BB should we make this strnlen of PATH_MAX? */ + len = strnlen(filename, 5); } - } else /* ASCII */ { - if (de->namelen == 1) { - if (de->name[0] == '.') - rc = 1; - } else if (de->namelen == 2) { - if (de->name[0] == '.' && de->name[1] == '.') - rc = 2; + } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_DIRECTORY_INFO) { + FILE_DIRECTORY_INFO *pFindData = + (FILE_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + } else if (cfile->srch_inf.info_level == + SMB_FIND_FILE_FULL_DIRECTORY_INFO) { + FILE_FULL_DIRECTORY_INFO *pFindData = + (FILE_FULL_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + } else if (cfile->srch_inf.info_level == + SMB_FIND_FILE_ID_FULL_DIR_INFO) { + SEARCH_ID_FULL_DIR_INFO *pFindData = + (SEARCH_ID_FULL_DIR_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + } else if (cfile->srch_inf.info_level == + SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { + FILE_BOTH_DIRECTORY_INFO *pFindData = + (FILE_BOTH_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + } else if (cfile->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) { + FIND_FILE_STANDARD_INFO *pFindData = + (FIND_FILE_STANDARD_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = pFindData->FileNameLength; + } else { + cFYI(1, "Unknown findfirst level %d", + cfile->srch_inf.info_level); + } + + if (filename) { + if (cfile->srch_inf.unicode) { + __le16 *ufilename = (__le16 *)filename; + if (len == 2) { + /* check for . */ + if (ufilename[0] == UNICODE_DOT) + rc = 1; + } else if (len == 4) { + /* check for .. */ + if ((ufilename[0] == UNICODE_DOT) + && (ufilename[1] == UNICODE_DOT)) + rc = 2; + } + } else /* ASCII */ { + if (len == 1) { + if (filename[0] == '.') + rc = 1; + } else if (len == 2) { + if ((filename[0] == '.') && (filename[1] == '.')) + rc = 2; + } } } @@ -478,18 +430,66 @@ static int is_dir_changed(struct file *file) } static int cifs_save_resume_key(const char *current_entry, - struct cifsFileInfo *file_info) + struct cifsFileInfo *cifsFile) { - struct cifs_dirent de; - int rc; + int rc = 0; + unsigned int len = 0; + __u16 level; + char *filename; - rc = cifs_fill_dirent(&de, current_entry, file_info->srch_inf.info_level, - file_info->srch_inf.unicode); - if (!rc) { - file_info->srch_inf.presume_name = de.name; - file_info->srch_inf.resume_name_len = de.namelen; - file_info->srch_inf.resume_key = de.resume_key; + if ((cifsFile == NULL) || (current_entry == NULL)) + return -EINVAL; + + level = cifsFile->srch_inf.info_level; + + if (level == SMB_FIND_FILE_UNIX) { + FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry; + + filename = &pFindData->FileName[0]; + if (cifsFile->srch_inf.unicode) { + len = cifs_unicode_bytelen(filename); + } else { + /* BB should we make this strnlen of PATH_MAX? */ + len = strnlen(filename, PATH_MAX); + } + cifsFile->srch_inf.resume_key = pFindData->ResumeKey; + } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { + FILE_DIRECTORY_INFO *pFindData = + (FILE_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + cifsFile->srch_inf.resume_key = pFindData->FileIndex; + } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { + FILE_FULL_DIRECTORY_INFO *pFindData = + (FILE_FULL_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + cifsFile->srch_inf.resume_key = pFindData->FileIndex; + } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { + SEARCH_ID_FULL_DIR_INFO *pFindData = + (SEARCH_ID_FULL_DIR_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + cifsFile->srch_inf.resume_key = pFindData->FileIndex; + } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { + FILE_BOTH_DIRECTORY_INFO *pFindData = + (FILE_BOTH_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + cifsFile->srch_inf.resume_key = pFindData->FileIndex; + } else if (level == SMB_FIND_FILE_INFO_STANDARD) { + FIND_FILE_STANDARD_INFO *pFindData = + (FIND_FILE_STANDARD_INFO *)current_entry; + filename = &pFindData->FileName[0]; + /* one byte length, no name conversion */ + len = (unsigned int)pFindData->FileNameLength; + cifsFile->srch_inf.resume_key = pFindData->ResumeKey; + } else { + cFYI(1, "Unknown findfirst level %d", level); + return -EINVAL; } + cifsFile->srch_inf.resume_name_len = len; + cifsFile->srch_inf.presume_name = filename; return rc; } @@ -554,10 +554,7 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, rc); return rc; } - /* FindFirst/Next set last_entry to NULL on malformed reply */ - if (cifsFile->srch_inf.last_entry) - cifs_save_resume_key(cifsFile->srch_inf.last_entry, - cifsFile); + cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); } while ((index_to_find >= cifsFile->srch_inf.index_of_last_entry) && @@ -565,10 +562,7 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, cFYI(1, "calling findnext2"); rc = CIFSFindNext(xid, pTcon, cifsFile->netfid, &cifsFile->srch_inf); - /* FindFirst/Next set last_entry to NULL on malformed reply */ - if (cifsFile->srch_inf.last_entry) - cifs_save_resume_key(cifsFile->srch_inf.last_entry, - cifsFile); + cifs_save_resume_key(cifsFile->srch_inf.last_entry, cifsFile); if (rc) return -ENOENT; } @@ -614,71 +608,136 @@ static int find_cifs_entry(const int xid, struct cifs_tcon *pTcon, return rc; } -static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, - void *dirent, char *scratch_buf, unsigned int max_len) +/* inode num, inode type and filename returned */ +static int cifs_get_name_from_search_buf(struct qstr *pqst, + char *current_entry, __u16 level, unsigned int unicode, + struct cifs_sb_info *cifs_sb, unsigned int max_len, __u64 *pinum) { - struct cifsFileInfo *file_info = file->private_data; - struct super_block *sb = file->f_path.dentry->d_sb; - struct cifs_sb_info *cifs_sb = CIFS_SB(sb); - struct cifs_dirent de = { NULL, }; - struct cifs_fattr fattr; - struct dentry *dentry; - struct qstr name; int rc = 0; - ino_t ino; + unsigned int len = 0; + char *filename; + struct nls_table *nlt = cifs_sb->local_nls; - rc = cifs_fill_dirent(&de, find_entry, file_info->srch_inf.info_level, - file_info->srch_inf.unicode); - if (rc) - return rc; + *pinum = 0; - if (de.namelen > max_len) { - cERROR(1, "bad search response length %zd past smb end", - de.namelen); + if (level == SMB_FIND_FILE_UNIX) { + FILE_UNIX_INFO *pFindData = (FILE_UNIX_INFO *)current_entry; + + filename = &pFindData->FileName[0]; + if (unicode) { + len = cifs_unicode_bytelen(filename); + } else { + /* BB should we make this strnlen of PATH_MAX? */ + len = strnlen(filename, PATH_MAX); + } + + *pinum = le64_to_cpu(pFindData->basic.UniqueId); + } else if (level == SMB_FIND_FILE_DIRECTORY_INFO) { + FILE_DIRECTORY_INFO *pFindData = + (FILE_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + } else if (level == SMB_FIND_FILE_FULL_DIRECTORY_INFO) { + FILE_FULL_DIRECTORY_INFO *pFindData = + (FILE_FULL_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + } else if (level == SMB_FIND_FILE_ID_FULL_DIR_INFO) { + SEARCH_ID_FULL_DIR_INFO *pFindData = + (SEARCH_ID_FULL_DIR_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + *pinum = le64_to_cpu(pFindData->UniqueId); + } else if (level == SMB_FIND_FILE_BOTH_DIRECTORY_INFO) { + FILE_BOTH_DIRECTORY_INFO *pFindData = + (FILE_BOTH_DIRECTORY_INFO *)current_entry; + filename = &pFindData->FileName[0]; + len = le32_to_cpu(pFindData->FileNameLength); + } else if (level == SMB_FIND_FILE_INFO_STANDARD) { + FIND_FILE_STANDARD_INFO *pFindData = + (FIND_FILE_STANDARD_INFO *)current_entry; + filename = &pFindData->FileName[0]; + /* one byte length, no name conversion */ + len = (unsigned int)pFindData->FileNameLength; + } else { + cFYI(1, "Unknown findfirst level %d", level); return -EINVAL; } - /* skip . and .. since we added them first */ - if (cifs_entry_is_dot(&de, file_info->srch_inf.unicode)) - return 0; - - if (file_info->srch_inf.unicode) { - struct nls_table *nlt = cifs_sb->local_nls; + if (len > max_len) { + cERROR(1, "bad search response length %d past smb end", len); + return -EINVAL; + } - name.name = scratch_buf; - name.len = - cifs_from_utf16((char *)name.name, (__le16 *)de.name, - UNICODE_NAME_MAX, - min_t(size_t, de.namelen, - (size_t)max_len), nlt, - cifs_sb->mnt_cifs_flags & + if (unicode) { + pqst->len = cifs_from_ucs2((char *) pqst->name, + (__le16 *) filename, + UNICODE_NAME_MAX, + min(len, max_len), nlt, + cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - name.len -= nls_nullsize(nlt); + pqst->len -= nls_nullsize(nlt); } else { - name.name = de.name; - name.len = de.namelen; + pqst->name = filename; + pqst->len = len; } + return rc; +} + +static int cifs_filldir(char *pfindEntry, struct file *file, filldir_t filldir, + void *direntry, char *scratch_buf, unsigned int max_len) +{ + int rc = 0; + struct qstr qstring; + struct cifsFileInfo *pCifsF; + u64 inum; + ino_t ino; + struct super_block *sb; + struct cifs_sb_info *cifs_sb; + struct dentry *tmp_dentry; + struct cifs_fattr fattr; + + /* get filename and len into qstring */ + /* get dentry */ + /* decide whether to create and populate ionde */ + if ((direntry == NULL) || (file == NULL)) + return -EINVAL; + + pCifsF = file->private_data; + + if ((scratch_buf == NULL) || (pfindEntry == NULL) || (pCifsF == NULL)) + return -ENOENT; + + rc = cifs_entry_is_dot(pfindEntry, pCifsF); + /* skip . and .. since we added them first */ + if (rc != 0) + return 0; + + sb = file->f_path.dentry->d_sb; + cifs_sb = CIFS_SB(sb); + + qstring.name = scratch_buf; + rc = cifs_get_name_from_search_buf(&qstring, pfindEntry, + pCifsF->srch_inf.info_level, + pCifsF->srch_inf.unicode, cifs_sb, + max_len, &inum /* returned */); + + if (rc) + return rc; - switch (file_info->srch_inf.info_level) { - case SMB_FIND_FILE_UNIX: + if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_UNIX) cifs_unix_basic_to_fattr(&fattr, - &((FILE_UNIX_INFO *)find_entry)->basic, - cifs_sb); - break; - case SMB_FIND_FILE_INFO_STANDARD: - cifs_std_info_to_fattr(&fattr, - (FIND_FILE_STANDARD_INFO *)find_entry, - cifs_sb); - break; - default: - cifs_dir_info_to_fattr(&fattr, - (FILE_DIRECTORY_INFO *)find_entry, - cifs_sb); - break; - } + &((FILE_UNIX_INFO *) pfindEntry)->basic, + cifs_sb); + else if (pCifsF->srch_inf.info_level == SMB_FIND_FILE_INFO_STANDARD) + cifs_std_info_to_fattr(&fattr, (FIND_FILE_STANDARD_INFO *) + pfindEntry, cifs_sb); + else + cifs_dir_info_to_fattr(&fattr, (FILE_DIRECTORY_INFO *) + pfindEntry, cifs_sb); - if (de.ino && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { - fattr.cf_uniqueid = de.ino; + if (inum && (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SERVER_INUM)) { + fattr.cf_uniqueid = inum; } else { fattr.cf_uniqueid = iunique(sb, ROOT_I); cifs_autodisable_serverino(cifs_sb); @@ -694,12 +753,12 @@ static int cifs_filldir(char *find_entry, struct file *file, filldir_t filldir, fattr.cf_flags |= CIFS_FATTR_NEED_REVAL; ino = cifs_uniqueid_to_ino_t(fattr.cf_uniqueid); - dentry = cifs_readdir_lookup(file->f_dentry, &name, &fattr); + tmp_dentry = cifs_readdir_lookup(file->f_dentry, &qstring, &fattr); - rc = filldir(dirent, name.name, name.len, file->f_pos, ino, - fattr.cf_dtype); + rc = filldir(direntry, qstring.name, qstring.len, file->f_pos, + ino, fattr.cf_dtype); - dput(dentry); + dput(tmp_dentry); return rc; } @@ -740,7 +799,7 @@ int cifs_readdir(struct file *file, void *direntry, filldir_t filldir) file->f_pos++; case 1: if (filldir(direntry, "..", 2, file->f_pos, - parent_ino(file->f_path.dentry), DT_DIR) < 0) { + file->f_path.dentry->d_parent->d_inode->i_ino, DT_DIR) < 0) { cERROR(1, "Filldir for parent dir failed"); rc = -ENOMEM; break; diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index 551d0c2b973..0cfae19129b 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -124,9 +124,7 @@ static __u32 cifs_ssetup_hdr(struct cifs_ses *ses, SESSION_SETUP_ANDX *pSMB) /* that we use in next few lines */ /* Note that header is initialized to zero in header_assemble */ pSMB->req.AndXCommand = 0xFF; - pSMB->req.MaxBufferSize = cpu_to_le16(min_t(u32, - CIFSMaxBufSize + MAX_CIFS_HDR_SIZE - 4, - USHRT_MAX)); + pSMB->req.MaxBufferSize = cpu_to_le16(ses->server->maxBuf); pSMB->req.MaxMpxCount = cpu_to_le16(ses->server->maxReq); pSMB->req.VcNumber = get_next_vcnum(ses); @@ -167,16 +165,16 @@ unicode_oslm_strings(char **pbcc_area, const struct nls_table *nls_cp) int bytes_ret = 0; /* Copy OS version */ - bytes_ret = cifs_strtoUTF16((__le16 *)bcc_ptr, "Linux version ", 32, - nls_cp); + bytes_ret = cifs_strtoUCS((__le16 *)bcc_ptr, "Linux version ", 32, + nls_cp); bcc_ptr += 2 * bytes_ret; - bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, init_utsname()->release, - 32, nls_cp); + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, init_utsname()->release, + 32, nls_cp); bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* trailing null */ - bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, - 32, nls_cp); + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, CIFS_NETWORK_OPSYS, + 32, nls_cp); bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* trailing null */ @@ -197,8 +195,8 @@ static void unicode_domain_string(char **pbcc_area, struct cifs_ses *ses, *(bcc_ptr+1) = 0; bytes_ret = 0; } else - bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->domainName, - 256, nls_cp); + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->domainName, + 256, nls_cp); bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* account for null terminator */ @@ -226,8 +224,8 @@ static void unicode_ssetup_strings(char **pbcc_area, struct cifs_ses *ses, *bcc_ptr = 0; *(bcc_ptr+1) = 0; } else { - bytes_ret = cifs_strtoUTF16((__le16 *) bcc_ptr, ses->user_name, - MAX_USERNAME_SIZE, nls_cp); + bytes_ret = cifs_strtoUCS((__le16 *) bcc_ptr, ses->user_name, + MAX_USERNAME_SIZE, nls_cp); } bcc_ptr += 2 * bytes_ret; bcc_ptr += 2; /* account for null termination */ @@ -286,7 +284,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, cFYI(1, "bleft %d", bleft); kfree(ses->serverOS); - ses->serverOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp); + ses->serverOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); cFYI(1, "serverOS=%s", ses->serverOS); len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; data += len; @@ -295,7 +293,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, return; kfree(ses->serverNOS); - ses->serverNOS = cifs_strndup_from_utf16(data, bleft, true, nls_cp); + ses->serverNOS = cifs_strndup_from_ucs(data, bleft, true, nls_cp); cFYI(1, "serverNOS=%s", ses->serverNOS); len = (UniStrnlen((wchar_t *) data, bleft / 2) * 2) + 2; data += len; @@ -304,7 +302,7 @@ decode_unicode_ssetup(char **pbcc_area, int bleft, struct cifs_ses *ses, return; kfree(ses->serverDomain); - ses->serverDomain = cifs_strndup_from_utf16(data, bleft, true, nls_cp); + ses->serverDomain = cifs_strndup_from_ucs(data, bleft, true, nls_cp); cFYI(1, "serverDomain=%s", ses->serverDomain); return; @@ -394,10 +392,6 @@ static int decode_ntlmssp_challenge(char *bcc_ptr, int blob_len, ses->ntlmssp->server_flags = le32_to_cpu(pblob->NegotiateFlags); tioffset = le32_to_cpu(pblob->TargetInfoArray.BufferOffset); tilen = le16_to_cpu(pblob->TargetInfoArray.Length); - if (tioffset > blob_len || tioffset + tilen > blob_len) { - cERROR(1, "tioffset + tilen too high %u + %u", tioffset, tilen); - return -EINVAL; - } if (tilen) { ses->auth_key.response = kmalloc(tilen, GFP_KERNEL); if (!ses->auth_key.response) { @@ -505,8 +499,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, tmp += 2; } else { int len; - len = cifs_strtoUTF16((__le16 *)tmp, ses->domainName, - MAX_USERNAME_SIZE, nls_cp); + len = cifs_strtoUCS((__le16 *)tmp, ses->domainName, + MAX_USERNAME_SIZE, nls_cp); len *= 2; /* unicode is 2 bytes each */ sec_blob->DomainName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->DomainName.Length = cpu_to_le16(len); @@ -521,8 +515,8 @@ static int build_ntlmssp_auth_blob(unsigned char *pbuffer, tmp += 2; } else { int len; - len = cifs_strtoUTF16((__le16 *)tmp, ses->user_name, - MAX_USERNAME_SIZE, nls_cp); + len = cifs_strtoUCS((__le16 *)tmp, ses->user_name, + MAX_USERNAME_SIZE, nls_cp); len *= 2; /* unicode is 2 bytes each */ sec_blob->UserName.BufferOffset = cpu_to_le32(tmp - pbuffer); sec_blob->UserName.Length = cpu_to_le16(len); @@ -686,7 +680,7 @@ CIFS_SessSetup(unsigned int xid, struct cifs_ses *ses, cpu_to_le16(CIFS_AUTH_RESP_SIZE); /* calculate ntlm response and session key */ - rc = setup_ntlm_response(ses, nls_cp); + rc = setup_ntlm_response(ses); if (rc) { cERROR(1, "Error %d during NTLM authentication", rc); goto ssetup_exit; diff --git a/fs/cifs/smbencrypt.c b/fs/cifs/smbencrypt.c index d5cd9aa7eac..1c5b770c314 100644 --- a/fs/cifs/smbencrypt.c +++ b/fs/cifs/smbencrypt.c @@ -157,14 +157,8 @@ mdfour(unsigned char *md4_hash, unsigned char *link_str, int link_len) cERROR(1, "%s: Could not init md4 shash\n", __func__); goto mdfour_err; } - rc = crypto_shash_update(&sdescmd4->shash, link_str, link_len); - if (rc) { - cERROR(1, "%s: Could not update with link_str\n", __func__); - goto mdfour_err; - } + crypto_shash_update(&sdescmd4->shash, link_str, link_len); rc = crypto_shash_final(&sdescmd4->shash, md4_hash); - if (rc) - cERROR(1, "%s: Could not genereate md4 hash\n", __func__); mdfour_err: crypto_free_shash(md4); @@ -199,36 +193,160 @@ SMBencrypt(unsigned char *passwd, const unsigned char *c8, unsigned char *p24) return rc; } +/* Routines for Windows NT MD4 Hash functions. */ +static int +_my_wcslen(__u16 *str) +{ + int len = 0; + while (*str++ != 0) + len++; + return len; +} + +/* + * Convert a string into an NT UNICODE string. + * Note that regardless of processor type + * this must be in intel (little-endian) + * format. + */ + +static int +_my_mbstowcs(__u16 *dst, const unsigned char *src, int len) +{ /* BB not a very good conversion routine - change/fix */ + int i; + __u16 val; + + for (i = 0; i < len; i++) { + val = *src; + SSVAL(dst, 0, val); + dst++; + src++; + if (val == 0) + break; + } + return i; +} + /* * Creates the MD4 Hash of the users password in NT UNICODE. */ int -E_md4hash(const unsigned char *passwd, unsigned char *p16, - const struct nls_table *codepage) +E_md4hash(const unsigned char *passwd, unsigned char *p16) { int rc; int len; - __le16 wpwd[129]; + __u16 wpwd[129]; /* Password cannot be longer than 128 characters */ - if (passwd) /* Password must be converted to NT unicode */ - len = cifs_strtoUTF16(wpwd, passwd, 128, codepage); - else { + if (passwd) { + len = strlen((char *) passwd); + if (len > 128) + len = 128; + + /* Password must be converted to NT unicode */ + _my_mbstowcs(wpwd, passwd, len); + } else len = 0; - *wpwd = 0; /* Ensure string is null terminated */ - } - rc = mdfour(p16, (unsigned char *) wpwd, len * sizeof(__le16)); - memset(wpwd, 0, 129 * sizeof(__le16)); + wpwd[len] = 0; /* Ensure string is null terminated */ + /* Calculate length in bytes */ + len = _my_wcslen(wpwd) * sizeof(__u16); + + rc = mdfour(p16, (unsigned char *) wpwd, len); + memset(wpwd, 0, 129 * 2); return rc; } +#if 0 /* currently unused */ +/* Does both the NT and LM owfs of a user's password */ +static void +nt_lm_owf_gen(char *pwd, unsigned char nt_p16[16], unsigned char p16[16]) +{ + char passwd[514]; + + memset(passwd, '\0', 514); + if (strlen(pwd) < 513) + strcpy(passwd, pwd); + else + memcpy(passwd, pwd, 512); + /* Calculate the MD4 hash (NT compatible) of the password */ + memset(nt_p16, '\0', 16); + E_md4hash(passwd, nt_p16); + + /* Mangle the passwords into Lanman format */ + passwd[14] = '\0'; +/* strupper(passwd); */ + + /* Calculate the SMB (lanman) hash functions of the password */ + + memset(p16, '\0', 16); + E_P16((unsigned char *) passwd, (unsigned char *) p16); + + /* clear out local copy of user's password (just being paranoid). */ + memset(passwd, '\0', sizeof(passwd)); +} +#endif + +/* Does the NTLMv2 owfs of a user's password */ +#if 0 /* function not needed yet - but will be soon */ +static void +ntv2_owf_gen(const unsigned char owf[16], const char *user_n, + const char *domain_n, unsigned char kr_buf[16], + const struct nls_table *nls_codepage) +{ + wchar_t *user_u; + wchar_t *dom_u; + int user_l, domain_l; + struct HMACMD5Context ctx; + + /* might as well do one alloc to hold both (user_u and dom_u) */ + user_u = kmalloc(2048 * sizeof(wchar_t), GFP_KERNEL); + if (user_u == NULL) + return; + dom_u = user_u + 1024; + + /* push_ucs2(NULL, user_u, user_n, (user_l+1)*2, + STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); + push_ucs2(NULL, dom_u, domain_n, (domain_l+1)*2, + STR_UNICODE|STR_NOALIGN|STR_TERMINATE|STR_UPPER); */ + + /* BB user and domain may need to be uppercased */ + user_l = cifs_strtoUCS(user_u, user_n, 511, nls_codepage); + domain_l = cifs_strtoUCS(dom_u, domain_n, 511, nls_codepage); + + user_l++; /* trailing null */ + domain_l++; + + hmac_md5_init_limK_to_64(owf, 16, &ctx); + hmac_md5_update((const unsigned char *) user_u, user_l * 2, &ctx); + hmac_md5_update((const unsigned char *) dom_u, domain_l * 2, &ctx); + hmac_md5_final(kr_buf, &ctx); + + kfree(user_u); +} +#endif + +/* Does the des encryption from the FIRST 8 BYTES of the NT or LM MD4 hash. */ +#if 0 /* currently unused */ +static void +NTLMSSPOWFencrypt(unsigned char passwd[8], + unsigned char *ntlmchalresp, unsigned char p24[24]) +{ + unsigned char p21[21]; + + memset(p21, '\0', 21); + memcpy(p21, passwd, 8); + memset(p21 + 8, 0xbd, 8); + + E_P24(p21, ntlmchalresp, p24); +} +#endif + /* Does the NT MD4 hash then des encryption. */ int -SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24, - const struct nls_table *codepage) +SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24) { int rc; unsigned char p16[16], p21[21]; @@ -236,7 +354,7 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24, memset(p16, '\0', 16); memset(p21, '\0', 21); - rc = E_md4hash(passwd, p16, codepage); + rc = E_md4hash(passwd, p16); if (rc) { cFYI(1, "%s Can't generate NT hash, error: %d", __func__, rc); return rc; @@ -245,3 +363,39 @@ SMBNTencrypt(unsigned char *passwd, unsigned char *c8, unsigned char *p24, rc = E_P24(p21, c8, p24); return rc; } + + +/* Does the md5 encryption from the NT hash for NTLMv2. */ +/* These routines will be needed later */ +#if 0 +static void +SMBOWFencrypt_ntv2(const unsigned char kr[16], + const struct data_blob *srv_chal, + const struct data_blob *cli_chal, unsigned char resp_buf[16]) +{ + struct HMACMD5Context ctx; + + hmac_md5_init_limK_to_64(kr, 16, &ctx); + hmac_md5_update(srv_chal->data, srv_chal->length, &ctx); + hmac_md5_update(cli_chal->data, cli_chal->length, &ctx); + hmac_md5_final(resp_buf, &ctx); +} + +static void +SMBsesskeygen_ntv2(const unsigned char kr[16], + const unsigned char *nt_resp, __u8 sess_key[16]) +{ + struct HMACMD5Context ctx; + + hmac_md5_init_limK_to_64(kr, 16, &ctx); + hmac_md5_update(nt_resp, 16, &ctx); + hmac_md5_final((unsigned char *) sess_key, &ctx); +} + +static void +SMBsesskeygen_ntv1(const unsigned char kr[16], + const unsigned char *nt_resp, __u8 sess_key[16]) +{ + mdfour((unsigned char *) sess_key, (unsigned char *) kr, 16); +} +#endif diff --git a/fs/cifs/transport.c b/fs/cifs/transport.c index 1607615186c..c1b9c4b1073 100644 --- a/fs/cifs/transport.c +++ b/fs/cifs/transport.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -60,8 +59,8 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) memset(temp, 0, sizeof(struct mid_q_entry)); temp->mid = smb_buffer->Mid; /* always LE */ temp->pid = current->pid; - temp->command = cpu_to_le16(smb_buffer->Command); - cFYI(1, "For smb_command %d", smb_buffer->Command); + temp->command = smb_buffer->Command; + cFYI(1, "For smb_command %d", temp->command); /* do_gettimeofday(&temp->when_sent);*/ /* easier to use jiffies */ /* when mid allocated can be before when sent */ temp->when_alloc = jiffies; @@ -75,7 +74,7 @@ AllocMidQEntry(const struct smb_hdr *smb_buffer, struct TCP_Server_Info *server) } atomic_inc(&midCount); - temp->mid_state = MID_REQUEST_ALLOCATED; + temp->midState = MID_REQUEST_ALLOCATED; return temp; } @@ -85,9 +84,9 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) #ifdef CONFIG_CIFS_STATS2 unsigned long now; #endif - midEntry->mid_state = MID_FREE; + midEntry->midState = MID_FREE; atomic_dec(&midCount); - if (midEntry->large_buf) + if (midEntry->largeBuf) cifs_buf_release(midEntry->resp_buf); else cifs_small_buf_release(midEntry->resp_buf); @@ -97,8 +96,8 @@ DeleteMidQEntry(struct mid_q_entry *midEntry) something is wrong, unless it is quite a slow link or server */ if ((now - midEntry->when_alloc) > HZ) { if ((cifsFYI & CIFS_TIMER) && - (midEntry->command != cpu_to_le16(SMB_COM_LOCKING_ANDX))) { - printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %llu", + (midEntry->command != SMB_COM_LOCKING_ANDX)) { + printk(KERN_DEBUG " CIFS slow rsp: cmd %d mid %d", midEntry->command, midEntry->mid); printk(" A: 0x%lx S: 0x%lx R: 0x%lx\n", now - midEntry->when_alloc, @@ -126,11 +125,11 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) int rc = 0; int i = 0; struct msghdr smb_msg; - __be32 *buf_len = (__be32 *)(iov[0].iov_base); + struct smb_hdr *smb_buffer = iov[0].iov_base; unsigned int len = iov[0].iov_len; unsigned int total_len; int first_vec = 0; - unsigned int smb_buf_length = get_rfc1002_length(iov[0].iov_base); + unsigned int smb_buf_length = be32_to_cpu(smb_buffer->smb_buf_length); struct socket *ssocket = server->ssocket; if (ssocket == NULL) @@ -150,7 +149,7 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) total_len += iov[i].iov_len; cFYI(1, "Sending smb: total_len %d", total_len); - dump_smb(iov[0].iov_base, len); + dump_smb(smb_buffer, len); i = 0; while (total_len) { @@ -158,24 +157,24 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) n_vec - first_vec, total_len); if ((rc == -ENOSPC) || (rc == -EAGAIN)) { i++; - /* - * If blocking send we try 3 times, since each can block - * for 5 seconds. For nonblocking we have to try more - * but wait increasing amounts of time allowing time for - * socket to clear. The overall time we wait in either - * case to send on the socket is about 15 seconds. - * Similarly we wait for 15 seconds for a response from - * the server in SendReceive[2] for the server to send - * a response back for most types of requests (except - * SMB Write past end of file which can be slow, and - * blocking lock operations). NFS waits slightly longer - * than CIFS, but this can make it take longer for - * nonresponsive servers to be detected and 15 seconds - * is more than enough time for modern networks to - * send a packet. In most cases if we fail to send - * after the retries we will kill the socket and - * reconnect which may clear the network problem. - */ + /* if blocking send we try 3 times, since each can block + for 5 seconds. For nonblocking we have to try more + but wait increasing amounts of time allowing time for + socket to clear. The overall time we wait in either + case to send on the socket is about 15 seconds. + Similarly we wait for 15 seconds for + a response from the server in SendReceive[2] + for the server to send a response back for + most types of requests (except SMB Write + past end of file which can be slow, and + blocking lock operations). NFS waits slightly longer + than CIFS, but this can make it take longer for + nonresponsive servers to be detected and 15 seconds + is more than enough time for modern networks to + send a packet. In most cases if we fail to send + after the retries we will kill the socket and + reconnect which may clear the network problem. + */ if ((i >= 14) || (!server->noblocksnd && (i > 2))) { cERROR(1, "sends on sock %p stuck for 15 seconds", ssocket); @@ -235,8 +234,9 @@ smb_sendv(struct TCP_Server_Info *server, struct kvec *iov, int n_vec) else rc = 0; - /* Don't want to modify the buffer as a side effect of this call. */ - *buf_len = cpu_to_be32(smb_buf_length); + /* Don't want to modify the buffer as a + side effect of this call. */ + smb_buffer->smb_buf_length = cpu_to_be32(smb_buf_length); return rc; } @@ -253,60 +253,48 @@ smb_send(struct TCP_Server_Info *server, struct smb_hdr *smb_buffer, return smb_sendv(server, &iov, 1); } -static int -wait_for_free_credits(struct TCP_Server_Info *server, const int optype, - int *credits) +static int wait_for_free_request(struct TCP_Server_Info *server, + const int long_op) { - int rc; - - spin_lock(&server->req_lock); - if (optype == CIFS_ASYNC_OP) { + if (long_op == CIFS_ASYNC_OP) { /* oplock breaks must not be held up */ - server->in_flight++; - *credits -= 1; - spin_unlock(&server->req_lock); + atomic_inc(&server->inFlight); return 0; } + spin_lock(&GlobalMid_Lock); while (1) { - if (*credits <= 0) { - spin_unlock(&server->req_lock); - cifs_num_waiters_inc(server); - rc = wait_event_killable(server->request_q, - has_credits(server, credits)); - cifs_num_waiters_dec(server); - if (rc) - return rc; - spin_lock(&server->req_lock); + if (atomic_read(&server->inFlight) >= cifs_max_pending) { + spin_unlock(&GlobalMid_Lock); +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&server->num_waiters); +#endif + wait_event(server->request_q, + atomic_read(&server->inFlight) + < cifs_max_pending); +#ifdef CONFIG_CIFS_STATS2 + atomic_dec(&server->num_waiters); +#endif + spin_lock(&GlobalMid_Lock); } else { if (server->tcpStatus == CifsExiting) { - spin_unlock(&server->req_lock); + spin_unlock(&GlobalMid_Lock); return -ENOENT; } - /* - * Can not count locking commands against total - * as they are allowed to block on server. - */ + /* can not count locking commands against total + as they are allowed to block on server */ /* update # of requests on the wire to server */ - if (optype != CIFS_BLOCKING_OP) { - *credits -= 1; - server->in_flight++; - } - spin_unlock(&server->req_lock); + if (long_op != CIFS_BLOCKING_OP) + atomic_inc(&server->inFlight); + spin_unlock(&GlobalMid_Lock); break; } } return 0; } -static int -wait_for_free_request(struct TCP_Server_Info *server, const int optype) -{ - return wait_for_free_credits(server, optype, get_credits_field(server)); -} - static int allocate_mid(struct cifs_ses *ses, struct smb_hdr *in_buf, struct mid_q_entry **ppmidQ) { @@ -340,29 +328,44 @@ wait_for_response(struct TCP_Server_Info *server, struct mid_q_entry *midQ) { int error; - error = wait_event_freezekillable(server->response_q, - midQ->mid_state != MID_REQUEST_SUBMITTED); + error = wait_event_killable(server->response_q, + midQ->midState != MID_REQUEST_SUBMITTED); if (error < 0) return -ERESTARTSYS; return 0; } -static int -cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov, - unsigned int nvec, struct mid_q_entry **ret_mid) + +/* + * Send a SMB request and set the callback function in the mid to handle + * the result. Caller is responsible for dealing with timeouts. + */ +int +cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, + unsigned int nvec, mid_callback_t *callback, void *cbdata, + bool ignore_pend) { int rc; - struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; struct mid_q_entry *mid; + struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; + + rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0); + if (rc) + return rc; /* enable signing if server requires it */ if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) hdr->Flags2 |= SMBFLG2_SECURITY_SIGNATURE; + mutex_lock(&server->srv_mutex); mid = AllocMidQEntry(hdr, server); - if (mid == NULL) + if (mid == NULL) { + mutex_unlock(&server->srv_mutex); + atomic_dec(&server->inFlight); + wake_up(&server->request_q); return -ENOMEM; + } /* put it on the pending_mid_q */ spin_lock(&GlobalMid_Lock); @@ -370,55 +373,30 @@ cifs_setup_async_request(struct TCP_Server_Info *server, struct kvec *iov, spin_unlock(&GlobalMid_Lock); rc = cifs_sign_smb2(iov, nvec, server, &mid->sequence_number); - if (rc) - delete_mid(mid); - *ret_mid = mid; - return rc; -} - -/* - * Send a SMB request and set the callback function in the mid to handle - * the result. Caller is responsible for dealing with timeouts. - */ -int -cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, - unsigned int nvec, mid_receive_t *receive, - mid_callback_t *callback, void *cbdata, bool ignore_pend) -{ - int rc; - struct mid_q_entry *mid; - - rc = wait_for_free_request(server, ignore_pend ? CIFS_ASYNC_OP : 0); - if (rc) - return rc; - - mutex_lock(&server->srv_mutex); - rc = cifs_setup_async_request(server, iov, nvec, &mid); if (rc) { mutex_unlock(&server->srv_mutex); - cifs_add_credits(server, 1); - wake_up(&server->request_q); - return rc; + goto out_err; } - mid->receive = receive; mid->callback = callback; mid->callback_data = cbdata; - mid->mid_state = MID_REQUEST_SUBMITTED; - - cifs_in_send_inc(server); + mid->midState = MID_REQUEST_SUBMITTED; +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&server->inSend); +#endif rc = smb_sendv(server, iov, nvec); - cifs_in_send_dec(server); - cifs_save_when_sent(mid); +#ifdef CONFIG_CIFS_STATS2 + atomic_dec(&server->inSend); + mid->when_sent = jiffies; +#endif mutex_unlock(&server->srv_mutex); - if (rc) goto out_err; return rc; out_err: delete_mid(mid); - cifs_add_credits(server, 1); + atomic_dec(&server->inFlight); wake_up(&server->request_q); return rc; } @@ -434,14 +412,14 @@ cifs_call_async(struct TCP_Server_Info *server, struct kvec *iov, */ int SendReceiveNoRsp(const unsigned int xid, struct cifs_ses *ses, - char *in_buf, int flags) + struct smb_hdr *in_buf, int flags) { int rc; struct kvec iov[1]; int resp_buf_type; - iov[0].iov_base = in_buf; - iov[0].iov_len = get_rfc1002_length(in_buf) + 4; + iov[0].iov_base = (char *)in_buf; + iov[0].iov_len = be32_to_cpu(in_buf->smb_buf_length) + 4; flags |= CIFS_NO_RESP; rc = SendReceive2(xid, ses, iov, 1, &resp_buf_type, flags); cFYI(DBG2, "SendRcvNoRsp flags %d rc %d", flags, rc); @@ -454,11 +432,11 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) { int rc = 0; - cFYI(1, "%s: cmd=%d mid=%llu state=%d", __func__, - le16_to_cpu(mid->command), mid->mid, mid->mid_state); + cFYI(1, "%s: cmd=%d mid=%d state=%d", __func__, mid->command, + mid->mid, mid->midState); spin_lock(&GlobalMid_Lock); - switch (mid->mid_state) { + switch (mid->midState) { case MID_RESPONSE_RECEIVED: spin_unlock(&GlobalMid_Lock); return rc; @@ -473,8 +451,8 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server) break; default: list_del_init(&mid->qhead); - cERROR(1, "%s: invalid mid state mid=%llu state=%d", __func__, - mid->mid, mid->mid_state); + cERROR(1, "%s: invalid mid state mid=%d state=%d", __func__, + mid->mid, mid->midState); rc = -EIO; } spin_unlock(&GlobalMid_Lock); @@ -524,18 +502,13 @@ int cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, bool log_error) { - unsigned int len = get_rfc1002_length(mid->resp_buf) + 4; - - dump_smb(mid->resp_buf, min_t(u32, 92, len)); + dump_smb(mid->resp_buf, + min_t(u32, 92, be32_to_cpu(mid->resp_buf->smb_buf_length))); /* convert the length into a more usable form */ if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) { - struct kvec iov; - - iov.iov_base = mid->resp_buf; - iov.iov_len = len; /* FIXME: add code to kill session */ - if (cifs_verify_signature(&iov, 1, server, + if (cifs_verify_signature(mid->resp_buf, server, mid->sequence_number + 1) != 0) cERROR(1, "Unexpected SMB signature"); } @@ -544,24 +517,6 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server, return map_smb_to_linux_error(mid->resp_buf, log_error); } -static int -cifs_setup_request(struct cifs_ses *ses, struct kvec *iov, - unsigned int nvec, struct mid_q_entry **ret_mid) -{ - int rc; - struct smb_hdr *hdr = (struct smb_hdr *)iov[0].iov_base; - struct mid_q_entry *mid; - - rc = allocate_mid(ses, hdr, &mid); - if (rc) - return rc; - rc = cifs_sign_smb2(iov, nvec, ses->server, &mid->sequence_number); - if (rc) - delete_mid(mid); - *ret_mid = mid; - return rc; -} - int SendReceive2(const unsigned int xid, struct cifs_ses *ses, struct kvec *iov, int n_vec, int *pRespBufType /* ret */, @@ -569,103 +524,111 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, { int rc = 0; int long_op; - struct mid_q_entry *midQ = NULL; - char *buf = iov[0].iov_base; + struct mid_q_entry *midQ; + struct smb_hdr *in_buf = iov[0].iov_base; long_op = flags & CIFS_TIMEOUT_MASK; *pRespBufType = CIFS_NO_BUFFER; /* no response buf yet */ if ((ses == NULL) || (ses->server == NULL)) { - cifs_small_buf_release(buf); + cifs_small_buf_release(in_buf); cERROR(1, "Null session"); return -EIO; } if (ses->server->tcpStatus == CifsExiting) { - cifs_small_buf_release(buf); + cifs_small_buf_release(in_buf); return -ENOENT; } - /* - * Ensure that we do not send more than 50 overlapping requests - * to the same server. We may make this configurable later or - * use ses->maxReq. - */ + /* Ensure that we do not send more than 50 overlapping requests + to the same server. We may make this configurable later or + use ses->maxReq */ rc = wait_for_free_request(ses->server, long_op); if (rc) { - cifs_small_buf_release(buf); + cifs_small_buf_release(in_buf); return rc; } - /* - * Make sure that we sign in the same order that we send on this socket - * and avoid races inside tcp sendmsg code that could cause corruption - * of smb data. - */ + /* make sure that we sign in the same order that we send on this socket + and avoid races inside tcp sendmsg code that could cause corruption + of smb data */ mutex_lock(&ses->server->srv_mutex); - rc = cifs_setup_request(ses, iov, n_vec, &midQ); + rc = allocate_mid(ses, in_buf, &midQ); if (rc) { mutex_unlock(&ses->server->srv_mutex); - cifs_small_buf_release(buf); + cifs_small_buf_release(in_buf); /* Update # of requests on wire to server */ - cifs_add_credits(ses->server, 1); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } + rc = cifs_sign_smb2(iov, n_vec, ses->server, &midQ->sequence_number); + if (rc) { + mutex_unlock(&ses->server->srv_mutex); + cifs_small_buf_release(in_buf); + goto out; + } - midQ->mid_state = MID_REQUEST_SUBMITTED; - cifs_in_send_inc(ses->server); + midQ->midState = MID_REQUEST_SUBMITTED; +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&ses->server->inSend); +#endif rc = smb_sendv(ses->server, iov, n_vec); - cifs_in_send_dec(ses->server); - cifs_save_when_sent(midQ); +#ifdef CONFIG_CIFS_STATS2 + atomic_dec(&ses->server->inSend); + midQ->when_sent = jiffies; +#endif mutex_unlock(&ses->server->srv_mutex); if (rc < 0) { - cifs_small_buf_release(buf); + cifs_small_buf_release(in_buf); goto out; } if (long_op == CIFS_ASYNC_OP) { - cifs_small_buf_release(buf); + cifs_small_buf_release(in_buf); goto out; } rc = wait_for_response(ses->server, midQ); if (rc != 0) { - send_nt_cancel(ses->server, (struct smb_hdr *)buf, midQ); + send_nt_cancel(ses->server, in_buf, midQ); spin_lock(&GlobalMid_Lock); - if (midQ->mid_state == MID_REQUEST_SUBMITTED) { + if (midQ->midState == MID_REQUEST_SUBMITTED) { midQ->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); - cifs_small_buf_release(buf); - cifs_add_credits(ses->server, 1); + cifs_small_buf_release(in_buf); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } spin_unlock(&GlobalMid_Lock); } - cifs_small_buf_release(buf); + cifs_small_buf_release(in_buf); rc = cifs_sync_mid_result(midQ, ses->server); if (rc != 0) { - cifs_add_credits(ses->server, 1); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } - if (!midQ->resp_buf || midQ->mid_state != MID_RESPONSE_RECEIVED) { + if (!midQ->resp_buf || midQ->midState != MID_RESPONSE_RECEIVED) { rc = -EIO; cFYI(1, "Bad MID state?"); goto out; } - buf = (char *)midQ->resp_buf; - iov[0].iov_base = buf; - iov[0].iov_len = get_rfc1002_length(buf) + 4; - if (midQ->large_buf) + iov[0].iov_base = (char *)midQ->resp_buf; + iov[0].iov_len = be32_to_cpu(midQ->resp_buf->smb_buf_length) + 4; + if (midQ->largeBuf) *pRespBufType = CIFS_LARGE_BUFFER; else *pRespBufType = CIFS_SMALL_BUFFER; @@ -677,7 +640,8 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses, midQ->resp_buf = NULL; out: delete_mid(midQ); - cifs_add_credits(ses->server, 1); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } @@ -727,7 +691,8 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, if (rc) { mutex_unlock(&ses->server->srv_mutex); /* Update # of requests on wire to server */ - cifs_add_credits(ses->server, 1); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } @@ -737,12 +702,15 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, goto out; } - midQ->mid_state = MID_REQUEST_SUBMITTED; - - cifs_in_send_inc(ses->server); + midQ->midState = MID_REQUEST_SUBMITTED; +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&ses->server->inSend); +#endif rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); - cifs_in_send_dec(ses->server); - cifs_save_when_sent(midQ); +#ifdef CONFIG_CIFS_STATS2 + atomic_dec(&ses->server->inSend); + midQ->when_sent = jiffies; +#endif mutex_unlock(&ses->server->srv_mutex); if (rc < 0) @@ -755,11 +723,12 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, if (rc != 0) { send_nt_cancel(ses->server, in_buf, midQ); spin_lock(&GlobalMid_Lock); - if (midQ->mid_state == MID_REQUEST_SUBMITTED) { + if (midQ->midState == MID_REQUEST_SUBMITTED) { /* no longer considered to be "in-flight" */ midQ->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); - cifs_add_credits(ses->server, 1); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } spin_unlock(&GlobalMid_Lock); @@ -767,23 +736,25 @@ SendReceive(const unsigned int xid, struct cifs_ses *ses, rc = cifs_sync_mid_result(midQ, ses->server); if (rc != 0) { - cifs_add_credits(ses->server, 1); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } if (!midQ->resp_buf || !out_buf || - midQ->mid_state != MID_RESPONSE_RECEIVED) { + midQ->midState != MID_RESPONSE_RECEIVED) { rc = -EIO; cERROR(1, "Bad MID state?"); goto out; } - *pbytes_returned = get_rfc1002_length(midQ->resp_buf); + *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length); memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); rc = cifs_check_receive(midQ, ses->server, 0); out: delete_mid(midQ); - cifs_add_credits(ses->server, 1); + atomic_dec(&ses->server->inFlight); + wake_up(&ses->server->request_q); return rc; } @@ -871,11 +842,15 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, return rc; } - midQ->mid_state = MID_REQUEST_SUBMITTED; - cifs_in_send_inc(ses->server); + midQ->midState = MID_REQUEST_SUBMITTED; +#ifdef CONFIG_CIFS_STATS2 + atomic_inc(&ses->server->inSend); +#endif rc = smb_send(ses->server, in_buf, be32_to_cpu(in_buf->smb_buf_length)); - cifs_in_send_dec(ses->server); - cifs_save_when_sent(midQ); +#ifdef CONFIG_CIFS_STATS2 + atomic_dec(&ses->server->inSend); + midQ->when_sent = jiffies; +#endif mutex_unlock(&ses->server->srv_mutex); if (rc < 0) { @@ -885,13 +860,13 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, /* Wait for a reply - allow signals to interrupt. */ rc = wait_event_interruptible(ses->server->response_q, - (!(midQ->mid_state == MID_REQUEST_SUBMITTED)) || + (!(midQ->midState == MID_REQUEST_SUBMITTED)) || ((ses->server->tcpStatus != CifsGood) && (ses->server->tcpStatus != CifsNew))); /* Were we interrupted by a signal ? */ if ((rc == -ERESTARTSYS) && - (midQ->mid_state == MID_REQUEST_SUBMITTED) && + (midQ->midState == MID_REQUEST_SUBMITTED) && ((ses->server->tcpStatus == CifsGood) || (ses->server->tcpStatus == CifsNew))) { @@ -921,7 +896,7 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, if (rc) { send_nt_cancel(ses->server, in_buf, midQ); spin_lock(&GlobalMid_Lock); - if (midQ->mid_state == MID_REQUEST_SUBMITTED) { + if (midQ->midState == MID_REQUEST_SUBMITTED) { /* no longer considered to be "in-flight" */ midQ->callback = DeleteMidQEntry; spin_unlock(&GlobalMid_Lock); @@ -939,13 +914,13 @@ SendReceiveBlockingLock(const unsigned int xid, struct cifs_tcon *tcon, return rc; /* rcvd frame is ok */ - if (out_buf == NULL || midQ->mid_state != MID_RESPONSE_RECEIVED) { + if (out_buf == NULL || midQ->midState != MID_RESPONSE_RECEIVED) { rc = -EIO; cERROR(1, "Bad MID state?"); goto out; } - *pbytes_returned = get_rfc1002_length(midQ->resp_buf); + *pbytes_returned = be32_to_cpu(midQ->resp_buf->smb_buf_length); memcpy(out_buf, midQ->resp_buf, *pbytes_returned + 4); rc = cifs_check_receive(midQ, ses->server, 0); out: diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c index 10d92cf57ab..2a22fb2989e 100644 --- a/fs/cifs/xattr.c +++ b/fs/cifs/xattr.c @@ -22,7 +22,6 @@ #include #include #include -#include #include "cifsfs.h" #include "cifspdu.h" #include "cifsglob.h" @@ -32,9 +31,17 @@ #define MAX_EA_VALUE_SIZE 65535 #define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" #define CIFS_XATTR_CIFS_ACL "system.cifs_acl" - +#define CIFS_XATTR_USER_PREFIX "user." +#define CIFS_XATTR_SYSTEM_PREFIX "system." +#define CIFS_XATTR_OS2_PREFIX "os2." +#define CIFS_XATTR_SECURITY_PREFIX "security." +#define CIFS_XATTR_TRUSTED_PREFIX "trusted." +#define XATTR_TRUSTED_PREFIX_LEN 8 +#define XATTR_SECURITY_PREFIX_LEN 9 /* BB need to add server (Samba e.g) support for security and trusted prefix */ + + int cifs_removexattr(struct dentry *direntry, const char *ea_name) { int rc = -EOPNOTSUPP; @@ -69,8 +76,8 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) } if (ea_name == NULL) { cFYI(1, "Null xattr names not supported"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - && (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) { + } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) + && (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) { cFYI(1, "illegal xattr request %s (only user namespace supported)", ea_name); @@ -81,7 +88,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name) if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto remove_ea_exit; - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ + ea_name += 5; /* skip past user. prefix */ rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL, (__u16)0, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -105,6 +112,7 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, struct cifs_tcon *pTcon; struct super_block *sb; char *full_path; + struct cifs_ntsd *pacl; if (direntry == NULL) return -EIO; @@ -141,46 +149,43 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name, if (ea_name == NULL) { cFYI(1, "Null xattr names not supported"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - == 0) { + } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto set_ea_exit; if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) cFYI(1, "attempt to set cifs inode metadata"); - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ + ea_name += 5; /* skip past user. prefix */ rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, (__u16)value_size, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) - == 0) { + } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto set_ea_exit; - ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ + ea_name += 4; /* skip past os2. prefix */ rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, (__u16)value_size, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); } else if (strncmp(ea_name, CIFS_XATTR_CIFS_ACL, strlen(CIFS_XATTR_CIFS_ACL)) == 0) { -#ifdef CONFIG_CIFS_ACL - struct cifs_ntsd *pacl; pacl = kmalloc(value_size, GFP_KERNEL); if (!pacl) { cFYI(1, "%s: Can't allocate memory for ACL", __func__); rc = -ENOMEM; } else { +#ifdef CONFIG_CIFS_ACL memcpy(pacl, ea_value, value_size); rc = set_cifs_acl(pacl, value_size, - direntry->d_inode, full_path, CIFS_ACL_DACL); + direntry->d_inode, full_path); if (rc == 0) /* force revalidate of the inode */ CIFS_I(direntry->d_inode)->time = 0; kfree(pacl); - } #else cFYI(1, "Set CIFS ACL not supported yet"); #endif /* CONFIG_CIFS_ACL */ + } } else { int temp; temp = strncmp(ea_name, POSIX_ACL_XATTR_ACCESS, @@ -264,8 +269,7 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, /* return alt name if available as pseudo attr */ if (ea_name == NULL) { cFYI(1, "Null xattr names not supported"); - } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN) - == 0) { + } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto get_ea_exit; @@ -273,15 +277,15 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, cFYI(1, "attempt to query cifs inode metadata"); /* revalidate/getattr then populate from inode */ } /* BB add else when above is implemented */ - ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */ + ea_name += 5; /* skip past user. prefix */ rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, buf_size, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); - } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) { + } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) goto get_ea_exit; - ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */ + ea_name += 4; /* skip past os2. prefix */ rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, buf_size, cifs_sb->local_nls, cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); @@ -335,10 +339,10 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name, cFYI(1, "Query CIFS ACL not supported yet"); #endif /* CONFIG_CIFS_ACL */ } else if (strncmp(ea_name, - XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { + CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { cFYI(1, "Trusted xattr namespace not supported yet"); } else if (strncmp(ea_name, - XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { + CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { cFYI(1, "Security xattr namespace not supported yet"); } else cFYI(1, diff --git a/fs/dcache.c b/fs/dcache.c index a94b9fdf205..30bf405e1d2 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2974,6 +2974,22 @@ void d_genocide(struct dentry *root) goto again; } +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) || + !d_unlinked(dentry)); + spin_lock(&dentry->d_parent->d_lock); + spin_lock_nested(&dentry->d_lock, DENTRY_D_LOCK_NESTED); + dentry->d_name.len = sprintf(dentry->d_iname, "#%llu", + (unsigned long long)inode->i_ino); + spin_unlock(&dentry->d_lock); + spin_unlock(&dentry->d_parent->d_lock); + d_instantiate(dentry, inode); +} +EXPORT_SYMBOL(d_tmpfile); + /** * find_inode_number - check for dentry with name * @dir: directory to check diff --git a/fs/dyn_sync_cntrl.c b/fs/dyn_sync_cntrl.c new file mode 100644 index 00000000000..e7464e72703 --- /dev/null +++ b/fs/dyn_sync_cntrl.c @@ -0,0 +1,206 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * Copyright 2013 Paul Reioux + * Copyright 2012 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 +#include +#include + +#define DYN_FSYNC_VERSION_MAJOR 1 +#define DYN_FSYNC_VERSION_MINOR 2 + +/* + * fsync_mutex protects dyn_fsync_active during early suspend / late resume + * transitions + */ +static DEFINE_MUTEX(fsync_mutex); + +bool early_suspend_active __read_mostly = false; +bool dyn_fsync_active __read_mostly = true; + +static ssize_t dyn_fsync_active_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", (dyn_fsync_active ? 1 : 0)); +} + +static ssize_t dyn_fsync_active_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int data; + + if(sscanf(buf, "%u\n", &data) == 1) { + if (data == 1) { + pr_info("%s: dynamic fsync enabled\n", __FUNCTION__); + dyn_fsync_active = true; + } + else if (data == 0) { + pr_info("%s: dyanamic fsync disabled\n", __FUNCTION__); + dyn_fsync_active = false; + } + else + pr_info("%s: bad value: %u\n", __FUNCTION__, data); + } else + pr_info("%s: unknown input!\n", __FUNCTION__); + + return count; +} + +static ssize_t dyn_fsync_version_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "version: %u.%u by faux123\n", + DYN_FSYNC_VERSION_MAJOR, + DYN_FSYNC_VERSION_MINOR); +} + +static ssize_t dyn_fsync_earlysuspend_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "early suspend active: %u\n", early_suspend_active); +} + +static struct kobj_attribute dyn_fsync_active_attribute = + __ATTR(Dyn_fsync_active, 0666, + dyn_fsync_active_show, + dyn_fsync_active_store); + +static struct kobj_attribute dyn_fsync_version_attribute = + __ATTR(Dyn_fsync_version, 0444, dyn_fsync_version_show, NULL); + +static struct kobj_attribute dyn_fsync_earlysuspend_attribute = + __ATTR(Dyn_fsync_earlysuspend, 0444, dyn_fsync_earlysuspend_show, NULL); + +static struct attribute *dyn_fsync_active_attrs[] = + { + &dyn_fsync_active_attribute.attr, + &dyn_fsync_version_attribute.attr, + &dyn_fsync_earlysuspend_attribute.attr, + NULL, + }; + +static struct attribute_group dyn_fsync_active_attr_group = + { + .attrs = dyn_fsync_active_attrs, + }; + +static struct kobject *dyn_fsync_kobj; + +static void dyn_fsync_force_flush(void) +{ + /* flush all outstanding buffers */ + wakeup_flusher_threads(0, WB_REASON_SYNC); + sync_filesystems(0); + sync_filesystems(1); +} + +static void dyn_fsync_early_suspend(struct early_suspend *h) +{ + mutex_lock(&fsync_mutex); + if (dyn_fsync_active) { + early_suspend_active = true; + dyn_fsync_force_flush(); + } + mutex_unlock(&fsync_mutex); +} + +static void dyn_fsync_late_resume(struct early_suspend *h) +{ + mutex_lock(&fsync_mutex); + early_suspend_active = false; + mutex_unlock(&fsync_mutex); +} + +static struct early_suspend dyn_fsync_early_suspend_handler = + { + .level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN, + .suspend = dyn_fsync_early_suspend, + .resume = dyn_fsync_late_resume, + }; + +static int dyn_fsync_panic_event(struct notifier_block *this, + unsigned long event, void *ptr) +{ + early_suspend_active = true; + dyn_fsync_force_flush(); + //pr_warn("dyn fsync: panic: force flush!\n"); + + return NOTIFY_DONE; +} + +static struct notifier_block dyn_fsync_panic_block = { + .notifier_call = dyn_fsync_panic_event, + .priority = INT_MAX, +}; + +static int dyn_fsync_notify_sys(struct notifier_block *this, unsigned long code, + void *unused) +{ + if (code == SYS_DOWN || code == SYS_HALT) { + early_suspend_active = true; + dyn_fsync_force_flush(); + //pr_warn("dyn fsync: reboot: force flush!\n"); + } + return NOTIFY_DONE; +} + +static struct notifier_block dyn_fsync_notifier = { + .notifier_call = dyn_fsync_notify_sys, +}; + +static int dyn_fsync_init(void) +{ + int sysfs_result; + + register_early_suspend(&dyn_fsync_early_suspend_handler); + register_reboot_notifier(&dyn_fsync_notifier); + atomic_notifier_chain_register(&panic_notifier_list, + &dyn_fsync_panic_block); + + dyn_fsync_kobj = kobject_create_and_add("dyn_fsync", kernel_kobj); + if (!dyn_fsync_kobj) { + pr_err("%s dyn_fsync kobject create failed!\n", __FUNCTION__); + return -ENOMEM; + } + + sysfs_result = sysfs_create_group(dyn_fsync_kobj, + &dyn_fsync_active_attr_group); + + if (sysfs_result) { + pr_info("%s dyn_fsync sysfs create failed!\n", __FUNCTION__); + kobject_put(dyn_fsync_kobj); + } + return sysfs_result; +} + +static void dyn_fsync_exit(void) +{ + unregister_early_suspend(&dyn_fsync_early_suspend_handler); + unregister_reboot_notifier(&dyn_fsync_notifier); + atomic_notifier_chain_unregister(&panic_notifier_list, + &dyn_fsync_panic_block); + + if (dyn_fsync_kobj != NULL) + kobject_put(dyn_fsync_kobj); +} + +module_init(dyn_fsync_init); +module_exit(dyn_fsync_exit); diff --git a/fs/eventpoll.c b/fs/eventpoll.c index c0b3c70ee87..497accdb2db 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -1415,7 +1416,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, } spin_unlock_irqrestore(&ep->lock, flags); - if (!schedule_hrtimeout_range(to, slack, HRTIMER_MODE_ABS)) + if (!freezable_schedule_hrtimeout_range(to, slack, + HRTIMER_MODE_ABS)) timed_out = 1; spin_lock_irqsave(&ep->lock, flags); diff --git a/fs/exec.c b/fs/exec.c index b1fd2025e59..a68180516f4 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -19,7 +19,7 @@ * current->executable is only used by the procfs. This allows a dispatch * table to check for several different types of binary formats. We keep * trying until we recognize the file or we run out of supported binary - * formats. + * formats. */ #include @@ -55,6 +55,7 @@ #include #include #include +#include #include #include @@ -1173,7 +1174,7 @@ void setup_new_exec(struct linux_binprm * bprm) group */ current->self_exec_id++; - + flush_signal_handlers(current, 0); flush_old_files(current->files); } @@ -1268,8 +1269,8 @@ static int check_unsafe_exec(struct linux_binprm *bprm) return res; } -/* - * Fill the binprm structure from the inode. +/* + * Fill the binprm structure from the inode. * Check permissions, then read the first 128 (BINPRM_BUF_SIZE) bytes * * This may be called multiple times for binary chains (scripts for example). diff --git a/fs/exfat/Kconfig b/fs/exfat/Kconfig new file mode 100644 index 00000000000..144b6eccabe --- /dev/null +++ b/fs/exfat/Kconfig @@ -0,0 +1,19 @@ +config EXFAT_FS + tristate "exFAT filesystem support" + select NLS + help + exFAT driver from Samsung + +config EXFAT_DEFAULT_CODEPAGE + int "Default codepage for exFAT" + depends on EXFAT_FS + default 437 + help + This option should be set to the codepage of your exFAT filesystems. + +config EXFAT_DEFAULT_IOCHARSET + string "Default iocharset for exFAT" + depends on EXFAT_FS + default "utf8" + help + Set this to the default input/output character set you'd like exFAT to use. diff --git a/fs/exfat/Makefile b/fs/exfat/Makefile new file mode 100644 index 00000000000..77dc36c6183 --- /dev/null +++ b/fs/exfat/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_EXFAT_FS) += exfat.o + +exfat-y := exfat_core.o exfat_api.o exfat_blkdev.o exfat_cache.o exfat_super.o \ + exfat_data.o exfat_global.o exfat_nls.o exfat_oal.o exfat_upcase.o diff --git a/fs/exfat/Makefile.module b/fs/exfat/Makefile.module new file mode 100644 index 00000000000..2e97826d059 --- /dev/null +++ b/fs/exfat/Makefile.module @@ -0,0 +1,20 @@ +EXTRA_FLAGS += -I$(PWD) + +#KDIR := /usr/src/linux/ +KDIR := /lib/modules/$(shell uname -r)/build +PWD := $(shell pwd) + +export CONFIG_EXFAT_FS := m + +all: + $(MAKE) -C $(KDIR) M=$(PWD) modules + +clean: + $(MAKE) -C $(KDIR) M=$(PWD) clean + +help: + $(MAKE) -C $(KDIR) M=$(PWD) help + +.PHONY : install +install : all + sudo $(MAKE) -C $(KDIR) M=$(PWD) modules_install; sudo depmod diff --git a/fs/exfat/README.md b/fs/exfat/README.md new file mode 100644 index 00000000000..e14291263ae --- /dev/null +++ b/fs/exfat/README.md @@ -0,0 +1,71 @@ +exfat-nofuse +============ + +Linux non-fuse read/write kernel driver for the exFAT file system.
+Originally ported from android kernel v3.0. + + +Kudos to ksv1986 for the mutex patch!
+Thanks to JackNorris for being awesome and providing the clear_inode() patch.
+
+Big thanks to lqs for completing the driver! +Big thanks to benpicco for fixing 3.11.y compatibility! + + +Special thanks to github user AndreiLux for spreading the word about the leak!
+ + +Installation as stand alone module: +==================================== + + make -f Makefile.module KDIR="path to kernel source" CROSS_COMPILE="path to android chain tools (as linaro)/bin/SOMETHING- (see your folder for clues)" + +Example how it's works for me! + + make -f Makefile.module CROSS_COMPILE=../dorimanx-SG2-I9100-Kernel/android-toolchain/bin/arm-eabi- KDIR=../dorimanx-SG2-I9100-Kernel/ + +exfat.ko module file will be created in exfat source folder. and will work with kernel source you have used. + + make -f Makefile.module install + +To load the driver manually, run this as root: + + modprobe exfat + +To add to kernel you need to do this: +====================================== + +cd your kernel source dir + +mkdir fs/exfat + +copy all files (except .git and .gitignore) from exfat-nofuse to your kernel source fs/exfat/ + +see +https://github.com/dorimanx/Dorimanx-SG2-I9100-Kernel/commit/e8fc728a68096db9ffcebff40244ebfb60a3de18 + +edit fs/Kconfig +edit fs/Makefile + +cd your kernel source +make menuconfig + +Go to: +> File systems > DOS/FAT/NT > check the exfat as MODULE (M) +> (437) Default codepage for exFAT +> (utf8) Default iocharset for exFAT + +> ESC to main menu +> Save an Alternate Configuration File +> ESC ESC + +build your kernel. + +and you will have new module! + +exfat.ko + +have fun. + +Free Software for the Free Minds! +===================================== diff --git a/fs/exfat/exfat.h b/fs/exfat/exfat.h new file mode 100644 index 00000000000..a37f4b15406 --- /dev/null +++ b/fs/exfat/exfat.h @@ -0,0 +1,675 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat.h */ +/* PURPOSE : Header File for exFAT File Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_H +#define _EXFAT_H + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat_cache.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if EXFAT_CONFIG_KERNEL_DEBUG + /* For Debugging Purpose */ + /* IOCTL code 'f' used by + * - file systems typically #0~0x1F + * - embedded terminal devices #128~ + * - exts for debugging purpose #99 + * number 100 and 101 is availble now but has possible conflicts + */ +#define EXFAT_IOC_GET_DEBUGFLAGS _IOR('f', 100, long) +#define EXFAT_IOC_SET_DEBUGFLAGS _IOW('f', 101, long) + +#define EXFAT_DEBUGFLAGS_INVALID_UMOUNT 0x01 +#define EXFAT_DEBUGFLAGS_ERROR_RW 0x02 +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define MAX_VOLUME 4 // max num of volumes per device + +#define DENTRY_SIZE 32 // dir entry size +#define DENTRY_SIZE_BITS 5 + + /* PBR entries */ +#define PBR_SIGNATURE 0xAA55 +#define EXT_SIGNATURE 0xAA550000 +#define VOL_LABEL "NO NAME " // size should be 11 +#define OEM_NAME "MSWIN4.1" // size should be 8 +#define STR_FAT12 "FAT12 " // size should be 8 +#define STR_FAT16 "FAT16 " // size should be 8 +#define STR_FAT32 "FAT32 " // size should be 8 +#define STR_EXFAT "EXFAT " // size should be 8 +#define VOL_CLEAN 0x0000 +#define VOL_DIRTY 0x0002 + + /* max number of clusters */ +#define FAT12_THRESHOLD 4087 // 2^12 - 1 + 2 (clu 0 & 1) +#define FAT16_THRESHOLD 65527 // 2^16 - 1 + 2 +#define FAT32_THRESHOLD 268435457 // 2^28 - 1 + 2 +#define EXFAT_THRESHOLD 268435457 // 2^28 - 1 + 2 + + /* file types */ +#define TYPE_UNUSED 0x0000 +#define TYPE_DELETED 0x0001 +#define TYPE_INVALID 0x0002 +#define TYPE_CRITICAL_PRI 0x0100 +#define TYPE_BITMAP 0x0101 +#define TYPE_UPCASE 0x0102 +#define TYPE_VOLUME 0x0103 +#define TYPE_DIR 0x0104 +#define TYPE_FILE 0x011F +#define TYPE_SYMLINK 0x015F +#define TYPE_CRITICAL_SEC 0x0200 +#define TYPE_STREAM 0x0201 +#define TYPE_EXTEND 0x0202 +#define TYPE_ACL 0x0203 +#define TYPE_BENIGN_PRI 0x0400 +#define TYPE_GUID 0x0401 +#define TYPE_PADDING 0x0402 +#define TYPE_ACLTAB 0x0403 +#define TYPE_BENIGN_SEC 0x0800 +#define TYPE_ALL 0x0FFF + + /* time modes */ +#define TM_CREATE 0 +#define TM_MODIFY 1 +#define TM_ACCESS 2 + + /* checksum types */ +#define CS_DIR_ENTRY 0 +#define CS_PBR_SECTOR 1 +#define CS_DEFAULT 2 + +#define CLUSTER_16(x) ((UINT16)(x)) +#define CLUSTER_32(x) ((UINT32)(x)) + +#define START_SECTOR(x) \ + ( (((x)-2) << p_fs->sectors_per_clu_bits) + p_fs->data_start_sector ) + +#define IS_LAST_SECTOR_IN_CLUSTER(sec) \ + ( (((sec) - p_fs->data_start_sector + 1) & ((1 << p_fs->sectors_per_clu_bits) -1)) == 0) + +#define GET_CLUSTER_FROM_SECTOR(sec) \ + ((((sec) - p_fs->data_start_sector) >> p_fs->sectors_per_clu_bits) +2) + +#define GET16(p_src) \ + ( ((UINT16)(p_src)[0]) | (((UINT16)(p_src)[1]) << 8) ) +#define GET32(p_src) \ + ( ((UINT32)(p_src)[0]) | (((UINT32)(p_src)[1]) << 8) | \ + (((UINT32)(p_src)[2]) << 16) | (((UINT32)(p_src)[3]) << 24) ) +#define GET64(p_src) \ + ( ((UINT64)(p_src)[0]) | (((UINT64)(p_src)[1]) << 8) | \ + (((UINT64)(p_src)[2]) << 16) | (((UINT64)(p_src)[3]) << 24) | \ + (((UINT64)(p_src)[4]) << 32) | (((UINT64)(p_src)[5]) << 40) | \ + (((UINT64)(p_src)[6]) << 48) | (((UINT64)(p_src)[7]) << 56) ) + + +#define SET16(p_dst,src) \ + do { \ + (p_dst)[0]=(UINT8)(src); \ + (p_dst)[1]=(UINT8)(((UINT16)(src)) >> 8); \ + } while (0) +#define SET32(p_dst,src) \ + do { \ + (p_dst)[0]=(UINT8)(src); \ + (p_dst)[1]=(UINT8)(((UINT32)(src)) >> 8); \ + (p_dst)[2]=(UINT8)(((UINT32)(src)) >> 16); \ + (p_dst)[3]=(UINT8)(((UINT32)(src)) >> 24); \ + } while (0) +#define SET64(p_dst,src) \ + do { \ + (p_dst)[0]=(UINT8)(src); \ + (p_dst)[1]=(UINT8)(((UINT64)(src)) >> 8); \ + (p_dst)[2]=(UINT8)(((UINT64)(src)) >> 16); \ + (p_dst)[3]=(UINT8)(((UINT64)(src)) >> 24); \ + (p_dst)[4]=(UINT8)(((UINT64)(src)) >> 32); \ + (p_dst)[5]=(UINT8)(((UINT64)(src)) >> 40); \ + (p_dst)[6]=(UINT8)(((UINT64)(src)) >> 48); \ + (p_dst)[7]=(UINT8)(((UINT64)(src)) >> 56); \ + } while (0) + +#ifdef __LITTLE_ENDIAN +#define GET16_A(p_src) (*((UINT16 *)(p_src))) +#define GET32_A(p_src) (*((UINT32 *)(p_src))) +#define GET64_A(p_src) (*((UINT64 *)(p_src))) +#define SET16_A(p_dst,src) *((UINT16 *)(p_dst)) = (UINT16)(src) +#define SET32_A(p_dst,src) *((UINT32 *)(p_dst)) = (UINT32)(src) +#define SET64_A(p_dst,src) *((UINT64 *)(p_dst)) = (UINT64)(src) +#else +#define GET16_A(p_src) GET16(p_src) +#define GET32_A(p_src) GET32(p_src) +#define GET64_A(p_src) GET64(p_src) +#define SET16_A(p_dst,src) SET16(p_dst, src) +#define SET32_A(p_dst,src) SET32(p_dst, src) +#define SET64_A(p_dst,src) SET64(p_dst, src) +#endif + + /* Upcase tabel mecro */ +#define HIGH_INDEX_BIT (8) +#define HIGH_INDEX_MASK (0xFF00) +#define LOW_INDEX_BIT (16-HIGH_INDEX_BIT) +#define UTBL_ROW_COUNT (1<> LOW_INDEX_BIT; + } + static inline UINT16 get_row_index(UINT16 i) + { + return i & ~HIGH_INDEX_MASK; + } + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + /* MS_DOS FAT partition boot record (512 bytes) */ + typedef struct { + UINT8 jmp_boot[3]; + UINT8 oem_name[8]; + UINT8 bpb[109]; + UINT8 boot_code[390]; + UINT8 signature[2]; + } PBR_SECTOR_T; + + /* MS-DOS FAT12/16 BIOS parameter block (51 bytes) */ + typedef struct { + UINT8 sector_size[2]; + UINT8 sectors_per_clu; + UINT8 num_reserved[2]; + UINT8 num_fats; + UINT8 num_root_entries[2]; + UINT8 num_sectors[2]; + UINT8 media_type; + UINT8 num_fat_sectors[2]; + UINT8 sectors_in_track[2]; + UINT8 num_heads[2]; + UINT8 num_hid_sectors[4]; + UINT8 num_huge_sectors[4]; + + UINT8 phy_drv_no; + UINT8 reserved; + UINT8 ext_signature; + UINT8 vol_serial[4]; + UINT8 vol_label[11]; + UINT8 vol_type[8]; + } BPB16_T; + + /* MS-DOS FAT32 BIOS parameter block (79 bytes) */ + typedef struct { + UINT8 sector_size[2]; + UINT8 sectors_per_clu; + UINT8 num_reserved[2]; + UINT8 num_fats; + UINT8 num_root_entries[2]; + UINT8 num_sectors[2]; + UINT8 media_type; + UINT8 num_fat_sectors[2]; + UINT8 sectors_in_track[2]; + UINT8 num_heads[2]; + UINT8 num_hid_sectors[4]; + UINT8 num_huge_sectors[4]; + UINT8 num_fat32_sectors[4]; + UINT8 ext_flags[2]; + UINT8 fs_version[2]; + UINT8 root_cluster[4]; + UINT8 fsinfo_sector[2]; + UINT8 backup_sector[2]; + UINT8 reserved[12]; + + UINT8 phy_drv_no; + UINT8 ext_reserved; + UINT8 ext_signature; + UINT8 vol_serial[4]; + UINT8 vol_label[11]; + UINT8 vol_type[8]; + } BPB32_T; + + /* MS-DOS EXFAT BIOS parameter block (109 bytes) */ + typedef struct { + UINT8 reserved1[53]; + UINT8 vol_offset[8]; + UINT8 vol_length[8]; + UINT8 fat_offset[4]; + UINT8 fat_length[4]; + UINT8 clu_offset[4]; + UINT8 clu_count[4]; + UINT8 root_cluster[4]; + UINT8 vol_serial[4]; + UINT8 fs_version[2]; + UINT8 vol_flags[2]; + UINT8 sector_size_bits; + UINT8 sectors_per_clu_bits; + UINT8 num_fats; + UINT8 phy_drv_no; + UINT8 perc_in_use; + UINT8 reserved2[7]; + } BPBEX_T; + + /* MS-DOS FAT file system information sector (512 bytes) */ + typedef struct { + UINT8 signature1[4]; // aligned + UINT8 reserved1[480]; + UINT8 signature2[4]; // aligned + UINT8 free_cluster[4]; // aligned + UINT8 next_cluster[4]; // aligned + UINT8 reserved2[14]; + UINT8 signature3[2]; + } FSI_SECTOR_T; + + /* MS-DOS FAT directory entry (32 bytes) */ + typedef struct { + UINT8 dummy[32]; + } DENTRY_T; + + typedef struct { + UINT8 name[DOS_NAME_LENGTH]; + UINT8 attr; + UINT8 lcase; + UINT8 create_time_ms; + UINT8 create_time[2]; // aligned + UINT8 create_date[2]; // aligned + UINT8 access_date[2]; // aligned + UINT8 start_clu_hi[2]; // aligned + UINT8 modify_time[2]; // aligned + UINT8 modify_date[2]; // aligned + UINT8 start_clu_lo[2]; // aligned + UINT8 size[4]; // aligned + } DOS_DENTRY_T; + + /* MS-DOS FAT extended directory entry (32 bytes) */ + typedef struct { + UINT8 order; + UINT8 unicode_0_4[10]; + UINT8 attr; + UINT8 sysid; + UINT8 checksum; + UINT8 unicode_5_10[12]; // aligned + UINT8 start_clu[2]; // aligned + UINT8 unicode_11_12[4]; // aligned + } EXT_DENTRY_T; + + /* MS-DOS EXFAT file directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 num_ext; + UINT8 checksum[2]; // aligned + UINT8 attr[2]; // aligned + UINT8 reserved1[2]; + UINT8 create_time[2]; // aligned + UINT8 create_date[2]; // aligned + UINT8 modify_time[2]; // aligned + UINT8 modify_date[2]; // aligned + UINT8 access_time[2]; // aligned + UINT8 access_date[2]; // aligned + UINT8 create_time_ms; + UINT8 modify_time_ms; + UINT8 access_time_ms; + UINT8 reserved2[9]; + } FILE_DENTRY_T; + + /* MS-DOS EXFAT stream extension directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 flags; + UINT8 reserved1; + UINT8 name_len; + UINT8 name_hash[2]; // aligned + UINT8 reserved2[2]; + UINT8 valid_size[8]; // aligned + UINT8 reserved3[4]; // aligned + UINT8 start_clu[4]; // aligned + UINT8 size[8]; // aligned + } STRM_DENTRY_T; + + /* MS-DOS EXFAT file name directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 flags; + UINT8 unicode_0_14[30]; // aligned + } NAME_DENTRY_T; + + /* MS-DOS EXFAT allocation bitmap directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 flags; + UINT8 reserved[18]; + UINT8 start_clu[4]; // aligned + UINT8 size[8]; // aligned + } BMAP_DENTRY_T; + + /* MS-DOS EXFAT up-case table directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 reserved1[3]; + UINT8 checksum[4]; // aligned + UINT8 reserved2[12]; + UINT8 start_clu[4]; // aligned + UINT8 size[8]; // aligned + } CASE_DENTRY_T; + + /* MS-DOS EXFAT volume label directory entry (32 bytes) */ + typedef struct { + UINT8 type; + UINT8 label_len; + UINT8 unicode_0_10[22]; // aligned + UINT8 reserved[8]; + } VOLM_DENTRY_T; + + /* unused entry hint information */ + typedef struct { + UINT32 dir; + INT32 entry; + CHAIN_T clu; + } UENTRY_T; + + /* file system volume information structure */ + typedef struct __FS_STRUCT_T { + UINT32 mounted; + struct super_block *sb; + struct semaphore v_sem; + } FS_STRUCT_T; + + typedef struct { + INT32 (*alloc_cluster)(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); + void (*free_cluster)(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); + INT32 (*count_used_clusters)(struct super_block *sb); + + INT32 (*init_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, + UINT32 start_clu, UINT64 size); + INT32 (*init_ext_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, + UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); + INT32 (*find_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); + void (*delete_dir_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 offset, INT32 num_entries); + void (*get_uni_name_from_ext_entry)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); + INT32 (*count_ext_entries)(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); + INT32 (*calc_num_entries)(UNI_NAME_T *p_uniname); + + UINT32 (*get_entry_type)(DENTRY_T *p_entry); + void (*set_entry_type)(DENTRY_T *p_entry, UINT32 type); + UINT32 (*get_entry_attr)(DENTRY_T *p_entry); + void (*set_entry_attr)(DENTRY_T *p_entry, UINT32 attr); + UINT8 (*get_entry_flag)(DENTRY_T *p_entry); + void (*set_entry_flag)(DENTRY_T *p_entry, UINT8 flag); + UINT32 (*get_entry_clu0)(DENTRY_T *p_entry); + void (*set_entry_clu0)(DENTRY_T *p_entry, UINT32 clu0); + UINT64 (*get_entry_size)(DENTRY_T *p_entry); + void (*set_entry_size)(DENTRY_T *p_entry, UINT64 size); + void (*get_entry_time)(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + void (*set_entry_time)(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + } FS_FUNC_T; + + typedef struct __FS_INFO_T { + UINT32 drv; // drive ID + UINT32 vol_type; // volume FAT type + UINT32 vol_id; // volume serial number + + UINT32 num_sectors; // num of sectors in volume + UINT32 num_clusters; // num of clusters in volume + UINT32 cluster_size; // cluster size in bytes + UINT32 cluster_size_bits; + UINT32 sectors_per_clu; // cluster size in sectors + UINT32 sectors_per_clu_bits; + + UINT32 PBR_sector; // PBR sector + UINT32 FAT1_start_sector; // FAT1 start sector + UINT32 FAT2_start_sector; // FAT2 start sector + UINT32 root_start_sector; // root dir start sector + UINT32 data_start_sector; // data area start sector + UINT32 num_FAT_sectors; // num of FAT sectors + + UINT32 root_dir; // root dir cluster + UINT32 dentries_in_root; // num of dentries in root dir + UINT32 dentries_per_clu; // num of dentries per cluster + + UINT32 vol_flag; // volume dirty flag + struct buffer_head *pbr_bh; // PBR sector + + UINT32 map_clu; // allocation bitmap start cluster + UINT32 map_sectors; // num of allocation bitmap sectors + struct buffer_head **vol_amap; // allocation bitmap + + UINT16 **vol_utbl; // upcase table + + UINT32 clu_srch_ptr; // cluster search pointer + UINT32 used_clusters; // number of used clusters + UENTRY_T hint_uentry; // unused entry hint information + + UINT32 dev_ejected; // block device operation error flag + + FS_FUNC_T *fs_func; + + /* FAT cache */ + BUF_CACHE_T FAT_cache_array[FAT_CACHE_SIZE]; + BUF_CACHE_T FAT_cache_lru_list; + BUF_CACHE_T FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; + + /* buf cache */ + BUF_CACHE_T buf_cache_array[BUF_CACHE_SIZE]; + BUF_CACHE_T buf_cache_lru_list; + BUF_CACHE_T buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; + } FS_INFO_T; + +#define ES_2_ENTRIES 2 +#define ES_3_ENTRIES 3 +#define ES_ALL_ENTRIES 0 + + typedef struct { + UINT32 sector; // sector number that contains file_entry + INT32 offset; // byte offset in the sector + INT32 alloc_flag; // flag in stream entry. 01 for cluster chain, 03 for contig. clusteres. + UINT32 num_entries; + + // __buf should be the last member + void *__buf; + } ENTRY_SET_CACHE_T; + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + /* file system initialization & shutdown functions */ + INT32 ffsInit(void); + INT32 ffsShutdown(void); + + /* volume management functions */ + INT32 ffsMountVol(struct super_block *sb, INT32 drv); + INT32 ffsUmountVol(struct super_block *sb); + INT32 ffsCheckVol(struct super_block *sb); + INT32 ffsGetVolInfo(struct super_block *sb, VOL_INFO_T *info); + INT32 ffsSyncVol(struct super_block *sb, INT32 do_sync); + + /* file management functions */ + INT32 ffsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid); + INT32 ffsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid); + INT32 ffsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount); + INT32 ffsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount); + INT32 ffsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size); + INT32 ffsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry); + INT32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid); + INT32 ffsSetAttr(struct inode *inode, UINT32 attr); + INT32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info); + INT32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info); + INT32 ffsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu); + + /* directory management functions */ + INT32 ffsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid); + INT32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_ent); + INT32 ffsRemoveDir(struct inode *inode, FILE_ID_T *fid); + + /*----------------------------------------------------------------------*/ + /* External Function Declarations (NOT TO UPPER LAYER) */ + /*----------------------------------------------------------------------*/ + + /* fs management functions */ + INT32 fs_init(void); + INT32 fs_shutdown(void); + void fs_set_vol_flags(struct super_block *sb, UINT32 new_flag); + void fs_sync(struct super_block *sb, INT32 do_sync); + void fs_error(struct super_block *sb); + + /* cluster management functions */ + INT32 clear_cluster(struct super_block *sb, UINT32 clu); + INT32 fat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); + INT32 exfat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain); + void fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); + void exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse); + UINT32 find_last_cluster(struct super_block *sb, CHAIN_T *p_chain); + INT32 count_num_clusters(struct super_block *sb, CHAIN_T *dir); + INT32 fat_count_used_clusters(struct super_block *sb); + INT32 exfat_count_used_clusters(struct super_block *sb); + void exfat_chain_cont_cluster(struct super_block *sb, UINT32 chain, INT32 len); + + /* allocation bitmap management functions */ + INT32 load_alloc_bitmap(struct super_block *sb); + void free_alloc_bitmap(struct super_block *sb); + INT32 set_alloc_bitmap(struct super_block *sb, UINT32 clu); + INT32 clr_alloc_bitmap(struct super_block *sb, UINT32 clu); + UINT32 test_alloc_bitmap(struct super_block *sb, UINT32 clu); + void sync_alloc_bitmap(struct super_block *sb); + + /* upcase table management functions */ + INT32 load_upcase_table(struct super_block *sb); + void free_upcase_table(struct super_block *sb); + + /* dir entry management functions */ + UINT32 fat_get_entry_type(DENTRY_T *p_entry); + UINT32 exfat_get_entry_type(DENTRY_T *p_entry); + void fat_set_entry_type(DENTRY_T *p_entry, UINT32 type); + void exfat_set_entry_type(DENTRY_T *p_entry, UINT32 type); + UINT32 fat_get_entry_attr(DENTRY_T *p_entry); + UINT32 exfat_get_entry_attr(DENTRY_T *p_entry); + void fat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr); + void exfat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr); + UINT8 fat_get_entry_flag(DENTRY_T *p_entry); + UINT8 exfat_get_entry_flag(DENTRY_T *p_entry); + void fat_set_entry_flag(DENTRY_T *p_entry, UINT8 flag); + void exfat_set_entry_flag(DENTRY_T *p_entry, UINT8 flag); + UINT32 fat_get_entry_clu0(DENTRY_T *p_entry); + UINT32 exfat_get_entry_clu0(DENTRY_T *p_entry); + void fat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu); + void exfat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu); + UINT64 fat_get_entry_size(DENTRY_T *p_entry); + UINT64 exfat_get_entry_size(DENTRY_T *p_entry); + void fat_set_entry_size(DENTRY_T *p_entry, UINT64 size); + void exfat_set_entry_size(DENTRY_T *p_entry, UINT64 size); + void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + void fat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode); + INT32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, UINT32 start_clu, UINT64 size); + INT32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, UINT32 start_clu, UINT64 size); + INT32 fat_init_ext_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); + INT32 exfat_init_ext_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); + void init_dos_entry(DOS_DENTRY_T *ep, UINT32 type, UINT32 start_clu); + void init_ext_entry(EXT_DENTRY_T *ep, INT32 order, UINT8 chksum, UINT16 *uniname); + void init_file_entry(FILE_DENTRY_T *ep, UINT32 type); + void init_strm_entry(STRM_DENTRY_T *ep, UINT8 flags, UINT32 start_clu, UINT64 size); + void init_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname); + void fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries); + void exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries); + + INT32 find_location(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector, INT32 *offset); + DENTRY_T *get_entry_with_sector(struct super_block *sb, UINT32 sector, INT32 offset); + DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector); + ENTRY_SET_CACHE_T *get_entry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, DENTRY_T **file_ep); + void release_entry_set (ENTRY_SET_CACHE_T *es); + INT32 write_whole_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es); + INT32 write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, DENTRY_T *ep, UINT32 count); + INT32 search_deleted_or_unused_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 num_entries); + INT32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, INT32 num_entries); + INT32 fat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); + INT32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type); + INT32 fat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); + INT32 exfat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry); + INT32 count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, UINT32 type); + void update_dir_checksum(struct super_block *sb, CHAIN_T *p_dir, INT32 entry); + void update_dir_checksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es); + BOOL is_dir_empty(struct super_block *sb, CHAIN_T *p_dir); + + /* name conversion functions */ + INT32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 *entries, DOS_NAME_T *p_dosname); + void get_uni_name_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, UINT8 mode); + void fat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); + void exfat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname); + INT32 extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, UINT16 *uniname, INT32 order); + INT32 extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname, INT32 order); + INT32 fat_generate_dos_name(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T *p_dosname); + void fat_attach_count_to_dos_name(UINT8 *dosname, INT32 count); + INT32 fat_calc_num_entries(UNI_NAME_T *p_uniname); + INT32 exfat_calc_num_entries(UNI_NAME_T *p_uniname); + UINT8 calc_checksum_1byte(void *data, INT32 len, UINT8 chksum); + UINT16 calc_checksum_2byte(void *data, INT32 len, UINT16 chksum, INT32 type); + UINT32 calc_checksum_4byte(void *data, INT32 len, UINT32 chksum, INT32 type); + + /* name resolution functions */ + INT32 resolve_path(struct inode *inode, UINT8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname); + INT32 resolve_name(UINT8 *name, UINT8 **arg); + + /* file operation functions */ + INT32 fat16_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); + INT32 fat32_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); + INT32 exfat_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr); + INT32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid); + INT32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, UINT8 mode, FILE_ID_T *fid); + void remove_file(struct inode *inode, CHAIN_T *p_dir, INT32 entry); + INT32 rename_file(struct inode *inode, CHAIN_T *p_dir, INT32 old_entry, UNI_NAME_T *p_uniname, FILE_ID_T *fid); + INT32 move_file(struct inode *inode, CHAIN_T *p_olddir, INT32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid); + + /* sector read/write functions */ + INT32 sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 read); + INT32 sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 sync); + INT32 multi_sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 num_secs, INT32 read); + INT32 multi_sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 num_secs, INT32 sync); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_H */ + +/* end of exfat.h */ diff --git a/fs/exfat/exfat_api.c b/fs/exfat/exfat_api.c new file mode 100644 index 00000000000..5423181260b --- /dev/null +++ b/fs/exfat/exfat_api.c @@ -0,0 +1,563 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_api.c */ +/* PURPOSE : exFAT API Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include +#include +#include + +#include "exfat_version.h" +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_part.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat_super.h" +#include "exfat.h" + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +extern FS_STRUCT_T fs_struct[]; + +extern struct semaphore z_sem; + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Function Declarations */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* Global Function Definitions */ +/* - All functions for global use have same return value format, */ +/* that is, FFS_SUCCESS on success and several FS error code on */ +/* various error condition. */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* exFAT Filesystem Init & Exit Functions */ +/*----------------------------------------------------------------------*/ + +INT32 FsInit(void) +{ + INT32 i; + + /* initialize all volumes as un-mounted */ + for (i = 0; i < MAX_DRIVE; i++) { + fs_struct[i].mounted = FALSE; + fs_struct[i].sb = NULL; + sm_init(&(fs_struct[i].v_sem)); + } + + return(ffsInit()); +} + +INT32 FsShutdown(void) +{ + INT32 i; + + /* unmount all volumes */ + for (i = 0; i < MAX_DRIVE; i++) { + if (!fs_struct[i].mounted) continue; + + ffsUmountVol(fs_struct[i].sb); + } + + return(ffsShutdown()); +} + +/*----------------------------------------------------------------------*/ +/* Volume Management Functions */ +/*----------------------------------------------------------------------*/ + +/* FsMountVol : mount the file system volume */ +INT32 FsMountVol(struct super_block *sb) +{ + INT32 err, drv; + + sm_P(&z_sem); + + for (drv = 0; drv < MAX_DRIVE; drv++) { + if (!fs_struct[drv].mounted) break; + } + + if (drv >= MAX_DRIVE) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[drv].v_sem)); + + err = buf_init(sb); + if (!err) { + err = ffsMountVol(sb, drv); + } + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[drv].v_sem)); + + if (!err) { + fs_struct[drv].mounted = TRUE; + fs_struct[drv].sb = sb; + } else { + buf_shutdown(sb); + } + + sm_V(&z_sem); + + return(err); +} /* end of FsMountVol */ + +/* FsUmountVol : unmount the file system volume */ +INT32 FsUmountVol(struct super_block *sb) +{ + INT32 err; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&z_sem); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsUmountVol(sb); + buf_shutdown(sb); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + fs_struct[p_fs->drv].mounted = FALSE; + fs_struct[p_fs->drv].sb = NULL; + + sm_V(&z_sem); + + return(err); +} /* end of FsUmountVol */ + +/* FsGetVolInfo : get the information of a file system volume */ +INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info) +{ + INT32 err; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if (info == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsGetVolInfo(sb, info); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsGetVolInfo */ + +/* FsSyncVol : synchronize a file system volume */ +INT32 FsSyncVol(struct super_block *sb, INT32 do_sync) +{ + INT32 err; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsSyncVol(sb, do_sync); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsSyncVol */ + + +/*----------------------------------------------------------------------*/ +/* File Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* FsCreateFile : create a file */ +INT32 FsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsLookupFile(inode, path, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsLookupFile */ + +/* FsCreateFile : create a file */ +INT32 FsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsCreateFile(inode, path, mode, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsCreateFile */ + +INT32 FsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* check the validity of pointer parameters */ + if (buffer == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsReadFile(inode, fid, buffer, count, rcount); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsReadFile */ + +INT32 FsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* check the validity of pointer parameters */ + if (buffer == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsWriteFile(inode, fid, buffer, count, wcount); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsWriteFile */ + +/* FsTruncateFile : resize the file length */ +INT32 FsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + PRINTK("FsTruncateFile entered (inode %p size %llu)\n", inode, new_size); + + err = ffsTruncateFile(inode, old_size, new_size); + + PRINTK("FsTruncateFile exitted (%d)\n", err); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsTruncateFile */ + +/* FsMoveFile : move(rename) a old file into a new file */ +INT32 FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry) +{ + INT32 err; + struct super_block *sb = old_parent_inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsMoveFile(old_parent_inode, fid, new_parent_inode, new_dentry); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsMoveFile */ + +/* FsRemoveFile : remove a file */ +INT32 FsRemoveFile(struct inode *inode, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsRemoveFile(inode, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsRemoveFile */ + +/* FsSetAttr : set the attribute of a given file */ +INT32 FsSetAttr(struct inode *inode, UINT32 attr) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsSetAttr(inode, attr); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsSetAttr */ + +/* FsReadStat : get the information of a given file */ +INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsGetStat(inode, info); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsReadStat */ + +/* FsWriteStat : set the information of a given file */ +INT32 FsWriteStat(struct inode *inode, DIR_ENTRY_T *info) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + PRINTK("FsWriteStat entered (inode %p info %p\n", inode, info); + + err = ffsSetStat(inode, info); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + PRINTK("FsWriteStat exited (%d)\n", err); + + return(err); +} /* end of FsWriteStat */ + +/* FsMapCluster : return the cluster number in the given cluster offset */ +INT32 FsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if (clu == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsMapCluster(inode, clu_offset, clu); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsMapCluster */ + +/*----------------------------------------------------------------------*/ +/* Directory Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* FsCreateDir : create(make) a directory */ +INT32 FsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if ((fid == NULL) || (path == NULL) || (*path == '\0')) + return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsCreateDir(inode, path, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsCreateDir */ + +/* FsReadDir : read a directory entry from the opened directory */ +INT32 FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of pointer parameters */ + if (dir_entry == NULL) return(FFS_ERROR); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsReadDir(inode, dir_entry); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsReadDir */ + +/* FsRemoveDir : remove a directory */ +INT32 FsRemoveDir(struct inode *inode, FILE_ID_T *fid) +{ + INT32 err; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of the given file id */ + if (fid == NULL) return(FFS_INVALIDFID); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + err = ffsRemoveDir(inode, fid); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return(err); +} /* end of FsRemoveDir */ + +EXPORT_SYMBOL(FsMountVol); +EXPORT_SYMBOL(FsUmountVol); +EXPORT_SYMBOL(FsGetVolInfo); +EXPORT_SYMBOL(FsSyncVol); +EXPORT_SYMBOL(FsLookupFile); +EXPORT_SYMBOL(FsCreateFile); +EXPORT_SYMBOL(FsReadFile); +EXPORT_SYMBOL(FsWriteFile); +EXPORT_SYMBOL(FsTruncateFile); +EXPORT_SYMBOL(FsMoveFile); +EXPORT_SYMBOL(FsRemoveFile); +EXPORT_SYMBOL(FsSetAttr); +EXPORT_SYMBOL(FsReadStat); +EXPORT_SYMBOL(FsWriteStat); +EXPORT_SYMBOL(FsMapCluster); +EXPORT_SYMBOL(FsCreateDir); +EXPORT_SYMBOL(FsReadDir); +EXPORT_SYMBOL(FsRemoveDir); + +#if EXFAT_CONFIG_KERNEL_DEBUG +/* FsReleaseCache: Release FAT & buf cache */ +INT32 FsReleaseCache(struct super_block *sb) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* acquire the lock for file system critical section */ + sm_P(&(fs_struct[p_fs->drv].v_sem)); + + FAT_release_all(sb); + buf_release_all(sb); + + /* release the lock for file system critical section */ + sm_V(&(fs_struct[p_fs->drv].v_sem)); + + return 0; +} +/* FsReleaseCache */ + +EXPORT_SYMBOL(FsReleaseCache); +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +/* end of exfat_api.c */ diff --git a/fs/exfat/exfat_api.h b/fs/exfat/exfat_api.h new file mode 100644 index 00000000000..d89b8fed596 --- /dev/null +++ b/fs/exfat/exfat_api.h @@ -0,0 +1,221 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_api.h */ +/* PURPOSE : Header File for exFAT API Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_API_H +#define _EXFAT_API_H + +#include "exfat_config.h" +#include "exfat_global.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define EXFAT_SUPER_MAGIC (0x2011BAB0L) +#define EXFAT_ROOT_INO 1 + + /* FAT types */ +#define FAT12 0x01 // FAT12 +#define FAT16 0x0E // Win95 FAT16 (LBA) +#define FAT32 0x0C // Win95 FAT32 (LBA) +#define EXFAT 0x07 // exFAT + + /* file name lengths */ +#define MAX_CHARSET_SIZE 3 // max size of multi-byte character +#define MAX_PATH_DEPTH 15 // max depth of path name +#define MAX_NAME_LENGTH 256 // max len of file name including NULL +#define MAX_PATH_LENGTH 260 // max len of path name including NULL +#define DOS_NAME_LENGTH 11 // DOS file name length excluding NULL +#define DOS_PATH_LENGTH 80 // DOS path name length excluding NULL + + /* file attributes */ +#define ATTR_NORMAL 0x0000 +#define ATTR_READONLY 0x0001 +#define ATTR_HIDDEN 0x0002 +#define ATTR_SYSTEM 0x0004 +#define ATTR_VOLUME 0x0008 +#define ATTR_SUBDIR 0x0010 +#define ATTR_ARCHIVE 0x0020 +#define ATTR_SYMLINK 0x0040 +#define ATTR_EXTEND 0x000F +#define ATTR_RWMASK 0x007E + + /* file creation modes */ +#define FM_REGULAR 0x00 +#define FM_SYMLINK 0x40 + + /* return values */ +#define FFS_SUCCESS 0 +#define FFS_MEDIAERR 1 +#define FFS_FORMATERR 2 +#define FFS_MOUNTED 3 +#define FFS_NOTMOUNTED 4 +#define FFS_ALIGNMENTERR 5 +#define FFS_SEMAPHOREERR 6 +#define FFS_INVALIDPATH 7 +#define FFS_INVALIDFID 8 +#define FFS_NOTFOUND 9 +#define FFS_FILEEXIST 10 +#define FFS_PERMISSIONERR 11 +#define FFS_NOTOPENED 12 +#define FFS_MAXOPENED 13 +#define FFS_FULL 14 +#define FFS_EOF 15 +#define FFS_DIRBUSY 16 +#define FFS_MEMORYERR 17 +#define FFS_NAMETOOLONG 18 +#define FFS_ERROR 19 // generic error code + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + typedef struct { + UINT16 Year; + UINT16 Month; + UINT16 Day; + UINT16 Hour; + UINT16 Minute; + UINT16 Second; + UINT16 MilliSecond; + } DATE_TIME_T; + + typedef struct { + UINT32 Offset; // start sector number of the partition + UINT32 Size; // in sectors + } PART_INFO_T; + + typedef struct { + UINT32 SecSize; // sector size in bytes + UINT32 DevSize; // block device size in sectors + } DEV_INFO_T; + + typedef struct { + UINT32 FatType; + UINT32 ClusterSize; + UINT32 NumClusters; + UINT32 FreeClusters; + UINT32 UsedClusters; + } VOL_INFO_T; + + /* directory structure */ + typedef struct { + UINT32 dir; + INT32 size; + UINT8 flags; + } CHAIN_T; + + /* file id structure */ + typedef struct { + CHAIN_T dir; + UINT8 flags; + INT32 entry; + UINT32 type; + UINT32 attr; + UINT32 start_clu; + INT32 hint_last_off; + UINT32 hint_last_clu; + INT64 rwoffset; + UINT64 size; + } FILE_ID_T; + + typedef struct { + INT8 Name[MAX_NAME_LENGTH *MAX_CHARSET_SIZE]; + INT8 ShortName[DOS_NAME_LENGTH + 2]; // used only for FAT12/16/32, not used for exFAT + UINT32 Attr; + UINT64 Size; + UINT32 NumSubdirs; + DATE_TIME_T CreateTimestamp; + DATE_TIME_T ModifyTimestamp; + DATE_TIME_T AccessTimestamp; + } DIR_ENTRY_T; + + /*======================================================================*/ + /* */ + /* API FUNCTION DECLARATIONS */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + /* file system initialization & shutdown functions */ + INT32 FsInit(void); + INT32 FsShutdown(void); + + /* volume management functions */ + INT32 FsMountVol(struct super_block *sb); + INT32 FsUmountVol(struct super_block *sb); + INT32 FsGetVolInfo(struct super_block *sb, VOL_INFO_T *info); + INT32 FsSyncVol(struct super_block *sb, INT32 do_sync); + + /* file management functions */ + INT32 FsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid); + INT32 FsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid); + INT32 FsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount); + INT32 FsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount); + INT32 FsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size); + INT32 FsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry); + INT32 FsRemoveFile(struct inode *inode, FILE_ID_T *fid); + INT32 FsSetAttr(struct inode *inode, UINT32 attr); + INT32 FsReadStat(struct inode *inode, DIR_ENTRY_T *info); + INT32 FsWriteStat(struct inode *inode, DIR_ENTRY_T *info); + INT32 FsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu); + + /* directory management functions */ + INT32 FsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid); + INT32 FsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry); + INT32 FsRemoveDir(struct inode *inode, FILE_ID_T *fid); + + /* debug functions */ + INT32 FsReleaseCache(struct super_block *sb); + + /* partition management functions */ +//INT32 FsSetPartition(INT32 dev, INT32 num_vol, PART_INFO_T *vol_spec); +//INT32 FsGetPartition(INT32 dev, INT32 *num_vol, PART_INFO_T *vol_spec); +//INT32 FsGetDevInfo(INT32 dev, DEV_INFO_T *info); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_API_H */ + +/* end of exfat_api.h */ diff --git a/fs/exfat/exfat_blkdev.c b/fs/exfat/exfat_blkdev.c new file mode 100644 index 00000000000..154b444b26f --- /dev/null +++ b/fs/exfat/exfat_blkdev.c @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_blkdev.c */ +/* PURPOSE : exFAT Block Device Driver Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_blkdev.h" +#include "exfat_data.h" +#include "exfat_api.h" +#include "exfat_super.h" + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* Function Definitions */ +/*======================================================================*/ + +INT32 bdev_init(void) +{ + return(FFS_SUCCESS); +} + +INT32 bdev_shutdown(void) +{ + return(FFS_SUCCESS); +} + +INT32 bdev_open(struct super_block *sb) +{ + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bd->opened) return(FFS_SUCCESS); + + p_bd->sector_size = bdev_logical_block_size(sb->s_bdev); + p_bd->sector_size_bits = my_log2(p_bd->sector_size); + p_bd->sector_size_mask = p_bd->sector_size - 1; + p_bd->num_sectors = i_size_read(sb->s_bdev->bd_inode) >> p_bd->sector_size_bits; + + p_bd->opened = TRUE; + + return(FFS_SUCCESS); +} + +INT32 bdev_close(struct super_block *sb) +{ + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (!p_bd->opened) return(FFS_SUCCESS); + + p_bd->opened = FALSE; + return(FFS_SUCCESS); +} + +INT32 bdev_read(struct super_block *sb, UINT32 secno, struct buffer_head **bh, UINT32 num_secs, INT32 read) +{ + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); +#if EXFAT_CONFIG_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + if (!p_bd->opened) return(FFS_MEDIAERR); + + if (*bh) __brelse(*bh); + + if (read) + *bh = __bread(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits); + else + *bh = __getblk(sb->s_bdev, secno, num_secs << p_bd->sector_size_bits); + + if (*bh) return(FFS_SUCCESS); + + WARN(!p_fs->dev_ejected, + "[EXFAT] No bh, device seems wrong or to be ejected.\n"); + + return(FFS_MEDIAERR); +} + +INT32 bdev_write(struct super_block *sb, UINT32 secno, struct buffer_head *bh, UINT32 num_secs, INT32 sync) +{ + INT32 count; + struct buffer_head *bh2; + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); +#if EXFAT_CONFIG_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + if (!p_bd->opened) return(FFS_MEDIAERR); + + if (secno == bh->b_blocknr) { + lock_buffer(bh); + set_buffer_uptodate(bh); + mark_buffer_dirty(bh); + unlock_buffer(bh); + if (sync && (sync_dirty_buffer(bh) != 0)) + return (FFS_MEDIAERR); + } else { + count = num_secs << p_bd->sector_size_bits; + + bh2 = __getblk(sb->s_bdev, secno, count); + + if (bh2 == NULL) + goto no_bh; + + lock_buffer(bh2); + MEMCPY(bh2->b_data, bh->b_data, count); + set_buffer_uptodate(bh2); + mark_buffer_dirty(bh2); + unlock_buffer(bh2); + if (sync && (sync_dirty_buffer(bh2) != 0)) { + __brelse(bh2); + goto no_bh; + } + __brelse(bh2); + } + + return(FFS_SUCCESS); + +no_bh: + WARN(!p_fs->dev_ejected, + "[EXFAT] No bh, device seems wrong or to be ejected.\n"); + + return (FFS_MEDIAERR); +} + +INT32 bdev_sync(struct super_block *sb) +{ + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); +#if EXFAT_CONFIG_KERNEL_DEBUG + struct exfat_sb_info *sbi = EXFAT_SB(sb); + long flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_ERROR_RW) return (FFS_MEDIAERR); +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + if (!p_bd->opened) return(FFS_MEDIAERR); + + return sync_blockdev(sb->s_bdev); +} + +/* end of exfat_blkdev.c */ diff --git a/fs/exfat/exfat_blkdev.h b/fs/exfat/exfat_blkdev.h new file mode 100644 index 00000000000..c1f0c28cacb --- /dev/null +++ b/fs/exfat/exfat_blkdev.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_blkdev.h */ +/* PURPOSE : Header File for exFAT Block Device Driver Glue Layer */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_BLKDEV_H +#define _EXFAT_BLKDEV_H + +#include "exfat_config.h" +#include "exfat_global.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions (Non-Configurable) */ + /*----------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + typedef struct __BD_INFO_T { + INT32 sector_size; // in bytes + INT32 sector_size_bits; + INT32 sector_size_mask; + INT32 num_sectors; // total number of sectors in this block device + BOOL opened; // opened or not + } BD_INFO_T; + + /*----------------------------------------------------------------------*/ + /* External Variable Declarations */ + /*----------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + INT32 bdev_init(void); + INT32 bdev_shutdown(void); + INT32 bdev_open(struct super_block *sb); + INT32 bdev_close(struct super_block *sb); + INT32 bdev_read(struct super_block *sb, UINT32 secno, struct buffer_head **bh, UINT32 num_secs, INT32 read); + INT32 bdev_write(struct super_block *sb, UINT32 secno, struct buffer_head *bh, UINT32 num_secs, INT32 sync); + INT32 bdev_sync(struct super_block *sb); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_BLKDEV_H */ + +/* end of exfat_blkdev.h */ diff --git a/fs/exfat/exfat_cache.c b/fs/exfat/exfat_cache.c new file mode 100644 index 00000000000..05c61365301 --- /dev/null +++ b/fs/exfat/exfat_cache.c @@ -0,0 +1,785 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_cache.c */ +/* PURPOSE : exFAT Cache Manager */ +/* (FAT Cache & Buffer Cache) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Sung-Kwan Kim] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" + +#include "exfat_cache.h" +#include "exfat_super.h" +#include "exfat.h" + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +extern FS_STRUCT_T fs_struct[]; + +#define sm_P(s) +#define sm_V(s) + +static INT32 __FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content); +static INT32 __FAT_write(struct super_block *sb, UINT32 loc, UINT32 content); + +static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, UINT32 sec); +static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, UINT32 sec); +static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp); +static void FAT_cache_remove_hash(BUF_CACHE_T *bp); + +static UINT8 *__buf_getblk(struct super_block *sb, UINT32 sec); + +static BUF_CACHE_T *buf_cache_find(struct super_block *sb, UINT32 sec); +static BUF_CACHE_T *buf_cache_get(struct super_block *sb, UINT32 sec); +static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp); +static void buf_cache_remove_hash(BUF_CACHE_T *bp); + +static void push_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list); +static void push_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list); +static void move_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list); +static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list); + +/*======================================================================*/ +/* Cache Initialization Functions */ +/*======================================================================*/ + +INT32 buf_init(struct super_block *sb) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + INT32 i; + + /* LRU list */ + p_fs->FAT_cache_lru_list.next = p_fs->FAT_cache_lru_list.prev = &p_fs->FAT_cache_lru_list; + + for (i = 0; i < FAT_CACHE_SIZE; i++) { + p_fs->FAT_cache_array[i].drv = -1; + p_fs->FAT_cache_array[i].sec = ~0; + p_fs->FAT_cache_array[i].flag = 0; + p_fs->FAT_cache_array[i].buf_bh = NULL; + p_fs->FAT_cache_array[i].prev = p_fs->FAT_cache_array[i].next = NULL; + push_to_mru(&(p_fs->FAT_cache_array[i]), &p_fs->FAT_cache_lru_list); + } + + p_fs->buf_cache_lru_list.next = p_fs->buf_cache_lru_list.prev = &p_fs->buf_cache_lru_list; + + for (i = 0; i < BUF_CACHE_SIZE; i++) { + p_fs->buf_cache_array[i].drv = -1; + p_fs->buf_cache_array[i].sec = ~0; + p_fs->buf_cache_array[i].flag = 0; + p_fs->buf_cache_array[i].buf_bh = NULL; + p_fs->buf_cache_array[i].prev = p_fs->buf_cache_array[i].next = NULL; + push_to_mru(&(p_fs->buf_cache_array[i]), &p_fs->buf_cache_lru_list); + } + + /* HASH list */ + for (i = 0; i < FAT_CACHE_HASH_SIZE; i++) { + p_fs->FAT_cache_hash_list[i].drv = -1; + p_fs->FAT_cache_hash_list[i].sec = ~0; + p_fs->FAT_cache_hash_list[i].hash_next = p_fs->FAT_cache_hash_list[i].hash_prev = &(p_fs->FAT_cache_hash_list[i]); + } + + for (i = 0; i < FAT_CACHE_SIZE; i++) { + FAT_cache_insert_hash(sb, &(p_fs->FAT_cache_array[i])); + } + + for (i = 0; i < BUF_CACHE_HASH_SIZE; i++) { + p_fs->buf_cache_hash_list[i].drv = -1; + p_fs->buf_cache_hash_list[i].sec = ~0; + p_fs->buf_cache_hash_list[i].hash_next = p_fs->buf_cache_hash_list[i].hash_prev = &(p_fs->buf_cache_hash_list[i]); + } + + for (i = 0; i < BUF_CACHE_SIZE; i++) { + buf_cache_insert_hash(sb, &(p_fs->buf_cache_array[i])); + } + + return(FFS_SUCCESS); +} /* end of buf_init */ + +INT32 buf_shutdown(struct super_block *sb) +{ + return(FFS_SUCCESS); +} /* end of buf_shutdown */ + +/*======================================================================*/ +/* FAT Read/Write Functions */ +/*======================================================================*/ + +/* in : sb, loc + * out: content + * returns 0 on success + * -1 on error + */ +INT32 FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content) +{ + INT32 ret; + + sm_P(&f_sem); + + ret = __FAT_read(sb, loc, content); + + sm_V(&f_sem); + + return(ret); +} /* end of FAT_read */ + +INT32 FAT_write(struct super_block *sb, UINT32 loc, UINT32 content) +{ + INT32 ret; + + sm_P(&f_sem); + + ret = __FAT_write(sb, loc, content); + + sm_V(&f_sem); + + return(ret); +} /* end of FAT_write */ + +static INT32 __FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content) +{ + INT32 off; + UINT32 sec, _content; + UINT8 *fat_sector, *fat_entry; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_fs->vol_type == FAT12) { + sec = p_fs->FAT1_start_sector + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); + off = (loc + (loc >> 1)) & p_bd->sector_size_mask; + + if (off == (p_bd->sector_size-1)) { + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + _content = (UINT32) fat_sector[off]; + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + + _content |= (UINT32) fat_sector[0] << 8; + } else { + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + _content = GET16(fat_entry); + } + + if (loc & 1) _content >>= 4; + + _content &= 0x00000FFF; + + if (_content >= CLUSTER_16(0x0FF8)) { + *content = CLUSTER_32(~0); + return 0; + } else { + *content = CLUSTER_32(_content); + return 0; + } + } else if (p_fs->vol_type == FAT16) { + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-1)); + off = (loc << 1) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + _content = GET16_A(fat_entry); + + _content &= 0x0000FFFF; + + if (_content >= CLUSTER_16(0xFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } else { + *content = CLUSTER_32(_content); + return 0; + } + } else if (p_fs->vol_type == FAT32) { + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + _content = GET32_A(fat_entry); + + _content &= 0x0FFFFFFF; + + if (_content >= CLUSTER_32(0x0FFFFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } else { + *content = CLUSTER_32(_content); + return 0; + } + } else { + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + _content = GET32_A(fat_entry); + + if (_content >= CLUSTER_32(0xFFFFFFF8)) { + *content = CLUSTER_32(~0); + return 0; + } else { + *content = CLUSTER_32(_content); + return 0; + } + } + + *content = CLUSTER_32(~0); + return 0; +} /* end of __FAT_read */ + +static INT32 __FAT_write(struct super_block *sb, UINT32 loc, UINT32 content) +{ + INT32 off; + UINT32 sec; + UINT8 *fat_sector, *fat_entry; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_fs->vol_type == FAT12) { + + content &= 0x00000FFF; + + sec = p_fs->FAT1_start_sector + ((loc + (loc >> 1)) >> p_bd->sector_size_bits); + off = (loc + (loc >> 1)) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + if (loc & 1) { /* odd */ + + content <<= 4; + + if (off == (p_bd->sector_size-1)) { + fat_sector[off] = (UINT8)(content | (fat_sector[off] & 0x0F)); + FAT_modify(sb, sec); + + fat_sector = FAT_getblk(sb, ++sec); + if (!fat_sector) + return -1; + + fat_sector[0] = (UINT8)(content >> 8); + } else { + fat_entry = &(fat_sector[off]); + content |= GET16(fat_entry) & 0x000F; + + SET16(fat_entry, content); + } + } else { /* even */ + fat_sector[off] = (UINT8)(content); + + if (off == (p_bd->sector_size-1)) { + fat_sector[off] = (UINT8)(content); + FAT_modify(sb, sec); + + fat_sector = FAT_getblk(sb, ++sec); + fat_sector[0] = (UINT8)((fat_sector[0] & 0xF0) | (content >> 8)); + } else { + fat_entry = &(fat_sector[off]); + content |= GET16(fat_entry) & 0xF000; + + SET16(fat_entry, content); + } + } + } + + else if (p_fs->vol_type == FAT16) { + + content &= 0x0000FFFF; + + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-1)); + off = (loc << 1) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + SET16_A(fat_entry, content); + } + + else if (p_fs->vol_type == FAT32) { + + content &= 0x0FFFFFFF; + + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + content |= GET32_A(fat_entry) & 0xF0000000; + + SET32_A(fat_entry, content); + } + + else { /* p_fs->vol_type == EXFAT */ + + sec = p_fs->FAT1_start_sector + (loc >> (p_bd->sector_size_bits-2)); + off = (loc << 2) & p_bd->sector_size_mask; + + fat_sector = FAT_getblk(sb, sec); + if (!fat_sector) + return -1; + + fat_entry = &(fat_sector[off]); + + SET32_A(fat_entry, content); + } + + FAT_modify(sb, sec); + return 0; +} /* end of __FAT_write */ + +UINT8 *FAT_getblk(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = FAT_cache_find(sb, sec); + if (bp != NULL) { + move_to_mru(bp, &p_fs->FAT_cache_lru_list); + return(bp->buf_bh->b_data); + } + + bp = FAT_cache_get(sb, sec); + + FAT_cache_remove_hash(bp); + + bp->drv = p_fs->drv; + bp->sec = sec; + bp->flag = 0; + + FAT_cache_insert_hash(sb, bp); + + if (sector_read(sb, sec, &(bp->buf_bh), 1) != FFS_SUCCESS) { + FAT_cache_remove_hash(bp); + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + bp->buf_bh = NULL; + + move_to_lru(bp, &p_fs->FAT_cache_lru_list); + return NULL; + } + + return(bp->buf_bh->b_data); +} /* end of FAT_getblk */ + +void FAT_modify(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + + bp = FAT_cache_find(sb, sec); + if (bp != NULL) { + sector_write(sb, sec, bp->buf_bh, 0); + } +} /* end of FAT_modify */ + +void FAT_release_all(struct super_block *sb) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&f_sem); + + bp = p_fs->FAT_cache_lru_list.next; + while (bp != &p_fs->FAT_cache_lru_list) { + if (bp->drv == p_fs->drv) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if(bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + } + bp = bp->next; + } + + sm_V(&f_sem); +} /* end of FAT_release_all */ + +void FAT_sync(struct super_block *sb) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&f_sem); + + bp = p_fs->FAT_cache_lru_list.next; + while (bp != &p_fs->FAT_cache_lru_list) { + if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { + sync_dirty_buffer(bp->buf_bh); + bp->flag &= ~(DIRTYBIT); + } + bp = bp->next; + } + + sm_V(&f_sem); +} /* end of FAT_sync */ + +static BUF_CACHE_T *FAT_cache_find(struct super_block *sb, UINT32 sec) +{ + INT32 off; + BUF_CACHE_T *bp, *hp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE - 1); + + hp = &(p_fs->FAT_cache_hash_list[off]); + for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { + if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { + + WARN(!bp->buf_bh, "[EXFAT] FAT_cache has no bh. " + "It will make system panic.\n"); + + touch_buffer(bp->buf_bh); + return(bp); + } + } + return(NULL); +} /* end of FAT_cache_find */ + +static BUF_CACHE_T *FAT_cache_get(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = p_fs->FAT_cache_lru_list.prev; + + + move_to_mru(bp, &p_fs->FAT_cache_lru_list); + return(bp); +} /* end of FAT_cache_get */ + +static void FAT_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp) +{ + INT32 off; + BUF_CACHE_T *hp; + FS_INFO_T *p_fs; + + p_fs = &(EXFAT_SB(sb)->fs_info); + off = (bp->sec + (bp->sec >> p_fs->sectors_per_clu_bits)) & (FAT_CACHE_HASH_SIZE-1); + + hp = &(p_fs->FAT_cache_hash_list[off]); + bp->hash_next = hp->hash_next; + bp->hash_prev = hp; + hp->hash_next->hash_prev = bp; + hp->hash_next = bp; +} /* end of FAT_cache_insert_hash */ + +static void FAT_cache_remove_hash(BUF_CACHE_T *bp) +{ + (bp->hash_prev)->hash_next = bp->hash_next; + (bp->hash_next)->hash_prev = bp->hash_prev; +} /* end of FAT_cache_remove_hash */ + +/*======================================================================*/ +/* Buffer Read/Write Functions */ +/*======================================================================*/ + +UINT8 *buf_getblk(struct super_block *sb, UINT32 sec) +{ + UINT8 *buf; + + sm_P(&b_sem); + + buf = __buf_getblk(sb, sec); + + sm_V(&b_sem); + + return(buf); +} /* end of buf_getblk */ + +static UINT8 *__buf_getblk(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = buf_cache_find(sb, sec); + if (bp != NULL) { + move_to_mru(bp, &p_fs->buf_cache_lru_list); + return(bp->buf_bh->b_data); + } + + bp = buf_cache_get(sb, sec); + + buf_cache_remove_hash(bp); + + bp->drv = p_fs->drv; + bp->sec = sec; + bp->flag = 0; + + buf_cache_insert_hash(sb, bp); + + if (sector_read(sb, sec, &(bp->buf_bh), 1) != FFS_SUCCESS) { + buf_cache_remove_hash(bp); + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + bp->buf_bh = NULL; + + move_to_lru(bp, &p_fs->buf_cache_lru_list); + return NULL; + } + + return(bp->buf_bh->b_data); + +} /* end of __buf_getblk */ + +void buf_modify(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + + sm_P(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp != NULL)) { + sector_write(sb, sec, bp->buf_bh, 0); + } + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); + + sm_V(&b_sem); +} /* end of buf_modify */ + +void buf_lock(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + + sm_P(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp != NULL)) bp->flag |= LOCKBIT; + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); + + sm_V(&b_sem); +} /* end of buf_lock */ + +void buf_unlock(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + + sm_P(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp != NULL)) bp->flag &= ~(LOCKBIT); + + WARN(!bp, "[EXFAT] failed to find buffer_cache(sector:%u).\n", sec); + + sm_V(&b_sem); +} /* end of buf_unlock */ + +void buf_release(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&b_sem); + + bp = buf_cache_find(sb, sec); + if (likely(bp != NULL)) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if(bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + + move_to_lru(bp, &p_fs->buf_cache_lru_list); + } + + sm_V(&b_sem); +} /* end of buf_release */ + +void buf_release_all(struct super_block *sb) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&b_sem); + + bp = p_fs->buf_cache_lru_list.next; + while (bp != &p_fs->buf_cache_lru_list) { + if (bp->drv == p_fs->drv) { + bp->drv = -1; + bp->sec = ~0; + bp->flag = 0; + + if(bp->buf_bh) { + __brelse(bp->buf_bh); + bp->buf_bh = NULL; + } + } + bp = bp->next; + } + + sm_V(&b_sem); +} /* end of buf_release_all */ + +void buf_sync(struct super_block *sb) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + sm_P(&b_sem); + + bp = p_fs->buf_cache_lru_list.next; + while (bp != &p_fs->buf_cache_lru_list) { + if ((bp->drv == p_fs->drv) && (bp->flag & DIRTYBIT)) { + sync_dirty_buffer(bp->buf_bh); + bp->flag &= ~(DIRTYBIT); + } + bp = bp->next; + } + + sm_V(&b_sem); +} /* end of buf_sync */ + +static BUF_CACHE_T *buf_cache_find(struct super_block *sb, UINT32 sec) +{ + INT32 off; + BUF_CACHE_T *bp, *hp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + off = (sec + (sec >> p_fs->sectors_per_clu_bits)) & (BUF_CACHE_HASH_SIZE - 1); + + hp = &(p_fs->buf_cache_hash_list[off]); + for (bp = hp->hash_next; bp != hp; bp = bp->hash_next) { + if ((bp->drv == p_fs->drv) && (bp->sec == sec)) { + touch_buffer(bp->buf_bh); + return(bp); + } + } + return(NULL); +} /* end of buf_cache_find */ + +static BUF_CACHE_T *buf_cache_get(struct super_block *sb, UINT32 sec) +{ + BUF_CACHE_T *bp; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + bp = p_fs->buf_cache_lru_list.prev; + while (bp->flag & LOCKBIT) bp = bp->prev; + + + move_to_mru(bp, &p_fs->buf_cache_lru_list); + return(bp); +} /* end of buf_cache_get */ + +static void buf_cache_insert_hash(struct super_block *sb, BUF_CACHE_T *bp) +{ + INT32 off; + BUF_CACHE_T *hp; + FS_INFO_T *p_fs; + + p_fs = &(EXFAT_SB(sb)->fs_info); + off = (bp->sec + (bp->sec >> p_fs->sectors_per_clu_bits)) & (BUF_CACHE_HASH_SIZE-1); + + hp = &(p_fs->buf_cache_hash_list[off]); + bp->hash_next = hp->hash_next; + bp->hash_prev = hp; + hp->hash_next->hash_prev = bp; + hp->hash_next = bp; +} /* end of buf_cache_insert_hash */ + +static void buf_cache_remove_hash(BUF_CACHE_T *bp) +{ + (bp->hash_prev)->hash_next = bp->hash_next; + (bp->hash_next)->hash_prev = bp->hash_prev; +} /* end of buf_cache_remove_hash */ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +static void push_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list) +{ + bp->next = list->next; + bp->prev = list; + list->next->prev = bp; + list->next = bp; +} /* end of buf_cache_push_to_mru */ + +static void push_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list) +{ + bp->prev = list->prev; + bp->next = list; + list->prev->next = bp; + list->prev = bp; +} /* end of buf_cache_push_to_lru */ + +static void move_to_mru(BUF_CACHE_T *bp, BUF_CACHE_T *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_mru(bp, list); +} /* end of buf_cache_move_to_mru */ + +static void move_to_lru(BUF_CACHE_T *bp, BUF_CACHE_T *list) +{ + bp->prev->next = bp->next; + bp->next->prev = bp->prev; + push_to_lru(bp, list); +} /* end of buf_cache_move_to_lru */ + +/* end of exfat_cache.c */ diff --git a/fs/exfat/exfat_cache.h b/fs/exfat/exfat_cache.h new file mode 100644 index 00000000000..056636b4e48 --- /dev/null +++ b/fs/exfat/exfat_cache.h @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_cache.h */ +/* PURPOSE : Header File for exFAT Cache Manager */ +/* (FAT Cache & Buffer Cache) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Sung-Kwan Kim] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_CACHE_H +#define _EXFAT_CACHE_H + +#include "exfat_config.h" +#include "exfat_global.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define LOCKBIT 0x01 +#define DIRTYBIT 0x02 + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + typedef struct __BUF_CACHE_T { + struct __BUF_CACHE_T *next; + struct __BUF_CACHE_T *prev; + struct __BUF_CACHE_T *hash_next; + struct __BUF_CACHE_T *hash_prev; + INT32 drv; + UINT32 sec; + UINT32 flag; + struct buffer_head *buf_bh; + } BUF_CACHE_T; + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + INT32 buf_init(struct super_block *sb); + INT32 buf_shutdown(struct super_block *sb); + INT32 FAT_read(struct super_block *sb, UINT32 loc, UINT32 *content); + INT32 FAT_write(struct super_block *sb, UINT32 loc, UINT32 content); + UINT8 *FAT_getblk(struct super_block *sb, UINT32 sec); + void FAT_modify(struct super_block *sb, UINT32 sec); + void FAT_release_all(struct super_block *sb); + void FAT_sync(struct super_block *sb); + UINT8 *buf_getblk(struct super_block *sb, UINT32 sec); + void buf_modify(struct super_block *sb, UINT32 sec); + void buf_lock(struct super_block *sb, UINT32 sec); + void buf_unlock(struct super_block *sb, UINT32 sec); + void buf_release(struct super_block *sb, UINT32 sec); + void buf_release_all(struct super_block *sb); + void buf_sync(struct super_block *sb); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_CACHE_H */ + +/* end of exfat_cache.h */ diff --git a/fs/exfat/exfat_config.h b/fs/exfat/exfat_config.h new file mode 100644 index 00000000000..d16c882f88c --- /dev/null +++ b/fs/exfat/exfat_config.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_config.h */ +/* PURPOSE : Header File for exFAT Configuable Policies */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_CONFIG_H +#define _EXFAT_CONFIG_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/*======================================================================*/ +/* */ +/* FFS CONFIGURATIONS */ +/* (CHANGE THIS PART IF REQUIRED) */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* Target OS Platform */ +/*----------------------------------------------------------------------*/ + +#define OS_NONOS 1 +#define OS_LINUX 2 + +#define FFS_CONFIG_OS OS_LINUX + +/*----------------------------------------------------------------------*/ +/* Set this definition to 1 to support APIs with pointer parameters */ +/* to 32-bit variables (e.g. read, write, seek, get_filesize) */ +/*----------------------------------------------------------------------*/ +#define FFS_CONFIG_LEGACY_32BIT_API 0 + +/*----------------------------------------------------------------------*/ +/* Set this definition to 1 to support APIs with pointer parameters */ +/* to 32-bit variables (e.g. read, write, seek, get_filesize) */ +/*----------------------------------------------------------------------*/ +#define FFS_CONFIG_LEGACY_32BIT_API 0 + +/*----------------------------------------------------------------------*/ +/* Set appropriate definitions to 1's to support the languages */ +/*----------------------------------------------------------------------*/ +#define FFS_CONFIG_SUPPORT_CP1250 1 // Central Europe +#define FFS_CONFIG_SUPPORT_CP1251 1 // Cyrillic +#define FFS_CONFIG_SUPPORT_CP1252 1 // Latin I +#define FFS_CONFIG_SUPPORT_CP1253 1 // Greek +#define FFS_CONFIG_SUPPORT_CP1254 1 // Turkish +#define FFS_CONFIG_SUPPORT_CP1255 1 // Hebrew +#define FFS_CONFIG_SUPPORT_CP1256 1 // Arabic +#define FFS_CONFIG_SUPPORT_CP1257 1 // Baltic +#define FFS_CONFIG_SUPPORT_CP1258 1 // Vietnamese +#define FFS_CONFIG_SUPPORT_CP874 1 // Thai +#define FFS_CONFIG_SUPPORT_CP932 1 // Japanese +#define FFS_CONFIG_SUPPORT_CP936 1 // Simplified Chinese +#define FFS_CONFIG_SUPPORT_CP949 1 // Korean +#define FFS_CONFIG_SUPPORT_CP950 1 // Traditional Chinese +#define FFS_CONFIG_SUPPORT_UTF8 1 // UTF8 encoding + +/*----------------------------------------------------------------------*/ +/* Feature Config */ +/*----------------------------------------------------------------------*/ +#define EXFAT_CONFIG_DISCARD 1 // mount option -o discard support +#define EXFAT_CONFIG_KERNEL_DEBUG 1 // kernel debug features via ioctl +#define EXFAT_CONFIG_DEBUG_MSG 0 // debugging message on/off + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_CONFIG_H */ + +/* end of exfat_config.h */ diff --git a/fs/exfat/exfat_core.c b/fs/exfat/exfat_core.c new file mode 100644 index 00000000000..2ab28dc32da --- /dev/null +++ b/fs/exfat/exfat_core.c @@ -0,0 +1,5187 @@ +/* Some of the source code in this file came from "linux/fs/fat/misc.c". */ +/* + * linux/fs/fat/misc.c + * + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat.c */ +/* PURPOSE : exFAT File Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat_super.h" +#include "exfat.h" + +#include + +/*----------------------------------------------------------------------*/ +/* Constant & Macro Definitions */ +/*----------------------------------------------------------------------*/ + +#define THERE_IS_MBR 0 /* if there is no MBR (e.g. memory card), +set this macro to 0 */ + +#if (THERE_IS_MBR == 1) +#include "exfat_part.h" +#endif + +#define DELAYED_SYNC 0 + +#define ELAPSED_TIME 0 + +#if (ELAPSED_TIME == 1) +#include + +static UINT32 __t1, __t2; +static UINT32 get_current_msec(void) +{ + struct timeval tm; + do_gettimeofday(&tm); + return (UINT32)(tm.tv_sec*1000000 + tm.tv_usec); +} +#define TIME_START() do {__t1 = get_current_msec(); } while (0) +#define TIME_END() do {__t2 = get_current_msec(); } while (0) +#define PRINT_TIME(n) do {printk("[EXFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1)); } while (0) +#else +#define TIME_START() +#define TIME_END() +#define PRINT_TIME(n) +#endif + +static void __set_sb_dirty(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + sb->s_dirt = 1; +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + sbi->s_dirt = 1; +#endif +} + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +extern UINT8 uni_upcase[]; + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +static UINT8 name_buf[MAX_PATH_LENGTH *MAX_CHARSET_SIZE]; + +static INT8 *reserved_names[] = { + "AUX ", "CON ", "NUL ", "PRN ", + "COM1 ", "COM2 ", "COM3 ", "COM4 ", + "COM5 ", "COM6 ", "COM7 ", "COM8 ", "COM9 ", + "LPT1 ", "LPT2 ", "LPT3 ", "LPT4 ", + "LPT5 ", "LPT6 ", "LPT7 ", "LPT8 ", "LPT9 ", + NULL +}; + +static UINT8 free_bit[] = { + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 0 ~ 19 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, /* 20 ~ 39 */ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 40 ~ 59 */ + 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 60 ~ 79 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, /* 80 ~ 99 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, /* 100 ~ 119 */ + 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 120 ~ 139 */ + 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, /* 140 ~ 159 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, /* 160 ~ 179 */ + 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, /* 180 ~ 199 */ + 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, /* 200 ~ 219 */ + 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, /* 220 ~ 239 */ + 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 /* 240 ~ 254 */ +}; + +static UINT8 used_bit[] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, /* 0 ~ 19 */ + 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, /* 20 ~ 39 */ + 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, /* 40 ~ 59 */ + 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, /* 60 ~ 79 */ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, /* 80 ~ 99 */ + 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, /* 100 ~ 119 */ + 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, /* 120 ~ 139 */ + 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, /* 140 ~ 159 */ + 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, /* 160 ~ 179 */ + 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, /* 180 ~ 199 */ + 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, /* 200 ~ 219 */ + 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, /* 220 ~ 239 */ + 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 /* 240 ~ 255 */ +}; + +/*======================================================================*/ +/* Global Function Definitions */ +/*======================================================================*/ + +/* ffsInit : roll back to the initial state of the file system */ +INT32 ffsInit(void) +{ + INT32 ret; + + ret = bdev_init(); + if (ret) + return ret; + + ret = fs_init(); + if (ret) + return ret; + + return FFS_SUCCESS; +} /* end of ffsInit */ + +/* ffsShutdown : make free all memory-alloced global buffers */ +INT32 ffsShutdown(void) +{ + INT32 ret; + ret = fs_shutdown(); + if (ret) + return ret; + + ret = bdev_shutdown(); + if (ret) + return ret; + + return FFS_SUCCESS; +} /* end of ffsShutdown */ + +/* ffsMountVol : mount the file system volume */ +INT32 ffsMountVol(struct super_block *sb, INT32 drv) +{ + INT32 i, ret; +#if (THERE_IS_MBR == 1) + MBR_SECTOR_T *p_mbr; + PART_ENTRY_T *p_pte; +#endif + PBR_SECTOR_T *p_pbr; + struct buffer_head *tmp_bh = NULL; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + PRINTK("[EXFAT] trying to mount...\n"); + + p_fs->drv = drv; + p_fs->dev_ejected = FALSE; + + /* open the block device */ + if (bdev_open(sb)) + return FFS_MEDIAERR; + + if (p_bd->sector_size < sb->s_blocksize) + return FFS_MEDIAERR; + if (p_bd->sector_size > sb->s_blocksize) + sb_set_blocksize(sb, p_bd->sector_size); + + /* read Sector 0 */ + if (sector_read(sb, 0, &tmp_bh, 1) != FFS_SUCCESS) + return FFS_MEDIAERR; + +#if (THERE_IS_MBR == 1) + if (buf[0] != 0xEB) { + /* MBR is read */ + p_mbr = (MBR_SECTOR_T *) tmp_bh->b_data; + + /* check the validity of MBR */ + if (GET16_A(p_mbr->signature) != MBR_SIGNATURE) { + brelse(tmp_bh); + bdev_close(sb); + return FFS_FORMATERR; + } + + p_pte = (PART_ENTRY_T *) p_mbr->partition + 0; + p_fs->PBR_sector = GET32(p_pte->start_sector); + p_fs->num_sectors = GET32(p_pte->num_sectors); + + if (p_fs->num_sectors == 0) { + brelse(tmp_bh); + bdev_close(sb); + return FFS_ERROR; + } + + /* read PBR */ + if (sector_read(sb, p_fs->PBR_sector, &tmp_bh, 1) != FFS_SUCCESS) { + bdev_close(sb); + return FFS_MEDIAERR; + } + } else { +#endif + /* PRB is read */ + p_fs->PBR_sector = 0; +#if (THERE_IS_MBR == 1) + } +#endif + + p_pbr = (PBR_SECTOR_T *) tmp_bh->b_data; + + /* check the validity of PBR */ + if (GET16_A(p_pbr->signature) != PBR_SIGNATURE) { + brelse(tmp_bh); + bdev_close(sb); + return FFS_FORMATERR; + } + + /* fill fs_stuct */ + for (i = 0; i < 53; i++) + if (p_pbr->bpb[i]) + break; + + if (i < 53) { + if (GET16(p_pbr->bpb+11)) /* num_fat_sectors */ + ret = fat16_mount(sb, p_pbr); + else + ret = fat32_mount(sb, p_pbr); + } else { + ret = exfat_mount(sb, p_pbr); + } + + brelse(tmp_bh); + + if (ret) { + bdev_close(sb); + return ret; + } + + if (p_fs->vol_type == EXFAT) { + ret = load_alloc_bitmap(sb); + if (ret) { + bdev_close(sb); + return ret; + } + ret = load_upcase_table(sb); + if (ret) { + free_alloc_bitmap(sb); + bdev_close(sb); + return ret; + } + } + + if (p_fs->dev_ejected) { + if (p_fs->vol_type == EXFAT) { + free_upcase_table(sb); + free_alloc_bitmap(sb); + } + bdev_close(sb); + return FFS_MEDIAERR; + } + + PRINTK("[EXFAT] mounted successfully\n"); + return FFS_SUCCESS; +} /* end of ffsMountVol */ + +/* ffsUmountVol : umount the file system volume */ +INT32 ffsUmountVol(struct super_block *sb) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + PRINTK("[EXFAT] trying to unmount...\n"); + + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); + + if (p_fs->vol_type == EXFAT) { + free_upcase_table(sb); + free_alloc_bitmap(sb); + } + + FAT_release_all(sb); + buf_release_all(sb); + + /* close the block device */ + bdev_close(sb); + + if (p_fs->dev_ejected) { + PRINTK( "[EXFAT] unmounted with media errors. " + "device's already ejected.\n"); + return FFS_MEDIAERR; + } + + PRINTK("[EXFAT] unmounted successfully\n"); + return FFS_SUCCESS; +} /* end of ffsUmountVol */ + +/* ffsGetVolInfo : get the information of a file system volume */ +INT32 ffsGetVolInfo(struct super_block *sb, VOL_INFO_T *info) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->used_clusters == (UINT32) ~0) + p_fs->used_clusters = p_fs->fs_func->count_used_clusters(sb); + + info->FatType = p_fs->vol_type; + info->ClusterSize = p_fs->cluster_size; + info->NumClusters = p_fs->num_clusters - 2; /* clu 0 & 1 */ + info->UsedClusters = p_fs->used_clusters; + info->FreeClusters = info->NumClusters - info->UsedClusters; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsGetVolInfo */ + +/* ffsSyncVol : synchronize all file system volumes */ +INT32 ffsSyncVol(struct super_block *sb, INT32 do_sync) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* synchronize the file system */ + fs_sync(sb, do_sync); + fs_set_vol_flags(sb, VOL_CLEAN); + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsSyncVol */ + +/*----------------------------------------------------------------------*/ +/* File Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* ffsLookupFile : lookup a file */ +INT32 ffsLookupFile(struct inode *inode, UINT8 *path, FILE_ID_T *fid) +{ + INT32 ret, dentry, num_entries; + CHAIN_T dir; + UNI_NAME_T uni_name; + DOS_NAME_T dos_name; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es=NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + PRINTK("ffsLookupFile entered\n"); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + return ret; + + ret = get_num_entries_and_dos_name(sb, &dir, &uni_name, &num_entries, &dos_name); + if (ret) + return ret; + + /* search the file name for directories */ + dentry = p_fs->fs_func->find_dir_entry(sb, &dir, &uni_name, num_entries, &dos_name, TYPE_ALL); + if (dentry < -1) + return FFS_NOTFOUND; + + fid->dir.dir = dir.dir; + fid->dir.size = dir.size; + fid->dir.flags = dir.flags; + fid->entry = dentry; + + if (dentry == -1) { + fid->type = TYPE_DIR; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + fid->attr = ATTR_SUBDIR; + fid->flags = 0x01; + fid->size = 0; + fid->start_clu = p_fs->root_dir; + } else { + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &dir, dentry, ES_2_ENTRIES, &ep); + if (!es) + return FFS_MEDIAERR; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &dir, dentry, NULL); + if (!ep) + return FFS_MEDIAERR; + ep2 = ep; + } + + fid->type = p_fs->fs_func->get_entry_type(ep); + fid->rwoffset = 0; + fid->hint_last_off = -1; + fid->attr = p_fs->fs_func->get_entry_attr(ep); + + fid->size = p_fs->fs_func->get_entry_size(ep2); + if ((fid->type == TYPE_FILE) && (fid->size == 0)) { + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUSTER_32(~0); + } else { + fid->flags = p_fs->fs_func->get_entry_flag(ep2); + fid->start_clu = p_fs->fs_func->get_entry_clu0(ep2); + } + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + } + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + PRINTK("ffsLookupFile exited successfully\n"); + + return FFS_SUCCESS; +} /* end of ffsLookupFile */ + +/* ffsCreateFile : create a file */ +INT32 ffsCreateFile(struct inode *inode, UINT8 *path, UINT8 mode, FILE_ID_T *fid) +{ + INT32 ret/*, dentry*/; + CHAIN_T dir; + UNI_NAME_T uni_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + /* check the validity of directory name in the given pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + return ret; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* create a new file */ + ret = create_file(inode, &dir, &uni_name, mode, fid); + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return ret; +} /* end of ffsCreateFile */ + +/* ffsReadFile : read data from a opened file */ +INT32 ffsReadFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *rcount) +{ + INT32 offset, sec_offset, clu_offset; + UINT32 clu, LogSector; + UINT64 oneblkread, read_bytes; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) + return FFS_PERMISSIONERR; + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count > (fid->size - fid->rwoffset)) + count = fid->size - fid->rwoffset; + + if (count == 0) { + if (rcount != NULL) + *rcount = 0; + return FFS_EOF; + } + + read_bytes = 0; + + while (count > 0) { + clu_offset = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + clu = fid->start_clu; + + if (fid->flags == 0x03) { + clu += clu_offset; + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu = fid->hint_last_clu; + } + + while (clu_offset > 0) { + /* clu = FAT_read(sb, clu); */ + if (FAT_read(sb, clu, &clu) == -1) + return FFS_MEDIAERR; + + clu_offset--; + } + } + + /* hint information */ + fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + fid->hint_last_clu = clu; + + offset = (INT32)(fid->rwoffset & (p_fs->cluster_size-1)); /* byte offset in cluster */ + sec_offset = offset >> p_bd->sector_size_bits; /* sector offset in cluster */ + offset &= p_bd->sector_size_mask; /* byte offset in sector */ + + LogSector = START_SECTOR(clu) + sec_offset; + + oneblkread = (UINT64)(p_bd->sector_size - offset); + if (oneblkread > count) + oneblkread = count; + + if ((offset == 0) && (oneblkread == p_bd->sector_size)) { + if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS) + goto err_out; + MEMCPY(((INT8 *) buffer)+read_bytes, ((INT8 *) tmp_bh->b_data), (INT32) oneblkread); + } else { + if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS) + goto err_out; + MEMCPY(((INT8 *) buffer)+read_bytes, ((INT8 *) tmp_bh->b_data)+offset, (INT32) oneblkread); + } + count -= oneblkread; + read_bytes += oneblkread; + fid->rwoffset += oneblkread; + } + brelse(tmp_bh); + +err_out: + /* set the size of read bytes */ + if (rcount != NULL) + *rcount = read_bytes; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsReadFile */ + +/* ffsWriteFile : write data into a opened file */ +INT32 ffsWriteFile(struct inode *inode, FILE_ID_T *fid, void *buffer, UINT64 count, UINT64 *wcount) +{ + INT32 modified = FALSE, offset, sec_offset, clu_offset; + INT32 num_clusters, num_alloc, num_alloced = (INT32) ~0; + UINT32 clu, last_clu, LogSector, sector = 0; + UINT64 oneblkwrite, write_bytes; + CHAIN_T new_clu; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es = NULL; + struct buffer_head *tmp_bh = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) + return FFS_PERMISSIONERR; + + if (fid->rwoffset > fid->size) + fid->rwoffset = fid->size; + + if (count == 0) { + if (wcount != NULL) + *wcount = 0; + return FFS_SUCCESS; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (fid->size == 0) + num_clusters = 0; + else + num_clusters = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + + write_bytes = 0; + + while (count > 0) { + clu_offset = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + clu = CLUSTER_32(~0); + else + clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu = fid->hint_last_clu; + } + + while ((clu_offset > 0) && (clu != CLUSTER_32(~0))) { + last_clu = clu; + /* clu = FAT_read(sb, clu); */ + if (FAT_read(sb, clu, &clu) == -1) + return FFS_MEDIAERR; + + clu_offset--; + } + } + + if (clu == CLUSTER_32(~0)) { + num_alloc = (INT32)((count-1) >> p_fs->cluster_size_bits) + 1; + new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu+1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a chain of clusters */ + num_alloced = p_fs->fs_func->alloc_cluster(sb, num_alloc, &new_clu); + if (num_alloced == 0) + break; + + /* (2) append to the FAT chain */ + if (last_clu == CLUSTER_32(~0)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = TRUE; + } else { + if (new_clu.flags != fid->flags) { + exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters); + fid->flags = 0x01; + modified = TRUE; + } + if (new_clu.flags == 0x01) + FAT_write(sb, last_clu, new_clu.dir); + } + + num_clusters += num_alloced; + clu = new_clu.dir; + } + + /* hint information */ + fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + fid->hint_last_clu = clu; + + offset = (INT32)(fid->rwoffset & (p_fs->cluster_size-1)); /* byte offset in cluster */ + sec_offset = offset >> p_bd->sector_size_bits; /* sector offset in cluster */ + offset &= p_bd->sector_size_mask; /* byte offset in sector */ + + LogSector = START_SECTOR(clu) + sec_offset; + + oneblkwrite = (UINT64)(p_bd->sector_size - offset); + if (oneblkwrite > count) + oneblkwrite = count; + + if ((offset == 0) && (oneblkwrite == p_bd->sector_size)) { + if (sector_read(sb, LogSector, &tmp_bh, 0) != FFS_SUCCESS) + goto err_out; + MEMCPY(((INT8 *) tmp_bh->b_data), ((INT8 *) buffer)+write_bytes, (INT32) oneblkwrite); + if (sector_write(sb, LogSector, tmp_bh, 0) != FFS_SUCCESS) { + brelse(tmp_bh); + goto err_out; + } + } else { + if ((offset > 0) || ((fid->rwoffset+oneblkwrite) < fid->size)) { + if (sector_read(sb, LogSector, &tmp_bh, 1) != FFS_SUCCESS) + goto err_out; + } else { + if (sector_read(sb, LogSector, &tmp_bh, 0) != FFS_SUCCESS) + goto err_out; + } + + MEMCPY(((INT8 *) tmp_bh->b_data)+offset, ((INT8 *) buffer)+write_bytes, (INT32) oneblkwrite); + if (sector_write(sb, LogSector, tmp_bh, 0) != FFS_SUCCESS) { + brelse(tmp_bh); + goto err_out; + } + } + + count -= oneblkwrite; + write_bytes += oneblkwrite; + fid->rwoffset += oneblkwrite; + + fid->attr |= ATTR_ARCHIVE; + + if (fid->size < fid->rwoffset) { + fid->size = fid->rwoffset; + modified = TRUE; + } + } + + brelse(tmp_bh); + + /* (3) update the direcoty entry */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + goto err_out; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + goto err_out; + ep2 = ep; + } + + p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); + p_fs->fs_func->set_entry_attr(ep, fid->attr); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + + if (modified) { + if (p_fs->fs_func->get_entry_flag(ep2) != fid->flags) + p_fs->fs_func->set_entry_flag(ep2, fid->flags); + + if (p_fs->fs_func->get_entry_size(ep2) != fid->size) + p_fs->fs_func->set_entry_size(ep2, fid->size); + + if (p_fs->fs_func->get_entry_clu0(ep2) != fid->start_clu) + p_fs->fs_func->set_entry_clu0(ep2, fid->start_clu); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + } + + if (p_fs->vol_type == EXFAT) { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + +err_out: + /* set the size of written bytes */ + if (wcount != NULL) + *wcount = write_bytes; + + if (num_alloced == 0) + return FFS_FULL; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsWriteFile */ + +/* ffsTruncateFile : resize the file length */ +INT32 ffsTruncateFile(struct inode *inode, UINT64 old_size, UINT64 new_size) +{ + INT32 num_clusters; + UINT32 last_clu = CLUSTER_32(0), sector = 0; + CHAIN_T clu; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + ENTRY_SET_CACHE_T *es=NULL; + + /* check if the given file ID is opened */ + if (fid->type != TYPE_FILE) + return FFS_PERMISSIONERR; + + if (fid->size != old_size) { + printk(KERN_ERR "[EXFAT] truncate : can't skip it because of " + "size-mismatch(old:%lld->fid:%lld).\n" + ,old_size, fid->size); + } + + if (old_size <= new_size) + return FFS_SUCCESS; + + fs_set_vol_flags(sb, VOL_DIRTY); + + clu.dir = fid->start_clu; + clu.size = (INT32)((old_size-1) >> p_fs->cluster_size_bits) + 1; + clu.flags = fid->flags; + + if (new_size > 0) { + num_clusters = (INT32)((new_size-1) >> p_fs->cluster_size_bits) + 1; + + if (clu.flags == 0x03) { + clu.dir += num_clusters; + } else { + while (num_clusters > 0) { + last_clu = clu.dir; + if (FAT_read(sb, clu.dir, &(clu.dir)) == -1) + return FFS_MEDIAERR; + num_clusters--; + } + } + + clu.size -= num_clusters; + } + + fid->size = new_size; + fid->attr |= ATTR_ARCHIVE; + if (new_size == 0) { + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->start_clu = CLUSTER_32(~0); + } + + /* (1) update the directory entry */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + ep2 = ep; + } + + p_fs->fs_func->set_entry_time(ep, tm_current(&tm), TM_MODIFY); + p_fs->fs_func->set_entry_attr(ep, fid->attr); + + p_fs->fs_func->set_entry_size(ep2, new_size); + if (new_size == 0) { + p_fs->fs_func->set_entry_flag(ep2, 0x01); + p_fs->fs_func->set_entry_clu0(ep2, CLUSTER_32(0)); + } + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + /* (2) cut off from the FAT chain */ + if (last_clu != CLUSTER_32(0)) { + if (fid->flags == 0x01) + FAT_write(sb, last_clu, CLUSTER_32(~0)); + } + + /* (3) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu, 0); + + /* hint information */ + fid->hint_last_off = -1; + if (fid->rwoffset > fid->size) { + fid->rwoffset = fid->size; + } + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsTruncateFile */ + +static void update_parent_info( FILE_ID_T *fid, struct inode *parent_inode) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(parent_inode->i_sb)->fs_info); + FILE_ID_T *parent_fid = &(EXFAT_I(parent_inode)->fid); + + if (unlikely((parent_fid->flags != fid->dir.flags) + || (parent_fid->size != (fid->dir.size<cluster_size_bits)) + || (parent_fid->start_clu != fid->dir.dir))) { + + fid->dir.dir = parent_fid->start_clu; + fid->dir.flags = parent_fid->flags; + fid->dir.size = ((parent_fid->size + (p_fs->cluster_size-1)) + >> p_fs->cluster_size_bits); + } +} + +/* ffsMoveFile : move(rename) a old file into a new file */ +INT32 ffsMoveFile(struct inode *old_parent_inode, FILE_ID_T *fid, struct inode *new_parent_inode, struct dentry *new_dentry) +{ + INT32 ret; + INT32 dentry; + CHAIN_T olddir, newdir; + CHAIN_T *p_dir=NULL; + UNI_NAME_T uni_name; + DENTRY_T *ep; + struct super_block *sb = old_parent_inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + UINT8 *new_path = (UINT8 *) new_dentry->d_name.name; + struct inode *new_inode = new_dentry->d_inode; + int num_entries; + FILE_ID_T *new_fid = NULL; + INT32 new_entry=0; + + /* check the validity of pointer parameters */ + if ((new_path == NULL) || (*new_path == '\0')) + return FFS_ERROR; + + update_parent_info(fid, old_parent_inode); + + olddir.dir = fid->dir.dir; + olddir.size = fid->dir.size; + olddir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the old file is "." or ".." */ + if (p_fs->vol_type != EXFAT) { + if ((olddir.dir != p_fs->root_dir) && (dentry < 2)) + return FFS_PERMISSIONERR; + } + + ep = get_entry_in_dir(sb, &olddir, dentry, NULL); + if (!ep) + return FFS_MEDIAERR; + + if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) + return FFS_PERMISSIONERR; + + /* check whether new dir is existing directory and empty */ + if (new_inode) { + UINT32 entry_type; + + ret = FFS_MEDIAERR; + new_fid = &EXFAT_I(new_inode)->fid; + + update_parent_info(new_fid, new_parent_inode); + + p_dir = &(new_fid->dir); + new_entry = new_fid->entry; + ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_DIR) { + CHAIN_T new_clu; + new_clu.dir = new_fid->start_clu; + new_clu.size = (INT32)((new_fid->size-1) >> p_fs->cluster_size_bits) + 1; + new_clu.flags = new_fid->flags; + + if (!is_dir_empty(sb, &new_clu)) + return FFS_FILEEXIST; + } + } + + /* check the validity of directory name in the given new pathname */ + ret = resolve_path(new_parent_inode, new_path, &newdir, &uni_name); + if (ret) + return ret; + + fs_set_vol_flags(sb, VOL_DIRTY); + + if (olddir.dir == newdir.dir) + ret = rename_file(new_parent_inode, &olddir, dentry, &uni_name, fid); + else + ret = move_file(new_parent_inode, &olddir, dentry, &newdir, &uni_name, fid); + + if ((ret == FFS_SUCCESS) && new_inode) { + /* delete entries of new_dir */ + ep = get_entry_in_dir(sb, p_dir, new_entry, NULL); + if (!ep) + goto out; + + num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, new_entry, ep); + if (num_entries < 0) + goto out; + p_fs->fs_func->delete_dir_entry(sb, p_dir, new_entry, 0, num_entries+1); + } +out: +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return ret; +} /* end of ffsMoveFile */ + +/* ffsRemoveFile : remove a file */ +INT32 ffsRemoveFile(struct inode *inode, FILE_ID_T *fid) +{ + INT32 dentry; + CHAIN_T dir, clu_to_free; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + ep = get_entry_in_dir(sb, &dir, dentry, NULL); + if (!ep) + return FFS_MEDIAERR; + + if (p_fs->fs_func->get_entry_attr(ep) & ATTR_READONLY) + return FFS_PERMISSIONERR; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + remove_file(inode, &dir, dentry); + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + /* (2) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu_to_free, 0); + + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + fid->flags = (p_fs->vol_type == EXFAT)? 0x03: 0x01; + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsRemoveFile */ + +/* ffsSetAttr : set the attribute of a given file */ +INT32 ffsSetAttr(struct inode *inode, UINT32 attr) +{ + UINT32 type, sector = 0; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + ENTRY_SET_CACHE_T *es = NULL; + + if (fid->attr == attr) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + } + + /* get the directory entry of given file */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + } + + type = p_fs->fs_func->get_entry_type(ep); + + if (((type == TYPE_FILE) && (attr & ATTR_SUBDIR)) || + ((type == TYPE_DIR) && (!(attr & ATTR_SUBDIR)))) { + INT32 err; + if (p_fs->dev_ejected) + err = FFS_MEDIAERR; + else + err = FFS_ERROR; + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + return err; + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* set the file attribute */ + fid->attr = attr; + p_fs->fs_func->set_entry_attr(ep, attr); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsSetAttr */ + +/* ffsGetStat : get the information of a given file */ +INT32 ffsGetStat(struct inode *inode, DIR_ENTRY_T *info) +{ + UINT32 sector = 0; + INT32 count; + CHAIN_T dir; + UNI_NAME_T uni_name; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + ENTRY_SET_CACHE_T *es=NULL; + UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + PRINTK("ffsGetStat entered\n"); + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + info->Attr = ATTR_SUBDIR; + MEMSET((INT8 *) &info->CreateTimestamp, 0, sizeof(DATE_TIME_T)); + MEMSET((INT8 *) &info->ModifyTimestamp, 0, sizeof(DATE_TIME_T)); + MEMSET((INT8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + STRCPY(info->ShortName, "."); + STRCPY(info->Name, "."); + + dir.dir = p_fs->root_dir; + dir.flags = 0x01; + + if (p_fs->root_dir == CLUSTER_32(0)) /* FAT16 root_dir */ + info->Size = p_fs->dentries_in_root << DENTRY_SIZE_BITS; + else + info->Size = count_num_clusters(sb, &dir) << p_fs->cluster_size_bits; + + count = count_dos_name_entries(sb, &dir, TYPE_DIR); + if (count < 0) + return FFS_MEDIAERR; + info->NumSubdirs = count; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + } + + /* get the directory entry of given file or directory */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_2_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + ep2 = ep+1; + } else { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + ep2 = ep; + buf_lock(sb, sector); + } + + /* set FILE_INFO structure using the acquired DENTRY_T */ + info->Attr = p_fs->fs_func->get_entry_attr(ep); + + p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE); + info->CreateTimestamp.Year = tm.year; + info->CreateTimestamp.Month = tm.mon; + info->CreateTimestamp.Day = tm.day; + info->CreateTimestamp.Hour = tm.hour; + info->CreateTimestamp.Minute = tm.min; + info->CreateTimestamp.Second = tm.sec; + info->CreateTimestamp.MilliSecond = 0; + + p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + info->ModifyTimestamp.Year = tm.year; + info->ModifyTimestamp.Month = tm.mon; + info->ModifyTimestamp.Day = tm.day; + info->ModifyTimestamp.Hour = tm.hour; + info->ModifyTimestamp.Minute = tm.min; + info->ModifyTimestamp.Second = tm.sec; + info->ModifyTimestamp.MilliSecond = 0; + + MEMSET((INT8 *) &info->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + + *(uni_name.name) = 0x0; + /* XXX this is very bad for exfat cuz name is already included in es. + API should be revised */ + p_fs->fs_func->get_uni_name_from_ext_entry(sb, &(fid->dir), fid->entry, uni_name.name); + if (*(uni_name.name) == 0x0) + get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1); + nls_uniname_to_cstring(sb, info->Name, &uni_name); + + if (p_fs->vol_type == EXFAT) { + info->NumSubdirs = 2; + } else { + buf_unlock(sb, sector); + get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0); + nls_uniname_to_cstring(sb, info->ShortName, &uni_name); + info->NumSubdirs = 0; + } + + info->Size = p_fs->fs_func->get_entry_size(ep2); + + if (p_fs->vol_type == EXFAT) + release_entry_set(es); + + if (is_dir) { + dir.dir = fid->start_clu; + dir.flags = 0x01; + + if (info->Size == 0) + info->Size = (UINT64) count_num_clusters(sb, &dir) << p_fs->cluster_size_bits; + + count = count_dos_name_entries(sb, &dir, TYPE_DIR); + if (count < 0) + return FFS_MEDIAERR; + info->NumSubdirs += count; + } + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + PRINTK("ffsGetStat exited successfully\n"); + return FFS_SUCCESS; +} /* end of ffsGetStat */ + +/* ffsSetStat : set the information of a given file */ +INT32 ffsSetStat(struct inode *inode, DIR_ENTRY_T *info) +{ + UINT32 sector = 0; + TIMESTAMP_T tm; + DENTRY_T *ep, *ep2; + ENTRY_SET_CACHE_T *es=NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + UINT8 is_dir = (fid->type == TYPE_DIR) ? 1 : 0; + + if (is_dir) { + if ((fid->dir.dir == p_fs->root_dir) && + (fid->entry == -1)) { + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + return FFS_SUCCESS; + } + } + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* get the directory entry of given file or directory */ + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + ep2 = ep+1; + } else { + /* for other than exfat */ + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + ep2 = ep; + } + + + p_fs->fs_func->set_entry_attr(ep, info->Attr); + + /* set FILE_INFO structure using the acquired DENTRY_T */ + tm.sec = info->CreateTimestamp.Second; + tm.min = info->CreateTimestamp.Minute; + tm.hour = info->CreateTimestamp.Hour; + tm.day = info->CreateTimestamp.Day; + tm.mon = info->CreateTimestamp.Month; + tm.year = info->CreateTimestamp.Year; + p_fs->fs_func->set_entry_time(ep, &tm, TM_CREATE); + + tm.sec = info->ModifyTimestamp.Second; + tm.min = info->ModifyTimestamp.Minute; + tm.hour = info->ModifyTimestamp.Hour; + tm.day = info->ModifyTimestamp.Day; + tm.mon = info->ModifyTimestamp.Month; + tm.year = info->ModifyTimestamp.Year; + p_fs->fs_func->set_entry_time(ep, &tm, TM_MODIFY); + + + p_fs->fs_func->set_entry_size(ep2, info->Size); + + if (p_fs->vol_type != EXFAT) { + buf_modify(sb, sector); + } else { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsSetStat */ + +INT32 ffsMapCluster(struct inode *inode, INT32 clu_offset, UINT32 *clu) +{ + INT32 num_clusters, num_alloced, modified = FALSE; + UINT32 last_clu, sector = 0; + CHAIN_T new_clu; + DENTRY_T *ep; + ENTRY_SET_CACHE_T *es = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + + fid->rwoffset = (INT64)(clu_offset) << p_fs->cluster_size_bits; + + if (EXFAT_I(inode)->mmu_private == 0) + num_clusters = 0; + else + num_clusters = (INT32)((EXFAT_I(inode)->mmu_private-1) >> p_fs->cluster_size_bits) + 1; + + *clu = last_clu = fid->start_clu; + + if (fid->flags == 0x03) { + if ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { + last_clu += clu_offset - 1; + + if (clu_offset == num_clusters) + *clu = CLUSTER_32(~0); + else + *clu += clu_offset; + } + } else { + /* hint information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + *clu = fid->hint_last_clu; + } + + while ((clu_offset > 0) && (*clu != CLUSTER_32(~0))) { + last_clu = *clu; + if (FAT_read(sb, *clu, clu) == -1) + return FFS_MEDIAERR; + clu_offset--; + } + } + + if (*clu == CLUSTER_32(~0)) { + fs_set_vol_flags(sb, VOL_DIRTY); + + new_clu.dir = (last_clu == CLUSTER_32(~0)) ? CLUSTER_32(~0) : last_clu+1; + new_clu.size = 0; + new_clu.flags = fid->flags; + + /* (1) allocate a cluster */ + num_alloced = p_fs->fs_func->alloc_cluster(sb, 1, &new_clu); + if (num_alloced < 1) + return FFS_FULL; + + /* (2) append to the FAT chain */ + if (last_clu == CLUSTER_32(~0)) { + if (new_clu.flags == 0x01) + fid->flags = 0x01; + fid->start_clu = new_clu.dir; + modified = TRUE; + } else { + if (new_clu.flags != fid->flags) { + exfat_chain_cont_cluster(sb, fid->start_clu, num_clusters); + fid->flags = 0x01; + modified = TRUE; + } + if (new_clu.flags == 0x01) + FAT_write(sb, last_clu, new_clu.dir); + } + + *clu = new_clu.dir; + + if (p_fs->vol_type == EXFAT) { + es = get_entry_set_in_dir(sb, &(fid->dir), fid->entry, ES_ALL_ENTRIES, &ep); + if (es == NULL) + return FFS_MEDIAERR; + /* get stream entry */ + ep++; + } + + /* (3) update directory entry */ + if (modified) { + if (p_fs->vol_type != EXFAT) { + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry, §or); + if (!ep) + return FFS_MEDIAERR; + } + + if (p_fs->fs_func->get_entry_flag(ep) != fid->flags) + p_fs->fs_func->set_entry_flag(ep, fid->flags); + + if (p_fs->fs_func->get_entry_clu0(ep) != fid->start_clu) + p_fs->fs_func->set_entry_clu0(ep, fid->start_clu); + + if (p_fs->vol_type != EXFAT) + buf_modify(sb, sector); + } + + if (p_fs->vol_type == EXFAT) { + update_dir_checksum_with_entry_set(sb, es); + release_entry_set(es); + } + + /* add number of new blocks to inode */ + inode->i_blocks += num_alloced << (p_fs->cluster_size_bits - 9); + } + + /* hint information */ + fid->hint_last_off = (INT32)(fid->rwoffset >> p_fs->cluster_size_bits); + fid->hint_last_clu = *clu; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsMapCluster */ + +/*----------------------------------------------------------------------*/ +/* Directory Operation Functions */ +/*----------------------------------------------------------------------*/ + +/* ffsCreateDir : create(make) a directory */ +INT32 ffsCreateDir(struct inode *inode, UINT8 *path, FILE_ID_T *fid) +{ + INT32 ret/*, dentry*/; + CHAIN_T dir; + UNI_NAME_T uni_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + PRINTK("ffsCreateDir entered\n"); + + /* check the validity of directory name in the given old pathname */ + ret = resolve_path(inode, path, &dir, &uni_name); + if (ret) + return ret; + + fs_set_vol_flags(sb, VOL_DIRTY); + + ret = create_dir(inode, &dir, &uni_name, fid); + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return ret; +} /* end of ffsCreateDir */ + +/* ffsReadDir : read a directory entry from the opened directory */ +INT32 ffsReadDir(struct inode *inode, DIR_ENTRY_T *dir_entry) +{ + INT32 i, dentry, clu_offset; + INT32 dentries_per_clu, dentries_per_clu_bits = 0; + UINT32 type, sector; + CHAIN_T dir, clu; + UNI_NAME_T uni_name; + TIMESTAMP_T tm; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + + /* check if the given file ID is opened */ + if (fid->type != TYPE_DIR) + return FFS_PERMISSIONERR; + + if (fid->entry == -1) { + dir.dir = p_fs->root_dir; + dir.flags = 0x01; + } else { + dir.dir = fid->start_clu; + dir.size = (INT32)(fid->size >> p_fs->cluster_size_bits); + dir.flags = fid->flags; + } + + dentry = (INT32) fid->rwoffset; + + if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + + if (dentry == dentries_per_clu) { + clu.dir = CLUSTER_32(~0); + } else { + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + } + } else { + dentries_per_clu = p_fs->dentries_per_clu; + dentries_per_clu_bits = my_log2(dentries_per_clu); + + clu_offset = dentry >> dentries_per_clu_bits; + clu.dir = dir.dir; + clu.size = dir.size; + clu.flags = dir.flags; + + if (clu.flags == 0x03) { + clu.dir += clu_offset; + clu.size -= clu_offset; + } else { + /* hint_information */ + if ((clu_offset > 0) && (fid->hint_last_off > 0) && + (clu_offset >= fid->hint_last_off)) { + clu_offset -= fid->hint_last_off; + clu.dir = fid->hint_last_clu; + } + + while (clu_offset > 0) { + /* clu.dir = FAT_read(sb, clu.dir); */ + if (FAT_read(sb, clu.dir, &(clu.dir)) == -1) + return FFS_MEDIAERR; + + clu_offset--; + } + } + } + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + if (dir.dir == CLUSTER_32(0)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu-1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, §or); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + break; + + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + buf_lock(sb, sector); + dir_entry->Attr = p_fs->fs_func->get_entry_attr(ep); + + p_fs->fs_func->get_entry_time(ep, &tm, TM_CREATE); + dir_entry->CreateTimestamp.Year = tm.year; + dir_entry->CreateTimestamp.Month = tm.mon; + dir_entry->CreateTimestamp.Day = tm.day; + dir_entry->CreateTimestamp.Hour = tm.hour; + dir_entry->CreateTimestamp.Minute = tm.min; + dir_entry->CreateTimestamp.Second = tm.sec; + dir_entry->CreateTimestamp.MilliSecond = 0; + + p_fs->fs_func->get_entry_time(ep, &tm, TM_MODIFY); + dir_entry->ModifyTimestamp.Year = tm.year; + dir_entry->ModifyTimestamp.Month = tm.mon; + dir_entry->ModifyTimestamp.Day = tm.day; + dir_entry->ModifyTimestamp.Hour = tm.hour; + dir_entry->ModifyTimestamp.Minute = tm.min; + dir_entry->ModifyTimestamp.Second = tm.sec; + dir_entry->ModifyTimestamp.MilliSecond = 0; + + MEMSET((INT8 *) &dir_entry->AccessTimestamp, 0, sizeof(DATE_TIME_T)); + + *(uni_name.name) = 0x0; + p_fs->fs_func->get_uni_name_from_ext_entry(sb, &dir, dentry, uni_name.name); + if (*(uni_name.name) == 0x0) + get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x1); + nls_uniname_to_cstring(sb, dir_entry->Name, &uni_name); + buf_unlock(sb, sector); + + if (p_fs->vol_type == EXFAT) { + ep = get_entry_in_dir(sb, &clu, i+1, NULL); + if (!ep) + return FFS_MEDIAERR; + } else { + get_uni_name_from_dos_entry(sb, (DOS_DENTRY_T *) ep, &uni_name, 0x0); + nls_uniname_to_cstring(sb, dir_entry->ShortName, &uni_name); + } + + dir_entry->Size = p_fs->fs_func->get_entry_size(ep); + + /* hint information */ + if (dir.dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + } else { + fid->hint_last_off = dentry >> dentries_per_clu_bits; + fid->hint_last_clu = clu.dir; + } + + fid->rwoffset = (INT64) ++dentry; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; + } + + if (dir.dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + /* clu.dir = FAT_read(sb, clu.dir); */ + if (FAT_read(sb, clu.dir, &(clu.dir)) == -1) + return FFS_MEDIAERR; + } + } + + *(dir_entry->Name) = '\0'; + + fid->rwoffset = (INT64) ++dentry; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsReadDir */ + +/* ffsRemoveDir : remove a directory */ +INT32 ffsRemoveDir(struct inode *inode, FILE_ID_T *fid) +{ + INT32 dentry; + CHAIN_T dir, clu_to_free; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + dir.dir = fid->dir.dir; + dir.size = fid->dir.size; + dir.flags = fid->dir.flags; + + dentry = fid->entry; + + /* check if the file is "." or ".." */ + if (p_fs->vol_type != EXFAT) { + if ((dir.dir != p_fs->root_dir) && (dentry < 2)) + return FFS_PERMISSIONERR; + } + + clu_to_free.dir = fid->start_clu; + clu_to_free.size = (INT32)((fid->size-1) >> p_fs->cluster_size_bits) + 1; + clu_to_free.flags = fid->flags; + + if (!is_dir_empty(sb, &clu_to_free)) + return FFS_FILEEXIST; + + fs_set_vol_flags(sb, VOL_DIRTY); + + /* (1) update the directory entry */ + remove_file(inode, &dir, dentry); + + /* (2) free the clusters */ + p_fs->fs_func->free_cluster(sb, &clu_to_free, 1); + + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + fid->flags = (p_fs->vol_type == EXFAT)? 0x03: 0x01; + +#if (DELAYED_SYNC == 0) + fs_sync(sb, 0); + fs_set_vol_flags(sb, VOL_CLEAN); +#endif + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + return FFS_SUCCESS; +} /* end of ffsRemoveDir */ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +/* + * File System Management Functions + */ + +INT32 fs_init(void) +{ + /* critical check for system requirement on size of DENTRY_T structure */ + if (sizeof(DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(DOS_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(EXT_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(FILE_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(STRM_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(NAME_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(BMAP_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(CASE_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + if (sizeof(VOLM_DENTRY_T) != DENTRY_SIZE) { + return FFS_ALIGNMENTERR; + } + + return FFS_SUCCESS; +} /* end of fs_init */ + +INT32 fs_shutdown(void) +{ + return FFS_SUCCESS; +} /* end of fs_shutdown */ + +void fs_set_vol_flags(struct super_block *sb, UINT32 new_flag) +{ + PBR_SECTOR_T *p_pbr; + BPBEX_T *p_bpb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->vol_flag == new_flag) + return; + + p_fs->vol_flag = new_flag; + + if (p_fs->vol_type == EXFAT) { + if (p_fs->pbr_bh == NULL) { + if (sector_read(sb, p_fs->PBR_sector, &(p_fs->pbr_bh), 1) != FFS_SUCCESS) + return; + } + + p_pbr = (PBR_SECTOR_T *) p_fs->pbr_bh->b_data; + p_bpb = (BPBEX_T *) p_pbr->bpb; + SET16(p_bpb->vol_flags, (UINT16) new_flag); + + /* XXX duyoung + what can we do here? (cuz fs_set_vol_flags() is void) */ + if ((new_flag == VOL_DIRTY) && (!buffer_dirty(p_fs->pbr_bh))) + sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 1); + else + sector_write(sb, p_fs->PBR_sector, p_fs->pbr_bh, 0); + } +} /* end of fs_set_vol_flags */ + +void fs_sync(struct super_block *sb, INT32 do_sync) +{ + if (do_sync) + bdev_sync(sb); +} /* end of fs_sync */ + +void fs_error(struct super_block *sb) +{ + struct exfat_mount_options *opts = &EXFAT_SB(sb)->options; + + if (opts->errors == EXFAT_ERRORS_PANIC) + panic("[EXFAT] Filesystem panic from previous error\n"); + else if ((opts->errors == EXFAT_ERRORS_RO) && !(sb->s_flags & MS_RDONLY)) { + sb->s_flags |= MS_RDONLY; + printk(KERN_ERR "[EXFAT] Filesystem has been set read-only\n"); + } +} + +/* + * Cluster Management Functions + */ + +INT32 clear_cluster(struct super_block *sb, UINT32 clu) +{ + UINT32 s, n; + INT32 ret = FFS_SUCCESS; + struct buffer_head *tmp_bh = NULL; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (clu == CLUSTER_32(0)) { /* FAT16 root_dir */ + s = p_fs->root_start_sector; + n = p_fs->data_start_sector; + } else { + s = START_SECTOR(clu); + n = s + p_fs->sectors_per_clu; + } + + for ( ; s < n; s++) { + if ((ret = sector_read(sb, s, &tmp_bh, 0)) != FFS_SUCCESS) + return ret; + + MEMSET((INT8 *) tmp_bh->b_data, 0x0, p_bd->sector_size); + if ((ret = sector_write(sb, s, tmp_bh, 0)) !=FFS_SUCCESS) + break; + } + + brelse(tmp_bh); + return ret; +} /* end of clear_cluster */ + +INT32 fat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain) +{ + INT32 i, num_clusters = 0; + UINT32 new_clu, last_clu = CLUSTER_32(~0), read_clu; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + new_clu = p_chain->dir; + if (new_clu == CLUSTER_32(~0)) + new_clu = p_fs->clu_srch_ptr; + else if (new_clu >= p_fs->num_clusters) + new_clu = 2; + + __set_sb_dirty(sb); + + p_chain->dir = CLUSTER_32(~0); + + for (i = 2; i < p_fs->num_clusters; i++) { + if (FAT_read(sb, new_clu, &read_clu) != 0) + return 0; + + if (read_clu == CLUSTER_32(0)) { + FAT_write(sb, new_clu, CLUSTER_32(~0)); + num_clusters++; + + if (p_chain->dir == CLUSTER_32(~0)) + p_chain->dir = new_clu; + else + FAT_write(sb, last_clu, new_clu); + + last_clu = new_clu; + + if ((--num_alloc) == 0) { + p_fs->clu_srch_ptr = new_clu; + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters += num_clusters; + + return(num_clusters); + } + } + if ((++new_clu) >= p_fs->num_clusters) + new_clu = 2; + } + + p_fs->clu_srch_ptr = new_clu; + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters += num_clusters; + + return(num_clusters); +} /* end of fat_alloc_cluster */ + +INT32 exfat_alloc_cluster(struct super_block *sb, INT32 num_alloc, CHAIN_T *p_chain) +{ + INT32 num_clusters = 0; + UINT32 hint_clu, new_clu, last_clu = CLUSTER_32(~0); + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + hint_clu = p_chain->dir; + if (hint_clu == CLUSTER_32(~0)) { + hint_clu = test_alloc_bitmap(sb, p_fs->clu_srch_ptr-2); + if (hint_clu == CLUSTER_32(~0)) + return 0; + } else if (hint_clu >= p_fs->num_clusters) { + hint_clu = 2; + p_chain->flags = 0x01; + } + + __set_sb_dirty(sb); + + p_chain->dir = CLUSTER_32(~0); + + while ((new_clu = test_alloc_bitmap(sb, hint_clu-2)) != CLUSTER_32(~0)) { + if (new_clu != hint_clu) { + if (p_chain->flags == 0x03) { + exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters); + p_chain->flags = 0x01; + } + } + + if (set_alloc_bitmap(sb, new_clu-2) != FFS_SUCCESS) + return 0; + + num_clusters++; + + if (p_chain->flags == 0x01) + FAT_write(sb, new_clu, CLUSTER_32(~0)); + + if (p_chain->dir == CLUSTER_32(~0)) { + p_chain->dir = new_clu; + } else { + if (p_chain->flags == 0x01) + FAT_write(sb, last_clu, new_clu); + } + last_clu = new_clu; + + if ((--num_alloc) == 0) { + p_fs->clu_srch_ptr = hint_clu; + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return(num_clusters); + } + + hint_clu = new_clu + 1; + if (hint_clu >= p_fs->num_clusters) { + hint_clu = 2; + + if (p_chain->flags == 0x03) { + exfat_chain_cont_cluster(sb, p_chain->dir, num_clusters); + p_chain->flags = 0x01; + } + } + } + + p_fs->clu_srch_ptr = hint_clu; + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters += num_clusters; + + p_chain->size += num_clusters; + return(num_clusters); +} /* end of exfat_alloc_cluster */ + +void fat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse) +{ + INT32 num_clusters = 0; + UINT32 clu, prev; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + INT32 i; + UINT32 sector; + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return; + __set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->size <= 0) + return; + + do { + if (p_fs->dev_ejected) + break; + + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) { + buf_release(sb, sector+i); + } + } + + prev = clu; + if (FAT_read(sb, clu, &clu) == -1) + break; + + FAT_write(sb, prev, CLUSTER_32(0)); + num_clusters++; + + } while (clu != CLUSTER_32(~0)); + + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters -= num_clusters; +} /* end of fat_free_cluster */ + +void exfat_free_cluster(struct super_block *sb, CHAIN_T *p_chain, INT32 do_relse) +{ + INT32 num_clusters = 0; + UINT32 clu; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + INT32 i; + UINT32 sector; + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return; + + if (p_chain->size <= 0) { + printk(KERN_ERR "[EXFAT] free_cluster : skip free-req clu:%u, " + "because of zero-size truncation\n" + ,p_chain->dir); + return; + } + + __set_sb_dirty(sb); + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + do { + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) { + buf_release(sb, sector+i); + } + } + + if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS) + break; + clu++; + + num_clusters++; + } while (num_clusters < p_chain->size); + } else { + do { + if (p_fs->dev_ejected) + break; + + if (do_relse) { + sector = START_SECTOR(clu); + for (i = 0; i < p_fs->sectors_per_clu; i++) { + buf_release(sb, sector+i); + } + } + + if (clr_alloc_bitmap(sb, clu-2) != FFS_SUCCESS) + break; + + if (FAT_read(sb, clu, &clu) == -1) + break; + num_clusters++; + } while ((clu != CLUSTER_32(0)) && (clu != CLUSTER_32(~0))); + } + + if (p_fs->used_clusters != (UINT32) ~0) + p_fs->used_clusters -= num_clusters; +} /* end of exfat_free_cluster */ + +UINT32 find_last_cluster(struct super_block *sb, CHAIN_T *p_chain) +{ + UINT32 clu, next; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + clu += p_chain->size - 1; + } else { + while((FAT_read(sb, clu, &next) == 0) && (next != CLUSTER_32(~0))) { + if (p_fs->dev_ejected) + break; + clu = next; + } + } + + return(clu); +} /* end of find_last_cluster */ + +INT32 count_num_clusters(struct super_block *sb, CHAIN_T *p_chain) +{ + INT32 i, count = 0; + UINT32 clu; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((p_chain->dir == CLUSTER_32(0)) || (p_chain->dir == CLUSTER_32(~0))) + return 0; + + clu = p_chain->dir; + + if (p_chain->flags == 0x03) { + count = p_chain->size; + } else { + for (i = 2; i < p_fs->num_clusters; i++) { + count++; + if (FAT_read(sb, clu, &clu) != 0) + return 0; + if (clu == CLUSTER_32(~0)) + break; + } + } + + return(count); +} /* end of count_num_clusters */ + +INT32 fat_count_used_clusters(struct super_block *sb) +{ + INT32 i, count = 0; + UINT32 clu; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = 2; i < p_fs->num_clusters; i++) { + if (FAT_read(sb, i, &clu) != 0) + break; + if (clu != CLUSTER_32(0)) + count++; + } + + return(count); +} /* end of fat_count_used_clusters */ + +INT32 exfat_count_used_clusters(struct super_block *sb) +{ + INT32 i, map_i, map_b, count = 0; + UINT8 k; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + map_i = map_b = 0; + + for (i = 2; i < p_fs->num_clusters; i += 8) { + k = *(((UINT8 *) p_fs->vol_amap[map_i]->b_data) + map_b); + count += used_bit[k]; + + if ((++map_b) >= p_bd->sector_size) { + map_i++; + map_b = 0; + } + } + + return(count); +} /* end of exfat_count_used_clusters */ + +void exfat_chain_cont_cluster(struct super_block *sb, UINT32 chain, INT32 len) +{ + if (len == 0) + return; + + while (len > 1) { + FAT_write(sb, chain, chain+1); + chain++; + len--; + } + FAT_write(sb, chain, CLUSTER_32(~0)); +} /* end of exfat_chain_cont_cluster */ + +/* + * Allocation Bitmap Management Functions + */ + +INT32 load_alloc_bitmap(struct super_block *sb) +{ + INT32 i, j, ret; + UINT32 map_size; + UINT32 type, sector; + CHAIN_T clu; + BMAP_DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu.dir = p_fs->root_dir; + clu.flags = 0x01; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < p_fs->dentries_per_clu; i++) { + ep = (BMAP_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_BITMAP) + continue; + + if (ep->flags == 0x0) { + p_fs->map_clu = GET32_A(ep->start_clu); + map_size = (UINT32) GET64_A(ep->size); + + p_fs->map_sectors = ((map_size-1) >> p_bd->sector_size_bits) + 1; + + p_fs->vol_amap = (struct buffer_head **) MALLOC(sizeof(struct buffer_head *) * p_fs->map_sectors); + if (p_fs->vol_amap == NULL) + return FFS_MEMORYERR; + + sector = START_SECTOR(p_fs->map_clu); + + for (j = 0; j < p_fs->map_sectors; j++) { + p_fs->vol_amap[j] = NULL; + ret = sector_read(sb, sector+j, &(p_fs->vol_amap[j]), 1); + if (ret != FFS_SUCCESS) { + /* release all buffers and free vol_amap */ + i=0; + while (i < j) + brelse(p_fs->vol_amap[i++]); + + FREE(p_fs->vol_amap); + p_fs->vol_amap = NULL; + return ret; + } + } + + p_fs->pbr_bh = NULL; + return FFS_SUCCESS; + } + } + + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return FFS_MEDIAERR; + } + + return FFS_FORMATERR; +} /* end of load_alloc_bitmap */ + +void free_alloc_bitmap(struct super_block *sb) +{ + INT32 i; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + brelse(p_fs->pbr_bh); + + for (i = 0; i < p_fs->map_sectors; i++) { + __brelse(p_fs->vol_amap[i]); + } + + FREE(p_fs->vol_amap); + p_fs->vol_amap = NULL; +} /* end of free_alloc_bitmap */ + +INT32 set_alloc_bitmap(struct super_block *sb, UINT32 clu) +{ + INT32 i, b; + UINT32 sector; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + i = clu >> (p_bd->sector_size_bits + 3); + b = clu & ((p_bd->sector_size << 3) - 1); + + sector = START_SECTOR(p_fs->map_clu) + i; + + Bitmap_set((UINT8 *) p_fs->vol_amap[i]->b_data, b); + + return (sector_write(sb, sector, p_fs->vol_amap[i], 0)); +} /* end of set_alloc_bitmap */ + +INT32 clr_alloc_bitmap(struct super_block *sb, UINT32 clu) +{ + INT32 i, b; + UINT32 sector; +#if EXFAT_CONFIG_DISCARD + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_mount_options *opts = &sbi->options; + int ret; +#endif /* EXFAT_CONFIG_DISCARD */ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + i = clu >> (p_bd->sector_size_bits + 3); + b = clu & ((p_bd->sector_size << 3) - 1); + + sector = START_SECTOR(p_fs->map_clu) + i; + + Bitmap_clear((UINT8 *) p_fs->vol_amap[i]->b_data, b); + + return (sector_write(sb, sector, p_fs->vol_amap[i], 0)); + +#if EXFAT_CONFIG_DISCARD + if (opts->discard) { +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits)); +#else + ret = sb_issue_discard(sb, START_SECTOR(clu), (1 << p_fs->sectors_per_clu_bits), GFP_NOFS, 0); +#endif + if (ret == -EOPNOTSUPP) { + printk(KERN_WARNING "discard not supported by device, disabling"); + opts->discard = 0; + } + } +#endif /* EXFAT_CONFIG_DISCARD */ +} /* end of clr_alloc_bitmap */ + +UINT32 test_alloc_bitmap(struct super_block *sb, UINT32 clu) +{ + INT32 i, map_i, map_b; + UINT32 clu_base, clu_free; + UINT8 k, clu_mask; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu_base = (clu & ~(0x7)) + 2; + clu_mask = (1 << (clu - clu_base + 2)) - 1; + + map_i = clu >> (p_bd->sector_size_bits + 3); + map_b = (clu >> 3) & p_bd->sector_size_mask; + + for (i = 2; i < p_fs->num_clusters; i += 8) { + k = *(((UINT8 *) p_fs->vol_amap[map_i]->b_data) + map_b); + if (clu_mask > 0) { + k |= clu_mask; + clu_mask = 0; + } + if (k < 0xFF) { + clu_free = clu_base + free_bit[k]; + if (clu_free < p_fs->num_clusters) + return(clu_free); + } + clu_base += 8; + + if (((++map_b) >= p_bd->sector_size) || (clu_base >= p_fs->num_clusters)) { + if ((++map_i) >= p_fs->map_sectors) { + clu_base = 2; + map_i = 0; + } + map_b = 0; + } + } + + return(CLUSTER_32(~0)); +} /* end of test_alloc_bitmap */ + +void sync_alloc_bitmap(struct super_block *sb) +{ + INT32 i; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_fs->vol_amap == NULL) + return; + + for (i = 0; i < p_fs->map_sectors; i++) { + sync_dirty_buffer(p_fs->vol_amap[i]); + } +} /* end of sync_alloc_bitmap */ + +/* + * Upcase table Management Functions + */ +INT32 __load_upcase_table(struct super_block *sb, UINT32 sector, UINT32 num_sectors, UINT32 utbl_checksum) +{ + INT32 i, ret = FFS_ERROR; + UINT32 j; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + struct buffer_head *tmp_bh = NULL; + + UINT8 skip = FALSE; + UINT32 index = 0; + UINT16 uni = 0; + UINT16 **upcase_table; + + UINT32 checksum = 0; + + upcase_table = p_fs->vol_utbl = (UINT16 **) MALLOC(UTBL_COL_COUNT * sizeof(UINT16 *)); + if(upcase_table == NULL) + return FFS_MEMORYERR; + MEMSET(upcase_table, 0, UTBL_COL_COUNT * sizeof(UINT16 *)); + + num_sectors += sector; + + while(sector < num_sectors) { + ret = sector_read(sb, sector, &tmp_bh, 1); + if (ret != FFS_SUCCESS) { + PRINTK("sector read (0x%X)fail\n", sector); + goto error; + } + sector++; + + for(i = 0; i < p_bd->sector_size && index <= 0xFFFF; i += 2) { + uni = GET16(((UINT8 *) tmp_bh->b_data)+i); + + checksum = ((checksum & 1) ? 0x80000000 : 0 ) + (checksum >> 1) + *(((UINT8 *) tmp_bh->b_data)+i); + checksum = ((checksum & 1) ? 0x80000000 : 0 ) + (checksum >> 1) + *(((UINT8 *) tmp_bh->b_data)+(i+1)); + + if(skip) { + PRINTK("skip from 0x%X ", index); + index += uni; + PRINTK("to 0x%X (amount of 0x%X)\n", index, uni); + skip = FALSE; + } else if(uni == index) + index++; + else if(uni == 0xFFFF) + skip = TRUE; + else { /* uni != index , uni != 0xFFFF */ + UINT16 col_index = get_col_index(index); + + if(upcase_table[col_index]== NULL) { + PRINTK("alloc = 0x%X\n", col_index); + upcase_table[col_index] = (UINT16 *) MALLOC(UTBL_ROW_COUNT * sizeof(UINT16)); + if(upcase_table[col_index] == NULL) { + ret = FFS_MEMORYERR; + goto error; + } + + for(j = 0 ; j < UTBL_ROW_COUNT ; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index++; + } + } + } + if(index >= 0xFFFF && utbl_checksum == checksum) { + if(tmp_bh) + brelse(tmp_bh); + return FFS_SUCCESS; + } + ret = FFS_ERROR; +error: + if(tmp_bh) + brelse(tmp_bh); + free_upcase_table(sb); + return ret; +} + +INT32 __load_default_upcase_table(struct super_block *sb) +{ + INT32 i, ret = FFS_ERROR; + UINT32 j; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + UINT8 skip = FALSE; + UINT32 index = 0; + UINT16 uni = 0; + UINT16 **upcase_table; + + upcase_table = p_fs->vol_utbl = (UINT16 **) MALLOC(UTBL_COL_COUNT * sizeof(UINT16 *)); + if(upcase_table == NULL) + return FFS_MEMORYERR; + MEMSET(upcase_table, 0, UTBL_COL_COUNT * sizeof(UINT16 *)); + + for(i = 0; index <= 0xFFFF && i < NUM_UPCASE*2; i += 2) { + uni = GET16(uni_upcase + i); + if(skip) { + PRINTK("skip from 0x%X ", index); + index += uni; + PRINTK("to 0x%X (amount of 0x%X)\n", index, uni); + skip = FALSE; + } else if(uni == index) + index++; + else if(uni == 0xFFFF) + skip = TRUE; + else { /* uni != index , uni != 0xFFFF */ + UINT16 col_index = get_col_index(index); + + if(upcase_table[col_index]== NULL) { + PRINTK("alloc = 0x%X\n", col_index); + upcase_table[col_index] = (UINT16 *) MALLOC(UTBL_ROW_COUNT * sizeof(UINT16)); + if(upcase_table[col_index] == NULL) { + ret = FFS_MEMORYERR; + goto error; + } + + for(j = 0 ; j < UTBL_ROW_COUNT ; j++) + upcase_table[col_index][j] = (col_index << LOW_INDEX_BIT) | j; + } + + upcase_table[col_index][get_row_index(index)] = uni; + index ++; + } + } + + if(index >= 0xFFFF) + return FFS_SUCCESS; + +error: + /* FATAL error: default upcase table has error */ + free_upcase_table(sb); + return ret; +} + +INT32 load_upcase_table(struct super_block *sb) +{ + INT32 i; + UINT32 tbl_clu, tbl_size; + UINT32 type, sector, num_sectors; + CHAIN_T clu; + CASE_DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + clu.dir = p_fs->root_dir; + clu.flags = 0x01; + + if (p_fs->dev_ejected) + return FFS_MEDIAERR; + + while (clu.dir != CLUSTER_32(~0)) { + for (i = 0; i < p_fs->dentries_per_clu; i++) { + ep = (CASE_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep); + + if (type == TYPE_UNUSED) + break; + if (type != TYPE_UPCASE) + continue; + + tbl_clu = GET32_A(ep->start_clu); + tbl_size = (UINT32) GET64_A(ep->size); + + sector = START_SECTOR(tbl_clu); + num_sectors = ((tbl_size-1) >> p_bd->sector_size_bits) + 1; + if(__load_upcase_table(sb, sector, num_sectors, GET32_A(ep->checksum)) != FFS_SUCCESS) + break; + else + return FFS_SUCCESS; + } + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return FFS_MEDIAERR; + } + /* load default upcase table */ + return __load_default_upcase_table(sb); +} /* end of load_upcase_table */ + +void free_upcase_table(struct super_block *sb) +{ + UINT32 i; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + UINT16 **upcase_table; + + upcase_table = p_fs->vol_utbl; + for(i = 0 ; i < UTBL_COL_COUNT ; i ++) + FREE(upcase_table[i]); + + FREE(p_fs->vol_utbl); + + p_fs->vol_utbl = NULL; +} /* end of free_upcase_table */ + +/* + * Directory Entry Management Functions + */ + +UINT32 fat_get_entry_type(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + if (*(ep->name) == 0x0) + return TYPE_UNUSED; + + else if (*(ep->name) == 0xE5) + return TYPE_DELETED; + + else if (ep->attr == ATTR_EXTEND) + return TYPE_EXTEND; + + else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_VOLUME) + return TYPE_VOLUME; + + else if ((ep->attr & (ATTR_SUBDIR|ATTR_VOLUME)) == ATTR_SUBDIR) + return TYPE_DIR; + + return TYPE_FILE; +} /* end of fat_get_entry_type */ + +UINT32 exfat_get_entry_type(DENTRY_T *p_entry) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + if (ep->type == 0x0) { + return TYPE_UNUSED; + } else if (ep->type < 0x80) { + return TYPE_DELETED; + } else if (ep->type == 0x80) { + return TYPE_INVALID; + } else if (ep->type < 0xA0) { + if (ep->type == 0x81) { + return TYPE_BITMAP; + } else if (ep->type == 0x82) { + return TYPE_UPCASE; + } else if (ep->type == 0x83) { + return TYPE_VOLUME; + } else if (ep->type == 0x85) { + if (GET16_A(ep->attr) & ATTR_SUBDIR) + return TYPE_DIR; + else + return TYPE_FILE; + } + return TYPE_CRITICAL_PRI; + } else if (ep->type < 0xC0) { + if (ep->type == 0xA0) { + return TYPE_GUID; + } else if (ep->type == 0xA1) { + return TYPE_PADDING; + } else if (ep->type == 0xA2) { + return TYPE_ACLTAB; + } + return TYPE_BENIGN_PRI; + } else if (ep->type < 0xE0) { + if (ep->type == 0xC0) { + return TYPE_STREAM; + } else if (ep->type == 0xC1) { + return TYPE_EXTEND; + } else if (ep->type == 0xC2) { + return TYPE_ACL; + } + return TYPE_CRITICAL_SEC; + } + + return TYPE_BENIGN_SEC; +} /* end of exfat_get_entry_type */ + +void fat_set_entry_type(DENTRY_T *p_entry, UINT32 type) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + if (type == TYPE_UNUSED) + *(ep->name) = 0x0; + + else if (type == TYPE_DELETED) + *(ep->name) = 0xE5; + + else if (type == TYPE_EXTEND) + ep->attr = ATTR_EXTEND; + + else if (type == TYPE_DIR) + ep->attr = ATTR_SUBDIR; + + else if (type == TYPE_FILE) + ep->attr = ATTR_ARCHIVE; + + else if (type == TYPE_SYMLINK) + ep->attr = ATTR_ARCHIVE | ATTR_SYMLINK; +} /* end of fat_set_entry_type */ + +void exfat_set_entry_type(DENTRY_T *p_entry, UINT32 type) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + if (type == TYPE_UNUSED) { + ep->type = 0x0; + } else if (type == TYPE_DELETED) { + ep->type &= ~0x80; + } else if (type == TYPE_STREAM) { + ep->type = 0xC0; + } else if (type == TYPE_EXTEND) { + ep->type = 0xC1; + } else if (type == TYPE_BITMAP) { + ep->type = 0x81; + } else if (type == TYPE_UPCASE) { + ep->type = 0x82; + } else if (type == TYPE_VOLUME) { + ep->type = 0x83; + } else if (type == TYPE_DIR) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_SUBDIR); + } else if (type == TYPE_FILE) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_ARCHIVE); + } else if (type == TYPE_SYMLINK) { + ep->type = 0x85; + SET16_A(ep->attr, ATTR_ARCHIVE | ATTR_SYMLINK); + } +} /* end of exfat_set_entry_type */ + +UINT32 fat_get_entry_attr(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + return((UINT32) ep->attr); +} /* end of fat_get_entry_attr */ + +UINT32 exfat_get_entry_attr(DENTRY_T *p_entry) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + return((UINT32) GET16_A(ep->attr)); +} /* end of exfat_get_entry_attr */ + +void fat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + ep->attr = (UINT8) attr; +} /* end of fat_set_entry_attr */ + +void exfat_set_entry_attr(DENTRY_T *p_entry, UINT32 attr) +{ + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + SET16_A(ep->attr, (UINT16) attr); +} /* end of exfat_set_entry_attr */ + +UINT8 fat_get_entry_flag(DENTRY_T *p_entry) +{ + return 0x01; +} /* end of fat_get_entry_flag */ + +UINT8 exfat_get_entry_flag(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + return(ep->flags); +} /* end of exfat_get_entry_flag */ + +void fat_set_entry_flag(DENTRY_T *p_entry, UINT8 flags) +{ +} /* end of fat_set_entry_flag */ + +void exfat_set_entry_flag(DENTRY_T *p_entry, UINT8 flags) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + ep->flags = flags; +} /* end of exfat_set_entry_flag */ + +UINT32 fat_get_entry_clu0(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + return((GET32_A(ep->start_clu_hi) << 16) | GET16_A(ep->start_clu_lo)); +} /* end of fat_get_entry_clu0 */ + +UINT32 exfat_get_entry_clu0(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + return(GET32_A(ep->start_clu)); +} /* end of exfat_get_entry_clu0 */ + +void fat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); + SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); +} /* end of fat_set_entry_clu0 */ + +void exfat_set_entry_clu0(DENTRY_T *p_entry, UINT32 start_clu) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + SET32_A(ep->start_clu, start_clu); +} /* end of exfat_set_entry_clu0 */ + +UINT64 fat_get_entry_size(DENTRY_T *p_entry) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + return((UINT64) GET32_A(ep->size)); +} /* end of fat_get_entry_size */ + +UINT64 exfat_get_entry_size(DENTRY_T *p_entry) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + return(GET64_A(ep->valid_size)); +} /* end of exfat_get_entry_size */ + +void fat_set_entry_size(DENTRY_T *p_entry, UINT64 size) +{ + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + SET32_A(ep->size, (UINT32) size); +} /* end of fat_set_entry_size */ + +void exfat_set_entry_size(DENTRY_T *p_entry, UINT64 size) +{ + STRM_DENTRY_T *ep = (STRM_DENTRY_T *) p_entry; + SET64_A(ep->valid_size, size); + SET64_A(ep->size, size); +} /* end of exfat_set_entry_size */ + +void fat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode) +{ + UINT16 t = 0x00, d = 0x21; + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + switch (mode) { + case TM_CREATE: + t = GET16_A(ep->create_time); + d = GET16_A(ep->create_date); + break; + case TM_MODIFY: + t = GET16_A(ep->modify_time); + d = GET16_A(ep->modify_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} /* end of fat_get_entry_time */ + +void exfat_get_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode) +{ + UINT16 t = 0x00, d = 0x21; + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + switch (mode) { + case TM_CREATE: + t = GET16_A(ep->create_time); + d = GET16_A(ep->create_date); + break; + case TM_MODIFY: + t = GET16_A(ep->modify_time); + d = GET16_A(ep->modify_date); + break; + case TM_ACCESS: + t = GET16_A(ep->access_time); + d = GET16_A(ep->access_date); + break; + } + + tp->sec = (t & 0x001F) << 1; + tp->min = (t >> 5) & 0x003F; + tp->hour = (t >> 11); + tp->day = (d & 0x001F); + tp->mon = (d >> 5) & 0x000F; + tp->year = (d >> 9); +} /* end of exfat_get_entry_time */ + +void fat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode) +{ + UINT16 t, d; + DOS_DENTRY_T *ep = (DOS_DENTRY_T *) p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + SET16_A(ep->create_time, t); + SET16_A(ep->create_date, d); + break; + case TM_MODIFY: + SET16_A(ep->modify_time, t); + SET16_A(ep->modify_date, d); + break; + } +} /* end of fat_set_entry_time */ + +void exfat_set_entry_time(DENTRY_T *p_entry, TIMESTAMP_T *tp, UINT8 mode) +{ + UINT16 t, d; + FILE_DENTRY_T *ep = (FILE_DENTRY_T *) p_entry; + + t = (tp->hour << 11) | (tp->min << 5) | (tp->sec >> 1); + d = (tp->year << 9) | (tp->mon << 5) | tp->day; + + switch (mode) { + case TM_CREATE: + SET16_A(ep->create_time, t); + SET16_A(ep->create_date, d); + break; + case TM_MODIFY: + SET16_A(ep->modify_time, t); + SET16_A(ep->modify_date, d); + break; + case TM_ACCESS: + SET16_A(ep->access_time, t); + SET16_A(ep->access_date, d); + break; + } +} /* end of exfat_set_entry_time */ + +INT32 fat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, + UINT32 start_clu, UINT64 size) +{ + UINT32 sector; + DOS_DENTRY_T *dos_ep; + + dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!dos_ep) + return FFS_MEDIAERR; + + init_dos_entry(dos_ep, type, start_clu); + buf_modify(sb, sector); + + return FFS_SUCCESS; +} /* end of fat_init_dir_entry */ + +INT32 exfat_init_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, + UINT32 start_clu, UINT64 size) +{ + UINT32 sector; + UINT8 flags; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + + flags = (type == TYPE_FILE) ? 0x01 : 0x03; + + /* we cannot use get_entry_set_in_dir here because file ep is not initialized yet */ + file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return FFS_MEDIAERR; + + strm_ep = (STRM_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+1, §or); + if (!strm_ep) + return FFS_MEDIAERR; + + init_file_entry(file_ep, type); + buf_modify(sb, sector); + + init_strm_entry(strm_ep, flags, start_clu, size); + buf_modify(sb, sector); + + return FFS_SUCCESS; +} /* end of exfat_init_dir_entry */ + +INT32 fat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, + UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) +{ + INT32 i; + UINT32 sector; + UINT8 chksum; + UINT16 *uniname = p_uniname->name; + DOS_DENTRY_T *dos_ep; + EXT_DENTRY_T *ext_ep; + + dos_ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!dos_ep) + return FFS_MEDIAERR; + + dos_ep->lcase = p_dosname->name_case; + MEMCPY(dos_ep->name, p_dosname->name, DOS_NAME_LENGTH); + buf_modify(sb, sector); + + if ((--num_entries) > 0) { + chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0); + + for (i = 1; i < num_entries; i++) { + ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry-i, §or); + if (!ext_ep) + return FFS_MEDIAERR; + + init_ext_entry(ext_ep, i, chksum, uniname); + buf_modify(sb, sector); + uniname += 13; + } + + ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry-i, §or); + if (!ext_ep) + return FFS_MEDIAERR; + + init_ext_entry(ext_ep, i+0x40, chksum, uniname); + buf_modify(sb, sector); + } + + return FFS_SUCCESS; +} /* end of fat_init_ext_entry */ + +INT32 exfat_init_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 num_entries, + UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) +{ + INT32 i; + UINT32 sector; + UINT16 *uniname = p_uniname->name; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + NAME_DENTRY_T *name_ep; + + file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return FFS_MEDIAERR; + + file_ep->num_ext = (UINT8)(num_entries - 1); + buf_modify(sb, sector); + + strm_ep = (STRM_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+1, §or); + if (!strm_ep) + return FFS_MEDIAERR; + + strm_ep->name_len = p_uniname->name_len; + SET16_A(strm_ep->name_hash, p_uniname->name_hash); + buf_modify(sb, sector); + + for (i = 2; i < num_entries; i++) { + name_ep = (NAME_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry+i, §or); + if (!name_ep) + return FFS_MEDIAERR; + + init_name_entry(name_ep, uniname); + buf_modify(sb, sector); + uniname += 15; + } + + update_dir_checksum(sb, p_dir, entry); + + return FFS_SUCCESS; +} /* end of exfat_init_ext_entry */ + +void init_dos_entry(DOS_DENTRY_T *ep, UINT32 type, UINT32 start_clu) +{ + TIMESTAMP_T tm, *tp; + + fat_set_entry_type((DENTRY_T *) ep, type); + SET16_A(ep->start_clu_lo, CLUSTER_16(start_clu)); + SET16_A(ep->start_clu_hi, CLUSTER_16(start_clu >> 16)); + SET32_A(ep->size, 0); + + tp = tm_current(&tm); + fat_set_entry_time((DENTRY_T *) ep, tp, TM_CREATE); + fat_set_entry_time((DENTRY_T *) ep, tp, TM_MODIFY); + SET16_A(ep->access_date, 0); + ep->create_time_ms = 0; +} /* end of init_dos_entry */ + +void init_ext_entry(EXT_DENTRY_T *ep, INT32 order, UINT8 chksum, UINT16 *uniname) +{ + INT32 i; + UINT8 end = FALSE; + + fat_set_entry_type((DENTRY_T *) ep, TYPE_EXTEND); + ep->order = (UINT8) order; + ep->sysid = 0; + ep->checksum = chksum; + SET16_A(ep->start_clu, 0); + + for (i = 0; i < 10; i += 2) { + if (!end) { + SET16(ep->unicode_0_4+i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16(ep->unicode_0_4+i, 0xFFFF); + } + } + + for (i = 0; i < 12; i += 2) { + if (!end) { + SET16_A(ep->unicode_5_10+i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16_A(ep->unicode_5_10+i, 0xFFFF); + } + } + + for (i = 0; i < 4; i += 2) { + if (!end) { + SET16_A(ep->unicode_11_12+i, *uniname); + if (*uniname == 0x0) + end = TRUE; + else + uniname++; + } else { + SET16_A(ep->unicode_11_12+i, 0xFFFF); + } + } +} /* end of init_ext_entry */ + +void init_file_entry(FILE_DENTRY_T *ep, UINT32 type) +{ + TIMESTAMP_T tm, *tp; + + exfat_set_entry_type((DENTRY_T *) ep, type); + + tp = tm_current(&tm); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_CREATE); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_MODIFY); + exfat_set_entry_time((DENTRY_T *) ep, tp, TM_ACCESS); + ep->create_time_ms = 0; + ep->modify_time_ms = 0; + ep->access_time_ms = 0; +} /* end of init_file_entry */ + +void init_strm_entry(STRM_DENTRY_T *ep, UINT8 flags, UINT32 start_clu, UINT64 size) +{ + exfat_set_entry_type((DENTRY_T *) ep, TYPE_STREAM); + ep->flags = flags; + SET32_A(ep->start_clu, start_clu); + SET64_A(ep->valid_size, size); + SET64_A(ep->size, size); +} /* end of init_strm_entry */ + +void init_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname) +{ + INT32 i; + + exfat_set_entry_type((DENTRY_T *) ep, TYPE_EXTEND); + ep->flags = 0x0; + + for (i = 0; i < 30; i++, i++) { + SET16_A(ep->unicode_0_14+i, *uniname); + if (*uniname == 0x0) + break; + uniname++; + } +} /* end of init_name_entry */ + +void fat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries) +{ + INT32 i; + UINT32 sector; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = num_entries-1; i >= order; i--) { + ep = get_entry_in_dir(sb, p_dir, entry-i, §or); + if (!ep) + return; + + p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + buf_modify(sb, sector); + } +} /* end of fat_delete_dir_entry */ + +void exfat_delete_dir_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, INT32 order, INT32 num_entries) +{ + INT32 i; + UINT32 sector; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = order; i < num_entries; i++) { + ep = get_entry_in_dir(sb, p_dir, entry+i, §or); + if (!ep) + return; + + p_fs->fs_func->set_entry_type(ep, TYPE_DELETED); + buf_modify(sb, sector); + } +} /* end of exfat_delete_dir_entry */ + +void update_dir_checksum(struct super_block *sb, CHAIN_T *p_dir, INT32 entry) +{ + INT32 i, num_entries; + UINT32 sector; + UINT16 chksum; + FILE_DENTRY_T *file_ep; + DENTRY_T *ep; + + file_ep = (FILE_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, §or); + if (!file_ep) + return; + + buf_lock(sb, sector); + + num_entries = (INT32) file_ep->num_ext + 1; + chksum = calc_checksum_2byte((void *) file_ep, DENTRY_SIZE, 0, CS_DIR_ENTRY); + + for (i = 1; i < num_entries; i++) { + ep = get_entry_in_dir(sb, p_dir, entry+i, NULL); + if (!ep) { + buf_unlock(sb, sector); + return; + } + + chksum = calc_checksum_2byte((void *) ep, DENTRY_SIZE, chksum, CS_DEFAULT); + } + + SET16_A(file_ep->checksum, chksum); + buf_modify(sb, sector); + buf_unlock(sb, sector); +} /* end of update_dir_checksum */ + +void update_dir_checksum_with_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es) +{ + DENTRY_T *ep; + UINT16 chksum = 0; + INT32 chksum_type = CS_DIR_ENTRY, i; + + ep = (DENTRY_T *)&(es->__buf); + for (i=0; i < es->num_entries; i++) { + PRINTK ("update_dir_checksum_with_entry_set ep %p\n", ep); + chksum = calc_checksum_2byte((void *) ep, DENTRY_SIZE, chksum, chksum_type); + ep++; + chksum_type = CS_DEFAULT; + } + + ep = (DENTRY_T *)&(es->__buf); + SET16_A(((FILE_DENTRY_T *)ep)->checksum, chksum); + write_whole_entry_set(sb, es); +} + +static INT32 _walk_fat_chain (struct super_block *sb, CHAIN_T *p_dir, INT32 byte_offset, UINT32 *clu) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + INT32 clu_offset; + UINT32 cur_clu; + + clu_offset = byte_offset >> p_fs->cluster_size_bits; + cur_clu = p_dir->dir; + + if (p_dir->flags == 0x03) { + cur_clu += clu_offset; + } else { + while (clu_offset > 0) { + if (FAT_read(sb, cur_clu, &cur_clu) == -1) + return FFS_MEDIAERR; + clu_offset--; + } + } + + if (clu) + *clu = cur_clu; + return FFS_SUCCESS; +} +INT32 find_location(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector, INT32 *offset) +{ + INT32 off, ret; + UINT32 clu=0; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + off = entry << DENTRY_SIZE_BITS; + + if (p_dir->dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + *offset = off & p_bd->sector_size_mask; + *sector = off >> p_bd->sector_size_bits; + *sector += p_fs->root_start_sector; + } else { + ret =_walk_fat_chain(sb, p_dir, off, &clu); + if (ret != FFS_SUCCESS) + return ret; + + off &= p_fs->cluster_size - 1; /* byte offset in cluster */ + + *offset = off & p_bd->sector_size_mask; /* byte offset in sector */ + *sector = off >> p_bd->sector_size_bits; /* sector offset in cluster */ + *sector += START_SECTOR(clu); + } + return FFS_SUCCESS; +} /* end of find_location */ + +DENTRY_T *get_entry_with_sector(struct super_block *sb, UINT32 sector, INT32 offset) +{ + UINT8 *buf; + + buf = buf_getblk(sb, sector); + + if (buf == NULL) + return NULL; + + return((DENTRY_T *)(buf + offset)); +} /* end of get_entry_with_sector */ + +DENTRY_T *get_entry_in_dir(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 *sector) +{ + INT32 off; + UINT32 sec; + UINT8 *buf; + + if (find_location(sb, p_dir, entry, &sec, &off) != FFS_SUCCESS) + return NULL; + + buf = buf_getblk(sb, sec); + + if (buf == NULL) + return NULL; + + if (sector != NULL) + *sector = sec; + return((DENTRY_T *)(buf + off)); +} /* end of get_entry_in_dir */ + + +/* returns a set of dentries for a file or dir. + * Note that this is a copy (dump) of dentries so that user should call write_entry_set() + * to apply changes made in this entry set to the real device. + * in: + * sb+p_dir+entry: indicates a file/dir + * type: specifies how many dentries should be included. + * out: + * file_ep: will point the first dentry(= file dentry) on success + * return: + * pointer of entry set on success, + * NULL on failure. + */ + +#define ES_MODE_STARTED 0 +#define ES_MODE_GET_FILE_ENTRY 1 +#define ES_MODE_GET_STRM_ENTRY 2 +#define ES_MODE_GET_NAME_ENTRY 3 +#define ES_MODE_GET_CRITICAL_SEC_ENTRY 4 +ENTRY_SET_CACHE_T *get_entry_set_in_dir (struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT32 type, DENTRY_T **file_ep) +{ + INT32 off, ret, byte_offset; + UINT32 clu=0; + UINT32 sec, entry_type; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + ENTRY_SET_CACHE_T *es = NULL; + DENTRY_T *ep, *pos; + UINT8 *buf; + UINT8 num_entries; + INT32 mode = ES_MODE_STARTED; + + PRINTK("get_entry_set_in_dir entered\n"); + PRINTK("p_dir dir %u flags %x size %d\n", p_dir->dir, p_dir->flags, p_dir->size); + + byte_offset = entry << DENTRY_SIZE_BITS; + ret =_walk_fat_chain(sb, p_dir, byte_offset, &clu); + if (ret != FFS_SUCCESS) + return NULL; + + + byte_offset &= p_fs->cluster_size - 1; /* byte offset in cluster */ + + off = byte_offset & p_bd->sector_size_mask; /* byte offset in sector */ + sec = byte_offset >> p_bd->sector_size_bits; /* sector offset in cluster */ + sec += START_SECTOR(clu); + + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + + + ep = (DENTRY_T *)(buf + off); + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type != TYPE_FILE) + && (entry_type != TYPE_DIR)) + goto err_out; + + if (type == ES_ALL_ENTRIES) + num_entries = ((FILE_DENTRY_T *)ep)->num_ext+1; + else + num_entries = type; + + PRINTK("trying to malloc %x bytes for %d entries\n", offsetof(ENTRY_SET_CACHE_T, __buf) + (num_entries) * sizeof(DENTRY_T), num_entries); + es = MALLOC(offsetof(ENTRY_SET_CACHE_T, __buf) + (num_entries) * sizeof(DENTRY_T)); + if (es == NULL) + goto err_out; + + es->num_entries = num_entries; + es->sector = sec; + es->offset = off; + es->alloc_flag = p_dir->flags; + + pos = (DENTRY_T *) &(es->__buf); + + while(num_entries) { + /* instead of copying whole sector, we will check every entry. + * this will provide minimum stablity and consistancy. + */ + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) + goto err_out; + + switch(mode) { + case ES_MODE_STARTED: + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) + mode = ES_MODE_GET_FILE_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_FILE_ENTRY: + if (entry_type == TYPE_STREAM) + mode = ES_MODE_GET_STRM_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_STRM_ENTRY: + if (entry_type == TYPE_EXTEND) + mode = ES_MODE_GET_NAME_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_NAME_ENTRY: + if (entry_type == TYPE_EXTEND) + break; + else if (entry_type == TYPE_STREAM) + goto err_out; + else if (entry_type & TYPE_CRITICAL_SEC) + mode = ES_MODE_GET_CRITICAL_SEC_ENTRY; + else + goto err_out; + break; + case ES_MODE_GET_CRITICAL_SEC_ENTRY: + if ((entry_type == TYPE_EXTEND) || (entry_type == TYPE_STREAM)) + goto err_out; + else if ((entry_type & TYPE_CRITICAL_SEC) != TYPE_CRITICAL_SEC) + goto err_out; + break; + } + + COPY_DENTRY(pos, ep); + + if (--num_entries == 0) + break; + + if (((off + DENTRY_SIZE) & p_bd->sector_size_mask) < (off & p_bd->sector_size_mask)) { + /* get the next sector */ + if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { + if (es->alloc_flag == 0x03) { + clu++; + } else { + if (FAT_read(sb, clu, &clu) == -1) + goto err_out; + } + sec = START_SECTOR(clu); + } else { + sec++; + } + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + off = 0; + ep = (DENTRY_T *)(buf); + } else { + ep++; + off += DENTRY_SIZE; + } + pos++; + } + + if (file_ep) + *file_ep = (DENTRY_T *)&(es->__buf); + + PRINTK("es sec %u offset %d flags %d, num_entries %u buf ptr %p\n", + es->sector, es->offset, es->alloc_flag, es->num_entries, &(es->__buf)); + PRINTK("get_entry_set_in_dir exited %p\n", es); + return es; +err_out: + PRINTK("get_entry_set_in_dir exited NULL (es %p)\n", es); + FREE(es); + return NULL; +} + +void release_entry_set (ENTRY_SET_CACHE_T *es) +{ + PRINTK("release_entry_set %p\n", es); + FREE(es); +} + + +static INT32 __write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, UINT32 sec, INT32 off, UINT32 count) +{ + INT32 num_entries, buf_off = (off - es->offset); + UINT32 remaining_byte_in_sector, copy_entries; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + UINT32 clu; + UINT8 *buf, *esbuf = (UINT8 *)&(es->__buf); + + PRINTK("__write_partial_entries_in_entry_set entered\n"); + PRINTK("es %p sec %u off %d count %d\n", es, sec, off, count); + num_entries = count; + + while(num_entries) { + /* white per sector base */ + remaining_byte_in_sector = (1 << p_bd->sector_size_bits) - off; + copy_entries = MIN(remaining_byte_in_sector>> DENTRY_SIZE_BITS , num_entries); + buf = buf_getblk(sb, sec); + if (buf == NULL) + goto err_out; + PRINTK("es->buf %p buf_off %u\n", esbuf, buf_off); + PRINTK("copying %d entries from %p to sector %u\n", copy_entries, (esbuf + buf_off), sec); + MEMCPY(buf + off, esbuf + buf_off, copy_entries << DENTRY_SIZE_BITS); + buf_modify(sb, sec); + num_entries -= copy_entries; + + if (num_entries) { + /* get next sector */ + if (IS_LAST_SECTOR_IN_CLUSTER(sec)) { + clu = GET_CLUSTER_FROM_SECTOR(sec); + if (es->alloc_flag == 0x03) { + clu++; + } else { + if (FAT_read(sb, clu, &clu) == -1) + goto err_out; + } + sec = START_SECTOR(clu); + } else { + sec++; + } + off = 0; + buf_off += copy_entries << DENTRY_SIZE_BITS; + } + } + + PRINTK("__write_partial_entries_in_entry_set exited successfully\n"); + return FFS_SUCCESS; +err_out: + PRINTK("__write_partial_entries_in_entry_set failed\n"); + return FFS_ERROR; +} + +/* write back all entries in entry set */ +INT32 write_whole_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es) +{ + return (__write_partial_entries_in_entry_set(sb, es, es->sector,es->offset, es->num_entries)); +} + +/* write back some entries in entry set */ +INT32 write_partial_entries_in_entry_set (struct super_block *sb, ENTRY_SET_CACHE_T *es, DENTRY_T *ep, UINT32 count) +{ + INT32 ret, byte_offset, off; + UINT32 clu=0, sec; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + CHAIN_T dir; + + /* vaidity check */ + if (ep + count > ((DENTRY_T *)&(es->__buf)) + es->num_entries) + return FFS_ERROR; + + dir.dir = GET_CLUSTER_FROM_SECTOR(es->sector); + dir.flags = es->alloc_flag; + dir.size = 0xffffffff; /* XXX */ + + byte_offset = (es->sector - START_SECTOR(dir.dir)) << p_bd->sector_size_bits; + byte_offset += ((INT32 *)ep - (INT32 *)&(es->__buf)) + es->offset; + + ret =_walk_fat_chain(sb, &dir, byte_offset, &clu); + if (ret != FFS_SUCCESS) + return ret; + byte_offset &= p_fs->cluster_size - 1; /* byte offset in cluster */ + off = byte_offset & p_bd->sector_size_mask; /* byte offset in sector */ + sec = byte_offset >> p_bd->sector_size_bits; /* sector offset in cluster */ + sec += START_SECTOR(clu); + return (__write_partial_entries_in_entry_set(sb, es, sec, off, count)); +} + +/* search EMPTY CONTINUOUS "num_entries" entries */ +INT32 search_deleted_or_unused_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 num_entries) +{ + INT32 i, dentry, num_empty = 0; + INT32 dentries_per_clu; + UINT32 type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + if (p_fs->hint_uentry.dir == p_dir->dir) { + if (p_fs->hint_uentry.entry == -1) + return -1; + + clu.dir = p_fs->hint_uentry.clu.dir; + clu.size = p_fs->hint_uentry.clu.size; + clu.flags = p_fs->hint_uentry.clu.flags; + + dentry = p_fs->hint_uentry.entry; + } else { + p_fs->hint_uentry.entry = -1; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + dentry = 0; + } + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + i = dentry % dentries_per_clu; + else + i = dentry & (dentries_per_clu-1); + + for ( ; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -1; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) { + num_empty++; + if (p_fs->hint_uentry.entry == -1) { + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = dentry; + + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = clu.size; + p_fs->hint_uentry.clu.flags = clu.flags; + } + } else if (type == TYPE_DELETED) { + num_empty++; + } else { + num_empty = 0; + } + + if (num_empty >= num_entries) { + p_fs->hint_uentry.dir = CLUSTER_32(~0); + p_fs->hint_uentry.entry = -1; + + if (p_fs->vol_type == EXFAT) + return(dentry - (num_entries-1)); + else + return(dentry); + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return -1; + } + } + + return -1; +} /* end of search_deleted_or_unused_entry */ + +INT32 find_empty_entry(struct inode *inode, CHAIN_T *p_dir, INT32 num_entries) +{ + INT32 ret, dentry; + UINT32 last_clu, sector; + UINT64 size = 0; + CHAIN_T clu; + DENTRY_T *ep = NULL; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + return(search_deleted_or_unused_entry(sb, p_dir, num_entries)); + + while ((dentry = search_deleted_or_unused_entry(sb, p_dir, num_entries)) < 0) { + if (p_fs->dev_ejected) + break; + + if (p_fs->vol_type == EXFAT) { + if (p_dir->dir != p_fs->root_dir) { + size = i_size_read(inode); + } + } + + last_clu = find_last_cluster(sb, p_dir); + clu.dir = last_clu + 1; + clu.size = 0; + clu.flags = p_dir->flags; + + /* (1) allocate a cluster */ + ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu); + if (ret < 1) + return -1; + + if (clear_cluster(sb, clu.dir) != FFS_SUCCESS) + return -1; + + /* (2) append to the FAT chain */ + if (clu.flags != p_dir->flags) { + exfat_chain_cont_cluster(sb, p_dir->dir, p_dir->size); + p_dir->flags = 0x01; + p_fs->hint_uentry.clu.flags = 0x01; + } + if (clu.flags == 0x01) + FAT_write(sb, last_clu, clu.dir); + + if (p_fs->hint_uentry.entry == -1) { + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = p_dir->size << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = 0; + p_fs->hint_uentry.clu.flags = clu.flags; + } + p_fs->hint_uentry.clu.size++; + p_dir->size++; + + /* (3) update the directory entry */ + if (p_fs->vol_type == EXFAT) { + if (p_dir->dir != p_fs->root_dir) { + size += p_fs->cluster_size; + + ep = get_entry_in_dir(sb, &(fid->dir), fid->entry+1, §or); + if (!ep) + return -1; + p_fs->fs_func->set_entry_size(ep, size); + p_fs->fs_func->set_entry_flag(ep, p_dir->flags); + buf_modify(sb, sector); + + update_dir_checksum(sb, &(fid->dir), fid->entry); + } + } + + i_size_write(inode, i_size_read(inode)+p_fs->cluster_size); + EXFAT_I(inode)->mmu_private += p_fs->cluster_size; + EXFAT_I(inode)->fid.size += p_fs->cluster_size; + EXFAT_I(inode)->fid.flags = p_dir->flags; + inode->i_blocks += 1 << (p_fs->cluster_size_bits - 9); + } + + return(dentry); +} /* end of find_empty_entry */ + +/* return values of fat_find_dir_entry() + >= 0 : return dir entiry position with the name in dir + -1 : (root dir, ".") it is the root dir itself + -2 : entry with the name does not exist */ +INT32 fat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type) +{ + INT32 i, dentry = 0, len; + INT32 order = 0, is_feasible_entry = TRUE, has_ext_entry = FALSE; + INT32 dentries_per_clu; + UINT32 entry_type; + UINT16 entry_uniname[14], *uniname = NULL, unichar; + CHAIN_T clu; + DENTRY_T *ep; + DOS_DENTRY_T *dos_ep; + EXT_DENTRY_T *ext_ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == p_fs->root_dir) { + if ((!nls_uniname_cmp(sb, p_uniname->name, (UINT16 *) UNI_CUR_DIR_NAME)) || + (!nls_uniname_cmp(sb, p_uniname->name, (UINT16 *) UNI_PAR_DIR_NAME))) + return -1; // special case, root directory itself + } + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -2; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + if ((type == TYPE_ALL) || (type == entry_type)) { + if (is_feasible_entry && has_ext_entry) + return(dentry); + + dos_ep = (DOS_DENTRY_T *) ep; + if (!nls_dosname_cmp(sb, p_dosname->name, dos_ep->name)) + return(dentry); + } + is_feasible_entry = TRUE; + has_ext_entry = FALSE; + } else if (entry_type == TYPE_EXTEND) { + if (is_feasible_entry) { + ext_ep = (EXT_DENTRY_T *) ep; + if (ext_ep->order > 0x40) { + order = (INT32)(ext_ep->order - 0x40); + uniname = p_uniname->name + 13 * (order-1); + } else { + order = (INT32) ext_ep->order; + uniname -= 13; + } + + len = extract_uni_name_from_ext_entry(ext_ep, entry_uniname, order); + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (nls_uniname_cmp(sb, uniname, entry_uniname)) { + is_feasible_entry = FALSE; + } + + *(uniname+len) = unichar; + } + has_ext_entry = TRUE; + } else if (entry_type == TYPE_UNUSED) { + return -2; + } else { + is_feasible_entry = TRUE; + has_ext_entry = FALSE; + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return -2; + } + + return -2; +} /* end of fat_find_dir_entry */ + +/* return values of exfat_find_dir_entry() + >= 0 : return dir entiry position with the name in dir + -1 : (root dir, ".") it is the root dir itself + -2 : entry with the name does not exist */ +INT32 exfat_find_dir_entry(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 num_entries, DOS_NAME_T *p_dosname, UINT32 type) +{ + INT32 i, dentry = 0, num_ext_entries = 0, len; + INT32 order = 0, is_feasible_entry = FALSE; + INT32 dentries_per_clu, num_empty = 0; + UINT32 entry_type; + UINT16 entry_uniname[16], *uniname = NULL, unichar; + CHAIN_T clu; + DENTRY_T *ep; + FILE_DENTRY_T *file_ep; + STRM_DENTRY_T *strm_ep; + NAME_DENTRY_T *name_ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == p_fs->root_dir) { + if ((!nls_uniname_cmp(sb, p_uniname->name, (UINT16 *) UNI_CUR_DIR_NAME)) || + (!nls_uniname_cmp(sb, p_uniname->name, (UINT16 *) UNI_PAR_DIR_NAME))) + return -1; // special case, root directory itself + } + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + p_fs->hint_uentry.dir = p_dir->dir; + p_fs->hint_uentry.entry = -1; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++, dentry++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -2; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if ((entry_type == TYPE_UNUSED) || (entry_type == TYPE_DELETED)) { + is_feasible_entry = FALSE; + + if (p_fs->hint_uentry.entry == -1) { + num_empty++; + + if (num_empty == 1) { + p_fs->hint_uentry.clu.dir = clu.dir; + p_fs->hint_uentry.clu.size = clu.size; + p_fs->hint_uentry.clu.flags = clu.flags; + } + if ((num_empty >= num_entries) || (entry_type == TYPE_UNUSED)) { + p_fs->hint_uentry.entry = dentry - (num_empty-1); + } + } + + if (entry_type == TYPE_UNUSED) { + return -2; + } + } else { + num_empty = 0; + + if ((entry_type == TYPE_FILE) || (entry_type == TYPE_DIR)) { + if ((type == TYPE_ALL) || (type == entry_type)) { + file_ep = (FILE_DENTRY_T *) ep; + num_ext_entries = file_ep->num_ext; + is_feasible_entry = TRUE; + } else { + is_feasible_entry = FALSE; + } + } else if (entry_type == TYPE_STREAM) { + if (is_feasible_entry) { + strm_ep = (STRM_DENTRY_T *) ep; + if (p_uniname->name_len == strm_ep->name_len) { + order = 1; + } else { + is_feasible_entry = FALSE; + } + } + } else if (entry_type == TYPE_EXTEND) { + if (is_feasible_entry) { + name_ep = (NAME_DENTRY_T *) ep; + + if ((++order) == 2) + uniname = p_uniname->name; + else + uniname += 15; + + len = extract_uni_name_from_name_entry(name_ep, entry_uniname, order); + + unichar = *(uniname+len); + *(uniname+len) = 0x0; + + if (nls_uniname_cmp(sb, uniname, entry_uniname)) { + is_feasible_entry = FALSE; + } else if (order == num_ext_entries) { + p_fs->hint_uentry.dir = CLUSTER_32(~0); + p_fs->hint_uentry.entry = -1; + return(dentry - (num_ext_entries)); + } + + *(uniname+len) = unichar; + } + } else { + is_feasible_entry = FALSE; + } + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return -2; + } + } + + return -2; +} /* end of exfat_find_dir_entry */ + +/* returns -1 on error */ +INT32 fat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry) +{ + INT32 count = 0; + UINT8 chksum; + DOS_DENTRY_T *dos_ep = (DOS_DENTRY_T *) p_entry; + EXT_DENTRY_T *ext_ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + chksum = calc_checksum_1byte((void *) dos_ep->name, DOS_NAME_LENGTH, 0); + + for (entry--; entry >= 0; entry--) { + ext_ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, NULL); + if (!ext_ep) + return -1; + + if ((p_fs->fs_func->get_entry_type((DENTRY_T *) ext_ep) == TYPE_EXTEND) && + (ext_ep->checksum == chksum)) { + count++; + if (ext_ep->order > 0x40) + return(count); + } else { + return(count); + } + } + + return(count); +} /* end of fat_count_ext_entries */ + +/* returns -1 on error */ +INT32 exfat_count_ext_entries(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, DENTRY_T *p_entry) +{ + INT32 i, count = 0; + UINT32 type; + FILE_DENTRY_T *file_ep = (FILE_DENTRY_T *) p_entry; + DENTRY_T *ext_ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (i = 0, entry++; i < file_ep->num_ext; i++, entry++) { + ext_ep = get_entry_in_dir(sb, p_dir, entry, NULL); + if (!ext_ep) + return -1; + + type = p_fs->fs_func->get_entry_type(ext_ep); + if ((type == TYPE_EXTEND) || (type == TYPE_STREAM)) { + count++; + } else { + return(count); + } + } + + return(count); +} /* end of exfat_count_ext_entries */ + +/* returns -1 on error */ +INT32 count_dos_name_entries(struct super_block *sb, CHAIN_T *p_dir, UINT32 type) +{ + INT32 i, count = 0; + INT32 dentries_per_clu; + UINT32 entry_type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return -1; + + entry_type = p_fs->fs_func->get_entry_type(ep); + + if (entry_type == TYPE_UNUSED) + return(count); + if (!(type & TYPE_CRITICAL_PRI) && !(type & TYPE_BENIGN_PRI)) + continue; + + if ((type == TYPE_ALL) || (type == entry_type)) + count++; + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return -1; + } + } + + return(count); +} /* end of count_dos_name_entries */ + +BOOL is_dir_empty(struct super_block *sb, CHAIN_T *p_dir) +{ + INT32 i, count = 0; + INT32 dentries_per_clu; + UINT32 type; + CHAIN_T clu; + DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.size = p_dir->size; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + break; + + type = p_fs->fs_func->get_entry_type(ep); + + if (type == TYPE_UNUSED) + return TRUE; + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + if (p_dir->dir == CLUSTER_32(0)) { /* FAT16 root_dir */ + return FALSE; + } else { + if (p_fs->vol_type == EXFAT) + return FALSE; + if ((p_dir->dir == p_fs->root_dir) || ((++count) > 2)) + return FALSE; + } + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (clu.flags == 0x03) { + if ((--clu.size) > 0) + clu.dir++; + else + clu.dir = CLUSTER_32(~0); + } else { + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + break; + } + } + + return TRUE; +} /* end of is_dir_empty */ + +/* + * Name Conversion Functions + */ + +/* input : dir, uni_name + output : num_of_entry, dos_name(format : aaaaaa~1.bbb) */ +INT32 get_num_entries_and_dos_name(struct super_block *sb, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, INT32 *entries, DOS_NAME_T *p_dosname) +{ + INT32 ret, num_entries, lossy = FALSE; + INT8 **r; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + num_entries = p_fs->fs_func->calc_num_entries(p_uniname); + if (num_entries == 0) + return FFS_INVALIDPATH; + + if (p_fs->vol_type != EXFAT) { + nls_uniname_to_dosname(sb, p_dosname, p_uniname, &lossy); + + if (lossy) { + ret = fat_generate_dos_name(sb, p_dir, p_dosname); + if (ret) + return ret; + } else { + for (r = reserved_names; *r; r++) { + if (!STRNCMP((void *) p_dosname->name, *r, 8)) + return FFS_INVALIDPATH; + } + + if (p_dosname->name_case != 0xFF) + num_entries = 1; + } + + if (num_entries > 1) + p_dosname->name_case = 0x0; + } + + *entries = num_entries; + + return FFS_SUCCESS; +} /* end of get_num_entries_and_dos_name */ + +void get_uni_name_from_dos_entry(struct super_block *sb, DOS_DENTRY_T *ep, UNI_NAME_T *p_uniname, UINT8 mode) +{ + DOS_NAME_T dos_name; + + if (mode == 0x0) + dos_name.name_case = 0x0; + else + dos_name.name_case = ep->lcase; + + MEMCPY(dos_name.name, ep->name, DOS_NAME_LENGTH); + nls_dosname_to_uniname(sb, p_uniname, &dos_name); +} /* end of get_uni_name_from_dos_entry */ + +void fat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname) +{ + INT32 i; + EXT_DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + for (entry--, i = 1; entry >= 0; entry--, i++) { + ep = (EXT_DENTRY_T *) get_entry_in_dir(sb, p_dir, entry, NULL); + if (!ep) + return; + + if (p_fs->fs_func->get_entry_type((DENTRY_T *) ep) == TYPE_EXTEND) { + extract_uni_name_from_ext_entry(ep, uniname, i); + if (ep->order > 0x40) + return; + } else { + return; + } + + uniname += 13; + } +} /* end of fat_get_uni_name_from_ext_entry */ + +void exfat_get_uni_name_from_ext_entry(struct super_block *sb, CHAIN_T *p_dir, INT32 entry, UINT16 *uniname) +{ + INT32 i; + DENTRY_T *ep; + ENTRY_SET_CACHE_T *es; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + es = get_entry_set_in_dir(sb, p_dir, entry, ES_ALL_ENTRIES, &ep); + if (es == NULL || es->num_entries < 3) { + if(es) { + release_entry_set(es); + } + return; + } + + ep += 2; + + /* + * First entry : file entry + * Second entry : stream-extension entry + * Third entry : first file-name entry + * So, the index of first file-name dentry should start from 2. + */ + for (i = 2; i < es->num_entries; i++, ep++) { + if (p_fs->fs_func->get_entry_type(ep) == TYPE_EXTEND) { + extract_uni_name_from_name_entry((NAME_DENTRY_T *)ep, uniname, i); + } else { + /* end of name entry */ + goto out; + } + uniname += 15; + } + +out: + release_entry_set(es); +} /* end of exfat_get_uni_name_from_ext_entry */ + +INT32 extract_uni_name_from_ext_entry(EXT_DENTRY_T *ep, UINT16 *uniname, INT32 order) +{ + INT32 i, len = 0; + + for (i = 0; i < 10; i += 2) { + *uniname = GET16(ep->unicode_0_4+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + + if (order < 20) { + for (i = 0; i < 12; i += 2) { + *uniname = GET16_A(ep->unicode_5_10+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + } else { + for (i = 0; i < 8; i += 2) { + *uniname = GET16_A(ep->unicode_5_10+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + *uniname = 0x0; /* uniname[MAX_NAME_LENGTH-1] */ + return(len); + } + + for (i = 0; i < 4; i += 2) { + *uniname = GET16_A(ep->unicode_11_12+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + + *uniname = 0x0; + return(len); + +} /* end of extract_uni_name_from_ext_entry */ + +INT32 extract_uni_name_from_name_entry(NAME_DENTRY_T *ep, UINT16 *uniname, INT32 order) +{ + INT32 i, len = 0; + + for (i = 0; i < 30; i += 2) { + *uniname = GET16_A(ep->unicode_0_14+i); + if (*uniname == 0x0) + return(len); + uniname++; + len++; + } + + *uniname = 0x0; + return(len); + +} /* end of extract_uni_name_from_name_entry */ + +INT32 fat_generate_dos_name(struct super_block *sb, CHAIN_T *p_dir, DOS_NAME_T *p_dosname) +{ + INT32 i, j, count = 0, count_begin = FALSE; + INT32 dentries_per_clu; + UINT32 type; + UINT8 bmap[128/* 1 ~ 1023 */]; + CHAIN_T clu; + DOS_DENTRY_T *ep; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + Bitmap_clear_all(bmap, 128); + Bitmap_set(bmap, 0); + + if (p_dir->dir == CLUSTER_32(0)) /* FAT16 root_dir */ + dentries_per_clu = p_fs->dentries_in_root; + else + dentries_per_clu = p_fs->dentries_per_clu; + + clu.dir = p_dir->dir; + clu.flags = p_dir->flags; + + while (clu.dir != CLUSTER_32(~0)) { + if (p_fs->dev_ejected) + break; + + for (i = 0; i < dentries_per_clu; i++) { + ep = (DOS_DENTRY_T *) get_entry_in_dir(sb, &clu, i, NULL); + if (!ep) + return FFS_MEDIAERR; + + type = p_fs->fs_func->get_entry_type((DENTRY_T *) ep); + + if (type == TYPE_UNUSED) + break; + if ((type != TYPE_FILE) && (type != TYPE_DIR)) + continue; + + count = 0; + count_begin = FALSE; + + for (j = 0; j < 8; j++) { + if (ep->name[j] == ' ') + break; + + if (ep->name[j] == '~') { + count_begin = TRUE; + } else if (count_begin) { + if ((ep->name[j] >= '0') && (ep->name[j] <= '9')) { + count = count * 10 + (ep->name[j] - '0'); + } else { + count = 0; + count_begin = FALSE; + } + } + } + + if ((count > 0) && (count < 1024)) + Bitmap_set(bmap, count); + } + + if (p_dir->dir == CLUSTER_32(0)) + break; /* FAT16 root_dir */ + + if (FAT_read(sb, clu.dir, &(clu.dir)) != 0) + return FFS_MEDIAERR; + } + + count = 0; + for (i = 0; i < 128; i++) { + if (bmap[i] != 0xFF) { + for (j = 0; j < 8; j++) { + if (Bitmap_test(&(bmap[i]), j) == 0) { + count = (i << 3) + j; + break; + } + } + if (count != 0) + break; + } + } + + if ((count == 0) || (count >= 1024)) + return FFS_FILEEXIST; + else + fat_attach_count_to_dos_name(p_dosname->name, count); + + /* Now dos_name has DOS~????.EXT */ + return FFS_SUCCESS; +} /* end of generate_dos_name */ + +void fat_attach_count_to_dos_name(UINT8 *dosname, INT32 count) +{ + INT32 i, j, length; + INT8 str_count[6]; + + str_count[0] = '~'; + str_count[1] = '\0'; + my_itoa(&(str_count[1]), count); + length = STRLEN(str_count); + + i = j = 0; + while (j <= (8 - length)) { + i = j; + if (dosname[j] == ' ') + break; + if (dosname[j] & 0x80) + j += 2; + else + j++; + } + + for (j = 0; j < length; i++, j++) + dosname[i] = (UINT8) str_count[j]; + + if (i == 7) + dosname[7] = ' '; + +} /* end of attach_count_to_dos_name */ + +INT32 fat_calc_num_entries(UNI_NAME_T *p_uniname) +{ + INT32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 dos name entry + extended entries */ + return((len-1) / 13 + 2); + +} /* end of calc_num_enties */ + +INT32 exfat_calc_num_entries(UNI_NAME_T *p_uniname) +{ + INT32 len; + + len = p_uniname->name_len; + if (len == 0) + return 0; + + /* 1 file entry + 1 stream entry + name entries */ + return((len-1) / 15 + 3); + +} /* end of exfat_calc_num_enties */ + +UINT8 calc_checksum_1byte(void *data, INT32 len, UINT8 chksum) +{ + INT32 i; + UINT8 *c = (UINT8 *) data; + + for (i = 0; i < len; i++, c++) + chksum = (((chksum & 1) << 7) | ((chksum & 0xFE) >> 1)) + *c; + + return(chksum); +} /* end of calc_checksum_1byte */ + +UINT16 calc_checksum_2byte(void *data, INT32 len, UINT16 chksum, INT32 type) +{ + INT32 i; + UINT8 *c = (UINT8 *) data; + + switch (type) { + case CS_DIR_ENTRY: + for (i = 0; i < len; i++, c++) { + if ((i == 2) || (i == 3)) + continue; + chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + (UINT16) *c; + } + break; + default + : + for (i = 0; i < len; i++, c++) { + chksum = (((chksum & 1) << 15) | ((chksum & 0xFFFE) >> 1)) + (UINT16) *c; + } + } + + return(chksum); +} /* end of calc_checksum_2byte */ + +UINT32 calc_checksum_4byte(void *data, INT32 len, UINT32 chksum, INT32 type) +{ + INT32 i; + UINT8 *c = (UINT8 *) data; + + switch (type) { + case CS_PBR_SECTOR: + for (i = 0; i < len; i++, c++) { + if ((i == 106) || (i == 107) || (i == 112)) + continue; + chksum = (((chksum & 1) << 31) | ((chksum & 0xFFFFFFFE) >> 1)) + (UINT32) *c; + } + break; + default + : + for (i = 0; i < len; i++, c++) { + chksum = (((chksum & 1) << 31) | ((chksum & 0xFFFFFFFE) >> 1)) + (UINT32) *c; + } + } + + return(chksum); +} /* end of calc_checksum_4byte */ + +/* + * Name Resolution Functions + */ + +/* return values of resolve_path() + > 0 : return the length of the path + < 0 : return error */ +INT32 resolve_path(struct inode *inode, UINT8 *path, CHAIN_T *p_dir, UNI_NAME_T *p_uniname) +{ + INT32 lossy = FALSE; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + + if (STRLEN(path) >= (MAX_NAME_LENGTH * MAX_CHARSET_SIZE)) + return(FFS_INVALIDPATH); + + STRCPY(name_buf, path); + + nls_cstring_to_uniname(sb, p_uniname, name_buf, &lossy); + if (lossy) + return(FFS_INVALIDPATH); + + fid->size = i_size_read(inode); + + p_dir->dir = fid->start_clu; + p_dir->size = (INT32)(fid->size >> p_fs->cluster_size_bits); + p_dir->flags = fid->flags; + + return(FFS_SUCCESS); +} + +/* + * File Operation Functions + */ +static FS_FUNC_T fat_fs_func = { + .alloc_cluster = fat_alloc_cluster, + .free_cluster = fat_free_cluster, + .count_used_clusters = fat_count_used_clusters, + + .init_dir_entry = fat_init_dir_entry, + .init_ext_entry = fat_init_ext_entry, + .find_dir_entry = fat_find_dir_entry, + .delete_dir_entry = fat_delete_dir_entry, + .get_uni_name_from_ext_entry = fat_get_uni_name_from_ext_entry, + .count_ext_entries = fat_count_ext_entries, + .calc_num_entries = fat_calc_num_entries, + + .get_entry_type = fat_get_entry_type, + .set_entry_type = fat_set_entry_type, + .get_entry_attr = fat_get_entry_attr, + .set_entry_attr = fat_set_entry_attr, + .get_entry_flag = fat_get_entry_flag, + .set_entry_flag = fat_set_entry_flag, + .get_entry_clu0 = fat_get_entry_clu0, + .set_entry_clu0 = fat_set_entry_clu0, + .get_entry_size = fat_get_entry_size, + .set_entry_size = fat_set_entry_size, + .get_entry_time = fat_get_entry_time, + .set_entry_time = fat_set_entry_time, +}; + + +INT32 fat16_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr) +{ + INT32 num_reserved, num_root_sectors; + BPB16_T *p_bpb = (BPB16_T *) p_pbr->bpb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + num_root_sectors = GET16(p_bpb->num_root_entries) << DENTRY_SIZE_BITS; + num_root_sectors = ((num_root_sectors-1) >> p_bd->sector_size_bits) + 1; + + p_fs->sectors_per_clu = p_bpb->sectors_per_clu; + p_fs->sectors_per_clu_bits = my_log2(p_bpb->sectors_per_clu); + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET16(p_bpb->num_fat_sectors); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->FAT2_start_sector + p_fs->num_FAT_sectors; + p_fs->data_start_sector = p_fs->root_start_sector + num_root_sectors; + + p_fs->num_sectors = GET16(p_bpb->num_sectors); + if (p_fs->num_sectors == 0) + p_fs->num_sectors = GET32(p_bpb->num_huge_sectors); + + num_reserved = p_fs->data_start_sector - p_fs->PBR_sector; + p_fs->num_clusters = ((p_fs->num_sectors - num_reserved) >> p_fs->sectors_per_clu_bits) + 2; + /* because the cluster index starts with 2 */ + + if (p_fs->num_clusters < FAT12_THRESHOLD) + p_fs->vol_type = FAT12; + else + p_fs->vol_type = FAT16; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = 0; + p_fs->dentries_in_root = GET16(p_bpb->num_root_entries); + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->vol_flag = VOL_CLEAN; + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (UINT32) ~0; + + p_fs->fs_func = &fat_fs_func; + + return FFS_SUCCESS; +} /* end of fat16_mount */ + +INT32 fat32_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr) +{ + INT32 num_reserved; + BPB32_T *p_bpb = (BPB32_T *) p_pbr->bpb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + p_fs->sectors_per_clu = p_bpb->sectors_per_clu; + p_fs->sectors_per_clu_bits = my_log2(p_bpb->sectors_per_clu); + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET32(p_bpb->num_fat32_sectors); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET16(p_bpb->num_reserved); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->FAT2_start_sector + p_fs->num_FAT_sectors; + p_fs->data_start_sector = p_fs->root_start_sector; + + p_fs->num_sectors = GET32(p_bpb->num_huge_sectors); + num_reserved = p_fs->data_start_sector - p_fs->PBR_sector; + + p_fs->num_clusters = ((p_fs->num_sectors-num_reserved) >> p_fs->sectors_per_clu_bits) + 2; + /* because the cluster index starts with 2 */ + + p_fs->vol_type = FAT32; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = GET32(p_bpb->root_cluster); + p_fs->dentries_in_root = 0; + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->vol_flag = VOL_CLEAN; + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (UINT32) ~0; + + p_fs->fs_func = &fat_fs_func; + + return FFS_SUCCESS; +} /* end of fat32_mount */ + +static FS_FUNC_T exfat_fs_func = { + .alloc_cluster = exfat_alloc_cluster, + .free_cluster = exfat_free_cluster, + .count_used_clusters = exfat_count_used_clusters, + + .init_dir_entry = exfat_init_dir_entry, + .init_ext_entry = exfat_init_ext_entry, + .find_dir_entry = exfat_find_dir_entry, + .delete_dir_entry = exfat_delete_dir_entry, + .get_uni_name_from_ext_entry = exfat_get_uni_name_from_ext_entry, + .count_ext_entries = exfat_count_ext_entries, + .calc_num_entries = exfat_calc_num_entries, + + .get_entry_type = exfat_get_entry_type, + .set_entry_type = exfat_set_entry_type, + .get_entry_attr = exfat_get_entry_attr, + .set_entry_attr = exfat_set_entry_attr, + .get_entry_flag = exfat_get_entry_flag, + .set_entry_flag = exfat_set_entry_flag, + .get_entry_clu0 = exfat_get_entry_clu0, + .set_entry_clu0 = exfat_set_entry_clu0, + .get_entry_size = exfat_get_entry_size, + .set_entry_size = exfat_set_entry_size, + .get_entry_time = exfat_get_entry_time, + .set_entry_time = exfat_set_entry_time, +}; + +INT32 exfat_mount(struct super_block *sb, PBR_SECTOR_T *p_pbr) +{ + BPBEX_T *p_bpb = (BPBEX_T *) p_pbr->bpb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + + if (p_bpb->num_fats == 0) + return FFS_FORMATERR; + + p_fs->sectors_per_clu = 1 << p_bpb->sectors_per_clu_bits; + p_fs->sectors_per_clu_bits = p_bpb->sectors_per_clu_bits; + p_fs->cluster_size_bits = p_fs->sectors_per_clu_bits + p_bd->sector_size_bits; + p_fs->cluster_size = 1 << p_fs->cluster_size_bits; + + p_fs->num_FAT_sectors = GET32(p_bpb->fat_length); + + p_fs->FAT1_start_sector = p_fs->PBR_sector + GET32(p_bpb->fat_offset); + if (p_bpb->num_fats == 1) + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector; + else + p_fs->FAT2_start_sector = p_fs->FAT1_start_sector + p_fs->num_FAT_sectors; + + p_fs->root_start_sector = p_fs->PBR_sector + GET32(p_bpb->clu_offset); + p_fs->data_start_sector = p_fs->root_start_sector; + + p_fs->num_sectors = GET64(p_bpb->vol_length); + p_fs->num_clusters = GET32(p_bpb->clu_count) + 2; + /* because the cluster index starts with 2 */ + + p_fs->vol_type = EXFAT; + p_fs->vol_id = GET32(p_bpb->vol_serial); + + p_fs->root_dir = GET32(p_bpb->root_cluster); + p_fs->dentries_in_root = 0; + p_fs->dentries_per_clu = 1 << (p_fs->cluster_size_bits - DENTRY_SIZE_BITS); + + p_fs->vol_flag = (UINT32) GET16(p_bpb->vol_flags); + p_fs->clu_srch_ptr = 2; + p_fs->used_clusters = (UINT32) ~0; + + p_fs->fs_func = &exfat_fs_func; + + return FFS_SUCCESS; +} /* end of exfat_mount */ + +INT32 create_dir(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + INT32 ret, dentry, num_entries; + UINT64 size; + CHAIN_T clu; + DOS_NAME_T dos_name, dot_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return FFS_FULL; + + clu.dir = CLUSTER_32(~0); + clu.size = 0; + clu.flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + + /* (1) allocate a cluster */ + ret = p_fs->fs_func->alloc_cluster(sb, 1, &clu); + if (ret < 1) + return FFS_FULL; + + ret = clear_cluster(sb, clu.dir); + if (ret != FFS_SUCCESS) + return ret; + + if (p_fs->vol_type == EXFAT) { + size = p_fs->cluster_size; + } else { + size = 0; + + /* initialize the . and .. entry + Information for . points to itself + Information for .. points to parent dir */ + + dot_name.name_case = 0x0; + MEMCPY(dot_name.name, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH); + + ret = p_fs->fs_func->init_dir_entry(sb, &clu, 0, TYPE_DIR, clu.dir, 0); + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, &clu, 0, 1, NULL, &dot_name); + if (ret != FFS_SUCCESS) + return ret; + + MEMCPY(dot_name.name, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH); + + if (p_dir->dir == p_fs->root_dir) + ret = p_fs->fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, CLUSTER_32(0), 0); + else + ret = p_fs->fs_func->init_dir_entry(sb, &clu, 1, TYPE_DIR, p_dir->dir, 0); + + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, &clu, 1, 1, NULL, &dot_name); + if (ret != FFS_SUCCESS) + return ret; + } + + /* (2) update the directory entry */ + /* make sub-dir entry in parent directory */ + ret = p_fs->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_DIR, clu.dir, size); + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_SUBDIR; + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = size; + fid->start_clu = clu.dir; + + fid->type= TYPE_DIR; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + return FFS_SUCCESS; +} /* end of create_dir */ + +INT32 create_file(struct inode *inode, CHAIN_T *p_dir, UNI_NAME_T *p_uniname, UINT8 mode, FILE_ID_T *fid) +{ + INT32 ret, dentry, num_entries; + DOS_NAME_T dos_name; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_entries, &dos_name); + if (ret) + return ret; + + /* find_empty_entry must be called before alloc_cluster() */ + dentry = find_empty_entry(inode, p_dir, num_entries); + if (dentry < 0) + return FFS_FULL; + + /* (1) update the directory entry */ + /* fill the dos name directory entry information of the created file. + the first cluster is not determined yet. (0) */ + ret = p_fs->fs_func->init_dir_entry(sb, p_dir, dentry, TYPE_FILE | mode, CLUSTER_32(0), 0); + if (ret != FFS_SUCCESS) + return ret; + + ret = p_fs->fs_func->init_ext_entry(sb, p_dir, dentry, num_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + fid->dir.dir = p_dir->dir; + fid->dir.size = p_dir->size; + fid->dir.flags = p_dir->flags; + fid->entry = dentry; + + fid->attr = ATTR_ARCHIVE | mode; + fid->flags = (p_fs->vol_type == EXFAT) ? 0x03 : 0x01; + fid->size = 0; + fid->start_clu = CLUSTER_32(~0); + + fid->type= TYPE_FILE; + fid->rwoffset = 0; + fid->hint_last_off = -1; + + return FFS_SUCCESS; +} /* end of create_file */ + +void remove_file(struct inode *inode, CHAIN_T *p_dir, INT32 entry) +{ + INT32 num_entries; + UINT32 sector; + DENTRY_T *ep; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + ep = get_entry_in_dir(sb, p_dir, entry, §or); + if (!ep) + return; + + buf_lock(sb, sector); + + /* buf_lock() before call count_ext_entries() */ + num_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, entry, ep); + if (num_entries < 0) { + buf_unlock(sb, sector); + return; + } + num_entries++; + + buf_unlock(sb, sector); + + /* (1) update the directory entry */ + p_fs->fs_func->delete_dir_entry(sb, p_dir, entry, 0, num_entries); +} /* end of remove_file */ + +INT32 rename_file(struct inode *inode, CHAIN_T *p_dir, INT32 oldentry, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + INT32 ret, newentry = -1, num_old_entries, num_new_entries; + UINT32 sector_old, sector_new; + DOS_NAME_T dos_name; + DENTRY_T *epold, *epnew; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + epold = get_entry_in_dir(sb, p_dir, oldentry, §or_old); + if (!epold) + return FFS_MEDIAERR; + + buf_lock(sb, sector_old); + + /* buf_lock() before call count_ext_entries() */ + num_old_entries = p_fs->fs_func->count_ext_entries(sb, p_dir, oldentry, epold); + if (num_old_entries < 0) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_dir, p_uniname, &num_new_entries, &dos_name); + if (ret) { + buf_unlock(sb, sector_old); + return ret; + } + + if (num_old_entries < num_new_entries) { + newentry = find_empty_entry(inode, p_dir, num_new_entries); + if (newentry < 0) { + buf_unlock(sb, sector_old); + return FFS_FULL; + } + + epnew = get_entry_in_dir(sb, p_dir, newentry, §or_new); + if (!epnew) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + + MEMCPY((void *) epnew, (void *) epold, DENTRY_SIZE); + if (p_fs->fs_func->get_entry_type(epnew) == TYPE_FILE) { + p_fs->fs_func->set_entry_attr(epnew, p_fs->fs_func->get_entry_attr(epnew) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_new); + buf_unlock(sb, sector_old); + + if (p_fs->vol_type == EXFAT) { + epold = get_entry_in_dir(sb, p_dir, oldentry+1, §or_old); + buf_lock(sb, sector_old); + epnew = get_entry_in_dir(sb, p_dir, newentry+1, §or_new); + + if (!epold || !epnew) { + buf_unlock(sb, sector_old); + return FFS_MEDIAERR; + } + + MEMCPY((void *) epnew, (void *) epold, DENTRY_SIZE); + buf_modify(sb, sector_new); + buf_unlock(sb, sector_old); + } + + ret = p_fs->fs_func->init_ext_entry(sb, p_dir, newentry, num_new_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + p_fs->fs_func->delete_dir_entry(sb, p_dir, oldentry, 0, num_old_entries); + fid->entry = newentry; + } else { + if (p_fs->fs_func->get_entry_type(epold) == TYPE_FILE) { + p_fs->fs_func->set_entry_attr(epold, p_fs->fs_func->get_entry_attr(epold) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_old); + buf_unlock(sb, sector_old); + + ret = p_fs->fs_func->init_ext_entry(sb, p_dir, oldentry, num_new_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + p_fs->fs_func->delete_dir_entry(sb, p_dir, oldentry, num_new_entries, num_old_entries); + } + + return FFS_SUCCESS; +} /* end of rename_file */ + +INT32 move_file(struct inode *inode, CHAIN_T *p_olddir, INT32 oldentry, CHAIN_T *p_newdir, UNI_NAME_T *p_uniname, FILE_ID_T *fid) +{ + INT32 ret, newentry, num_new_entries, num_old_entries; + UINT32 sector_mov, sector_new; + CHAIN_T clu; + DOS_NAME_T dos_name; + DENTRY_T *epmov, *epnew; + struct super_block *sb = inode->i_sb; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + epmov = get_entry_in_dir(sb, p_olddir, oldentry, §or_mov); + if (!epmov) + return FFS_MEDIAERR; + + /* check if the source and target directory is the same */ + if (p_fs->fs_func->get_entry_type(epmov) == TYPE_DIR && + p_fs->fs_func->get_entry_clu0(epmov) == p_newdir->dir) + return FFS_INVALIDPATH; + + buf_lock(sb, sector_mov); + + /* buf_lock() before call count_ext_entries() */ + num_old_entries = p_fs->fs_func->count_ext_entries(sb, p_olddir, oldentry, epmov); + if (num_old_entries < 0) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + num_old_entries++; + + ret = get_num_entries_and_dos_name(sb, p_newdir, p_uniname, &num_new_entries, &dos_name); + if (ret) { + buf_unlock(sb, sector_mov); + return ret; + } + + newentry = find_empty_entry(inode, p_newdir, num_new_entries); + if (newentry < 0) { + buf_unlock(sb, sector_mov); + return FFS_FULL; + } + + epnew = get_entry_in_dir(sb, p_newdir, newentry, §or_new); + if (!epnew) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + + MEMCPY((void *) epnew, (void *) epmov, DENTRY_SIZE); + if (p_fs->fs_func->get_entry_type(epnew) == TYPE_FILE) { + p_fs->fs_func->set_entry_attr(epnew, p_fs->fs_func->get_entry_attr(epnew) | ATTR_ARCHIVE); + fid->attr |= ATTR_ARCHIVE; + } + buf_modify(sb, sector_new); + buf_unlock(sb, sector_mov); + + if (p_fs->vol_type == EXFAT) { + epmov = get_entry_in_dir(sb, p_olddir, oldentry+1, §or_mov); + buf_lock(sb, sector_mov); + epnew = get_entry_in_dir(sb, p_newdir, newentry+1, §or_new); + if (!epmov || !epnew) { + buf_unlock(sb, sector_mov); + return FFS_MEDIAERR; + } + + MEMCPY((void *) epnew, (void *) epmov, DENTRY_SIZE); + buf_modify(sb, sector_new); + buf_unlock(sb, sector_mov); + } else if (p_fs->fs_func->get_entry_type(epnew) == TYPE_DIR) { + /* change ".." pointer to new parent dir */ + clu.dir = p_fs->fs_func->get_entry_clu0(epnew); + clu.flags = 0x01; + + epnew = get_entry_in_dir(sb, &clu, 1, §or_new); + if (!epnew) + return FFS_MEDIAERR; + + if (p_newdir->dir == p_fs->root_dir) + p_fs->fs_func->set_entry_clu0(epnew, CLUSTER_32(0)); + else + p_fs->fs_func->set_entry_clu0(epnew, p_newdir->dir); + buf_modify(sb, sector_new); + } + + ret = p_fs->fs_func->init_ext_entry(sb, p_newdir, newentry, num_new_entries, p_uniname, &dos_name); + if (ret != FFS_SUCCESS) + return ret; + + p_fs->fs_func->delete_dir_entry(sb, p_olddir, oldentry, 0, num_old_entries); + + fid->dir.dir = p_newdir->dir; + fid->dir.size = p_newdir->size; + fid->dir.flags = p_newdir->flags; + + fid->entry = newentry; + + return FFS_SUCCESS; +} /* end of move_file */ + +/* + * Sector Read/Write Functions + */ + +INT32 sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 read) +{ + INT32 ret = FFS_MEDIAERR; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((sec >= (p_fs->PBR_sector+p_fs->num_sectors)) && (p_fs->num_sectors > 0)) { + PRINT("[EXFAT] sector_read: out of range error! (sec = %d)\n", sec); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_read(sb, sec, bh, 1, read); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} /* end of sector_read */ + +INT32 sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 sync) +{ + INT32 ret = FFS_MEDIAERR; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (sec >= (p_fs->PBR_sector+p_fs->num_sectors) && (p_fs->num_sectors > 0)) { + PRINT("[EXFAT] sector_write: out of range error! (sec = %d)\n", sec); + fs_error(sb); + return ret; + } + if (bh == NULL) { + PRINT("[EXFAT] sector_write: bh is NULL!\n"); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_write(sb, sec, bh, 1, sync); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} /* end of sector_write */ + +INT32 multi_sector_read(struct super_block *sb, UINT32 sec, struct buffer_head **bh, INT32 num_secs, INT32 read) +{ + INT32 ret = FFS_MEDIAERR; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (((sec+num_secs) > (p_fs->PBR_sector+p_fs->num_sectors)) && (p_fs->num_sectors > 0)) { + PRINT("[EXFAT] multi_sector_read: out of range error! (sec = %d, num_secs = %d)\n", sec, num_secs); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_read(sb, sec, bh, num_secs, read); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} /* end of multi_sector_read */ + +INT32 multi_sector_write(struct super_block *sb, UINT32 sec, struct buffer_head *bh, INT32 num_secs, INT32 sync) +{ + INT32 ret = FFS_MEDIAERR; + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if ((sec+num_secs) > (p_fs->PBR_sector+p_fs->num_sectors) && (p_fs->num_sectors > 0)) { + PRINT("[EXFAT] multi_sector_write: out of range error! (sec = %d, num_secs = %d)\n", sec, num_secs); + fs_error(sb); + return ret; + } + if (bh == NULL) { + PRINT("[EXFAT] multi_sector_write: bh is NULL!\n"); + fs_error(sb); + return ret; + } + + if (!p_fs->dev_ejected) { + ret = bdev_write(sb, sec, bh, num_secs, sync); + if (ret != FFS_SUCCESS) + p_fs->dev_ejected = TRUE; + } + + return ret; +} /* end of multi_sector_write */ + +/* end of exfat_core.c */ diff --git a/fs/exfat/exfat_data.c b/fs/exfat/exfat_data.c new file mode 100644 index 00000000000..37e1932109b --- /dev/null +++ b/fs/exfat/exfat_data.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_data.c */ +/* PURPOSE : exFAT Configuable Data Definitions */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_nls.h" +#include "exfat_super.h" +#include "exfat.h" + +/*======================================================================*/ +/* */ +/* GLOBAL VARIABLE DEFINITIONS */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* File Manager */ +/*----------------------------------------------------------------------*/ + +/* file system volume table */ +FS_STRUCT_T fs_struct[MAX_DRIVE]; + +#if 0 +/*----------------------------------------------------------------------*/ +/* Buffer Manager */ +/*----------------------------------------------------------------------*/ + +/* FAT cache */ +DECLARE_MUTEX(f_sem); +BUF_CACHE_T FAT_cache_array[FAT_CACHE_SIZE]; +BUF_CACHE_T FAT_cache_lru_list; +BUF_CACHE_T FAT_cache_hash_list[FAT_CACHE_HASH_SIZE]; + +/* buf cache */ +DECLARE_MUTEX(b_sem); +BUF_CACHE_T buf_cache_array[BUF_CACHE_SIZE]; +BUF_CACHE_T buf_cache_lru_list; +BUF_CACHE_T buf_cache_hash_list[BUF_CACHE_HASH_SIZE]; +#endif + +/* end of exfat_data.c */ diff --git a/fs/exfat/exfat_data.h b/fs/exfat/exfat_data.h new file mode 100644 index 00000000000..f1a0332c961 --- /dev/null +++ b/fs/exfat/exfat_data.h @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_data.h */ +/* PURPOSE : Header File for exFAT Configuable Constants */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_DATA_H +#define _EXFAT_DATA_H + +#include "exfat_config.h" +#include "exfat_global.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*======================================================================*/ + /* */ + /* FFS CONFIGURATIONS */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /* max number of block devices */ +#define MAX_DEVICE 2 + + /* max number of volumes on all block devices */ +#define MAX_DRIVE 2 + + /* max number of open files */ +#define MAX_OPEN 20 + + /* max number of root directory entries in FAT12/16 */ + /* (should be an exponential value of 2) */ +#define MAX_DENTRY 512 + + /* cache size (in number of sectors) */ + /* (should be an exponential value of 2) */ +#define FAT_CACHE_SIZE 128 +#define FAT_CACHE_HASH_SIZE 64 +#define BUF_CACHE_SIZE 256 +#define BUF_CACHE_HASH_SIZE 64 + +#ifndef CONFIG_EXFAT_DEFAULT_CODEPAGE +#define CONFIG_EXFAT_DEFAULT_CODEPAGE 437 +#define CONFIG_EXFAT_DEFAULT_IOCHARSET "utf8" +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_DATA_H */ + +/* end of exfat_data.h */ diff --git a/fs/exfat/exfat_global.c b/fs/exfat/exfat_global.c new file mode 100644 index 00000000000..036f08eb0a9 --- /dev/null +++ b/fs/exfat/exfat_global.c @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_global.c */ +/* PURPOSE : exFAT Miscellaneous Functions */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*======================================================================*/ +/* */ +/* LIBRARY FUNCTION DEFINITIONS -- WELL-KNOWN FUNCTIONS */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* String Manipulation Functions */ +/* (defined if no system memory functions are available) */ +/*----------------------------------------------------------------------*/ + +INT32 __wstrchr(UINT16 *str, UINT16 wchar) +{ + while (*str) { + if (*(str++) == wchar) return(1); + } + return(0); +} + +INT32 __wstrlen(UINT16 *str) +{ + INT32 length = 0; + + while (*(str++)) length++; + return(length); +} + +/*======================================================================*/ +/* */ +/* LIBRARY FUNCTION DEFINITIONS -- OTHER UTILITY FUNCTIONS */ +/* */ +/*======================================================================*/ + +/*----------------------------------------------------------------------*/ +/* Bitmap Manipulation Functions */ +/*----------------------------------------------------------------------*/ + +#define BITMAP_LOC(v) ((v) >> 3) +#define BITMAP_SHIFT(v) ((v) & 0x07) + +void Bitmap_set_all(UINT8 *bitmap, INT32 mapsize) +{ + MEMSET(bitmap, 0xFF, mapsize); +} /* end of Bitmap_set_all */ + +void Bitmap_clear_all(UINT8 *bitmap, INT32 mapsize) +{ + MEMSET(bitmap, 0x0, mapsize); +} /* end of Bitmap_clear_all */ + +INT32 Bitmap_test(UINT8 *bitmap, INT32 i) +{ + UINT8 data; + + data = bitmap[BITMAP_LOC(i)]; + if ((data >> BITMAP_SHIFT(i)) & 0x01) return(1); + return(0); +} /* end of Bitmap_test */ + +void Bitmap_set(UINT8 *bitmap, INT32 i) +{ + bitmap[BITMAP_LOC(i)] |= (0x01 << BITMAP_SHIFT(i)); +} /* end of Bitmap_set */ + +void Bitmap_clear(UINT8 *bitmap, INT32 i) +{ + bitmap[BITMAP_LOC(i)] &= ~(0x01 << BITMAP_SHIFT(i)); +} /* end of Bitmap_clear */ + +void Bitmap_nbits_set(UINT8 *bitmap, INT32 offset, INT32 nbits) +{ + INT32 i; + + for (i = 0; i < nbits; i++) { + Bitmap_set(bitmap, offset+i); + } +} /* end of Bitmap_nbits_set */ + +void Bitmap_nbits_clear(UINT8 *bitmap, INT32 offset, INT32 nbits) +{ + INT32 i; + + for (i = 0; i < nbits; i++) { + Bitmap_clear(bitmap, offset+i); + } +} /* end of Bitmap_nbits_clear */ + +/*----------------------------------------------------------------------*/ +/* Miscellaneous Library Functions */ +/*----------------------------------------------------------------------*/ + +/* integer to ascii conversion */ +void my_itoa(INT8 *buf, INT32 v) +{ + INT32 mod[10]; + INT32 i; + + for (i = 0; i < 10; i++) { + mod[i] = (v % 10); + v = v / 10; + if (v == 0) break; + } + + if (i == 10) + i--; + + for (; i >= 0; i--) { + *buf = (UINT8) ('0' + mod[i]); + buf++; + } + *buf = '\0'; +} /* end of my_itoa */ + +/* value to base 2 log conversion */ +INT32 my_log2(UINT32 v) +{ + UINT32 bits = 0; + + while (v > 1) { + if (v & 0x01) return(-1); + v >>= 1; + bits++; + } + return(bits); +} /* end of my_log2 */ + +/* end of exfat_global.c */ diff --git a/fs/exfat/exfat_global.h b/fs/exfat/exfat_global.h new file mode 100644 index 00000000000..890bd390de3 --- /dev/null +++ b/fs/exfat/exfat_global.h @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_global.h */ +/* PURPOSE : Header File for exFAT Global Definitions & Misc Functions */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_GLOBAL_H +#define _EXFAT_GLOBAL_H + +#include +#include +#include +#include +#include + +#include "exfat_config.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*======================================================================*/ + /* */ + /* CONSTANT & MACRO DEFINITIONS */ + /* */ + /*======================================================================*/ + + /*----------------------------------------------------------------------*/ + /* Well-Known Constants (DO NOT CHANGE THIS PART !!) */ + /*----------------------------------------------------------------------*/ + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif +#ifndef OK +#define OK 0 +#endif +#ifndef FAIL +#define FAIL 1 +#endif +#ifndef NULL +#define NULL 0 +#endif + + /* Min/Max macro */ +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + + /*======================================================================*/ + /* */ + /* TYPE DEFINITIONS */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /* type definitions for primitive types; + these should be re-defined to meet its size for each OS platform; + these should be used instead of primitive types for portability. */ + + typedef char INT8; // 1 byte signed integer + typedef short INT16; // 2 byte signed integer + typedef int INT32; // 4 byte signed integer + typedef long long INT64; // 8 byte signed integer + + typedef unsigned char UINT8; // 1 byte unsigned integer + typedef unsigned short UINT16; // 2 byte unsigned integer + typedef unsigned int UINT32; // 4 byte unsigned integer + typedef unsigned long long UINT64; // 8 byte ussigned integer + + typedef unsigned char BOOL; + + + /*======================================================================*/ + /* */ + /* LIBRARY FUNCTION DECLARATIONS -- WELL-KNOWN FUNCTIONS */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /*----------------------------------------------------------------------*/ + /* Memory Manipulation Macros & Functions */ + /*----------------------------------------------------------------------*/ + +#ifdef MALLOC +#undef MALLOC +#endif +#ifdef FREE +#undef FREE +#endif +#ifdef MEMSET +#undef MEMSET +#endif +#ifdef MEMCPY +#undef MEMCPY +#endif +#ifdef MEMCMP +#undef MEMCMP +#endif + +#define MALLOC(size) kmalloc(size, GFP_KERNEL) +#define FREE(mem) if (mem) kfree(mem) +#define MEMSET(mem, value, size) memset(mem, value, size) +#define MEMCPY(dest, src, size) memcpy(dest, src, size) +#define MEMCMP(mem1, mem2, size) memcmp(mem1, mem2, size) +#define COPY_DENTRY(dest, src) memcpy(dest, src, sizeof(DENTRY_T)) + + /*----------------------------------------------------------------------*/ + /* String Manipulation Macros & Functions */ + /*----------------------------------------------------------------------*/ + +#define STRCPY(dest, src) strcpy(dest, src) +#define STRNCPY(dest, src, n) strncpy(dest, src, n) +#define STRCAT(str1, str2) strcat(str1, str2) +#define STRCMP(str1, str2) strcmp(str1, str2) +#define STRNCMP(str1, str2, n) strncmp(str1, str2, n) +#define STRLEN(str) strlen(str) + + INT32 __wstrchr(UINT16 *str, UINT16 wchar); + INT32 __wstrlen(UINT16 *str); + +#define WSTRCHR(str, wchar) __wstrchr(str, wchar) +#define WSTRLEN(str) __wstrlen(str) + + /*----------------------------------------------------------------------*/ + /* Debugging Macros & Functions */ + /* EXFAT_CONFIG_DEBUG_MSG is configured in exfat_config.h */ + /*----------------------------------------------------------------------*/ +#if EXFAT_CONFIG_DEBUG_MSG +#define PRINTK(...) \ + do { \ + printk("[EXFAT] " __VA_ARGS__); \ + } while(0) +#else +#define PRINTK(...) +#endif + + /*======================================================================*/ + /* */ + /* LIBRARY FUNCTION DECLARATIONS -- OTHER UTILITY FUNCTIONS */ + /* (DO NOT CHANGE THIS PART !!) */ + /* */ + /*======================================================================*/ + + /*----------------------------------------------------------------------*/ + /* Bitmap Manipulation Functions */ + /*----------------------------------------------------------------------*/ + + void Bitmap_set_all(UINT8 *bitmap, INT32 mapsize); + void Bitmap_clear_all(UINT8 *bitmap, INT32 mapsize); + INT32 Bitmap_test(UINT8 *bitmap, INT32 i); + void Bitmap_set(UINT8 *bitmap, INT32 i); + void Bitmap_clear(UINT8 *bitmpa, INT32 i); + void Bitmap_nbits_set(UINT8 *bitmap, INT32 offset, INT32 nbits); + void Bitmap_nbits_clear(UINT8 *bitmap, INT32 offset, INT32 nbits); + + /*----------------------------------------------------------------------*/ + /* Miscellaneous Library Functions */ + /*----------------------------------------------------------------------*/ + + void my_itoa(INT8 *buf, INT32 v); + INT32 my_log2(UINT32 v); + + /*======================================================================*/ + /* */ + /* DEFINITIONS FOR DEBUGGING */ + /* (CHANGE THIS PART IF REQUIRED) */ + /* */ + /*======================================================================*/ + + /* debug message ouput macro */ +#ifdef PRINT +#undef PRINT +#endif + +#define PRINT printk + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_GLOBAL_H */ + +/* end of exfat_global.h */ diff --git a/fs/exfat/exfat_nls.c b/fs/exfat/exfat_nls.c new file mode 100644 index 00000000000..f80af8b186b --- /dev/null +++ b/fs/exfat/exfat_nls.c @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_nls.c */ +/* PURPOSE : exFAT NLS Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" + +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat_super.h" +#include "exfat.h" + +#include + +/*----------------------------------------------------------------------*/ +/* Global Variable Definitions */ +/*----------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------*/ +/* Local Variable Definitions */ +/*----------------------------------------------------------------------*/ + +static UINT16 bad_dos_chars[] = { + /* + , ; = [ ] */ + 0x002B, 0x002C, 0x003B, 0x003D, 0x005B, 0x005D, + 0xFF0B, 0xFF0C, 0xFF1B, 0xFF1D, 0xFF3B, 0xFF3D, + 0 +}; + +static UINT16 bad_uni_chars[] = { + /* " * / : < > ? \ | */ + 0x0022, 0x002A, 0x002F, 0x003A, + 0x003C, 0x003E, 0x003F, 0x005C, 0x007C, + 0 +}; + +/*----------------------------------------------------------------------*/ +/* Local Function Declarations */ +/*----------------------------------------------------------------------*/ + +static INT32 convert_uni_to_ch(struct nls_table *nls, UINT8 *ch, UINT16 uni, INT32 *lossy); +static INT32 convert_ch_to_uni(struct nls_table *nls, UINT16 *uni, UINT8 *ch, INT32 *lossy); + +/*======================================================================*/ +/* Global Function Definitions */ +/*======================================================================*/ + +UINT16 nls_upper(struct super_block *sb, UINT16 a) +{ + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + + if (EXFAT_SB(sb)->options.casesensitive) + return(a); + if (p_fs->vol_utbl != NULL && (p_fs->vol_utbl)[get_col_index(a)] != NULL) + return (p_fs->vol_utbl)[get_col_index(a)][get_row_index(a)]; + else + return a; +} + +INT32 nls_dosname_cmp(struct super_block *sb, UINT8 *a, UINT8 *b) +{ + return(STRNCMP((void *) a, (void *) b, DOS_NAME_LENGTH)); +} /* end of nls_dosname_cmp */ + +INT32 nls_uniname_cmp(struct super_block *sb, UINT16 *a, UINT16 *b) +{ + INT32 i; + + for (i = 0; i < MAX_NAME_LENGTH; i++, a++, b++) { + if (nls_upper(sb, *a) != nls_upper(sb, *b)) return(1); + if (*a == 0x0) return(0); + } + return(0); +} /* end of nls_uniname_cmp */ + +void nls_uniname_to_dosname(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname, INT32 *p_lossy) +{ + INT32 i, j, len, lossy = FALSE; + UINT8 buf[MAX_CHARSET_SIZE]; + UINT8 lower = 0, upper = 0; + UINT8 *dosname = p_dosname->name; + UINT16 *uniname = p_uniname->name; + UINT16 *p, *last_period; + struct nls_table *nls = EXFAT_SB(sb)->nls_disk; + + for (i = 0; i < DOS_NAME_LENGTH; i++) { + *(dosname+i) = ' '; + } + + if (!nls_uniname_cmp(sb, uniname, (UINT16 *) UNI_CUR_DIR_NAME)) { + *(dosname) = '.'; + p_dosname->name_case = 0x0; + if (p_lossy != NULL) *p_lossy = FALSE; + return; + } + + if (!nls_uniname_cmp(sb, uniname, (UINT16 *) UNI_PAR_DIR_NAME)) { + *(dosname) = '.'; + *(dosname+1) = '.'; + p_dosname->name_case = 0x0; + if (p_lossy != NULL) *p_lossy = FALSE; + return; + } + + /* search for the last embedded period */ + last_period = NULL; + for (p = uniname; *p; p++) { + if (*p == (UINT16) '.') last_period = p; + } + + i = 0; + while (i < DOS_NAME_LENGTH) { + if (i == 8) { + if (last_period == NULL) break; + + if (uniname <= last_period) { + if (uniname < last_period) lossy = TRUE; + uniname = last_period + 1; + } + } + + if (*uniname == (UINT16) '\0') { + break; + } else if (*uniname == (UINT16) ' ') { + lossy = TRUE; + } else if (*uniname == (UINT16) '.') { + if (uniname < last_period) lossy = TRUE; + else i = 8; + } else if (WSTRCHR(bad_dos_chars, *uniname)) { + lossy = TRUE; + *(dosname+i) = '_'; + i++; + } else { + len = convert_uni_to_ch(nls, buf, *uniname, &lossy); + + if (len > 1) { + if ((i >= 8) && ((i+len) > DOS_NAME_LENGTH)) { + break; + } + if ((i < 8) && ((i+len) > 8)) { + i = 8; + continue; + } + + lower = 0xFF; + + for (j = 0; j < len; j++, i++) { + *(dosname+i) = *(buf+j); + } + } else { /* len == 1 */ + if ((*buf >= 'a') && (*buf <= 'z')) { + *(dosname+i) = *buf - ('a' - 'A'); + + if (i < 8) lower |= 0x08; + else lower |= 0x10; + } else if ((*buf >= 'A') && (*buf <= 'Z')) { + *(dosname+i) = *buf; + + if (i < 8) upper |= 0x08; + else upper |= 0x10; + } else { + *(dosname+i) = *buf; + } + i++; + } + } + + uniname++; + } + + if (*dosname == 0xE5) *dosname = 0x05; + if (*uniname != 0x0) lossy = TRUE; + + if (upper & lower) p_dosname->name_case = 0xFF; + else p_dosname->name_case = lower; + + if (p_lossy != NULL) *p_lossy = lossy; +} /* end of nls_uniname_to_dosname */ + +void nls_dosname_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname) +{ + INT32 i = 0, j, n = 0; + UINT8 buf[DOS_NAME_LENGTH+2]; + UINT8 *dosname = p_dosname->name; + UINT16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_disk; + + if (*dosname == 0x05) { + *buf = 0xE5; + i++; + n++; + } + + for ( ; i < 8; i++, n++) { + if (*(dosname+i) == ' ') break; + + if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && (p_dosname->name_case & 0x08)) + *(buf+n) = *(dosname+i) + ('a' - 'A'); + else + *(buf+n) = *(dosname+i); + } + if (*(dosname+8) != ' ') { + *(buf+n) = '.'; + n++; + } + + for (i = 8; i < DOS_NAME_LENGTH; i++, n++) { + if (*(dosname+i) == ' ') break; + + if ((*(dosname+i) >= 'A') && (*(dosname+i) <= 'Z') && (p_dosname->name_case & 0x10)) + *(buf+n) = *(dosname+i) + ('a' - 'A'); + else + *(buf+n) = *(dosname+i); + } + *(buf+n) = '\0'; + + i = j = 0; + while (j < (MAX_NAME_LENGTH-1)) { + if (*(buf+i) == '\0') break; + + i += convert_ch_to_uni(nls, uniname, (buf+i), NULL); + + uniname++; + j++; + } + + *uniname = (UINT16) '\0'; +} /* end of nls_dosname_to_uniname */ + +void nls_uniname_to_cstring(struct super_block *sb, UINT8 *p_cstring, UNI_NAME_T *p_uniname) +{ + INT32 i, j, len; + UINT8 buf[MAX_CHARSET_SIZE]; + UINT16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + i = 0; + while (i < (MAX_NAME_LENGTH-1)) { + if (*uniname == (UINT16) '\0') break; + + len = convert_uni_to_ch(nls, buf, *uniname, NULL); + + if (len > 1) { + for (j = 0; j < len; j++) + *p_cstring++ = (INT8) *(buf+j); + } else { /* len == 1 */ + *p_cstring++ = (INT8) *buf; + } + + uniname++; + i++; + } + + *p_cstring = '\0'; +} /* end of nls_uniname_to_cstring */ + +void nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, UINT8 *p_cstring, INT32 *p_lossy) +{ + INT32 i, j, lossy = FALSE; + UINT8 *end_of_name; + UINT8 upname[MAX_NAME_LENGTH * 2]; + UINT16 *uniname = p_uniname->name; + struct nls_table *nls = EXFAT_SB(sb)->nls_io; + + + /* strip all trailing spaces */ + end_of_name = p_cstring + STRLEN((INT8 *) p_cstring); + + while (*(--end_of_name) == ' ') { + if (end_of_name < p_cstring) break; + } + *(++end_of_name) = '\0'; + + if (STRCMP((INT8 *) p_cstring, ".") && STRCMP((INT8 *) p_cstring, "..")) { + + /* strip all trailing periods */ + while (*(--end_of_name) == '.') { + if (end_of_name < p_cstring) break; + } + *(++end_of_name) = '\0'; + } + + if (*p_cstring == '\0') + lossy = TRUE; + + i = j = 0; + while (j < (MAX_NAME_LENGTH-1)) { + if (*(p_cstring+i) == '\0') break; + + i += convert_ch_to_uni(nls, uniname, (UINT8 *)(p_cstring+i), &lossy); + + if ((*uniname < 0x0020) || WSTRCHR(bad_uni_chars, *uniname)) + lossy = TRUE; + + SET16_A(upname + j * 2, nls_upper(sb, *uniname)); + + uniname++; + j++; + } + + if (*(p_cstring+i) != '\0') + lossy = TRUE; + *uniname = (UINT16) '\0'; + + p_uniname->name_len = j; + p_uniname->name_hash = calc_checksum_2byte((void *) upname, j<<1, 0, CS_DEFAULT); + + if (p_lossy != NULL) + *p_lossy = lossy; +} /* end of nls_cstring_to_uniname */ + +/*======================================================================*/ +/* Local Function Definitions */ +/*======================================================================*/ + +static INT32 convert_ch_to_uni(struct nls_table *nls, UINT16 *uni, UINT8 *ch, INT32 *lossy) +{ + int len; + + *uni = 0x0; + + if (ch[0] < 0x80) { + *uni = (UINT16) ch[0]; + return(1); + } + + if ((len = nls->char2uni(ch, NLS_MAX_CHARSET_SIZE, uni)) < 0) { + /* conversion failed */ + printk("%s: fail to use nls \n", __func__); + if (lossy != NULL) + *lossy = TRUE; + *uni = (UINT16) '_'; + if (!strcmp(nls->charset, "utf8")) return(1); + else return(2); + } + + return(len); +} /* end of convert_ch_to_uni */ + +static INT32 convert_uni_to_ch(struct nls_table *nls, UINT8 *ch, UINT16 uni, INT32 *lossy) +{ + int len; + + ch[0] = 0x0; + + if (uni < 0x0080) { + ch[0] = (UINT8) uni; + return(1); + } + + if ((len = nls->uni2char(uni, ch, NLS_MAX_CHARSET_SIZE)) < 0) { + /* conversion failed */ + printk("%s: fail to use nls \n", __func__); + if (lossy != NULL) *lossy = TRUE; + ch[0] = '_'; + return(1); + } + + return(len); + +} /* end of convert_uni_to_ch */ + +/* end of exfat_nls.c */ diff --git a/fs/exfat/exfat_nls.h b/fs/exfat/exfat_nls.h new file mode 100644 index 00000000000..5b14cef0246 --- /dev/null +++ b/fs/exfat/exfat_nls.h @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_nls.h */ +/* PURPOSE : Header File for exFAT NLS Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_NLS_H +#define _EXFAT_NLS_H + +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_api.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define NUM_UPCASE 2918 + +#define DOS_CUR_DIR_NAME ". " +#define DOS_PAR_DIR_NAME ".. " + +#ifdef __LITTLE_ENDIAN +#define UNI_CUR_DIR_NAME ".\0" +#define UNI_PAR_DIR_NAME ".\0.\0" +#else +#define UNI_CUR_DIR_NAME "\0." +#define UNI_PAR_DIR_NAME "\0.\0." +#endif + +/*----------------------------------------------------------------------*/ +/* Type Definitions */ +/*----------------------------------------------------------------------*/ + +/* DOS name stucture */ +typedef struct { + UINT8 name[DOS_NAME_LENGTH]; + UINT8 name_case; +} DOS_NAME_T; + +/* unicode name stucture */ +typedef struct { + UINT16 name[MAX_NAME_LENGTH]; + UINT16 name_hash; + UINT8 name_len; +} UNI_NAME_T; + +/*----------------------------------------------------------------------*/ +/* External Function Declarations */ +/*----------------------------------------------------------------------*/ + +/* NLS management function */ +UINT16 nls_upper(struct super_block *sb, UINT16 a); +INT32 nls_dosname_cmp(struct super_block *sb, UINT8 *a, UINT8 *b); +INT32 nls_uniname_cmp(struct super_block *sb, UINT16 *a, UINT16 *b); +void nls_uniname_to_dosname(struct super_block *sb, DOS_NAME_T *p_dosname, UNI_NAME_T *p_uniname, INT32 *p_lossy); +void nls_dosname_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, DOS_NAME_T *p_dosname); +void nls_uniname_to_cstring(struct super_block *sb, UINT8 *p_cstring, UNI_NAME_T *p_uniname); +void nls_cstring_to_uniname(struct super_block *sb, UNI_NAME_T *p_uniname, UINT8 *p_cstring, INT32 *p_lossy); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_NLS_H */ + +/* end of exfat_nls.h */ diff --git a/fs/exfat/exfat_oal.c b/fs/exfat/exfat_oal.c new file mode 100644 index 00000000000..8d1a9b93bcc --- /dev/null +++ b/fs/exfat/exfat_oal.c @@ -0,0 +1,189 @@ +/* Some of the source code in this file came from "linux/fs/fat/misc.c". */ +/* + * linux/fs/fat/misc.c + * + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_oal.c */ +/* PURPOSE : exFAT OS Adaptation Layer */ +/* (Semaphore Functions & Real-Time Clock Functions) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_api.h" +#include "exfat_oal.h" + +/*======================================================================*/ +/* */ +/* SEMAPHORE FUNCTIONS */ +/* */ +/*======================================================================*/ + +DECLARE_MUTEX(z_sem); + +INT32 sm_init(struct semaphore *sm) +{ + sema_init(sm, 1); + return(0); +} /* end of sm_init */ + +INT32 sm_P(struct semaphore *sm) +{ + down(sm); + return 0; +} /* end of sm_P */ + +void sm_V(struct semaphore *sm) +{ + up(sm); +} /* end of sm_V */ + + +/*======================================================================*/ +/* */ +/* REAL-TIME CLOCK FUNCTIONS */ +/* */ +/*======================================================================*/ + +extern struct timezone sys_tz; + +/* + * The epoch of FAT timestamp is 1980. + * : bits : value + * date: 0 - 4: day (1 - 31) + * date: 5 - 8: month (1 - 12) + * date: 9 - 15: year (0 - 127) from 1980 + * time: 0 - 4: sec (0 - 29) 2sec counts + * time: 5 - 10: min (0 - 59) + * time: 11 - 15: hour (0 - 23) + */ +#define UNIX_SECS_1980 315532800L + +#if BITS_PER_LONG == 64 +#define UNIX_SECS_2108 4354819200L +#endif +/* days between 1.1.70 and 1.1.80 (2 leap days) */ +#define DAYS_DELTA_DECADE (365 * 10 + 2) +/* 120 (2100 - 1980) isn't leap year */ +#define NO_LEAP_YEAR_2100 (120) +#define IS_LEAP_YEAR(y) (!((y) & 3) && (y) != NO_LEAP_YEAR_2100) + +#define SECS_PER_MIN (60) +#define SECS_PER_HOUR (60 * SECS_PER_MIN) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) + +#define MAKE_LEAP_YEAR(leap_year, year) \ + do { \ + if (unlikely(year > NO_LEAP_YEAR_2100)) \ + leap_year = ((year + 3) / 4) - 1; \ + else \ + leap_year = ((year + 3) / 4); \ + } while(0) + +/* Linear day numbers of the respective 1sts in non-leap years. */ +static time_t accum_days_in_year[] = { + /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, +}; + +TIMESTAMP_T *tm_current(TIMESTAMP_T *tp) +{ + struct timespec ts = CURRENT_TIME_SEC; + time_t second = ts.tv_sec; + time_t day, leap_day, month, year; + + second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (second < UNIX_SECS_1980) { + tp->sec = 0; + tp->min = 0; + tp->hour = 0; + tp->day = 1; + tp->mon = 1; + tp->year = 0; + return(tp); + } +#if BITS_PER_LONG == 64 + if (second >= UNIX_SECS_2108) { + tp->sec = 59; + tp->min = 59; + tp->hour = 23; + tp->day = 31; + tp->mon = 12; + tp->year = 127; + return(tp); + } +#endif + + day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; + year = day / 365; + + MAKE_LEAP_YEAR(leap_day, year); + if (year * 365 + leap_day > day) + year--; + + MAKE_LEAP_YEAR(leap_day, year); + + day -= year * 365 + leap_day; + + if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { + month = 2; + } else { + if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) + day--; + for (month = 1; month < 12; month++) { + if (accum_days_in_year[month + 1] > day) + break; + } + } + day -= accum_days_in_year[month]; + + tp->sec = second % SECS_PER_MIN; + tp->min = (second / SECS_PER_MIN) % 60; + tp->hour = (second / SECS_PER_HOUR) % 24; + tp->day = day + 1; + tp->mon = month; + tp->year = year; + + return(tp); +} /* end of tm_current */ + +/* end of exfat_oal.c */ diff --git a/fs/exfat/exfat_oal.h b/fs/exfat/exfat_oal.h new file mode 100644 index 00000000000..ca3f956eead --- /dev/null +++ b/fs/exfat/exfat_oal.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_oal.h */ +/* PURPOSE : Header File for exFAT OS Adaptation Layer */ +/* (Semaphore Functions & Real-Time Clock Functions) */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_OAL_H +#define _EXFAT_OAL_H + +#include "exfat_config.h" +#include "exfat_global.h" +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions (Configurable) */ + /*----------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions (Non-Configurable) */ + /*----------------------------------------------------------------------*/ + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + typedef struct { + UINT16 sec; /* 0 ~ 59 */ + UINT16 min; /* 0 ~ 59 */ + UINT16 hour; /* 0 ~ 23 */ + UINT16 day; /* 1 ~ 31 */ + UINT16 mon; /* 1 ~ 12 */ + UINT16 year; /* 0 ~ 127 (since 1980) */ + } TIMESTAMP_T; + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) +#define DECLARE_MUTEX(m) DEFINE_SEMAPHORE(m) +#endif + + INT32 sm_init(struct semaphore *sm); + INT32 sm_P(struct semaphore *sm); + void sm_V(struct semaphore *sm); + + TIMESTAMP_T *tm_current(TIMESTAMP_T *tm); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_OAL_H */ + +/* end of exfat_oal.h */ diff --git a/fs/exfat/exfat_part.h b/fs/exfat/exfat_part.h new file mode 100644 index 00000000000..94dd8862f5e --- /dev/null +++ b/fs/exfat/exfat_part.h @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_part.h */ +/* PURPOSE : Header File for exFAT Partition Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#ifndef _EXFAT_PART_H +#define _EXFAT_PART_H + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_api.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + /*----------------------------------------------------------------------*/ + /* Constant & Macro Definitions */ + /*----------------------------------------------------------------------*/ + +#define MBR_SIGNATURE 0xAA55 + + /*----------------------------------------------------------------------*/ + /* Type Definitions */ + /*----------------------------------------------------------------------*/ + + /* MS-DOS FAT master boot record (512 bytes) */ + typedef struct { + UINT8 boot_code[446]; + UINT8 partition[64]; + UINT8 signature[2]; + } MBR_SECTOR_T; + + /* MS-DOS FAT partition table (64 bytes) */ + typedef struct { + UINT8 def_boot; + UINT8 bgn_chs[3]; + UINT8 sys_type; + UINT8 end_chs[3]; + UINT8 start_sector[4]; + UINT8 num_sectors[4]; + } PART_ENTRY_T; + + /*----------------------------------------------------------------------*/ + /* External Function Declarations */ + /*----------------------------------------------------------------------*/ + + /* volume management functions */ + INT32 ffsSetPartition(INT32 dev, INT32 num_vol, PART_INFO_T *vol_spec); + INT32 ffsGetPartition(INT32 dev, INT32 *num_vol, PART_INFO_T *vol_spec); + INT32 ffsGetDevInfo(INT32 dev, DEV_INFO_T *info); + + /*----------------------------------------------------------------------*/ + /* External Function Declarations (NOT TO UPPER LAYER) */ + /*----------------------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* _EXFAT_PART_H */ + +/* end of exfat_part.h */ diff --git a/fs/exfat/exfat_super.c b/fs/exfat/exfat_super.c new file mode 100644 index 00000000000..1bc3b0d2104 --- /dev/null +++ b/fs/exfat/exfat_super.c @@ -0,0 +1,2306 @@ +/* Some of the source code in this file came from "linux/fs/fat/file.c","linux/fs/fat/inode.c" and "linux/fs/fat/misc.c". */ +/* + * linux/fs/fat/file.c + * + * Written 1992,1993 by Werner Almesberger + * + * regular file handling primitives for fat-based filesystems + */ + +/* + * linux/fs/fat/inode.c + * + * Written 1992,1993 by Werner Almesberger + * VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner + * Rewritten for the constant inumbers support by Al Viro + * + * Fixes: + * + * Max Cohan: Fixed invalid FSINFO offset when info_sector is 0 + */ + +/* + * linux/fs/fat/misc.c + * + * Written 1992,1993 by Werner Almesberger + * 22/11/2000 - Fixed fat_date_unix2dos for dates earlier than 01/01/1980 + * and date_dos2unix for date==0 by Igor Zhbanov(bsg@uniyar.ac.ru) + */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) +#include +#endif + +#include "exfat_version.h" +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_part.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat.h" + +#include "exfat_super.h" + +static struct kmem_cache *exfat_inode_cachep; + +static int exfat_default_codepage = CONFIG_EXFAT_DEFAULT_CODEPAGE; +static char exfat_default_iocharset[] = CONFIG_EXFAT_DEFAULT_IOCHARSET; + +extern struct timezone sys_tz; + +#define CHECK_ERR(x) BUG_ON(x) +#define ELAPSED_TIME 0 + +#if (ELAPSED_TIME == 1) +#include + +static UINT32 __t1, __t2; +static UINT32 get_current_msec(void) +{ + struct timeval tm; + do_gettimeofday(&tm); + return((UINT32)(tm.tv_sec*1000000 + tm.tv_usec)); +} +#define TIME_START() do {__t1 = get_current_msec();} while (0) +#define TIME_END() do {__t2 = get_current_msec();} while (0) +#define PRINT_TIME(n) do {printk("[EXFAT] Elapsed time %d = %d (usec)\n", n, (__t2 - __t1));} while (0) +#else +#define TIME_START() +#define TIME_END() +#define PRINT_TIME(n) +#endif + +#define UNIX_SECS_1980 315532800L + +#if BITS_PER_LONG == 64 +#define UNIX_SECS_2108 4354819200L +#endif +/* days between 1.1.70 and 1.1.80 (2 leap days) */ +#define DAYS_DELTA_DECADE (365 * 10 + 2) +/* 120 (2100 - 1980) isn't leap year */ +#define NO_LEAP_YEAR_2100 (120) +#define IS_LEAP_YEAR(y) (!((y) & 0x3) && (y) != NO_LEAP_YEAR_2100) + +#define SECS_PER_MIN (60) +#define SECS_PER_HOUR (60 * SECS_PER_MIN) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) + +#define MAKE_LEAP_YEAR(leap_year, year) \ + do { \ + if (unlikely(year > NO_LEAP_YEAR_2100)) \ + leap_year = ((year + 3) / 4) - 1; \ + else \ + leap_year = ((year + 3) / 4); \ + } while(0) + +/* Linear day numbers of the respective 1sts in non-leap years. */ +static time_t accum_days_in_year[] = { + /* Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec */ + 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 0, 0, 0, +}; + +static void _exfat_truncate(struct inode *inode, loff_t old_size); + +/* Convert a FAT time/date pair to a UNIX date (seconds since 1 1 70). */ +void exfat_time_fat2unix(struct exfat_sb_info *sbi, struct timespec *ts, + DATE_TIME_T *tp) +{ + time_t year = tp->Year; + time_t ld; + + MAKE_LEAP_YEAR(ld, year); + + if (IS_LEAP_YEAR(year) && (tp->Month) > 2) + ld++; + + ts->tv_sec = tp->Second + tp->Minute * SECS_PER_MIN + + tp->Hour * SECS_PER_HOUR + + (year * 365 + ld + accum_days_in_year[(tp->Month)] + (tp->Day - 1) + DAYS_DELTA_DECADE) * SECS_PER_DAY + + sys_tz.tz_minuteswest * SECS_PER_MIN; + ts->tv_nsec = 0; +} + +/* Convert linear UNIX date to a FAT time/date pair. */ +void exfat_time_unix2fat(struct exfat_sb_info *sbi, struct timespec *ts, + DATE_TIME_T *tp) +{ + time_t second = ts->tv_sec; + time_t day, month, year; + time_t ld; + + second -= sys_tz.tz_minuteswest * SECS_PER_MIN; + + /* Jan 1 GMT 00:00:00 1980. But what about another time zone? */ + if (second < UNIX_SECS_1980) { + tp->Second = 0; + tp->Minute = 0; + tp->Hour = 0; + tp->Day = 1; + tp->Month = 1; + tp->Year = 0; + return; + } +#if (BITS_PER_LONG == 64) + if (second >= UNIX_SECS_2108) { + tp->Second = 59; + tp->Minute = 59; + tp->Hour = 23; + tp->Day = 31; + tp->Month = 12; + tp->Year = 127; + return; + } +#endif + day = second / SECS_PER_DAY - DAYS_DELTA_DECADE; + year = day / 365; + MAKE_LEAP_YEAR(ld, year); + if (year * 365 + ld > day) + year--; + + MAKE_LEAP_YEAR(ld, year); + day -= year * 365 + ld; + + if (IS_LEAP_YEAR(year) && day == accum_days_in_year[3]) { + month = 2; + } else { + if (IS_LEAP_YEAR(year) && day > accum_days_in_year[3]) + day--; + for (month = 1; month < 12; month++) { + if (accum_days_in_year[month + 1] > day) + break; + } + } + day -= accum_days_in_year[month]; + + tp->Second = second % SECS_PER_MIN; + tp->Minute = (second / SECS_PER_MIN) % 60; + tp->Hour = (second / SECS_PER_HOUR) % 24; + tp->Day = day + 1; + tp->Month = month; + tp->Year = year; +} + +static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos); +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +static int exfat_generic_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); +#else +static long exfat_generic_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); +#endif +static int exfat_sync_inode(struct inode *inode); +static struct inode *exfat_build_inode(struct super_block *sb, FILE_ID_T *fid, loff_t i_pos); +static void exfat_detach(struct inode *inode); +static void exfat_attach(struct inode *inode, loff_t i_pos); +static inline unsigned long exfat_hash(loff_t i_pos); +static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc); +static void exfat_write_super(struct super_block *sb); + +static void __lock_super(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + lock_super(sb); +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + mutex_lock(&sbi->s_lock); +#endif +} + +static void __unlock_super(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + unlock_super(sb); +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + mutex_unlock(&sbi->s_lock); +#endif +} + +static int __is_sb_dirty(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + return sb->s_dirt; +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + return sbi->s_dirt; +#endif +} + +static void __set_sb_clean(struct super_block *sb) +{ +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + sb->s_dirt = 0; +#else + struct exfat_sb_info *sbi = EXFAT_SB(sb); + sbi->s_dirt = 0; +#endif +} + +/*======================================================================*/ +/* Directory Entry Operations */ +/*======================================================================*/ + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) +static int exfat_readdir(struct file *filp, struct dir_context *ctx) +#else +static int exfat_readdir(struct file *filp, void *dirent, filldir_t filldir) +#endif +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,9,0) + struct inode *inode = file_inode(filp); +#else + struct inode *inode = filp->f_path.dentry->d_inode; +#endif + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + BD_INFO_T *p_bd = &(EXFAT_SB(sb)->bd_info); + DIR_ENTRY_T de; + unsigned long inum; + loff_t cpos; + int err = 0; + + __lock_super(sb); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + cpos = ctx->pos; +#else + cpos = filp->f_pos; +#endif + /* Fake . and .. for the root directory. */ + if ((p_fs->vol_type == EXFAT) || (inode->i_ino == EXFAT_ROOT_INO)) { + while (cpos < 2) { + if (inode->i_ino == EXFAT_ROOT_INO) + inum = EXFAT_ROOT_INO; + else if (cpos == 0) + inum = inode->i_ino; + else /* (cpos == 1) */ + inum = parent_ino(filp->f_path.dentry); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + if (!dir_emit_dots(filp, ctx)) +#else + if (filldir(dirent, "..", cpos+1, cpos, inum, DT_DIR) < 0) +#endif + goto out; + cpos++; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + ctx->pos++; +#else + filp->f_pos++; +#endif + } + if (cpos == 2) { + cpos = 0; + } + } + if (cpos & (DENTRY_SIZE - 1)) { + err = -ENOENT; + goto out; + } + +get_new: + EXFAT_I(inode)->fid.size = i_size_read(inode); + EXFAT_I(inode)->fid.rwoffset = cpos >> DENTRY_SIZE_BITS; + + err = FsReadDir(inode, &de); + if (err) { + /* at least we tried to read a sector + * move cpos to next sector position (should be aligned) + */ + if (err == FFS_MEDIAERR) { + cpos += 1 << p_bd->sector_size_bits; + cpos &= ~((1 << p_bd->sector_size_bits)-1); + } + + err = -EIO; + goto end_of_dir; + } + + cpos = EXFAT_I(inode)->fid.rwoffset << DENTRY_SIZE_BITS; + + if (!de.Name[0]) + goto end_of_dir; + + if (!memcmp(de.ShortName, DOS_CUR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = inode->i_ino; + } else if (!memcmp(de.ShortName, DOS_PAR_DIR_NAME, DOS_NAME_LENGTH)) { + inum = parent_ino(filp->f_path.dentry); + } else { + loff_t i_pos = ((loff_t) EXFAT_I(inode)->fid.start_clu << 32) | + ((EXFAT_I(inode)->fid.rwoffset-1) & 0xffffffff); + + struct inode *tmp = exfat_iget(sb, i_pos); + if (tmp) { + inum = tmp->i_ino; + iput(tmp); + } else { + inum = iunique(sb, EXFAT_ROOT_INO); + } + } + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + if (!dir_emit(ctx, de.Name, strlen(de.Name), inum, + (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG)) +#else + if (filldir(dirent, de.Name, strlen(de.Name), cpos-1, inum, + (de.Attr & ATTR_SUBDIR) ? DT_DIR : DT_REG) < 0) +#endif + goto out; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + ctx->pos = cpos; +#else + filp->f_pos = cpos; +#endif + goto get_new; + +end_of_dir: +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + ctx->pos = cpos; +#else + filp->f_pos = cpos; +#endif +out: + __unlock_super(sb); + return err; +} + +static int exfat_ioctl_volume_id(struct inode *dir) +{ + struct super_block *sb = dir->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + + return p_fs->vol_id; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +static int exfat_generic_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +#else +static long exfat_generic_ioctl(struct file *filp, + unsigned int cmd, unsigned long arg) +#endif +{ +#if EXFAT_CONFIG_KERNEL_DEBUG +#if !(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36)) + struct inode *inode = filp->f_dentry->d_inode; +#endif + unsigned int flags; +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + + switch (cmd) { + case EXFAT_IOCTL_GET_VOLUME_ID: + return exfat_ioctl_volume_id(inode); +#if EXFAT_CONFIG_KERNEL_DEBUG + case EXFAT_IOC_GET_DEBUGFLAGS: { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + flags = sbi->debug_flags; + return put_user(flags, (int __user *)arg); + } + case EXFAT_IOC_SET_DEBUGFLAGS: { + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + + if (get_user(flags, (int __user *) arg)) + return -EFAULT; + + __lock_super(sb); + sbi->debug_flags = flags; + __unlock_super(sb); + + return 0; + } +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + default: + return -ENOTTY; /* Inappropriate ioctl for device */ + } +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +static int exfat_file_fsync(struct file *filp, int datasync) +{ + struct inode *inode = filp->f_mapping->host; + struct super_block *sb = inode->i_sb; + int res, err; + + res = generic_file_fsync(filp, datasync); + err = FsSyncVol(sb, 1); + + return res ? res : err; +} +#endif + +const struct file_operations exfat_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,11,0) + .iterate = exfat_readdir, +#else + .readdir = exfat_readdir, +#endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) + .ioctl = exfat_generic_ioctl, + .fsync = exfat_file_fsync, +#else + .unlocked_ioctl = exfat_generic_ioctl, + .fsync = generic_file_fsync, +#endif +}; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) +static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + bool excl) +#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) +static int exfat_create(struct inode *dir, struct dentry *dentry, umode_t mode, + struct nameidata *nd) +#else +static int exfat_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) +#endif +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + PRINTK("exfat_create entered\n"); + + ts = CURRENT_TIME_SEC; + + err = FsCreateFile(dir, (UINT8 *) dentry->d_name.name, FM_REGULAR, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else if (err == FFS_NAMETOOLONG) + err = -ENAMETOOLONG; + else + err = -EIO; + goto out; + } + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unnecessary. */ + + dentry->d_time = dentry->d_parent->d_inode->i_version; + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + PRINTK("exfat_create exited\n"); + return err; +} + +static int exfat_find(struct inode *dir, struct qstr *qname, + FILE_ID_T *fid) +{ + int err; + + if (qname->len == 0) + return -ENOENT; + + err = FsLookupFile(dir, (UINT8 *) qname->name, fid); + if (err) + return -ENOENT; + + return 0; +} + +static int exfat_d_anon_disconn(struct dentry *dentry) +{ + return IS_ROOT(dentry) && (dentry->d_flags & DCACHE_DISCONNECTED); +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) +static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +#else +static struct dentry *exfat_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +#endif +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct dentry *alias; + int err; + FILE_ID_T fid; + loff_t i_pos; + UINT64 ret; + mode_t i_mode; + + __lock_super(sb); + PRINTK("exfat_lookup entered\n"); + err = exfat_find(dir, &dentry->d_name, &fid); + if (err) { + if (err == -ENOENT) { + inode = NULL; + goto out; + } + goto error; + } + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto error; + } + + i_mode = inode->i_mode; + if (S_ISLNK(i_mode)) { + EXFAT_I(inode)->target = MALLOC(i_size_read(inode)+1); + if (!EXFAT_I(inode)->target) { + err = -ENOMEM; + goto error; + } + FsReadFile(dir, &fid, EXFAT_I(inode)->target, i_size_read(inode), &ret); + *(EXFAT_I(inode)->target + i_size_read(inode)) = '\0'; + } + + alias = d_find_alias(inode); + if (alias && !exfat_d_anon_disconn(alias)) { + CHECK_ERR(d_unhashed(alias)); + if (!S_ISDIR(i_mode)) + d_move(alias, dentry); + iput(inode); + __unlock_super(sb); + PRINTK("exfat_lookup exited 1\n"); + return alias; + } else { + dput(alias); + } +out: + __unlock_super(sb); + dentry->d_time = dentry->d_parent->d_inode->i_version; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38) + dentry->d_op = sb->s_root->d_op; + dentry = d_splice_alias(inode, dentry); + if (dentry) { + dentry->d_op = sb->s_root->d_op; + dentry->d_time = dentry->d_parent->d_inode->i_version; + } +#else + dentry = d_splice_alias(inode, dentry); + if (dentry) + dentry->d_time = dentry->d_parent->d_inode->i_version; +#endif + PRINTK("exfat_lookup exited 2\n"); + return dentry; + +error: + __unlock_super(sb); + PRINTK("exfat_lookup exited 3\n"); + return ERR_PTR(err); +} + +static int exfat_unlink(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + struct timespec ts; + int err; + + __lock_super(sb); + + PRINTK("exfat_unlink entered\n"); + + ts = CURRENT_TIME_SEC; + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = FsRemoveFile(dir, &(EXFAT_I(inode)->fid)); + if (err) { + if (err == FFS_PERMISSIONERR) + err = -EPERM; + else + err = -EIO; + goto out; + } + dir->i_version++; + dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = ts; + exfat_detach(inode); + remove_inode_hash(inode); + +out: + __unlock_super(sb); + PRINTK("exfat_unlink exited\n"); + return err; +} + +static int exfat_symlink(struct inode *dir, struct dentry *dentry, const char *target) +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + UINT64 len = (UINT64) strlen(target); + UINT64 ret; + + __lock_super(sb); + + PRINTK("exfat_symlink entered\n"); + + ts = CURRENT_TIME_SEC; + + err = FsCreateFile(dir, (UINT8 *) dentry->d_name.name, FM_SYMLINK, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + + err = FsWriteFile(dir, &fid, (char *) target, len, &ret); + + if (err) { + FsRemoveFile(dir, &fid); + + if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + EXFAT_I(inode)->target = MALLOC(len+1); + if (!EXFAT_I(inode)->target) { + err = -ENOMEM; + goto out; + } + MEMCPY(EXFAT_I(inode)->target, target, len+1); + + dentry->d_time = dentry->d_parent->d_inode->i_version; + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + PRINTK("exfat_symlink exited\n"); + return err; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) +static int exfat_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +#else +static int exfat_mkdir(struct inode *dir, struct dentry *dentry, int mode) +#endif +{ + struct super_block *sb = dir->i_sb; + struct inode *inode; + struct timespec ts; + FILE_ID_T fid; + loff_t i_pos; + int err; + + __lock_super(sb); + + PRINTK("exfat_mkdir entered\n"); + + ts = CURRENT_TIME_SEC; + + err = FsCreateDir(dir, (UINT8 *) dentry->d_name.name, &fid); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_FULL) + err = -ENOSPC; + else if (err == FFS_NAMETOOLONG) + err = -ENAMETOOLONG; + else + err = -EIO; + goto out; + } + dir->i_version++; + dir->i_ctime = dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + inc_nlink(dir); + + i_pos = ((loff_t) fid.dir.dir << 32) | (fid.entry & 0xffffffff); + + inode = exfat_build_inode(sb, &fid, i_pos); + if (IS_ERR(inode)) { + err = PTR_ERR(inode); + goto out; + } + inode->i_version++; + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; + /* timestamp is already written, so mark_inode_dirty() is unneeded. */ + + dentry->d_time = dentry->d_parent->d_inode->i_version; + d_instantiate(dentry, inode); + +out: + __unlock_super(sb); + PRINTK("exfat_mkdir exited\n"); + return err; +} + +static int exfat_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + struct super_block *sb = dir->i_sb; + struct timespec ts; + int err; + + __lock_super(sb); + + PRINTK("exfat_rmdir entered\n"); + + ts = CURRENT_TIME_SEC; + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = FsRemoveDir(dir, &(EXFAT_I(inode)->fid)); + if (err) { + if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -ENOTEMPTY; + else if (err == FFS_NOTFOUND) + err = -ENOENT; + else if (err == FFS_DIRBUSY) + err = -EBUSY; + else + err = -EIO; + goto out; + } + dir->i_version++; + dir->i_mtime = dir->i_atime = ts; + if (IS_DIRSYNC(dir)) + (void) exfat_sync_inode(dir); + else + mark_inode_dirty(dir); + drop_nlink(dir); + + clear_nlink(inode); + inode->i_mtime = inode->i_atime = ts; + exfat_detach(inode); + remove_inode_hash(inode); + +out: + __unlock_super(sb); + PRINTK("exfat_rmdir exited\n"); + return err; +} + +static int exfat_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + struct inode *old_inode, *new_inode; + struct super_block *sb = old_dir->i_sb; + struct timespec ts; + loff_t i_pos; + int err; + + __lock_super(sb); + + PRINTK("exfat_rename entered\n"); + + old_inode = old_dentry->d_inode; + new_inode = new_dentry->d_inode; + + ts = CURRENT_TIME_SEC; + + EXFAT_I(old_inode)->fid.size = i_size_read(old_inode); + + err = FsMoveFile(old_dir, &(EXFAT_I(old_inode)->fid), new_dir, new_dentry); + if (err) { + if (err == FFS_PERMISSIONERR) + err = -EPERM; + else if (err == FFS_INVALIDPATH) + err = -EINVAL; + else if (err == FFS_FILEEXIST) + err = -EEXIST; + else if (err == FFS_NOTFOUND) + err = -ENOENT; + else if (err == FFS_FULL) + err = -ENOSPC; + else + err = -EIO; + goto out; + } + new_dir->i_version++; + new_dir->i_ctime = new_dir->i_mtime = new_dir->i_atime = ts; + if (IS_DIRSYNC(new_dir)) + (void) exfat_sync_inode(new_dir); + else + mark_inode_dirty(new_dir); + + i_pos = ((loff_t) EXFAT_I(old_inode)->fid.dir.dir << 32) | + (EXFAT_I(old_inode)->fid.entry & 0xffffffff); + + exfat_detach(old_inode); + exfat_attach(old_inode, i_pos); + if (IS_DIRSYNC(new_dir)) + (void) exfat_sync_inode(old_inode); + else + mark_inode_dirty(old_inode); + + if ((S_ISDIR(old_inode->i_mode)) && (old_dir != new_dir)) { + drop_nlink(old_dir); + if (!new_inode) inc_nlink(new_dir); + } + + old_dir->i_version++; + old_dir->i_ctime = old_dir->i_mtime = ts; + if (IS_DIRSYNC(old_dir)) + (void) exfat_sync_inode(old_dir); + else + mark_inode_dirty(old_dir); + + if (new_inode) { + exfat_detach(new_inode); + drop_nlink(new_inode); + if (S_ISDIR(new_inode->i_mode)) + drop_nlink(new_inode); + new_inode->i_ctime = ts; + } + +out: + __unlock_super(sb); + PRINTK("exfat_rename exited\n"); + return err; +} + +static int exfat_cont_expand(struct inode *inode, loff_t size) +{ + struct address_space *mapping = inode->i_mapping; + loff_t start = i_size_read(inode), count = size - i_size_read(inode); + int err, err2; + + if ((err = generic_cont_expand_simple(inode, size)) != 0) + return err; + + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; + mark_inode_dirty(inode); + + if (IS_SYNC(inode)) { + err = filemap_fdatawrite_range(mapping, start, start + count - 1); + err2 = sync_mapping_buffers(mapping); + err = (err)?(err):(err2); + err2 = write_inode_now(inode, 1); + err = (err)?(err):(err2); + if (!err) { + err = filemap_fdatawait_range(mapping, start, start + count - 1); + } + } + return err; +} + +static int exfat_allow_set_time(struct exfat_sb_info *sbi, struct inode *inode) +{ + mode_t allow_utime = sbi->options.allow_utime; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + if (!uid_eq(current_fsuid(), inode->i_uid)) +#else + if (current_fsuid() != inode->i_uid) +#endif + { + if (in_group_p(inode->i_gid)) + allow_utime >>= 3; + if (allow_utime & MAY_WRITE) + return 1; + } + + /* use a default check */ + return 0; +} + +static int exfat_sanitize_mode(const struct exfat_sb_info *sbi, + struct inode *inode, umode_t *mode_ptr) +{ + mode_t i_mode, mask, perm; + + i_mode = inode->i_mode; + + if (S_ISREG(i_mode) || S_ISLNK(i_mode)) + mask = sbi->options.fs_fmask; + else + mask = sbi->options.fs_dmask; + + perm = *mode_ptr & ~(S_IFMT | mask); + + /* Of the r and x bits, all (subject to umask) must be present.*/ + if ((perm & (S_IRUGO | S_IXUGO)) != (i_mode & (S_IRUGO|S_IXUGO))) + return -EPERM; + + if (exfat_mode_can_hold_ro(inode)) { + /* Of the w bits, either all (subject to umask) or none must be present. */ + if ((perm & S_IWUGO) && ((perm & S_IWUGO) != (S_IWUGO & ~mask))) + return -EPERM; + } else { + /* If exfat_mode_can_hold_ro(inode) is false, can't change w bits. */ + if ((perm & S_IWUGO) != (S_IWUGO & ~mask)) + return -EPERM; + } + + *mode_ptr &= S_IFMT | perm; + + return 0; +} + +static int exfat_setattr(struct dentry *dentry, struct iattr *attr) +{ + + struct exfat_sb_info *sbi = EXFAT_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + unsigned int ia_valid; + int error; + loff_t old_size; + + PRINTK("exfat_setattr entered\n"); + + if ((attr->ia_valid & ATTR_SIZE) + && (attr->ia_size > i_size_read(inode))) { + error = exfat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + return error; + attr->ia_valid &= ~ATTR_SIZE; + } + + ia_valid = attr->ia_valid; + + if ((ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET)) + && exfat_allow_set_time(sbi, inode)) { + attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET | ATTR_TIMES_SET); + } + + error = inode_change_ok(inode, attr); + attr->ia_valid = ia_valid; + if (error) { + return error; + } + + if (((attr->ia_valid & ATTR_UID) && +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + (!uid_eq(attr->ia_uid, sbi->options.fs_uid))) || + ((attr->ia_valid & ATTR_GID) && + (!gid_eq(attr->ia_gid, sbi->options.fs_gid))) || +#else + (attr->ia_uid != sbi->options.fs_uid)) || + ((attr->ia_valid & ATTR_GID) && + (attr->ia_gid != sbi->options.fs_gid)) || +#endif + ((attr->ia_valid & ATTR_MODE) && + (attr->ia_mode & ~(S_IFREG | S_IFLNK | S_IFDIR | S_IRWXUGO)))) { + return -EPERM; + } + + /* + * We don't return -EPERM here. Yes, strange, but this is too + * old behavior. + */ + if (attr->ia_valid & ATTR_MODE) { + if (exfat_sanitize_mode(sbi, inode, &attr->ia_mode) < 0) + attr->ia_valid &= ~ATTR_MODE; + } + + EXFAT_I(inode)->fid.size = i_size_read(inode); + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) + if (attr->ia_valid) + error = inode_setattr(inode, attr); +#else + if (attr->ia_valid & ATTR_SIZE) { + old_size = i_size_read(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + down_write(&EXFAT_I(inode)->truncate_lock); + truncate_setsize(inode, attr->ia_size); + _exfat_truncate(inode, old_size); + up_write(&EXFAT_I(inode)->truncate_lock); +#else + truncate_setsize(inode, attr->ia_size); + _exfat_truncate(inode, old_size); +#endif + } + setattr_copy(inode, attr); + mark_inode_dirty(inode); +#endif + + PRINTK("exfat_setattr exited\n"); + return error; +} + +static int exfat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + + PRINTK("exfat_getattr entered\n"); + + generic_fillattr(inode, stat); + stat->blksize = EXFAT_SB(inode->i_sb)->fs_info.cluster_size; + + PRINTK("exfat_getattr exited\n"); + return 0; +} + +const struct inode_operations exfat_dir_inode_operations = { + .create = exfat_create, + .lookup = exfat_lookup, + .unlink = exfat_unlink, + .symlink = exfat_symlink, + .mkdir = exfat_mkdir, + .rmdir = exfat_rmdir, + .rename = exfat_rename, + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; + +/*======================================================================*/ +/* File Operations */ +/*======================================================================*/ + +static void *exfat_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + struct exfat_inode_info *ei = EXFAT_I(dentry->d_inode); + nd_set_link(nd, (char *)(ei->target)); + return NULL; +} + +const struct inode_operations exfat_symlink_inode_operations = { + .readlink = generic_readlink, + .follow_link = exfat_follow_link, +}; + +static int exfat_file_release(struct inode *inode, struct file *filp) +{ + struct super_block *sb = inode->i_sb; + + EXFAT_I(inode)->fid.size = i_size_read(inode); + FsSyncVol(sb, 0); + return 0; +} + +const struct file_operations exfat_file_operations = { + .llseek = generic_file_llseek, + .read = do_sync_read, + .write = do_sync_write, + .aio_read = generic_file_aio_read, + .aio_write = generic_file_aio_write, + .mmap = generic_file_mmap, + .release = exfat_file_release, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) + .ioctl = exfat_generic_ioctl, + .fsync = exfat_file_fsync, +#else + .unlocked_ioctl = exfat_generic_ioctl, + .fsync = generic_file_fsync, +#endif + .splice_read = generic_file_splice_read, +}; + +static void _exfat_truncate(struct inode *inode, loff_t old_size) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + int err; + + __lock_super(sb); + + /* + * This protects against truncating a file bigger than it was then + * trying to write into the hole. + */ + if (EXFAT_I(inode)->mmu_private > i_size_read(inode)) + EXFAT_I(inode)->mmu_private = i_size_read(inode); + + if (EXFAT_I(inode)->fid.start_clu == 0) goto out; + + err = FsTruncateFile(inode, old_size, i_size_read(inode)); + if (err) goto out; + + inode->i_ctime = inode->i_mtime = CURRENT_TIME_SEC; + if (IS_DIRSYNC(inode)) + (void) exfat_sync_inode(inode); + else + mark_inode_dirty(inode); + + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; +out: + __unlock_super(sb); +} + +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) +static void exfat_truncate(struct inode *inode) +{ + _exfat_truncate(inode, i_size_read(inode)); +} +#endif + +const struct inode_operations exfat_file_inode_operations = { +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,36) + .truncate = exfat_truncate, +#endif + .setattr = exfat_setattr, + .getattr = exfat_getattr, +}; + +/*======================================================================*/ +/* Address Space Operations */ +/*======================================================================*/ + +static int exfat_bmap(struct inode *inode, sector_t sector, sector_t *phys, + unsigned long *mapped_blocks, int *create) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + BD_INFO_T *p_bd = &(sbi->bd_info); + const unsigned long blocksize = sb->s_blocksize; + const unsigned char blocksize_bits = sb->s_blocksize_bits; + sector_t last_block; + int err, clu_offset, sec_offset; + unsigned int cluster; + + *phys = 0; + *mapped_blocks = 0; + + if ((p_fs->vol_type == FAT12) || (p_fs->vol_type == FAT16)) { + if (inode->i_ino == EXFAT_ROOT_INO) { + if (sector < (p_fs->dentries_in_root >> (p_bd->sector_size_bits-DENTRY_SIZE_BITS))) { + *phys = sector + p_fs->root_start_sector; + *mapped_blocks = 1; + } + return 0; + } + } + + last_block = (i_size_read(inode) + (blocksize - 1)) >> blocksize_bits; + if (sector >= last_block) { + if (*create == 0) return 0; + } else { + *create = 0; + } + + clu_offset = sector >> p_fs->sectors_per_clu_bits; /* cluster offset */ + sec_offset = sector & (p_fs->sectors_per_clu - 1); /* sector offset in cluster */ + + EXFAT_I(inode)->fid.size = i_size_read(inode); + + err = FsMapCluster(inode, clu_offset, &cluster); + + if (err) { + if (err == FFS_FULL) + return -ENOSPC; + else + return -EIO; + } else if (cluster != CLUSTER_32(~0)) { + *phys = START_SECTOR(cluster) + sec_offset; + *mapped_blocks = p_fs->sectors_per_clu - sec_offset; + } + + return 0; +} + +static int exfat_get_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + struct super_block *sb = inode->i_sb; + unsigned long max_blocks = bh_result->b_size >> inode->i_blkbits; + int err; + unsigned long mapped_blocks; + sector_t phys; + + __lock_super(sb); + + err = exfat_bmap(inode, iblock, &phys, &mapped_blocks, &create); + if (err) { + __unlock_super(sb); + return err; + } + + if (phys) { + max_blocks = min(mapped_blocks, max_blocks); + if (create) { + EXFAT_I(inode)->mmu_private += max_blocks << sb->s_blocksize_bits; + set_buffer_new(bh_result); + } + map_bh(bh_result, sb, phys); + } + + bh_result->b_size = max_blocks << sb->s_blocksize_bits; + __unlock_super(sb); + + return 0; +} + +static int exfat_readpage(struct file *file, struct page *page) +{ + int ret; + ret = mpage_readpage(page, exfat_get_block); + return ret; +} + +static int exfat_readpages(struct file *file, struct address_space *mapping, + struct list_head *pages, unsigned nr_pages) +{ + int ret; + ret = mpage_readpages(mapping, pages, nr_pages, exfat_get_block); + return ret; +} + +static int exfat_writepage(struct page *page, struct writeback_control *wbc) +{ + int ret; + ret = block_write_full_page(page, exfat_get_block, wbc); + return ret; +} + +static int exfat_writepages(struct address_space *mapping, + struct writeback_control *wbc) +{ + int ret; + ret = mpage_writepages(mapping, wbc, exfat_get_block); + return ret; +} + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) +static void exfat_write_failed(struct address_space *mapping, loff_t to) +{ + struct inode *inode = mapping->host; + if (to > i_size_read(inode)) { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,12,0) + truncate_pagecache(inode, i_size_read(inode)); +#else + truncate_pagecache(inode, to, i_size_read(inode)); +#endif + EXFAT_I(inode)->fid.size = i_size_read(inode); + _exfat_truncate(inode, i_size_read(inode)); + } +} +#endif + + +static int exfat_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +{ + int ret; + *pagep = NULL; + ret = cont_write_begin(file, mapping, pos, len, flags, pagep, fsdata, + exfat_get_block, + &EXFAT_I(mapping->host)->mmu_private); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + if (ret < 0) + exfat_write_failed(mapping, pos+len); +#endif + return ret; +} + +static int exfat_write_end(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *pagep, void *fsdata) +{ + struct inode *inode = mapping->host; + FILE_ID_T *fid = &(EXFAT_I(inode)->fid); + int err; + + err = generic_write_end(file, mapping, pos, len, copied, pagep, fsdata); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + if (err < len) + exfat_write_failed(mapping, pos+len); +#endif + + if (!(err < 0) && !(fid->attr & ATTR_ARCHIVE)) { + inode->i_mtime = inode->i_ctime = CURRENT_TIME_SEC; + fid->attr |= ATTR_ARCHIVE; + mark_inode_dirty(inode); + } + return err; +} + +static ssize_t exfat_direct_IO(int rw, struct kiocb *iocb, + const struct iovec *iov, + loff_t offset, unsigned long nr_segs) +{ + struct inode *inode = iocb->ki_filp->f_mapping->host; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + struct address_space *mapping = iocb->ki_filp->f_mapping; +#endif + ssize_t ret; + + if (rw == WRITE) { + if (EXFAT_I(inode)->mmu_private < (offset + iov_length(iov, nr_segs))) + return 0; + } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + ret = blockdev_direct_IO(rw, iocb, inode, iov, + offset, nr_segs, exfat_get_block); +#else + ret = blockdev_direct_IO(rw, iocb, inode, inode->i_sb->s_bdev, iov, + offset, nr_segs, exfat_get_block, NULL); +#endif + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,34) + if ((ret < 0) && (rw & WRITE)) + exfat_write_failed(mapping, offset+iov_length(iov, nr_segs)); +#endif + return ret; +} + +static sector_t _exfat_bmap(struct address_space *mapping, sector_t block) +{ + sector_t blocknr; + + /* exfat_get_cluster() assumes the requested blocknr isn't truncated. */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + down_read(&EXFAT_I(mapping->host)->truncate_lock); + blocknr = generic_block_bmap(mapping, block, exfat_get_block); + up_read(&EXFAT_I(mapping->host)->truncate_lock); +#else + down_read(&EXFAT_I(mapping->host)->i_alloc_sem); + blocknr = generic_block_bmap(mapping, block, exfat_get_block); + up_read(&EXFAT_I(mapping->host)->i_alloc_sem); +#endif + + return blocknr; +} + +const struct address_space_operations exfat_aops = { + .readpage = exfat_readpage, + .readpages = exfat_readpages, + .writepage = exfat_writepage, + .writepages = exfat_writepages, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) + .sync_page = block_sync_page, +#endif + .write_begin = exfat_write_begin, + .write_end = exfat_write_end, + .direct_IO = exfat_direct_IO, + .bmap = _exfat_bmap +}; + +/*======================================================================*/ +/* Super Operations */ +/*======================================================================*/ + +static inline unsigned long exfat_hash(loff_t i_pos) +{ + return hash_32(i_pos, EXFAT_HASH_BITS); +} + +static struct inode *exfat_iget(struct super_block *sb, loff_t i_pos) { + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct exfat_inode_info *info; + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + struct inode *inode = NULL; +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,9,0) + struct hlist_node *node; + + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, node, head, i_hash_fat) { +#else + spin_lock(&sbi->inode_hash_lock); + hlist_for_each_entry(info, head, i_hash_fat) { +#endif + CHECK_ERR(info->vfs_inode.i_sb != sb); + + if (i_pos != info->i_pos) + continue; + inode = igrab(&info->vfs_inode); + if (inode) + break; + } + spin_unlock(&sbi->inode_hash_lock); + return inode; +} + +static void exfat_attach(struct inode *inode, loff_t i_pos) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + struct hlist_head *head = sbi->inode_hashtable + exfat_hash(i_pos); + + spin_lock(&sbi->inode_hash_lock); + EXFAT_I(inode)->i_pos = i_pos; + hlist_add_head(&EXFAT_I(inode)->i_hash_fat, head); + spin_unlock(&sbi->inode_hash_lock); +} + +static void exfat_detach(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + spin_lock(&sbi->inode_hash_lock); + hlist_del_init(&EXFAT_I(inode)->i_hash_fat); + EXFAT_I(inode)->i_pos = 0; + spin_unlock(&sbi->inode_hash_lock); +} + +/* doesn't deal with root inode */ +static int exfat_fill_inode(struct inode *inode, FILE_ID_T *fid) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + FS_INFO_T *p_fs = &(sbi->fs_info); + DIR_ENTRY_T info; + + memcpy(&(EXFAT_I(inode)->fid), fid, sizeof(FILE_ID_T)); + + FsReadStat(inode, &info); + + EXFAT_I(inode)->i_pos = 0; + EXFAT_I(inode)->target = NULL; + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode->i_version++; + inode->i_generation = get_seconds(); + + if (info.Attr & ATTR_SUBDIR) { /* directory */ + inode->i_generation &= ~1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + set_nlink(inode,info.NumSubdirs); +#else + inode->i_nlink = info.NumSubdirs; +#endif + } else if (info.Attr & ATTR_SYMLINK) { /* symbolic link */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); + inode->i_op = &exfat_symlink_inode_operations; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + } else { /* regular file */ + inode->i_generation |= 1; + inode->i_mode = exfat_make_mode(sbi, info.Attr, S_IRWXUGO); + inode->i_op = &exfat_file_inode_operations; + inode->i_fop = &exfat_file_operations; + inode->i_mapping->a_ops = &exfat_aops; + inode->i_mapping->nrpages = 0; + + i_size_write(inode, info.Size); + EXFAT_I(inode)->mmu_private = i_size_read(inode); + } + exfat_save_attr(inode, info.Attr); + + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; + + exfat_time_fat2unix(sbi, &inode->i_mtime, &info.ModifyTimestamp); + exfat_time_fat2unix(sbi, &inode->i_ctime, &info.CreateTimestamp); + exfat_time_fat2unix(sbi, &inode->i_atime, &info.AccessTimestamp); + + return 0; +} + +static struct inode *exfat_build_inode(struct super_block *sb, + FILE_ID_T *fid, loff_t i_pos) { + struct inode *inode; + int err; + + inode = exfat_iget(sb, i_pos); + if (inode) + goto out; + inode = new_inode(sb); + if (!inode) { + inode = ERR_PTR(-ENOMEM); + goto out; + } + inode->i_ino = iunique(sb, EXFAT_ROOT_INO); + inode->i_version = 1; + err = exfat_fill_inode(inode, fid); + if (err) { + iput(inode); + inode = ERR_PTR(err); + goto out; + } + exfat_attach(inode, i_pos); + insert_inode_hash(inode); +out: + return inode; +} + +static int exfat_sync_inode(struct inode *inode) +{ + return exfat_write_inode(inode, NULL); +} + +static struct inode *exfat_alloc_inode(struct super_block *sb) { + struct exfat_inode_info *ei; + + ei = kmem_cache_alloc(exfat_inode_cachep, GFP_NOFS); + if (!ei) + return NULL; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + init_rwsem(&ei->truncate_lock); +#endif + + return &ei->vfs_inode; +} + +static void exfat_destroy_inode(struct inode *inode) +{ + FREE(EXFAT_I(inode)->target); + EXFAT_I(inode)->target = NULL; + + kmem_cache_free(exfat_inode_cachep, EXFAT_I(inode)); +} + +static int exfat_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + DIR_ENTRY_T info; + + if (inode->i_ino == EXFAT_ROOT_INO) + return 0; + + info.Attr = exfat_make_attr(inode); + info.Size = i_size_read(inode); + + exfat_time_unix2fat(sbi, &inode->i_mtime, &info.ModifyTimestamp); + exfat_time_unix2fat(sbi, &inode->i_ctime, &info.CreateTimestamp); + exfat_time_unix2fat(sbi, &inode->i_atime, &info.AccessTimestamp); + + FsWriteStat(inode, &info); + + return 0; +} + +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) +static void exfat_delete_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + clear_inode(inode); +} + +static void exfat_clear_inode(struct inode *inode) +{ + exfat_detach(inode); + remove_inode_hash(inode); +} +#else +static void exfat_evict_inode(struct inode *inode) +{ + truncate_inode_pages(&inode->i_data, 0); + + if (!inode->i_nlink) + i_size_write(inode, 0); + invalidate_inode_buffers(inode); +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,00) + end_writeback(inode); +#else + clear_inode(inode); +#endif + exfat_detach(inode); + + remove_inode_hash(inode); +} +#endif + +static void exfat_free_super(struct exfat_sb_info *sbi) +{ + if (sbi->nls_disk) + unload_nls(sbi->nls_disk); + if (sbi->nls_io) + unload_nls(sbi->nls_io); + if (sbi->options.iocharset != exfat_default_iocharset) + kfree(sbi->options.iocharset); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) + /* mutex_init is in exfat_fill_super function. only for 3.7+ */ + mutex_destroy(&sbi->s_lock); +#endif + kfree(sbi); +} + +static void exfat_put_super(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + if (__is_sb_dirty(sb)) + exfat_write_super(sb); + + FsUmountVol(sb); + + sb->s_fs_info = NULL; + exfat_free_super(sbi); +} + +static void exfat_write_super(struct super_block *sb) +{ + __lock_super(sb); + + __set_sb_clean(sb); + + if (!(sb->s_flags & MS_RDONLY)) + FsSyncVol(sb, 1); + + __unlock_super(sb); +} + +static int exfat_sync_fs(struct super_block *sb, int wait) +{ + int err = 0; + + if (__is_sb_dirty(sb)) { + __lock_super(sb); + __set_sb_clean(sb); + err = FsSyncVol(sb, 1); + __unlock_super(sb); + } + + return err; +} + +static int exfat_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + FS_INFO_T *p_fs = &(EXFAT_SB(sb)->fs_info); + VOL_INFO_T info; + + if (p_fs->used_clusters == (UINT32) ~0) { + if (FFS_MEDIAERR == FsGetVolInfo(sb, &info)) + return -EIO; + + } else { + info.FatType = p_fs->vol_type; + info.ClusterSize = p_fs->cluster_size; + info.NumClusters = p_fs->num_clusters - 2; + info.UsedClusters = p_fs->used_clusters; + info.FreeClusters = info.NumClusters - info.UsedClusters; + + if (p_fs->dev_ejected) + return -EIO; + } + + buf->f_type = sb->s_magic; + buf->f_bsize = info.ClusterSize; + buf->f_blocks = info.NumClusters; + buf->f_bfree = info.FreeClusters; + buf->f_bavail = info.FreeClusters; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + buf->f_namelen = 260; + + return 0; +} + +static int exfat_remount(struct super_block *sb, int *flags, char *data) +{ + *flags |= MS_NODIRATIME; + return 0; +} + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) +static int exfat_show_options(struct seq_file *m, struct dentry *root) +{ + struct exfat_sb_info *sbi = EXFAT_SB(root->d_sb); +#else +static int exfat_show_options(struct seq_file *m, struct vfsmount *mnt) +{ + struct exfat_sb_info *sbi = EXFAT_SB(mnt->mnt_sb); +#endif + struct exfat_mount_options *opts = &sbi->options; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + if (__kuid_val(opts->fs_uid)) + seq_printf(m, ",uid=%u", __kuid_val(opts->fs_uid)); + if (__kgid_val(opts->fs_gid)) + seq_printf(m, ",gid=%u", __kgid_val(opts->fs_gid)); +#else + if (opts->fs_uid != 0) + seq_printf(m, ",uid=%u", opts->fs_uid); + if (opts->fs_gid != 0) + seq_printf(m, ",gid=%u", opts->fs_gid); +#endif + seq_printf(m, ",fmask=%04o", opts->fs_fmask); + seq_printf(m, ",dmask=%04o", opts->fs_dmask); + if (opts->allow_utime) + seq_printf(m, ",allow_utime=%04o", opts->allow_utime); + if (sbi->nls_disk) + seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); + if (sbi->nls_io) + seq_printf(m, ",iocharset=%s", sbi->nls_io->charset); + seq_printf(m, ",namecase=%u", opts->casesensitive); + if (opts->errors == EXFAT_ERRORS_CONT) + seq_puts(m, ",errors=continue"); + else if (opts->errors == EXFAT_ERRORS_PANIC) + seq_puts(m, ",errors=panic"); + else + seq_puts(m, ",errors=remount-ro"); +#if EXFAT_CONFIG_DISCARD + if (opts->discard) + seq_printf(m, ",discard"); +#endif + return 0; +} + +const struct super_operations exfat_sops = { + .alloc_inode = exfat_alloc_inode, + .destroy_inode = exfat_destroy_inode, + .write_inode = exfat_write_inode, +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) + .delete_inode = exfat_delete_inode, + .clear_inode = exfat_clear_inode, +#else + .evict_inode = exfat_evict_inode, +#endif + .put_super = exfat_put_super, +#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0) + .write_super = exfat_write_super, +#endif + .sync_fs = exfat_sync_fs, + .statfs = exfat_statfs, + .remount_fs = exfat_remount, + .show_options = exfat_show_options, +}; + +/*======================================================================*/ +/* Super Block Read Operations */ +/*======================================================================*/ + +enum { + Opt_uid, + Opt_gid, + Opt_umask, + Opt_dmask, + Opt_fmask, + Opt_allow_utime, + Opt_codepage, + Opt_charset, + Opt_namecase, + Opt_debug, + Opt_err_cont, + Opt_err_panic, + Opt_err_ro, + Opt_err, +#if EXFAT_CONFIG_DISCARD + Opt_discard, +#endif /* EXFAT_CONFIG_DISCARD */ +}; + +static const match_table_t exfat_tokens = { + {Opt_uid, "uid=%u"}, + {Opt_gid, "gid=%u"}, + {Opt_umask, "umask=%o"}, + {Opt_dmask, "dmask=%o"}, + {Opt_fmask, "fmask=%o"}, + {Opt_allow_utime, "allow_utime=%o"}, + {Opt_codepage, "codepage=%u"}, + {Opt_charset, "iocharset=%s"}, + {Opt_namecase, "namecase=%u"}, + {Opt_debug, "debug"}, + {Opt_err_cont, "errors=continue"}, + {Opt_err_panic, "errors=panic"}, + {Opt_err_ro, "errors=remount-ro"}, +#if EXFAT_CONFIG_DISCARD + {Opt_discard, "discard"}, +#endif /* EXFAT_CONFIG_DISCARD */ + {Opt_err, NULL} +}; + +static int parse_options(char *options, int silent, int *debug, + struct exfat_mount_options *opts) +{ + char *p; + substring_t args[MAX_OPT_ARGS]; + int option; + char *iocharset; + + opts->fs_uid = current_uid(); + opts->fs_gid = current_gid(); + opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->allow_utime = (unsigned short) -1; + opts->codepage = exfat_default_codepage; + opts->iocharset = exfat_default_iocharset; + opts->casesensitive = 0; + opts->errors = EXFAT_ERRORS_RO; +#if EXFAT_CONFIG_DISCARD + opts->discard = 0; +#endif + *debug = 0; + + if (!options) + goto out; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + if (!*p) + continue; + + token = match_token(p, exfat_tokens, args); + switch (token) { + case Opt_uid: + if (match_int(&args[0], &option)) + return 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + opts->fs_uid = KUIDT_INIT(option); +#else + opts->fs_uid = option; +#endif + break; + case Opt_gid: + if (match_int(&args[0], &option)) + return 0; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + opts->fs_gid = KGIDT_INIT(option); +#else + opts->fs_gid = option; +#endif + break; + case Opt_umask: + case Opt_dmask: + case Opt_fmask: + if (match_octal(&args[0], &option)) + return 0; + if (token != Opt_dmask) + opts->fs_fmask = option; + if (token != Opt_fmask) + opts->fs_dmask = option; + break; + case Opt_allow_utime: + if (match_octal(&args[0], &option)) + return 0; + opts->allow_utime = option & (S_IWGRP | S_IWOTH); + break; + case Opt_codepage: + if (match_int(&args[0], &option)) + return 0; + opts->codepage = option; + break; + case Opt_charset: + if (opts->iocharset != exfat_default_iocharset) + kfree(opts->iocharset); + iocharset = match_strdup(&args[0]); + if (!iocharset) + return -ENOMEM; + opts->iocharset = iocharset; + break; + case Opt_namecase: + if (match_int(&args[0], &option)) + return 0; + opts->casesensitive = option; + break; + case Opt_err_cont: + opts->errors = EXFAT_ERRORS_CONT; + break; + case Opt_err_panic: + opts->errors = EXFAT_ERRORS_PANIC; + break; + case Opt_err_ro: + opts->errors = EXFAT_ERRORS_RO; + break; + case Opt_debug: + *debug = 1; + break; +#if EXFAT_CONFIG_DISCARD + case Opt_discard: + opts->discard = 1; + break; +#endif /* EXFAT_CONFIG_DISCARD */ + default: + if (!silent) { + printk(KERN_ERR "[EXFAT] Unrecognized mount option %s or missing value\n", p); + } + return -EINVAL; + } + } + +out: + if (opts->allow_utime == (unsigned short) -1) + opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); + + return 0; +} + +static void exfat_hash_init(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + int i; + + spin_lock_init(&sbi->inode_hash_lock); + for (i = 0; i < EXFAT_HASH_SIZE; i++) + INIT_HLIST_HEAD(&sbi->inode_hashtable[i]); +} + +static int exfat_read_root(struct inode *inode) +{ + struct super_block *sb = inode->i_sb; + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct timespec ts; + FS_INFO_T *p_fs = &(sbi->fs_info); + DIR_ENTRY_T info; + + ts = CURRENT_TIME_SEC; + + EXFAT_I(inode)->fid.dir.dir = p_fs->root_dir; + EXFAT_I(inode)->fid.dir.flags = 0x01; + EXFAT_I(inode)->fid.entry = -1; + EXFAT_I(inode)->fid.start_clu = p_fs->root_dir; + EXFAT_I(inode)->fid.flags = 0x01; + EXFAT_I(inode)->fid.type = TYPE_DIR; + EXFAT_I(inode)->fid.rwoffset = 0; + EXFAT_I(inode)->fid.hint_last_off = -1; + + EXFAT_I(inode)->target = NULL; + + FsReadStat(inode, &info); + + inode->i_uid = sbi->options.fs_uid; + inode->i_gid = sbi->options.fs_gid; + inode->i_version++; + inode->i_generation = 0; + inode->i_mode = exfat_make_mode(sbi, ATTR_SUBDIR, S_IRWXUGO); + inode->i_op = &exfat_dir_inode_operations; + inode->i_fop = &exfat_dir_operations; + + i_size_write(inode, info.Size); + inode->i_blocks = ((i_size_read(inode) + (p_fs->cluster_size - 1)) + & ~((loff_t)p_fs->cluster_size - 1)) >> 9; + EXFAT_I(inode)->i_pos = ((loff_t) p_fs->root_dir << 32) | 0xffffffff; + EXFAT_I(inode)->mmu_private = i_size_read(inode); + + exfat_save_attr(inode, ATTR_SUBDIR); + inode->i_mtime = inode->i_atime = inode->i_ctime = ts; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + set_nlink(inode,info.NumSubdirs + 2); +#else + inode->i_nlink = info.NumSubdirs + 2; +#endif + + return 0; +} + +static int exfat_fill_super(struct super_block *sb, void *data, int silent) +{ + struct inode *root_inode = NULL; + struct exfat_sb_info *sbi; + int debug, ret; + long error; + char buf[50]; + + /* + * GFP_KERNEL is ok here, because while we do hold the + * supeblock lock, memory pressure can't call back into + * the filesystem, since we're only just about to mount + * it and have no inodes etc active! + */ + sbi = kzalloc(sizeof(struct exfat_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0) + mutex_init(&sbi->s_lock); +#endif + sb->s_fs_info = sbi; + + sb->s_flags |= MS_NODIRATIME; + sb->s_magic = EXFAT_SUPER_MAGIC; + sb->s_op = &exfat_sops; + + error = parse_options(data, silent, &debug, &sbi->options); + if (error) + goto out_fail; + + error = -EIO; + sb_min_blocksize(sb, 512); + sb->s_maxbytes = 0x7fffffffffffffffLL; // maximum file size + + ret = FsMountVol(sb); + if (ret) { + if (!silent) + printk(KERN_ERR "[EXFAT] FsMountVol failed\n"); + + goto out_fail; + } + + /* set up enough so that it can read an inode */ + exfat_hash_init(sb); + + /* + * The low byte of FAT's first entry must have same value with + * media-field. But in real world, too many devices is + * writing wrong value. So, removed that validity check. + * + * if (FAT_FIRST_ENT(sb, media) != first) + */ + + if (sbi->fs_info.vol_type != EXFAT) { + error = -EINVAL; + sprintf(buf, "cp%d", sbi->options.codepage); + sbi->nls_disk = load_nls(buf); + if (!sbi->nls_disk) { + printk(KERN_ERR "[EXFAT] Codepage %s not found\n", buf); + goto out_fail2; + } + } + + sbi->nls_io = load_nls(sbi->options.iocharset); + if (!sbi->nls_io) { + printk(KERN_ERR "[EXFAT] IO charset %s not found\n", + sbi->options.iocharset); + goto out_fail2; + } + + error = -ENOMEM; + root_inode = new_inode(sb); + if (!root_inode) + goto out_fail2; + root_inode->i_ino = EXFAT_ROOT_INO; + root_inode->i_version = 1; + error = exfat_read_root(root_inode); + if (error < 0) + goto out_fail2; + error = -ENOMEM; + exfat_attach(root_inode, EXFAT_I(root_inode)->i_pos); + insert_inode_hash(root_inode); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + sb->s_root = d_make_root(root_inode); +#else + sb->s_root = d_alloc_root(root_inode); +#endif + if (!sb->s_root) { + printk(KERN_ERR "[EXFAT] Getting the root inode failed\n"); + goto out_fail2; + } + + return 0; + +out_fail2: + FsUmountVol(sb); +out_fail: + if (root_inode) + iput(root_inode); + sb->s_fs_info = NULL; + exfat_free_super(sbi); + return error; +} +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) +static int exfat_get_sb(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) +{ + return get_sb_bdev(fs_type, flags, dev_name, data, exfat_fill_super, mnt); +} +#else +static struct dentry *exfat_fs_mount(struct file_system_type *fs_type, + int flags, const char *dev_name, + void *data) { + return mount_bdev(fs_type, flags, dev_name, data, exfat_fill_super); +} +#endif + +static void init_once(void *foo) +{ + struct exfat_inode_info *ei = (struct exfat_inode_info *)foo; + + INIT_HLIST_NODE(&ei->i_hash_fat); + inode_init_once(&ei->vfs_inode); +} + +static int __init exfat_init_inodecache(void) +{ + exfat_inode_cachep = kmem_cache_create("exfat_inode_cache", + sizeof(struct exfat_inode_info), + 0, (SLAB_RECLAIM_ACCOUNT| + SLAB_MEM_SPREAD), + init_once); + if (exfat_inode_cachep == NULL) + return -ENOMEM; + return 0; +} + +static void __exit exfat_destroy_inodecache(void) +{ + kmem_cache_destroy(exfat_inode_cachep); +} + +#if EXFAT_CONFIG_KERNEL_DEBUG +static void exfat_debug_kill_sb(struct super_block *sb) +{ + struct exfat_sb_info *sbi = EXFAT_SB(sb); + struct block_device *bdev = sb->s_bdev; + + long flags; + + if (sbi) { + flags = sbi->debug_flags; + + if (flags & EXFAT_DEBUGFLAGS_INVALID_UMOUNT) { + /* invalidate_bdev drops all device cache include dirty. + we use this to simulate device removal */ + FsReleaseCache(sb); + invalidate_bdev(bdev); + } + } + + kill_block_super(sb); +} +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ + +static struct file_system_type exfat_fs_type = { + .owner = THIS_MODULE, + .name = "exfat", +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37) + .get_sb = exfat_get_sb, +#else + .mount = exfat_fs_mount, +#endif +#if EXFAT_CONFIG_KERNEL_DEBUG + .kill_sb = exfat_debug_kill_sb, +#else + .kill_sb = kill_block_super, +#endif /* EXFAT_CONFIG_KERNLE_DEBUG */ + .fs_flags = FS_REQUIRES_DEV, +}; + +static int __init init_exfat(void) +{ + int err; + + err = FsInit(); + if (err) { + if (err == FFS_MEMORYERR) + return -ENOMEM; + else + return -EIO; + } + + printk(KERN_INFO "exFAT: Version %s\n", EXFAT_VERSION); + + err = exfat_init_inodecache(); + if (err) goto out; + + err = register_filesystem(&exfat_fs_type); + if (err) goto out; + + return 0; +out: + FsShutdown(); + return err; +} + +static void __exit exit_exfat(void) +{ + exfat_destroy_inodecache(); + unregister_filesystem(&exfat_fs_type); + FsShutdown(); +} + +module_init(init_exfat); +module_exit(exit_exfat); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("exFAT Filesystem Driver"); +#ifdef MODULE_ALIAS_FS +MODULE_ALIAS_FS("exfat"); +#endif diff --git a/fs/exfat/exfat_super.h b/fs/exfat/exfat_super.h new file mode 100644 index 00000000000..c9201dd7925 --- /dev/null +++ b/fs/exfat/exfat_super.h @@ -0,0 +1,172 @@ +/* Some of the source code in this file came from "linux/fs/fat/fat.h". */ + +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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 _EXFAT_LINUX_H +#define _EXFAT_LINUX_H + +#include +#include +#include +#include +#include +#include + +#include "exfat_config.h" +#include "exfat_global.h" +#include "exfat_data.h" +#include "exfat_oal.h" + +#include "exfat_blkdev.h" +#include "exfat_cache.h" +#include "exfat_part.h" +#include "exfat_nls.h" +#include "exfat_api.h" +#include "exfat.h" + +#define EXFAT_ERRORS_CONT 1 /* ignore error and continue */ +#define EXFAT_ERRORS_PANIC 2 /* panic on error */ +#define EXFAT_ERRORS_RO 3 /* remount r/o on error */ + +/* ioctl command */ +#define EXFAT_IOCTL_GET_VOLUME_ID _IOR('r', 0x12, __u32) + +struct exfat_mount_options { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) + kuid_t fs_uid; + kgid_t fs_gid; +#else + uid_t fs_uid; + gid_t fs_gid; +#endif + unsigned short fs_fmask; + unsigned short fs_dmask; + unsigned short allow_utime; /* permission for setting the [am]time */ + unsigned short codepage; /* codepage for shortname conversions */ + char *iocharset; /* charset for filename input/display */ + unsigned char casesensitive; + unsigned char errors; /* on error: continue, panic, remount-ro */ +#if EXFAT_CONFIG_DISCARD + unsigned char discard; /* flag on if -o dicard specified and device support discard() */ +#endif /* EXFAT_CONFIG_DISCARD */ +}; + +#define EXFAT_HASH_BITS 8 +#define EXFAT_HASH_SIZE (1UL << EXFAT_HASH_BITS) + +/* + * EXFAT file system in-core superblock data + */ +struct exfat_sb_info { + FS_INFO_T fs_info; + BD_INFO_T bd_info; + + struct exfat_mount_options options; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,00) + int s_dirt; + struct mutex s_lock; +#endif + struct nls_table *nls_disk; /* Codepage used on disk */ + struct nls_table *nls_io; /* Charset used for input and display */ + + struct inode *fat_inode; + + spinlock_t inode_hash_lock; + struct hlist_head inode_hashtable[EXFAT_HASH_SIZE]; +#if EXFAT_CONFIG_KERNEL_DEBUG + long debug_flags; +#endif /* EXFAT_CONFIG_KERNEL_DEBUG */ +}; + +/* + * EXFAT file system inode data in memory + */ +struct exfat_inode_info { + FILE_ID_T fid; + char *target; + /* NOTE: mmu_private is 64bits, so must hold ->i_mutex to access */ + loff_t mmu_private; /* physically allocated size */ + loff_t i_pos; /* on-disk position of directory entry or 0 */ + struct hlist_node i_hash_fat; /* hash by i_location */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,4,00) + struct rw_semaphore truncate_lock; +#endif + struct inode vfs_inode; + struct rw_semaphore i_alloc_sem; /* protect bmap against truncate */ +}; + +#define EXFAT_SB(sb) ((struct exfat_sb_info *)((sb)->s_fs_info)) + +static inline struct exfat_inode_info *EXFAT_I(struct inode *inode) { + return container_of(inode, struct exfat_inode_info, vfs_inode); +} + +/* + * If ->i_mode can't hold S_IWUGO (i.e. ATTR_RO), we use ->i_attrs to + * save ATTR_RO instead of ->i_mode. + * + * If it's directory and !sbi->options.rodir, ATTR_RO isn't read-only + * bit, it's just used as flag for app. + */ +static inline int exfat_mode_can_hold_ro(struct inode *inode) +{ + struct exfat_sb_info *sbi = EXFAT_SB(inode->i_sb); + + if (S_ISDIR(inode->i_mode)) + return 0; + + if ((~sbi->options.fs_fmask) & S_IWUGO) + return 1; + return 0; +} + +/* Convert attribute bits and a mask to the UNIX mode. */ +static inline mode_t exfat_make_mode(struct exfat_sb_info *sbi, + u32 attr, mode_t mode) +{ + if ((attr & ATTR_READONLY) && !(attr & ATTR_SUBDIR)) + mode &= ~S_IWUGO; + + if (attr & ATTR_SUBDIR) + return (mode & ~sbi->options.fs_dmask) | S_IFDIR; + else if (attr & ATTR_SYMLINK) + return (mode & ~sbi->options.fs_dmask) | S_IFLNK; + else + return (mode & ~sbi->options.fs_fmask) | S_IFREG; +} + +/* Return the FAT attribute byte for this inode */ +static inline u32 exfat_make_attr(struct inode *inode) +{ + if (exfat_mode_can_hold_ro(inode) && !(inode->i_mode & S_IWUGO)) + return ((EXFAT_I(inode)->fid.attr) | ATTR_READONLY); + else + return (EXFAT_I(inode)->fid.attr); +} + +static inline void exfat_save_attr(struct inode *inode, u32 attr) +{ + if (exfat_mode_can_hold_ro(inode)) + EXFAT_I(inode)->fid.attr = attr & ATTR_RWMASK; + else + EXFAT_I(inode)->fid.attr = attr & (ATTR_RWMASK | ATTR_READONLY); +} + +#endif /* _EXFAT_LINUX_H */ diff --git a/fs/exfat/exfat_upcase.c b/fs/exfat/exfat_upcase.c new file mode 100644 index 00000000000..10e48d28b29 --- /dev/null +++ b/fs/exfat/exfat_upcase.c @@ -0,0 +1,408 @@ +/* + * Copyright (C) 2012-2013 Samsung Electronics Co., Ltd. + * + * 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. + * + * 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. + */ + +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_upcase.c */ +/* PURPOSE : exFAT Up-case Table */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY (Ver 0.9) */ +/* */ +/* - 2010.11.15 [Joosun Hahn] : first writing */ +/* */ +/************************************************************************/ + +#include "exfat_config.h" +#include "exfat_global.h" + +#include "exfat_nls.h" + +UINT8 uni_upcase[NUM_UPCASE<<1] = { + 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, + 0x08, 0x00, 0x09, 0x00, 0x0A, 0x00, 0x0B, 0x00, 0x0C, 0x00, 0x0D, 0x00, 0x0E, 0x00, 0x0F, 0x00, + 0x10, 0x00, 0x11, 0x00, 0x12, 0x00, 0x13, 0x00, 0x14, 0x00, 0x15, 0x00, 0x16, 0x00, 0x17, 0x00, + 0x18, 0x00, 0x19, 0x00, 0x1A, 0x00, 0x1B, 0x00, 0x1C, 0x00, 0x1D, 0x00, 0x1E, 0x00, 0x1F, 0x00, + 0x20, 0x00, 0x21, 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x00, 0x25, 0x00, 0x26, 0x00, 0x27, 0x00, + 0x28, 0x00, 0x29, 0x00, 0x2A, 0x00, 0x2B, 0x00, 0x2C, 0x00, 0x2D, 0x00, 0x2E, 0x00, 0x2F, 0x00, + 0x30, 0x00, 0x31, 0x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00, 0x37, 0x00, + 0x38, 0x00, 0x39, 0x00, 0x3A, 0x00, 0x3B, 0x00, 0x3C, 0x00, 0x3D, 0x00, 0x3E, 0x00, 0x3F, 0x00, + 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x5B, 0x00, 0x5C, 0x00, 0x5D, 0x00, 0x5E, 0x00, 0x5F, 0x00, + 0x60, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44, 0x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, + 0x48, 0x00, 0x49, 0x00, 0x4A, 0x00, 0x4B, 0x00, 0x4C, 0x00, 0x4D, 0x00, 0x4E, 0x00, 0x4F, 0x00, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x00, + 0x58, 0x00, 0x59, 0x00, 0x5A, 0x00, 0x7B, 0x00, 0x7C, 0x00, 0x7D, 0x00, 0x7E, 0x00, 0x7F, 0x00, + 0x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85, 0x00, 0x86, 0x00, 0x87, 0x00, + 0x88, 0x00, 0x89, 0x00, 0x8A, 0x00, 0x8B, 0x00, 0x8C, 0x00, 0x8D, 0x00, 0x8E, 0x00, 0x8F, 0x00, + 0x90, 0x00, 0x91, 0x00, 0x92, 0x00, 0x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, + 0x98, 0x00, 0x99, 0x00, 0x9A, 0x00, 0x9B, 0x00, 0x9C, 0x00, 0x9D, 0x00, 0x9E, 0x00, 0x9F, 0x00, + 0xA0, 0x00, 0xA1, 0x00, 0xA2, 0x00, 0xA3, 0x00, 0xA4, 0x00, 0xA5, 0x00, 0xA6, 0x00, 0xA7, 0x00, + 0xA8, 0x00, 0xA9, 0x00, 0xAA, 0x00, 0xAB, 0x00, 0xAC, 0x00, 0xAD, 0x00, 0xAE, 0x00, 0xAF, 0x00, + 0xB0, 0x00, 0xB1, 0x00, 0xB2, 0x00, 0xB3, 0x00, 0xB4, 0x00, 0xB5, 0x00, 0xB6, 0x00, 0xB7, 0x00, + 0xB8, 0x00, 0xB9, 0x00, 0xBA, 0x00, 0xBB, 0x00, 0xBC, 0x00, 0xBD, 0x00, 0xBE, 0x00, 0xBF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xD7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0xDF, 0x00, + 0xC0, 0x00, 0xC1, 0x00, 0xC2, 0x00, 0xC3, 0x00, 0xC4, 0x00, 0xC5, 0x00, 0xC6, 0x00, 0xC7, 0x00, + 0xC8, 0x00, 0xC9, 0x00, 0xCA, 0x00, 0xCB, 0x00, 0xCC, 0x00, 0xCD, 0x00, 0xCE, 0x00, 0xCF, 0x00, + 0xD0, 0x00, 0xD1, 0x00, 0xD2, 0x00, 0xD3, 0x00, 0xD4, 0x00, 0xD5, 0x00, 0xD6, 0x00, 0xF7, 0x00, + 0xD8, 0x00, 0xD9, 0x00, 0xDA, 0x00, 0xDB, 0x00, 0xDC, 0x00, 0xDD, 0x00, 0xDE, 0x00, 0x78, 0x01, + 0x00, 0x01, 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x04, 0x01, 0x04, 0x01, 0x06, 0x01, 0x06, 0x01, + 0x08, 0x01, 0x08, 0x01, 0x0A, 0x01, 0x0A, 0x01, 0x0C, 0x01, 0x0C, 0x01, 0x0E, 0x01, 0x0E, 0x01, + 0x10, 0x01, 0x10, 0x01, 0x12, 0x01, 0x12, 0x01, 0x14, 0x01, 0x14, 0x01, 0x16, 0x01, 0x16, 0x01, + 0x18, 0x01, 0x18, 0x01, 0x1A, 0x01, 0x1A, 0x01, 0x1C, 0x01, 0x1C, 0x01, 0x1E, 0x01, 0x1E, 0x01, + 0x20, 0x01, 0x20, 0x01, 0x22, 0x01, 0x22, 0x01, 0x24, 0x01, 0x24, 0x01, 0x26, 0x01, 0x26, 0x01, + 0x28, 0x01, 0x28, 0x01, 0x2A, 0x01, 0x2A, 0x01, 0x2C, 0x01, 0x2C, 0x01, 0x2E, 0x01, 0x2E, 0x01, + 0x30, 0x01, 0x31, 0x01, 0x32, 0x01, 0x32, 0x01, 0x34, 0x01, 0x34, 0x01, 0x36, 0x01, 0x36, 0x01, + 0x38, 0x01, 0x39, 0x01, 0x39, 0x01, 0x3B, 0x01, 0x3B, 0x01, 0x3D, 0x01, 0x3D, 0x01, 0x3F, 0x01, + 0x3F, 0x01, 0x41, 0x01, 0x41, 0x01, 0x43, 0x01, 0x43, 0x01, 0x45, 0x01, 0x45, 0x01, 0x47, 0x01, + 0x47, 0x01, 0x49, 0x01, 0x4A, 0x01, 0x4A, 0x01, 0x4C, 0x01, 0x4C, 0x01, 0x4E, 0x01, 0x4E, 0x01, + 0x50, 0x01, 0x50, 0x01, 0x52, 0x01, 0x52, 0x01, 0x54, 0x01, 0x54, 0x01, 0x56, 0x01, 0x56, 0x01, + 0x58, 0x01, 0x58, 0x01, 0x5A, 0x01, 0x5A, 0x01, 0x5C, 0x01, 0x5C, 0x01, 0x5E, 0x01, 0x5E, 0x01, + 0x60, 0x01, 0x60, 0x01, 0x62, 0x01, 0x62, 0x01, 0x64, 0x01, 0x64, 0x01, 0x66, 0x01, 0x66, 0x01, + 0x68, 0x01, 0x68, 0x01, 0x6A, 0x01, 0x6A, 0x01, 0x6C, 0x01, 0x6C, 0x01, 0x6E, 0x01, 0x6E, 0x01, + 0x70, 0x01, 0x70, 0x01, 0x72, 0x01, 0x72, 0x01, 0x74, 0x01, 0x74, 0x01, 0x76, 0x01, 0x76, 0x01, + 0x78, 0x01, 0x79, 0x01, 0x79, 0x01, 0x7B, 0x01, 0x7B, 0x01, 0x7D, 0x01, 0x7D, 0x01, 0x7F, 0x01, + 0x43, 0x02, 0x81, 0x01, 0x82, 0x01, 0x82, 0x01, 0x84, 0x01, 0x84, 0x01, 0x86, 0x01, 0x87, 0x01, + 0x87, 0x01, 0x89, 0x01, 0x8A, 0x01, 0x8B, 0x01, 0x8B, 0x01, 0x8D, 0x01, 0x8E, 0x01, 0x8F, 0x01, + 0x90, 0x01, 0x91, 0x01, 0x91, 0x01, 0x93, 0x01, 0x94, 0x01, 0xF6, 0x01, 0x96, 0x01, 0x97, 0x01, + 0x98, 0x01, 0x98, 0x01, 0x3D, 0x02, 0x9B, 0x01, 0x9C, 0x01, 0x9D, 0x01, 0x20, 0x02, 0x9F, 0x01, + 0xA0, 0x01, 0xA0, 0x01, 0xA2, 0x01, 0xA2, 0x01, 0xA4, 0x01, 0xA4, 0x01, 0xA6, 0x01, 0xA7, 0x01, + 0xA7, 0x01, 0xA9, 0x01, 0xAA, 0x01, 0xAB, 0x01, 0xAC, 0x01, 0xAC, 0x01, 0xAE, 0x01, 0xAF, 0x01, + 0xAF, 0x01, 0xB1, 0x01, 0xB2, 0x01, 0xB3, 0x01, 0xB3, 0x01, 0xB5, 0x01, 0xB5, 0x01, 0xB7, 0x01, + 0xB8, 0x01, 0xB8, 0x01, 0xBA, 0x01, 0xBB, 0x01, 0xBC, 0x01, 0xBC, 0x01, 0xBE, 0x01, 0xF7, 0x01, + 0xC0, 0x01, 0xC1, 0x01, 0xC2, 0x01, 0xC3, 0x01, 0xC4, 0x01, 0xC5, 0x01, 0xC4, 0x01, 0xC7, 0x01, + 0xC8, 0x01, 0xC7, 0x01, 0xCA, 0x01, 0xCB, 0x01, 0xCA, 0x01, 0xCD, 0x01, 0xCD, 0x01, 0xCF, 0x01, + 0xCF, 0x01, 0xD1, 0x01, 0xD1, 0x01, 0xD3, 0x01, 0xD3, 0x01, 0xD5, 0x01, 0xD5, 0x01, 0xD7, 0x01, + 0xD7, 0x01, 0xD9, 0x01, 0xD9, 0x01, 0xDB, 0x01, 0xDB, 0x01, 0x8E, 0x01, 0xDE, 0x01, 0xDE, 0x01, + 0xE0, 0x01, 0xE0, 0x01, 0xE2, 0x01, 0xE2, 0x01, 0xE4, 0x01, 0xE4, 0x01, 0xE6, 0x01, 0xE6, 0x01, + 0xE8, 0x01, 0xE8, 0x01, 0xEA, 0x01, 0xEA, 0x01, 0xEC, 0x01, 0xEC, 0x01, 0xEE, 0x01, 0xEE, 0x01, + 0xF0, 0x01, 0xF1, 0x01, 0xF2, 0x01, 0xF1, 0x01, 0xF4, 0x01, 0xF4, 0x01, 0xF6, 0x01, 0xF7, 0x01, + 0xF8, 0x01, 0xF8, 0x01, 0xFA, 0x01, 0xFA, 0x01, 0xFC, 0x01, 0xFC, 0x01, 0xFE, 0x01, 0xFE, 0x01, + 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x04, 0x02, 0x06, 0x02, 0x06, 0x02, + 0x08, 0x02, 0x08, 0x02, 0x0A, 0x02, 0x0A, 0x02, 0x0C, 0x02, 0x0C, 0x02, 0x0E, 0x02, 0x0E, 0x02, + 0x10, 0x02, 0x10, 0x02, 0x12, 0x02, 0x12, 0x02, 0x14, 0x02, 0x14, 0x02, 0x16, 0x02, 0x16, 0x02, + 0x18, 0x02, 0x18, 0x02, 0x1A, 0x02, 0x1A, 0x02, 0x1C, 0x02, 0x1C, 0x02, 0x1E, 0x02, 0x1E, 0x02, + 0x20, 0x02, 0x21, 0x02, 0x22, 0x02, 0x22, 0x02, 0x24, 0x02, 0x24, 0x02, 0x26, 0x02, 0x26, 0x02, + 0x28, 0x02, 0x28, 0x02, 0x2A, 0x02, 0x2A, 0x02, 0x2C, 0x02, 0x2C, 0x02, 0x2E, 0x02, 0x2E, 0x02, + 0x30, 0x02, 0x30, 0x02, 0x32, 0x02, 0x32, 0x02, 0x34, 0x02, 0x35, 0x02, 0x36, 0x02, 0x37, 0x02, + 0x38, 0x02, 0x39, 0x02, 0x65, 0x2C, 0x3B, 0x02, 0x3B, 0x02, 0x3D, 0x02, 0x66, 0x2C, 0x3F, 0x02, + 0x40, 0x02, 0x41, 0x02, 0x41, 0x02, 0x43, 0x02, 0x44, 0x02, 0x45, 0x02, 0x46, 0x02, 0x46, 0x02, + 0x48, 0x02, 0x48, 0x02, 0x4A, 0x02, 0x4A, 0x02, 0x4C, 0x02, 0x4C, 0x02, 0x4E, 0x02, 0x4E, 0x02, + 0x50, 0x02, 0x51, 0x02, 0x52, 0x02, 0x81, 0x01, 0x86, 0x01, 0x55, 0x02, 0x89, 0x01, 0x8A, 0x01, + 0x58, 0x02, 0x8F, 0x01, 0x5A, 0x02, 0x90, 0x01, 0x5C, 0x02, 0x5D, 0x02, 0x5E, 0x02, 0x5F, 0x02, + 0x93, 0x01, 0x61, 0x02, 0x62, 0x02, 0x94, 0x01, 0x64, 0x02, 0x65, 0x02, 0x66, 0x02, 0x67, 0x02, + 0x97, 0x01, 0x96, 0x01, 0x6A, 0x02, 0x62, 0x2C, 0x6C, 0x02, 0x6D, 0x02, 0x6E, 0x02, 0x9C, 0x01, + 0x70, 0x02, 0x71, 0x02, 0x9D, 0x01, 0x73, 0x02, 0x74, 0x02, 0x9F, 0x01, 0x76, 0x02, 0x77, 0x02, + 0x78, 0x02, 0x79, 0x02, 0x7A, 0x02, 0x7B, 0x02, 0x7C, 0x02, 0x64, 0x2C, 0x7E, 0x02, 0x7F, 0x02, + 0xA6, 0x01, 0x81, 0x02, 0x82, 0x02, 0xA9, 0x01, 0x84, 0x02, 0x85, 0x02, 0x86, 0x02, 0x87, 0x02, + 0xAE, 0x01, 0x44, 0x02, 0xB1, 0x01, 0xB2, 0x01, 0x45, 0x02, 0x8D, 0x02, 0x8E, 0x02, 0x8F, 0x02, + 0x90, 0x02, 0x91, 0x02, 0xB7, 0x01, 0x93, 0x02, 0x94, 0x02, 0x95, 0x02, 0x96, 0x02, 0x97, 0x02, + 0x98, 0x02, 0x99, 0x02, 0x9A, 0x02, 0x9B, 0x02, 0x9C, 0x02, 0x9D, 0x02, 0x9E, 0x02, 0x9F, 0x02, + 0xA0, 0x02, 0xA1, 0x02, 0xA2, 0x02, 0xA3, 0x02, 0xA4, 0x02, 0xA5, 0x02, 0xA6, 0x02, 0xA7, 0x02, + 0xA8, 0x02, 0xA9, 0x02, 0xAA, 0x02, 0xAB, 0x02, 0xAC, 0x02, 0xAD, 0x02, 0xAE, 0x02, 0xAF, 0x02, + 0xB0, 0x02, 0xB1, 0x02, 0xB2, 0x02, 0xB3, 0x02, 0xB4, 0x02, 0xB5, 0x02, 0xB6, 0x02, 0xB7, 0x02, + 0xB8, 0x02, 0xB9, 0x02, 0xBA, 0x02, 0xBB, 0x02, 0xBC, 0x02, 0xBD, 0x02, 0xBE, 0x02, 0xBF, 0x02, + 0xC0, 0x02, 0xC1, 0x02, 0xC2, 0x02, 0xC3, 0x02, 0xC4, 0x02, 0xC5, 0x02, 0xC6, 0x02, 0xC7, 0x02, + 0xC8, 0x02, 0xC9, 0x02, 0xCA, 0x02, 0xCB, 0x02, 0xCC, 0x02, 0xCD, 0x02, 0xCE, 0x02, 0xCF, 0x02, + 0xD0, 0x02, 0xD1, 0x02, 0xD2, 0x02, 0xD3, 0x02, 0xD4, 0x02, 0xD5, 0x02, 0xD6, 0x02, 0xD7, 0x02, + 0xD8, 0x02, 0xD9, 0x02, 0xDA, 0x02, 0xDB, 0x02, 0xDC, 0x02, 0xDD, 0x02, 0xDE, 0x02, 0xDF, 0x02, + 0xE0, 0x02, 0xE1, 0x02, 0xE2, 0x02, 0xE3, 0x02, 0xE4, 0x02, 0xE5, 0x02, 0xE6, 0x02, 0xE7, 0x02, + 0xE8, 0x02, 0xE9, 0x02, 0xEA, 0x02, 0xEB, 0x02, 0xEC, 0x02, 0xED, 0x02, 0xEE, 0x02, 0xEF, 0x02, + 0xF0, 0x02, 0xF1, 0x02, 0xF2, 0x02, 0xF3, 0x02, 0xF4, 0x02, 0xF5, 0x02, 0xF6, 0x02, 0xF7, 0x02, + 0xF8, 0x02, 0xF9, 0x02, 0xFA, 0x02, 0xFB, 0x02, 0xFC, 0x02, 0xFD, 0x02, 0xFE, 0x02, 0xFF, 0x02, + 0x00, 0x03, 0x01, 0x03, 0x02, 0x03, 0x03, 0x03, 0x04, 0x03, 0x05, 0x03, 0x06, 0x03, 0x07, 0x03, + 0x08, 0x03, 0x09, 0x03, 0x0A, 0x03, 0x0B, 0x03, 0x0C, 0x03, 0x0D, 0x03, 0x0E, 0x03, 0x0F, 0x03, + 0x10, 0x03, 0x11, 0x03, 0x12, 0x03, 0x13, 0x03, 0x14, 0x03, 0x15, 0x03, 0x16, 0x03, 0x17, 0x03, + 0x18, 0x03, 0x19, 0x03, 0x1A, 0x03, 0x1B, 0x03, 0x1C, 0x03, 0x1D, 0x03, 0x1E, 0x03, 0x1F, 0x03, + 0x20, 0x03, 0x21, 0x03, 0x22, 0x03, 0x23, 0x03, 0x24, 0x03, 0x25, 0x03, 0x26, 0x03, 0x27, 0x03, + 0x28, 0x03, 0x29, 0x03, 0x2A, 0x03, 0x2B, 0x03, 0x2C, 0x03, 0x2D, 0x03, 0x2E, 0x03, 0x2F, 0x03, + 0x30, 0x03, 0x31, 0x03, 0x32, 0x03, 0x33, 0x03, 0x34, 0x03, 0x35, 0x03, 0x36, 0x03, 0x37, 0x03, + 0x38, 0x03, 0x39, 0x03, 0x3A, 0x03, 0x3B, 0x03, 0x3C, 0x03, 0x3D, 0x03, 0x3E, 0x03, 0x3F, 0x03, + 0x40, 0x03, 0x41, 0x03, 0x42, 0x03, 0x43, 0x03, 0x44, 0x03, 0x45, 0x03, 0x46, 0x03, 0x47, 0x03, + 0x48, 0x03, 0x49, 0x03, 0x4A, 0x03, 0x4B, 0x03, 0x4C, 0x03, 0x4D, 0x03, 0x4E, 0x03, 0x4F, 0x03, + 0x50, 0x03, 0x51, 0x03, 0x52, 0x03, 0x53, 0x03, 0x54, 0x03, 0x55, 0x03, 0x56, 0x03, 0x57, 0x03, + 0x58, 0x03, 0x59, 0x03, 0x5A, 0x03, 0x5B, 0x03, 0x5C, 0x03, 0x5D, 0x03, 0x5E, 0x03, 0x5F, 0x03, + 0x60, 0x03, 0x61, 0x03, 0x62, 0x03, 0x63, 0x03, 0x64, 0x03, 0x65, 0x03, 0x66, 0x03, 0x67, 0x03, + 0x68, 0x03, 0x69, 0x03, 0x6A, 0x03, 0x6B, 0x03, 0x6C, 0x03, 0x6D, 0x03, 0x6E, 0x03, 0x6F, 0x03, + 0x70, 0x03, 0x71, 0x03, 0x72, 0x03, 0x73, 0x03, 0x74, 0x03, 0x75, 0x03, 0x76, 0x03, 0x77, 0x03, + 0x78, 0x03, 0x79, 0x03, 0x7A, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, 0x7E, 0x03, 0x7F, 0x03, + 0x80, 0x03, 0x81, 0x03, 0x82, 0x03, 0x83, 0x03, 0x84, 0x03, 0x85, 0x03, 0x86, 0x03, 0x87, 0x03, + 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, 0x8B, 0x03, 0x8C, 0x03, 0x8D, 0x03, 0x8E, 0x03, 0x8F, 0x03, + 0x90, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA2, 0x03, 0xA3, 0x03, 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, 0x86, 0x03, 0x88, 0x03, 0x89, 0x03, 0x8A, 0x03, + 0xB0, 0x03, 0x91, 0x03, 0x92, 0x03, 0x93, 0x03, 0x94, 0x03, 0x95, 0x03, 0x96, 0x03, 0x97, 0x03, + 0x98, 0x03, 0x99, 0x03, 0x9A, 0x03, 0x9B, 0x03, 0x9C, 0x03, 0x9D, 0x03, 0x9E, 0x03, 0x9F, 0x03, + 0xA0, 0x03, 0xA1, 0x03, 0xA3, 0x03, 0xA3, 0x03, 0xA4, 0x03, 0xA5, 0x03, 0xA6, 0x03, 0xA7, 0x03, + 0xA8, 0x03, 0xA9, 0x03, 0xAA, 0x03, 0xAB, 0x03, 0x8C, 0x03, 0x8E, 0x03, 0x8F, 0x03, 0xCF, 0x03, + 0xD0, 0x03, 0xD1, 0x03, 0xD2, 0x03, 0xD3, 0x03, 0xD4, 0x03, 0xD5, 0x03, 0xD6, 0x03, 0xD7, 0x03, + 0xD8, 0x03, 0xD8, 0x03, 0xDA, 0x03, 0xDA, 0x03, 0xDC, 0x03, 0xDC, 0x03, 0xDE, 0x03, 0xDE, 0x03, + 0xE0, 0x03, 0xE0, 0x03, 0xE2, 0x03, 0xE2, 0x03, 0xE4, 0x03, 0xE4, 0x03, 0xE6, 0x03, 0xE6, 0x03, + 0xE8, 0x03, 0xE8, 0x03, 0xEA, 0x03, 0xEA, 0x03, 0xEC, 0x03, 0xEC, 0x03, 0xEE, 0x03, 0xEE, 0x03, + 0xF0, 0x03, 0xF1, 0x03, 0xF9, 0x03, 0xF3, 0x03, 0xF4, 0x03, 0xF5, 0x03, 0xF6, 0x03, 0xF7, 0x03, + 0xF7, 0x03, 0xF9, 0x03, 0xFA, 0x03, 0xFA, 0x03, 0xFC, 0x03, 0xFD, 0x03, 0xFE, 0x03, 0xFF, 0x03, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x10, 0x04, 0x11, 0x04, 0x12, 0x04, 0x13, 0x04, 0x14, 0x04, 0x15, 0x04, 0x16, 0x04, 0x17, 0x04, + 0x18, 0x04, 0x19, 0x04, 0x1A, 0x04, 0x1B, 0x04, 0x1C, 0x04, 0x1D, 0x04, 0x1E, 0x04, 0x1F, 0x04, + 0x20, 0x04, 0x21, 0x04, 0x22, 0x04, 0x23, 0x04, 0x24, 0x04, 0x25, 0x04, 0x26, 0x04, 0x27, 0x04, + 0x28, 0x04, 0x29, 0x04, 0x2A, 0x04, 0x2B, 0x04, 0x2C, 0x04, 0x2D, 0x04, 0x2E, 0x04, 0x2F, 0x04, + 0x00, 0x04, 0x01, 0x04, 0x02, 0x04, 0x03, 0x04, 0x04, 0x04, 0x05, 0x04, 0x06, 0x04, 0x07, 0x04, + 0x08, 0x04, 0x09, 0x04, 0x0A, 0x04, 0x0B, 0x04, 0x0C, 0x04, 0x0D, 0x04, 0x0E, 0x04, 0x0F, 0x04, + 0x60, 0x04, 0x60, 0x04, 0x62, 0x04, 0x62, 0x04, 0x64, 0x04, 0x64, 0x04, 0x66, 0x04, 0x66, 0x04, + 0x68, 0x04, 0x68, 0x04, 0x6A, 0x04, 0x6A, 0x04, 0x6C, 0x04, 0x6C, 0x04, 0x6E, 0x04, 0x6E, 0x04, + 0x70, 0x04, 0x70, 0x04, 0x72, 0x04, 0x72, 0x04, 0x74, 0x04, 0x74, 0x04, 0x76, 0x04, 0x76, 0x04, + 0x78, 0x04, 0x78, 0x04, 0x7A, 0x04, 0x7A, 0x04, 0x7C, 0x04, 0x7C, 0x04, 0x7E, 0x04, 0x7E, 0x04, + 0x80, 0x04, 0x80, 0x04, 0x82, 0x04, 0x83, 0x04, 0x84, 0x04, 0x85, 0x04, 0x86, 0x04, 0x87, 0x04, + 0x88, 0x04, 0x89, 0x04, 0x8A, 0x04, 0x8A, 0x04, 0x8C, 0x04, 0x8C, 0x04, 0x8E, 0x04, 0x8E, 0x04, + 0x90, 0x04, 0x90, 0x04, 0x92, 0x04, 0x92, 0x04, 0x94, 0x04, 0x94, 0x04, 0x96, 0x04, 0x96, 0x04, + 0x98, 0x04, 0x98, 0x04, 0x9A, 0x04, 0x9A, 0x04, 0x9C, 0x04, 0x9C, 0x04, 0x9E, 0x04, 0x9E, 0x04, + 0xA0, 0x04, 0xA0, 0x04, 0xA2, 0x04, 0xA2, 0x04, 0xA4, 0x04, 0xA4, 0x04, 0xA6, 0x04, 0xA6, 0x04, + 0xA8, 0x04, 0xA8, 0x04, 0xAA, 0x04, 0xAA, 0x04, 0xAC, 0x04, 0xAC, 0x04, 0xAE, 0x04, 0xAE, 0x04, + 0xB0, 0x04, 0xB0, 0x04, 0xB2, 0x04, 0xB2, 0x04, 0xB4, 0x04, 0xB4, 0x04, 0xB6, 0x04, 0xB6, 0x04, + 0xB8, 0x04, 0xB8, 0x04, 0xBA, 0x04, 0xBA, 0x04, 0xBC, 0x04, 0xBC, 0x04, 0xBE, 0x04, 0xBE, 0x04, + 0xC0, 0x04, 0xC1, 0x04, 0xC1, 0x04, 0xC3, 0x04, 0xC3, 0x04, 0xC5, 0x04, 0xC5, 0x04, 0xC7, 0x04, + 0xC7, 0x04, 0xC9, 0x04, 0xC9, 0x04, 0xCB, 0x04, 0xCB, 0x04, 0xCD, 0x04, 0xCD, 0x04, 0xC0, 0x04, + 0xD0, 0x04, 0xD0, 0x04, 0xD2, 0x04, 0xD2, 0x04, 0xD4, 0x04, 0xD4, 0x04, 0xD6, 0x04, 0xD6, 0x04, + 0xD8, 0x04, 0xD8, 0x04, 0xDA, 0x04, 0xDA, 0x04, 0xDC, 0x04, 0xDC, 0x04, 0xDE, 0x04, 0xDE, 0x04, + 0xE0, 0x04, 0xE0, 0x04, 0xE2, 0x04, 0xE2, 0x04, 0xE4, 0x04, 0xE4, 0x04, 0xE6, 0x04, 0xE6, 0x04, + 0xE8, 0x04, 0xE8, 0x04, 0xEA, 0x04, 0xEA, 0x04, 0xEC, 0x04, 0xEC, 0x04, 0xEE, 0x04, 0xEE, 0x04, + 0xF0, 0x04, 0xF0, 0x04, 0xF2, 0x04, 0xF2, 0x04, 0xF4, 0x04, 0xF4, 0x04, 0xF6, 0x04, 0xF6, 0x04, + 0xF8, 0x04, 0xF8, 0x04, 0xFA, 0x04, 0xFA, 0x04, 0xFC, 0x04, 0xFC, 0x04, 0xFE, 0x04, 0xFE, 0x04, + 0x00, 0x05, 0x00, 0x05, 0x02, 0x05, 0x02, 0x05, 0x04, 0x05, 0x04, 0x05, 0x06, 0x05, 0x06, 0x05, + 0x08, 0x05, 0x08, 0x05, 0x0A, 0x05, 0x0A, 0x05, 0x0C, 0x05, 0x0C, 0x05, 0x0E, 0x05, 0x0E, 0x05, + 0x10, 0x05, 0x10, 0x05, 0x12, 0x05, 0x12, 0x05, 0x14, 0x05, 0x15, 0x05, 0x16, 0x05, 0x17, 0x05, + 0x18, 0x05, 0x19, 0x05, 0x1A, 0x05, 0x1B, 0x05, 0x1C, 0x05, 0x1D, 0x05, 0x1E, 0x05, 0x1F, 0x05, + 0x20, 0x05, 0x21, 0x05, 0x22, 0x05, 0x23, 0x05, 0x24, 0x05, 0x25, 0x05, 0x26, 0x05, 0x27, 0x05, + 0x28, 0x05, 0x29, 0x05, 0x2A, 0x05, 0x2B, 0x05, 0x2C, 0x05, 0x2D, 0x05, 0x2E, 0x05, 0x2F, 0x05, + 0x30, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0x57, 0x05, + 0x58, 0x05, 0x59, 0x05, 0x5A, 0x05, 0x5B, 0x05, 0x5C, 0x05, 0x5D, 0x05, 0x5E, 0x05, 0x5F, 0x05, + 0x60, 0x05, 0x31, 0x05, 0x32, 0x05, 0x33, 0x05, 0x34, 0x05, 0x35, 0x05, 0x36, 0x05, 0x37, 0x05, + 0x38, 0x05, 0x39, 0x05, 0x3A, 0x05, 0x3B, 0x05, 0x3C, 0x05, 0x3D, 0x05, 0x3E, 0x05, 0x3F, 0x05, + 0x40, 0x05, 0x41, 0x05, 0x42, 0x05, 0x43, 0x05, 0x44, 0x05, 0x45, 0x05, 0x46, 0x05, 0x47, 0x05, + 0x48, 0x05, 0x49, 0x05, 0x4A, 0x05, 0x4B, 0x05, 0x4C, 0x05, 0x4D, 0x05, 0x4E, 0x05, 0x4F, 0x05, + 0x50, 0x05, 0x51, 0x05, 0x52, 0x05, 0x53, 0x05, 0x54, 0x05, 0x55, 0x05, 0x56, 0x05, 0xFF, 0xFF, + 0xF6, 0x17, 0x63, 0x2C, 0x7E, 0x1D, 0x7F, 0x1D, 0x80, 0x1D, 0x81, 0x1D, 0x82, 0x1D, 0x83, 0x1D, + 0x84, 0x1D, 0x85, 0x1D, 0x86, 0x1D, 0x87, 0x1D, 0x88, 0x1D, 0x89, 0x1D, 0x8A, 0x1D, 0x8B, 0x1D, + 0x8C, 0x1D, 0x8D, 0x1D, 0x8E, 0x1D, 0x8F, 0x1D, 0x90, 0x1D, 0x91, 0x1D, 0x92, 0x1D, 0x93, 0x1D, + 0x94, 0x1D, 0x95, 0x1D, 0x96, 0x1D, 0x97, 0x1D, 0x98, 0x1D, 0x99, 0x1D, 0x9A, 0x1D, 0x9B, 0x1D, + 0x9C, 0x1D, 0x9D, 0x1D, 0x9E, 0x1D, 0x9F, 0x1D, 0xA0, 0x1D, 0xA1, 0x1D, 0xA2, 0x1D, 0xA3, 0x1D, + 0xA4, 0x1D, 0xA5, 0x1D, 0xA6, 0x1D, 0xA7, 0x1D, 0xA8, 0x1D, 0xA9, 0x1D, 0xAA, 0x1D, 0xAB, 0x1D, + 0xAC, 0x1D, 0xAD, 0x1D, 0xAE, 0x1D, 0xAF, 0x1D, 0xB0, 0x1D, 0xB1, 0x1D, 0xB2, 0x1D, 0xB3, 0x1D, + 0xB4, 0x1D, 0xB5, 0x1D, 0xB6, 0x1D, 0xB7, 0x1D, 0xB8, 0x1D, 0xB9, 0x1D, 0xBA, 0x1D, 0xBB, 0x1D, + 0xBC, 0x1D, 0xBD, 0x1D, 0xBE, 0x1D, 0xBF, 0x1D, 0xC0, 0x1D, 0xC1, 0x1D, 0xC2, 0x1D, 0xC3, 0x1D, + 0xC4, 0x1D, 0xC5, 0x1D, 0xC6, 0x1D, 0xC7, 0x1D, 0xC8, 0x1D, 0xC9, 0x1D, 0xCA, 0x1D, 0xCB, 0x1D, + 0xCC, 0x1D, 0xCD, 0x1D, 0xCE, 0x1D, 0xCF, 0x1D, 0xD0, 0x1D, 0xD1, 0x1D, 0xD2, 0x1D, 0xD3, 0x1D, + 0xD4, 0x1D, 0xD5, 0x1D, 0xD6, 0x1D, 0xD7, 0x1D, 0xD8, 0x1D, 0xD9, 0x1D, 0xDA, 0x1D, 0xDB, 0x1D, + 0xDC, 0x1D, 0xDD, 0x1D, 0xDE, 0x1D, 0xDF, 0x1D, 0xE0, 0x1D, 0xE1, 0x1D, 0xE2, 0x1D, 0xE3, 0x1D, + 0xE4, 0x1D, 0xE5, 0x1D, 0xE6, 0x1D, 0xE7, 0x1D, 0xE8, 0x1D, 0xE9, 0x1D, 0xEA, 0x1D, 0xEB, 0x1D, + 0xEC, 0x1D, 0xED, 0x1D, 0xEE, 0x1D, 0xEF, 0x1D, 0xF0, 0x1D, 0xF1, 0x1D, 0xF2, 0x1D, 0xF3, 0x1D, + 0xF4, 0x1D, 0xF5, 0x1D, 0xF6, 0x1D, 0xF7, 0x1D, 0xF8, 0x1D, 0xF9, 0x1D, 0xFA, 0x1D, 0xFB, 0x1D, + 0xFC, 0x1D, 0xFD, 0x1D, 0xFE, 0x1D, 0xFF, 0x1D, 0x00, 0x1E, 0x00, 0x1E, 0x02, 0x1E, 0x02, 0x1E, + 0x04, 0x1E, 0x04, 0x1E, 0x06, 0x1E, 0x06, 0x1E, 0x08, 0x1E, 0x08, 0x1E, 0x0A, 0x1E, 0x0A, 0x1E, + 0x0C, 0x1E, 0x0C, 0x1E, 0x0E, 0x1E, 0x0E, 0x1E, 0x10, 0x1E, 0x10, 0x1E, 0x12, 0x1E, 0x12, 0x1E, + 0x14, 0x1E, 0x14, 0x1E, 0x16, 0x1E, 0x16, 0x1E, 0x18, 0x1E, 0x18, 0x1E, 0x1A, 0x1E, 0x1A, 0x1E, + 0x1C, 0x1E, 0x1C, 0x1E, 0x1E, 0x1E, 0x1E, 0x1E, 0x20, 0x1E, 0x20, 0x1E, 0x22, 0x1E, 0x22, 0x1E, + 0x24, 0x1E, 0x24, 0x1E, 0x26, 0x1E, 0x26, 0x1E, 0x28, 0x1E, 0x28, 0x1E, 0x2A, 0x1E, 0x2A, 0x1E, + 0x2C, 0x1E, 0x2C, 0x1E, 0x2E, 0x1E, 0x2E, 0x1E, 0x30, 0x1E, 0x30, 0x1E, 0x32, 0x1E, 0x32, 0x1E, + 0x34, 0x1E, 0x34, 0x1E, 0x36, 0x1E, 0x36, 0x1E, 0x38, 0x1E, 0x38, 0x1E, 0x3A, 0x1E, 0x3A, 0x1E, + 0x3C, 0x1E, 0x3C, 0x1E, 0x3E, 0x1E, 0x3E, 0x1E, 0x40, 0x1E, 0x40, 0x1E, 0x42, 0x1E, 0x42, 0x1E, + 0x44, 0x1E, 0x44, 0x1E, 0x46, 0x1E, 0x46, 0x1E, 0x48, 0x1E, 0x48, 0x1E, 0x4A, 0x1E, 0x4A, 0x1E, + 0x4C, 0x1E, 0x4C, 0x1E, 0x4E, 0x1E, 0x4E, 0x1E, 0x50, 0x1E, 0x50, 0x1E, 0x52, 0x1E, 0x52, 0x1E, + 0x54, 0x1E, 0x54, 0x1E, 0x56, 0x1E, 0x56, 0x1E, 0x58, 0x1E, 0x58, 0x1E, 0x5A, 0x1E, 0x5A, 0x1E, + 0x5C, 0x1E, 0x5C, 0x1E, 0x5E, 0x1E, 0x5E, 0x1E, 0x60, 0x1E, 0x60, 0x1E, 0x62, 0x1E, 0x62, 0x1E, + 0x64, 0x1E, 0x64, 0x1E, 0x66, 0x1E, 0x66, 0x1E, 0x68, 0x1E, 0x68, 0x1E, 0x6A, 0x1E, 0x6A, 0x1E, + 0x6C, 0x1E, 0x6C, 0x1E, 0x6E, 0x1E, 0x6E, 0x1E, 0x70, 0x1E, 0x70, 0x1E, 0x72, 0x1E, 0x72, 0x1E, + 0x74, 0x1E, 0x74, 0x1E, 0x76, 0x1E, 0x76, 0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x7A, 0x1E, 0x7A, 0x1E, + 0x7C, 0x1E, 0x7C, 0x1E, 0x7E, 0x1E, 0x7E, 0x1E, 0x80, 0x1E, 0x80, 0x1E, 0x82, 0x1E, 0x82, 0x1E, + 0x84, 0x1E, 0x84, 0x1E, 0x86, 0x1E, 0x86, 0x1E, 0x88, 0x1E, 0x88, 0x1E, 0x8A, 0x1E, 0x8A, 0x1E, + 0x8C, 0x1E, 0x8C, 0x1E, 0x8E, 0x1E, 0x8E, 0x1E, 0x90, 0x1E, 0x90, 0x1E, 0x92, 0x1E, 0x92, 0x1E, + 0x94, 0x1E, 0x94, 0x1E, 0x96, 0x1E, 0x97, 0x1E, 0x98, 0x1E, 0x99, 0x1E, 0x9A, 0x1E, 0x9B, 0x1E, + 0x9C, 0x1E, 0x9D, 0x1E, 0x9E, 0x1E, 0x9F, 0x1E, 0xA0, 0x1E, 0xA0, 0x1E, 0xA2, 0x1E, 0xA2, 0x1E, + 0xA4, 0x1E, 0xA4, 0x1E, 0xA6, 0x1E, 0xA6, 0x1E, 0xA8, 0x1E, 0xA8, 0x1E, 0xAA, 0x1E, 0xAA, 0x1E, + 0xAC, 0x1E, 0xAC, 0x1E, 0xAE, 0x1E, 0xAE, 0x1E, 0xB0, 0x1E, 0xB0, 0x1E, 0xB2, 0x1E, 0xB2, 0x1E, + 0xB4, 0x1E, 0xB4, 0x1E, 0xB6, 0x1E, 0xB6, 0x1E, 0xB8, 0x1E, 0xB8, 0x1E, 0xBA, 0x1E, 0xBA, 0x1E, + 0xBC, 0x1E, 0xBC, 0x1E, 0xBE, 0x1E, 0xBE, 0x1E, 0xC0, 0x1E, 0xC0, 0x1E, 0xC2, 0x1E, 0xC2, 0x1E, + 0xC4, 0x1E, 0xC4, 0x1E, 0xC6, 0x1E, 0xC6, 0x1E, 0xC8, 0x1E, 0xC8, 0x1E, 0xCA, 0x1E, 0xCA, 0x1E, + 0xCC, 0x1E, 0xCC, 0x1E, 0xCE, 0x1E, 0xCE, 0x1E, 0xD0, 0x1E, 0xD0, 0x1E, 0xD2, 0x1E, 0xD2, 0x1E, + 0xD4, 0x1E, 0xD4, 0x1E, 0xD6, 0x1E, 0xD6, 0x1E, 0xD8, 0x1E, 0xD8, 0x1E, 0xDA, 0x1E, 0xDA, 0x1E, + 0xDC, 0x1E, 0xDC, 0x1E, 0xDE, 0x1E, 0xDE, 0x1E, 0xE0, 0x1E, 0xE0, 0x1E, 0xE2, 0x1E, 0xE2, 0x1E, + 0xE4, 0x1E, 0xE4, 0x1E, 0xE6, 0x1E, 0xE6, 0x1E, 0xE8, 0x1E, 0xE8, 0x1E, 0xEA, 0x1E, 0xEA, 0x1E, + 0xEC, 0x1E, 0xEC, 0x1E, 0xEE, 0x1E, 0xEE, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF2, 0x1E, 0xF2, 0x1E, + 0xF4, 0x1E, 0xF4, 0x1E, 0xF6, 0x1E, 0xF6, 0x1E, 0xF8, 0x1E, 0xF8, 0x1E, 0xFA, 0x1E, 0xFB, 0x1E, + 0xFC, 0x1E, 0xFD, 0x1E, 0xFE, 0x1E, 0xFF, 0x1E, 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, 0x08, 0x1F, 0x09, 0x1F, 0x0A, 0x1F, 0x0B, 0x1F, + 0x0C, 0x1F, 0x0D, 0x1F, 0x0E, 0x1F, 0x0F, 0x1F, 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x16, 0x1F, 0x17, 0x1F, 0x18, 0x1F, 0x19, 0x1F, 0x1A, 0x1F, 0x1B, 0x1F, + 0x1C, 0x1F, 0x1D, 0x1F, 0x1E, 0x1F, 0x1F, 0x1F, 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, 0x28, 0x1F, 0x29, 0x1F, 0x2A, 0x1F, 0x2B, 0x1F, + 0x2C, 0x1F, 0x2D, 0x1F, 0x2E, 0x1F, 0x2F, 0x1F, 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, 0x38, 0x1F, 0x39, 0x1F, 0x3A, 0x1F, 0x3B, 0x1F, + 0x3C, 0x1F, 0x3D, 0x1F, 0x3E, 0x1F, 0x3F, 0x1F, 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x46, 0x1F, 0x47, 0x1F, 0x48, 0x1F, 0x49, 0x1F, 0x4A, 0x1F, 0x4B, 0x1F, + 0x4C, 0x1F, 0x4D, 0x1F, 0x4E, 0x1F, 0x4F, 0x1F, 0x50, 0x1F, 0x59, 0x1F, 0x52, 0x1F, 0x5B, 0x1F, + 0x54, 0x1F, 0x5D, 0x1F, 0x56, 0x1F, 0x5F, 0x1F, 0x58, 0x1F, 0x59, 0x1F, 0x5A, 0x1F, 0x5B, 0x1F, + 0x5C, 0x1F, 0x5D, 0x1F, 0x5E, 0x1F, 0x5F, 0x1F, 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, 0x68, 0x1F, 0x69, 0x1F, 0x6A, 0x1F, 0x6B, 0x1F, + 0x6C, 0x1F, 0x6D, 0x1F, 0x6E, 0x1F, 0x6F, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, + 0xCA, 0x1F, 0xCB, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, 0xF8, 0x1F, 0xF9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xFA, 0x1F, 0xFB, 0x1F, 0x7E, 0x1F, 0x7F, 0x1F, 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, 0x88, 0x1F, 0x89, 0x1F, 0x8A, 0x1F, 0x8B, 0x1F, + 0x8C, 0x1F, 0x8D, 0x1F, 0x8E, 0x1F, 0x8F, 0x1F, 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, 0x98, 0x1F, 0x99, 0x1F, 0x9A, 0x1F, 0x9B, 0x1F, + 0x9C, 0x1F, 0x9D, 0x1F, 0x9E, 0x1F, 0x9F, 0x1F, 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, 0xA8, 0x1F, 0xA9, 0x1F, 0xAA, 0x1F, 0xAB, 0x1F, + 0xAC, 0x1F, 0xAD, 0x1F, 0xAE, 0x1F, 0xAF, 0x1F, 0xB8, 0x1F, 0xB9, 0x1F, 0xB2, 0x1F, 0xBC, 0x1F, + 0xB4, 0x1F, 0xB5, 0x1F, 0xB6, 0x1F, 0xB7, 0x1F, 0xB8, 0x1F, 0xB9, 0x1F, 0xBA, 0x1F, 0xBB, 0x1F, + 0xBC, 0x1F, 0xBD, 0x1F, 0xBE, 0x1F, 0xBF, 0x1F, 0xC0, 0x1F, 0xC1, 0x1F, 0xC2, 0x1F, 0xC3, 0x1F, + 0xC4, 0x1F, 0xC5, 0x1F, 0xC6, 0x1F, 0xC7, 0x1F, 0xC8, 0x1F, 0xC9, 0x1F, 0xCA, 0x1F, 0xCB, 0x1F, + 0xC3, 0x1F, 0xCD, 0x1F, 0xCE, 0x1F, 0xCF, 0x1F, 0xD8, 0x1F, 0xD9, 0x1F, 0xD2, 0x1F, 0xD3, 0x1F, + 0xD4, 0x1F, 0xD5, 0x1F, 0xD6, 0x1F, 0xD7, 0x1F, 0xD8, 0x1F, 0xD9, 0x1F, 0xDA, 0x1F, 0xDB, 0x1F, + 0xDC, 0x1F, 0xDD, 0x1F, 0xDE, 0x1F, 0xDF, 0x1F, 0xE8, 0x1F, 0xE9, 0x1F, 0xE2, 0x1F, 0xE3, 0x1F, + 0xE4, 0x1F, 0xEC, 0x1F, 0xE6, 0x1F, 0xE7, 0x1F, 0xE8, 0x1F, 0xE9, 0x1F, 0xEA, 0x1F, 0xEB, 0x1F, + 0xEC, 0x1F, 0xED, 0x1F, 0xEE, 0x1F, 0xEF, 0x1F, 0xF0, 0x1F, 0xF1, 0x1F, 0xF2, 0x1F, 0xF3, 0x1F, + 0xF4, 0x1F, 0xF5, 0x1F, 0xF6, 0x1F, 0xF7, 0x1F, 0xF8, 0x1F, 0xF9, 0x1F, 0xFA, 0x1F, 0xFB, 0x1F, + 0xF3, 0x1F, 0xFD, 0x1F, 0xFE, 0x1F, 0xFF, 0x1F, 0x00, 0x20, 0x01, 0x20, 0x02, 0x20, 0x03, 0x20, + 0x04, 0x20, 0x05, 0x20, 0x06, 0x20, 0x07, 0x20, 0x08, 0x20, 0x09, 0x20, 0x0A, 0x20, 0x0B, 0x20, + 0x0C, 0x20, 0x0D, 0x20, 0x0E, 0x20, 0x0F, 0x20, 0x10, 0x20, 0x11, 0x20, 0x12, 0x20, 0x13, 0x20, + 0x14, 0x20, 0x15, 0x20, 0x16, 0x20, 0x17, 0x20, 0x18, 0x20, 0x19, 0x20, 0x1A, 0x20, 0x1B, 0x20, + 0x1C, 0x20, 0x1D, 0x20, 0x1E, 0x20, 0x1F, 0x20, 0x20, 0x20, 0x21, 0x20, 0x22, 0x20, 0x23, 0x20, + 0x24, 0x20, 0x25, 0x20, 0x26, 0x20, 0x27, 0x20, 0x28, 0x20, 0x29, 0x20, 0x2A, 0x20, 0x2B, 0x20, + 0x2C, 0x20, 0x2D, 0x20, 0x2E, 0x20, 0x2F, 0x20, 0x30, 0x20, 0x31, 0x20, 0x32, 0x20, 0x33, 0x20, + 0x34, 0x20, 0x35, 0x20, 0x36, 0x20, 0x37, 0x20, 0x38, 0x20, 0x39, 0x20, 0x3A, 0x20, 0x3B, 0x20, + 0x3C, 0x20, 0x3D, 0x20, 0x3E, 0x20, 0x3F, 0x20, 0x40, 0x20, 0x41, 0x20, 0x42, 0x20, 0x43, 0x20, + 0x44, 0x20, 0x45, 0x20, 0x46, 0x20, 0x47, 0x20, 0x48, 0x20, 0x49, 0x20, 0x4A, 0x20, 0x4B, 0x20, + 0x4C, 0x20, 0x4D, 0x20, 0x4E, 0x20, 0x4F, 0x20, 0x50, 0x20, 0x51, 0x20, 0x52, 0x20, 0x53, 0x20, + 0x54, 0x20, 0x55, 0x20, 0x56, 0x20, 0x57, 0x20, 0x58, 0x20, 0x59, 0x20, 0x5A, 0x20, 0x5B, 0x20, + 0x5C, 0x20, 0x5D, 0x20, 0x5E, 0x20, 0x5F, 0x20, 0x60, 0x20, 0x61, 0x20, 0x62, 0x20, 0x63, 0x20, + 0x64, 0x20, 0x65, 0x20, 0x66, 0x20, 0x67, 0x20, 0x68, 0x20, 0x69, 0x20, 0x6A, 0x20, 0x6B, 0x20, + 0x6C, 0x20, 0x6D, 0x20, 0x6E, 0x20, 0x6F, 0x20, 0x70, 0x20, 0x71, 0x20, 0x72, 0x20, 0x73, 0x20, + 0x74, 0x20, 0x75, 0x20, 0x76, 0x20, 0x77, 0x20, 0x78, 0x20, 0x79, 0x20, 0x7A, 0x20, 0x7B, 0x20, + 0x7C, 0x20, 0x7D, 0x20, 0x7E, 0x20, 0x7F, 0x20, 0x80, 0x20, 0x81, 0x20, 0x82, 0x20, 0x83, 0x20, + 0x84, 0x20, 0x85, 0x20, 0x86, 0x20, 0x87, 0x20, 0x88, 0x20, 0x89, 0x20, 0x8A, 0x20, 0x8B, 0x20, + 0x8C, 0x20, 0x8D, 0x20, 0x8E, 0x20, 0x8F, 0x20, 0x90, 0x20, 0x91, 0x20, 0x92, 0x20, 0x93, 0x20, + 0x94, 0x20, 0x95, 0x20, 0x96, 0x20, 0x97, 0x20, 0x98, 0x20, 0x99, 0x20, 0x9A, 0x20, 0x9B, 0x20, + 0x9C, 0x20, 0x9D, 0x20, 0x9E, 0x20, 0x9F, 0x20, 0xA0, 0x20, 0xA1, 0x20, 0xA2, 0x20, 0xA3, 0x20, + 0xA4, 0x20, 0xA5, 0x20, 0xA6, 0x20, 0xA7, 0x20, 0xA8, 0x20, 0xA9, 0x20, 0xAA, 0x20, 0xAB, 0x20, + 0xAC, 0x20, 0xAD, 0x20, 0xAE, 0x20, 0xAF, 0x20, 0xB0, 0x20, 0xB1, 0x20, 0xB2, 0x20, 0xB3, 0x20, + 0xB4, 0x20, 0xB5, 0x20, 0xB6, 0x20, 0xB7, 0x20, 0xB8, 0x20, 0xB9, 0x20, 0xBA, 0x20, 0xBB, 0x20, + 0xBC, 0x20, 0xBD, 0x20, 0xBE, 0x20, 0xBF, 0x20, 0xC0, 0x20, 0xC1, 0x20, 0xC2, 0x20, 0xC3, 0x20, + 0xC4, 0x20, 0xC5, 0x20, 0xC6, 0x20, 0xC7, 0x20, 0xC8, 0x20, 0xC9, 0x20, 0xCA, 0x20, 0xCB, 0x20, + 0xCC, 0x20, 0xCD, 0x20, 0xCE, 0x20, 0xCF, 0x20, 0xD0, 0x20, 0xD1, 0x20, 0xD2, 0x20, 0xD3, 0x20, + 0xD4, 0x20, 0xD5, 0x20, 0xD6, 0x20, 0xD7, 0x20, 0xD8, 0x20, 0xD9, 0x20, 0xDA, 0x20, 0xDB, 0x20, + 0xDC, 0x20, 0xDD, 0x20, 0xDE, 0x20, 0xDF, 0x20, 0xE0, 0x20, 0xE1, 0x20, 0xE2, 0x20, 0xE3, 0x20, + 0xE4, 0x20, 0xE5, 0x20, 0xE6, 0x20, 0xE7, 0x20, 0xE8, 0x20, 0xE9, 0x20, 0xEA, 0x20, 0xEB, 0x20, + 0xEC, 0x20, 0xED, 0x20, 0xEE, 0x20, 0xEF, 0x20, 0xF0, 0x20, 0xF1, 0x20, 0xF2, 0x20, 0xF3, 0x20, + 0xF4, 0x20, 0xF5, 0x20, 0xF6, 0x20, 0xF7, 0x20, 0xF8, 0x20, 0xF9, 0x20, 0xFA, 0x20, 0xFB, 0x20, + 0xFC, 0x20, 0xFD, 0x20, 0xFE, 0x20, 0xFF, 0x20, 0x00, 0x21, 0x01, 0x21, 0x02, 0x21, 0x03, 0x21, + 0x04, 0x21, 0x05, 0x21, 0x06, 0x21, 0x07, 0x21, 0x08, 0x21, 0x09, 0x21, 0x0A, 0x21, 0x0B, 0x21, + 0x0C, 0x21, 0x0D, 0x21, 0x0E, 0x21, 0x0F, 0x21, 0x10, 0x21, 0x11, 0x21, 0x12, 0x21, 0x13, 0x21, + 0x14, 0x21, 0x15, 0x21, 0x16, 0x21, 0x17, 0x21, 0x18, 0x21, 0x19, 0x21, 0x1A, 0x21, 0x1B, 0x21, + 0x1C, 0x21, 0x1D, 0x21, 0x1E, 0x21, 0x1F, 0x21, 0x20, 0x21, 0x21, 0x21, 0x22, 0x21, 0x23, 0x21, + 0x24, 0x21, 0x25, 0x21, 0x26, 0x21, 0x27, 0x21, 0x28, 0x21, 0x29, 0x21, 0x2A, 0x21, 0x2B, 0x21, + 0x2C, 0x21, 0x2D, 0x21, 0x2E, 0x21, 0x2F, 0x21, 0x30, 0x21, 0x31, 0x21, 0x32, 0x21, 0x33, 0x21, + 0x34, 0x21, 0x35, 0x21, 0x36, 0x21, 0x37, 0x21, 0x38, 0x21, 0x39, 0x21, 0x3A, 0x21, 0x3B, 0x21, + 0x3C, 0x21, 0x3D, 0x21, 0x3E, 0x21, 0x3F, 0x21, 0x40, 0x21, 0x41, 0x21, 0x42, 0x21, 0x43, 0x21, + 0x44, 0x21, 0x45, 0x21, 0x46, 0x21, 0x47, 0x21, 0x48, 0x21, 0x49, 0x21, 0x4A, 0x21, 0x4B, 0x21, + 0x4C, 0x21, 0x4D, 0x21, 0x32, 0x21, 0x4F, 0x21, 0x50, 0x21, 0x51, 0x21, 0x52, 0x21, 0x53, 0x21, + 0x54, 0x21, 0x55, 0x21, 0x56, 0x21, 0x57, 0x21, 0x58, 0x21, 0x59, 0x21, 0x5A, 0x21, 0x5B, 0x21, + 0x5C, 0x21, 0x5D, 0x21, 0x5E, 0x21, 0x5F, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, 0x60, 0x21, 0x61, 0x21, 0x62, 0x21, 0x63, 0x21, + 0x64, 0x21, 0x65, 0x21, 0x66, 0x21, 0x67, 0x21, 0x68, 0x21, 0x69, 0x21, 0x6A, 0x21, 0x6B, 0x21, + 0x6C, 0x21, 0x6D, 0x21, 0x6E, 0x21, 0x6F, 0x21, 0x80, 0x21, 0x81, 0x21, 0x82, 0x21, 0x83, 0x21, + 0x83, 0x21, 0xFF, 0xFF, 0x4B, 0x03, 0xB6, 0x24, 0xB7, 0x24, 0xB8, 0x24, 0xB9, 0x24, 0xBA, 0x24, + 0xBB, 0x24, 0xBC, 0x24, 0xBD, 0x24, 0xBE, 0x24, 0xBF, 0x24, 0xC0, 0x24, 0xC1, 0x24, 0xC2, 0x24, + 0xC3, 0x24, 0xC4, 0x24, 0xC5, 0x24, 0xC6, 0x24, 0xC7, 0x24, 0xC8, 0x24, 0xC9, 0x24, 0xCA, 0x24, + 0xCB, 0x24, 0xCC, 0x24, 0xCD, 0x24, 0xCE, 0x24, 0xCF, 0x24, 0xFF, 0xFF, 0x46, 0x07, 0x00, 0x2C, + 0x01, 0x2C, 0x02, 0x2C, 0x03, 0x2C, 0x04, 0x2C, 0x05, 0x2C, 0x06, 0x2C, 0x07, 0x2C, 0x08, 0x2C, + 0x09, 0x2C, 0x0A, 0x2C, 0x0B, 0x2C, 0x0C, 0x2C, 0x0D, 0x2C, 0x0E, 0x2C, 0x0F, 0x2C, 0x10, 0x2C, + 0x11, 0x2C, 0x12, 0x2C, 0x13, 0x2C, 0x14, 0x2C, 0x15, 0x2C, 0x16, 0x2C, 0x17, 0x2C, 0x18, 0x2C, + 0x19, 0x2C, 0x1A, 0x2C, 0x1B, 0x2C, 0x1C, 0x2C, 0x1D, 0x2C, 0x1E, 0x2C, 0x1F, 0x2C, 0x20, 0x2C, + 0x21, 0x2C, 0x22, 0x2C, 0x23, 0x2C, 0x24, 0x2C, 0x25, 0x2C, 0x26, 0x2C, 0x27, 0x2C, 0x28, 0x2C, + 0x29, 0x2C, 0x2A, 0x2C, 0x2B, 0x2C, 0x2C, 0x2C, 0x2D, 0x2C, 0x2E, 0x2C, 0x5F, 0x2C, 0x60, 0x2C, + 0x60, 0x2C, 0x62, 0x2C, 0x63, 0x2C, 0x64, 0x2C, 0x65, 0x2C, 0x66, 0x2C, 0x67, 0x2C, 0x67, 0x2C, + 0x69, 0x2C, 0x69, 0x2C, 0x6B, 0x2C, 0x6B, 0x2C, 0x6D, 0x2C, 0x6E, 0x2C, 0x6F, 0x2C, 0x70, 0x2C, + 0x71, 0x2C, 0x72, 0x2C, 0x73, 0x2C, 0x74, 0x2C, 0x75, 0x2C, 0x75, 0x2C, 0x77, 0x2C, 0x78, 0x2C, + 0x79, 0x2C, 0x7A, 0x2C, 0x7B, 0x2C, 0x7C, 0x2C, 0x7D, 0x2C, 0x7E, 0x2C, 0x7F, 0x2C, 0x80, 0x2C, + 0x80, 0x2C, 0x82, 0x2C, 0x82, 0x2C, 0x84, 0x2C, 0x84, 0x2C, 0x86, 0x2C, 0x86, 0x2C, 0x88, 0x2C, + 0x88, 0x2C, 0x8A, 0x2C, 0x8A, 0x2C, 0x8C, 0x2C, 0x8C, 0x2C, 0x8E, 0x2C, 0x8E, 0x2C, 0x90, 0x2C, + 0x90, 0x2C, 0x92, 0x2C, 0x92, 0x2C, 0x94, 0x2C, 0x94, 0x2C, 0x96, 0x2C, 0x96, 0x2C, 0x98, 0x2C, + 0x98, 0x2C, 0x9A, 0x2C, 0x9A, 0x2C, 0x9C, 0x2C, 0x9C, 0x2C, 0x9E, 0x2C, 0x9E, 0x2C, 0xA0, 0x2C, + 0xA0, 0x2C, 0xA2, 0x2C, 0xA2, 0x2C, 0xA4, 0x2C, 0xA4, 0x2C, 0xA6, 0x2C, 0xA6, 0x2C, 0xA8, 0x2C, + 0xA8, 0x2C, 0xAA, 0x2C, 0xAA, 0x2C, 0xAC, 0x2C, 0xAC, 0x2C, 0xAE, 0x2C, 0xAE, 0x2C, 0xB0, 0x2C, + 0xB0, 0x2C, 0xB2, 0x2C, 0xB2, 0x2C, 0xB4, 0x2C, 0xB4, 0x2C, 0xB6, 0x2C, 0xB6, 0x2C, 0xB8, 0x2C, + 0xB8, 0x2C, 0xBA, 0x2C, 0xBA, 0x2C, 0xBC, 0x2C, 0xBC, 0x2C, 0xBE, 0x2C, 0xBE, 0x2C, 0xC0, 0x2C, + 0xC0, 0x2C, 0xC2, 0x2C, 0xC2, 0x2C, 0xC4, 0x2C, 0xC4, 0x2C, 0xC6, 0x2C, 0xC6, 0x2C, 0xC8, 0x2C, + 0xC8, 0x2C, 0xCA, 0x2C, 0xCA, 0x2C, 0xCC, 0x2C, 0xCC, 0x2C, 0xCE, 0x2C, 0xCE, 0x2C, 0xD0, 0x2C, + 0xD0, 0x2C, 0xD2, 0x2C, 0xD2, 0x2C, 0xD4, 0x2C, 0xD4, 0x2C, 0xD6, 0x2C, 0xD6, 0x2C, 0xD8, 0x2C, + 0xD8, 0x2C, 0xDA, 0x2C, 0xDA, 0x2C, 0xDC, 0x2C, 0xDC, 0x2C, 0xDE, 0x2C, 0xDE, 0x2C, 0xE0, 0x2C, + 0xE0, 0x2C, 0xE2, 0x2C, 0xE2, 0x2C, 0xE4, 0x2C, 0xE5, 0x2C, 0xE6, 0x2C, 0xE7, 0x2C, 0xE8, 0x2C, + 0xE9, 0x2C, 0xEA, 0x2C, 0xEB, 0x2C, 0xEC, 0x2C, 0xED, 0x2C, 0xEE, 0x2C, 0xEF, 0x2C, 0xF0, 0x2C, + 0xF1, 0x2C, 0xF2, 0x2C, 0xF3, 0x2C, 0xF4, 0x2C, 0xF5, 0x2C, 0xF6, 0x2C, 0xF7, 0x2C, 0xF8, 0x2C, + 0xF9, 0x2C, 0xFA, 0x2C, 0xFB, 0x2C, 0xFC, 0x2C, 0xFD, 0x2C, 0xFE, 0x2C, 0xFF, 0x2C, 0xA0, 0x10, + 0xA1, 0x10, 0xA2, 0x10, 0xA3, 0x10, 0xA4, 0x10, 0xA5, 0x10, 0xA6, 0x10, 0xA7, 0x10, 0xA8, 0x10, + 0xA9, 0x10, 0xAA, 0x10, 0xAB, 0x10, 0xAC, 0x10, 0xAD, 0x10, 0xAE, 0x10, 0xAF, 0x10, 0xB0, 0x10, + 0xB1, 0x10, 0xB2, 0x10, 0xB3, 0x10, 0xB4, 0x10, 0xB5, 0x10, 0xB6, 0x10, 0xB7, 0x10, 0xB8, 0x10, + 0xB9, 0x10, 0xBA, 0x10, 0xBB, 0x10, 0xBC, 0x10, 0xBD, 0x10, 0xBE, 0x10, 0xBF, 0x10, 0xC0, 0x10, + 0xC1, 0x10, 0xC2, 0x10, 0xC3, 0x10, 0xC4, 0x10, 0xC5, 0x10, 0xFF, 0xFF, 0x1B, 0xD2, 0x21, 0xFF, + 0x22, 0xFF, 0x23, 0xFF, 0x24, 0xFF, 0x25, 0xFF, 0x26, 0xFF, 0x27, 0xFF, 0x28, 0xFF, 0x29, 0xFF, + 0x2A, 0xFF, 0x2B, 0xFF, 0x2C, 0xFF, 0x2D, 0xFF, 0x2E, 0xFF, 0x2F, 0xFF, 0x30, 0xFF, 0x31, 0xFF, + 0x32, 0xFF, 0x33, 0xFF, 0x34, 0xFF, 0x35, 0xFF, 0x36, 0xFF, 0x37, 0xFF, 0x38, 0xFF, 0x39, 0xFF, + 0x3A, 0xFF, 0x5B, 0xFF, 0x5C, 0xFF, 0x5D, 0xFF, 0x5E, 0xFF, 0x5F, 0xFF, 0x60, 0xFF, 0x61, 0xFF, + 0x62, 0xFF, 0x63, 0xFF, 0x64, 0xFF, 0x65, 0xFF, 0x66, 0xFF, 0x67, 0xFF, 0x68, 0xFF, 0x69, 0xFF, + 0x6A, 0xFF, 0x6B, 0xFF, 0x6C, 0xFF, 0x6D, 0xFF, 0x6E, 0xFF, 0x6F, 0xFF, 0x70, 0xFF, 0x71, 0xFF, + 0x72, 0xFF, 0x73, 0xFF, 0x74, 0xFF, 0x75, 0xFF, 0x76, 0xFF, 0x77, 0xFF, 0x78, 0xFF, 0x79, 0xFF, + 0x7A, 0xFF, 0x7B, 0xFF, 0x7C, 0xFF, 0x7D, 0xFF, 0x7E, 0xFF, 0x7F, 0xFF, 0x80, 0xFF, 0x81, 0xFF, + 0x82, 0xFF, 0x83, 0xFF, 0x84, 0xFF, 0x85, 0xFF, 0x86, 0xFF, 0x87, 0xFF, 0x88, 0xFF, 0x89, 0xFF, + 0x8A, 0xFF, 0x8B, 0xFF, 0x8C, 0xFF, 0x8D, 0xFF, 0x8E, 0xFF, 0x8F, 0xFF, 0x90, 0xFF, 0x91, 0xFF, + 0x92, 0xFF, 0x93, 0xFF, 0x94, 0xFF, 0x95, 0xFF, 0x96, 0xFF, 0x97, 0xFF, 0x98, 0xFF, 0x99, 0xFF, + 0x9A, 0xFF, 0x9B, 0xFF, 0x9C, 0xFF, 0x9D, 0xFF, 0x9E, 0xFF, 0x9F, 0xFF, 0xA0, 0xFF, 0xA1, 0xFF, + 0xA2, 0xFF, 0xA3, 0xFF, 0xA4, 0xFF, 0xA5, 0xFF, 0xA6, 0xFF, 0xA7, 0xFF, 0xA8, 0xFF, 0xA9, 0xFF, + 0xAA, 0xFF, 0xAB, 0xFF, 0xAC, 0xFF, 0xAD, 0xFF, 0xAE, 0xFF, 0xAF, 0xFF, 0xB0, 0xFF, 0xB1, 0xFF, + 0xB2, 0xFF, 0xB3, 0xFF, 0xB4, 0xFF, 0xB5, 0xFF, 0xB6, 0xFF, 0xB7, 0xFF, 0xB8, 0xFF, 0xB9, 0xFF, + 0xBA, 0xFF, 0xBB, 0xFF, 0xBC, 0xFF, 0xBD, 0xFF, 0xBE, 0xFF, 0xBF, 0xFF, 0xC0, 0xFF, 0xC1, 0xFF, + 0xC2, 0xFF, 0xC3, 0xFF, 0xC4, 0xFF, 0xC5, 0xFF, 0xC6, 0xFF, 0xC7, 0xFF, 0xC8, 0xFF, 0xC9, 0xFF, + 0xCA, 0xFF, 0xCB, 0xFF, 0xCC, 0xFF, 0xCD, 0xFF, 0xCE, 0xFF, 0xCF, 0xFF, 0xD0, 0xFF, 0xD1, 0xFF, + 0xD2, 0xFF, 0xD3, 0xFF, 0xD4, 0xFF, 0xD5, 0xFF, 0xD6, 0xFF, 0xD7, 0xFF, 0xD8, 0xFF, 0xD9, 0xFF, + 0xDA, 0xFF, 0xDB, 0xFF, 0xDC, 0xFF, 0xDD, 0xFF, 0xDE, 0xFF, 0xDF, 0xFF, 0xE0, 0xFF, 0xE1, 0xFF, + 0xE2, 0xFF, 0xE3, 0xFF, 0xE4, 0xFF, 0xE5, 0xFF, 0xE6, 0xFF, 0xE7, 0xFF, 0xE8, 0xFF, 0xE9, 0xFF, + 0xEA, 0xFF, 0xEB, 0xFF, 0xEC, 0xFF, 0xED, 0xFF, 0xEE, 0xFF, 0xEF, 0xFF, 0xF0, 0xFF, 0xF1, 0xFF, + 0xF2, 0xFF, 0xF3, 0xFF, 0xF4, 0xFF, 0xF5, 0xFF, 0xF6, 0xFF, 0xF7, 0xFF, 0xF8, 0xFF, 0xF9, 0xFF, + 0xFA, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF +}; + +/* end of exfat_upcase.c */ diff --git a/fs/exfat/exfat_version.h b/fs/exfat/exfat_version.h new file mode 100644 index 00000000000..44289678311 --- /dev/null +++ b/fs/exfat/exfat_version.h @@ -0,0 +1,19 @@ +/************************************************************************/ +/* */ +/* PROJECT : exFAT & FAT12/16/32 File System */ +/* FILE : exfat_version.h */ +/* PURPOSE : exFAT File Manager */ +/* */ +/*----------------------------------------------------------------------*/ +/* NOTES */ +/* */ +/*----------------------------------------------------------------------*/ +/* REVISION HISTORY */ +/* */ +/* - 2012.02.10 : Release Version 1.1.0 */ +/* - 2012.04.02 : P1 : Change Module License to Samsung Proprietary */ +/* - 2012.06.07 : P2 : Fixed incorrect filename problem */ +/* */ +/************************************************************************/ + +#define EXFAT_VERSION "1.2.5" diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index abcdeab67f5..e2108c76b3f 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c @@ -2208,10 +2208,13 @@ static int ext4_remove_blocks(handle_t *handle, struct inode *inode, struct ext4_sb_info *sbi = EXT4_SB(inode->i_sb); unsigned short ee_len = ext4_ext_get_actual_len(ex); ext4_fsblk_t pblk; - int flags = EXT4_FREE_BLOCKS_FORGET; + int flags = 0; if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode)) - flags |= EXT4_FREE_BLOCKS_METADATA; + flags |= EXT4_FREE_BLOCKS_METADATA | EXT4_FREE_BLOCKS_FORGET; + else if (ext4_should_journal_data(inode)) + flags |= EXT4_FREE_BLOCKS_FORGET; + /* * For bigalloc file systems, we never free a partial cluster * at the beginning of the extent. Instead, we make a note diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index e99ad778173..578c8060da2 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -37,6 +37,7 @@ #include #include #include +#include #include "ext4_jbd2.h" #include "xattr.h" @@ -3562,18 +3563,20 @@ int ext4_get_inode_loc(struct inode *inode, struct ext4_iloc *iloc) void ext4_set_inode_flags(struct inode *inode) { unsigned int flags = EXT4_I(inode)->i_flags; + unsigned int new_fl = 0; - inode->i_flags &= ~(S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC); if (flags & EXT4_SYNC_FL) - inode->i_flags |= S_SYNC; + new_fl |= S_SYNC; if (flags & EXT4_APPEND_FL) - inode->i_flags |= S_APPEND; + new_fl |= S_APPEND; if (flags & EXT4_IMMUTABLE_FL) - inode->i_flags |= S_IMMUTABLE; + new_fl |= S_IMMUTABLE; if (flags & EXT4_NOATIME_FL) - inode->i_flags |= S_NOATIME; + new_fl |= S_NOATIME; if (flags & EXT4_DIRSYNC_FL) - inode->i_flags |= S_DIRSYNC; + new_fl |= S_DIRSYNC; + set_mask_bits(&inode->i_flags, + S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC, new_fl); } /* Propagate flags from i_flags to EXT4_I(inode)->i_flags */ diff --git a/fs/f2fs/Kconfig b/fs/f2fs/Kconfig new file mode 100644 index 00000000000..1b2379b566a --- /dev/null +++ b/fs/f2fs/Kconfig @@ -0,0 +1,73 @@ +config F2FS_FS + tristate "F2FS filesystem support (EXPERIMENTAL)" + depends on BLOCK + help + F2FS is based on Log-structured File System (LFS), which supports + versatile "flash-friendly" features. The design has been focused on + addressing the fundamental issues in LFS, which are snowball effect + of wandering tree and high cleaning overhead. + + Since flash-based storages show different characteristics according to + the internal geometry or flash memory management schemes aka FTL, F2FS + and tools support various parameters not only for configuring on-disk + layout, but also for selecting allocation and cleaning algorithms. + + If unsure, say N. + +config F2FS_STAT_FS + bool "F2FS Status Information" + depends on F2FS_FS && DEBUG_FS + default y + help + /sys/./debug/f2fs/ contains information about all the partitions + mounted as f2fs. Each file shows the whole f2fs information. + + /sys/./debug/f2fs/status includes: + - major file system information managed by f2fs currently + - average SIT information about whole segments + - current memory footprint consumed by f2fs. + +config F2FS_FS_XATTR + bool "F2FS extended attributes" + depends on F2FS_FS + default y + help + Extended attributes are name:value pairs associated with inodes by + the . or by users (see the attr(5) manual page, or visit + for details). + + If unsure, say N. + +config F2FS_FS_POSIX_ACL + bool "F2FS Access Control Lists" + depends on F2FS_FS_XATTR + select FS_POSIX_ACL + default y + help + Posix Access Control Lists (ACLs) support permissions for users and + gourps beyond the owner/group/world scheme. + + To learn more about Access Control Lists, visit the POSIX ACLs for + Linux website . + + If you don't know what Access Control Lists are, say N + +config F2FS_FS_SECURITY + bool "F2FS Security Labels" + depends on F2FS_FS_XATTR + help + Security labels provide an access control facility to support Linux + Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO + Linux. This option enables an extended attribute handler for file + security labels in the f2fs filesystem, so that it requires enabling + the extended attribute support in advance. + + If you are not using a security module, say N. + +config F2FS_CHECK_FS + bool "F2FS consistency checking feature" + depends on F2FS_FS + help + Enables BUG_ONs which check the file system consistency in runtime. + + If you want to improve the performance, say N. diff --git a/fs/f2fs/Makefile b/fs/f2fs/Makefile new file mode 100644 index 00000000000..2e35da12d29 --- /dev/null +++ b/fs/f2fs/Makefile @@ -0,0 +1,7 @@ +obj-$(CONFIG_F2FS_FS) += f2fs.o + +f2fs-y := dir.o file.o inode.o namei.o hash.o super.o inline.o +f2fs-y += checkpoint.o gc.o data.o node.o segment.o recovery.o +f2fs-$(CONFIG_F2FS_STAT_FS) += debug.o +f2fs-$(CONFIG_F2FS_FS_XATTR) += xattr.o +f2fs-$(CONFIG_F2FS_FS_POSIX_ACL) += acl.o diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c new file mode 100644 index 00000000000..d7cb81ff513 --- /dev/null +++ b/fs/f2fs/acl.c @@ -0,0 +1,284 @@ +/* + * fs/f2fs/acl.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Portions of this code from linux/fs/ext2/acl.c + * + * Copyright (C) 2001-2003 Andreas Gruenbacher, + * + * 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 "f2fs.h" +#include "xattr.h" +#include "acl.h" + +static inline size_t f2fs_acl_size(int count) +{ + if (count <= 4) { + return sizeof(struct f2fs_acl_header) + + count * sizeof(struct f2fs_acl_entry_short); + } else { + return sizeof(struct f2fs_acl_header) + + 4 * sizeof(struct f2fs_acl_entry_short) + + (count - 4) * sizeof(struct f2fs_acl_entry); + } +} + +static inline int f2fs_acl_count(size_t size) +{ + ssize_t s; + size -= sizeof(struct f2fs_acl_header); + s = size - 4 * sizeof(struct f2fs_acl_entry_short); + if (s < 0) { + if (size % sizeof(struct f2fs_acl_entry_short)) + return -1; + return size / sizeof(struct f2fs_acl_entry_short); + } else { + if (s % sizeof(struct f2fs_acl_entry)) + return -1; + return s / sizeof(struct f2fs_acl_entry) + 4; + } +} + +static struct posix_acl *f2fs_acl_from_disk(const char *value, size_t size) +{ + int i, count; + struct posix_acl *acl; + struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value; + struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr + 1); + const char *end = value + size; + + if (hdr->a_version != cpu_to_le32(F2FS_ACL_VERSION)) + return ERR_PTR(-EINVAL); + + count = f2fs_acl_count(size); + if (count < 0) + return ERR_PTR(-EINVAL); + if (count == 0) + return NULL; + + acl = posix_acl_alloc(count, GFP_KERNEL); + if (!acl) + return ERR_PTR(-ENOMEM); + + for (i = 0; i < count; i++) { + + if ((char *)entry > end) + goto fail; + + acl->a_entries[i].e_tag = le16_to_cpu(entry->e_tag); + acl->a_entries[i].e_perm = le16_to_cpu(entry->e_perm); + + switch (acl->a_entries[i].e_tag) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + entry = (struct f2fs_acl_entry *)((char *)entry + + sizeof(struct f2fs_acl_entry_short)); + break; + + case ACL_USER: + case ACL_GROUP: + acl->a_entries[i].e_id = le32_to_cpu(entry->e_id); + entry = (struct f2fs_acl_entry *)((char *)entry + + sizeof(struct f2fs_acl_entry)); + break; + default: + goto fail; + } + } + if ((char *)entry != end) + goto fail; + return acl; +fail: + posix_acl_release(acl); + return ERR_PTR(-EINVAL); +} + +static void *f2fs_acl_to_disk(const struct posix_acl *acl, size_t *size) +{ + struct f2fs_acl_header *f2fs_acl; + struct f2fs_acl_entry *entry; + int i; + + f2fs_acl = kmalloc(sizeof(struct f2fs_acl_header) + acl->a_count * + sizeof(struct f2fs_acl_entry), GFP_KERNEL); + if (!f2fs_acl) + return ERR_PTR(-ENOMEM); + + f2fs_acl->a_version = cpu_to_le32(F2FS_ACL_VERSION); + entry = (struct f2fs_acl_entry *)(f2fs_acl + 1); + + for (i = 0; i < acl->a_count; i++) { + + entry->e_tag = cpu_to_le16(acl->a_entries[i].e_tag); + entry->e_perm = cpu_to_le16(acl->a_entries[i].e_perm); + + switch (acl->a_entries[i].e_tag) { + case ACL_USER: + case ACL_GROUP: + entry->e_id = cpu_to_le32(acl->a_entries[i].e_id); + entry = (struct f2fs_acl_entry *)((char *)entry + + sizeof(struct f2fs_acl_entry)); + break; + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + entry = (struct f2fs_acl_entry *)((char *)entry + + sizeof(struct f2fs_acl_entry_short)); + break; + default: + goto fail; + } + } + *size = f2fs_acl_size(acl->a_count); + return (void *)f2fs_acl; + +fail: + kfree(f2fs_acl); + return ERR_PTR(-EINVAL); +} + +struct posix_acl *f2fs_get_acl(struct inode *inode, int type) +{ + int name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; + void *value = NULL; + struct posix_acl *acl; + int retval; + + if (type == ACL_TYPE_ACCESS) + name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; + + retval = f2fs_getxattr(inode, name_index, "", NULL, 0); + if (retval > 0) { + value = kmalloc(retval, GFP_F2FS_ZERO); + if (!value) + return ERR_PTR(-ENOMEM); + retval = f2fs_getxattr(inode, name_index, "", value, retval); + } + + if (retval > 0) + acl = f2fs_acl_from_disk(value, retval); + else if (retval == -ENODATA) + acl = NULL; + else + acl = ERR_PTR(retval); + kfree(value); + + if (!IS_ERR(acl)) + set_cached_acl(inode, type, acl); + + return acl; +} + +static int __f2fs_set_acl(struct inode *inode, int type, + struct posix_acl *acl, struct page *ipage) +{ + struct f2fs_inode_info *fi = F2FS_I(inode); + int name_index; + void *value = NULL; + size_t size = 0; + int error; + + switch (type) { + case ACL_TYPE_ACCESS: + name_index = F2FS_XATTR_INDEX_POSIX_ACL_ACCESS; + if (acl) { + error = posix_acl_equiv_mode(acl, &inode->i_mode); + if (error < 0) + return error; + set_acl_inode(fi, inode->i_mode); + if (error == 0) + acl = NULL; + } + break; + + case ACL_TYPE_DEFAULT: + name_index = F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT; + if (!S_ISDIR(inode->i_mode)) + return acl ? -EACCES : 0; + break; + + default: + return -EINVAL; + } + + if (acl) { + value = f2fs_acl_to_disk(acl, &size); + if (IS_ERR(value)) { + cond_clear_inode_flag(fi, FI_ACL_MODE); + return (int)PTR_ERR(value); + } + } + + error = f2fs_setxattr(inode, name_index, "", value, size, ipage, 0); + + kfree(value); + if (!error) + set_cached_acl(inode, type, acl); + + cond_clear_inode_flag(fi, FI_ACL_MODE); + return error; +} + +int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type) +{ + return __f2fs_set_acl(inode, type, acl, NULL); +} + +int f2fs_init_acl(struct inode *inode, struct inode *dir, struct page *ipage) +{ + struct posix_acl *default_acl, *acl; + int error = 0; + + error = posix_acl_create(dir, &inode->i_mode, &default_acl, &acl); + if (error) + return error; + + if (default_acl) { + error = __f2fs_set_acl(inode, ACL_TYPE_DEFAULT, default_acl, + ipage); + posix_acl_release(default_acl); + } + if (acl) { + if (error) + error = __f2fs_set_acl(inode, ACL_TYPE_ACCESS, acl, + ipage); + posix_acl_release(acl); + } + + return error; +} + +int f2fs_android_emu(struct f2fs_sb_info *sbi, struct inode *inode, + u32 *uid, u32 *gid, umode_t *mode) +{ + F2FS_I(inode)->i_advise |= FADVISE_ANDROID_EMU; + + if (uid) + *uid = sbi->android_emu_uid; + if (gid) + *gid = sbi->android_emu_gid; + if (mode) { + *mode = (*mode & ~S_IRWXUGO) | sbi->android_emu_mode; + if (F2FS_I(inode)->i_advise & FADVISE_ANDROID_EMU_ROOT) + *mode &= ~S_IRWXO; + if (S_ISDIR(*mode)) { + if (*mode & S_IRUSR) + *mode |= S_IXUSR; + if (*mode & S_IRGRP) + *mode |= S_IXGRP; + if (*mode & S_IROTH) + *mode |= S_IXOTH; + } + } + + return 0; +} diff --git a/fs/f2fs/acl.h b/fs/f2fs/acl.h new file mode 100644 index 00000000000..e0864651cdc --- /dev/null +++ b/fs/f2fs/acl.h @@ -0,0 +1,53 @@ +/* + * fs/f2fs/acl.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Portions of this code from linux/fs/ext2/acl.h + * + * Copyright (C) 2001-2003 Andreas Gruenbacher, + * + * 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 __F2FS_ACL_H__ +#define __F2FS_ACL_H__ + +#include + +#define F2FS_ACL_VERSION 0x0001 + +struct f2fs_acl_entry { + __le16 e_tag; + __le16 e_perm; + __le32 e_id; +}; + +struct f2fs_acl_entry_short { + __le16 e_tag; + __le16 e_perm; +}; + +struct f2fs_acl_header { + __le32 a_version; +}; + +#ifdef CONFIG_F2FS_FS_POSIX_ACL + +extern struct posix_acl *f2fs_get_acl(struct inode *, int); +extern int f2fs_set_acl(struct inode *inode, struct posix_acl *acl, int type); +extern int f2fs_init_acl(struct inode *, struct inode *, struct page *); +#else +#define f2fs_check_acl NULL +#define f2fs_get_acl NULL +#define f2fs_set_acl NULL + +static inline int f2fs_init_acl(struct inode *inode, struct inode *dir, + struct page *page) +{ + return 0; +} +#endif +#endif /* __F2FS_ACL_H__ */ diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c new file mode 100644 index 00000000000..e24a06f9dfa --- /dev/null +++ b/fs/f2fs/checkpoint.c @@ -0,0 +1,986 @@ +/* + * fs/f2fs/checkpoint.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" +#include "segment.h" +#include + +static struct kmem_cache *orphan_entry_slab; +static struct kmem_cache *inode_entry_slab; + +/* + * We guarantee no failure on the returned page. + */ +struct page *grab_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) +{ + struct address_space *mapping = META_MAPPING(sbi); + struct page *page = NULL; +repeat: + page = grab_cache_page(mapping, index); + if (!page) { + cond_resched(); + goto repeat; + } + f2fs_wait_on_page_writeback(page, META); + SetPageUptodate(page); + return page; +} + +/* + * We guarantee no failure on the returned page. + */ +struct page *get_meta_page(struct f2fs_sb_info *sbi, pgoff_t index) +{ + struct address_space *mapping = META_MAPPING(sbi); + struct page *page; +repeat: + page = grab_cache_page(mapping, index); + if (!page) { + cond_resched(); + goto repeat; + } + if (PageUptodate(page)) + goto out; + + if (f2fs_submit_page_bio(sbi, page, index, + READ_SYNC | REQ_META | REQ_PRIO)) + goto repeat; + + lock_page(page); + if (unlikely(page->mapping != mapping)) { + f2fs_put_page(page, 1); + goto repeat; + } +out: + mark_page_accessed(page); + return page; +} + +static inline int get_max_meta_blks(struct f2fs_sb_info *sbi, int type) +{ + switch (type) { + case META_NAT: + return NM_I(sbi)->max_nid / NAT_ENTRY_PER_BLOCK; + case META_SIT: + return SIT_BLK_CNT(sbi); + case META_SSA: + case META_CP: + return 0; + default: + BUG(); + } +} + +/* + * Readahead CP/NAT/SIT/SSA pages + */ +int ra_meta_pages(struct f2fs_sb_info *sbi, int start, int nrpages, int type) +{ + block_t prev_blk_addr = 0; + struct page *page; + int blkno = start; + int max_blks = get_max_meta_blks(sbi, type); + + struct f2fs_io_info fio = { + .type = META, + .rw = READ_SYNC | REQ_META | REQ_PRIO + }; + + for (; nrpages-- > 0; blkno++) { + block_t blk_addr; + + switch (type) { + case META_NAT: + /* get nat block addr */ + if (unlikely(blkno >= max_blks)) + blkno = 0; + blk_addr = current_nat_addr(sbi, + blkno * NAT_ENTRY_PER_BLOCK); + break; + case META_SIT: + /* get sit block addr */ + if (unlikely(blkno >= max_blks)) + goto out; + blk_addr = current_sit_addr(sbi, + blkno * SIT_ENTRY_PER_BLOCK); + if (blkno != start && prev_blk_addr + 1 != blk_addr) + goto out; + prev_blk_addr = blk_addr; + break; + case META_SSA: + case META_CP: + /* get ssa/cp block addr */ + blk_addr = blkno; + break; + default: + BUG(); + } + + page = grab_cache_page(META_MAPPING(sbi), blk_addr); + if (!page) + continue; + if (PageUptodate(page)) { + mark_page_accessed(page); + f2fs_put_page(page, 1); + continue; + } + + f2fs_submit_page_mbio(sbi, page, blk_addr, &fio); + mark_page_accessed(page); + f2fs_put_page(page, 0); + } +out: + f2fs_submit_merged_bio(sbi, META, READ); + return blkno - start; +} + +static int f2fs_write_meta_page(struct page *page, + struct writeback_control *wbc) +{ + struct inode *inode = page->mapping->host; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + + trace_f2fs_writepage(page, META); + + if (unlikely(sbi->por_doing)) + goto redirty_out; + if (wbc->for_reclaim) + goto redirty_out; + + /* Should not write any meta pages, if any IO error was occurred */ + if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG))) + goto no_write; + + f2fs_wait_on_page_writeback(page, META); + write_meta_page(sbi, page); +no_write: + dec_page_count(sbi, F2FS_DIRTY_META); + unlock_page(page); + return 0; + +redirty_out: + redirty_page_for_writepage(wbc, page); + return AOP_WRITEPAGE_ACTIVATE; +} + +static int f2fs_write_meta_pages(struct address_space *mapping, + struct writeback_control *wbc) +{ + struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); + long diff, written; + + trace_f2fs_writepages(mapping->host, wbc, META); + + /* collect a number of dirty meta pages and write together */ + if (wbc->for_kupdate || + get_pages(sbi, F2FS_DIRTY_META) < nr_pages_to_skip(sbi, META)) + goto skip_write; + + /* if mounting is failed, skip writing node pages */ + mutex_lock(&sbi->cp_mutex); + diff = nr_pages_to_write(sbi, META, wbc); + written = sync_meta_pages(sbi, META, wbc->nr_to_write); + mutex_unlock(&sbi->cp_mutex); + wbc->nr_to_write = max((long)0, wbc->nr_to_write - written - diff); + return 0; + +skip_write: + wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_META); + return 0; +} + +long sync_meta_pages(struct f2fs_sb_info *sbi, enum page_type type, + long nr_to_write) +{ + struct address_space *mapping = META_MAPPING(sbi); + pgoff_t index = 0, end = LONG_MAX; + struct pagevec pvec; + long nwritten = 0; + struct writeback_control wbc = { + .for_reclaim = 0, + }; + + pagevec_init(&pvec, 0); + + while (index <= end) { + int i, nr_pages; + nr_pages = pagevec_lookup_tag(&pvec, mapping, &index, + PAGECACHE_TAG_DIRTY, + min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); + if (unlikely(nr_pages == 0)) + break; + + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + + lock_page(page); + + if (unlikely(page->mapping != mapping)) { +continue_unlock: + unlock_page(page); + continue; + } + if (!PageDirty(page)) { + /* someone wrote it for us */ + goto continue_unlock; + } + + if (!clear_page_dirty_for_io(page)) + goto continue_unlock; + + if (f2fs_write_meta_page(page, &wbc)) { + unlock_page(page); + break; + } + nwritten++; + if (unlikely(nwritten >= nr_to_write)) + break; + } + pagevec_release(&pvec); + cond_resched(); + } + + if (nwritten) + f2fs_submit_merged_bio(sbi, type, WRITE); + + return nwritten; +} + +static int f2fs_set_meta_page_dirty(struct page *page) +{ + struct address_space *mapping = page->mapping; + struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); + + trace_f2fs_set_page_dirty(page, META); + + SetPageUptodate(page); + if (!PageDirty(page)) { + __set_page_dirty_nobuffers(page); + inc_page_count(sbi, F2FS_DIRTY_META); + return 1; + } + return 0; +} + +const struct address_space_operations f2fs_meta_aops = { + .writepage = f2fs_write_meta_page, + .writepages = f2fs_write_meta_pages, + .set_page_dirty = f2fs_set_meta_page_dirty, +}; + +int acquire_orphan_inode(struct f2fs_sb_info *sbi) +{ + int err = 0; + + spin_lock(&sbi->orphan_inode_lock); + if (unlikely(sbi->n_orphans >= sbi->max_orphans)) + err = -ENOSPC; + else + sbi->n_orphans++; + spin_unlock(&sbi->orphan_inode_lock); + + return err; +} + +void release_orphan_inode(struct f2fs_sb_info *sbi) +{ + spin_lock(&sbi->orphan_inode_lock); + if (sbi->n_orphans == 0) { + f2fs_msg(sbi->sb, KERN_ERR, "releasing " + "unacquired orphan inode"); + f2fs_handle_error(sbi); + } else + sbi->n_orphans--; + spin_unlock(&sbi->orphan_inode_lock); +} + +void add_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) +{ + struct list_head *head; + struct orphan_inode_entry *new, *orphan; + + new = f2fs_kmem_cache_alloc(orphan_entry_slab, GFP_ATOMIC); + new->ino = ino; + + spin_lock(&sbi->orphan_inode_lock); + head = &sbi->orphan_inode_list; + list_for_each_entry(orphan, head, list) { + if (orphan->ino == ino) { + spin_unlock(&sbi->orphan_inode_lock); + kmem_cache_free(orphan_entry_slab, new); + return; + } + + if (orphan->ino > ino) + break; + } + + /* add new orphan entry into list which is sorted by inode number */ + list_add_tail(&new->list, &orphan->list); + spin_unlock(&sbi->orphan_inode_lock); +} + +void remove_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) +{ + struct list_head *head; + struct orphan_inode_entry *orphan; + + spin_lock(&sbi->orphan_inode_lock); + head = &sbi->orphan_inode_list; + list_for_each_entry(orphan, head, list) { + if (orphan->ino == ino) { + list_del(&orphan->list); + if (sbi->n_orphans == 0) { + f2fs_msg(sbi->sb, KERN_ERR, "removing " + "unacquired orphan inode %d", + ino); + f2fs_handle_error(sbi); + } else + sbi->n_orphans--; + spin_unlock(&sbi->orphan_inode_lock); + kmem_cache_free(orphan_entry_slab, orphan); + return; + } + } + spin_unlock(&sbi->orphan_inode_lock); +} + +static void recover_orphan_inode(struct f2fs_sb_info *sbi, nid_t ino) +{ + struct inode *inode = f2fs_iget(sbi->sb, ino); + if (IS_ERR(inode)) { + f2fs_msg(sbi->sb, KERN_ERR, "unable to recover orphan inode %d", + ino); + f2fs_handle_error(sbi); + return; + } + clear_nlink(inode); + + /* truncate all the data during iput */ + iput(inode); +} + +void recover_orphan_inodes(struct f2fs_sb_info *sbi) +{ + block_t start_blk, orphan_blkaddr, i, j; + + if (!is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG)) + return; + + sbi->por_doing = true; + + start_blk = __start_cp_addr(sbi) + 1 + + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); + orphan_blkaddr = __start_sum_addr(sbi) - 1; + + ra_meta_pages(sbi, start_blk, orphan_blkaddr, META_CP); + + for (i = 0; i < orphan_blkaddr; i++) { + struct page *page = get_meta_page(sbi, start_blk + i); + struct f2fs_orphan_block *orphan_blk; + + orphan_blk = (struct f2fs_orphan_block *)page_address(page); + for (j = 0; j < le32_to_cpu(orphan_blk->entry_count); j++) { + nid_t ino = le32_to_cpu(orphan_blk->ino[j]); + recover_orphan_inode(sbi, ino); + } + f2fs_put_page(page, 1); + } + /* clear Orphan Flag */ + clear_ckpt_flags(F2FS_CKPT(sbi), CP_ORPHAN_PRESENT_FLAG); + sbi->por_doing = false; + return; +} + +static void write_orphan_inodes(struct f2fs_sb_info *sbi, block_t start_blk) +{ + struct list_head *head; + struct f2fs_orphan_block *orphan_blk = NULL; + unsigned int nentries = 0; + unsigned short index; + unsigned short orphan_blocks = (unsigned short)((sbi->n_orphans + + (F2FS_ORPHANS_PER_BLOCK - 1)) / F2FS_ORPHANS_PER_BLOCK); + struct page *page = NULL; + struct orphan_inode_entry *orphan = NULL; + + for (index = 0; index < orphan_blocks; index++) + grab_meta_page(sbi, start_blk + index); + + index = 1; + spin_lock(&sbi->orphan_inode_lock); + head = &sbi->orphan_inode_list; + + /* loop for each orphan inode entry and write them in Jornal block */ + list_for_each_entry(orphan, head, list) { + if (!page) { + page = find_get_page(META_MAPPING(sbi), start_blk++); + f2fs_bug_on(!page); + orphan_blk = + (struct f2fs_orphan_block *)page_address(page); + memset(orphan_blk, 0, sizeof(*orphan_blk)); + f2fs_put_page(page, 0); + } + + orphan_blk->ino[nentries++] = cpu_to_le32(orphan->ino); + + if (nentries == F2FS_ORPHANS_PER_BLOCK) { + /* + * an orphan block is full of 1020 entries, + * then we need to flush current orphan blocks + * and bring another one in memory + */ + orphan_blk->blk_addr = cpu_to_le16(index); + orphan_blk->blk_count = cpu_to_le16(orphan_blocks); + orphan_blk->entry_count = cpu_to_le32(nentries); + set_page_dirty(page); + f2fs_put_page(page, 1); + index++; + nentries = 0; + page = NULL; + } + } + + if (page) { + orphan_blk->blk_addr = cpu_to_le16(index); + orphan_blk->blk_count = cpu_to_le16(orphan_blocks); + orphan_blk->entry_count = cpu_to_le32(nentries); + set_page_dirty(page); + f2fs_put_page(page, 1); + } + + spin_unlock(&sbi->orphan_inode_lock); +} + +static struct page *validate_checkpoint(struct f2fs_sb_info *sbi, + block_t cp_addr, unsigned long long *version) +{ + struct page *cp_page_1, *cp_page_2 = NULL; + unsigned long blk_size = sbi->blocksize; + struct f2fs_checkpoint *cp_block; + unsigned long long cur_version = 0, pre_version = 0; + size_t crc_offset; + __u32 crc = 0; + + /* Read the 1st cp block in this CP pack */ + cp_page_1 = get_meta_page(sbi, cp_addr); + + /* get the version number */ + cp_block = (struct f2fs_checkpoint *)page_address(cp_page_1); + crc_offset = le32_to_cpu(cp_block->checksum_offset); + if (crc_offset >= blk_size) + goto invalid_cp1; + + crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); + if (!f2fs_crc_valid(crc, cp_block, crc_offset)) + goto invalid_cp1; + + pre_version = cur_cp_version(cp_block); + + /* Read the 2nd cp block in this CP pack */ + cp_addr += le32_to_cpu(cp_block->cp_pack_total_block_count) - 1; + cp_page_2 = get_meta_page(sbi, cp_addr); + + cp_block = (struct f2fs_checkpoint *)page_address(cp_page_2); + crc_offset = le32_to_cpu(cp_block->checksum_offset); + if (crc_offset >= blk_size) + goto invalid_cp2; + + crc = le32_to_cpu(*((__u32 *)((unsigned char *)cp_block + crc_offset))); + if (!f2fs_crc_valid(crc, cp_block, crc_offset)) + goto invalid_cp2; + + cur_version = cur_cp_version(cp_block); + + if (cur_version == pre_version) { + *version = cur_version; + f2fs_put_page(cp_page_2, 1); + return cp_page_1; + } +invalid_cp2: + f2fs_put_page(cp_page_2, 1); +invalid_cp1: + f2fs_put_page(cp_page_1, 1); + return NULL; +} + +int get_valid_checkpoint(struct f2fs_sb_info *sbi) +{ + struct f2fs_checkpoint *cp_block; + struct f2fs_super_block *fsb = sbi->raw_super; + struct page *cp1, *cp2, *cur_page; + unsigned long blk_size = sbi->blocksize; + unsigned long long cp1_version = 0, cp2_version = 0; + unsigned long long cp_start_blk_no; + unsigned int cp_blks = 1 + le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); + block_t cp_blk_no; + int i; + + sbi->ckpt = kzalloc(cp_blks * blk_size, GFP_KERNEL); + if (!sbi->ckpt) + return -ENOMEM; + /* + * Finding out valid cp block involves read both + * sets( cp pack1 and cp pack 2) + */ + cp_start_blk_no = le32_to_cpu(fsb->cp_blkaddr); + cp1 = validate_checkpoint(sbi, cp_start_blk_no, &cp1_version); + + /* The second checkpoint pack should start at the next segment */ + cp_start_blk_no += ((unsigned long long)1) << + le32_to_cpu(fsb->log_blocks_per_seg); + cp2 = validate_checkpoint(sbi, cp_start_blk_no, &cp2_version); + + if (cp1 && cp2) { + if (ver_after(cp2_version, cp1_version)) + cur_page = cp2; + else + cur_page = cp1; + } else if (cp1) { + cur_page = cp1; + } else if (cp2) { + cur_page = cp2; + } else { + goto fail_no_cp; + } + + cp_block = (struct f2fs_checkpoint *)page_address(cur_page); + memcpy(sbi->ckpt, cp_block, blk_size); + + if (cp_blks <= 1) + goto done; + + cp_blk_no = le32_to_cpu(fsb->cp_blkaddr); + if (cur_page == cp2) + cp_blk_no += 1 << le32_to_cpu(fsb->log_blocks_per_seg); + + for (i = 1; i < cp_blks; i++) { + void *sit_bitmap_ptr; + unsigned char *ckpt = (unsigned char *)sbi->ckpt; + + cur_page = get_meta_page(sbi, cp_blk_no + i); + sit_bitmap_ptr = page_address(cur_page); + memcpy(ckpt + i * blk_size, sit_bitmap_ptr, blk_size); + f2fs_put_page(cur_page, 1); + } +done: + f2fs_put_page(cp1, 1); + f2fs_put_page(cp2, 1); + return 0; + +fail_no_cp: + kfree(sbi->ckpt); + return -EINVAL; +} + +static int __add_dirty_inode(struct inode *inode, struct dir_inode_entry *new) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + + if (is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR)) + return -EEXIST; + + set_inode_flag(F2FS_I(inode), FI_DIRTY_DIR); + F2FS_I(inode)->dirty_dir = new; + list_add_tail(&new->list, &sbi->dir_inode_list); + stat_inc_dirty_dir(sbi); + return 0; +} + +void set_dirty_dir_page(struct inode *inode, struct page *page) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct dir_inode_entry *new; + int ret = 0; + + if (!S_ISDIR(inode->i_mode)) + return; + + new = f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); + new->inode = inode; + INIT_LIST_HEAD(&new->list); + + spin_lock(&sbi->dir_inode_lock); + ret = __add_dirty_inode(inode, new); + inode_inc_dirty_dents(inode); + SetPagePrivate(page); + spin_unlock(&sbi->dir_inode_lock); + + if (ret) + kmem_cache_free(inode_entry_slab, new); +} + +void add_dirty_dir_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct dir_inode_entry *new = + f2fs_kmem_cache_alloc(inode_entry_slab, GFP_NOFS); + int ret = 0; + + new->inode = inode; + INIT_LIST_HEAD(&new->list); + + spin_lock(&sbi->dir_inode_lock); + ret = __add_dirty_inode(inode, new); + spin_unlock(&sbi->dir_inode_lock); + + if (ret) + kmem_cache_free(inode_entry_slab, new); +} + +void remove_dirty_dir_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct dir_inode_entry *entry; + + if (!S_ISDIR(inode->i_mode)) + return; + + spin_lock(&sbi->dir_inode_lock); + if (get_dirty_dents(inode) || + !is_inode_flag_set(F2FS_I(inode), FI_DIRTY_DIR)) { + spin_unlock(&sbi->dir_inode_lock); + return; + } + + entry = F2FS_I(inode)->dirty_dir; + list_del(&entry->list); + F2FS_I(inode)->dirty_dir = NULL; + clear_inode_flag(F2FS_I(inode), FI_DIRTY_DIR); + stat_dec_dirty_dir(sbi); + spin_unlock(&sbi->dir_inode_lock); + kmem_cache_free(inode_entry_slab, entry); + + /* Only from the recovery routine */ + if (is_inode_flag_set(F2FS_I(inode), FI_DELAY_IPUT)) { + clear_inode_flag(F2FS_I(inode), FI_DELAY_IPUT); + iput(inode); + } +} + +void sync_dirty_dir_inodes(struct f2fs_sb_info *sbi) +{ + struct list_head *head; + struct dir_inode_entry *entry; + struct inode *inode; +retry: + spin_lock(&sbi->dir_inode_lock); + + head = &sbi->dir_inode_list; + if (list_empty(head)) { + spin_unlock(&sbi->dir_inode_lock); + return; + } + entry = list_entry(head->next, struct dir_inode_entry, list); + inode = igrab(entry->inode); + spin_unlock(&sbi->dir_inode_lock); + if (inode) { + filemap_fdatawrite(inode->i_mapping); + iput(inode); + } else { + /* + * We should submit bio, since it exists several + * wribacking dentry pages in the freeing inode. + */ + f2fs_submit_merged_bio(sbi, DATA, WRITE); + } + goto retry; +} + +/* + * Freeze all the FS-operations for checkpoint. + */ +static void block_operations(struct f2fs_sb_info *sbi) +{ + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = LONG_MAX, + .for_reclaim = 0, + }; + struct blk_plug plug; + + blk_start_plug(&plug); + +retry_flush_dents: + f2fs_lock_all(sbi); + /* write all the dirty dentry pages */ + if (get_pages(sbi, F2FS_DIRTY_DENTS)) { + f2fs_unlock_all(sbi); + sync_dirty_dir_inodes(sbi); + goto retry_flush_dents; + } + + /* + * POR: we should ensure that there is no dirty node pages + * until finishing nat/sit flush. + */ +retry_flush_nodes: + mutex_lock(&sbi->node_write); + + if (get_pages(sbi, F2FS_DIRTY_NODES)) { + mutex_unlock(&sbi->node_write); + sync_node_pages(sbi, 0, &wbc); + goto retry_flush_nodes; + } + blk_finish_plug(&plug); +} + +static void unblock_operations(struct f2fs_sb_info *sbi) +{ + mutex_unlock(&sbi->node_write); + f2fs_unlock_all(sbi); +} + +static void wait_on_all_pages_writeback(struct f2fs_sb_info *sbi) +{ + DEFINE_WAIT(wait); + + for (;;) { + prepare_to_wait(&sbi->cp_wait, &wait, TASK_UNINTERRUPTIBLE); + + if (!get_pages(sbi, F2FS_WRITEBACK)) + break; + + io_schedule(); + } + finish_wait(&sbi->cp_wait, &wait); +} + +static void do_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) +{ + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + nid_t last_nid = 0; + block_t start_blk; + struct page *cp_page; + unsigned int data_sum_blocks, orphan_blocks; + __u32 crc32 = 0; + void *kaddr; + int i; + int cp_payload_blks = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload); + + /* + * This avoids to conduct wrong roll-forward operations and uses + * metapages, so should be called prior to sync_meta_pages below. + */ + discard_next_dnode(sbi); + + /* Flush all the NAT/SIT pages */ + while (get_pages(sbi, F2FS_DIRTY_META)) + sync_meta_pages(sbi, META, LONG_MAX); + + next_free_nid(sbi, &last_nid); + + /* + * modify checkpoint + * version number is already updated + */ + ckpt->elapsed_time = cpu_to_le64(get_mtime(sbi)); + ckpt->valid_block_count = cpu_to_le64(valid_user_blocks(sbi)); + ckpt->free_segment_count = cpu_to_le32(free_segments(sbi)); + for (i = 0; i < 3; i++) { + ckpt->cur_node_segno[i] = + cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_NODE)); + ckpt->cur_node_blkoff[i] = + cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_NODE)); + ckpt->alloc_type[i + CURSEG_HOT_NODE] = + curseg_alloc_type(sbi, i + CURSEG_HOT_NODE); + } + for (i = 0; i < 3; i++) { + ckpt->cur_data_segno[i] = + cpu_to_le32(curseg_segno(sbi, i + CURSEG_HOT_DATA)); + ckpt->cur_data_blkoff[i] = + cpu_to_le16(curseg_blkoff(sbi, i + CURSEG_HOT_DATA)); + ckpt->alloc_type[i + CURSEG_HOT_DATA] = + curseg_alloc_type(sbi, i + CURSEG_HOT_DATA); + } + + ckpt->valid_node_count = cpu_to_le32(valid_node_count(sbi)); + ckpt->valid_inode_count = cpu_to_le32(valid_inode_count(sbi)); + ckpt->next_free_nid = cpu_to_le32(last_nid); + + /* 2 cp + n data seg summary + orphan inode blocks */ + data_sum_blocks = npages_for_summary_flush(sbi); + if (data_sum_blocks < 3) + set_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); + else + clear_ckpt_flags(ckpt, CP_COMPACT_SUM_FLAG); + + orphan_blocks = (sbi->n_orphans + F2FS_ORPHANS_PER_BLOCK - 1) + / F2FS_ORPHANS_PER_BLOCK; + ckpt->cp_pack_start_sum = cpu_to_le32(1 + cp_payload_blks + + orphan_blocks); + + if (is_umount) { + set_ckpt_flags(ckpt, CP_UMOUNT_FLAG); + ckpt->cp_pack_total_block_count = cpu_to_le32(2 + + cp_payload_blks + data_sum_blocks + + orphan_blocks + NR_CURSEG_NODE_TYPE); + } else { + clear_ckpt_flags(ckpt, CP_UMOUNT_FLAG); + ckpt->cp_pack_total_block_count = cpu_to_le32(2 + + cp_payload_blks + data_sum_blocks + + orphan_blocks); + } + + if (sbi->n_orphans) + set_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG); + else + clear_ckpt_flags(ckpt, CP_ORPHAN_PRESENT_FLAG); + + /* update SIT/NAT bitmap */ + get_sit_bitmap(sbi, __bitmap_ptr(sbi, SIT_BITMAP)); + get_nat_bitmap(sbi, __bitmap_ptr(sbi, NAT_BITMAP)); + + crc32 = f2fs_crc32(ckpt, le32_to_cpu(ckpt->checksum_offset)); + *((__le32 *)((unsigned char *)ckpt + + le32_to_cpu(ckpt->checksum_offset))) + = cpu_to_le32(crc32); + + start_blk = __start_cp_addr(sbi); + + /* write out checkpoint buffer at block 0 */ + cp_page = grab_meta_page(sbi, start_blk++); + kaddr = page_address(cp_page); + memcpy(kaddr, ckpt, (1 << sbi->log_blocksize)); + set_page_dirty(cp_page); + f2fs_put_page(cp_page, 1); + + for (i = 1; i < 1 + cp_payload_blks; i++) { + cp_page = grab_meta_page(sbi, start_blk++); + kaddr = page_address(cp_page); + memcpy(kaddr, (char *)ckpt + i * F2FS_BLKSIZE, + (1 << sbi->log_blocksize)); + set_page_dirty(cp_page); + f2fs_put_page(cp_page, 1); + } + + if (sbi->n_orphans) { + write_orphan_inodes(sbi, start_blk); + start_blk += orphan_blocks; + } + + write_data_summaries(sbi, start_blk); + start_blk += data_sum_blocks; + if (is_umount) { + write_node_summaries(sbi, start_blk); + start_blk += NR_CURSEG_NODE_TYPE; + } + + /* writeout checkpoint block */ + cp_page = grab_meta_page(sbi, start_blk); + kaddr = page_address(cp_page); + memcpy(kaddr, ckpt, (1 << sbi->log_blocksize)); + set_page_dirty(cp_page); + f2fs_put_page(cp_page, 1); + + /* wait for previous submitted node/meta pages writeback */ + wait_on_all_pages_writeback(sbi); + + filemap_fdatawait_range(NODE_MAPPING(sbi), 0, LONG_MAX); + filemap_fdatawait_range(META_MAPPING(sbi), 0, LONG_MAX); + + /* update user_block_counts */ + sbi->last_valid_block_count = sbi->total_valid_block_count; + sbi->alloc_valid_block_count = 0; + + /* Here, we only have one bio having CP pack */ + sync_meta_pages(sbi, META_FLUSH, LONG_MAX); + + if (unlikely(!is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))) { + clear_prefree_segments(sbi); + F2FS_RESET_SB_DIRT(sbi); + } +} + +/* + * We guarantee that this checkpoint procedure should not fail. + */ +void write_checkpoint(struct f2fs_sb_info *sbi, bool is_umount) +{ + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + unsigned long long ckpt_ver; + + trace_f2fs_write_checkpoint(sbi->sb, is_umount, "start block_ops"); + + mutex_lock(&sbi->cp_mutex); + block_operations(sbi); + + trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish block_ops"); + + f2fs_submit_merged_bio(sbi, DATA, WRITE); + f2fs_submit_merged_bio(sbi, NODE, WRITE); + f2fs_submit_merged_bio(sbi, META, WRITE); + + /* + * update checkpoint pack index + * Increase the version number so that + * SIT entries and seg summaries are written at correct place + */ + ckpt_ver = cur_cp_version(ckpt); + ckpt->checkpoint_ver = cpu_to_le64(++ckpt_ver); + + /* write cached NAT/SIT entries to NAT/SIT area */ + flush_nat_entries(sbi); + flush_sit_entries(sbi); + + /* unlock all the fs_lock[] in do_checkpoint() */ + do_checkpoint(sbi, is_umount); + + unblock_operations(sbi); + mutex_unlock(&sbi->cp_mutex); + + stat_inc_cp_count(sbi->stat_info); + trace_f2fs_write_checkpoint(sbi->sb, is_umount, "finish checkpoint"); +} + +void init_orphan_info(struct f2fs_sb_info *sbi) +{ + spin_lock_init(&sbi->orphan_inode_lock); + INIT_LIST_HEAD(&sbi->orphan_inode_list); + sbi->n_orphans = 0; + /* + * considering 512 blocks in a segment 8 blocks are needed for cp + * and log segment summaries. Remaining blocks are used to keep + * orphan entries with the limitation one reserved segment + * for cp pack we can have max 1020*504 orphan entries + */ + sbi->max_orphans = (sbi->blocks_per_seg - 2 - NR_CURSEG_TYPE) + * F2FS_ORPHANS_PER_BLOCK; +} + +int __init create_checkpoint_caches(void) +{ + orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry", + sizeof(struct orphan_inode_entry)); + if (!orphan_entry_slab) + return -ENOMEM; + inode_entry_slab = f2fs_kmem_cache_create("f2fs_dirty_dir_entry", + sizeof(struct dir_inode_entry)); + if (!inode_entry_slab) { + kmem_cache_destroy(orphan_entry_slab); + return -ENOMEM; + } + return 0; +} + +void destroy_checkpoint_caches(void) +{ + kmem_cache_destroy(orphan_entry_slab); + kmem_cache_destroy(inode_entry_slab); +} diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c new file mode 100644 index 00000000000..3ed90150622 --- /dev/null +++ b/fs/f2fs/data.c @@ -0,0 +1,1131 @@ +/* + * fs/f2fs/data.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" +#include "segment.h" +#include + +static void f2fs_read_end_io(struct bio *bio, int err) +{ + const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); + struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; + + do { + struct page *page = bvec->bv_page; + + if (--bvec >= bio->bi_io_vec) + prefetchw(&bvec->bv_page->flags); + + if (unlikely(!uptodate)) { + ClearPageUptodate(page); + SetPageError(page); + } else { + SetPageUptodate(page); + } + unlock_page(page); + } while (bvec >= bio->bi_io_vec); + + bio_put(bio); +} + +static void f2fs_write_end_io(struct bio *bio, int err) +{ + const int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); + struct bio_vec *bvec = bio->bi_io_vec + bio->bi_vcnt - 1; + struct f2fs_sb_info *sbi = bio->bi_private; + + do { + struct page *page = bvec->bv_page; + + if (--bvec >= bio->bi_io_vec) + prefetchw(&bvec->bv_page->flags); + + if (unlikely(!uptodate)) { + SetPageError(page); + set_bit(AS_EIO, &page->mapping->flags); + f2fs_stop_checkpoint(sbi); + } + end_page_writeback(page); + dec_page_count(sbi, F2FS_WRITEBACK); + } while (bvec >= bio->bi_io_vec); + + if (sbi->wait_io) { + complete(sbi->wait_io); + sbi->wait_io = NULL; + } + + if (!get_pages(sbi, F2FS_WRITEBACK) && + !list_empty(&sbi->cp_wait.task_list)) + wake_up(&sbi->cp_wait); + + bio_put(bio); +} + +/* + * Low-level block read/write IO operations. + */ +static struct bio *__bio_alloc(struct f2fs_sb_info *sbi, block_t blk_addr, + int npages, bool is_read) +{ + struct bio *bio; + + /* No failure on bio allocation */ + bio = bio_alloc(GFP_NOIO, npages); + + bio->bi_bdev = sbi->sb->s_bdev; + bio->bi_sector = SECTOR_FROM_BLOCK(sbi, blk_addr); + bio->bi_end_io = is_read ? f2fs_read_end_io : f2fs_write_end_io; + bio->bi_private = sbi; + + return bio; +} + +static void __submit_merged_bio(struct f2fs_bio_info *io) +{ + struct f2fs_io_info *fio = &io->fio; + int rw; + + if (!io->bio) + return; + + rw = fio->rw; + + if (is_read_io(rw)) { + trace_f2fs_submit_read_bio(io->sbi->sb, rw, + fio->type, io->bio); + submit_bio(rw, io->bio); + } else { + trace_f2fs_submit_write_bio(io->sbi->sb, rw, + fio->type, io->bio); + /* + * META_FLUSH is only from the checkpoint procedure, and we + * should wait this metadata bio for FS consistency. + */ + if (fio->type == META_FLUSH) { + DECLARE_COMPLETION_ONSTACK(wait); + io->sbi->wait_io = &wait; + submit_bio(rw, io->bio); + wait_for_completion(&wait); + } else { + submit_bio(rw, io->bio); + } + } + + io->bio = NULL; +} + +void f2fs_submit_merged_bio(struct f2fs_sb_info *sbi, + enum page_type type, int rw) +{ + enum page_type btype = PAGE_TYPE_OF_BIO(type); + struct f2fs_bio_info *io; + + io = is_read_io(rw) ? &sbi->read_io : &sbi->write_io[btype]; + + down_write(&io->io_rwsem); + + /* change META to META_FLUSH in the checkpoint procedure */ + if (type >= META_FLUSH) { + io->fio.type = META_FLUSH; + io->fio.rw = WRITE_FLUSH_FUA | REQ_META | REQ_PRIO; + } + __submit_merged_bio(io); + up_write(&io->io_rwsem); +} + +/* + * Fill the locked page with data located in the block address. + * Return unlocked page. + */ +int f2fs_submit_page_bio(struct f2fs_sb_info *sbi, struct page *page, + block_t blk_addr, int rw) +{ + struct bio *bio; + + trace_f2fs_submit_page_bio(page, blk_addr, rw); + + /* Allocate a new bio */ + bio = __bio_alloc(sbi, blk_addr, 1, is_read_io(rw)); + + if (bio_add_page(bio, page, PAGE_CACHE_SIZE, 0) < PAGE_CACHE_SIZE) { + bio_put(bio); + f2fs_put_page(page, 1); + return -EFAULT; + } + + submit_bio(rw, bio); + return 0; +} + +void f2fs_submit_page_mbio(struct f2fs_sb_info *sbi, struct page *page, + block_t blk_addr, struct f2fs_io_info *fio) +{ + enum page_type btype = PAGE_TYPE_OF_BIO(fio->type); + struct f2fs_bio_info *io; + bool is_read = is_read_io(fio->rw); + + io = is_read ? &sbi->read_io : &sbi->write_io[btype]; + + verify_block_addr(sbi, blk_addr); + + down_write(&io->io_rwsem); + + if (!is_read) + inc_page_count(sbi, F2FS_WRITEBACK); + + if (io->bio && (io->last_block_in_bio != blk_addr - 1 || + io->fio.rw != fio->rw)) + __submit_merged_bio(io); +alloc_new: + if (io->bio == NULL) { + int bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); + + io->bio = __bio_alloc(sbi, blk_addr, bio_blocks, is_read); + io->fio = *fio; + } + + if (bio_add_page(io->bio, page, PAGE_CACHE_SIZE, 0) < + PAGE_CACHE_SIZE) { + __submit_merged_bio(io); + goto alloc_new; + } + + io->last_block_in_bio = blk_addr; + + up_write(&io->io_rwsem); + trace_f2fs_submit_page_mbio(page, fio->rw, fio->type, blk_addr); +} + +/* + * Lock ordering for the change of data block address: + * ->data_page + * ->node_page + * update block addresses in the node page + */ +static void __set_data_blkaddr(struct dnode_of_data *dn, block_t new_addr) +{ + struct f2fs_node *rn; + __le32 *addr_array; + struct page *node_page = dn->node_page; + unsigned int ofs_in_node = dn->ofs_in_node; + + f2fs_wait_on_page_writeback(node_page, NODE); + + rn = F2FS_NODE(node_page); + + /* Get physical address of data block */ + addr_array = blkaddr_in_node(rn); + addr_array[ofs_in_node] = cpu_to_le32(new_addr); + set_page_dirty(node_page); +} + +int reserve_new_block(struct dnode_of_data *dn) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + + if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))) + return -EPERM; + if (unlikely(!inc_valid_block_count(sbi, dn->inode, 1))) + return -ENOSPC; + + trace_f2fs_reserve_new_block(dn->inode, dn->nid, dn->ofs_in_node); + + __set_data_blkaddr(dn, NEW_ADDR); + dn->data_blkaddr = NEW_ADDR; + mark_inode_dirty(dn->inode); + sync_inode_page(dn); + return 0; +} + +int f2fs_reserve_block(struct dnode_of_data *dn, pgoff_t index) +{ + bool need_put = dn->inode_page ? false : true; + int err; + + /* if inode_page exists, index should be zero */ + f2fs_bug_on(!need_put && index); + + err = get_dnode_of_data(dn, index, ALLOC_NODE); + if (err) + return err; + + if (dn->data_blkaddr == NULL_ADDR) + err = reserve_new_block(dn); + if (err || need_put) + f2fs_put_dnode(dn); + return err; +} + +static int check_extent_cache(struct inode *inode, pgoff_t pgofs, + struct buffer_head *bh_result) +{ + struct f2fs_inode_info *fi = F2FS_I(inode); + pgoff_t start_fofs, end_fofs; + block_t start_blkaddr; + + if (is_inode_flag_set(fi, FI_NO_EXTENT)) + return 0; + + read_lock(&fi->ext.ext_lock); + if (fi->ext.len == 0) { + read_unlock(&fi->ext.ext_lock); + return 0; + } + + stat_inc_total_hit(inode->i_sb); + + start_fofs = fi->ext.fofs; + end_fofs = fi->ext.fofs + fi->ext.len - 1; + start_blkaddr = fi->ext.blk_addr; + + if (pgofs >= start_fofs && pgofs <= end_fofs) { + unsigned int blkbits = inode->i_sb->s_blocksize_bits; + size_t count; + + clear_buffer_new(bh_result); + map_bh(bh_result, inode->i_sb, + start_blkaddr + pgofs - start_fofs); + count = end_fofs - pgofs + 1; + if (count < (UINT_MAX >> blkbits)) + bh_result->b_size = (count << blkbits); + else + bh_result->b_size = UINT_MAX; + + stat_inc_read_hit(inode->i_sb); + read_unlock(&fi->ext.ext_lock); + return 1; + } + read_unlock(&fi->ext.ext_lock); + return 0; +} + +void update_extent_cache(block_t blk_addr, struct dnode_of_data *dn) +{ + struct f2fs_inode_info *fi = F2FS_I(dn->inode); + pgoff_t fofs, start_fofs, end_fofs; + block_t start_blkaddr, end_blkaddr; + int need_update = true; + + f2fs_bug_on(blk_addr == NEW_ADDR); + fofs = start_bidx_of_node(ofs_of_node(dn->node_page), fi) + + dn->ofs_in_node; + + /* Update the page address in the parent node */ + __set_data_blkaddr(dn, blk_addr); + + if (is_inode_flag_set(fi, FI_NO_EXTENT)) + return; + + write_lock(&fi->ext.ext_lock); + + start_fofs = fi->ext.fofs; + end_fofs = fi->ext.fofs + fi->ext.len - 1; + start_blkaddr = fi->ext.blk_addr; + end_blkaddr = fi->ext.blk_addr + fi->ext.len - 1; + + /* Drop and initialize the matched extent */ + if (fi->ext.len == 1 && fofs == start_fofs) + fi->ext.len = 0; + + /* Initial extent */ + if (fi->ext.len == 0) { + if (blk_addr != NULL_ADDR) { + fi->ext.fofs = fofs; + fi->ext.blk_addr = blk_addr; + fi->ext.len = 1; + } + goto end_update; + } + + /* Front merge */ + if (fofs == start_fofs - 1 && blk_addr == start_blkaddr - 1) { + fi->ext.fofs--; + fi->ext.blk_addr--; + fi->ext.len++; + goto end_update; + } + + /* Back merge */ + if (fofs == end_fofs + 1 && blk_addr == end_blkaddr + 1) { + fi->ext.len++; + goto end_update; + } + + /* Split the existing extent */ + if (fi->ext.len > 1 && + fofs >= start_fofs && fofs <= end_fofs) { + if ((end_fofs - fofs) < (fi->ext.len >> 1)) { + fi->ext.len = fofs - start_fofs; + } else { + fi->ext.fofs = fofs + 1; + fi->ext.blk_addr = start_blkaddr + + fofs - start_fofs + 1; + fi->ext.len -= fofs - start_fofs + 1; + } + } else { + need_update = false; + } + + /* Finally, if the extent is very fragmented, let's drop the cache. */ + if (fi->ext.len < F2FS_MIN_EXTENT_LEN) { + fi->ext.len = 0; + set_inode_flag(fi, FI_NO_EXTENT); + need_update = true; + } +end_update: + write_unlock(&fi->ext.ext_lock); + if (need_update) + sync_inode_page(dn); + return; +} + +struct page *find_data_page(struct inode *inode, pgoff_t index, bool sync) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct address_space *mapping = inode->i_mapping; + struct dnode_of_data dn; + struct page *page; + int err; + + page = find_get_page(mapping, index); + if (page && PageUptodate(page)) + return page; + f2fs_put_page(page, 0); + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, index, LOOKUP_NODE); + if (err) + return ERR_PTR(err); + f2fs_put_dnode(&dn); + + if (dn.data_blkaddr == NULL_ADDR) + return ERR_PTR(-ENOENT); + + /* By fallocate(), there is no cached page, but with NEW_ADDR */ + if (unlikely(dn.data_blkaddr == NEW_ADDR)) + return ERR_PTR(-EINVAL); + + page = grab_cache_page(mapping, index); + if (!page) + return ERR_PTR(-ENOMEM); + + if (PageUptodate(page)) { + unlock_page(page); + return page; + } + + err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr, + sync ? READ_SYNC : READA); + if (err) + return ERR_PTR(err); + + if (sync) { + wait_on_page_locked(page); + if (unlikely(!PageUptodate(page))) { + f2fs_put_page(page, 0); + return ERR_PTR(-EIO); + } + } + return page; +} + +/* + * If it tries to access a hole, return an error. + * Because, the callers, functions in dir.c and GC, should be able to know + * whether this page exists or not. + */ +struct page *get_lock_data_page(struct inode *inode, pgoff_t index) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct address_space *mapping = inode->i_mapping; + struct dnode_of_data dn; + struct page *page; + int err; + +repeat: + page = grab_cache_page(mapping, index); + if (!page) + return ERR_PTR(-ENOMEM); + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, index, LOOKUP_NODE); + if (err) { + f2fs_put_page(page, 1); + return ERR_PTR(err); + } + f2fs_put_dnode(&dn); + + if (unlikely(dn.data_blkaddr == NULL_ADDR)) { + f2fs_put_page(page, 1); + return ERR_PTR(-ENOENT); + } + + if (PageUptodate(page)) + return page; + + /* + * A new dentry page is allocated but not able to be written, since its + * new inode page couldn't be allocated due to -ENOSPC. + * In such the case, its blkaddr can be remained as NEW_ADDR. + * see, f2fs_add_link -> get_new_data_page -> init_inode_metadata. + */ + if (dn.data_blkaddr == NEW_ADDR) { + zero_user_segment(page, 0, PAGE_CACHE_SIZE); + SetPageUptodate(page); + return page; + } + + err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr, READ_SYNC); + if (err) + return ERR_PTR(err); + + lock_page(page); + if (unlikely(!PageUptodate(page))) { + f2fs_put_page(page, 1); + return ERR_PTR(-EIO); + } + if (unlikely(page->mapping != mapping)) { + f2fs_put_page(page, 1); + goto repeat; + } + return page; +} + +/* + * Caller ensures that this data page is never allocated. + * A new zero-filled data page is allocated in the page cache. + * + * Also, caller should grab and release a rwsem by calling f2fs_lock_op() and + * f2fs_unlock_op(). + * Note that, ipage is set only by make_empty_dir. + */ +struct page *get_new_data_page(struct inode *inode, + struct page *ipage, pgoff_t index, bool new_i_size) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct address_space *mapping = inode->i_mapping; + struct page *page; + struct dnode_of_data dn; + int err; + + set_new_dnode(&dn, inode, ipage, NULL, 0); + err = f2fs_reserve_block(&dn, index); + if (err) + return ERR_PTR(err); +repeat: + page = grab_cache_page(mapping, index); + if (!page) { + err = -ENOMEM; + goto put_err; + } + + if (PageUptodate(page)) + return page; + + if (dn.data_blkaddr == NEW_ADDR) { + zero_user_segment(page, 0, PAGE_CACHE_SIZE); + SetPageUptodate(page); + } else { + err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr, + READ_SYNC); + if (err) + goto put_err; + + lock_page(page); + if (unlikely(!PageUptodate(page))) { + f2fs_put_page(page, 1); + err = -EIO; + goto put_err; + } + if (unlikely(page->mapping != mapping)) { + f2fs_put_page(page, 1); + goto repeat; + } + } + + if (new_i_size && + i_size_read(inode) < ((index + 1) << PAGE_CACHE_SHIFT)) { + i_size_write(inode, ((index + 1) << PAGE_CACHE_SHIFT)); + /* Only the directory inode sets new_i_size */ + set_inode_flag(F2FS_I(inode), FI_UPDATE_DIR); + } + return page; + +put_err: + f2fs_put_dnode(&dn); + return ERR_PTR(err); +} + +static int __allocate_data_block(struct dnode_of_data *dn) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct f2fs_summary sum; + block_t new_blkaddr; + struct node_info ni; + int type; + + if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))) + return -EPERM; + if (unlikely(!inc_valid_block_count(sbi, dn->inode, 1))) + return -ENOSPC; + + __set_data_blkaddr(dn, NEW_ADDR); + dn->data_blkaddr = NEW_ADDR; + + get_node_info(sbi, dn->nid, &ni); + set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); + + type = CURSEG_WARM_DATA; + + allocate_data_block(sbi, NULL, NULL_ADDR, &new_blkaddr, &sum, type); + + /* direct IO doesn't use extent cache to maximize the performance */ + set_inode_flag(F2FS_I(dn->inode), FI_NO_EXTENT); + update_extent_cache(new_blkaddr, dn); + clear_inode_flag(F2FS_I(dn->inode), FI_NO_EXTENT); + + dn->data_blkaddr = new_blkaddr; + return 0; +} + +/* + * get_data_block() now supported readahead/bmap/rw direct_IO with mapped bh. + * If original data blocks are allocated, then give them to blockdev. + * Otherwise, + * a. preallocate requested block addresses + * b. do not use extent cache for better performance + * c. give the block addresses to blockdev + */ +static int __get_data_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create, bool fiemap) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + unsigned int blkbits = inode->i_sb->s_blocksize_bits; + unsigned maxblocks = bh_result->b_size >> blkbits; + struct dnode_of_data dn; + int mode = create ? ALLOC_NODE : LOOKUP_NODE_RA; + pgoff_t pgofs, end_offset; + int err = 0, ofs = 1; + bool allocated = false; + + /* Get the page offset from the block offset(iblock) */ + pgofs = (pgoff_t)(iblock >> (PAGE_CACHE_SHIFT - blkbits)); + + if (check_extent_cache(inode, pgofs, bh_result)) + goto out; + + if (create) + f2fs_lock_op(sbi); + + /* When reading holes, we need its node page */ + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, pgofs, mode); + if (err) { + if (err == -ENOENT) + err = 0; + goto unlock_out; + } + if (dn.data_blkaddr == NEW_ADDR && !fiemap) + goto put_out; + + if (dn.data_blkaddr != NULL_ADDR) { + map_bh(bh_result, inode->i_sb, dn.data_blkaddr); + } else if (create) { + err = __allocate_data_block(&dn); + if (err) + goto put_out; + allocated = true; + map_bh(bh_result, inode->i_sb, dn.data_blkaddr); + } else { + goto put_out; + } + + end_offset = IS_INODE(dn.node_page) ? + ADDRS_PER_INODE(F2FS_I(inode)) : ADDRS_PER_BLOCK; + bh_result->b_size = (((size_t)1) << blkbits); + dn.ofs_in_node++; + pgofs++; + +get_next: + if (dn.ofs_in_node >= end_offset) { + if (allocated) + sync_inode_page(&dn); + allocated = false; + f2fs_put_dnode(&dn); + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, pgofs, mode); + if (err) { + if (err == -ENOENT) + err = 0; + goto unlock_out; + } + if (dn.data_blkaddr == NEW_ADDR && !fiemap) + goto put_out; + + end_offset = IS_INODE(dn.node_page) ? + ADDRS_PER_INODE(F2FS_I(inode)) : ADDRS_PER_BLOCK; + } + + if (maxblocks > (bh_result->b_size >> blkbits)) { + block_t blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node); + if (blkaddr == NULL_ADDR && create) { + err = __allocate_data_block(&dn); + if (err) + goto sync_out; + allocated = true; + blkaddr = dn.data_blkaddr; + } + /* Give more consecutive addresses for the read ahead */ + if (blkaddr == (bh_result->b_blocknr + ofs)) { + ofs++; + dn.ofs_in_node++; + pgofs++; + bh_result->b_size += (((size_t)1) << blkbits); + goto get_next; + } + } +sync_out: + if (allocated) + sync_inode_page(&dn); +put_out: + f2fs_put_dnode(&dn); +unlock_out: + if (create) + f2fs_unlock_op(sbi); +out: + trace_f2fs_get_data_block(inode, iblock, bh_result, err); + return err; +} + +static int get_data_block(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + return __get_data_block(inode, iblock, bh_result, create, false); +} + +static int get_data_block_fiemap(struct inode *inode, sector_t iblock, + struct buffer_head *bh_result, int create) +{ + return __get_data_block(inode, iblock, bh_result, create, true); +} + +int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, + u64 start, u64 len) +{ + return generic_block_fiemap(inode, fieinfo, + start, len, get_data_block_fiemap); +} + +static int f2fs_read_data_page(struct file *file, struct page *page) +{ + struct inode *inode = page->mapping->host; + int ret; + + trace_f2fs_readpage(page, DATA); + + /* If the file has inline data, try to read it directlly */ + if (f2fs_has_inline_data(inode)) + ret = f2fs_read_inline_data(inode, page); + else + ret = mpage_readpage(page, get_data_block); + + return ret; +} + +static int f2fs_read_data_pages(struct file *file, + struct address_space *mapping, + struct list_head *pages, unsigned nr_pages) +{ + struct inode *inode = file->f_mapping->host; + + /* If the file has inline data, skip readpages */ + if (f2fs_has_inline_data(inode)) + return 0; + + return mpage_readpages(mapping, pages, nr_pages, get_data_block); +} + +int do_write_data_page(struct page *page, struct f2fs_io_info *fio) +{ + struct inode *inode = page->mapping->host; + block_t old_blkaddr, new_blkaddr; + struct dnode_of_data dn; + int err = 0; + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, page->index, LOOKUP_NODE); + if (err) + return err; + + old_blkaddr = dn.data_blkaddr; + + /* This page is already truncated */ + if (old_blkaddr == NULL_ADDR) + goto out_writepage; + + set_page_writeback(page); + + /* + * If current allocation needs SSR, + * it had better in-place writes for updated data. + */ + if (unlikely(old_blkaddr != NEW_ADDR && + !is_cold_data(page) && + need_inplace_update(inode))) { + rewrite_data_page(page, old_blkaddr, fio); + } else { + write_data_page(page, &dn, &new_blkaddr, fio); + update_extent_cache(new_blkaddr, &dn); + } +out_writepage: + f2fs_put_dnode(&dn); + return err; +} + +static int f2fs_write_data_page(struct page *page, + struct writeback_control *wbc) +{ + struct inode *inode = page->mapping->host; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + loff_t i_size = i_size_read(inode); + const pgoff_t end_index = ((unsigned long long) i_size) + >> PAGE_CACHE_SHIFT; + unsigned offset = 0; + bool need_balance_fs = false; + int err = 0; + struct f2fs_io_info fio = { + .type = DATA, + .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE, + }; + + trace_f2fs_writepage(page, DATA); + + if (page->index < end_index) + goto write; + + /* + * If the offset is out-of-range of file size, + * this page does not have to be written to disk. + */ + offset = i_size & (PAGE_CACHE_SIZE - 1); + if ((page->index >= end_index + 1) || !offset) + goto out; + + zero_user_segment(page, offset, PAGE_CACHE_SIZE); +write: + if (unlikely(sbi->por_doing)) + goto redirty_out; + + /* Dentry blocks are controlled by checkpoint */ + if (S_ISDIR(inode->i_mode)) { + err = do_write_data_page(page, &fio); + goto done; + } + + if (!wbc->for_reclaim) + need_balance_fs = true; + else if (has_not_enough_free_secs(sbi, 0)) + goto redirty_out; + + f2fs_lock_op(sbi); + if (f2fs_has_inline_data(inode) || f2fs_may_inline(inode)) + err = f2fs_write_inline_data(inode, page, offset); + else + err = do_write_data_page(page, &fio); + f2fs_unlock_op(sbi); +done: + if (err && err != -ENOENT) + goto redirty_out; + + clear_cold_data(page); +out: + inode_dec_dirty_dents(inode); + unlock_page(page); + if (need_balance_fs) + f2fs_balance_fs(sbi); + if (wbc->for_reclaim) + f2fs_submit_merged_bio(sbi, DATA, WRITE); + return 0; + +redirty_out: + redirty_page_for_writepage(wbc, page); + return AOP_WRITEPAGE_ACTIVATE; +} + +static int __f2fs_writepage(struct page *page, struct writeback_control *wbc, + void *data) +{ + struct address_space *mapping = data; + int ret = mapping->a_ops->writepage(page, wbc); + mapping_set_error(mapping, ret); + return ret; +} + +static int f2fs_write_data_pages(struct address_space *mapping, + struct writeback_control *wbc) +{ + struct inode *inode = mapping->host; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + bool locked = false; + int ret; + long diff; + + trace_f2fs_writepages(mapping->host, wbc, DATA); + + /* deal with chardevs and other special file */ + if (!mapping->a_ops->writepage) + return 0; + + if (S_ISDIR(inode->i_mode) && wbc->sync_mode == WB_SYNC_NONE && + get_dirty_dents(inode) < nr_pages_to_skip(sbi, DATA) && + available_free_memory(sbi, DIRTY_DENTS)) + goto skip_write; + + diff = nr_pages_to_write(sbi, DATA, wbc); + + if (!S_ISDIR(inode->i_mode)) { + mutex_lock(&sbi->writepages); + locked = true; + } + ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping); + if (locked) + mutex_unlock(&sbi->writepages); + + f2fs_submit_merged_bio(sbi, DATA, WRITE); + + remove_dirty_dir_inode(inode); + + wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff); + return ret; + +skip_write: + wbc->pages_skipped += get_dirty_dents(inode); + return 0; +} + +static int f2fs_write_begin(struct file *file, struct address_space *mapping, + loff_t pos, unsigned len, unsigned flags, + struct page **pagep, void **fsdata) +{ + struct inode *inode = mapping->host; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct page *page; + pgoff_t index = ((unsigned long long) pos) >> PAGE_CACHE_SHIFT; + struct dnode_of_data dn; + int err = 0; + + trace_f2fs_write_begin(inode, pos, len, flags); + + f2fs_balance_fs(sbi); +repeat: + err = f2fs_convert_inline_data(inode, pos + len); + if (err) + return err; + + page = grab_cache_page_write_begin(mapping, index, flags); + if (!page) + return -ENOMEM; + + /* to avoid latency during memory pressure */ + unlock_page(page); + + *pagep = page; + + if (f2fs_has_inline_data(inode) && (pos + len) <= MAX_INLINE_DATA) + goto inline_data; + + f2fs_lock_op(sbi); + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = f2fs_reserve_block(&dn, index); + f2fs_unlock_op(sbi); + + if (err) { + f2fs_put_page(page, 0); + return err; + } +inline_data: + lock_page(page); + if (unlikely(page->mapping != mapping)) { + f2fs_put_page(page, 1); + goto repeat; + } + + f2fs_wait_on_page_writeback(page, DATA); + + if ((len == PAGE_CACHE_SIZE) || PageUptodate(page)) + return 0; + + if ((pos & PAGE_CACHE_MASK) >= i_size_read(inode)) { + unsigned start = pos & (PAGE_CACHE_SIZE - 1); + unsigned end = start + len; + + /* Reading beyond i_size is simple: memset to zero */ + zero_user_segments(page, 0, start, end, PAGE_CACHE_SIZE); + goto out; + } + + if (dn.data_blkaddr == NEW_ADDR) { + zero_user_segment(page, 0, PAGE_CACHE_SIZE); + } else { + if (f2fs_has_inline_data(inode)) { + err = f2fs_read_inline_data(inode, page); + if (err) { + page_cache_release(page); + return err; + } + } else { + err = f2fs_submit_page_bio(sbi, page, dn.data_blkaddr, + READ_SYNC); + if (err) + return err; + } + + lock_page(page); + if (unlikely(!PageUptodate(page))) { + f2fs_put_page(page, 1); + return -EIO; + } + if (unlikely(page->mapping != mapping)) { + f2fs_put_page(page, 1); + goto repeat; + } + } +out: + SetPageUptodate(page); + clear_cold_data(page); + return 0; +} + +static int f2fs_write_end(struct file *file, + struct address_space *mapping, + loff_t pos, unsigned len, unsigned copied, + struct page *page, void *fsdata) +{ + struct inode *inode = page->mapping->host; + + trace_f2fs_write_end(inode, pos, len, copied); + + set_page_dirty(page); + + if (pos + copied > i_size_read(inode)) { + i_size_write(inode, pos + copied); + mark_inode_dirty(inode); + update_inode_page(inode); + } + + f2fs_put_page(page, 1); + return copied; +} + +static int check_direct_IO(struct inode *inode, int rw, + const struct iovec *iov, loff_t offset, unsigned long nr_segs) +{ + unsigned blocksize_mask = inode->i_sb->s_blocksize - 1; + int i; + + if (rw == READ) + return 0; + + if (offset & blocksize_mask) + return -EINVAL; + + for (i = 0; i < nr_segs; i++) + if (iov[i].iov_len & blocksize_mask) + return -EINVAL; + return 0; +} + +static ssize_t f2fs_direct_IO(int rw, struct kiocb *iocb, + const struct iovec *iov, loff_t offset, unsigned long nr_segs) +{ + struct file *file = iocb->ki_filp; + struct inode *inode = file->f_mapping->host; + + /* Let buffer I/O handle the inline data case. */ + if (f2fs_has_inline_data(inode)) + return 0; + + if (check_direct_IO(inode, rw, iov, offset, nr_segs)) + return 0; + + /* clear fsync mark to recover these blocks */ + fsync_mark_clear(F2FS_SB(inode->i_sb), inode->i_ino); + + return blockdev_direct_IO(rw, iocb, inode, iov, offset, nr_segs, + get_data_block); +} + +static void f2fs_invalidate_data_page(struct page *page, unsigned long offset) +{ + struct inode *inode = page->mapping->host; + if (PageDirty(page)) + inode_dec_dirty_dents(inode); + ClearPagePrivate(page); +} + +static int f2fs_release_data_page(struct page *page, gfp_t wait) +{ + ClearPagePrivate(page); + return 1; +} + +static int f2fs_set_data_page_dirty(struct page *page) +{ + struct address_space *mapping = page->mapping; + struct inode *inode = mapping->host; + + trace_f2fs_set_page_dirty(page, DATA); + + SetPageUptodate(page); + mark_inode_dirty(inode); + + if (!PageDirty(page)) { + __set_page_dirty_nobuffers(page); + set_dirty_dir_page(inode, page); + return 1; + } + return 0; +} + +static sector_t f2fs_bmap(struct address_space *mapping, sector_t block) +{ + struct inode *inode = mapping->host; + + if (f2fs_has_inline_data(inode)) + return 0; + + return generic_block_bmap(mapping, block, get_data_block); +} + +const struct address_space_operations f2fs_dblock_aops = { + .readpage = f2fs_read_data_page, + .readpages = f2fs_read_data_pages, + .writepage = f2fs_write_data_page, + .writepages = f2fs_write_data_pages, + .write_begin = f2fs_write_begin, + .write_end = f2fs_write_end, + .set_page_dirty = f2fs_set_data_page_dirty, + .invalidatepage = f2fs_invalidate_data_page, + .releasepage = f2fs_release_data_page, + .direct_IO = f2fs_direct_IO, + .bmap = f2fs_bmap, +}; diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c new file mode 100644 index 00000000000..b52c12cf587 --- /dev/null +++ b/fs/f2fs/debug.c @@ -0,0 +1,372 @@ +/* + * f2fs debugging statistics + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * Copyright (c) 2012 Linux Foundation + * Copyright (c) 2012 Greg Kroah-Hartman + * + * 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 "f2fs.h" +#include "node.h" +#include "segment.h" +#include "gc.h" + +static LIST_HEAD(f2fs_stat_list); +static struct dentry *f2fs_debugfs_root; +static DEFINE_MUTEX(f2fs_stat_mutex); + +static void update_general_status(struct f2fs_sb_info *sbi) +{ + struct f2fs_stat_info *si = F2FS_STAT(sbi); + int i; + + /* valid check of the segment numbers */ + si->hit_ext = sbi->read_hit_ext; + si->total_ext = sbi->total_hit_ext; + si->ndirty_node = get_pages(sbi, F2FS_DIRTY_NODES); + si->ndirty_dent = get_pages(sbi, F2FS_DIRTY_DENTS); + si->ndirty_dirs = sbi->n_dirty_dirs; + si->ndirty_meta = get_pages(sbi, F2FS_DIRTY_META); + si->total_count = (int)sbi->user_block_count / sbi->blocks_per_seg; + si->rsvd_segs = reserved_segments(sbi); + si->overp_segs = overprovision_segments(sbi); + si->valid_count = valid_user_blocks(sbi); + si->valid_node_count = valid_node_count(sbi); + si->valid_inode_count = valid_inode_count(sbi); + si->inline_inode = sbi->inline_inode; + si->utilization = utilization(sbi); + + si->free_segs = free_segments(sbi); + si->free_secs = free_sections(sbi); + si->prefree_count = prefree_segments(sbi); + si->dirty_count = dirty_segments(sbi); + si->node_pages = NODE_MAPPING(sbi)->nrpages; + si->meta_pages = META_MAPPING(sbi)->nrpages; + si->nats = NM_I(sbi)->nat_cnt; + si->sits = SIT_I(sbi)->dirty_sentries; + si->fnids = NM_I(sbi)->fcnt; + si->bg_gc = sbi->bg_gc; + si->util_free = (int)(free_user_blocks(sbi) >> sbi->log_blocks_per_seg) + * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg) + / 2; + si->util_valid = (int)(written_block_count(sbi) >> + sbi->log_blocks_per_seg) + * 100 / (int)(sbi->user_block_count >> sbi->log_blocks_per_seg) + / 2; + si->util_invalid = 50 - si->util_free - si->util_valid; + for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_NODE; i++) { + struct curseg_info *curseg = CURSEG_I(sbi, i); + si->curseg[i] = curseg->segno; + si->cursec[i] = curseg->segno / sbi->segs_per_sec; + si->curzone[i] = si->cursec[i] / sbi->secs_per_zone; + } + + for (i = 0; i < 2; i++) { + si->segment_count[i] = sbi->segment_count[i]; + si->block_count[i] = sbi->block_count[i]; + } +} + +/* + * This function calculates BDF of every segments + */ +static void update_sit_info(struct f2fs_sb_info *sbi) +{ + struct f2fs_stat_info *si = F2FS_STAT(sbi); + unsigned int blks_per_sec, hblks_per_sec, total_vblocks, bimodal, dist; + unsigned int segno, vblocks; + int ndirty = 0; + + bimodal = 0; + total_vblocks = 0; + blks_per_sec = sbi->segs_per_sec * (1 << sbi->log_blocks_per_seg); + hblks_per_sec = blks_per_sec / 2; + for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) { + vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec); + dist = abs(vblocks - hblks_per_sec); + bimodal += dist * dist; + + if (vblocks > 0 && vblocks < blks_per_sec) { + total_vblocks += vblocks; + ndirty++; + } + } + dist = TOTAL_SECS(sbi) * hblks_per_sec * hblks_per_sec / 100; + si->bimodal = bimodal / dist; + if (si->dirty_count) + si->avg_vblocks = total_vblocks / ndirty; + else + si->avg_vblocks = 0; +} + +/* + * This function calculates memory footprint. + */ +static void update_mem_info(struct f2fs_sb_info *sbi) +{ + struct f2fs_stat_info *si = F2FS_STAT(sbi); + unsigned npages; + + if (si->base_mem) + goto get_cache; + + si->base_mem = sizeof(struct f2fs_sb_info) + sbi->sb->s_blocksize; + si->base_mem += 2 * sizeof(struct f2fs_inode_info); + si->base_mem += sizeof(*sbi->ckpt); + + /* build sm */ + si->base_mem += sizeof(struct f2fs_sm_info); + + /* build sit */ + si->base_mem += sizeof(struct sit_info); + si->base_mem += TOTAL_SEGS(sbi) * sizeof(struct seg_entry); + si->base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi)); + si->base_mem += 2 * SIT_VBLOCK_MAP_SIZE * TOTAL_SEGS(sbi); + if (sbi->segs_per_sec > 1) + si->base_mem += TOTAL_SECS(sbi) * sizeof(struct sec_entry); + si->base_mem += __bitmap_size(sbi, SIT_BITMAP); + + /* build free segmap */ + si->base_mem += sizeof(struct free_segmap_info); + si->base_mem += f2fs_bitmap_size(TOTAL_SEGS(sbi)); + si->base_mem += f2fs_bitmap_size(TOTAL_SECS(sbi)); + + /* build curseg */ + si->base_mem += sizeof(struct curseg_info) * NR_CURSEG_TYPE; + si->base_mem += PAGE_CACHE_SIZE * NR_CURSEG_TYPE; + + /* build dirty segmap */ + si->base_mem += sizeof(struct dirty_seglist_info); + si->base_mem += NR_DIRTY_TYPE * f2fs_bitmap_size(TOTAL_SEGS(sbi)); + si->base_mem += f2fs_bitmap_size(TOTAL_SECS(sbi)); + + /* buld nm */ + si->base_mem += sizeof(struct f2fs_nm_info); + si->base_mem += __bitmap_size(sbi, NAT_BITMAP); + + /* build gc */ + si->base_mem += sizeof(struct f2fs_gc_kthread); + +get_cache: + /* free nids */ + si->cache_mem = NM_I(sbi)->fcnt; + si->cache_mem += NM_I(sbi)->nat_cnt; + npages = NODE_MAPPING(sbi)->nrpages; + si->cache_mem += npages << PAGE_CACHE_SHIFT; + npages = META_MAPPING(sbi)->nrpages; + si->cache_mem += npages << PAGE_CACHE_SHIFT; + si->cache_mem += sbi->n_orphans * sizeof(struct orphan_inode_entry); + si->cache_mem += sbi->n_dirty_dirs * sizeof(struct dir_inode_entry); +} + +static int stat_show(struct seq_file *s, void *v) +{ + struct f2fs_stat_info *si; + int i = 0; + int j; + + mutex_lock(&f2fs_stat_mutex); + list_for_each_entry(si, &f2fs_stat_list, stat_list) { + char devname[BDEVNAME_SIZE]; + + update_general_status(si->sbi); + + seq_printf(s, "\n=====[ partition info(%s). #%d ]=====\n", + bdevname(si->sbi->sb->s_bdev, devname), i++); + seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ", + si->sit_area_segs, si->nat_area_segs); + seq_printf(s, "[SSA: %d] [MAIN: %d", + si->ssa_area_segs, si->main_area_segs); + seq_printf(s, "(OverProv:%d Resv:%d)]\n\n", + si->overp_segs, si->rsvd_segs); + seq_printf(s, "Utilization: %d%% (%d valid blocks)\n", + si->utilization, si->valid_count); + seq_printf(s, " - Node: %u (Inode: %u, ", + si->valid_node_count, si->valid_inode_count); + seq_printf(s, "Other: %u)\n - Data: %u\n", + si->valid_node_count - si->valid_inode_count, + si->valid_count - si->valid_node_count); + seq_printf(s, " - Inline_data Inode: %u\n", + si->inline_inode); + seq_printf(s, "\nMain area: %d segs, %d secs %d zones\n", + si->main_area_segs, si->main_area_sections, + si->main_area_zones); + seq_printf(s, " - COLD data: %d, %d, %d\n", + si->curseg[CURSEG_COLD_DATA], + si->cursec[CURSEG_COLD_DATA], + si->curzone[CURSEG_COLD_DATA]); + seq_printf(s, " - WARM data: %d, %d, %d\n", + si->curseg[CURSEG_WARM_DATA], + si->cursec[CURSEG_WARM_DATA], + si->curzone[CURSEG_WARM_DATA]); + seq_printf(s, " - HOT data: %d, %d, %d\n", + si->curseg[CURSEG_HOT_DATA], + si->cursec[CURSEG_HOT_DATA], + si->curzone[CURSEG_HOT_DATA]); + seq_printf(s, " - Dir dnode: %d, %d, %d\n", + si->curseg[CURSEG_HOT_NODE], + si->cursec[CURSEG_HOT_NODE], + si->curzone[CURSEG_HOT_NODE]); + seq_printf(s, " - File dnode: %d, %d, %d\n", + si->curseg[CURSEG_WARM_NODE], + si->cursec[CURSEG_WARM_NODE], + si->curzone[CURSEG_WARM_NODE]); + seq_printf(s, " - Indir nodes: %d, %d, %d\n", + si->curseg[CURSEG_COLD_NODE], + si->cursec[CURSEG_COLD_NODE], + si->curzone[CURSEG_COLD_NODE]); + seq_printf(s, "\n - Valid: %d\n - Dirty: %d\n", + si->main_area_segs - si->dirty_count - + si->prefree_count - si->free_segs, + si->dirty_count); + seq_printf(s, " - Prefree: %d\n - Free: %d (%d)\n\n", + si->prefree_count, si->free_segs, si->free_secs); + seq_printf(s, "CP calls: %d\n", si->cp_count); + seq_printf(s, "GC calls: %d (BG: %d)\n", + si->call_count, si->bg_gc); + seq_printf(s, " - data segments : %d\n", si->data_segs); + seq_printf(s, " - node segments : %d\n", si->node_segs); + seq_printf(s, "Try to move %d blocks\n", si->tot_blks); + seq_printf(s, " - data blocks : %d\n", si->data_blks); + seq_printf(s, " - node blocks : %d\n", si->node_blks); + seq_printf(s, "\nExtent Hit Ratio: %d / %d\n", + si->hit_ext, si->total_ext); + seq_puts(s, "\nBalancing F2FS Async:\n"); + seq_printf(s, " - nodes: %4d in %4d\n", + si->ndirty_node, si->node_pages); + seq_printf(s, " - dents: %4d in dirs:%4d\n", + si->ndirty_dent, si->ndirty_dirs); + seq_printf(s, " - meta: %4d in %4d\n", + si->ndirty_meta, si->meta_pages); + seq_printf(s, " - NATs: %9d\n - SITs: %9d\n", + si->nats, si->sits); + seq_printf(s, " - free_nids: %9d\n", + si->fnids); + seq_puts(s, "\nDistribution of User Blocks:"); + seq_puts(s, " [ valid | invalid | free ]\n"); + seq_puts(s, " ["); + + for (j = 0; j < si->util_valid; j++) + seq_putc(s, '-'); + seq_putc(s, '|'); + + for (j = 0; j < si->util_invalid; j++) + seq_putc(s, '-'); + seq_putc(s, '|'); + + for (j = 0; j < si->util_free; j++) + seq_putc(s, '-'); + seq_puts(s, "]\n\n"); + seq_printf(s, "SSR: %u blocks in %u segments\n", + si->block_count[SSR], si->segment_count[SSR]); + seq_printf(s, "LFS: %u blocks in %u segments\n", + si->block_count[LFS], si->segment_count[LFS]); + + /* segment usage info */ + update_sit_info(si->sbi); + seq_printf(s, "\nBDF: %u, avg. vblocks: %u\n", + si->bimodal, si->avg_vblocks); + + /* memory footprint */ + update_mem_info(si->sbi); + seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n", + (si->base_mem + si->cache_mem) >> 10, + si->base_mem >> 10, si->cache_mem >> 10); + } + mutex_unlock(&f2fs_stat_mutex); + return 0; +} + +static int stat_open(struct inode *inode, struct file *file) +{ + return single_open(file, stat_show, inode->i_private); +} + +static const struct file_operations stat_fops = { + .open = stat_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +int f2fs_build_stats(struct f2fs_sb_info *sbi) +{ + struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); + struct f2fs_stat_info *si; + + si = kzalloc(sizeof(struct f2fs_stat_info), GFP_KERNEL); + if (!si) + return -ENOMEM; + + si->all_area_segs = le32_to_cpu(raw_super->segment_count); + si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit); + si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat); + si->ssa_area_segs = le32_to_cpu(raw_super->segment_count_ssa); + si->main_area_segs = le32_to_cpu(raw_super->segment_count_main); + si->main_area_sections = le32_to_cpu(raw_super->section_count); + si->main_area_zones = si->main_area_sections / + le32_to_cpu(raw_super->secs_per_zone); + si->sbi = sbi; + sbi->stat_info = si; + + mutex_lock(&f2fs_stat_mutex); + list_add_tail(&si->stat_list, &f2fs_stat_list); + mutex_unlock(&f2fs_stat_mutex); + + return 0; +} + +void f2fs_destroy_stats(struct f2fs_sb_info *sbi) +{ + struct f2fs_stat_info *si = F2FS_STAT(sbi); + + mutex_lock(&f2fs_stat_mutex); + list_del(&si->stat_list); + mutex_unlock(&f2fs_stat_mutex); + + kfree(si); +} + +void __init f2fs_create_root_stats(void) +{ + struct dentry *file; + + f2fs_debugfs_root = debugfs_create_dir("f2fs", NULL); + if (!f2fs_debugfs_root) + goto bail; + + file = debugfs_create_file("status", S_IRUGO, f2fs_debugfs_root, + NULL, &stat_fops); + if (!file) + goto free_debugfs_dir; + + return; + +free_debugfs_dir: + debugfs_remove(f2fs_debugfs_root); + +bail: + f2fs_debugfs_root = NULL; + return; +} + +void f2fs_destroy_root_stats(void) +{ + if (!f2fs_debugfs_root) + return; + + debugfs_remove_recursive(f2fs_debugfs_root); + f2fs_debugfs_root = NULL; +} diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c new file mode 100644 index 00000000000..a2e0d7509db --- /dev/null +++ b/fs/f2fs/dir.c @@ -0,0 +1,749 @@ +/* + * fs/f2fs/dir.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include "f2fs.h" +#include "node.h" +#include "acl.h" +#include "xattr.h" + +static unsigned long dir_blocks(struct inode *inode) +{ + return ((unsigned long long) (i_size_read(inode) + PAGE_CACHE_SIZE - 1)) + >> PAGE_CACHE_SHIFT; +} + +static unsigned int dir_buckets(unsigned int level, int dir_level) +{ + if (level + dir_level < MAX_DIR_HASH_DEPTH / 2) + return 1 << (level + dir_level); + else + return MAX_DIR_BUCKETS; +} + +static unsigned int bucket_blocks(unsigned int level) +{ + if (level < MAX_DIR_HASH_DEPTH / 2) + return 2; + else + return 4; +} + +static unsigned char f2fs_filetype_table[F2FS_FT_MAX] = { + [F2FS_FT_UNKNOWN] = DT_UNKNOWN, + [F2FS_FT_REG_FILE] = DT_REG, + [F2FS_FT_DIR] = DT_DIR, + [F2FS_FT_CHRDEV] = DT_CHR, + [F2FS_FT_BLKDEV] = DT_BLK, + [F2FS_FT_FIFO] = DT_FIFO, + [F2FS_FT_SOCK] = DT_SOCK, + [F2FS_FT_SYMLINK] = DT_LNK, +}; + +#define S_SHIFT 12 +static unsigned char f2fs_type_by_mode[S_IFMT >> S_SHIFT] = { + [S_IFREG >> S_SHIFT] = F2FS_FT_REG_FILE, + [S_IFDIR >> S_SHIFT] = F2FS_FT_DIR, + [S_IFCHR >> S_SHIFT] = F2FS_FT_CHRDEV, + [S_IFBLK >> S_SHIFT] = F2FS_FT_BLKDEV, + [S_IFIFO >> S_SHIFT] = F2FS_FT_FIFO, + [S_IFSOCK >> S_SHIFT] = F2FS_FT_SOCK, + [S_IFLNK >> S_SHIFT] = F2FS_FT_SYMLINK, +}; + +static void set_de_type(struct f2fs_dir_entry *de, struct inode *inode) +{ + mode_t mode = inode->i_mode; + de->file_type = f2fs_type_by_mode[(mode & S_IFMT) >> S_SHIFT]; +} + +static unsigned long dir_block_index(unsigned int level, + int dir_level, unsigned int idx) +{ + unsigned long i; + unsigned long bidx = 0; + + for (i = 0; i < level; i++) + bidx += dir_buckets(i, dir_level) * bucket_blocks(i); + bidx += idx * bucket_blocks(level); + return bidx; +} + +static bool early_match_name(size_t namelen, f2fs_hash_t namehash, + struct f2fs_dir_entry *de) +{ + if (le16_to_cpu(de->name_len) != namelen) + return false; + + if (de->hash_code != namehash) + return false; + + return true; +} + +static struct f2fs_dir_entry *find_in_block(struct page *dentry_page, + struct qstr *name, int *max_slots, + f2fs_hash_t namehash, struct page **res_page, + bool nocase) +{ + struct f2fs_dir_entry *de; + unsigned long bit_pos = 0; + struct f2fs_dentry_block *dentry_blk = kmap(dentry_page); + const void *dentry_bits = &dentry_blk->dentry_bitmap; + int max_len = 0; + + while (bit_pos < NR_DENTRY_IN_BLOCK) { + if (!test_bit_le(bit_pos, dentry_bits)) { + if (bit_pos == 0) + max_len = 1; + else if (!test_bit_le(bit_pos - 1, dentry_bits)) + max_len++; + bit_pos++; + continue; + } + de = &dentry_blk->dentry[bit_pos]; + if (nocase) { + if ((le16_to_cpu(de->name_len) == name->len) && + !strncasecmp(dentry_blk->filename[bit_pos], + name->name, name->len)) { + *res_page = dentry_page; + goto found; + } + } else if (early_match_name(name->len, namehash, de)) { + if (!memcmp(dentry_blk->filename[bit_pos], + name->name, + name->len)) { + *res_page = dentry_page; + goto found; + } + } + if (max_len > *max_slots) { + *max_slots = max_len; + max_len = 0; + } + bit_pos += GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); + } + + de = NULL; + kunmap(dentry_page); +found: + if (max_len > *max_slots) + *max_slots = max_len; + return de; +} + +static struct f2fs_dir_entry *find_in_level(struct inode *dir, + unsigned int level, struct qstr *name, + f2fs_hash_t namehash, struct page **res_page) +{ + int s = GET_DENTRY_SLOTS(name->len); + unsigned int nbucket, nblock; + unsigned int bidx, end_block; + struct page *dentry_page; + struct f2fs_dir_entry *de = NULL; + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + bool room = false; + int max_slots = 0; + + f2fs_bug_on(level > MAX_DIR_HASH_DEPTH); + + nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level); + nblock = bucket_blocks(level); + + bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level, + le32_to_cpu(namehash) % nbucket); + end_block = bidx + nblock; + + for (; bidx < end_block; bidx++) { + bool nocase = false; + + /* no need to allocate new dentry pages to all the indices */ + dentry_page = find_data_page(dir, bidx, true); + if (IS_ERR(dentry_page)) { + room = true; + continue; + } + + if (test_opt(sbi, ANDROID_EMU) && + (sbi->android_emu_flags & F2FS_ANDROID_EMU_NOCASE) && + F2FS_I(dir)->i_advise & FADVISE_ANDROID_EMU) + nocase = true; + + de = find_in_block(dentry_page, name, &max_slots, + namehash, res_page, nocase); + if (de) + break; + + if (max_slots >= s) + room = true; + f2fs_put_page(dentry_page, 0); + } + + if (!de && room && F2FS_I(dir)->chash != namehash) { + F2FS_I(dir)->chash = namehash; + F2FS_I(dir)->clevel = level; + } + + return de; +} + +/* + * Find an entry in the specified directory with the wanted name. + * It returns the page where the entry was found (as a parameter - res_page), + * and the entry itself. Page is returned mapped and unlocked. + * Entry is guaranteed to be valid. + */ +struct f2fs_dir_entry *f2fs_find_entry(struct inode *dir, + struct qstr *child, struct page **res_page) +{ + unsigned long npages = dir_blocks(dir); + struct f2fs_dir_entry *de = NULL; + f2fs_hash_t name_hash; + unsigned int max_depth; + unsigned int level; + + if (npages == 0) + return NULL; + + *res_page = NULL; + + name_hash = f2fs_dentry_hash(child); + max_depth = F2FS_I(dir)->i_current_depth; + + for (level = 0; level < max_depth; level++) { + de = find_in_level(dir, level, child, name_hash, res_page); + if (de) + break; + } + if (!de && F2FS_I(dir)->chash != name_hash) { + F2FS_I(dir)->chash = name_hash; + F2FS_I(dir)->clevel = level - 1; + } + return de; +} + +struct f2fs_dir_entry *f2fs_parent_dir(struct inode *dir, struct page **p) +{ + struct page *page; + struct f2fs_dir_entry *de; + struct f2fs_dentry_block *dentry_blk; + + page = get_lock_data_page(dir, 0); + if (IS_ERR(page)) + return NULL; + + dentry_blk = kmap(page); + de = &dentry_blk->dentry[1]; + *p = page; + unlock_page(page); + return de; +} + +ino_t f2fs_inode_by_name(struct inode *dir, struct qstr *qstr) +{ + ino_t res = 0; + struct f2fs_dir_entry *de; + struct page *page; + + de = f2fs_find_entry(dir, qstr, &page); + if (de) { + res = le32_to_cpu(de->ino); + kunmap(page); + f2fs_put_page(page, 0); + } + + return res; +} + +void f2fs_set_link(struct inode *dir, struct f2fs_dir_entry *de, + struct page *page, struct inode *inode) +{ + lock_page(page); + f2fs_wait_on_page_writeback(page, DATA); + de->ino = cpu_to_le32(inode->i_ino); + set_de_type(de, inode); + kunmap(page); + set_page_dirty(page); + dir->i_mtime = dir->i_ctime = CURRENT_TIME; + mark_inode_dirty(dir); + + f2fs_put_page(page, 1); +} + +static void init_dent_inode(const struct qstr *name, struct page *ipage) +{ + struct f2fs_inode *ri; + + f2fs_wait_on_page_writeback(ipage, NODE); + + /* copy name info. to this inode page */ + ri = F2FS_INODE(ipage); + ri->i_namelen = cpu_to_le32(name->len); + memcpy(ri->i_name, name->name, name->len); + set_page_dirty(ipage); +} + +int update_dent_inode(struct inode *inode, const struct qstr *name) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct page *page; + + page = get_node_page(sbi, inode->i_ino); + if (IS_ERR(page)) + return PTR_ERR(page); + + init_dent_inode(name, page); + f2fs_put_page(page, 1); + + return 0; +} + +static int make_empty_dir(struct inode *inode, + struct inode *parent, struct page *page) +{ + struct page *dentry_page; + struct f2fs_dentry_block *dentry_blk; + struct f2fs_dir_entry *de; + + dentry_page = get_new_data_page(inode, page, 0, true); + if (IS_ERR(dentry_page)) + return PTR_ERR(dentry_page); + + + dentry_blk = kmap_atomic(dentry_page); + + de = &dentry_blk->dentry[0]; + de->name_len = cpu_to_le16(1); + de->hash_code = 0; + de->ino = cpu_to_le32(inode->i_ino); + memcpy(dentry_blk->filename[0], ".", 1); + set_de_type(de, inode); + + de = &dentry_blk->dentry[1]; + de->hash_code = 0; + de->name_len = cpu_to_le16(2); + de->ino = cpu_to_le32(parent->i_ino); + memcpy(dentry_blk->filename[1], "..", 2); + set_de_type(de, inode); + + test_and_set_bit_le(0, &dentry_blk->dentry_bitmap); + test_and_set_bit_le(1, &dentry_blk->dentry_bitmap); + kunmap_atomic(dentry_blk); + + set_page_dirty(dentry_page); + f2fs_put_page(dentry_page, 1); + return 0; +} + +static struct page *init_inode_metadata(struct inode *inode, + struct inode *dir, const struct qstr *name) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + struct page *page; + int err; + + if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { + page = new_inode_page(inode); + if (IS_ERR(page)) + return page; + + if (S_ISDIR(inode->i_mode)) { + err = make_empty_dir(inode, dir, page); + if (err) + goto error; + } + + err = f2fs_init_acl(inode, dir, page); + if (err) + goto put_error; + + err = f2fs_init_security(inode, dir, name, page); + if (err) + goto put_error; + } else { + page = get_node_page(F2FS_SB(dir->i_sb), inode->i_ino); + if (IS_ERR(page)) + return page; + + set_cold_node(inode, page); + } + + if (name) + init_dent_inode(name, page); + + /* + * This file should be checkpointed during fsync. + * We lost i_pino from now on. + */ + if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) { + file_lost_pino(inode); + /* + * If link the tmpfile to alias through linkat path, + * we should remove this inode from orphan list. + */ + if (inode->i_nlink == 0) + remove_orphan_inode(sbi, inode->i_ino); + inc_nlink(inode); + } + return page; + +put_error: + f2fs_put_page(page, 1); +error: + /* once the failed inode becomes a bad inode, i_mode is S_IFREG */ + truncate_inode_pages(&inode->i_data, 0); + truncate_blocks(inode, 0); + remove_dirty_dir_inode(inode); + remove_inode_page(inode); + return ERR_PTR(err); +} + +static void update_parent_metadata(struct inode *dir, struct inode *inode, + unsigned int current_depth) +{ + if (is_inode_flag_set(F2FS_I(inode), FI_NEW_INODE)) { + if (S_ISDIR(inode->i_mode)) { + inc_nlink(dir); + set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); + } + clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); + } + dir->i_mtime = dir->i_ctime = CURRENT_TIME; + mark_inode_dirty(dir); + + if (F2FS_I(dir)->i_current_depth != current_depth) { + F2FS_I(dir)->i_current_depth = current_depth; + set_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); + } + + if (is_inode_flag_set(F2FS_I(inode), FI_INC_LINK)) + clear_inode_flag(F2FS_I(inode), FI_INC_LINK); +} + +static int room_for_filename(struct f2fs_dentry_block *dentry_blk, int slots) +{ + int bit_start = 0; + int zero_start, zero_end; +next: + zero_start = find_next_zero_bit_le(&dentry_blk->dentry_bitmap, + NR_DENTRY_IN_BLOCK, + bit_start); + if (zero_start >= NR_DENTRY_IN_BLOCK) + return NR_DENTRY_IN_BLOCK; + + zero_end = find_next_bit_le(&dentry_blk->dentry_bitmap, + NR_DENTRY_IN_BLOCK, + zero_start); + if (zero_end - zero_start >= slots) + return zero_start; + + bit_start = zero_end + 1; + + if (zero_end + 1 >= NR_DENTRY_IN_BLOCK) + return NR_DENTRY_IN_BLOCK; + goto next; +} + +/* + * Caller should grab and release a rwsem by calling f2fs_lock_op() and + * f2fs_unlock_op(). + */ +int __f2fs_add_link(struct inode *dir, const struct qstr *name, + struct inode *inode) +{ + unsigned int bit_pos; + unsigned int level; + unsigned int current_depth; + unsigned long bidx, block; + f2fs_hash_t dentry_hash; + struct f2fs_dir_entry *de; + unsigned int nbucket, nblock; + size_t namelen = name->len; + struct page *dentry_page = NULL; + struct f2fs_dentry_block *dentry_blk = NULL; + int slots = GET_DENTRY_SLOTS(namelen); + struct page *page; + int err = 0; + int i; + + dentry_hash = f2fs_dentry_hash(name); + level = 0; + current_depth = F2FS_I(dir)->i_current_depth; + if (F2FS_I(dir)->chash == dentry_hash) { + level = F2FS_I(dir)->clevel; + F2FS_I(dir)->chash = 0; + } + +start: + if (unlikely(current_depth == MAX_DIR_HASH_DEPTH)) + return -ENOSPC; + + /* Increase the depth, if required */ + if (level == current_depth) + ++current_depth; + + nbucket = dir_buckets(level, F2FS_I(dir)->i_dir_level); + nblock = bucket_blocks(level); + + bidx = dir_block_index(level, F2FS_I(dir)->i_dir_level, + (le32_to_cpu(dentry_hash) % nbucket)); + + for (block = bidx; block <= (bidx + nblock - 1); block++) { + dentry_page = get_new_data_page(dir, NULL, block, true); + if (IS_ERR(dentry_page)) + return PTR_ERR(dentry_page); + + dentry_blk = kmap(dentry_page); + bit_pos = room_for_filename(dentry_blk, slots); + if (bit_pos < NR_DENTRY_IN_BLOCK) + goto add_dentry; + + kunmap(dentry_page); + f2fs_put_page(dentry_page, 1); + } + + /* Move to next level to find the empty slot for new dentry */ + ++level; + goto start; +add_dentry: + f2fs_wait_on_page_writeback(dentry_page, DATA); + + down_write(&F2FS_I(inode)->i_sem); + page = init_inode_metadata(inode, dir, name); + if (IS_ERR(page)) { + err = PTR_ERR(page); + goto fail; + } + de = &dentry_blk->dentry[bit_pos]; + de->hash_code = dentry_hash; + de->name_len = cpu_to_le16(namelen); + memcpy(dentry_blk->filename[bit_pos], name->name, name->len); + de->ino = cpu_to_le32(inode->i_ino); + set_de_type(de, inode); + for (i = 0; i < slots; i++) + test_and_set_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); + set_page_dirty(dentry_page); + + /* we don't need to mark_inode_dirty now */ + F2FS_I(inode)->i_pino = dir->i_ino; + update_inode(inode, page); + f2fs_put_page(page, 1); + + update_parent_metadata(dir, inode, current_depth); +fail: + up_write(&F2FS_I(inode)->i_sem); + + if (is_inode_flag_set(F2FS_I(dir), FI_UPDATE_DIR)) { + update_inode_page(dir); + clear_inode_flag(F2FS_I(dir), FI_UPDATE_DIR); + } + kunmap(dentry_page); + f2fs_put_page(dentry_page, 1); + return err; +} + +int f2fs_do_tmpfile(struct inode *inode, struct inode *dir) +{ + struct page *page; + int err = 0; + + down_write(&F2FS_I(inode)->i_sem); + page = init_inode_metadata(inode, dir, NULL); + if (IS_ERR(page)) { + err = PTR_ERR(page); + goto fail; + } + /* we don't need to mark_inode_dirty now */ + update_inode(inode, page); + f2fs_put_page(page, 1); + + clear_inode_flag(F2FS_I(inode), FI_NEW_INODE); +fail: + up_write(&F2FS_I(inode)->i_sem); + return err; +} + +/* + * It only removes the dentry from the dentry page,corresponding name + * entry in name page does not need to be touched during deletion. + */ +void f2fs_delete_entry(struct f2fs_dir_entry *dentry, struct page *page, + struct inode *inode) +{ + struct f2fs_dentry_block *dentry_blk; + unsigned int bit_pos; + struct address_space *mapping = page->mapping; + struct inode *dir = mapping->host; + int slots = GET_DENTRY_SLOTS(le16_to_cpu(dentry->name_len)); + int i; + + lock_page(page); + f2fs_wait_on_page_writeback(page, DATA); + + dentry_blk = page_address(page); + bit_pos = dentry - dentry_blk->dentry; + for (i = 0; i < slots; i++) + test_and_clear_bit_le(bit_pos + i, &dentry_blk->dentry_bitmap); + + /* Let's check and deallocate this dentry page */ + bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, + NR_DENTRY_IN_BLOCK, + 0); + kunmap(page); /* kunmap - pair of f2fs_find_entry */ + set_page_dirty(page); + + dir->i_ctime = dir->i_mtime = CURRENT_TIME; + + if (inode) { + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + + down_write(&F2FS_I(inode)->i_sem); + + if (S_ISDIR(inode->i_mode)) { + drop_nlink(dir); + update_inode_page(dir); + } + inode->i_ctime = CURRENT_TIME; + drop_nlink(inode); + if (S_ISDIR(inode->i_mode)) { + drop_nlink(inode); + i_size_write(inode, 0); + } + up_write(&F2FS_I(inode)->i_sem); + update_inode_page(inode); + + if (inode->i_nlink == 0) + add_orphan_inode(sbi, inode->i_ino); + else + release_orphan_inode(sbi); + } + + if (bit_pos == NR_DENTRY_IN_BLOCK) { + truncate_hole(dir, page->index, page->index + 1); + clear_page_dirty_for_io(page); + ClearPageUptodate(page); + inode_dec_dirty_dents(dir); + } + f2fs_put_page(page, 1); +} + +bool f2fs_empty_dir(struct inode *dir) +{ + unsigned long bidx; + struct page *dentry_page; + unsigned int bit_pos; + struct f2fs_dentry_block *dentry_blk; + unsigned long nblock = dir_blocks(dir); + + for (bidx = 0; bidx < nblock; bidx++) { + dentry_page = get_lock_data_page(dir, bidx); + if (IS_ERR(dentry_page)) { + if (PTR_ERR(dentry_page) == -ENOENT) + continue; + else + return false; + } + + + dentry_blk = kmap_atomic(dentry_page); + if (bidx == 0) + bit_pos = 2; + else + bit_pos = 0; + bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, + NR_DENTRY_IN_BLOCK, + bit_pos); + kunmap_atomic(dentry_blk); + + f2fs_put_page(dentry_page, 1); + + if (bit_pos < NR_DENTRY_IN_BLOCK) + return false; + } + return true; +} + +static int f2fs_readdir(struct file *file, void *dirent, filldir_t filldir) +{ + unsigned long pos = file->f_pos; + struct inode *inode = file->f_dentry->d_inode; + unsigned long npages = dir_blocks(inode); + unsigned char *types = f2fs_filetype_table; + unsigned int bit_pos = 0, start_bit_pos = 0; + int over = 0; + struct f2fs_dentry_block *dentry_blk = NULL; + struct f2fs_dir_entry *de = NULL; + struct page *dentry_page = NULL; + struct file_ra_state *ra = &file->f_ra; + unsigned int n = (pos / NR_DENTRY_IN_BLOCK); + unsigned char d_type = DT_UNKNOWN; + int slots; + + bit_pos = (pos % NR_DENTRY_IN_BLOCK); + + /* readahead for multi pages of dir */ + if (npages - n > 1 && !ra_has_index(ra, n)) + page_cache_sync_readahead(inode->i_mapping, ra, file, n, + min(npages - n, (pgoff_t)MAX_DIR_RA_PAGES)); + + for (; n < npages; n++) { + dentry_page = get_lock_data_page(inode, n); + if (IS_ERR(dentry_page)) + continue; + + start_bit_pos = bit_pos; + dentry_blk = kmap(dentry_page); + while (bit_pos < NR_DENTRY_IN_BLOCK) { + d_type = DT_UNKNOWN; + bit_pos = find_next_bit_le(&dentry_blk->dentry_bitmap, + NR_DENTRY_IN_BLOCK, + bit_pos); + if (bit_pos >= NR_DENTRY_IN_BLOCK) + break; + + de = &dentry_blk->dentry[bit_pos]; + if (types && de->file_type < F2FS_FT_MAX) + d_type = types[de->file_type]; + + over = filldir(dirent, + dentry_blk->filename[bit_pos], + le16_to_cpu(de->name_len), + (n * NR_DENTRY_IN_BLOCK) + bit_pos, + le32_to_cpu(de->ino), d_type); + if (over) { + file->f_pos += bit_pos - start_bit_pos; + goto success; + } + slots = GET_DENTRY_SLOTS(le16_to_cpu(de->name_len)); + bit_pos += slots; + } + bit_pos = 0; + file->f_pos = (n + 1) * NR_DENTRY_IN_BLOCK; + kunmap(dentry_page); + f2fs_put_page(dentry_page, 1); + dentry_page = NULL; + } +success: + if (dentry_page && !IS_ERR(dentry_page)) { + kunmap(dentry_page); + f2fs_put_page(dentry_page, 1); + } + + return 0; +} + +const struct file_operations f2fs_dir_operations = { + .llseek = generic_file_llseek, + .read = generic_read_dir, + .readdir = f2fs_readdir, + .fsync = f2fs_sync_file, + .unlocked_ioctl = f2fs_ioctl, +}; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h new file mode 100644 index 00000000000..b09395992fa --- /dev/null +++ b/fs/f2fs/f2fs.h @@ -0,0 +1,1474 @@ +/* + * fs/f2fs/f2fs.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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 _LINUX_F2FS_H +#define _LINUX_F2FS_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_F2FS_CHECK_FS +#define f2fs_bug_on(condition) BUG_ON(condition) +#else +#define f2fs_bug_on(condition) +#endif + +/* + * For mount options + */ +#define F2FS_MOUNT_BG_GC 0x00000001 +#define F2FS_MOUNT_DISABLE_ROLL_FORWARD 0x00000002 +#define F2FS_MOUNT_DISCARD 0x00000004 +#define F2FS_MOUNT_NOHEAP 0x00000008 +#define F2FS_MOUNT_XATTR_USER 0x00000010 +#define F2FS_MOUNT_POSIX_ACL 0x00000020 +#define F2FS_MOUNT_DISABLE_EXT_IDENTIFY 0x00000040 +#define F2FS_MOUNT_INLINE_XATTR 0x00000080 +#define F2FS_MOUNT_ANDROID_EMU 0x00001000 +#define F2FS_MOUNT_ERRORS_PANIC 0x00002000 +#define F2FS_MOUNT_ERRORS_RECOVER 0x00004000 +#define F2FS_MOUNT_INLINE_DATA 0x00000100 +#define F2FS_MOUNT_FLUSH_MERGE 0x00000200 + +#define clear_opt(sbi, option) (sbi->mount_opt.opt &= ~F2FS_MOUNT_##option) +#define set_opt(sbi, option) (sbi->mount_opt.opt |= F2FS_MOUNT_##option) +#define test_opt(sbi, option) (sbi->mount_opt.opt & F2FS_MOUNT_##option) + +#define ver_after(a, b) (typecheck(unsigned long long, a) && \ + typecheck(unsigned long long, b) && \ + ((long long)((a) - (b)) > 0)) + +typedef u32 block_t; /* + * should not change u32, since it is the on-disk block + * address format, __le32. + */ +typedef u32 nid_t; + +struct f2fs_mount_info { + unsigned int opt; +}; + +#define CRCPOLY_LE 0xedb88320 + +static inline __u32 f2fs_crc32(void *buf, size_t len) +{ + unsigned char *p = (unsigned char *)buf; + __u32 crc = F2FS_SUPER_MAGIC; + int i; + + while (len--) { + crc ^= *p++; + for (i = 0; i < 8; i++) + crc = (crc >> 1) ^ ((crc & 1) ? CRCPOLY_LE : 0); + } + return crc; +} + +static inline bool f2fs_crc_valid(__u32 blk_crc, void *buf, size_t buf_size) +{ + return f2fs_crc32(buf, buf_size) == blk_crc; +} + +/* + * For checkpoint manager + */ +enum { + NAT_BITMAP, + SIT_BITMAP +}; + +/* + * For CP/NAT/SIT/SSA readahead + */ +enum { + META_CP, + META_NAT, + META_SIT, + META_SSA +}; + +/* for the list of orphan inodes */ +struct orphan_inode_entry { + struct list_head list; /* list head */ + nid_t ino; /* inode number */ +}; + +/* for the list of directory inodes */ +struct dir_inode_entry { + struct list_head list; /* list head */ + struct inode *inode; /* vfs inode pointer */ +}; + +/* for the list of blockaddresses to be discarded */ +struct discard_entry { + struct list_head list; /* list head */ + block_t blkaddr; /* block address to be discarded */ + int len; /* # of consecutive blocks of the discard */ +}; + +/* for the list of fsync inodes, used only during recovery */ +struct fsync_inode_entry { + struct list_head list; /* list head */ + struct inode *inode; /* vfs inode pointer */ + block_t blkaddr; /* block address locating the last inode */ +}; + +#define nats_in_cursum(sum) (le16_to_cpu(sum->n_nats)) +#define sits_in_cursum(sum) (le16_to_cpu(sum->n_sits)) + +#define nat_in_journal(sum, i) (sum->nat_j.entries[i].ne) +#define nid_in_journal(sum, i) (sum->nat_j.entries[i].nid) +#define sit_in_journal(sum, i) (sum->sit_j.entries[i].se) +#define segno_in_journal(sum, i) (sum->sit_j.entries[i].segno) + +static inline int update_nats_in_cursum(struct f2fs_summary_block *rs, int i) +{ + int before = nats_in_cursum(rs); + rs->n_nats = cpu_to_le16(before + i); + return before; +} + +static inline int update_sits_in_cursum(struct f2fs_summary_block *rs, int i) +{ + int before = sits_in_cursum(rs); + rs->n_sits = cpu_to_le16(before + i); + return before; +} + +/* + * ioctl commands + */ +#define F2FS_IOC_GETFLAGS FS_IOC_GETFLAGS +#define F2FS_IOC_SETFLAGS FS_IOC_SETFLAGS + +#if defined(__KERNEL__) && defined(CONFIG_COMPAT) +/* + * ioctl commands in 32 bit emulation + */ +#define F2FS_IOC32_GETFLAGS FS_IOC32_GETFLAGS +#define F2FS_IOC32_SETFLAGS FS_IOC32_SETFLAGS +#endif + +/* + * For INODE and NODE manager + */ +/* + * XATTR_NODE_OFFSET stores xattrs to one node block per file keeping -1 + * as its node offset to distinguish from index node blocks. + * But some bits are used to mark the node block. + */ +#define XATTR_NODE_OFFSET ((((unsigned int)-1) << OFFSET_BIT_SHIFT) \ + >> OFFSET_BIT_SHIFT) +enum { + ALLOC_NODE, /* allocate a new node page if needed */ + LOOKUP_NODE, /* look up a node without readahead */ + LOOKUP_NODE_RA, /* + * look up a node with readahead called + * by get_data_block. + */ +}; + +#define F2FS_LINK_MAX 32000 /* maximum link count per file */ + +#define MAX_DIR_RA_PAGES 4 /* maximum ra pages of dir */ + +/* for in-memory extent cache entry */ +#define F2FS_MIN_EXTENT_LEN 16 /* minimum extent length */ + +struct extent_info { + rwlock_t ext_lock; /* rwlock for consistency */ + unsigned int fofs; /* start offset in a file */ + u32 blk_addr; /* start block address of the extent */ + unsigned int len; /* length of the extent */ +}; + +/* + * i_advise uses FADVISE_XXX_BIT. We can add additional hints later. + */ +#define FADVISE_COLD_BIT 0x01 +#define FADVISE_LOST_PINO_BIT 0x02 +#define FADVISE_ANDROID_EMU 0x10 +#define FADVISE_ANDROID_EMU_ROOT 0x20 + +#define DEF_DIR_LEVEL 0 + +struct f2fs_inode_info { + struct inode vfs_inode; /* serve a vfs inode */ + unsigned long i_flags; /* keep an inode flags for ioctl */ + unsigned char i_advise; /* use to give file attribute hints */ + unsigned char i_dir_level; /* use for dentry level for large dir */ + unsigned int i_current_depth; /* use only in directory structure */ + unsigned int i_pino; /* parent inode number */ + umode_t i_acl_mode; /* keep file acl mode temporarily */ + + /* Use below internally in f2fs*/ + unsigned long flags; /* use to pass per-file flags */ + struct rw_semaphore i_sem; /* protect fi info */ + atomic_t dirty_dents; /* # of dirty dentry pages */ + f2fs_hash_t chash; /* hash value of given file name */ + unsigned int clevel; /* maximum level of given file name */ + nid_t i_xattr_nid; /* node id that contains xattrs */ + unsigned long long xattr_ver; /* cp version of xattr modification */ + struct extent_info ext; /* in-memory extent cache entry */ + struct dir_inode_entry *dirty_dir; /* the pointer of dirty dir */ +}; + +static inline void get_extent_info(struct extent_info *ext, + struct f2fs_extent i_ext) +{ + write_lock(&ext->ext_lock); + ext->fofs = le32_to_cpu(i_ext.fofs); + ext->blk_addr = le32_to_cpu(i_ext.blk_addr); + ext->len = le32_to_cpu(i_ext.len); + write_unlock(&ext->ext_lock); +} + +static inline void set_raw_extent(struct extent_info *ext, + struct f2fs_extent *i_ext) +{ + read_lock(&ext->ext_lock); + i_ext->fofs = cpu_to_le32(ext->fofs); + i_ext->blk_addr = cpu_to_le32(ext->blk_addr); + i_ext->len = cpu_to_le32(ext->len); + read_unlock(&ext->ext_lock); +} + +struct f2fs_nm_info { + block_t nat_blkaddr; /* base disk address of NAT */ + nid_t max_nid; /* maximum possible node ids */ + nid_t available_nids; /* maximum available node ids */ + nid_t next_scan_nid; /* the next nid to be scanned */ + unsigned int ram_thresh; /* control the memory footprint */ + + /* NAT cache management */ + struct radix_tree_root nat_root;/* root of the nat entry cache */ + rwlock_t nat_tree_lock; /* protect nat_tree_lock */ + unsigned int nat_cnt; /* the # of cached nat entries */ + struct list_head nat_entries; /* cached nat entry list (clean) */ + struct list_head dirty_nat_entries; /* cached nat entry list (dirty) */ + struct list_head nat_entry_set; /* nat entry set list */ + unsigned int dirty_nat_cnt; /* total num of nat entries in set */ + + /* free node ids management */ + struct radix_tree_root free_nid_root;/* root of the free_nid cache */ + struct list_head free_nid_list; /* a list for free nids */ + spinlock_t free_nid_list_lock; /* protect free nid list */ + unsigned int fcnt; /* the number of free node id */ + struct mutex build_lock; /* lock for build free nids */ + + /* for checkpoint */ + char *nat_bitmap; /* NAT bitmap pointer */ + int bitmap_size; /* bitmap size */ +}; + +/* + * this structure is used as one of function parameters. + * all the information are dedicated to a given direct node block determined + * by the data offset in a file. + */ +struct dnode_of_data { + struct inode *inode; /* vfs inode pointer */ + struct page *inode_page; /* its inode page, NULL is possible */ + struct page *node_page; /* cached direct node page */ + nid_t nid; /* node id of the direct node block */ + unsigned int ofs_in_node; /* data offset in the node page */ + bool inode_page_locked; /* inode page is locked or not */ + block_t data_blkaddr; /* block address of the node block */ +}; + +static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode, + struct page *ipage, struct page *npage, nid_t nid) +{ + memset(dn, 0, sizeof(*dn)); + dn->inode = inode; + dn->inode_page = ipage; + dn->node_page = npage; + dn->nid = nid; +} + +/* + * For SIT manager + * + * By default, there are 6 active log areas across the whole main area. + * When considering hot and cold data separation to reduce cleaning overhead, + * we split 3 for data logs and 3 for node logs as hot, warm, and cold types, + * respectively. + * In the current design, you should not change the numbers intentionally. + * Instead, as a mount option such as active_logs=x, you can use 2, 4, and 6 + * logs individually according to the underlying devices. (default: 6) + * Just in case, on-disk layout covers maximum 16 logs that consist of 8 for + * data and 8 for node logs. + */ +#define NR_CURSEG_DATA_TYPE (3) +#define NR_CURSEG_NODE_TYPE (3) +#define NR_CURSEG_TYPE (NR_CURSEG_DATA_TYPE + NR_CURSEG_NODE_TYPE) + +enum { + CURSEG_HOT_DATA = 0, /* directory entry blocks */ + CURSEG_WARM_DATA, /* data blocks */ + CURSEG_COLD_DATA, /* multimedia or GCed data blocks */ + CURSEG_HOT_NODE, /* direct node blocks of directory files */ + CURSEG_WARM_NODE, /* direct node blocks of normal files */ + CURSEG_COLD_NODE, /* indirect node blocks */ + NO_CHECK_TYPE +}; + +struct flush_cmd { + struct flush_cmd *next; + struct completion wait; + int ret; +}; + +struct flush_cmd_control { + struct task_struct *f2fs_issue_flush; /* flush thread */ + wait_queue_head_t flush_wait_queue; /* waiting queue for wake-up */ + struct flush_cmd *issue_list; /* list for command issue */ + struct flush_cmd *dispatch_list; /* list for command dispatch */ + spinlock_t issue_lock; /* for issue list lock */ + struct flush_cmd *issue_tail; /* list tail of issue list */ +}; + +struct f2fs_sm_info { + struct sit_info *sit_info; /* whole segment information */ + struct free_segmap_info *free_info; /* free segment information */ + struct dirty_seglist_info *dirty_info; /* dirty segment information */ + struct curseg_info *curseg_array; /* active segment information */ + + block_t seg0_blkaddr; /* block address of 0'th segment */ + block_t main_blkaddr; /* start block address of main area */ + block_t ssa_blkaddr; /* start block address of SSA area */ + + unsigned int segment_count; /* total # of segments */ + unsigned int main_segments; /* # of segments in main area */ + unsigned int reserved_segments; /* # of reserved segments */ + unsigned int ovp_segments; /* # of overprovision segments */ + + /* a threshold to reclaim prefree segments */ + unsigned int rec_prefree_segments; + + /* for small discard management */ + struct list_head discard_list; /* 4KB discard list */ + int nr_discards; /* # of discards in the list */ + int max_discards; /* max. discards to be issued */ + + unsigned int ipu_policy; /* in-place-update policy */ + unsigned int min_ipu_util; /* in-place-update threshold */ + + /* for flush command control */ + struct task_struct *f2fs_issue_flush; /* flush thread */ + wait_queue_head_t flush_wait_queue; /* waiting queue for wake-up */ + struct flush_cmd *issue_list; /* list for command issue */ + struct flush_cmd *dispatch_list; /* list for command dispatch */ + spinlock_t issue_lock; /* for issue list lock */ + struct flush_cmd *issue_tail; /* list tail of issue list */ + struct flush_cmd_control *cmd_control_info; +}; + +/* + * For superblock + */ +/* + * COUNT_TYPE for monitoring + * + * f2fs monitors the number of several block types such as on-writeback, + * dirty dentry blocks, dirty node blocks, and dirty meta blocks. + */ +enum count_type { + F2FS_WRITEBACK, + F2FS_DIRTY_DENTS, + F2FS_DIRTY_NODES, + F2FS_DIRTY_META, + NR_COUNT_TYPE, +}; + +/* + * The below are the page types of bios used in submti_bio(). + * The available types are: + * DATA User data pages. It operates as async mode. + * NODE Node pages. It operates as async mode. + * META FS metadata pages such as SIT, NAT, CP. + * NR_PAGE_TYPE The number of page types. + * META_FLUSH Make sure the previous pages are written + * with waiting the bio's completion + * ... Only can be used with META. + */ +#define PAGE_TYPE_OF_BIO(type) ((type) > META ? META : (type)) +enum page_type { + DATA, + NODE, + META, + NR_PAGE_TYPE, + META_FLUSH, +}; + +/* + * Android sdcard emulation flags + */ +#define F2FS_ANDROID_EMU_NOCASE 0x00000001 + +struct f2fs_io_info { + enum page_type type; /* contains DATA/NODE/META/META_FLUSH */ + int rw; /* contains R/RS/W/WS with REQ_META/REQ_PRIO */ +}; + +#define is_read_io(rw) (((rw) & 1) == READ) +struct f2fs_bio_info { + struct f2fs_sb_info *sbi; /* f2fs superblock */ + struct bio *bio; /* bios to merge */ + sector_t last_block_in_bio; /* last block number */ + struct f2fs_io_info fio; /* store buffered io info. */ + struct rw_semaphore io_rwsem; /* blocking op for bio */ +}; + +struct f2fs_sb_info { + struct super_block *sb; /* pointer to VFS super block */ + struct proc_dir_entry *s_proc; /* proc entry */ + struct buffer_head *raw_super_buf; /* buffer head of raw sb */ + struct f2fs_super_block *raw_super; /* raw super block pointer */ + int s_dirty; /* dirty flag for checkpoint */ + + /* for node-related operations */ + struct f2fs_nm_info *nm_info; /* node manager */ + struct inode *node_inode; /* cache node blocks */ + + /* for segment-related operations */ + struct f2fs_sm_info *sm_info; /* segment manager */ + + /* for bio operations */ + struct f2fs_bio_info read_io; /* for read bios */ + struct f2fs_bio_info write_io[NR_PAGE_TYPE]; /* for write bios */ + struct completion *wait_io; /* for completion bios */ + + /* for checkpoint */ + struct f2fs_checkpoint *ckpt; /* raw checkpoint pointer */ + struct inode *meta_inode; /* cache meta blocks */ + struct mutex cp_mutex; /* checkpoint procedure lock */ + struct rw_semaphore cp_rwsem; /* blocking FS operations */ + struct mutex node_write; /* locking node writes */ + struct mutex writepages; /* mutex for writepages() */ + bool por_doing; /* recovery is doing or not */ + wait_queue_head_t cp_wait; + + /* for orphan inode management */ + struct list_head orphan_inode_list; /* orphan inode list */ + spinlock_t orphan_inode_lock; /* for orphan inode list */ + unsigned int n_orphans; /* # of orphan inodes */ + unsigned int max_orphans; /* max orphan inodes */ + + /* for directory inode management */ + struct list_head dir_inode_list; /* dir inode list */ + spinlock_t dir_inode_lock; /* for dir inode list lock */ + + /* basic file system units */ + unsigned int log_sectors_per_block; /* log2 sectors per block */ + unsigned int log_blocksize; /* log2 block size */ + unsigned int blocksize; /* block size */ + unsigned int root_ino_num; /* root inode number*/ + unsigned int node_ino_num; /* node inode number*/ + unsigned int meta_ino_num; /* meta inode number*/ + unsigned int log_blocks_per_seg; /* log2 blocks per segment */ + unsigned int blocks_per_seg; /* blocks per segment */ + unsigned int segs_per_sec; /* segments per section */ + unsigned int secs_per_zone; /* sections per zone */ + unsigned int total_sections; /* total section count */ + unsigned int total_node_count; /* total node block count */ + unsigned int total_valid_node_count; /* valid node block count */ + unsigned int total_valid_inode_count; /* valid inode count */ + int active_logs; /* # of active logs */ + int dir_level; /* directory level */ + + block_t user_block_count; /* # of user blocks */ + block_t total_valid_block_count; /* # of valid blocks */ + block_t alloc_valid_block_count; /* # of allocated blocks */ + block_t last_valid_block_count; /* for recovery */ + u32 s_next_generation; /* for NFS support */ + atomic_t nr_pages[NR_COUNT_TYPE]; /* # of pages, see count_type */ + + struct f2fs_mount_info mount_opt; /* mount options */ + + /* for cleaning operations */ + struct mutex gc_mutex; /* mutex for GC */ + struct f2fs_gc_kthread *gc_thread; /* GC thread */ + unsigned int cur_victim_sec; /* current victim section num */ + + /* maximum # of trials to find a victim segment for SSR and GC */ + unsigned int max_victim_search; + + /* + * for stat information. + * one is for the LFS mode, and the other is for the SSR mode. + */ +#ifdef CONFIG_F2FS_STAT_FS + struct f2fs_stat_info *stat_info; /* FS status information */ + unsigned int segment_count[2]; /* # of allocated segments */ + unsigned int block_count[2]; /* # of allocated blocks */ + int total_hit_ext, read_hit_ext; /* extent cache hit ratio */ + int inline_inode; /* # of inline_data inodes */ + int bg_gc; /* background gc calls */ + unsigned int n_dirty_dirs; /* # of dir inodes */ +#endif + unsigned int last_victim[2]; /* last victim segment # */ + spinlock_t stat_lock; /* lock for stat operations */ + + /* For sysfs suppport */ + struct kobject s_kobj; + struct completion s_kobj_unregister; + + /* For Android sdcard emulation */ + u32 android_emu_uid; + u32 android_emu_gid; + umode_t android_emu_mode; + int android_emu_flags; +}; + +/* + * Inline functions + */ +static inline struct f2fs_inode_info *F2FS_I(struct inode *inode) +{ + return container_of(inode, struct f2fs_inode_info, vfs_inode); +} + +static inline struct f2fs_sb_info *F2FS_SB(struct super_block *sb) +{ + return sb->s_fs_info; +} + +static inline struct f2fs_super_block *F2FS_RAW_SUPER(struct f2fs_sb_info *sbi) +{ + return (struct f2fs_super_block *)(sbi->raw_super); +} + +static inline struct f2fs_checkpoint *F2FS_CKPT(struct f2fs_sb_info *sbi) +{ + return (struct f2fs_checkpoint *)(sbi->ckpt); +} + +static inline struct f2fs_node *F2FS_NODE(struct page *page) +{ + return (struct f2fs_node *)page_address(page); +} + +static inline struct f2fs_inode *F2FS_INODE(struct page *page) +{ + return &((struct f2fs_node *)page_address(page))->i; +} + +static inline struct f2fs_nm_info *NM_I(struct f2fs_sb_info *sbi) +{ + return (struct f2fs_nm_info *)(sbi->nm_info); +} + +static inline struct f2fs_sm_info *SM_I(struct f2fs_sb_info *sbi) +{ + return (struct f2fs_sm_info *)(sbi->sm_info); +} + +static inline struct sit_info *SIT_I(struct f2fs_sb_info *sbi) +{ + return (struct sit_info *)(SM_I(sbi)->sit_info); +} + +static inline struct free_segmap_info *FREE_I(struct f2fs_sb_info *sbi) +{ + return (struct free_segmap_info *)(SM_I(sbi)->free_info); +} + +static inline struct dirty_seglist_info *DIRTY_I(struct f2fs_sb_info *sbi) +{ + return (struct dirty_seglist_info *)(SM_I(sbi)->dirty_info); +} + +static inline struct address_space *META_MAPPING(struct f2fs_sb_info *sbi) +{ + return sbi->meta_inode->i_mapping; +} + +static inline struct address_space *NODE_MAPPING(struct f2fs_sb_info *sbi) +{ + return sbi->node_inode->i_mapping; +} + +static inline void F2FS_SET_SB_DIRT(struct f2fs_sb_info *sbi) +{ + sbi->s_dirty = 1; +} + +static inline void F2FS_RESET_SB_DIRT(struct f2fs_sb_info *sbi) +{ + sbi->s_dirty = 0; +} + +static inline unsigned long long cur_cp_version(struct f2fs_checkpoint *cp) +{ + return le64_to_cpu(cp->checkpoint_ver); +} + +static inline bool is_set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f) +{ + unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags); + return ckpt_flags & f; +} + +static inline void set_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f) +{ + unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags); + ckpt_flags |= f; + cp->ckpt_flags = cpu_to_le32(ckpt_flags); +} + +static inline void clear_ckpt_flags(struct f2fs_checkpoint *cp, unsigned int f) +{ + unsigned int ckpt_flags = le32_to_cpu(cp->ckpt_flags); + ckpt_flags &= (~f); + cp->ckpt_flags = cpu_to_le32(ckpt_flags); +} + +static inline void f2fs_lock_op(struct f2fs_sb_info *sbi) +{ + down_read(&sbi->cp_rwsem); +} + +static inline void f2fs_unlock_op(struct f2fs_sb_info *sbi) +{ + up_read(&sbi->cp_rwsem); +} + +static inline void f2fs_lock_all(struct f2fs_sb_info *sbi) +{ + down_write(&sbi->cp_rwsem); +} + +static inline void f2fs_unlock_all(struct f2fs_sb_info *sbi) +{ + up_write(&sbi->cp_rwsem); +} + +/* + * Check whether the given nid is within node id range. + */ +static inline int check_nid_range(struct f2fs_sb_info *sbi, nid_t nid) +{ + if (unlikely(nid < F2FS_ROOT_INO(sbi))) + return -EINVAL; + if (unlikely(nid >= NM_I(sbi)->max_nid)) + return -EINVAL; + return 0; +} + +#define F2FS_DEFAULT_ALLOCATED_BLOCKS 1 + +/* + * Check whether the inode has blocks or not + */ +static inline int F2FS_HAS_BLOCKS(struct inode *inode) +{ + if (F2FS_I(inode)->i_xattr_nid) + return inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS + 1; + else + return inode->i_blocks > F2FS_DEFAULT_ALLOCATED_BLOCKS; +} + +static inline int f2fs_handle_error(struct f2fs_sb_info *sbi) +{ + if (test_opt(sbi, ERRORS_PANIC)) + BUG(); + if (test_opt(sbi, ERRORS_RECOVER)) + return 1; + return 0; +} + +static inline bool f2fs_has_xattr_block(unsigned int ofs) +{ + return ofs == XATTR_NODE_OFFSET; +} + +static inline bool inc_valid_block_count(struct f2fs_sb_info *sbi, + struct inode *inode, blkcnt_t count) +{ + block_t valid_block_count; + + spin_lock(&sbi->stat_lock); + valid_block_count = + sbi->total_valid_block_count + (block_t)count; + if (unlikely(valid_block_count > sbi->user_block_count)) { + spin_unlock(&sbi->stat_lock); + return false; + } + inode->i_blocks += count; + sbi->total_valid_block_count = valid_block_count; + sbi->alloc_valid_block_count += (block_t)count; + spin_unlock(&sbi->stat_lock); + return true; +} + +static inline void dec_valid_block_count(struct f2fs_sb_info *sbi, + struct inode *inode, + blkcnt_t count) +{ + spin_lock(&sbi->stat_lock); + + if (sbi->total_valid_block_count < (block_t)count) { + pr_crit("F2FS-fs (%s): block accounting error: %u < %llu\n", + sbi->sb->s_id, sbi->total_valid_block_count, count); + f2fs_handle_error(sbi); + sbi->total_valid_block_count = count; + } + if (inode->i_blocks < count) { + pr_crit("F2FS-fs (%s): inode accounting error: %llu < %llu\n", + sbi->sb->s_id, inode->i_blocks, count); + f2fs_handle_error(sbi); + inode->i_blocks = count; + } + + inode->i_blocks -= count; + sbi->total_valid_block_count -= (block_t)count; + spin_unlock(&sbi->stat_lock); +} + +static inline void inc_page_count(struct f2fs_sb_info *sbi, int count_type) +{ + atomic_inc(&sbi->nr_pages[count_type]); + F2FS_SET_SB_DIRT(sbi); +} + +static inline void inode_inc_dirty_dents(struct inode *inode) +{ + inc_page_count(F2FS_SB(inode->i_sb), F2FS_DIRTY_DENTS); + atomic_inc(&F2FS_I(inode)->dirty_dents); +} + +static inline void dec_page_count(struct f2fs_sb_info *sbi, int count_type) +{ + atomic_dec(&sbi->nr_pages[count_type]); +} + +static inline void inode_dec_dirty_dents(struct inode *inode) +{ + if (!S_ISDIR(inode->i_mode)) + return; + + dec_page_count(F2FS_SB(inode->i_sb), F2FS_DIRTY_DENTS); + atomic_dec(&F2FS_I(inode)->dirty_dents); +} + +static inline int get_pages(struct f2fs_sb_info *sbi, int count_type) +{ + return atomic_read(&sbi->nr_pages[count_type]); +} + +static inline int get_dirty_dents(struct inode *inode) +{ + return atomic_read(&F2FS_I(inode)->dirty_dents); +} + +static inline int get_blocktype_secs(struct f2fs_sb_info *sbi, int block_type) +{ + unsigned int pages_per_sec = sbi->segs_per_sec * + (1 << sbi->log_blocks_per_seg); + return ((get_pages(sbi, block_type) + pages_per_sec - 1) + >> sbi->log_blocks_per_seg) / sbi->segs_per_sec; +} + +static inline block_t valid_user_blocks(struct f2fs_sb_info *sbi) +{ + return sbi->total_valid_block_count; +} + +static inline unsigned long __bitmap_size(struct f2fs_sb_info *sbi, int flag) +{ + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + + /* return NAT or SIT bitmap */ + if (flag == NAT_BITMAP) + return le32_to_cpu(ckpt->nat_ver_bitmap_bytesize); + else if (flag == SIT_BITMAP) + return le32_to_cpu(ckpt->sit_ver_bitmap_bytesize); + + return 0; +} + +static inline void *__bitmap_ptr(struct f2fs_sb_info *sbi, int flag) +{ + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + int offset; + + if (le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_payload) > 0) { + if (flag == NAT_BITMAP) + return &ckpt->sit_nat_version_bitmap; + else + return ((unsigned char *)ckpt + F2FS_BLKSIZE); + } else { + offset = (flag == NAT_BITMAP) ? + le32_to_cpu(ckpt->sit_ver_bitmap_bytesize) : 0; + return &ckpt->sit_nat_version_bitmap + offset; + } +} + +static inline block_t __start_cp_addr(struct f2fs_sb_info *sbi) +{ + block_t start_addr; + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + unsigned long long ckpt_version = cur_cp_version(ckpt); + + start_addr = le32_to_cpu(F2FS_RAW_SUPER(sbi)->cp_blkaddr); + + /* + * odd numbered checkpoint should at cp segment 0 + * and even segent must be at cp segment 1 + */ + if (!(ckpt_version & 1)) + start_addr += sbi->blocks_per_seg; + + return start_addr; +} + +static inline block_t __start_sum_addr(struct f2fs_sb_info *sbi) +{ + return le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum); +} + +static inline bool inc_valid_node_count(struct f2fs_sb_info *sbi, + struct inode *inode) +{ + block_t valid_block_count; + unsigned int valid_node_count; + + spin_lock(&sbi->stat_lock); + + valid_block_count = sbi->total_valid_block_count + 1; + if (unlikely(valid_block_count > sbi->user_block_count)) { + spin_unlock(&sbi->stat_lock); + return false; + } + + valid_node_count = sbi->total_valid_node_count + 1; + if (unlikely(valid_node_count > sbi->total_node_count)) { + spin_unlock(&sbi->stat_lock); + return false; + } + + if (inode) + inode->i_blocks++; + + sbi->alloc_valid_block_count++; + sbi->total_valid_node_count++; + sbi->total_valid_block_count++; + spin_unlock(&sbi->stat_lock); + + return true; +} + +static inline void dec_valid_node_count(struct f2fs_sb_info *sbi, + struct inode *inode) +{ + spin_lock(&sbi->stat_lock); + + f2fs_bug_on(!sbi->total_valid_block_count); + f2fs_bug_on(!sbi->total_valid_node_count); + f2fs_bug_on(!inode->i_blocks); + + inode->i_blocks--; + sbi->total_valid_node_count--; + sbi->total_valid_block_count--; + + spin_unlock(&sbi->stat_lock); +} + +static inline unsigned int valid_node_count(struct f2fs_sb_info *sbi) +{ + return sbi->total_valid_node_count; +} + +static inline void inc_valid_inode_count(struct f2fs_sb_info *sbi) +{ + spin_lock(&sbi->stat_lock); + f2fs_bug_on(sbi->total_valid_inode_count == sbi->total_node_count); + sbi->total_valid_inode_count++; + spin_unlock(&sbi->stat_lock); +} + +static inline void dec_valid_inode_count(struct f2fs_sb_info *sbi) +{ + spin_lock(&sbi->stat_lock); + f2fs_bug_on(!sbi->total_valid_inode_count); + sbi->total_valid_inode_count--; + spin_unlock(&sbi->stat_lock); +} + +static inline unsigned int valid_inode_count(struct f2fs_sb_info *sbi) +{ + return sbi->total_valid_inode_count; +} + +static inline void f2fs_put_page(struct page *page, int unlock) +{ + if (!page) + return; + + if (unlock) { + f2fs_bug_on(!PageLocked(page)); + unlock_page(page); + } + page_cache_release(page); +} + +static inline void f2fs_put_dnode(struct dnode_of_data *dn) +{ + if (dn->node_page) + f2fs_put_page(dn->node_page, 1); + if (dn->inode_page && dn->node_page != dn->inode_page) + f2fs_put_page(dn->inode_page, 0); + dn->node_page = NULL; + dn->inode_page = NULL; +} + +static inline struct kmem_cache *f2fs_kmem_cache_create(const char *name, + size_t size) +{ + return kmem_cache_create(name, size, 0, SLAB_RECLAIM_ACCOUNT, NULL); +} + +static inline void *f2fs_kmem_cache_alloc(struct kmem_cache *cachep, + gfp_t flags) +{ + void *entry; +retry: + entry = kmem_cache_alloc(cachep, flags); + if (!entry) { + cond_resched(); + goto retry; + } + + return entry; +} + +#define RAW_IS_INODE(p) ((p)->footer.nid == (p)->footer.ino) + +static inline bool IS_INODE(struct page *page) +{ + struct f2fs_node *p = F2FS_NODE(page); + return RAW_IS_INODE(p); +} + +static inline __le32 *blkaddr_in_node(struct f2fs_node *node) +{ + return RAW_IS_INODE(node) ? node->i.i_addr : node->dn.addr; +} + +static inline block_t datablock_addr(struct page *node_page, + unsigned int offset) +{ + struct f2fs_node *raw_node; + __le32 *addr_array; + raw_node = F2FS_NODE(node_page); + addr_array = blkaddr_in_node(raw_node); + return le32_to_cpu(addr_array[offset]); +} + +static inline int f2fs_test_bit(unsigned int nr, char *addr) +{ + int mask; + + addr += (nr >> 3); + mask = 1 << (7 - (nr & 0x07)); + return mask & *addr; +} + +static inline int f2fs_set_bit(unsigned int nr, char *addr) +{ + int mask; + int ret; + + addr += (nr >> 3); + mask = 1 << (7 - (nr & 0x07)); + ret = mask & *addr; + *addr |= mask; + return ret; +} + +static inline int f2fs_clear_bit(unsigned int nr, char *addr) +{ + int mask; + int ret; + + addr += (nr >> 3); + mask = 1 << (7 - (nr & 0x07)); + ret = mask & *addr; + *addr &= ~mask; + return ret; +} + +/* used for f2fs_inode_info->flags */ +enum { + FI_NEW_INODE, /* indicate newly allocated inode */ + FI_DIRTY_INODE, /* indicate inode is dirty or not */ + FI_DIRTY_DIR, /* indicate directory has dirty pages */ + FI_INC_LINK, /* need to increment i_nlink */ + FI_ACL_MODE, /* indicate acl mode */ + FI_NO_ALLOC, /* should not allocate any blocks */ + FI_UPDATE_DIR, /* should update inode block for consistency */ + FI_DELAY_IPUT, /* used for the recovery */ + FI_NO_EXTENT, /* not to use the extent cache */ + FI_INLINE_XATTR, /* used for inline xattr */ + FI_INLINE_DATA, /* used for inline data*/ +}; + +static inline void set_inode_flag(struct f2fs_inode_info *fi, int flag) +{ + set_bit(flag, &fi->flags); +} + +static inline int is_inode_flag_set(struct f2fs_inode_info *fi, int flag) +{ + return test_bit(flag, &fi->flags); +} + +static inline void clear_inode_flag(struct f2fs_inode_info *fi, int flag) +{ + clear_bit(flag, &fi->flags); +} + +static inline void set_acl_inode(struct f2fs_inode_info *fi, umode_t mode) +{ + fi->i_acl_mode = mode; + set_inode_flag(fi, FI_ACL_MODE); +} + +static inline int cond_clear_inode_flag(struct f2fs_inode_info *fi, int flag) +{ + if (is_inode_flag_set(fi, FI_ACL_MODE)) { + clear_inode_flag(fi, FI_ACL_MODE); + return 1; + } + return 0; +} + +int f2fs_android_emu(struct f2fs_sb_info *, struct inode *, u32 *, u32 *, + umode_t *); + +#define IS_ANDROID_EMU(sbi, fi, pfi) \ + (test_opt((sbi), ANDROID_EMU) && \ + (((fi)->i_advise & FADVISE_ANDROID_EMU) || \ + ((pfi)->i_advise & FADVISE_ANDROID_EMU))) + +static inline void get_inline_info(struct f2fs_inode_info *fi, + struct f2fs_inode *ri) +{ + if (ri->i_inline & F2FS_INLINE_XATTR) + set_inode_flag(fi, FI_INLINE_XATTR); + if (ri->i_inline & F2FS_INLINE_DATA) + set_inode_flag(fi, FI_INLINE_DATA); +} + +static inline void set_raw_inline(struct f2fs_inode_info *fi, + struct f2fs_inode *ri) +{ + ri->i_inline = 0; + + if (is_inode_flag_set(fi, FI_INLINE_XATTR)) + ri->i_inline |= F2FS_INLINE_XATTR; + if (is_inode_flag_set(fi, FI_INLINE_DATA)) + ri->i_inline |= F2FS_INLINE_DATA; +} + +static inline int f2fs_has_inline_xattr(struct inode *inode) +{ + return is_inode_flag_set(F2FS_I(inode), FI_INLINE_XATTR); +} + +static inline unsigned int addrs_per_inode(struct f2fs_inode_info *fi) +{ + if (f2fs_has_inline_xattr(&fi->vfs_inode)) + return DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS; + return DEF_ADDRS_PER_INODE; +} + +static inline void *inline_xattr_addr(struct page *page) +{ + struct f2fs_inode *ri = F2FS_INODE(page); + return (void *)&(ri->i_addr[DEF_ADDRS_PER_INODE - + F2FS_INLINE_XATTR_ADDRS]); +} + +static inline int inline_xattr_size(struct inode *inode) +{ + if (f2fs_has_inline_xattr(inode)) + return F2FS_INLINE_XATTR_ADDRS << 2; + else + return 0; +} + +static inline int f2fs_has_inline_data(struct inode *inode) +{ + return is_inode_flag_set(F2FS_I(inode), FI_INLINE_DATA); +} + +static inline void *inline_data_addr(struct page *page) +{ + struct f2fs_inode *ri = F2FS_INODE(page); + return (void *)&(ri->i_addr[1]); +} + +static inline int f2fs_readonly(struct super_block *sb) +{ + return sb->s_flags & MS_RDONLY; +} + +static inline void f2fs_stop_checkpoint(struct f2fs_sb_info *sbi) +{ + set_ckpt_flags(sbi->ckpt, CP_ERROR_FLAG); + sbi->sb->s_flags |= MS_RDONLY; +} + +#define get_inode_mode(i) \ + ((is_inode_flag_set(F2FS_I(i), FI_ACL_MODE)) ? \ + (F2FS_I(i)->i_acl_mode) : ((i)->i_mode)) + +/* get offset of first page in next direct node */ +#define PGOFS_OF_NEXT_DNODE(pgofs, fi) \ + ((pgofs < ADDRS_PER_INODE(fi)) ? ADDRS_PER_INODE(fi) : \ + (pgofs - ADDRS_PER_INODE(fi) + ADDRS_PER_BLOCK) / \ + ADDRS_PER_BLOCK * ADDRS_PER_BLOCK + ADDRS_PER_INODE(fi)) + +/* + * file.c + */ +int f2fs_sync_file(struct file *, loff_t, loff_t, int); +void truncate_data_blocks(struct dnode_of_data *); +int truncate_blocks(struct inode *, u64); +void f2fs_truncate(struct inode *); +int f2fs_getattr(struct vfsmount *, struct dentry *, struct kstat *); +int f2fs_setattr(struct dentry *, struct iattr *); +int truncate_hole(struct inode *, pgoff_t, pgoff_t); +int truncate_data_blocks_range(struct dnode_of_data *, int); +long f2fs_ioctl(struct file *, unsigned int, unsigned long); +long f2fs_compat_ioctl(struct file *, unsigned int, unsigned long); + +/* + * inode.c + */ +void f2fs_set_inode_flags(struct inode *); +struct inode *f2fs_iget(struct super_block *, unsigned long); +int try_to_free_nats(struct f2fs_sb_info *, int); +void update_inode(struct inode *, struct page *); +void update_inode_page(struct inode *); +int f2fs_write_inode(struct inode *, struct writeback_control *); +void f2fs_evict_inode(struct inode *); + +/* + * namei.c + */ +struct dentry *f2fs_get_parent(struct dentry *child); + +/* + * dir.c + */ +struct f2fs_dir_entry *f2fs_find_entry(struct inode *, struct qstr *, + struct page **); +struct f2fs_dir_entry *f2fs_parent_dir(struct inode *, struct page **); +ino_t f2fs_inode_by_name(struct inode *, struct qstr *); +void f2fs_set_link(struct inode *, struct f2fs_dir_entry *, + struct page *, struct inode *); +int update_dent_inode(struct inode *, const struct qstr *); +int __f2fs_add_link(struct inode *, const struct qstr *, struct inode *); +void f2fs_delete_entry(struct f2fs_dir_entry *, struct page *, struct inode *); +int f2fs_do_tmpfile(struct inode *, struct inode *); +int f2fs_make_empty(struct inode *, struct inode *); +bool f2fs_empty_dir(struct inode *); + +static inline int f2fs_add_link(struct dentry *dentry, struct inode *inode) +{ + return __f2fs_add_link(dentry->d_parent->d_inode, &dentry->d_name, + inode); +} + +/* + * super.c + */ +int f2fs_sync_fs(struct super_block *, int); +extern __printf(3, 4) +void f2fs_msg(struct super_block *, const char *, const char *, ...); + +/* + * hash.c + */ +f2fs_hash_t f2fs_dentry_hash(const struct qstr *); + +/* + * node.c + */ +struct dnode_of_data; +struct node_info; + +bool available_free_memory(struct f2fs_sb_info *, int); +int is_checkpointed_node(struct f2fs_sb_info *, nid_t); +bool fsync_mark_done(struct f2fs_sb_info *, nid_t); +void fsync_mark_clear(struct f2fs_sb_info *, nid_t); +void get_node_info(struct f2fs_sb_info *, nid_t, struct node_info *); +int get_dnode_of_data(struct dnode_of_data *, pgoff_t, int); +int truncate_inode_blocks(struct inode *, pgoff_t); +int truncate_xattr_node(struct inode *, struct page *); +int wait_on_node_pages_writeback(struct f2fs_sb_info *, nid_t); +void remove_inode_page(struct inode *); +struct page *new_inode_page(struct inode *); +struct page *new_node_page(struct dnode_of_data *, unsigned int, struct page *); +void ra_node_page(struct f2fs_sb_info *, nid_t); +struct page *get_node_page(struct f2fs_sb_info *, pgoff_t); +struct page *get_node_page_ra(struct page *, int); +void sync_inode_page(struct dnode_of_data *); +int sync_node_pages(struct f2fs_sb_info *, nid_t, struct writeback_control *); +bool alloc_nid(struct f2fs_sb_info *, nid_t *); +void alloc_nid_done(struct f2fs_sb_info *, nid_t); +void alloc_nid_failed(struct f2fs_sb_info *, nid_t); +void recover_node_page(struct f2fs_sb_info *, struct page *, + struct f2fs_summary *, struct node_info *, block_t); +bool recover_xattr_data(struct inode *, struct page *, block_t); +int recover_inode_page(struct f2fs_sb_info *, struct page *); +int restore_node_summary(struct f2fs_sb_info *, unsigned int, + struct f2fs_summary_block *); +void flush_nat_entries(struct f2fs_sb_info *); +int build_node_manager(struct f2fs_sb_info *); +void destroy_node_manager(struct f2fs_sb_info *); +int __init create_node_manager_caches(void); +void destroy_node_manager_caches(void); + +/* + * segment.c + */ +void f2fs_balance_fs(struct f2fs_sb_info *); +void f2fs_balance_fs_bg(struct f2fs_sb_info *); +int issue_flush_thread(void *); +int f2fs_issue_flush(struct f2fs_sb_info *); +void invalidate_blocks(struct f2fs_sb_info *, block_t); +void refresh_sit_entry(struct f2fs_sb_info *, block_t, block_t); +void clear_prefree_segments(struct f2fs_sb_info *); +void discard_next_dnode(struct f2fs_sb_info *); +int npages_for_summary_flush(struct f2fs_sb_info *); +void allocate_new_segments(struct f2fs_sb_info *); +struct page *get_sum_page(struct f2fs_sb_info *, unsigned int); +void write_meta_page(struct f2fs_sb_info *, struct page *); +void write_node_page(struct f2fs_sb_info *, struct page *, + struct f2fs_io_info *, unsigned int, block_t, block_t *); +void write_data_page(struct page *, struct dnode_of_data *, block_t *, + struct f2fs_io_info *); +void rewrite_data_page(struct page *, block_t, struct f2fs_io_info *); +void recover_data_page(struct f2fs_sb_info *, struct page *, + struct f2fs_summary *, block_t, block_t); +void rewrite_node_page(struct f2fs_sb_info *, struct page *, + struct f2fs_summary *, block_t, block_t); +void allocate_data_block(struct f2fs_sb_info *, struct page *, + block_t, block_t *, struct f2fs_summary *, int); +void f2fs_wait_on_page_writeback(struct page *, enum page_type); +void write_data_summaries(struct f2fs_sb_info *, block_t); +void write_node_summaries(struct f2fs_sb_info *, block_t); +int lookup_journal_in_cursum(struct f2fs_summary_block *, + int, unsigned int, int); +void flush_sit_entries(struct f2fs_sb_info *); +int build_segment_manager(struct f2fs_sb_info *); +void destroy_segment_manager(struct f2fs_sb_info *); +int __init create_segment_manager_caches(void); +void destroy_segment_manager_caches(void); + +/* + * checkpoint.c + */ +struct page *grab_meta_page(struct f2fs_sb_info *, pgoff_t); +struct page *get_meta_page(struct f2fs_sb_info *, pgoff_t); +int ra_meta_pages(struct f2fs_sb_info *, int, int, int); +long sync_meta_pages(struct f2fs_sb_info *, enum page_type, long); +int acquire_orphan_inode(struct f2fs_sb_info *); +void release_orphan_inode(struct f2fs_sb_info *); +void add_orphan_inode(struct f2fs_sb_info *, nid_t); +void remove_orphan_inode(struct f2fs_sb_info *, nid_t); +void recover_orphan_inodes(struct f2fs_sb_info *); +int get_valid_checkpoint(struct f2fs_sb_info *); +void set_dirty_dir_page(struct inode *, struct page *); +void add_dirty_dir_inode(struct inode *); +void remove_dirty_dir_inode(struct inode *); +void sync_dirty_dir_inodes(struct f2fs_sb_info *); +void write_checkpoint(struct f2fs_sb_info *, bool); +void init_orphan_info(struct f2fs_sb_info *); +int __init create_checkpoint_caches(void); +void destroy_checkpoint_caches(void); + +/* + * data.c + */ +void f2fs_submit_merged_bio(struct f2fs_sb_info *, enum page_type, int); +int f2fs_submit_page_bio(struct f2fs_sb_info *, struct page *, block_t, int); +void f2fs_submit_page_mbio(struct f2fs_sb_info *, struct page *, block_t, + struct f2fs_io_info *); +int reserve_new_block(struct dnode_of_data *); +int f2fs_reserve_block(struct dnode_of_data *, pgoff_t); +void update_extent_cache(block_t, struct dnode_of_data *); +struct page *find_data_page(struct inode *, pgoff_t, bool); +struct page *get_lock_data_page(struct inode *, pgoff_t); +struct page *get_new_data_page(struct inode *, struct page *, pgoff_t, bool); +int do_write_data_page(struct page *, struct f2fs_io_info *); +int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *, u64, u64); + +/* + * gc.c + */ +int start_gc_thread(struct f2fs_sb_info *); +void stop_gc_thread(struct f2fs_sb_info *); +block_t start_bidx_of_node(unsigned int, struct f2fs_inode_info *); +int f2fs_gc(struct f2fs_sb_info *); +void build_gc_manager(struct f2fs_sb_info *); +int __init create_gc_caches(void); +void destroy_gc_caches(void); + +/* + * recovery.c + */ +int recover_fsync_data(struct f2fs_sb_info *); +bool space_for_roll_forward(struct f2fs_sb_info *); + +/* + * debug.c + */ +#ifdef CONFIG_F2FS_STAT_FS +struct f2fs_stat_info { + struct list_head stat_list; + struct f2fs_sb_info *sbi; + struct mutex stat_lock; + int all_area_segs, sit_area_segs, nat_area_segs, ssa_area_segs; + int main_area_segs, main_area_sections, main_area_zones; + int hit_ext, total_ext; + int ndirty_node, ndirty_dent, ndirty_dirs, ndirty_meta; + int nats, sits, fnids; + int total_count, utilization; + int bg_gc, inline_inode; + unsigned int valid_count, valid_node_count, valid_inode_count; + unsigned int bimodal, avg_vblocks; + int util_free, util_valid, util_invalid; + int rsvd_segs, overp_segs; + int dirty_count, node_pages, meta_pages; + int prefree_count, call_count, cp_count; + int tot_segs, node_segs, data_segs, free_segs, free_secs; + int tot_blks, data_blks, node_blks; + int curseg[NR_CURSEG_TYPE]; + int cursec[NR_CURSEG_TYPE]; + int curzone[NR_CURSEG_TYPE]; + + unsigned int segment_count[2]; + unsigned int block_count[2]; + unsigned base_mem, cache_mem; +}; + +static inline struct f2fs_stat_info *F2FS_STAT(struct f2fs_sb_info *sbi) +{ + return (struct f2fs_stat_info *)sbi->stat_info; +} + +#define stat_inc_cp_count(si) ((si)->cp_count++) +#define stat_inc_call_count(si) ((si)->call_count++) +#define stat_inc_bggc_count(sbi) ((sbi)->bg_gc++) +#define stat_inc_dirty_dir(sbi) ((sbi)->n_dirty_dirs++) +#define stat_dec_dirty_dir(sbi) ((sbi)->n_dirty_dirs--) +#define stat_inc_total_hit(sb) ((F2FS_SB(sb))->total_hit_ext++) +#define stat_inc_read_hit(sb) ((F2FS_SB(sb))->read_hit_ext++) +#define stat_inc_inline_inode(inode) \ + do { \ + if (f2fs_has_inline_data(inode)) \ + ((F2FS_SB(inode->i_sb))->inline_inode++); \ + } while (0) +#define stat_dec_inline_inode(inode) \ + do { \ + if (f2fs_has_inline_data(inode)) \ + ((F2FS_SB(inode->i_sb))->inline_inode--); \ + } while (0) + +#define stat_inc_seg_type(sbi, curseg) \ + ((sbi)->segment_count[(curseg)->alloc_type]++) +#define stat_inc_block_count(sbi, curseg) \ + ((sbi)->block_count[(curseg)->alloc_type]++) + +#define stat_inc_seg_count(sbi, type) \ + do { \ + struct f2fs_stat_info *si = F2FS_STAT(sbi); \ + (si)->tot_segs++; \ + if (type == SUM_TYPE_DATA) \ + si->data_segs++; \ + else \ + si->node_segs++; \ + } while (0) + +#define stat_inc_tot_blk_count(si, blks) \ + (si->tot_blks += (blks)) + +#define stat_inc_data_blk_count(sbi, blks) \ + do { \ + struct f2fs_stat_info *si = F2FS_STAT(sbi); \ + stat_inc_tot_blk_count(si, blks); \ + si->data_blks += (blks); \ + } while (0) + +#define stat_inc_node_blk_count(sbi, blks) \ + do { \ + struct f2fs_stat_info *si = F2FS_STAT(sbi); \ + stat_inc_tot_blk_count(si, blks); \ + si->node_blks += (blks); \ + } while (0) + +int f2fs_build_stats(struct f2fs_sb_info *); +void f2fs_destroy_stats(struct f2fs_sb_info *); +void __init f2fs_create_root_stats(void); +void f2fs_destroy_root_stats(void); +#else +#define stat_inc_cp_count(si) +#define stat_inc_call_count(si) +#define stat_inc_bggc_count(si) +#define stat_inc_dirty_dir(sbi) +#define stat_dec_dirty_dir(sbi) +#define stat_inc_total_hit(sb) +#define stat_inc_read_hit(sb) +#define stat_inc_inline_inode(inode) +#define stat_dec_inline_inode(inode) +#define stat_inc_seg_type(sbi, curseg) +#define stat_inc_block_count(sbi, curseg) +#define stat_inc_seg_count(si, type) +#define stat_inc_tot_blk_count(si, blks) +#define stat_inc_data_blk_count(si, blks) +#define stat_inc_node_blk_count(sbi, blks) + +static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; } +static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { } +static inline void __init f2fs_create_root_stats(void) { } +static inline void f2fs_destroy_root_stats(void) { } +#endif + +extern const struct file_operations f2fs_dir_operations; +extern const struct file_operations f2fs_file_operations; +extern const struct inode_operations f2fs_file_inode_operations; +extern const struct address_space_operations f2fs_dblock_aops; +extern const struct address_space_operations f2fs_node_aops; +extern const struct address_space_operations f2fs_meta_aops; +extern const struct inode_operations f2fs_dir_inode_operations; +extern const struct inode_operations f2fs_symlink_inode_operations; +extern const struct inode_operations f2fs_special_inode_operations; + +/* + * inline.c + */ +bool f2fs_may_inline(struct inode *); +int f2fs_read_inline_data(struct inode *, struct page *); +int f2fs_convert_inline_data(struct inode *, pgoff_t); +int f2fs_write_inline_data(struct inode *, struct page *, unsigned int); +void truncate_inline_data(struct inode *, u64); +int recover_inline_data(struct inode *, struct page *); +#endif diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c new file mode 100644 index 00000000000..57050e80767 --- /dev/null +++ b/fs/f2fs/file.c @@ -0,0 +1,848 @@ +/* + * fs/f2fs/file.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" +#include "segment.h" +#include "xattr.h" +#include "acl.h" +#include + +static int f2fs_vm_page_mkwrite(struct vm_area_struct *vma, + struct vm_fault *vmf) +{ + struct page *page = vmf->page; + struct inode *inode = vma->vm_file->f_path.dentry->d_inode; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct dnode_of_data dn; + int err; + + f2fs_balance_fs(sbi); + + /* Wait if fs is frozen. This is racy so we check again later on + * and retry if the fs has been frozen after the page lock has + * been acquired + */ + vfs_check_frozen(inode->i_sb, SB_FREEZE_WRITE); + + /* block allocation */ + f2fs_lock_op(sbi); + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = f2fs_reserve_block(&dn, page->index); + f2fs_unlock_op(sbi); + if (err) + goto out; + + file_update_time(vma->vm_file); + lock_page(page); + if (unlikely(page->mapping != inode->i_mapping || + page_offset(page) > i_size_read(inode) || + !PageUptodate(page))) { + unlock_page(page); + err = -EFAULT; + goto out; + } + + /* + * check to see if the page is mapped already (no holes) + */ + if (PageMappedToDisk(page)) + goto mapped; + + /* page is wholly or partially inside EOF */ + if (((page->index + 1) << PAGE_CACHE_SHIFT) > i_size_read(inode)) { + unsigned offset; + offset = i_size_read(inode) & ~PAGE_CACHE_MASK; + zero_user_segment(page, offset, PAGE_CACHE_SIZE); + } + set_page_dirty(page); + SetPageUptodate(page); + + trace_f2fs_vm_page_mkwrite(page, DATA); +mapped: + /* fill the page */ + f2fs_wait_on_page_writeback(page, DATA); +out: + return block_page_mkwrite_return(err); +} + +static const struct vm_operations_struct f2fs_file_vm_ops = { + .fault = filemap_fault, + .page_mkwrite = f2fs_vm_page_mkwrite, +}; + +static int get_parent_ino(struct inode *inode, nid_t *pino) +{ + struct dentry *dentry; + + inode = igrab(inode); + dentry = d_find_any_alias(inode); + iput(inode); + if (!dentry) + return 0; + + if (update_dent_inode(inode, &dentry->d_name)) { + dput(dentry); + return 0; + } + + *pino = parent_ino(dentry); + dput(dentry); + return 1; +} + +int f2fs_sync_file(struct file *file, loff_t start, loff_t end, int datasync) +{ + struct inode *inode = file->f_mapping->host; + struct f2fs_inode_info *fi = F2FS_I(inode); + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + int ret = 0; + bool need_cp = false; + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = LONG_MAX, + .for_reclaim = 0, + }; + + if (unlikely(f2fs_readonly(inode->i_sb))) + return 0; + + trace_f2fs_sync_file_enter(inode); + ret = filemap_write_and_wait_range(inode->i_mapping, start, end); + if (ret) { + trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); + return ret; + } + + /* guarantee free sections for fsync */ + f2fs_balance_fs(sbi); + + down_read(&fi->i_sem); + + /* + * Both of fdatasync() and fsync() are able to be recovered from + * sudden-power-off. + */ + if (!S_ISREG(inode->i_mode) || inode->i_nlink != 1) + need_cp = true; + else if (file_wrong_pino(inode)) + need_cp = true; + else if (!space_for_roll_forward(sbi)) + need_cp = true; + else if (!is_checkpointed_node(sbi, F2FS_I(inode)->i_pino)) + need_cp = true; + else if (F2FS_I(inode)->xattr_ver == cur_cp_version(F2FS_CKPT(sbi))) + need_cp = true; + + up_read(&fi->i_sem); + + if (need_cp) { + nid_t pino; + + /* all the dirty node pages should be flushed for POR */ + ret = f2fs_sync_fs(inode->i_sb, 1); + + down_write(&fi->i_sem); + F2FS_I(inode)->xattr_ver = 0; + if (file_wrong_pino(inode) && inode->i_nlink == 1 && + get_parent_ino(inode, &pino)) { + F2FS_I(inode)->i_pino = pino; + file_got_pino(inode); + up_write(&fi->i_sem); + mark_inode_dirty_sync(inode); + ret = f2fs_write_inode(inode, NULL); + if (ret) + goto out; + } else { + up_write(&fi->i_sem); + } + } else { + /* if there is no written node page, write its inode page */ + while (!sync_node_pages(sbi, inode->i_ino, &wbc)) { + if (fsync_mark_done(sbi, inode->i_ino)) + goto out; + mark_inode_dirty_sync(inode); + ret = f2fs_write_inode(inode, NULL); + if (ret) + goto out; + } + ret = wait_on_node_pages_writeback(sbi, inode->i_ino); + if (ret) + goto out; + ret = f2fs_issue_flush(F2FS_SB(inode->i_sb)); + } +out: + trace_f2fs_sync_file_exit(inode, need_cp, datasync, ret); + return ret; +} + +static pgoff_t __get_first_dirty_index(struct address_space *mapping, + pgoff_t pgofs, int whence) +{ + struct pagevec pvec; + int nr_pages; + + if (whence != SEEK_DATA) + return 0; + + /* find first dirty page index */ + pagevec_init(&pvec, 0); + nr_pages = pagevec_lookup_tag(&pvec, mapping, &pgofs, PAGECACHE_TAG_DIRTY, 1); + pgofs = nr_pages ? pvec.pages[0]->index: LONG_MAX; + pagevec_release(&pvec); + return pgofs; +} + +static bool __found_offset(block_t blkaddr, pgoff_t dirty, pgoff_t pgofs, + int whence) +{ + switch (whence) { + case SEEK_DATA: + if ((blkaddr == NEW_ADDR && dirty == pgofs) || + (blkaddr != NEW_ADDR && blkaddr != NULL_ADDR)) + return true; + break; + case SEEK_HOLE: + if (blkaddr == NULL_ADDR) + return true; + break; + } + return false; +} + +static loff_t f2fs_seek_block(struct file *file, loff_t offset, int whence) +{ + struct inode *inode = file->f_mapping->host; + loff_t maxbytes = inode->i_sb->s_maxbytes; + struct dnode_of_data dn; + pgoff_t pgofs, end_offset, dirty; + loff_t data_ofs = offset; + loff_t isize; + int err = 0; + + mutex_lock(&inode->i_mutex); + + isize = i_size_read(inode); + if (offset >= isize) + goto fail; + + /* handle inline data case */ + if (f2fs_has_inline_data(inode)) { + if (whence == SEEK_HOLE) + data_ofs = isize; + goto found; + } + + pgofs = (pgoff_t)(offset >> PAGE_CACHE_SHIFT); + + dirty = __get_first_dirty_index(inode->i_mapping, pgofs, whence); + + for (; data_ofs < isize; data_ofs = pgofs << PAGE_CACHE_SHIFT) { + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, pgofs, LOOKUP_NODE_RA); + if (err && err != -ENOENT) { + goto fail; + } else if (err == -ENOENT) { + /* direct node is not exist */ + if (whence == SEEK_DATA) { + pgofs = PGOFS_OF_NEXT_DNODE(pgofs, + F2FS_I(inode)); + continue; + } else { + goto found; + } + } + + end_offset = IS_INODE(dn.node_page) ? + ADDRS_PER_INODE(F2FS_I(inode)) : ADDRS_PER_BLOCK; + + /* find data/hole in dnode block */ + for (; dn.ofs_in_node < end_offset; + dn.ofs_in_node++, pgofs++, + data_ofs = pgofs << PAGE_CACHE_SHIFT) { + block_t blkaddr; + blkaddr = datablock_addr(dn.node_page, dn.ofs_in_node); + + if (__found_offset(blkaddr, dirty, pgofs, whence)) { + f2fs_put_dnode(&dn); + goto found; + } + } + f2fs_put_dnode(&dn); + } + + if (whence == SEEK_DATA) + goto fail; +found: + if (whence == SEEK_HOLE && data_ofs > isize) + data_ofs = isize; + mutex_unlock(&inode->i_mutex); + return vfs_setpos(file, data_ofs, maxbytes); +fail: + mutex_unlock(&inode->i_mutex); + return -ENXIO; +} + +static loff_t f2fs_llseek(struct file *file, loff_t offset, int whence) +{ + struct inode *inode = file->f_mapping->host; + loff_t maxbytes = inode->i_sb->s_maxbytes; + + switch (whence) { + case SEEK_SET: + case SEEK_CUR: + case SEEK_END: + return __generic_file_llseek_size(file, offset, whence, + maxbytes, i_size_read(inode)); + case SEEK_DATA: + case SEEK_HOLE: + return f2fs_seek_block(file, offset, whence); + } + + return -EINVAL; +} + +static int f2fs_file_mmap(struct file *file, struct vm_area_struct *vma) +{ + file_accessed(file); + vma->vm_ops = &f2fs_file_vm_ops; + return 0; +} + +int truncate_data_blocks_range(struct dnode_of_data *dn, int count) +{ + int nr_free = 0, ofs = dn->ofs_in_node; + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct f2fs_node *raw_node; + __le32 *addr; + + raw_node = F2FS_NODE(dn->node_page); + addr = blkaddr_in_node(raw_node) + ofs; + + for (; count > 0; count--, addr++, dn->ofs_in_node++) { + block_t blkaddr = le32_to_cpu(*addr); + if (blkaddr == NULL_ADDR) + continue; + + update_extent_cache(NULL_ADDR, dn); + invalidate_blocks(sbi, blkaddr); + nr_free++; + } + if (nr_free) { + dec_valid_block_count(sbi, dn->inode, nr_free); + set_page_dirty(dn->node_page); + sync_inode_page(dn); + } + dn->ofs_in_node = ofs; + + trace_f2fs_truncate_data_blocks_range(dn->inode, dn->nid, + dn->ofs_in_node, nr_free); + return nr_free; +} + +void truncate_data_blocks(struct dnode_of_data *dn) +{ + truncate_data_blocks_range(dn, ADDRS_PER_BLOCK); +} + +static void truncate_partial_data_page(struct inode *inode, u64 from) +{ + unsigned offset = from & (PAGE_CACHE_SIZE - 1); + struct page *page; + + if (f2fs_has_inline_data(inode)) + return truncate_inline_data(inode, from); + + if (!offset) + return; + + page = find_data_page(inode, from >> PAGE_CACHE_SHIFT, false); + if (IS_ERR(page)) + return; + + lock_page(page); + if (unlikely(!PageUptodate(page) || + page->mapping != inode->i_mapping)) + goto out; + + f2fs_wait_on_page_writeback(page, DATA); + zero_user(page, offset, PAGE_CACHE_SIZE - offset); + set_page_dirty(page); + +out: + f2fs_put_page(page, 1); +} + +int truncate_blocks(struct inode *inode, u64 from) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + unsigned int blocksize = inode->i_sb->s_blocksize; + struct dnode_of_data dn; + pgoff_t free_from; + int count = 0, err = 0; + + trace_f2fs_truncate_blocks_enter(inode, from); + + if (f2fs_has_inline_data(inode)) + goto done; + + free_from = (pgoff_t) + ((from + blocksize - 1) >> (sbi->log_blocksize)); + + f2fs_lock_op(sbi); + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, free_from, LOOKUP_NODE); + if (err) { + if (err == -ENOENT) + goto free_next; + f2fs_unlock_op(sbi); + trace_f2fs_truncate_blocks_exit(inode, err); + return err; + } + + if (IS_INODE(dn.node_page)) + count = ADDRS_PER_INODE(F2FS_I(inode)); + else + count = ADDRS_PER_BLOCK; + + count -= dn.ofs_in_node; + f2fs_bug_on(count < 0); + + if (dn.ofs_in_node || IS_INODE(dn.node_page)) { + truncate_data_blocks_range(&dn, count); + free_from += count; + } + + f2fs_put_dnode(&dn); +free_next: + err = truncate_inode_blocks(inode, free_from); + f2fs_unlock_op(sbi); +done: + /* lastly zero out the first data page */ + truncate_partial_data_page(inode, from); + + trace_f2fs_truncate_blocks_exit(inode, err); + return err; +} + +void f2fs_truncate(struct inode *inode) +{ + int err; + + if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) || + S_ISLNK(inode->i_mode))) + return; + + trace_f2fs_truncate(inode); + + err = truncate_blocks(inode, i_size_read(inode)); + if (err) { + f2fs_msg(inode->i_sb, KERN_ERR, "truncate failed with %d", + err); + f2fs_handle_error(F2FS_SB(inode->i_sb)); + } else { + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); + } +} + +int f2fs_getattr(struct vfsmount *mnt, + struct dentry *dentry, struct kstat *stat) +{ + struct inode *inode = dentry->d_inode; + generic_fillattr(inode, stat); + stat->blocks <<= 3; + return 0; +} + +#ifdef CONFIG_F2FS_FS_POSIX_ACL +static void __setattr_copy(struct inode *inode, const struct iattr *attr) +{ + struct f2fs_inode_info *fi = F2FS_I(inode); + unsigned int ia_valid = attr->ia_valid; + + if (ia_valid & ATTR_UID) + inode->i_uid = attr->ia_uid; + if (ia_valid & ATTR_GID) + inode->i_gid = attr->ia_gid; + if (ia_valid & ATTR_ATIME) + inode->i_atime = timespec_trunc(attr->ia_atime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_MTIME) + inode->i_mtime = timespec_trunc(attr->ia_mtime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_CTIME) + inode->i_ctime = timespec_trunc(attr->ia_ctime, + inode->i_sb->s_time_gran); + if (ia_valid & ATTR_MODE) { + umode_t mode = attr->ia_mode; + + if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) + mode &= ~S_ISGID; + set_acl_inode(fi, mode); + } +} +#else +#define __setattr_copy setattr_copy +#endif + +int f2fs_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct inode *inode = dentry->d_inode; + struct f2fs_inode_info *fi = F2FS_I(inode); + struct f2fs_inode_info *pfi = F2FS_I(dentry->d_parent->d_inode); + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + int err; + + err = inode_change_ok(inode, attr); + if (err) + return err; + + if (IS_ANDROID_EMU(sbi, fi, pfi)) + f2fs_android_emu(sbi, inode, &attr->ia_uid, &attr->ia_gid, + &attr->ia_mode); + + if ((attr->ia_valid & ATTR_SIZE) && + attr->ia_size != i_size_read(inode)) { + err = f2fs_convert_inline_data(inode, attr->ia_size); + if (err) + return err; + + truncate_setsize(inode, attr->ia_size); + f2fs_truncate(inode); + f2fs_balance_fs(F2FS_SB(inode->i_sb)); + } + + __setattr_copy(inode, attr); + + if (attr->ia_valid & ATTR_MODE) { + err = posix_acl_chmod(inode, get_inode_mode(inode)); + if (err || is_inode_flag_set(fi, FI_ACL_MODE)) { + inode->i_mode = fi->i_acl_mode; + clear_inode_flag(fi, FI_ACL_MODE); + } + } + + mark_inode_dirty(inode); + return err; +} + +const struct inode_operations f2fs_file_inode_operations = { + .getattr = f2fs_getattr, + .setattr = f2fs_setattr, + .get_acl = f2fs_get_acl, + .set_acl = f2fs_set_acl, +#ifdef CONFIG_F2FS_FS_XATTR + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = f2fs_listxattr, + .removexattr = generic_removexattr, +#endif + .fiemap = f2fs_fiemap, +}; + +static void fill_zero(struct inode *inode, pgoff_t index, + loff_t start, loff_t len) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct page *page; + + if (!len) + return; + + f2fs_balance_fs(sbi); + + f2fs_lock_op(sbi); + page = get_new_data_page(inode, NULL, index, false); + f2fs_unlock_op(sbi); + + if (!IS_ERR(page)) { + f2fs_wait_on_page_writeback(page, DATA); + zero_user(page, start, len); + set_page_dirty(page); + f2fs_put_page(page, 1); + } +} + +int truncate_hole(struct inode *inode, pgoff_t pg_start, pgoff_t pg_end) +{ + pgoff_t index; + int err; + + for (index = pg_start; index < pg_end; index++) { + struct dnode_of_data dn; + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, index, LOOKUP_NODE); + if (err) { + if (err == -ENOENT) + continue; + return err; + } + + if (dn.data_blkaddr != NULL_ADDR) + truncate_data_blocks_range(&dn, 1); + f2fs_put_dnode(&dn); + } + return 0; +} + +static int punch_hole(struct inode *inode, loff_t offset, loff_t len) +{ + pgoff_t pg_start, pg_end; + loff_t off_start, off_end; + int ret = 0; + + ret = f2fs_convert_inline_data(inode, MAX_INLINE_DATA + 1); + if (ret) + return ret; + + pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT; + pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT; + + off_start = offset & (PAGE_CACHE_SIZE - 1); + off_end = (offset + len) & (PAGE_CACHE_SIZE - 1); + + if (pg_start == pg_end) { + fill_zero(inode, pg_start, off_start, + off_end - off_start); + } else { + if (off_start) + fill_zero(inode, pg_start++, off_start, + PAGE_CACHE_SIZE - off_start); + if (off_end) + fill_zero(inode, pg_end, 0, off_end); + + if (pg_start < pg_end) { + struct address_space *mapping = inode->i_mapping; + loff_t blk_start, blk_end; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + + f2fs_balance_fs(sbi); + + blk_start = pg_start << PAGE_CACHE_SHIFT; + blk_end = pg_end << PAGE_CACHE_SHIFT; + truncate_inode_pages_range(mapping, blk_start, + blk_end - 1); + + f2fs_lock_op(sbi); + ret = truncate_hole(inode, pg_start, pg_end); + f2fs_unlock_op(sbi); + } + } + + return ret; +} + +static int expand_inode_data(struct inode *inode, loff_t offset, + loff_t len, int mode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + pgoff_t index, pg_start, pg_end; + loff_t new_size = i_size_read(inode); + loff_t off_start, off_end; + int ret = 0; + + ret = inode_newsize_ok(inode, (len + offset)); + if (ret) + return ret; + + ret = f2fs_convert_inline_data(inode, offset + len); + if (ret) + return ret; + + pg_start = ((unsigned long long) offset) >> PAGE_CACHE_SHIFT; + pg_end = ((unsigned long long) offset + len) >> PAGE_CACHE_SHIFT; + + off_start = offset & (PAGE_CACHE_SIZE - 1); + off_end = (offset + len) & (PAGE_CACHE_SIZE - 1); + + f2fs_lock_op(sbi); + + for (index = pg_start; index <= pg_end; index++) { + struct dnode_of_data dn; + + if (index == pg_end && !off_end) + goto noalloc; + + set_new_dnode(&dn, inode, NULL, NULL, 0); + ret = f2fs_reserve_block(&dn, index); + if (ret) + break; +noalloc: + if (pg_start == pg_end) + new_size = offset + len; + else if (index == pg_start && off_start) + new_size = (index + 1) << PAGE_CACHE_SHIFT; + else if (index == pg_end) + new_size = (index << PAGE_CACHE_SHIFT) + off_end; + else + new_size += PAGE_CACHE_SIZE; + } + + if (!(mode & FALLOC_FL_KEEP_SIZE) && + i_size_read(inode) < new_size) { + i_size_write(inode, new_size); + mark_inode_dirty(inode); + update_inode_page(inode); + } + f2fs_unlock_op(sbi); + + return ret; +} + +static long f2fs_fallocate(struct file *file, int mode, + loff_t offset, loff_t len) +{ + struct inode *inode = file->f_path.dentry->d_inode; + long ret; + + if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE)) + return -EOPNOTSUPP; + + mutex_lock(&inode->i_mutex); + + if (mode & FALLOC_FL_PUNCH_HOLE) + ret = punch_hole(inode, offset, len); + else + ret = expand_inode_data(inode, offset, len, mode); + + if (!ret) { + inode->i_mtime = inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); + } + + mutex_unlock(&inode->i_mutex); + + trace_f2fs_fallocate(inode, mode, offset, len, ret); + return ret; +} + +#define F2FS_REG_FLMASK (~(FS_DIRSYNC_FL | FS_TOPDIR_FL)) +#define F2FS_OTHER_FLMASK (FS_NODUMP_FL | FS_NOATIME_FL) + +static inline __u32 f2fs_mask_flags(umode_t mode, __u32 flags) +{ + if (S_ISDIR(mode)) + return flags; + else if (S_ISREG(mode)) + return flags & F2FS_REG_FLMASK; + else + return flags & F2FS_OTHER_FLMASK; +} + +long f2fs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) +{ + struct inode *inode = filp->f_dentry->d_inode; + struct f2fs_inode_info *fi = F2FS_I(inode); + unsigned int flags; + int ret; + + switch (cmd) { + case F2FS_IOC_GETFLAGS: + flags = fi->i_flags & FS_FL_USER_VISIBLE; + return put_user(flags, (int __user *) arg); + case F2FS_IOC_SETFLAGS: + { + unsigned int oldflags; + + ret = mnt_want_write(filp->f_path.mnt); + if (ret) + return ret; + + if (!inode_owner_or_capable(inode)) { + ret = -EACCES; + goto out; + } + + if (get_user(flags, (int __user *) arg)) { + ret = -EFAULT; + goto out; + } + + flags = f2fs_mask_flags(inode->i_mode, flags); + + mutex_lock(&inode->i_mutex); + + oldflags = fi->i_flags; + + if ((flags ^ oldflags) & (FS_APPEND_FL | FS_IMMUTABLE_FL)) { + if (!capable(CAP_LINUX_IMMUTABLE)) { + mutex_unlock(&inode->i_mutex); + ret = -EPERM; + goto out; + } + } + + flags = flags & FS_FL_USER_MODIFIABLE; + flags |= oldflags & ~FS_FL_USER_MODIFIABLE; + fi->i_flags = flags; + mutex_unlock(&inode->i_mutex); + + f2fs_set_inode_flags(inode); + inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(inode); +out: + mnt_drop_write(filp->f_path.mnt); + return ret; + } + default: + return -ENOTTY; + } +} + +#ifdef CONFIG_COMPAT +long f2fs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case F2FS_IOC32_GETFLAGS: + cmd = F2FS_IOC_GETFLAGS; + break; + case F2FS_IOC32_SETFLAGS: + cmd = F2FS_IOC_SETFLAGS; + break; + default: + return -ENOIOCTLCMD; + } + return f2fs_ioctl(file, cmd, (unsigned long) compat_ptr(arg)); +} +#endif + +const struct file_operations f2fs_file_operations = { + .llseek = f2fs_llseek, + .read = do_sync_read, + .write = do_sync_write, + .aio_read = generic_file_aio_read, + .aio_write = generic_file_aio_write, + .open = generic_file_open, + .mmap = f2fs_file_mmap, + .fsync = f2fs_sync_file, + .fallocate = f2fs_fallocate, + .unlocked_ioctl = f2fs_ioctl, +#ifdef CONFIG_COMPAT + .compat_ioctl = f2fs_compat_ioctl, +#endif + .splice_read = generic_file_splice_read, + .splice_write = generic_file_splice_write, +}; diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c new file mode 100644 index 00000000000..770ebf222b7 --- /dev/null +++ b/fs/f2fs/gc.c @@ -0,0 +1,749 @@ +/* + * fs/f2fs/gc.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" +#include "segment.h" +#include "gc.h" +#include + +static struct kmem_cache *winode_slab; + +static int gc_thread_func(void *data) +{ + struct f2fs_sb_info *sbi = data; + struct f2fs_gc_kthread *gc_th = sbi->gc_thread; + wait_queue_head_t *wq = &sbi->gc_thread->gc_wait_queue_head; + long wait_ms; + + wait_ms = gc_th->min_sleep_time; + + do { + if (try_to_freeze()) + continue; + else + wait_event_interruptible_timeout(*wq, + kthread_should_stop(), + msecs_to_jiffies(wait_ms)); + if (kthread_should_stop()) + break; + + /* + * [GC triggering condition] + * 0. GC is not conducted currently. + * 1. There are enough dirty segments. + * 2. IO subsystem is idle by checking the # of writeback pages. + * 3. IO subsystem is idle by checking the # of requests in + * bdev's request list. + * + * Note) We have to avoid triggering GCs too much frequently. + * Because it is possible that some segments can be + * invalidated soon after by user update or deletion. + * So, I'd like to wait some time to collect dirty segments. + */ + if (!mutex_trylock(&sbi->gc_mutex)) + continue; + + if (!is_idle(sbi)) { + wait_ms = increase_sleep_time(gc_th, wait_ms); + mutex_unlock(&sbi->gc_mutex); + continue; + } + + if (has_enough_invalid_blocks(sbi)) + wait_ms = decrease_sleep_time(gc_th, wait_ms); + else + wait_ms = increase_sleep_time(gc_th, wait_ms); + + stat_inc_bggc_count(sbi); + + /* if return value is not zero, no victim was selected */ + if (f2fs_gc(sbi)) + wait_ms = gc_th->no_gc_sleep_time; + + /* balancing f2fs's metadata periodically */ + f2fs_balance_fs_bg(sbi); + + } while (!kthread_should_stop()); + return 0; +} + +int start_gc_thread(struct f2fs_sb_info *sbi) +{ + struct f2fs_gc_kthread *gc_th; + dev_t dev = sbi->sb->s_bdev->bd_dev; + int err = 0; + + if (!test_opt(sbi, BG_GC)) + goto out; + gc_th = kmalloc(sizeof(struct f2fs_gc_kthread), GFP_KERNEL); + if (!gc_th) { + err = -ENOMEM; + goto out; + } + + gc_th->min_sleep_time = DEF_GC_THREAD_MIN_SLEEP_TIME; + gc_th->max_sleep_time = DEF_GC_THREAD_MAX_SLEEP_TIME; + gc_th->no_gc_sleep_time = DEF_GC_THREAD_NOGC_SLEEP_TIME; + + gc_th->gc_idle = 0; + + sbi->gc_thread = gc_th; + init_waitqueue_head(&sbi->gc_thread->gc_wait_queue_head); + sbi->gc_thread->f2fs_gc_task = kthread_run(gc_thread_func, sbi, + "f2fs_gc-%u:%u", MAJOR(dev), MINOR(dev)); + if (IS_ERR(gc_th->f2fs_gc_task)) { + err = PTR_ERR(gc_th->f2fs_gc_task); + kfree(gc_th); + sbi->gc_thread = NULL; + } +out: + return err; +} + +void stop_gc_thread(struct f2fs_sb_info *sbi) +{ + struct f2fs_gc_kthread *gc_th = sbi->gc_thread; + if (!gc_th) + return; + kthread_stop(gc_th->f2fs_gc_task); + kfree(gc_th); + sbi->gc_thread = NULL; +} + +static int select_gc_type(struct f2fs_gc_kthread *gc_th, int gc_type) +{ + int gc_mode = (gc_type == BG_GC) ? GC_CB : GC_GREEDY; + + if (gc_th && gc_th->gc_idle) { + if (gc_th->gc_idle == 1) + gc_mode = GC_CB; + else if (gc_th->gc_idle == 2) + gc_mode = GC_GREEDY; + } + return gc_mode; +} + +static void select_policy(struct f2fs_sb_info *sbi, int gc_type, + int type, struct victim_sel_policy *p) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + + if (p->alloc_mode == SSR) { + p->gc_mode = GC_GREEDY; + p->dirty_segmap = dirty_i->dirty_segmap[type]; + p->max_search = dirty_i->nr_dirty[type]; + p->ofs_unit = 1; + } else { + p->gc_mode = select_gc_type(sbi->gc_thread, gc_type); + p->dirty_segmap = dirty_i->dirty_segmap[DIRTY]; + p->max_search = dirty_i->nr_dirty[DIRTY]; + p->ofs_unit = sbi->segs_per_sec; + } + + if (p->max_search > sbi->max_victim_search) + p->max_search = sbi->max_victim_search; + + p->offset = sbi->last_victim[p->gc_mode]; +} + +static unsigned int get_max_cost(struct f2fs_sb_info *sbi, + struct victim_sel_policy *p) +{ + /* SSR allocates in a segment unit */ + if (p->alloc_mode == SSR) + return 1 << sbi->log_blocks_per_seg; + if (p->gc_mode == GC_GREEDY) + return (1 << sbi->log_blocks_per_seg) * p->ofs_unit; + else if (p->gc_mode == GC_CB) + return UINT_MAX; + else /* No other gc_mode */ + return 0; +} + +static unsigned int check_bg_victims(struct f2fs_sb_info *sbi) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned int hint = 0; + unsigned int secno; + + /* + * If the gc_type is FG_GC, we can select victim segments + * selected by background GC before. + * Those segments guarantee they have small valid blocks. + */ +next: + secno = find_next_bit(dirty_i->victim_secmap, TOTAL_SECS(sbi), hint++); + if (secno < TOTAL_SECS(sbi)) { + if (sec_usage_check(sbi, secno)) + goto next; + clear_bit(secno, dirty_i->victim_secmap); + return secno * sbi->segs_per_sec; + } + return NULL_SEGNO; +} + +static unsigned int get_cb_cost(struct f2fs_sb_info *sbi, unsigned int segno) +{ + struct sit_info *sit_i = SIT_I(sbi); + unsigned int secno = GET_SECNO(sbi, segno); + unsigned int start = secno * sbi->segs_per_sec; + unsigned long long mtime = 0; + unsigned int vblocks; + unsigned char age = 0; + unsigned char u; + unsigned int i; + + for (i = 0; i < sbi->segs_per_sec; i++) + mtime += get_seg_entry(sbi, start + i)->mtime; + vblocks = get_valid_blocks(sbi, segno, sbi->segs_per_sec); + + mtime = div_u64(mtime, sbi->segs_per_sec); + vblocks = div_u64(vblocks, sbi->segs_per_sec); + + u = (vblocks * 100) >> sbi->log_blocks_per_seg; + + /* Handle if the system time is changed by user */ + if (mtime < sit_i->min_mtime) + sit_i->min_mtime = mtime; + if (mtime > sit_i->max_mtime) + sit_i->max_mtime = mtime; + if (sit_i->max_mtime != sit_i->min_mtime) + age = 100 - div64_u64(100 * (mtime - sit_i->min_mtime), + sit_i->max_mtime - sit_i->min_mtime); + + return UINT_MAX - ((100 * (100 - u) * age) / (100 + u)); +} + +static inline unsigned int get_gc_cost(struct f2fs_sb_info *sbi, + unsigned int segno, struct victim_sel_policy *p) +{ + if (p->alloc_mode == SSR) + return get_seg_entry(sbi, segno)->ckpt_valid_blocks; + + /* alloc_mode == LFS */ + if (p->gc_mode == GC_GREEDY) + return get_valid_blocks(sbi, segno, sbi->segs_per_sec); + else + return get_cb_cost(sbi, segno); +} + +/* + * This function is called from two paths. + * One is garbage collection and the other is SSR segment selection. + * When it is called during GC, it just gets a victim segment + * and it does not remove it from dirty seglist. + * When it is called from SSR segment selection, it finds a segment + * which has minimum valid blocks and removes it from dirty seglist. + */ +static int get_victim_by_default(struct f2fs_sb_info *sbi, + unsigned int *result, int gc_type, int type, char alloc_mode) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + struct victim_sel_policy p; + unsigned int secno, max_cost; + int nsearched = 0; + + p.alloc_mode = alloc_mode; + select_policy(sbi, gc_type, type, &p); + + p.min_segno = NULL_SEGNO; + p.min_cost = max_cost = get_max_cost(sbi, &p); + + mutex_lock(&dirty_i->seglist_lock); + + if (p.alloc_mode == LFS && gc_type == FG_GC) { + p.min_segno = check_bg_victims(sbi); + if (p.min_segno != NULL_SEGNO) + goto got_it; + } + + while (1) { + unsigned long cost; + unsigned int segno; + + segno = find_next_bit(p.dirty_segmap, + TOTAL_SEGS(sbi), p.offset); + if (segno >= TOTAL_SEGS(sbi)) { + if (sbi->last_victim[p.gc_mode]) { + sbi->last_victim[p.gc_mode] = 0; + p.offset = 0; + continue; + } + break; + } + + p.offset = segno + p.ofs_unit; + if (p.ofs_unit > 1) + p.offset -= segno % p.ofs_unit; + + secno = GET_SECNO(sbi, segno); + + if (sec_usage_check(sbi, secno)) + continue; + if (gc_type == BG_GC && test_bit(secno, dirty_i->victim_secmap)) + continue; + + cost = get_gc_cost(sbi, segno, &p); + + if (p.min_cost > cost) { + p.min_segno = segno; + p.min_cost = cost; + } else if (unlikely(cost == max_cost)) { + continue; + } + + if (nsearched++ >= p.max_search) { + sbi->last_victim[p.gc_mode] = segno; + break; + } + } + if (p.min_segno != NULL_SEGNO) { +got_it: + if (p.alloc_mode == LFS) { + secno = GET_SECNO(sbi, p.min_segno); + if (gc_type == FG_GC) + sbi->cur_victim_sec = secno; + else + set_bit(secno, dirty_i->victim_secmap); + } + *result = (p.min_segno / p.ofs_unit) * p.ofs_unit; + + trace_f2fs_get_victim(sbi->sb, type, gc_type, &p, + sbi->cur_victim_sec, + prefree_segments(sbi), free_segments(sbi)); + } + mutex_unlock(&dirty_i->seglist_lock); + + return (p.min_segno == NULL_SEGNO) ? 0 : 1; +} + +static const struct victim_selection default_v_ops = { + .get_victim = get_victim_by_default, +}; + +static struct inode *find_gc_inode(nid_t ino, struct list_head *ilist) +{ + struct inode_entry *ie; + + list_for_each_entry(ie, ilist, list) + if (ie->inode->i_ino == ino) + return ie->inode; + return NULL; +} + +static void add_gc_inode(struct inode *inode, struct list_head *ilist) +{ + struct inode_entry *new_ie; + + if (inode == find_gc_inode(inode->i_ino, ilist)) { + iput(inode); + return; + } + + new_ie = f2fs_kmem_cache_alloc(winode_slab, GFP_NOFS); + new_ie->inode = inode; + list_add_tail(&new_ie->list, ilist); +} + +static void put_gc_inode(struct list_head *ilist) +{ + struct inode_entry *ie, *next_ie; + list_for_each_entry_safe(ie, next_ie, ilist, list) { + iput(ie->inode); + list_del(&ie->list); + kmem_cache_free(winode_slab, ie); + } +} + +static int check_valid_map(struct f2fs_sb_info *sbi, + unsigned int segno, int offset) +{ + struct sit_info *sit_i = SIT_I(sbi); + struct seg_entry *sentry; + int ret; + + mutex_lock(&sit_i->sentry_lock); + sentry = get_seg_entry(sbi, segno); + ret = f2fs_test_bit(offset, sentry->cur_valid_map); + mutex_unlock(&sit_i->sentry_lock); + return ret; +} + +/* + * This function compares node address got in summary with that in NAT. + * On validity, copy that node with cold status, otherwise (invalid node) + * ignore that. + */ +static void gc_node_segment(struct f2fs_sb_info *sbi, + struct f2fs_summary *sum, unsigned int segno, int gc_type) +{ + bool initial = true; + struct f2fs_summary *entry; + int off; + +next_step: + entry = sum; + + for (off = 0; off < sbi->blocks_per_seg; off++, entry++) { + nid_t nid = le32_to_cpu(entry->nid); + struct page *node_page; + + /* stop BG_GC if there is not enough free sections. */ + if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0)) + return; + + if (check_valid_map(sbi, segno, off) == 0) + continue; + + if (initial) { + ra_node_page(sbi, nid); + continue; + } + node_page = get_node_page(sbi, nid); + if (IS_ERR(node_page)) + continue; + + /* set page dirty and write it */ + if (gc_type == FG_GC) { + f2fs_wait_on_page_writeback(node_page, NODE); + set_page_dirty(node_page); + } else { + if (!PageWriteback(node_page)) + set_page_dirty(node_page); + } + f2fs_put_page(node_page, 1); + stat_inc_node_blk_count(sbi, 1); + } + + if (initial) { + initial = false; + goto next_step; + } + + if (gc_type == FG_GC) { + struct writeback_control wbc = { + .sync_mode = WB_SYNC_ALL, + .nr_to_write = LONG_MAX, + .for_reclaim = 0, + }; + sync_node_pages(sbi, 0, &wbc); + + /* + * In the case of FG_GC, it'd be better to reclaim this victim + * completely. + */ + if (get_valid_blocks(sbi, segno, 1) != 0) + goto next_step; + } +} + +/* + * Calculate start block index indicating the given node offset. + * Be careful, caller should give this node offset only indicating direct node + * blocks. If any node offsets, which point the other types of node blocks such + * as indirect or double indirect node blocks, are given, it must be a caller's + * bug. + */ +block_t start_bidx_of_node(unsigned int node_ofs, struct f2fs_inode_info *fi) +{ + unsigned int indirect_blks = 2 * NIDS_PER_BLOCK + 4; + unsigned int bidx; + + if (node_ofs == 0) + return 0; + + if (node_ofs <= 2) { + bidx = node_ofs - 1; + } else if (node_ofs <= indirect_blks) { + int dec = (node_ofs - 4) / (NIDS_PER_BLOCK + 1); + bidx = node_ofs - 2 - dec; + } else { + int dec = (node_ofs - indirect_blks - 3) / (NIDS_PER_BLOCK + 1); + bidx = node_ofs - 5 - dec; + } + return bidx * ADDRS_PER_BLOCK + ADDRS_PER_INODE(fi); +} + +static int check_dnode(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + struct node_info *dni, block_t blkaddr, unsigned int *nofs) +{ + struct page *node_page; + nid_t nid; + unsigned int ofs_in_node; + block_t source_blkaddr; + + nid = le32_to_cpu(sum->nid); + ofs_in_node = le16_to_cpu(sum->ofs_in_node); + + node_page = get_node_page(sbi, nid); + if (IS_ERR(node_page)) + return 0; + + get_node_info(sbi, nid, dni); + + if (sum->version != dni->version) { + f2fs_put_page(node_page, 1); + return 0; + } + + *nofs = ofs_of_node(node_page); + source_blkaddr = datablock_addr(node_page, ofs_in_node); + f2fs_put_page(node_page, 1); + + if (source_blkaddr != blkaddr) + return 0; + return 1; +} + +static void move_data_page(struct inode *inode, struct page *page, int gc_type) +{ + struct f2fs_io_info fio = { + .type = DATA, + .rw = WRITE_SYNC, + }; + + if (gc_type == BG_GC) { + if (PageWriteback(page)) + goto out; + set_page_dirty(page); + set_cold_data(page); + } else { + f2fs_wait_on_page_writeback(page, DATA); + + if (clear_page_dirty_for_io(page)) + inode_dec_dirty_dents(inode); + set_cold_data(page); + do_write_data_page(page, &fio); + clear_cold_data(page); + } +out: + f2fs_put_page(page, 1); +} + +/* + * This function tries to get parent node of victim data block, and identifies + * data block validity. If the block is valid, copy that with cold status and + * modify parent node. + * If the parent node is not valid or the data block address is different, + * the victim data block is ignored. + */ +static void gc_data_segment(struct f2fs_sb_info *sbi, struct f2fs_summary *sum, + struct list_head *ilist, unsigned int segno, int gc_type) +{ + struct super_block *sb = sbi->sb; + struct f2fs_summary *entry; + block_t start_addr; + int off; + int phase = 0; + + start_addr = START_BLOCK(sbi, segno); + +next_step: + entry = sum; + + for (off = 0; off < sbi->blocks_per_seg; off++, entry++) { + struct page *data_page; + struct inode *inode; + struct node_info dni; /* dnode info for the data */ + unsigned int ofs_in_node, nofs; + block_t start_bidx; + + /* stop BG_GC if there is not enough free sections. */ + if (gc_type == BG_GC && has_not_enough_free_secs(sbi, 0)) + return; + + if (check_valid_map(sbi, segno, off) == 0) + continue; + + if (phase == 0) { + ra_node_page(sbi, le32_to_cpu(entry->nid)); + continue; + } + + /* Get an inode by ino with checking validity */ + if (check_dnode(sbi, entry, &dni, start_addr + off, &nofs) == 0) + continue; + + if (phase == 1) { + ra_node_page(sbi, dni.ino); + continue; + } + + ofs_in_node = le16_to_cpu(entry->ofs_in_node); + + if (phase == 2) { + inode = f2fs_iget(sb, dni.ino); + if (IS_ERR(inode)) + continue; + + start_bidx = start_bidx_of_node(nofs, F2FS_I(inode)); + + data_page = find_data_page(inode, + start_bidx + ofs_in_node, false); + if (IS_ERR(data_page)) + goto next_iput; + + f2fs_put_page(data_page, 0); + add_gc_inode(inode, ilist); + } else { + inode = find_gc_inode(dni.ino, ilist); + if (inode) { + start_bidx = start_bidx_of_node(nofs, + F2FS_I(inode)); + data_page = get_lock_data_page(inode, + start_bidx + ofs_in_node); + if (IS_ERR(data_page)) + continue; + move_data_page(inode, data_page, gc_type); + stat_inc_data_blk_count(sbi, 1); + } + } + continue; +next_iput: + iput(inode); + } + + if (++phase < 4) + goto next_step; + + if (gc_type == FG_GC) { + f2fs_submit_merged_bio(sbi, DATA, WRITE); + + /* + * In the case of FG_GC, it'd be better to reclaim this victim + * completely. + */ + if (get_valid_blocks(sbi, segno, 1) != 0) { + phase = 2; + goto next_step; + } + } +} + +static int __get_victim(struct f2fs_sb_info *sbi, unsigned int *victim, + int gc_type, int type) +{ + struct sit_info *sit_i = SIT_I(sbi); + int ret; + mutex_lock(&sit_i->sentry_lock); + ret = DIRTY_I(sbi)->v_ops->get_victim(sbi, victim, gc_type, type, LFS); + mutex_unlock(&sit_i->sentry_lock); + return ret; +} + +static void do_garbage_collect(struct f2fs_sb_info *sbi, unsigned int segno, + struct list_head *ilist, int gc_type) +{ + struct page *sum_page; + struct f2fs_summary_block *sum; + struct blk_plug plug; + + /* read segment summary of victim */ + sum_page = get_sum_page(sbi, segno); + + blk_start_plug(&plug); + + sum = page_address(sum_page); + + switch (GET_SUM_TYPE((&sum->footer))) { + case SUM_TYPE_NODE: + gc_node_segment(sbi, sum->entries, segno, gc_type); + break; + case SUM_TYPE_DATA: + gc_data_segment(sbi, sum->entries, ilist, segno, gc_type); + break; + } + blk_finish_plug(&plug); + + stat_inc_seg_count(sbi, GET_SUM_TYPE((&sum->footer))); + stat_inc_call_count(sbi->stat_info); + + f2fs_put_page(sum_page, 1); +} + +int f2fs_gc(struct f2fs_sb_info *sbi) +{ + struct list_head ilist; + unsigned int segno, i; + int gc_type = BG_GC; + int nfree = 0; + int ret = -1; + + INIT_LIST_HEAD(&ilist); +gc_more: + if (unlikely(!(sbi->sb->s_flags & MS_ACTIVE))) + goto stop; + if (unlikely(is_set_ckpt_flags(F2FS_CKPT(sbi), CP_ERROR_FLAG))) + goto stop; + + if (gc_type == BG_GC && has_not_enough_free_secs(sbi, nfree)) { + gc_type = FG_GC; + write_checkpoint(sbi, false); + } + + if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE)) + goto stop; + ret = 0; + + /* readahead multi ssa blocks those have contiguous address */ + if (sbi->segs_per_sec > 1) + ra_meta_pages(sbi, GET_SUM_BLOCK(sbi, segno), sbi->segs_per_sec, + META_SSA); + + for (i = 0; i < sbi->segs_per_sec; i++) + do_garbage_collect(sbi, segno + i, &ilist, gc_type); + + if (gc_type == FG_GC) { + sbi->cur_victim_sec = NULL_SEGNO; + nfree++; + WARN_ON(get_valid_blocks(sbi, segno, sbi->segs_per_sec)); + } + + if (has_not_enough_free_secs(sbi, nfree)) + goto gc_more; + + if (gc_type == FG_GC) + write_checkpoint(sbi, false); +stop: + mutex_unlock(&sbi->gc_mutex); + + put_gc_inode(&ilist); + return ret; +} + +void build_gc_manager(struct f2fs_sb_info *sbi) +{ + DIRTY_I(sbi)->v_ops = &default_v_ops; +} + +int __init create_gc_caches(void) +{ + winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes", + sizeof(struct inode_entry)); + if (!winode_slab) + return -ENOMEM; + return 0; +} + +void destroy_gc_caches(void) +{ + kmem_cache_destroy(winode_slab); +} diff --git a/fs/f2fs/gc.h b/fs/f2fs/gc.h new file mode 100644 index 00000000000..e423aef9114 --- /dev/null +++ b/fs/f2fs/gc.h @@ -0,0 +1,110 @@ +/* + * fs/f2fs/gc.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#define GC_THREAD_MIN_WB_PAGES 1 /* + * a threshold to determine + * whether IO subsystem is idle + * or not + */ +#define DEF_GC_THREAD_MIN_SLEEP_TIME 30000 /* milliseconds */ +#define DEF_GC_THREAD_MAX_SLEEP_TIME 60000 +#define DEF_GC_THREAD_NOGC_SLEEP_TIME 300000 /* wait 5 min */ +#define LIMIT_INVALID_BLOCK 40 /* percentage over total user space */ +#define LIMIT_FREE_BLOCK 40 /* percentage over invalid + free space */ + +/* Search max. number of dirty segments to select a victim segment */ +#define DEF_MAX_VICTIM_SEARCH 4096 /* covers 8GB */ + +struct f2fs_gc_kthread { + struct task_struct *f2fs_gc_task; + wait_queue_head_t gc_wait_queue_head; + + /* for gc sleep time */ + unsigned int min_sleep_time; + unsigned int max_sleep_time; + unsigned int no_gc_sleep_time; + + /* for changing gc mode */ + unsigned int gc_idle; +}; + +struct inode_entry { + struct list_head list; + struct inode *inode; +}; + +/* + * inline functions + */ +static inline block_t free_user_blocks(struct f2fs_sb_info *sbi) +{ + if (free_segments(sbi) < overprovision_segments(sbi)) + return 0; + else + return (free_segments(sbi) - overprovision_segments(sbi)) + << sbi->log_blocks_per_seg; +} + +static inline block_t limit_invalid_user_blocks(struct f2fs_sb_info *sbi) +{ + return (long)(sbi->user_block_count * LIMIT_INVALID_BLOCK) / 100; +} + +static inline block_t limit_free_user_blocks(struct f2fs_sb_info *sbi) +{ + block_t reclaimable_user_blocks = sbi->user_block_count - + written_block_count(sbi); + return (long)(reclaimable_user_blocks * LIMIT_FREE_BLOCK) / 100; +} + +static inline long increase_sleep_time(struct f2fs_gc_kthread *gc_th, long wait) +{ + if (wait == gc_th->no_gc_sleep_time) + return wait; + + wait += gc_th->min_sleep_time; + if (wait > gc_th->max_sleep_time) + wait = gc_th->max_sleep_time; + return wait; +} + +static inline long decrease_sleep_time(struct f2fs_gc_kthread *gc_th, long wait) +{ + if (wait == gc_th->no_gc_sleep_time) + wait = gc_th->max_sleep_time; + + wait -= gc_th->min_sleep_time; + if (wait <= gc_th->min_sleep_time) + wait = gc_th->min_sleep_time; + return wait; +} + +static inline bool has_enough_invalid_blocks(struct f2fs_sb_info *sbi) +{ + block_t invalid_user_blocks = sbi->user_block_count - + written_block_count(sbi); + /* + * Background GC is triggered with the following condition. + * 1. There are a number of invalid blocks. + * 2. There is not enough free space. + */ + if (invalid_user_blocks > limit_invalid_user_blocks(sbi) && + free_user_blocks(sbi) < limit_free_user_blocks(sbi)) + return true; + return false; +} + +static inline int is_idle(struct f2fs_sb_info *sbi) +{ + struct block_device *bdev = sbi->sb->s_bdev; + struct request_queue *q = bdev_get_queue(bdev); + struct request_list *rl = &q->rq; + return !(rl->count[BLK_RW_SYNC]) && !(rl->count[BLK_RW_ASYNC]); +} diff --git a/fs/f2fs/hash.c b/fs/f2fs/hash.c new file mode 100644 index 00000000000..948d17bf728 --- /dev/null +++ b/fs/f2fs/hash.c @@ -0,0 +1,103 @@ +/* + * fs/f2fs/hash.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Portions of this code from linux/fs/ext3/hash.c + * + * Copyright (C) 2002 by Theodore Ts'o + * + * 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 "f2fs.h" + +/* + * Hashing code copied from ext3 + */ +#define DELTA 0x9E3779B9 + +static void TEA_transform(unsigned int buf[4], unsigned int const in[]) +{ + __u32 sum = 0; + __u32 b0 = buf[0], b1 = buf[1]; + __u32 a = in[0], b = in[1], c = in[2], d = in[3]; + int n = 16; + + do { + sum += DELTA; + b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b); + b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d); + } while (--n); + + buf[0] += b0; + buf[1] += b1; +} + +static void str2hashbuf(const char *msg, size_t len, unsigned int *buf, int num) +{ + unsigned pad, val; + int i; + + pad = (__u32)len | ((__u32)len << 8); + pad |= pad << 16; + + val = pad; + if (len > num * 4) + len = num * 4; + for (i = 0; i < len; i++) { + if ((i % 4) == 0) + val = pad; + val = msg[i] + (val << 8); + if ((i % 4) == 3) { + *buf++ = val; + val = pad; + num--; + } + } + if (--num >= 0) + *buf++ = val; + while (--num >= 0) + *buf++ = pad; +} + +f2fs_hash_t f2fs_dentry_hash(const struct qstr *name_info) +{ + __u32 hash; + f2fs_hash_t f2fs_hash; + const char *p; + __u32 in[8], buf[4]; + const char *name = name_info->name; + size_t len = name_info->len; + + if ((len <= 2) && (name[0] == '.') && + (name[1] == '.' || name[1] == '\0')) + return 0; + + /* Initialize the default seed for the hash checksum functions */ + buf[0] = 0x67452301; + buf[1] = 0xefcdab89; + buf[2] = 0x98badcfe; + buf[3] = 0x10325476; + + p = name; + while (1) { + str2hashbuf(p, len, in, 4); + TEA_transform(buf, in); + p += 16; + if (len <= 16) + break; + len -= 16; + } + hash = buf[0]; + f2fs_hash = cpu_to_le32(hash & ~F2FS_HASH_COL_BIT); + return f2fs_hash; +} diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c new file mode 100644 index 00000000000..1bba5228c19 --- /dev/null +++ b/fs/f2fs/inline.c @@ -0,0 +1,250 @@ +/* + * fs/f2fs/inline.c + * Copyright (c) 2013, Intel Corporation + * Authors: Huajun Li + * Haicheng Li + * 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 "f2fs.h" + +bool f2fs_may_inline(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + block_t nr_blocks; + loff_t i_size; + + if (!test_opt(sbi, INLINE_DATA)) + return false; + + nr_blocks = F2FS_I(inode)->i_xattr_nid ? 3 : 2; + if (inode->i_blocks > nr_blocks) + return false; + + i_size = i_size_read(inode); + if (i_size > MAX_INLINE_DATA) + return false; + + return true; +} + +int f2fs_read_inline_data(struct inode *inode, struct page *page) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct page *ipage; + void *src_addr, *dst_addr; + + if (page->index) { + zero_user_segment(page, 0, PAGE_CACHE_SIZE); + goto out; + } + + ipage = get_node_page(sbi, inode->i_ino); + if (IS_ERR(ipage)) { + unlock_page(page); + return PTR_ERR(ipage); + } + + zero_user_segment(page, MAX_INLINE_DATA, PAGE_CACHE_SIZE); + + /* Copy the whole inline data block */ + src_addr = inline_data_addr(ipage); + dst_addr = kmap(page); + memcpy(dst_addr, src_addr, MAX_INLINE_DATA); + kunmap(page); + f2fs_put_page(ipage, 1); + +out: + SetPageUptodate(page); + unlock_page(page); + + return 0; +} + +static int __f2fs_convert_inline_data(struct inode *inode, struct page *page) +{ + int err; + struct page *ipage; + struct dnode_of_data dn; + void *src_addr, *dst_addr; + block_t new_blk_addr; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct f2fs_io_info fio = { + .type = DATA, + .rw = WRITE_SYNC | REQ_PRIO, + }; + + f2fs_lock_op(sbi); + ipage = get_node_page(sbi, inode->i_ino); + if (IS_ERR(ipage)) { + err = PTR_ERR(ipage); + goto out; + } + + /* + * i_addr[0] is not used for inline data, + * so reserving new block will not destroy inline data + */ + set_new_dnode(&dn, inode, ipage, NULL, 0); + err = f2fs_reserve_block(&dn, 0); + if (err) + goto out; + + f2fs_wait_on_page_writeback(page, DATA); + zero_user_segment(page, MAX_INLINE_DATA, PAGE_CACHE_SIZE); + + /* Copy the whole inline data block */ + src_addr = inline_data_addr(ipage); + dst_addr = kmap(page); + memcpy(dst_addr, src_addr, MAX_INLINE_DATA); + kunmap(page); + SetPageUptodate(page); + + /* write data page to try to make data consistent */ + set_page_writeback(page); + write_data_page(page, &dn, &new_blk_addr, &fio); + update_extent_cache(new_blk_addr, &dn); + f2fs_wait_on_page_writeback(page, DATA); + + /* clear inline data and flag after data writeback */ + zero_user_segment(ipage, INLINE_DATA_OFFSET, + INLINE_DATA_OFFSET + MAX_INLINE_DATA); + clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA); + stat_dec_inline_inode(inode); + + sync_inode_page(&dn); + f2fs_put_dnode(&dn); +out: + f2fs_unlock_op(sbi); + return err; +} + +int f2fs_convert_inline_data(struct inode *inode, pgoff_t to_size) +{ + struct page *page; + int err; + + if (!f2fs_has_inline_data(inode)) + return 0; + else if (to_size <= MAX_INLINE_DATA) + return 0; + + page = grab_cache_page(inode->i_mapping, 0); + if (!page) + return -ENOMEM; + + err = __f2fs_convert_inline_data(inode, page); + f2fs_put_page(page, 1); + return err; +} + +int f2fs_write_inline_data(struct inode *inode, + struct page *page, unsigned size) +{ + void *src_addr, *dst_addr; + struct page *ipage; + struct dnode_of_data dn; + int err; + + set_new_dnode(&dn, inode, NULL, NULL, 0); + err = get_dnode_of_data(&dn, 0, LOOKUP_NODE); + if (err) + return err; + ipage = dn.inode_page; + + f2fs_wait_on_page_writeback(ipage, NODE); + zero_user_segment(ipage, INLINE_DATA_OFFSET, + INLINE_DATA_OFFSET + MAX_INLINE_DATA); + src_addr = kmap(page); + dst_addr = inline_data_addr(ipage); + memcpy(dst_addr, src_addr, size); + kunmap(page); + + /* Release the first data block if it is allocated */ + if (!f2fs_has_inline_data(inode)) { + truncate_data_blocks_range(&dn, 1); + set_inode_flag(F2FS_I(inode), FI_INLINE_DATA); + stat_inc_inline_inode(inode); + } + + sync_inode_page(&dn); + f2fs_put_dnode(&dn); + + return 0; +} + +void truncate_inline_data(struct inode *inode, u64 from) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct page *ipage; + + if (from >= MAX_INLINE_DATA) + return; + + ipage = get_node_page(sbi, inode->i_ino); + if (IS_ERR(ipage)) + return; + + f2fs_wait_on_page_writeback(ipage, NODE); + + zero_user_segment(ipage, INLINE_DATA_OFFSET + from, + INLINE_DATA_OFFSET + MAX_INLINE_DATA); + set_page_dirty(ipage); + f2fs_put_page(ipage, 1); +} + +int recover_inline_data(struct inode *inode, struct page *npage) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct f2fs_inode *ri = NULL; + void *src_addr, *dst_addr; + struct page *ipage; + + /* + * The inline_data recovery policy is as follows. + * [prev.] [next] of inline_data flag + * o o -> recover inline_data + * o x -> remove inline_data, and then recover data blocks + * x o -> remove inline_data, and then recover inline_data + * x x -> recover data blocks + */ + if (IS_INODE(npage)) + ri = F2FS_INODE(npage); + + if (f2fs_has_inline_data(inode) && + ri && ri->i_inline & F2FS_INLINE_DATA) { +process_inline: + ipage = get_node_page(sbi, inode->i_ino); + f2fs_bug_on(IS_ERR(ipage)); + + f2fs_wait_on_page_writeback(ipage, NODE); + + src_addr = inline_data_addr(npage); + dst_addr = inline_data_addr(ipage); + memcpy(dst_addr, src_addr, MAX_INLINE_DATA); + update_inode(inode, ipage); + f2fs_put_page(ipage, 1); + return -1; + } + + if (f2fs_has_inline_data(inode)) { + ipage = get_node_page(sbi, inode->i_ino); + f2fs_bug_on(IS_ERR(ipage)); + f2fs_wait_on_page_writeback(ipage, NODE); + zero_user_segment(ipage, INLINE_DATA_OFFSET, + INLINE_DATA_OFFSET + MAX_INLINE_DATA); + clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA); + update_inode(inode, ipage); + f2fs_put_page(ipage, 1); + } else if (ri && ri->i_inline & F2FS_INLINE_DATA) { + truncate_blocks(inode, 0); + set_inode_flag(F2FS_I(inode), FI_INLINE_DATA); + goto process_inline; + } + return 0; +} diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c new file mode 100644 index 00000000000..9a290ef5eaf --- /dev/null +++ b/fs/f2fs/inode.c @@ -0,0 +1,298 @@ +/* + * fs/f2fs/inode.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" + +#include + +void f2fs_set_inode_flags(struct inode *inode) +{ + unsigned int flags = F2FS_I(inode)->i_flags; + unsigned int new_fl = 0; + + if (flags & FS_SYNC_FL) + new_fl |= S_SYNC; + if (flags & FS_APPEND_FL) + new_fl |= S_APPEND; + if (flags & FS_IMMUTABLE_FL) + new_fl |= S_IMMUTABLE; + if (flags & FS_NOATIME_FL) + new_fl |= S_NOATIME; + if (flags & FS_DIRSYNC_FL) + new_fl |= S_DIRSYNC; + set_mask_bits(&inode->i_flags, + S_SYNC|S_APPEND|S_IMMUTABLE|S_NOATIME|S_DIRSYNC, new_fl); +} + +static void __get_inode_rdev(struct inode *inode, struct f2fs_inode *ri) +{ + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || + S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + if (ri->i_addr[0]) + inode->i_rdev = + old_decode_dev(le32_to_cpu(ri->i_addr[0])); + else + inode->i_rdev = + new_decode_dev(le32_to_cpu(ri->i_addr[1])); + } +} + +static void __set_inode_rdev(struct inode *inode, struct f2fs_inode *ri) +{ + if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { + if (old_valid_dev(inode->i_rdev)) { + ri->i_addr[0] = + cpu_to_le32(old_encode_dev(inode->i_rdev)); + ri->i_addr[1] = 0; + } else { + ri->i_addr[0] = 0; + ri->i_addr[1] = + cpu_to_le32(new_encode_dev(inode->i_rdev)); + ri->i_addr[2] = 0; + } + } +} + +static int do_read_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct f2fs_inode_info *fi = F2FS_I(inode); + struct page *node_page; + struct f2fs_inode *ri; + + /* Check if ino is within scope */ + if (check_nid_range(sbi, inode->i_ino)) { + f2fs_msg(inode->i_sb, KERN_ERR, "bad inode number: %lu", + (unsigned long) inode->i_ino); + WARN_ON(1); + return -EINVAL; + } + + node_page = get_node_page(sbi, inode->i_ino); + if (IS_ERR(node_page)) + return PTR_ERR(node_page); + + ri = F2FS_INODE(node_page); + + inode->i_mode = le16_to_cpu(ri->i_mode); + inode->i_uid = le32_to_cpu(ri->i_uid); + inode->i_gid = le32_to_cpu(ri->i_gid); + set_nlink(inode, le32_to_cpu(ri->i_links)); + inode->i_size = le64_to_cpu(ri->i_size); + inode->i_blocks = le64_to_cpu(ri->i_blocks); + + inode->i_atime.tv_sec = le64_to_cpu(ri->i_atime); + inode->i_ctime.tv_sec = le64_to_cpu(ri->i_ctime); + inode->i_mtime.tv_sec = le64_to_cpu(ri->i_mtime); + inode->i_atime.tv_nsec = le32_to_cpu(ri->i_atime_nsec); + inode->i_ctime.tv_nsec = le32_to_cpu(ri->i_ctime_nsec); + inode->i_mtime.tv_nsec = le32_to_cpu(ri->i_mtime_nsec); + inode->i_generation = le32_to_cpu(ri->i_generation); + + fi->i_current_depth = le32_to_cpu(ri->i_current_depth); + fi->i_xattr_nid = le32_to_cpu(ri->i_xattr_nid); + fi->i_flags = le32_to_cpu(ri->i_flags); + fi->flags = 0; + fi->i_advise = ri->i_advise; + fi->i_pino = le32_to_cpu(ri->i_pino); + fi->i_dir_level = ri->i_dir_level; + + get_extent_info(&fi->ext, ri->i_ext); + get_inline_info(fi, ri); + + /* get rdev by using inline_info */ + __get_inode_rdev(inode, ri); + + f2fs_put_page(node_page, 1); + return 0; +} + +struct inode *f2fs_iget(struct super_block *sb, unsigned long ino) +{ + struct f2fs_sb_info *sbi = F2FS_SB(sb); + struct inode *inode; + int ret = 0; + + inode = iget_locked(sb, ino); + if (!inode) + return ERR_PTR(-ENOMEM); + + if (!(inode->i_state & I_NEW)) { + trace_f2fs_iget(inode); + return inode; + } + if (ino == F2FS_NODE_INO(sbi) || ino == F2FS_META_INO(sbi)) + goto make_now; + + ret = do_read_inode(inode); + if (ret) + goto bad_inode; +make_now: + if (ino == F2FS_NODE_INO(sbi)) { + inode->i_mapping->a_ops = &f2fs_node_aops; + mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); + } else if (ino == F2FS_META_INO(sbi)) { + inode->i_mapping->a_ops = &f2fs_meta_aops; + mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); + } else if (S_ISREG(inode->i_mode)) { + inode->i_op = &f2fs_file_inode_operations; + inode->i_fop = &f2fs_file_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; + } else if (S_ISDIR(inode->i_mode)) { + inode->i_op = &f2fs_dir_inode_operations; + inode->i_fop = &f2fs_dir_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; + mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); + } else if (S_ISLNK(inode->i_mode)) { + inode->i_op = &f2fs_symlink_inode_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; + } else if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode) || + S_ISFIFO(inode->i_mode) || S_ISSOCK(inode->i_mode)) { + inode->i_op = &f2fs_special_inode_operations; + init_special_inode(inode, inode->i_mode, inode->i_rdev); + } else { + ret = -EIO; + goto bad_inode; + } + unlock_new_inode(inode); + trace_f2fs_iget(inode); + return inode; + +bad_inode: + iget_failed(inode); + trace_f2fs_iget_exit(inode, ret); + return ERR_PTR(ret); +} + +void update_inode(struct inode *inode, struct page *node_page) +{ + struct f2fs_inode *ri; + + f2fs_wait_on_page_writeback(node_page, NODE); + + ri = F2FS_INODE(node_page); + + ri->i_mode = cpu_to_le16(inode->i_mode); + ri->i_advise = F2FS_I(inode)->i_advise; + ri->i_uid = cpu_to_le32(inode->i_uid); + ri->i_gid = cpu_to_le32(inode->i_gid); + ri->i_links = cpu_to_le32(inode->i_nlink); + ri->i_size = cpu_to_le64(i_size_read(inode)); + ri->i_blocks = cpu_to_le64(inode->i_blocks); + set_raw_extent(&F2FS_I(inode)->ext, &ri->i_ext); + set_raw_inline(F2FS_I(inode), ri); + + ri->i_atime = cpu_to_le64(inode->i_atime.tv_sec); + ri->i_ctime = cpu_to_le64(inode->i_ctime.tv_sec); + ri->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec); + ri->i_atime_nsec = cpu_to_le32(inode->i_atime.tv_nsec); + ri->i_ctime_nsec = cpu_to_le32(inode->i_ctime.tv_nsec); + ri->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); + ri->i_current_depth = cpu_to_le32(F2FS_I(inode)->i_current_depth); + ri->i_xattr_nid = cpu_to_le32(F2FS_I(inode)->i_xattr_nid); + ri->i_flags = cpu_to_le32(F2FS_I(inode)->i_flags); + ri->i_pino = cpu_to_le32(F2FS_I(inode)->i_pino); + ri->i_generation = cpu_to_le32(inode->i_generation); + ri->i_dir_level = F2FS_I(inode)->i_dir_level; + + __set_inode_rdev(inode, ri); + set_cold_node(inode, node_page); + set_page_dirty(node_page); + + clear_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); +} + +void update_inode_page(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct page *node_page; +retry: + node_page = get_node_page(sbi, inode->i_ino); + if (IS_ERR(node_page)) { + int err = PTR_ERR(node_page); + if (err == -ENOMEM) { + cond_resched(); + goto retry; + } else if (err != -ENOENT) { + f2fs_stop_checkpoint(sbi); + } + return; + } + update_inode(inode, node_page); + f2fs_put_page(node_page, 1); +} + +int f2fs_write_inode(struct inode *inode, struct writeback_control *wbc) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + + if (inode->i_ino == F2FS_NODE_INO(sbi) || + inode->i_ino == F2FS_META_INO(sbi)) + return 0; + + if (!is_inode_flag_set(F2FS_I(inode), FI_DIRTY_INODE)) + return 0; + + /* + * We need to lock here to prevent from producing dirty node pages + * during the urgent cleaning time when runing out of free sections. + */ + f2fs_lock_op(sbi); + update_inode_page(inode); + f2fs_unlock_op(sbi); + + if (wbc) + f2fs_balance_fs(sbi); + + return 0; +} + +/* + * Called at the last iput() if i_nlink is zero + */ +void f2fs_evict_inode(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + + trace_f2fs_evict_inode(inode); + truncate_inode_pages(&inode->i_data, 0); + + if (inode->i_ino == F2FS_NODE_INO(sbi) || + inode->i_ino == F2FS_META_INO(sbi)) + goto no_delete; + + f2fs_bug_on(get_dirty_dents(inode)); + remove_dirty_dir_inode(inode); + + if (inode->i_nlink || is_bad_inode(inode)) + goto no_delete; + + set_inode_flag(F2FS_I(inode), FI_NO_ALLOC); + i_size_write(inode, 0); + + if (F2FS_HAS_BLOCKS(inode)) + f2fs_truncate(inode); + + f2fs_lock_op(sbi); + remove_inode_page(inode); + stat_dec_inline_inode(inode); + f2fs_unlock_op(sbi); + +no_delete: + end_writeback(inode); + invalidate_mapping_pages(NODE_MAPPING(sbi), inode->i_ino, inode->i_ino); +} diff --git a/fs/f2fs/namei.c b/fs/f2fs/namei.c new file mode 100644 index 00000000000..a4b37a7a022 --- /dev/null +++ b/fs/f2fs/namei.c @@ -0,0 +1,587 @@ +/* + * fs/f2fs/namei.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" +#include "xattr.h" +#include "acl.h" +#include + +static struct inode *f2fs_new_inode(struct inode *dir, umode_t mode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + nid_t ino; + struct inode *inode; + bool nid_free = false; + int err; + + inode = new_inode(dir->i_sb); + if (!inode) + return ERR_PTR(-ENOMEM); + + f2fs_lock_op(sbi); + if (!alloc_nid(sbi, &ino)) { + f2fs_unlock_op(sbi); + err = -ENOSPC; + goto fail; + } + f2fs_unlock_op(sbi); + + if (IS_ANDROID_EMU(sbi, F2FS_I(dir), F2FS_I(dir))) + f2fs_android_emu(sbi, inode, &inode->i_uid, + &inode->i_gid, &mode); + else + inode_init_owner(inode, dir, mode); + + inode->i_ino = ino; + inode->i_blocks = 0; + inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; + inode->i_generation = sbi->s_next_generation++; + + err = insert_inode_locked(inode); + if (err) { + err = -EINVAL; + nid_free = true; + goto out; + } + trace_f2fs_new_inode(inode, 0); + mark_inode_dirty(inode); + return inode; + +out: + clear_nlink(inode); + unlock_new_inode(inode); +fail: + trace_f2fs_new_inode(inode, err); + make_bad_inode(inode); + iput(inode); + if (nid_free) + alloc_nid_failed(sbi, ino); + return ERR_PTR(err); +} + +static int is_multimedia_file(const unsigned char *s, const char *sub) +{ + size_t slen = strlen(s); + size_t sublen = strlen(sub); + + if (sublen > slen) + return 0; + + return !strncasecmp(s + slen - sublen, sub, sublen); +} + +/* + * Set multimedia files as cold files for hot/cold data separation + */ +static inline void set_cold_files(struct f2fs_sb_info *sbi, struct inode *inode, + const unsigned char *name) +{ + int i; + __u8 (*extlist)[8] = sbi->raw_super->extension_list; + + int count = le32_to_cpu(sbi->raw_super->extension_count); + for (i = 0; i < count; i++) { + if (is_multimedia_file(name, extlist[i])) { + file_set_cold(inode); + break; + } + } +} + +static int f2fs_create(struct inode *dir, struct dentry *dentry, umode_t mode, + struct nameidata *nd) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + struct inode *inode; + nid_t ino = 0; + int err; + + f2fs_balance_fs(sbi); + + inode = f2fs_new_inode(dir, mode); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + if (!test_opt(sbi, DISABLE_EXT_IDENTIFY)) + set_cold_files(sbi, inode, dentry->d_name.name); + + inode->i_op = &f2fs_file_inode_operations; + inode->i_fop = &f2fs_file_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; + ino = inode->i_ino; + + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); + f2fs_unlock_op(sbi); + if (err) + goto out; + + alloc_nid_done(sbi, ino); + + d_instantiate(dentry, inode); + unlock_new_inode(inode); + return 0; +out: + clear_nlink(inode); + unlock_new_inode(inode); + make_bad_inode(inode); + iput(inode); + alloc_nid_failed(sbi, ino); + return err; +} + +static int f2fs_link(struct dentry *old_dentry, struct inode *dir, + struct dentry *dentry) +{ + struct inode *inode = old_dentry->d_inode; + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + int err; + + f2fs_balance_fs(sbi); + + inode->i_ctime = CURRENT_TIME; + ihold(inode); + + set_inode_flag(F2FS_I(inode), FI_INC_LINK); + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); + f2fs_unlock_op(sbi); + if (err) + goto out; + + d_instantiate(dentry, inode); + return 0; +out: + clear_inode_flag(F2FS_I(inode), FI_INC_LINK); + iput(inode); + return err; +} + +struct dentry *f2fs_get_parent(struct dentry *child) +{ + struct qstr dotdot = {.name = "..", .len = 2}; + unsigned long ino = f2fs_inode_by_name(child->d_inode, &dotdot); + if (!ino) + return ERR_PTR(-ENOENT); + return d_obtain_alias(f2fs_iget(child->d_inode->i_sb, ino)); +} + +static struct dentry *f2fs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) +{ + struct inode *inode = NULL; + struct f2fs_dir_entry *de; + struct page *page; + + if (dentry->d_name.len > F2FS_NAME_LEN) + return ERR_PTR(-ENAMETOOLONG); + + de = f2fs_find_entry(dir, &dentry->d_name, &page); + if (de) { + nid_t ino = le32_to_cpu(de->ino); + kunmap(page); + f2fs_put_page(page, 0); + + inode = f2fs_iget(dir->i_sb, ino); + if (IS_ERR(inode)) + return ERR_CAST(inode); + + stat_inc_inline_inode(inode); + } + + return d_splice_alias(inode, dentry); +} + +static int f2fs_unlink(struct inode *dir, struct dentry *dentry) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + struct inode *inode = dentry->d_inode; + struct f2fs_dir_entry *de; + struct page *page; + int err = -ENOENT; + + trace_f2fs_unlink_enter(dir, dentry); + f2fs_balance_fs(sbi); + + de = f2fs_find_entry(dir, &dentry->d_name, &page); + if (!de) + goto fail; + + f2fs_lock_op(sbi); + err = acquire_orphan_inode(sbi); + if (err) { + f2fs_unlock_op(sbi); + kunmap(page); + f2fs_put_page(page, 0); + goto fail; + } + f2fs_delete_entry(de, page, inode); + f2fs_unlock_op(sbi); + + /* In order to evict this inode, we set it dirty */ + mark_inode_dirty(inode); +fail: + trace_f2fs_unlink_exit(inode, err); + return err; +} + +static int f2fs_symlink(struct inode *dir, struct dentry *dentry, + const char *symname) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + struct inode *inode; + size_t symlen = strlen(symname) + 1; + int err; + + f2fs_balance_fs(sbi); + + inode = f2fs_new_inode(dir, S_IFLNK | S_IRWXUGO); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + inode->i_op = &f2fs_symlink_inode_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; + + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); + f2fs_unlock_op(sbi); + if (err) + goto out; + + err = page_symlink(inode, symname, symlen); + alloc_nid_done(sbi, inode->i_ino); + + d_instantiate(dentry, inode); + unlock_new_inode(inode); + return err; +out: + clear_nlink(inode); + unlock_new_inode(inode); + make_bad_inode(inode); + iput(inode); + alloc_nid_failed(sbi, inode->i_ino); + return err; +} + +static int f2fs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + struct inode *inode; + int err; + + f2fs_balance_fs(sbi); + + inode = f2fs_new_inode(dir, S_IFDIR | mode); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + inode->i_op = &f2fs_dir_inode_operations; + inode->i_fop = &f2fs_dir_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; + mapping_set_gfp_mask(inode->i_mapping, GFP_F2FS_ZERO); + + set_inode_flag(F2FS_I(inode), FI_INC_LINK); + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); + f2fs_unlock_op(sbi); + if (err) + goto out_fail; + + alloc_nid_done(sbi, inode->i_ino); + + d_instantiate(dentry, inode); + unlock_new_inode(inode); + + return 0; + +out_fail: + clear_inode_flag(F2FS_I(inode), FI_INC_LINK); + clear_nlink(inode); + unlock_new_inode(inode); + make_bad_inode(inode); + iput(inode); + alloc_nid_failed(sbi, inode->i_ino); + return err; +} + +static int f2fs_rmdir(struct inode *dir, struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + if (f2fs_empty_dir(inode)) + return f2fs_unlink(dir, dentry); + return -ENOTEMPTY; +} + +static int f2fs_mknod(struct inode *dir, struct dentry *dentry, + umode_t mode, dev_t rdev) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + struct inode *inode; + int err = 0; + + if (!new_valid_dev(rdev)) + return -EINVAL; + + f2fs_balance_fs(sbi); + + inode = f2fs_new_inode(dir, mode); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + init_special_inode(inode, inode->i_mode, rdev); + inode->i_op = &f2fs_special_inode_operations; + + f2fs_lock_op(sbi); + err = f2fs_add_link(dentry, inode); + f2fs_unlock_op(sbi); + if (err) + goto out; + + alloc_nid_done(sbi, inode->i_ino); + d_instantiate(dentry, inode); + unlock_new_inode(inode); + return 0; +out: + clear_nlink(inode); + unlock_new_inode(inode); + make_bad_inode(inode); + iput(inode); + alloc_nid_failed(sbi, inode->i_ino); + return err; +} + +static int f2fs_rename(struct inode *old_dir, struct dentry *old_dentry, + struct inode *new_dir, struct dentry *new_dentry) +{ + struct f2fs_sb_info *sbi = F2FS_SB(old_dir->i_sb); + struct inode *old_inode = old_dentry->d_inode; + struct inode *new_inode = new_dentry->d_inode; + struct page *old_dir_page; + struct page *old_page, *new_page; + struct f2fs_dir_entry *old_dir_entry = NULL; + struct f2fs_dir_entry *old_entry; + struct f2fs_dir_entry *new_entry; + int err = -ENOENT; + + f2fs_balance_fs(sbi); + + old_entry = f2fs_find_entry(old_dir, &old_dentry->d_name, &old_page); + if (!old_entry) + goto out; + + if (S_ISDIR(old_inode->i_mode)) { + err = -EIO; + old_dir_entry = f2fs_parent_dir(old_inode, &old_dir_page); + if (!old_dir_entry) + goto out_old; + } + + if (new_inode) { + + err = -ENOTEMPTY; + if (old_dir_entry && !f2fs_empty_dir(new_inode)) + goto out_dir; + + err = -ENOENT; + new_entry = f2fs_find_entry(new_dir, &new_dentry->d_name, + &new_page); + if (!new_entry) + goto out_dir; + + f2fs_lock_op(sbi); + + err = acquire_orphan_inode(sbi); + if (err) + goto put_out_dir; + + if (update_dent_inode(old_inode, &new_dentry->d_name)) { + release_orphan_inode(sbi); + goto put_out_dir; + } + + f2fs_set_link(new_dir, new_entry, new_page, old_inode); + + new_inode->i_ctime = CURRENT_TIME; + down_write(&F2FS_I(new_inode)->i_sem); + if (old_dir_entry) + drop_nlink(new_inode); + drop_nlink(new_inode); + up_write(&F2FS_I(new_inode)->i_sem); + + mark_inode_dirty(new_inode); + + if (!new_inode->i_nlink) + add_orphan_inode(sbi, new_inode->i_ino); + else + release_orphan_inode(sbi); + + update_inode_page(old_inode); + update_inode_page(new_inode); + } else { + f2fs_lock_op(sbi); + + err = f2fs_add_link(new_dentry, old_inode); + if (err) { + f2fs_unlock_op(sbi); + goto out_dir; + } + + if (old_dir_entry) { + inc_nlink(new_dir); + update_inode_page(new_dir); + } + } + + down_write(&F2FS_I(old_inode)->i_sem); + file_lost_pino(old_inode); + up_write(&F2FS_I(old_inode)->i_sem); + + old_inode->i_ctime = CURRENT_TIME; + mark_inode_dirty(old_inode); + + f2fs_delete_entry(old_entry, old_page, NULL); + + if (old_dir_entry) { + if (old_dir != new_dir) { + f2fs_set_link(old_inode, old_dir_entry, + old_dir_page, new_dir); + update_inode_page(old_inode); + } else { + kunmap(old_dir_page); + f2fs_put_page(old_dir_page, 0); + } + drop_nlink(old_dir); + mark_inode_dirty(old_dir); + update_inode_page(old_dir); + } + + f2fs_unlock_op(sbi); + return 0; + +put_out_dir: + f2fs_unlock_op(sbi); + kunmap(new_page); + f2fs_put_page(new_page, 0); +out_dir: + if (old_dir_entry) { + kunmap(old_dir_page); + f2fs_put_page(old_dir_page, 0); + } +out_old: + kunmap(old_page); + f2fs_put_page(old_page, 0); +out: + return err; +} + +static int f2fs_tmpfile(struct inode *dir, struct dentry *dentry, umode_t mode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); + struct inode *inode; + int err; + + inode = f2fs_new_inode(dir, mode); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + inode->i_op = &f2fs_file_inode_operations; + inode->i_fop = &f2fs_file_operations; + inode->i_mapping->a_ops = &f2fs_dblock_aops; + + f2fs_lock_op(sbi); + err = acquire_orphan_inode(sbi); + if (err) + goto out; + + err = f2fs_do_tmpfile(inode, dir); + if (err) + goto release_out; + + /* + * add this non-linked tmpfile to orphan list, in this way we could + * remove all unused data of tmpfile after abnormal power-off. + */ + add_orphan_inode(sbi, inode->i_ino); + f2fs_unlock_op(sbi); + + alloc_nid_done(sbi, inode->i_ino); + d_tmpfile(dentry, inode); + unlock_new_inode(inode); + return 0; + +release_out: + release_orphan_inode(sbi); +out: + f2fs_unlock_op(sbi); + clear_nlink(inode); + unlock_new_inode(inode); + make_bad_inode(inode); + iput(inode); + alloc_nid_failed(sbi, inode->i_ino); + return err; +} + +const struct inode_operations f2fs_dir_inode_operations = { + .create = f2fs_create, + .lookup = f2fs_lookup, + .link = f2fs_link, + .unlink = f2fs_unlink, + .symlink = f2fs_symlink, + .mkdir = f2fs_mkdir, + .rmdir = f2fs_rmdir, + .mknod = f2fs_mknod, + .rename = f2fs_rename, + .tmpfile = f2fs_tmpfile, + .getattr = f2fs_getattr, + .setattr = f2fs_setattr, + .get_acl = f2fs_get_acl, + .set_acl = f2fs_set_acl, +#ifdef CONFIG_F2FS_FS_XATTR + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = f2fs_listxattr, + .removexattr = generic_removexattr, +#endif +}; + +const struct inode_operations f2fs_symlink_inode_operations = { + .readlink = generic_readlink, + .follow_link = page_follow_link_light, + .put_link = page_put_link, + .getattr = f2fs_getattr, + .setattr = f2fs_setattr, +#ifdef CONFIG_F2FS_FS_XATTR + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = f2fs_listxattr, + .removexattr = generic_removexattr, +#endif +}; + +const struct inode_operations f2fs_special_inode_operations = { + .getattr = f2fs_getattr, + .setattr = f2fs_setattr, + .get_acl = f2fs_get_acl, + .set_acl = f2fs_set_acl, +#ifdef CONFIG_F2FS_FS_XATTR + .setxattr = generic_setxattr, + .getxattr = generic_getxattr, + .listxattr = f2fs_listxattr, + .removexattr = generic_removexattr, +#endif +}; diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c new file mode 100644 index 00000000000..b8ac0149010 --- /dev/null +++ b/fs/f2fs/node.c @@ -0,0 +1,2112 @@ +/* + * fs/f2fs/node.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" +#include "segment.h" +#include + +#define on_build_free_nids(nmi) mutex_is_locked(&nm_i->build_lock) + +static struct kmem_cache *nat_entry_slab; +static struct kmem_cache *free_nid_slab; +static struct kmem_cache *nat_entry_set_slab; + +bool available_free_memory(struct f2fs_sb_info *sbi, int type) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct sysinfo val; + unsigned long mem_size = 0; + bool res = false; + + si_meminfo(&val); + /* give 25%, 25%, 50% memory for each components respectively */ + if (type == FREE_NIDS) { + mem_size = (nm_i->fcnt * sizeof(struct free_nid)) >> 12; + res = mem_size < ((val.totalram * nm_i->ram_thresh / 100) >> 2); + } else if (type == NAT_ENTRIES) { + mem_size = (nm_i->nat_cnt * sizeof(struct nat_entry)) >> 12; + res = mem_size < ((val.totalram * nm_i->ram_thresh / 100) >> 2); + } else if (type == DIRTY_DENTS) { + if (sbi->sb->s_bdi->dirty_exceeded) + return false; + mem_size = get_pages(sbi, F2FS_DIRTY_DENTS); + res = mem_size < ((val.totalram * nm_i->ram_thresh / 100) >> 1); + } + return res; +} + +static void clear_node_page_dirty(struct page *page) +{ + struct address_space *mapping = page->mapping; + struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); + unsigned int long flags; + + if (PageDirty(page)) { + spin_lock_irqsave(&mapping->tree_lock, flags); + radix_tree_tag_clear(&mapping->page_tree, + page_index(page), + PAGECACHE_TAG_DIRTY); + spin_unlock_irqrestore(&mapping->tree_lock, flags); + + clear_page_dirty_for_io(page); + dec_page_count(sbi, F2FS_DIRTY_NODES); + } + ClearPageUptodate(page); +} + +static struct page *get_current_nat_page(struct f2fs_sb_info *sbi, nid_t nid) +{ + pgoff_t index = current_nat_addr(sbi, nid); + return get_meta_page(sbi, index); +} + +static struct page *get_next_nat_page(struct f2fs_sb_info *sbi, nid_t nid) +{ + struct page *src_page; + struct page *dst_page; + pgoff_t src_off; + pgoff_t dst_off; + void *src_addr; + void *dst_addr; + struct f2fs_nm_info *nm_i = NM_I(sbi); + + src_off = current_nat_addr(sbi, nid); + dst_off = next_nat_addr(sbi, src_off); + + /* get current nat block page with lock */ + src_page = get_meta_page(sbi, src_off); + dst_page = grab_meta_page(sbi, dst_off); + f2fs_bug_on(PageDirty(src_page)); + + src_addr = page_address(src_page); + dst_addr = page_address(dst_page); + memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE); + set_page_dirty(dst_page); + f2fs_put_page(src_page, 1); + + set_to_next_nat(nm_i, nid); + + return dst_page; +} + +static struct nat_entry *__lookup_nat_cache(struct f2fs_nm_info *nm_i, nid_t n) +{ + return radix_tree_lookup(&nm_i->nat_root, n); +} + +static unsigned int __gang_lookup_nat_cache(struct f2fs_nm_info *nm_i, + nid_t start, unsigned int nr, struct nat_entry **ep) +{ + return radix_tree_gang_lookup(&nm_i->nat_root, (void **)ep, start, nr); +} + +static void __del_from_nat_cache(struct f2fs_nm_info *nm_i, struct nat_entry *e) +{ + list_del(&e->list); + radix_tree_delete(&nm_i->nat_root, nat_get_nid(e)); + nm_i->nat_cnt--; + kmem_cache_free(nat_entry_slab, e); +} + +int is_checkpointed_node(struct f2fs_sb_info *sbi, nid_t nid) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct nat_entry *e; + int is_cp = 1; + + read_lock(&nm_i->nat_tree_lock); + e = __lookup_nat_cache(nm_i, nid); + if (e && !e->checkpointed) + is_cp = 0; + read_unlock(&nm_i->nat_tree_lock); + return is_cp; +} + +bool fsync_mark_done(struct f2fs_sb_info *sbi, nid_t nid) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct nat_entry *e; + bool fsync_done = false; + + read_lock(&nm_i->nat_tree_lock); + e = __lookup_nat_cache(nm_i, nid); + if (e) + fsync_done = e->fsync_done; + read_unlock(&nm_i->nat_tree_lock); + return fsync_done; +} + +void fsync_mark_clear(struct f2fs_sb_info *sbi, nid_t nid) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct nat_entry *e; + + write_lock(&nm_i->nat_tree_lock); + e = __lookup_nat_cache(nm_i, nid); + if (e) + e->fsync_done = false; + write_unlock(&nm_i->nat_tree_lock); +} + +static struct nat_entry *grab_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid) +{ + struct nat_entry *new; + + new = kmem_cache_alloc(nat_entry_slab, GFP_ATOMIC); + if (!new) + return NULL; + if (radix_tree_insert(&nm_i->nat_root, nid, new)) { + kmem_cache_free(nat_entry_slab, new); + return NULL; + } + memset(new, 0, sizeof(struct nat_entry)); + nat_set_nid(new, nid); + new->checkpointed = true; + list_add_tail(&new->list, &nm_i->nat_entries); + nm_i->nat_cnt++; + return new; +} + +static void cache_nat_entry(struct f2fs_nm_info *nm_i, nid_t nid, + struct f2fs_nat_entry *ne) +{ + struct nat_entry *e; +retry: + write_lock(&nm_i->nat_tree_lock); + e = __lookup_nat_cache(nm_i, nid); + if (!e) { + e = grab_nat_entry(nm_i, nid); + if (!e) { + write_unlock(&nm_i->nat_tree_lock); + goto retry; + } + node_info_from_raw_nat(&e->ni, ne); + } + write_unlock(&nm_i->nat_tree_lock); +} + +static int set_node_addr(struct f2fs_sb_info *sbi, struct node_info *ni, + block_t new_blkaddr, bool fsync_done) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct nat_entry *e; +retry: + write_lock(&nm_i->nat_tree_lock); + e = __lookup_nat_cache(nm_i, ni->nid); + if (!e) { + e = grab_nat_entry(nm_i, ni->nid); + if (!e) { + write_unlock(&nm_i->nat_tree_lock); + goto retry; + } + e->ni = *ni; + f2fs_bug_on(ni->blk_addr == NEW_ADDR); + } else if (new_blkaddr == NEW_ADDR) { + /* + * when nid is reallocated, + * previous nat entry can be remained in nat cache. + * So, reinitialize it with new information. + */ + e->ni = *ni; + if (ni->blk_addr != NULL_ADDR) { + f2fs_msg(sbi->sb, KERN_ERR, "node block address is " + "already set: %u", ni->blk_addr); + f2fs_handle_error(sbi); + /* just give up on this node */ + write_unlock(&nm_i->nat_tree_lock); + return -EIO; + } + } + + /* sanity check */ + f2fs_bug_on(nat_get_blkaddr(e) != ni->blk_addr); + f2fs_bug_on(nat_get_blkaddr(e) == NULL_ADDR && + new_blkaddr == NULL_ADDR); + f2fs_bug_on(nat_get_blkaddr(e) == NEW_ADDR && + new_blkaddr == NEW_ADDR); + f2fs_bug_on(nat_get_blkaddr(e) != NEW_ADDR && + nat_get_blkaddr(e) != NULL_ADDR && + new_blkaddr == NEW_ADDR); + + /* increament version no as node is removed */ + if (nat_get_blkaddr(e) != NEW_ADDR && new_blkaddr == NULL_ADDR) { + unsigned char version = nat_get_version(e); + nat_set_version(e, inc_node_version(version)); + } + + /* change address */ + nat_set_blkaddr(e, new_blkaddr); + __set_nat_cache_dirty(nm_i, e); + + /* update fsync_mark if its inode nat entry is still alive */ + e = __lookup_nat_cache(nm_i, ni->ino); + if (e) + e->fsync_done = fsync_done; + write_unlock(&nm_i->nat_tree_lock); + return 0; +} + +int try_to_free_nats(struct f2fs_sb_info *sbi, int nr_shrink) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + + if (available_free_memory(sbi, NAT_ENTRIES)) + return 0; + + write_lock(&nm_i->nat_tree_lock); + while (nr_shrink && !list_empty(&nm_i->nat_entries)) { + struct nat_entry *ne; + ne = list_first_entry(&nm_i->nat_entries, + struct nat_entry, list); + __del_from_nat_cache(nm_i, ne); + nr_shrink--; + } + write_unlock(&nm_i->nat_tree_lock); + return nr_shrink; +} + +/* + * This function returns always success + */ +void get_node_info(struct f2fs_sb_info *sbi, nid_t nid, struct node_info *ni) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); + struct f2fs_summary_block *sum = curseg->sum_blk; + nid_t start_nid = START_NID(nid); + struct f2fs_nat_block *nat_blk; + struct page *page = NULL; + struct f2fs_nat_entry ne; + struct nat_entry *e; + int i; + + memset(&ne, 0, sizeof(struct f2fs_nat_entry)); + ni->nid = nid; + + /* Check nat cache */ + read_lock(&nm_i->nat_tree_lock); + e = __lookup_nat_cache(nm_i, nid); + if (e) { + ni->ino = nat_get_ino(e); + ni->blk_addr = nat_get_blkaddr(e); + ni->version = nat_get_version(e); + } + read_unlock(&nm_i->nat_tree_lock); + if (e) + return; + + /* Check current segment summary */ + mutex_lock(&curseg->curseg_mutex); + i = lookup_journal_in_cursum(sum, NAT_JOURNAL, nid, 0); + if (i >= 0) { + ne = nat_in_journal(sum, i); + node_info_from_raw_nat(ni, &ne); + } + mutex_unlock(&curseg->curseg_mutex); + if (i >= 0) + goto cache; + + /* Fill node_info from nat page */ + page = get_current_nat_page(sbi, start_nid); + nat_blk = (struct f2fs_nat_block *)page_address(page); + ne = nat_blk->entries[nid - start_nid]; + node_info_from_raw_nat(ni, &ne); + f2fs_put_page(page, 1); +cache: + /* cache nat entry */ + cache_nat_entry(NM_I(sbi), nid, &ne); +} + +/* + * The maximum depth is four. + * Offset[0] will have raw inode offset. + */ +static int get_node_path(struct f2fs_inode_info *fi, long block, + int offset[4], unsigned int noffset[4]) +{ + const long direct_index = ADDRS_PER_INODE(fi); + const long direct_blks = ADDRS_PER_BLOCK; + const long dptrs_per_blk = NIDS_PER_BLOCK; + const long indirect_blks = ADDRS_PER_BLOCK * NIDS_PER_BLOCK; + const long dindirect_blks = indirect_blks * NIDS_PER_BLOCK; + int n = 0; + int level = 0; + + noffset[0] = 0; + + if (block < direct_index) { + offset[n] = block; + goto got; + } + block -= direct_index; + if (block < direct_blks) { + offset[n++] = NODE_DIR1_BLOCK; + noffset[n] = 1; + offset[n] = block; + level = 1; + goto got; + } + block -= direct_blks; + if (block < direct_blks) { + offset[n++] = NODE_DIR2_BLOCK; + noffset[n] = 2; + offset[n] = block; + level = 1; + goto got; + } + block -= direct_blks; + if (block < indirect_blks) { + offset[n++] = NODE_IND1_BLOCK; + noffset[n] = 3; + offset[n++] = block / direct_blks; + noffset[n] = 4 + offset[n - 1]; + offset[n] = block % direct_blks; + level = 2; + goto got; + } + block -= indirect_blks; + if (block < indirect_blks) { + offset[n++] = NODE_IND2_BLOCK; + noffset[n] = 4 + dptrs_per_blk; + offset[n++] = block / direct_blks; + noffset[n] = 5 + dptrs_per_blk + offset[n - 1]; + offset[n] = block % direct_blks; + level = 2; + goto got; + } + block -= indirect_blks; + if (block < dindirect_blks) { + offset[n++] = NODE_DIND_BLOCK; + noffset[n] = 5 + (dptrs_per_blk * 2); + offset[n++] = block / indirect_blks; + noffset[n] = 6 + (dptrs_per_blk * 2) + + offset[n - 1] * (dptrs_per_blk + 1); + offset[n++] = (block / direct_blks) % dptrs_per_blk; + noffset[n] = 7 + (dptrs_per_blk * 2) + + offset[n - 2] * (dptrs_per_blk + 1) + + offset[n - 1]; + offset[n] = block % direct_blks; + level = 3; + goto got; + } else { + BUG(); + } +got: + return level; +} + +/* + * Caller should call f2fs_put_dnode(dn). + * Also, it should grab and release a rwsem by calling f2fs_lock_op() and + * f2fs_unlock_op() only if ro is not set RDONLY_NODE. + * In the case of RDONLY_NODE, we don't need to care about mutex. + */ +int get_dnode_of_data(struct dnode_of_data *dn, pgoff_t index, int mode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct page *npage[4]; + struct page *parent; + int offset[4]; + unsigned int noffset[4]; + nid_t nids[4]; + int level, i; + int err = 0; + + level = get_node_path(F2FS_I(dn->inode), index, offset, noffset); + + nids[0] = dn->inode->i_ino; + npage[0] = dn->inode_page; + + if (!npage[0]) { + npage[0] = get_node_page(sbi, nids[0]); + if (IS_ERR(npage[0])) + return PTR_ERR(npage[0]); + } + parent = npage[0]; + if (level != 0) + nids[1] = get_nid(parent, offset[0], true); + dn->inode_page = npage[0]; + dn->inode_page_locked = true; + + /* get indirect or direct nodes */ + for (i = 1; i <= level; i++) { + bool done = false; + + if (!nids[i] && mode == ALLOC_NODE) { + /* alloc new node */ + if (!alloc_nid(sbi, &(nids[i]))) { + err = -ENOSPC; + goto release_pages; + } + + dn->nid = nids[i]; + npage[i] = new_node_page(dn, noffset[i], NULL); + if (IS_ERR(npage[i])) { + alloc_nid_failed(sbi, nids[i]); + err = PTR_ERR(npage[i]); + goto release_pages; + } + + set_nid(parent, offset[i - 1], nids[i], i == 1); + alloc_nid_done(sbi, nids[i]); + done = true; + } else if (mode == LOOKUP_NODE_RA && i == level && level > 1) { + npage[i] = get_node_page_ra(parent, offset[i - 1]); + if (IS_ERR(npage[i])) { + err = PTR_ERR(npage[i]); + goto release_pages; + } + done = true; + } + if (i == 1) { + dn->inode_page_locked = false; + unlock_page(parent); + } else { + f2fs_put_page(parent, 1); + } + + if (!done) { + npage[i] = get_node_page(sbi, nids[i]); + if (IS_ERR(npage[i])) { + err = PTR_ERR(npage[i]); + f2fs_put_page(npage[0], 0); + goto release_out; + } + } + if (i < level) { + parent = npage[i]; + nids[i + 1] = get_nid(parent, offset[i], false); + } + } + dn->nid = nids[level]; + dn->ofs_in_node = offset[level]; + dn->node_page = npage[level]; + dn->data_blkaddr = datablock_addr(dn->node_page, dn->ofs_in_node); + return 0; + +release_pages: + f2fs_put_page(parent, 1); + if (i > 1) + f2fs_put_page(npage[0], 0); +release_out: + dn->inode_page = NULL; + dn->node_page = NULL; + return err; +} + +static void truncate_node(struct dnode_of_data *dn) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct node_info ni; + + get_node_info(sbi, dn->nid, &ni); + if (dn->inode->i_blocks == 0) { + if (ni.blk_addr != NULL_ADDR) { + f2fs_msg(sbi->sb, KERN_ERR, + "empty node still has block address %u ", + ni.blk_addr); + f2fs_handle_error(sbi); + } + goto invalidate; + } + f2fs_bug_on(ni.blk_addr == NULL_ADDR); + + /* Deallocate node address */ + invalidate_blocks(sbi, ni.blk_addr); + dec_valid_node_count(sbi, dn->inode); + set_node_addr(sbi, &ni, NULL_ADDR, false); + + if (dn->nid == dn->inode->i_ino) { + remove_orphan_inode(sbi, dn->nid); + dec_valid_inode_count(sbi); + } else { + sync_inode_page(dn); + } +invalidate: + clear_node_page_dirty(dn->node_page); + F2FS_SET_SB_DIRT(sbi); + + f2fs_put_page(dn->node_page, 1); + + invalidate_mapping_pages(NODE_MAPPING(sbi), + dn->node_page->index, dn->node_page->index); + + dn->node_page = NULL; + trace_f2fs_truncate_node(dn->inode, dn->nid, ni.blk_addr); +} + +static int truncate_dnode(struct dnode_of_data *dn) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct page *page; + + if (dn->nid == 0) + return 1; + + /* get direct node */ + page = get_node_page(sbi, dn->nid); + if (IS_ERR(page) && PTR_ERR(page) == -ENOENT) + return 1; + else if (IS_ERR(page)) + return PTR_ERR(page); + + /* Make dnode_of_data for parameter */ + dn->node_page = page; + dn->ofs_in_node = 0; + truncate_data_blocks(dn); + truncate_node(dn); + return 1; +} + +static int truncate_nodes(struct dnode_of_data *dn, unsigned int nofs, + int ofs, int depth) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct dnode_of_data rdn = *dn; + struct page *page; + struct f2fs_node *rn; + nid_t child_nid; + unsigned int child_nofs; + int freed = 0; + int i, ret; + + if (dn->nid == 0) + return NIDS_PER_BLOCK + 1; + + trace_f2fs_truncate_nodes_enter(dn->inode, dn->nid, dn->data_blkaddr); + + page = get_node_page(sbi, dn->nid); + if (IS_ERR(page)) { + trace_f2fs_truncate_nodes_exit(dn->inode, PTR_ERR(page)); + return PTR_ERR(page); + } + + rn = F2FS_NODE(page); + if (depth < 3) { + for (i = ofs; i < NIDS_PER_BLOCK; i++, freed++) { + child_nid = le32_to_cpu(rn->in.nid[i]); + if (child_nid == 0) + continue; + rdn.nid = child_nid; + ret = truncate_dnode(&rdn); + if (ret < 0) + goto out_err; + set_nid(page, i, 0, false); + } + } else { + child_nofs = nofs + ofs * (NIDS_PER_BLOCK + 1) + 1; + for (i = ofs; i < NIDS_PER_BLOCK; i++) { + child_nid = le32_to_cpu(rn->in.nid[i]); + if (child_nid == 0) { + child_nofs += NIDS_PER_BLOCK + 1; + continue; + } + rdn.nid = child_nid; + ret = truncate_nodes(&rdn, child_nofs, 0, depth - 1); + if (ret == (NIDS_PER_BLOCK + 1)) { + set_nid(page, i, 0, false); + child_nofs += ret; + } else if (ret < 0 && ret != -ENOENT) { + goto out_err; + } + } + freed = child_nofs; + } + + if (!ofs) { + /* remove current indirect node */ + dn->node_page = page; + truncate_node(dn); + freed++; + } else { + f2fs_put_page(page, 1); + } + trace_f2fs_truncate_nodes_exit(dn->inode, freed); + return freed; + +out_err: + f2fs_put_page(page, 1); + trace_f2fs_truncate_nodes_exit(dn->inode, ret); + return ret; +} + +static int truncate_partial_nodes(struct dnode_of_data *dn, + struct f2fs_inode *ri, int *offset, int depth) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct page *pages[2]; + nid_t nid[3]; + nid_t child_nid; + int err = 0; + int i; + int idx = depth - 2; + + nid[0] = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); + if (!nid[0]) + return 0; + + /* get indirect nodes in the path */ + for (i = 0; i < idx + 1; i++) { + /* refernece count'll be increased */ + pages[i] = get_node_page(sbi, nid[i]); + if (IS_ERR(pages[i])) { + err = PTR_ERR(pages[i]); + idx = i - 1; + goto fail; + } + nid[i + 1] = get_nid(pages[i], offset[i + 1], false); + } + + /* free direct nodes linked to a partial indirect node */ + for (i = offset[idx + 1]; i < NIDS_PER_BLOCK; i++) { + child_nid = get_nid(pages[idx], i, false); + if (!child_nid) + continue; + dn->nid = child_nid; + err = truncate_dnode(dn); + if (err < 0) + goto fail; + set_nid(pages[idx], i, 0, false); + } + + if (offset[idx + 1] == 0) { + dn->node_page = pages[idx]; + dn->nid = nid[idx]; + truncate_node(dn); + } else { + f2fs_put_page(pages[idx], 1); + } + offset[idx]++; + offset[idx + 1] = 0; + idx--; +fail: + for (i = idx; i >= 0; i--) + f2fs_put_page(pages[i], 1); + + trace_f2fs_truncate_partial_nodes(dn->inode, nid, depth, err); + + return err; +} + +/* + * All the block addresses of data and nodes should be nullified. + */ +int truncate_inode_blocks(struct inode *inode, pgoff_t from) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + int err = 0, cont = 1; + int level, offset[4], noffset[4]; + unsigned int nofs = 0; + struct f2fs_inode *ri; + struct dnode_of_data dn; + struct page *page; + + noffset[1] = 0; + + trace_f2fs_truncate_inode_blocks_enter(inode, from); + + level = get_node_path(F2FS_I(inode), from, offset, noffset); +restart: + page = get_node_page(sbi, inode->i_ino); + if (IS_ERR(page)) { + trace_f2fs_truncate_inode_blocks_exit(inode, PTR_ERR(page)); + return PTR_ERR(page); + } + + set_new_dnode(&dn, inode, page, NULL, 0); + unlock_page(page); + + ri = F2FS_INODE(page); + switch (level) { + case 0: + case 1: + nofs = noffset[1]; + break; + case 2: + nofs = noffset[1]; + if (!offset[level - 1]) + goto skip_partial; + err = truncate_partial_nodes(&dn, ri, offset, level); + if (err < 0 && err != -ENOENT) + goto fail; + nofs += 1 + NIDS_PER_BLOCK; + break; + case 3: + nofs = 5 + 2 * NIDS_PER_BLOCK; + if (!offset[level - 1]) + goto skip_partial; + err = truncate_partial_nodes(&dn, ri, offset, level); + if (err < 0 && err != -ENOENT) + goto fail; + break; + default: + BUG(); + } + +skip_partial: + while (cont) { + dn.nid = le32_to_cpu(ri->i_nid[offset[0] - NODE_DIR1_BLOCK]); + switch (offset[0]) { + case NODE_DIR1_BLOCK: + case NODE_DIR2_BLOCK: + err = truncate_dnode(&dn); + break; + + case NODE_IND1_BLOCK: + case NODE_IND2_BLOCK: + err = truncate_nodes(&dn, nofs, offset[1], 2); + break; + + case NODE_DIND_BLOCK: + err = truncate_nodes(&dn, nofs, offset[1], 3); + cont = 0; + break; + + default: + BUG(); + } + if (err < 0 && err != -ENOENT) + goto fail; + if (offset[1] == 0 && + ri->i_nid[offset[0] - NODE_DIR1_BLOCK]) { + lock_page(page); + if (unlikely(page->mapping != NODE_MAPPING(sbi))) { + f2fs_put_page(page, 1); + goto restart; + } + f2fs_wait_on_page_writeback(page, NODE); + ri->i_nid[offset[0] - NODE_DIR1_BLOCK] = 0; + set_page_dirty(page); + unlock_page(page); + } + offset[1] = 0; + offset[0]++; + nofs += err; + } +fail: + f2fs_put_page(page, 0); + trace_f2fs_truncate_inode_blocks_exit(inode, err); + return err > 0 ? 0 : err; +} + +int truncate_xattr_node(struct inode *inode, struct page *page) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + nid_t nid = F2FS_I(inode)->i_xattr_nid; + struct dnode_of_data dn; + struct page *npage; + + if (!nid) + return 0; + + npage = get_node_page(sbi, nid); + if (IS_ERR(npage)) + return PTR_ERR(npage); + + F2FS_I(inode)->i_xattr_nid = 0; + + /* need to do checkpoint during fsync */ + F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi)); + + set_new_dnode(&dn, inode, page, npage, nid); + + if (page) + dn.inode_page_locked = true; + truncate_node(&dn); + return 0; +} + +/* + * Caller should grab and release a rwsem by calling f2fs_lock_op() and + * f2fs_unlock_op(). + */ +void remove_inode_page(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct page *page; + nid_t ino = inode->i_ino; + struct dnode_of_data dn; + + page = get_node_page(sbi, ino); + if (IS_ERR(page)) + return; + + if (truncate_xattr_node(inode, page)) { + f2fs_put_page(page, 1); + return; + } + /* 0 is possible, after f2fs_new_inode() is failed */ + if (inode->i_blocks != 0 && inode->i_blocks != 1) { + f2fs_msg(sbi->sb, KERN_ERR, "inode %u still has %llu blocks", + ino, inode->i_blocks); + f2fs_handle_error(sbi); + } + set_new_dnode(&dn, inode, page, page, ino); + truncate_node(&dn); +} + +struct page *new_inode_page(struct inode *inode) +{ + struct dnode_of_data dn; + + /* allocate inode page for new inode */ + set_new_dnode(&dn, inode, NULL, NULL, inode->i_ino); + + /* caller should f2fs_put_page(page, 1); */ + return new_node_page(&dn, 0, NULL); +} + +struct page *new_node_page(struct dnode_of_data *dn, + unsigned int ofs, struct page *ipage) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct node_info old_ni, new_ni; + struct page *page; + int err; + + if (unlikely(is_inode_flag_set(F2FS_I(dn->inode), FI_NO_ALLOC))) + return ERR_PTR(-EPERM); + + page = grab_cache_page(NODE_MAPPING(sbi), dn->nid); + if (!page) + return ERR_PTR(-ENOMEM); + + if (unlikely(!inc_valid_node_count(sbi, dn->inode))) { + err = -ENOSPC; + goto fail; + } + + get_node_info(sbi, dn->nid, &old_ni); + + /* Reinitialize old_ni with new node page */ + f2fs_bug_on(old_ni.blk_addr != NULL_ADDR); + new_ni = old_ni; + new_ni.ino = dn->inode->i_ino; + set_node_addr(sbi, &new_ni, NEW_ADDR, false); + + f2fs_wait_on_page_writeback(page, NODE); + fill_node_footer(page, dn->nid, dn->inode->i_ino, ofs, true); + set_cold_node(dn->inode, page); + SetPageUptodate(page); + set_page_dirty(page); + + if (f2fs_has_xattr_block(ofs)) + F2FS_I(dn->inode)->i_xattr_nid = dn->nid; + + dn->node_page = page; + if (ipage) + update_inode(dn->inode, ipage); + else + sync_inode_page(dn); + if (ofs == 0) + inc_valid_inode_count(sbi); + + return page; + +fail: + clear_node_page_dirty(page); + f2fs_put_page(page, 1); + return ERR_PTR(err); +} + +/* + * Caller should do after getting the following values. + * 0: f2fs_put_page(page, 0) + * LOCKED_PAGE: f2fs_put_page(page, 1) + * error: nothing + */ +static int read_node_page(struct page *page, int rw) +{ + struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); + struct node_info ni; + + get_node_info(sbi, page->index, &ni); + + if (unlikely(ni.blk_addr == NULL_ADDR)) { + f2fs_put_page(page, 1); + return -ENOENT; + } + + if (PageUptodate(page)) + return LOCKED_PAGE; + + return f2fs_submit_page_bio(sbi, page, ni.blk_addr, rw); +} + +/* + * Readahead a node page + */ +void ra_node_page(struct f2fs_sb_info *sbi, nid_t nid) +{ + struct page *apage; + int err; + + apage = find_get_page(NODE_MAPPING(sbi), nid); + if (apage && PageUptodate(apage)) { + f2fs_put_page(apage, 0); + return; + } + f2fs_put_page(apage, 0); + + apage = grab_cache_page(NODE_MAPPING(sbi), nid); + if (!apage) + return; + + err = read_node_page(apage, READA); + if (err == 0) + f2fs_put_page(apage, 0); + else if (err == LOCKED_PAGE) + f2fs_put_page(apage, 1); +} + +struct page *get_node_page(struct f2fs_sb_info *sbi, pgoff_t nid) +{ + struct page *page; + int err; +repeat: + page = grab_cache_page(NODE_MAPPING(sbi), nid); + if (!page) + return ERR_PTR(-ENOMEM); + + err = read_node_page(page, READ_SYNC); + if (err < 0) + return ERR_PTR(err); + else if (err == LOCKED_PAGE) + goto got_it; + + lock_page(page); + if (unlikely(!PageUptodate(page) || nid != nid_of_node(page))) { + f2fs_put_page(page, 1); + return ERR_PTR(-EIO); + } + if (unlikely(page->mapping != NODE_MAPPING(sbi))) { + f2fs_put_page(page, 1); + goto repeat; + } +got_it: + mark_page_accessed(page); + return page; +} + +/* + * Return a locked page for the desired node page. + * And, readahead MAX_RA_NODE number of node pages. + */ +struct page *get_node_page_ra(struct page *parent, int start) +{ + struct f2fs_sb_info *sbi = F2FS_SB(parent->mapping->host->i_sb); + struct blk_plug plug; + struct page *page; + int err, i, end; + nid_t nid; + + /* First, try getting the desired direct node. */ + nid = get_nid(parent, start, false); + if (!nid) + return ERR_PTR(-ENOENT); +repeat: + page = grab_cache_page(NODE_MAPPING(sbi), nid); + if (!page) + return ERR_PTR(-ENOMEM); + + err = read_node_page(page, READ_SYNC); + if (err < 0) + return ERR_PTR(err); + else if (err == LOCKED_PAGE) + goto page_hit; + + blk_start_plug(&plug); + + /* Then, try readahead for siblings of the desired node */ + end = start + MAX_RA_NODE; + end = min(end, NIDS_PER_BLOCK); + for (i = start + 1; i < end; i++) { + nid = get_nid(parent, i, false); + if (!nid) + continue; + ra_node_page(sbi, nid); + } + + blk_finish_plug(&plug); + + lock_page(page); + if (unlikely(page->mapping != NODE_MAPPING(sbi))) { + f2fs_put_page(page, 1); + goto repeat; + } +page_hit: + if (unlikely(!PageUptodate(page))) { + f2fs_put_page(page, 1); + return ERR_PTR(-EIO); + } + mark_page_accessed(page); + return page; +} + +void sync_inode_page(struct dnode_of_data *dn) +{ + if (IS_INODE(dn->node_page) || dn->inode_page == dn->node_page) { + update_inode(dn->inode, dn->node_page); + } else if (dn->inode_page) { + if (!dn->inode_page_locked) + lock_page(dn->inode_page); + update_inode(dn->inode, dn->inode_page); + if (!dn->inode_page_locked) + unlock_page(dn->inode_page); + } else { + update_inode_page(dn->inode); + } +} + +int sync_node_pages(struct f2fs_sb_info *sbi, nid_t ino, + struct writeback_control *wbc) +{ + pgoff_t index, end; + struct pagevec pvec; + int step = ino ? 2 : 0; + int nwritten = 0, wrote = 0; + + pagevec_init(&pvec, 0); + +next_step: + index = 0; + end = LONG_MAX; + + while (index <= end) { + int i, nr_pages; + nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, + PAGECACHE_TAG_DIRTY, + min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); + if (nr_pages == 0) + break; + + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + + /* + * flushing sequence with step: + * 0. indirect nodes + * 1. dentry dnodes + * 2. file dnodes + */ + if (step == 0 && IS_DNODE(page)) + continue; + if (step == 1 && (!IS_DNODE(page) || + is_cold_node(page))) + continue; + if (step == 2 && (!IS_DNODE(page) || + !is_cold_node(page))) + continue; + + /* + * If an fsync mode, + * we should not skip writing node pages. + */ + if (ino && ino_of_node(page) == ino) + lock_page(page); + else if (!trylock_page(page)) + continue; + + if (unlikely(page->mapping != NODE_MAPPING(sbi))) { +continue_unlock: + unlock_page(page); + continue; + } + if (ino && ino_of_node(page) != ino) + goto continue_unlock; + + if (!PageDirty(page)) { + /* someone wrote it for us */ + goto continue_unlock; + } + + if (!clear_page_dirty_for_io(page)) + goto continue_unlock; + + /* called by fsync() */ + if (ino && IS_DNODE(page)) { + int mark = !is_checkpointed_node(sbi, ino); + set_fsync_mark(page, 1); + if (IS_INODE(page)) + set_dentry_mark(page, mark); + nwritten++; + } else { + set_fsync_mark(page, 0); + set_dentry_mark(page, 0); + } + NODE_MAPPING(sbi)->a_ops->writepage(page, wbc); + wrote++; + + if (--wbc->nr_to_write == 0) + break; + } + pagevec_release(&pvec); + cond_resched(); + + if (wbc->nr_to_write == 0) { + step = 2; + break; + } + } + + if (step < 2) { + step++; + goto next_step; + } + + if (wrote) + f2fs_submit_merged_bio(sbi, NODE, WRITE); + return nwritten; +} + +int wait_on_node_pages_writeback(struct f2fs_sb_info *sbi, nid_t ino) +{ + pgoff_t index = 0, end = LONG_MAX; + struct pagevec pvec; + int ret2 = 0, ret = 0; + + pagevec_init(&pvec, 0); + + while (index <= end) { + int i, nr_pages; + nr_pages = pagevec_lookup_tag(&pvec, NODE_MAPPING(sbi), &index, + PAGECACHE_TAG_WRITEBACK, + min(end - index, (pgoff_t)PAGEVEC_SIZE-1) + 1); + if (nr_pages == 0) + break; + + for (i = 0; i < nr_pages; i++) { + struct page *page = pvec.pages[i]; + + /* until radix tree lookup accepts end_index */ + if (unlikely(page->index > end)) + continue; + + if (ino && ino_of_node(page) == ino) { + f2fs_wait_on_page_writeback(page, NODE); + if (TestClearPageError(page)) + ret = -EIO; + } + } + pagevec_release(&pvec); + cond_resched(); + } + + if (unlikely(test_and_clear_bit(AS_ENOSPC, &NODE_MAPPING(sbi)->flags))) + ret2 = -ENOSPC; + if (unlikely(test_and_clear_bit(AS_EIO, &NODE_MAPPING(sbi)->flags))) + ret2 = -EIO; + if (!ret) + ret = ret2; + return ret; +} + +static int f2fs_write_node_page(struct page *page, + struct writeback_control *wbc) +{ + struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); + nid_t nid; + block_t new_addr; + struct node_info ni; + struct f2fs_io_info fio = { + .type = NODE, + .rw = (wbc->sync_mode == WB_SYNC_ALL) ? WRITE_SYNC : WRITE, + }; + + trace_f2fs_writepage(page, NODE); + + if (unlikely(sbi->por_doing)) + goto redirty_out; + + f2fs_wait_on_page_writeback(page, NODE); + + /* get old block addr of this node page */ + nid = nid_of_node(page); + f2fs_bug_on(page->index != nid); + + get_node_info(sbi, nid, &ni); + + /* This page is already truncated */ + if (unlikely(ni.blk_addr == NULL_ADDR)) { + dec_page_count(sbi, F2FS_DIRTY_NODES); + unlock_page(page); + return 0; + } + + if (wbc->for_reclaim) + goto redirty_out; + + mutex_lock(&sbi->node_write); + set_page_writeback(page); + write_node_page(sbi, page, &fio, nid, ni.blk_addr, &new_addr); + set_node_addr(sbi, &ni, new_addr, is_fsync_dnode(page)); + dec_page_count(sbi, F2FS_DIRTY_NODES); + mutex_unlock(&sbi->node_write); + unlock_page(page); + return 0; + +redirty_out: + redirty_page_for_writepage(wbc, page); + return AOP_WRITEPAGE_ACTIVATE; +} + +static int f2fs_write_node_pages(struct address_space *mapping, + struct writeback_control *wbc) +{ + struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); + long diff; + + trace_f2fs_writepages(mapping->host, wbc, NODE); + + /* balancing f2fs's metadata in background */ + f2fs_balance_fs_bg(sbi); + + /* collect a number of dirty node pages and write together */ + if (get_pages(sbi, F2FS_DIRTY_NODES) < nr_pages_to_skip(sbi, NODE)) + goto skip_write; + + diff = nr_pages_to_write(sbi, NODE, wbc); + wbc->sync_mode = WB_SYNC_NONE; + sync_node_pages(sbi, 0, wbc); + wbc->nr_to_write = max((long)0, wbc->nr_to_write - diff); + return 0; + +skip_write: + wbc->pages_skipped += get_pages(sbi, F2FS_DIRTY_NODES); + return 0; +} + +static int f2fs_set_node_page_dirty(struct page *page) +{ + struct address_space *mapping = page->mapping; + struct f2fs_sb_info *sbi = F2FS_SB(mapping->host->i_sb); + + trace_f2fs_set_page_dirty(page, NODE); + + SetPageUptodate(page); + if (!PageDirty(page)) { + __set_page_dirty_nobuffers(page); + inc_page_count(sbi, F2FS_DIRTY_NODES); + SetPagePrivate(page); + return 1; + } + return 0; +} + +static void f2fs_invalidate_node_page(struct page *page, unsigned long offset) +{ + struct inode *inode = page->mapping->host; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + if (PageDirty(page)) + dec_page_count(sbi, F2FS_DIRTY_NODES); + ClearPagePrivate(page); +} + +static int f2fs_release_node_page(struct page *page, gfp_t wait) +{ + ClearPagePrivate(page); + return 1; +} + +/* + * Structure of the f2fs node operations + */ +const struct address_space_operations f2fs_node_aops = { + .writepage = f2fs_write_node_page, + .writepages = f2fs_write_node_pages, + .set_page_dirty = f2fs_set_node_page_dirty, + .invalidatepage = f2fs_invalidate_node_page, + .releasepage = f2fs_release_node_page, +}; + +static struct free_nid *__lookup_free_nid_list(struct f2fs_nm_info *nm_i, + nid_t n) +{ + return radix_tree_lookup(&nm_i->free_nid_root, n); +} + +static void __del_from_free_nid_list(struct f2fs_nm_info *nm_i, + struct free_nid *i) +{ + list_del(&i->list); + radix_tree_delete(&nm_i->free_nid_root, i->nid); +} + +static int add_free_nid(struct f2fs_sb_info *sbi, nid_t nid, bool build) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct free_nid *i; + struct nat_entry *ne; + bool allocated = false; + + if (!available_free_memory(sbi, FREE_NIDS)) + return -1; + + /* 0 nid should not be used */ + if (unlikely(nid == 0)) + return 0; + + if (build) { + /* do not add allocated nids */ + read_lock(&nm_i->nat_tree_lock); + ne = __lookup_nat_cache(nm_i, nid); + if (ne && + (!ne->checkpointed || nat_get_blkaddr(ne) != NULL_ADDR)) + allocated = true; + read_unlock(&nm_i->nat_tree_lock); + if (allocated) + return 0; + } + + i = f2fs_kmem_cache_alloc(free_nid_slab, GFP_NOFS); + i->nid = nid; + i->state = NID_NEW; + + spin_lock(&nm_i->free_nid_list_lock); + if (radix_tree_insert(&nm_i->free_nid_root, i->nid, i)) { + spin_unlock(&nm_i->free_nid_list_lock); + kmem_cache_free(free_nid_slab, i); + return 0; + } + list_add_tail(&i->list, &nm_i->free_nid_list); + nm_i->fcnt++; + spin_unlock(&nm_i->free_nid_list_lock); + return 1; +} + +static void remove_free_nid(struct f2fs_nm_info *nm_i, nid_t nid) +{ + struct free_nid *i; + bool need_free = false; + + spin_lock(&nm_i->free_nid_list_lock); + i = __lookup_free_nid_list(nm_i, nid); + if (i && i->state == NID_NEW) { + __del_from_free_nid_list(nm_i, i); + nm_i->fcnt--; + need_free = true; + } + spin_unlock(&nm_i->free_nid_list_lock); + + if (need_free) + kmem_cache_free(free_nid_slab, i); +} + +static void scan_nat_page(struct f2fs_sb_info *sbi, + struct page *nat_page, nid_t start_nid) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct f2fs_nat_block *nat_blk = page_address(nat_page); + block_t blk_addr; + int i; + + i = start_nid % NAT_ENTRY_PER_BLOCK; + + for (; i < NAT_ENTRY_PER_BLOCK; i++, start_nid++) { + + if (unlikely(start_nid >= nm_i->max_nid)) + break; + + blk_addr = le32_to_cpu(nat_blk->entries[i].block_addr); + f2fs_bug_on(blk_addr == NEW_ADDR); + if (blk_addr == NULL_ADDR) { + if (add_free_nid(sbi, start_nid, true) < 0) + break; + } + } +} + +static void build_free_nids(struct f2fs_sb_info *sbi) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); + struct f2fs_summary_block *sum = curseg->sum_blk; + int i = 0; + nid_t nid = nm_i->next_scan_nid; + + /* Enough entries */ + if (nm_i->fcnt > NAT_ENTRY_PER_BLOCK) + return; + + /* readahead nat pages to be scanned */ + ra_meta_pages(sbi, NAT_BLOCK_OFFSET(nid), FREE_NID_PAGES, META_NAT); + + while (1) { + struct page *page = get_current_nat_page(sbi, nid); + + scan_nat_page(sbi, page, nid); + f2fs_put_page(page, 1); + + nid += (NAT_ENTRY_PER_BLOCK - (nid % NAT_ENTRY_PER_BLOCK)); + if (unlikely(nid >= nm_i->max_nid)) + nid = 0; + + if (i++ == FREE_NID_PAGES) + break; + } + + /* go to the next free nat pages to find free nids abundantly */ + nm_i->next_scan_nid = nid; + + /* find free nids from current sum_pages */ + mutex_lock(&curseg->curseg_mutex); + for (i = 0; i < nats_in_cursum(sum); i++) { + block_t addr = le32_to_cpu(nat_in_journal(sum, i).block_addr); + nid = le32_to_cpu(nid_in_journal(sum, i)); + if (addr == NULL_ADDR) + add_free_nid(sbi, nid, true); + else + remove_free_nid(nm_i, nid); + } + mutex_unlock(&curseg->curseg_mutex); +} + +/* + * If this function returns success, caller can obtain a new nid + * from second parameter of this function. + * The returned nid could be used ino as well as nid when inode is created. + */ +bool alloc_nid(struct f2fs_sb_info *sbi, nid_t *nid) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct free_nid *i = NULL; +retry: + if (unlikely(sbi->total_valid_node_count + 1 > nm_i->available_nids)) + return false; + + spin_lock(&nm_i->free_nid_list_lock); + + /* We should not use stale free nids created by build_free_nids */ + if (nm_i->fcnt && !on_build_free_nids(nm_i)) { + f2fs_bug_on(list_empty(&nm_i->free_nid_list)); + list_for_each_entry(i, &nm_i->free_nid_list, list) + if (i->state == NID_NEW) + break; + + f2fs_bug_on(i->state != NID_NEW); + *nid = i->nid; + i->state = NID_ALLOC; + nm_i->fcnt--; + spin_unlock(&nm_i->free_nid_list_lock); + return true; + } + spin_unlock(&nm_i->free_nid_list_lock); + + /* Let's scan nat pages and its caches to get free nids */ + mutex_lock(&nm_i->build_lock); + build_free_nids(sbi); + mutex_unlock(&nm_i->build_lock); + goto retry; +} + +/* + * alloc_nid() should be called prior to this function. + */ +void alloc_nid_done(struct f2fs_sb_info *sbi, nid_t nid) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct free_nid *i; + + spin_lock(&nm_i->free_nid_list_lock); + i = __lookup_free_nid_list(nm_i, nid); + f2fs_bug_on(!i || i->state != NID_ALLOC); + __del_from_free_nid_list(nm_i, i); + spin_unlock(&nm_i->free_nid_list_lock); + + kmem_cache_free(free_nid_slab, i); +} + +/* + * alloc_nid() should be called prior to this function. + */ +void alloc_nid_failed(struct f2fs_sb_info *sbi, nid_t nid) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct free_nid *i; + bool need_free = false; + + if (!nid) + return; + + spin_lock(&nm_i->free_nid_list_lock); + i = __lookup_free_nid_list(nm_i, nid); + f2fs_bug_on(!i || i->state != NID_ALLOC); + if (!available_free_memory(sbi, FREE_NIDS)) { + __del_from_free_nid_list(nm_i, i); + need_free = true; + } else { + i->state = NID_NEW; + nm_i->fcnt++; + } + spin_unlock(&nm_i->free_nid_list_lock); + + if (need_free) + kmem_cache_free(free_nid_slab, i); +} + +void recover_node_page(struct f2fs_sb_info *sbi, struct page *page, + struct f2fs_summary *sum, struct node_info *ni, + block_t new_blkaddr) +{ + rewrite_node_page(sbi, page, sum, ni->blk_addr, new_blkaddr); + set_node_addr(sbi, ni, new_blkaddr, false); + clear_node_page_dirty(page); +} + +static void recover_inline_xattr(struct inode *inode, struct page *page) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + void *src_addr, *dst_addr; + size_t inline_size; + struct page *ipage; + struct f2fs_inode *ri; + + if (!f2fs_has_inline_xattr(inode)) + return; + + if (!IS_INODE(page)) + return; + + ri = F2FS_INODE(page); + if (!(ri->i_inline & F2FS_INLINE_XATTR)) + return; + + ipage = get_node_page(sbi, inode->i_ino); + f2fs_bug_on(IS_ERR(ipage)); + + dst_addr = inline_xattr_addr(ipage); + src_addr = inline_xattr_addr(page); + inline_size = inline_xattr_size(inode); + + f2fs_wait_on_page_writeback(ipage, NODE); + memcpy(dst_addr, src_addr, inline_size); + + update_inode(inode, ipage); + f2fs_put_page(ipage, 1); +} + +bool recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid; + nid_t new_xnid = nid_of_node(page); + struct node_info ni; + + recover_inline_xattr(inode, page); + + if (!f2fs_has_xattr_block(ofs_of_node(page))) + return false; + + /* 1: invalidate the previous xattr nid */ + if (!prev_xnid) + goto recover_xnid; + + /* Deallocate node address */ + get_node_info(sbi, prev_xnid, &ni); + f2fs_bug_on(ni.blk_addr == NULL_ADDR); + invalidate_blocks(sbi, ni.blk_addr); + dec_valid_node_count(sbi, inode); + set_node_addr(sbi, &ni, NULL_ADDR, false); + +recover_xnid: + /* 2: allocate new xattr nid */ + if (unlikely(!inc_valid_node_count(sbi, inode))) + f2fs_bug_on(1); + + remove_free_nid(NM_I(sbi), new_xnid); + get_node_info(sbi, new_xnid, &ni); + ni.ino = inode->i_ino; + set_node_addr(sbi, &ni, NEW_ADDR, false); + F2FS_I(inode)->i_xattr_nid = new_xnid; + + /* 3: update xattr blkaddr */ + refresh_sit_entry(sbi, NEW_ADDR, blkaddr); + set_node_addr(sbi, &ni, blkaddr, false); + + update_inode_page(inode); + return true; +} + +int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page) +{ + struct f2fs_inode *src, *dst; + nid_t ino = ino_of_node(page); + struct node_info old_ni, new_ni; + struct page *ipage; + int err; + + get_node_info(sbi, ino, &old_ni); + + if (unlikely(old_ni.blk_addr != NULL_ADDR)) + return -EINVAL; + + ipage = grab_cache_page(NODE_MAPPING(sbi), ino); + if (!ipage) + return -ENOMEM; + + /* Should not use this inode from free nid list */ + remove_free_nid(NM_I(sbi), ino); + + SetPageUptodate(ipage); + fill_node_footer(ipage, ino, ino, 0, true); + + src = F2FS_INODE(page); + dst = F2FS_INODE(ipage); + + memcpy(dst, src, (unsigned long)&src->i_ext - (unsigned long)src); + dst->i_size = 0; + dst->i_blocks = cpu_to_le64(1); + dst->i_links = cpu_to_le32(1); + dst->i_xattr_nid = 0; + + new_ni = old_ni; + new_ni.ino = ino; + + err = set_node_addr(sbi, &new_ni, NEW_ADDR, false); + if (!err) + if (unlikely(!inc_valid_node_count(sbi, NULL))) + err = -ENOSPC; + if (!err) + inc_valid_inode_count(sbi); + f2fs_put_page(ipage, 1); + return err; +} + +/* + * ra_sum_pages() merge contiguous pages into one bio and submit. + * these pre-readed pages are alloced in bd_inode's mapping tree. + */ +static int ra_sum_pages(struct f2fs_sb_info *sbi, struct page **pages, + int start, int nrpages) +{ + struct inode *inode = sbi->sb->s_bdev->bd_inode; + struct address_space *mapping = inode->i_mapping; + int i, page_idx = start; + struct f2fs_io_info fio = { + .type = META, + .rw = READ_SYNC | REQ_META | REQ_PRIO + }; + + for (i = 0; page_idx < start + nrpages; page_idx++, i++) { + /* alloc page in bd_inode for reading node summary info */ + pages[i] = grab_cache_page(mapping, page_idx); + if (!pages[i]) + break; + f2fs_submit_page_mbio(sbi, pages[i], page_idx, &fio); + } + + f2fs_submit_merged_bio(sbi, META, READ); + return i; +} + +int restore_node_summary(struct f2fs_sb_info *sbi, + unsigned int segno, struct f2fs_summary_block *sum) +{ + struct f2fs_node *rn; + struct f2fs_summary *sum_entry; + struct inode *inode = sbi->sb->s_bdev->bd_inode; + block_t addr; + int bio_blocks = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); + struct page *pages[bio_blocks]; + int i, idx, last_offset, nrpages, err = 0; + + /* scan the node segment */ + last_offset = sbi->blocks_per_seg; + addr = START_BLOCK(sbi, segno); + sum_entry = &sum->entries[0]; + + for (i = 0; !err && i < last_offset; i += nrpages, addr += nrpages) { + nrpages = min(last_offset - i, bio_blocks); + + /* read ahead node pages */ + nrpages = ra_sum_pages(sbi, pages, addr, nrpages); + if (!nrpages) + return -ENOMEM; + + for (idx = 0; idx < nrpages; idx++) { + if (err) + goto skip; + + lock_page(pages[idx]); + if (unlikely(!PageUptodate(pages[idx]))) { + err = -EIO; + } else { + rn = F2FS_NODE(pages[idx]); + sum_entry->nid = rn->footer.nid; + sum_entry->version = 0; + sum_entry->ofs_in_node = 0; + sum_entry++; + } + unlock_page(pages[idx]); +skip: + page_cache_release(pages[idx]); + } + + invalidate_mapping_pages(inode->i_mapping, addr, + addr + nrpages); + } + return err; +} + +static struct nat_entry_set *grab_nat_entry_set(void) +{ + struct nat_entry_set *nes = + f2fs_kmem_cache_alloc(nat_entry_set_slab, GFP_ATOMIC); + + nes->entry_cnt = 0; + INIT_LIST_HEAD(&nes->set_list); + INIT_LIST_HEAD(&nes->entry_list); + return nes; +} + +static void release_nat_entry_set(struct nat_entry_set *nes, + struct f2fs_nm_info *nm_i) +{ + f2fs_bug_on(!list_empty(&nes->entry_list)); + + nm_i->dirty_nat_cnt -= nes->entry_cnt; + list_del(&nes->set_list); + kmem_cache_free(nat_entry_set_slab, nes); +} + +static void adjust_nat_entry_set(struct nat_entry_set *nes, + struct list_head *head) +{ + struct nat_entry_set *next = nes; + + if (list_is_last(&nes->set_list, head)) + return; + + list_for_each_entry_continue(next, head, set_list) + if (nes->entry_cnt <= next->entry_cnt) + break; + + list_move_tail(&nes->set_list, &next->set_list); +} + +static void add_nat_entry(struct nat_entry *ne, struct list_head *head) +{ + struct nat_entry_set *nes; + nid_t start_nid = START_NID(ne->ni.nid); + + list_for_each_entry(nes, head, set_list) { + if (nes->start_nid == start_nid) { + list_move_tail(&ne->list, &nes->entry_list); + nes->entry_cnt++; + adjust_nat_entry_set(nes, head); + return; + } + } + + nes = grab_nat_entry_set(); + + nes->start_nid = start_nid; + list_move_tail(&ne->list, &nes->entry_list); + nes->entry_cnt++; + list_add(&nes->set_list, head); +} + +static void merge_nats_in_set(struct f2fs_sb_info *sbi) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct list_head *dirty_list = &nm_i->dirty_nat_entries; + struct list_head *set_list = &nm_i->nat_entry_set; + struct nat_entry *ne, *tmp; + + write_lock(&nm_i->nat_tree_lock); + list_for_each_entry_safe(ne, tmp, dirty_list, list) { + if (nat_get_blkaddr(ne) == NEW_ADDR) + continue; + add_nat_entry(ne, set_list); + nm_i->dirty_nat_cnt++; + } + write_unlock(&nm_i->nat_tree_lock); +} + +static bool __has_cursum_space(struct f2fs_summary_block *sum, int size) +{ + if (nats_in_cursum(sum) + size <= NAT_JOURNAL_ENTRIES) + return true; + else + return false; +} + +static void remove_nats_in_journal(struct f2fs_sb_info *sbi) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); + struct f2fs_summary_block *sum = curseg->sum_blk; + int i; + + mutex_lock(&curseg->curseg_mutex); + for (i = 0; i < nats_in_cursum(sum); i++) { + struct nat_entry *ne; + struct f2fs_nat_entry raw_ne; + nid_t nid = le32_to_cpu(nid_in_journal(sum, i)); + + raw_ne = nat_in_journal(sum, i); +retry: + write_lock(&nm_i->nat_tree_lock); + ne = __lookup_nat_cache(nm_i, nid); + if (ne) + goto found; + + ne = grab_nat_entry(nm_i, nid); + if (!ne) { + write_unlock(&nm_i->nat_tree_lock); + goto retry; + } + node_info_from_raw_nat(&ne->ni, &raw_ne); +found: + __set_nat_cache_dirty(nm_i, ne); + write_unlock(&nm_i->nat_tree_lock); + } + update_nats_in_cursum(sum, -i); + mutex_unlock(&curseg->curseg_mutex); +} + +/* + * This function is called during the checkpointing process. + */ +void flush_nat_entries(struct f2fs_sb_info *sbi) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_HOT_DATA); + struct f2fs_summary_block *sum = curseg->sum_blk; + struct nat_entry_set *nes, *tmp; + struct list_head *head = &nm_i->nat_entry_set; + bool to_journal = true; + + /* merge nat entries of dirty list to nat entry set temporarily */ + merge_nats_in_set(sbi); + + /* + * if there are no enough space in journal to store dirty nat + * entries, remove all entries from journal and merge them + * into nat entry set. + */ + if (!__has_cursum_space(sum, nm_i->dirty_nat_cnt)) { + remove_nats_in_journal(sbi); + + /* + * merge nat entries of dirty list to nat entry set temporarily + */ + merge_nats_in_set(sbi); + } + + if (!nm_i->dirty_nat_cnt) + return; + + /* + * there are two steps to flush nat entries: + * #1, flush nat entries to journal in current hot data summary block. + * #2, flush nat entries to nat page. + */ + list_for_each_entry_safe(nes, tmp, head, set_list) { + struct f2fs_nat_block *nat_blk; + struct nat_entry *ne, *cur; + struct page *page; + nid_t start_nid = nes->start_nid; + + if (to_journal && !__has_cursum_space(sum, nes->entry_cnt)) + to_journal = false; + + if (to_journal) { + mutex_lock(&curseg->curseg_mutex); + } else { + page = get_next_nat_page(sbi, start_nid); + nat_blk = page_address(page); + f2fs_bug_on(!nat_blk); + } + + /* flush dirty nats in nat entry set */ + list_for_each_entry_safe(ne, cur, &nes->entry_list, list) { + struct f2fs_nat_entry *raw_ne; + nid_t nid = nat_get_nid(ne); + int offset; + + if (to_journal) { + offset = lookup_journal_in_cursum(sum, + NAT_JOURNAL, nid, 1); + f2fs_bug_on(offset < 0); + raw_ne = &nat_in_journal(sum, offset); + nid_in_journal(sum, offset) = cpu_to_le32(nid); + } else { + raw_ne = &nat_blk->entries[nid - start_nid]; + } + raw_nat_from_node_info(raw_ne, &ne->ni); + + if (nat_get_blkaddr(ne) == NULL_ADDR && + add_free_nid(sbi, nid, false) <= 0) { + write_lock(&nm_i->nat_tree_lock); + __del_from_nat_cache(nm_i, ne); + write_unlock(&nm_i->nat_tree_lock); + } else { + write_lock(&nm_i->nat_tree_lock); + __clear_nat_cache_dirty(nm_i, ne); + write_unlock(&nm_i->nat_tree_lock); + } + } + + if (to_journal) + mutex_unlock(&curseg->curseg_mutex); + else + f2fs_put_page(page, 1); + + release_nat_entry_set(nes, nm_i); + } + + f2fs_bug_on(!list_empty(head)); + f2fs_bug_on(nm_i->dirty_nat_cnt); +} + +static int init_node_manager(struct f2fs_sb_info *sbi) +{ + struct f2fs_super_block *sb_raw = F2FS_RAW_SUPER(sbi); + struct f2fs_nm_info *nm_i = NM_I(sbi); + unsigned char *version_bitmap; + unsigned int nat_segs, nat_blocks; + + nm_i->nat_blkaddr = le32_to_cpu(sb_raw->nat_blkaddr); + + /* segment_count_nat includes pair segment so divide to 2. */ + nat_segs = le32_to_cpu(sb_raw->segment_count_nat) >> 1; + nat_blocks = nat_segs << le32_to_cpu(sb_raw->log_blocks_per_seg); + + nm_i->max_nid = NAT_ENTRY_PER_BLOCK * nat_blocks; + + /* not used nids: 0, node, meta, (and root counted as valid node) */ + nm_i->available_nids = nm_i->max_nid - 3; + nm_i->fcnt = 0; + nm_i->nat_cnt = 0; + nm_i->ram_thresh = DEF_RAM_THRESHOLD; + + INIT_RADIX_TREE(&nm_i->free_nid_root, GFP_ATOMIC); + INIT_LIST_HEAD(&nm_i->free_nid_list); + INIT_RADIX_TREE(&nm_i->nat_root, GFP_ATOMIC); + INIT_LIST_HEAD(&nm_i->nat_entries); + INIT_LIST_HEAD(&nm_i->dirty_nat_entries); + INIT_LIST_HEAD(&nm_i->nat_entry_set); + + mutex_init(&nm_i->build_lock); + spin_lock_init(&nm_i->free_nid_list_lock); + rwlock_init(&nm_i->nat_tree_lock); + + nm_i->next_scan_nid = le32_to_cpu(sbi->ckpt->next_free_nid); + nm_i->bitmap_size = __bitmap_size(sbi, NAT_BITMAP); + version_bitmap = __bitmap_ptr(sbi, NAT_BITMAP); + if (!version_bitmap) + return -EFAULT; + + nm_i->nat_bitmap = kmemdup(version_bitmap, nm_i->bitmap_size, + GFP_KERNEL); + if (!nm_i->nat_bitmap) + return -ENOMEM; + return 0; +} + +int build_node_manager(struct f2fs_sb_info *sbi) +{ + int err; + + sbi->nm_info = kzalloc(sizeof(struct f2fs_nm_info), GFP_KERNEL); + if (!sbi->nm_info) + return -ENOMEM; + + err = init_node_manager(sbi); + if (err) + return err; + + build_free_nids(sbi); + return 0; +} + +void destroy_node_manager(struct f2fs_sb_info *sbi) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct free_nid *i, *next_i; + struct nat_entry *natvec[NATVEC_SIZE]; + nid_t nid = 0; + unsigned int found; + + if (!nm_i) + return; + + /* destroy free nid list */ + spin_lock(&nm_i->free_nid_list_lock); + list_for_each_entry_safe(i, next_i, &nm_i->free_nid_list, list) { + f2fs_bug_on(i->state == NID_ALLOC); + __del_from_free_nid_list(nm_i, i); + nm_i->fcnt--; + spin_unlock(&nm_i->free_nid_list_lock); + kmem_cache_free(free_nid_slab, i); + spin_lock(&nm_i->free_nid_list_lock); + } + f2fs_bug_on(nm_i->fcnt); + spin_unlock(&nm_i->free_nid_list_lock); + + /* destroy nat cache */ + write_lock(&nm_i->nat_tree_lock); + while ((found = __gang_lookup_nat_cache(nm_i, + nid, NATVEC_SIZE, natvec))) { + unsigned idx; + nid = nat_get_nid(natvec[found - 1]) + 1; + for (idx = 0; idx < found; idx++) + __del_from_nat_cache(nm_i, natvec[idx]); + } + f2fs_bug_on(nm_i->nat_cnt); + write_unlock(&nm_i->nat_tree_lock); + + kfree(nm_i->nat_bitmap); + sbi->nm_info = NULL; + kfree(nm_i); +} + +int __init create_node_manager_caches(void) +{ + nat_entry_slab = f2fs_kmem_cache_create("nat_entry", + sizeof(struct nat_entry)); + if (!nat_entry_slab) + goto fail; + + free_nid_slab = f2fs_kmem_cache_create("free_nid", + sizeof(struct free_nid)); + if (!free_nid_slab) + goto destory_nat_entry; + + nat_entry_set_slab = f2fs_kmem_cache_create("nat_entry_set", + sizeof(struct nat_entry_set)); + if (!nat_entry_set_slab) + goto destory_free_nid; + return 0; + +destory_free_nid: + kmem_cache_destroy(free_nid_slab); +destory_nat_entry: + kmem_cache_destroy(nat_entry_slab); +fail: + return -ENOMEM; +} + +void destroy_node_manager_caches(void) +{ + kmem_cache_destroy(nat_entry_set_slab); + kmem_cache_destroy(free_nid_slab); + kmem_cache_destroy(nat_entry_slab); +} diff --git a/fs/f2fs/node.h b/fs/f2fs/node.h new file mode 100644 index 00000000000..8a116a40759 --- /dev/null +++ b/fs/f2fs/node.h @@ -0,0 +1,376 @@ +/* + * fs/f2fs/node.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +/* start node id of a node block dedicated to the given node id */ +#define START_NID(nid) ((nid / NAT_ENTRY_PER_BLOCK) * NAT_ENTRY_PER_BLOCK) + +/* node block offset on the NAT area dedicated to the given start node id */ +#define NAT_BLOCK_OFFSET(start_nid) (start_nid / NAT_ENTRY_PER_BLOCK) + +/* # of pages to perform readahead before building free nids */ +#define FREE_NID_PAGES 4 + +/* maximum readahead size for node during getting data blocks */ +#define MAX_RA_NODE 128 + +/* control the memory footprint threshold (10MB per 1GB ram) */ +#define DEF_RAM_THRESHOLD 10 + +/* vector size for gang look-up from nat cache that consists of radix tree */ +#define NATVEC_SIZE 64 + +/* return value for read_node_page */ +#define LOCKED_PAGE 1 + +/* + * For node information + */ +struct node_info { + nid_t nid; /* node id */ + nid_t ino; /* inode number of the node's owner */ + block_t blk_addr; /* block address of the node */ + unsigned char version; /* version of the node */ +}; + +struct nat_entry { + struct list_head list; /* for clean or dirty nat list */ + bool checkpointed; /* whether it is checkpointed or not */ + bool fsync_done; /* whether the latest node has fsync mark */ + struct node_info ni; /* in-memory node information */ +}; + +#define nat_get_nid(nat) (nat->ni.nid) +#define nat_set_nid(nat, n) (nat->ni.nid = n) +#define nat_get_blkaddr(nat) (nat->ni.blk_addr) +#define nat_set_blkaddr(nat, b) (nat->ni.blk_addr = b) +#define nat_get_ino(nat) (nat->ni.ino) +#define nat_set_ino(nat, i) (nat->ni.ino = i) +#define nat_get_version(nat) (nat->ni.version) +#define nat_set_version(nat, v) (nat->ni.version = v) + +#define __set_nat_cache_dirty(nm_i, ne) \ + do { \ + ne->checkpointed = false; \ + list_move_tail(&ne->list, &nm_i->dirty_nat_entries); \ + } while (0) +#define __clear_nat_cache_dirty(nm_i, ne) \ + do { \ + ne->checkpointed = true; \ + list_move_tail(&ne->list, &nm_i->nat_entries); \ + } while (0) +#define inc_node_version(version) (++version) + +static inline void node_info_from_raw_nat(struct node_info *ni, + struct f2fs_nat_entry *raw_ne) +{ + ni->ino = le32_to_cpu(raw_ne->ino); + ni->blk_addr = le32_to_cpu(raw_ne->block_addr); + ni->version = raw_ne->version; +} + +static inline void raw_nat_from_node_info(struct f2fs_nat_entry *raw_ne, + struct node_info *ni) +{ + raw_ne->ino = cpu_to_le32(ni->ino); + raw_ne->block_addr = cpu_to_le32(ni->blk_addr); + raw_ne->version = ni->version; +} + +enum mem_type { + FREE_NIDS, /* indicates the free nid list */ + NAT_ENTRIES, /* indicates the cached nat entry */ + DIRTY_DENTS /* indicates dirty dentry pages */ +}; + +struct nat_entry_set { + struct list_head set_list; /* link with all nat sets */ + struct list_head entry_list; /* link with dirty nat entries */ + nid_t start_nid; /* start nid of nats in set */ + unsigned int entry_cnt; /* the # of nat entries in set */ +}; + +/* + * For free nid mangement + */ +enum nid_state { + NID_NEW, /* newly added to free nid list */ + NID_ALLOC /* it is allocated */ +}; + +struct free_nid { + struct list_head list; /* for free node id list */ + nid_t nid; /* node id */ + int state; /* in use or not: NID_NEW or NID_ALLOC */ +}; + +static inline int next_free_nid(struct f2fs_sb_info *sbi, nid_t *nid) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + struct free_nid *fnid; + + if (nm_i->fcnt <= 0) + return -1; + spin_lock(&nm_i->free_nid_list_lock); + fnid = list_entry(nm_i->free_nid_list.next, struct free_nid, list); + *nid = fnid->nid; + spin_unlock(&nm_i->free_nid_list_lock); + return 0; +} + +/* + * inline functions + */ +static inline void get_nat_bitmap(struct f2fs_sb_info *sbi, void *addr) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + memcpy(addr, nm_i->nat_bitmap, nm_i->bitmap_size); +} + +static inline pgoff_t current_nat_addr(struct f2fs_sb_info *sbi, nid_t start) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + pgoff_t block_off; + pgoff_t block_addr; + int seg_off; + + block_off = NAT_BLOCK_OFFSET(start); + seg_off = block_off >> sbi->log_blocks_per_seg; + + block_addr = (pgoff_t)(nm_i->nat_blkaddr + + (seg_off << sbi->log_blocks_per_seg << 1) + + (block_off & ((1 << sbi->log_blocks_per_seg) - 1))); + + if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) + block_addr += sbi->blocks_per_seg; + + return block_addr; +} + +static inline pgoff_t next_nat_addr(struct f2fs_sb_info *sbi, + pgoff_t block_addr) +{ + struct f2fs_nm_info *nm_i = NM_I(sbi); + + block_addr -= nm_i->nat_blkaddr; + if ((block_addr >> sbi->log_blocks_per_seg) % 2) + block_addr -= sbi->blocks_per_seg; + else + block_addr += sbi->blocks_per_seg; + + return block_addr + nm_i->nat_blkaddr; +} + +static inline void set_to_next_nat(struct f2fs_nm_info *nm_i, nid_t start_nid) +{ + unsigned int block_off = NAT_BLOCK_OFFSET(start_nid); + + if (f2fs_test_bit(block_off, nm_i->nat_bitmap)) + f2fs_clear_bit(block_off, nm_i->nat_bitmap); + else + f2fs_set_bit(block_off, nm_i->nat_bitmap); +} + +static inline void fill_node_footer(struct page *page, nid_t nid, + nid_t ino, unsigned int ofs, bool reset) +{ + struct f2fs_node *rn = F2FS_NODE(page); + if (reset) + memset(rn, 0, sizeof(*rn)); + rn->footer.nid = cpu_to_le32(nid); + rn->footer.ino = cpu_to_le32(ino); + rn->footer.flag = cpu_to_le32(ofs << OFFSET_BIT_SHIFT); +} + +static inline void copy_node_footer(struct page *dst, struct page *src) +{ + struct f2fs_node *src_rn = F2FS_NODE(src); + struct f2fs_node *dst_rn = F2FS_NODE(dst); + memcpy(&dst_rn->footer, &src_rn->footer, sizeof(struct node_footer)); +} + +static inline void fill_node_footer_blkaddr(struct page *page, block_t blkaddr) +{ + struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + struct f2fs_node *rn = F2FS_NODE(page); + + rn->footer.cp_ver = ckpt->checkpoint_ver; + rn->footer.next_blkaddr = cpu_to_le32(blkaddr); +} + +static inline nid_t ino_of_node(struct page *node_page) +{ + struct f2fs_node *rn = F2FS_NODE(node_page); + return le32_to_cpu(rn->footer.ino); +} + +static inline nid_t nid_of_node(struct page *node_page) +{ + struct f2fs_node *rn = F2FS_NODE(node_page); + return le32_to_cpu(rn->footer.nid); +} + +static inline unsigned int ofs_of_node(struct page *node_page) +{ + struct f2fs_node *rn = F2FS_NODE(node_page); + unsigned flag = le32_to_cpu(rn->footer.flag); + return flag >> OFFSET_BIT_SHIFT; +} + +static inline unsigned long long cpver_of_node(struct page *node_page) +{ + struct f2fs_node *rn = F2FS_NODE(node_page); + return le64_to_cpu(rn->footer.cp_ver); +} + +static inline block_t next_blkaddr_of_node(struct page *node_page) +{ + struct f2fs_node *rn = F2FS_NODE(node_page); + return le32_to_cpu(rn->footer.next_blkaddr); +} + +/* + * f2fs assigns the following node offsets described as (num). + * N = NIDS_PER_BLOCK + * + * Inode block (0) + * |- direct node (1) + * |- direct node (2) + * |- indirect node (3) + * | `- direct node (4 => 4 + N - 1) + * |- indirect node (4 + N) + * | `- direct node (5 + N => 5 + 2N - 1) + * `- double indirect node (5 + 2N) + * `- indirect node (6 + 2N) + * `- direct node + * ...... + * `- indirect node ((6 + 2N) + x(N + 1)) + * `- direct node + * ...... + * `- indirect node ((6 + 2N) + (N - 1)(N + 1)) + * `- direct node + */ +static inline bool IS_DNODE(struct page *node_page) +{ + unsigned int ofs = ofs_of_node(node_page); + + if (f2fs_has_xattr_block(ofs)) + return false; + + if (ofs == 3 || ofs == 4 + NIDS_PER_BLOCK || + ofs == 5 + 2 * NIDS_PER_BLOCK) + return false; + if (ofs >= 6 + 2 * NIDS_PER_BLOCK) { + ofs -= 6 + 2 * NIDS_PER_BLOCK; + if (!((long int)ofs % (NIDS_PER_BLOCK + 1))) + return false; + } + return true; +} + +static inline void set_nid(struct page *p, int off, nid_t nid, bool i) +{ + struct f2fs_node *rn = F2FS_NODE(p); + + f2fs_wait_on_page_writeback(p, NODE); + + if (i) + rn->i.i_nid[off - NODE_DIR1_BLOCK] = cpu_to_le32(nid); + else + rn->in.nid[off] = cpu_to_le32(nid); + set_page_dirty(p); +} + +static inline nid_t get_nid(struct page *p, int off, bool i) +{ + struct f2fs_node *rn = F2FS_NODE(p); + + if (i) + return le32_to_cpu(rn->i.i_nid[off - NODE_DIR1_BLOCK]); + return le32_to_cpu(rn->in.nid[off]); +} + +/* + * Coldness identification: + * - Mark cold files in f2fs_inode_info + * - Mark cold node blocks in their node footer + * - Mark cold data pages in page cache + */ +static inline int is_file(struct inode *inode, int type) +{ + return F2FS_I(inode)->i_advise & type; +} + +static inline void set_file(struct inode *inode, int type) +{ + F2FS_I(inode)->i_advise |= type; +} + +static inline void clear_file(struct inode *inode, int type) +{ + F2FS_I(inode)->i_advise &= ~type; +} + +#define file_is_cold(inode) is_file(inode, FADVISE_COLD_BIT) +#define file_wrong_pino(inode) is_file(inode, FADVISE_LOST_PINO_BIT) +#define file_set_cold(inode) set_file(inode, FADVISE_COLD_BIT) +#define file_lost_pino(inode) set_file(inode, FADVISE_LOST_PINO_BIT) +#define file_clear_cold(inode) clear_file(inode, FADVISE_COLD_BIT) +#define file_got_pino(inode) clear_file(inode, FADVISE_LOST_PINO_BIT) + +static inline int is_cold_data(struct page *page) +{ + return PageChecked(page); +} + +static inline void set_cold_data(struct page *page) +{ + SetPageChecked(page); +} + +static inline void clear_cold_data(struct page *page) +{ + ClearPageChecked(page); +} + +static inline int is_node(struct page *page, int type) +{ + struct f2fs_node *rn = F2FS_NODE(page); + return le32_to_cpu(rn->footer.flag) & (1 << type); +} + +#define is_cold_node(page) is_node(page, COLD_BIT_SHIFT) +#define is_fsync_dnode(page) is_node(page, FSYNC_BIT_SHIFT) +#define is_dent_dnode(page) is_node(page, DENT_BIT_SHIFT) + +static inline void set_cold_node(struct inode *inode, struct page *page) +{ + struct f2fs_node *rn = F2FS_NODE(page); + unsigned int flag = le32_to_cpu(rn->footer.flag); + + if (S_ISDIR(inode->i_mode)) + flag &= ~(0x1 << COLD_BIT_SHIFT); + else + flag |= (0x1 << COLD_BIT_SHIFT); + rn->footer.flag = cpu_to_le32(flag); +} + +static inline void set_mark(struct page *page, int mark, int type) +{ + struct f2fs_node *rn = F2FS_NODE(page); + unsigned int flag = le32_to_cpu(rn->footer.flag); + if (mark) + flag |= (0x1 << type); + else + flag &= ~(0x1 << type); + rn->footer.flag = cpu_to_le32(flag); +} +#define set_dentry_mark(page, mark) set_mark(page, mark, DENT_BIT_SHIFT) +#define set_fsync_mark(page, mark) set_mark(page, mark, FSYNC_BIT_SHIFT) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c new file mode 100644 index 00000000000..1e0f3141dd6 --- /dev/null +++ b/fs/f2fs/recovery.c @@ -0,0 +1,521 @@ +/* + * fs/f2fs/recovery.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include "f2fs.h" +#include "node.h" +#include "segment.h" + +static struct kmem_cache *fsync_entry_slab; + +bool space_for_roll_forward(struct f2fs_sb_info *sbi) +{ + if (sbi->last_valid_block_count + sbi->alloc_valid_block_count + > sbi->user_block_count) + return false; + return true; +} + +static struct fsync_inode_entry *get_fsync_inode(struct list_head *head, + nid_t ino) +{ + struct fsync_inode_entry *entry; + + list_for_each_entry(entry, head, list) + if (entry->inode->i_ino == ino) + return entry; + + return NULL; +} + +static int recover_dentry(struct page *ipage, struct inode *inode) +{ + struct f2fs_inode *raw_inode = F2FS_INODE(ipage); + nid_t pino = le32_to_cpu(raw_inode->i_pino); + struct f2fs_dir_entry *de; + struct qstr name; + struct page *page; + struct inode *dir, *einode; + int err = 0; + + dir = f2fs_iget(inode->i_sb, pino); + if (IS_ERR(dir)) { + err = PTR_ERR(dir); + goto out; + } + + name.len = le32_to_cpu(raw_inode->i_namelen); + name.name = raw_inode->i_name; + + if (unlikely(name.len > F2FS_NAME_LEN)) { + WARN_ON(1); + err = -ENAMETOOLONG; + goto out_err; + } +retry: + de = f2fs_find_entry(dir, &name, &page); + if (de && inode->i_ino == le32_to_cpu(de->ino)) + goto out_unmap_put; + if (de) { + einode = f2fs_iget(inode->i_sb, le32_to_cpu(de->ino)); + if (IS_ERR(einode)) { + WARN_ON(1); + err = PTR_ERR(einode); + if (err == -ENOENT) + err = -EEXIST; + goto out_unmap_put; + } + err = acquire_orphan_inode(F2FS_SB(inode->i_sb)); + if (err) { + iput(einode); + goto out_unmap_put; + } + f2fs_delete_entry(de, page, einode); + iput(einode); + goto retry; + } + err = __f2fs_add_link(dir, &name, inode); + if (err) + goto out_err; + + if (is_inode_flag_set(F2FS_I(dir), FI_DELAY_IPUT)) { + iput(dir); + } else { + add_dirty_dir_inode(dir); + set_inode_flag(F2FS_I(dir), FI_DELAY_IPUT); + } + + goto out; + +out_unmap_put: + kunmap(page); + f2fs_put_page(page, 0); +out_err: + iput(dir); +out: + f2fs_msg(inode->i_sb, KERN_DEBUG, + "%s: ino = %x, name = %s, dir = %lx, err = %d", + __func__, ino_of_node(ipage), raw_inode->i_name, + IS_ERR(dir) ? 0 : dir->i_ino, err); + return err; +} + +static int recover_inode(struct inode *inode, struct page *node_page) +{ + struct f2fs_inode *raw_inode = F2FS_INODE(node_page); + + if (!IS_INODE(node_page)) + return 0; + + inode->i_mode = le16_to_cpu(raw_inode->i_mode); + i_size_write(inode, le64_to_cpu(raw_inode->i_size)); + inode->i_atime.tv_sec = le64_to_cpu(raw_inode->i_mtime); + inode->i_ctime.tv_sec = le64_to_cpu(raw_inode->i_ctime); + inode->i_mtime.tv_sec = le64_to_cpu(raw_inode->i_mtime); + 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 (is_dent_dnode(node_page)) + return recover_dentry(node_page, inode); + + f2fs_msg(inode->i_sb, KERN_DEBUG, "recover_inode: ino = %x, name = %s", + ino_of_node(node_page), raw_inode->i_name); + return 0; +} + +static int find_fsync_dnodes(struct f2fs_sb_info *sbi, struct list_head *head) +{ + unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); + struct curseg_info *curseg; + struct page *page; + block_t blkaddr; + int err = 0; + + /* get node pages in the current segment */ + curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); + blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); + + /* read node page */ + page = alloc_page(GFP_F2FS_ZERO); + if (!page) + return -ENOMEM; + lock_page(page); + + while (1) { + struct fsync_inode_entry *entry; + + err = f2fs_submit_page_bio(sbi, page, blkaddr, READ_SYNC); + if (err) + return err; + + lock_page(page); + + if (cp_ver != cpver_of_node(page)) + break; + + if (!is_fsync_dnode(page)) + goto next; + + entry = get_fsync_inode(head, ino_of_node(page)); + if (entry) { + if (IS_INODE(page) && is_dent_dnode(page)) + set_inode_flag(F2FS_I(entry->inode), + FI_INC_LINK); + } else { + if (IS_INODE(page) && is_dent_dnode(page)) { + err = recover_inode_page(sbi, page); + if (err) { + f2fs_msg(sbi->sb, KERN_INFO, + "%s: recover_inode_page failed: %d", + __func__, err); + break; + } + } + + /* add this fsync inode to the list */ + entry = kmem_cache_alloc(fsync_entry_slab, GFP_NOFS); + if (!entry) { + err = -ENOMEM; + break; + } + + entry->inode = f2fs_iget(sbi->sb, ino_of_node(page)); + if (IS_ERR(entry->inode)) { + err = PTR_ERR(entry->inode); + f2fs_msg(sbi->sb, KERN_INFO, + "%s: f2fs_iget failed: %d", + __func__, err); + kmem_cache_free(fsync_entry_slab, entry); + break; + } + list_add_tail(&entry->list, head); + } + entry->blkaddr = blkaddr; + + err = recover_inode(entry->inode, page); + if (err && err != -ENOENT) { + f2fs_msg(sbi->sb, KERN_INFO, + "%s: recover_inode failed: %d", + __func__, err); + break; + } +next: + /* check next segment */ + blkaddr = next_blkaddr_of_node(page); + } + + unlock_page(page); + __free_pages(page, 0); + + return err; +} + +static void destroy_fsync_dnodes(struct list_head *head) +{ + struct fsync_inode_entry *entry, *tmp; + + list_for_each_entry_safe(entry, tmp, head, list) { + iput(entry->inode); + list_del(&entry->list); + kmem_cache_free(fsync_entry_slab, entry); + } +} + +static int check_index_in_prev_nodes(struct f2fs_sb_info *sbi, + block_t blkaddr, struct dnode_of_data *dn) +{ + struct seg_entry *sentry; + unsigned int segno = GET_SEGNO(sbi, blkaddr); + unsigned short blkoff = GET_BLKOFF_FROM_SEG0(sbi, blkaddr); + struct f2fs_summary_block *sum_node; + struct f2fs_summary sum; + struct page *sum_page, *node_page; + nid_t ino, nid; + struct inode *inode; + unsigned int offset; + block_t bidx; + int i; + + if (segno >= TOTAL_SEGS(sbi)) { + f2fs_msg(sbi->sb, KERN_ERR, "invalid segment number %u", segno); + if (f2fs_handle_error(sbi)) + return -EIO; + } + + sentry = get_seg_entry(sbi, segno); + if (!f2fs_test_bit(blkoff, sentry->cur_valid_map)) + return 0; + + /* Get the previous summary */ + for (i = CURSEG_WARM_DATA; i <= CURSEG_COLD_DATA; i++) { + struct curseg_info *curseg = CURSEG_I(sbi, i); + if (curseg->segno == segno) { + sum = curseg->sum_blk->entries[blkoff]; + goto got_it; + } + } + + sum_page = get_sum_page(sbi, segno); + sum_node = (struct f2fs_summary_block *)page_address(sum_page); + sum = sum_node->entries[blkoff]; + f2fs_put_page(sum_page, 1); +got_it: + /* Use the locked dnode page and inode */ + nid = le32_to_cpu(sum.nid); + if (dn->inode->i_ino == nid) { + struct dnode_of_data tdn = *dn; + tdn.nid = nid; + tdn.node_page = dn->inode_page; + tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); + truncate_data_blocks_range(&tdn, 1); + return 0; + } else if (dn->nid == nid) { + struct dnode_of_data tdn = *dn; + tdn.ofs_in_node = le16_to_cpu(sum.ofs_in_node); + truncate_data_blocks_range(&tdn, 1); + return 0; + } + + /* Get the node page */ + node_page = get_node_page(sbi, nid); + if (IS_ERR(node_page)) + return PTR_ERR(node_page); + + offset = ofs_of_node(node_page); + ino = ino_of_node(node_page); + f2fs_put_page(node_page, 1); + + /* Skip nodes with circular references */ + if (ino == dn->inode->i_ino) { + f2fs_msg(sbi->sb, KERN_ERR, "%s: node %x has circular inode %x", + __func__, ino, nid); + f2fs_handle_error(sbi); + return -EDEADLK; + } + + /* Deallocate previous index in the node page */ + inode = f2fs_iget(sbi->sb, ino); + if (IS_ERR(inode)) + return PTR_ERR(inode); + + bidx = start_bidx_of_node(offset, F2FS_I(inode)) + + le16_to_cpu(sum.ofs_in_node); + + truncate_hole(inode, bidx, bidx + 1); + iput(inode); + return 0; +} + +static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, + struct page *page, block_t blkaddr) +{ + struct f2fs_inode_info *fi = F2FS_I(inode); + unsigned int start, end; + struct dnode_of_data dn; + struct f2fs_summary sum; + struct node_info ni; + int err = 0, recovered = 0; + + if (recover_inline_data(inode, page)) + goto out; + + if (recover_xattr_data(inode, page, blkaddr)) + goto out; + + start = start_bidx_of_node(ofs_of_node(page), fi); + if (IS_INODE(page)) + end = start + ADDRS_PER_INODE(fi); + else + end = start + ADDRS_PER_BLOCK; + + f2fs_lock_op(sbi); + + set_new_dnode(&dn, inode, NULL, NULL, 0); + + err = get_dnode_of_data(&dn, start, ALLOC_NODE); + if (err) { + f2fs_unlock_op(sbi); + f2fs_msg(sbi->sb, KERN_INFO, + "%s: get_dnode_of_data failed: %d", __func__, err); + goto out; + } + + f2fs_wait_on_page_writeback(dn.node_page, NODE); + + get_node_info(sbi, dn.nid, &ni); + f2fs_bug_on(ni.ino != ino_of_node(page)); + f2fs_bug_on(ofs_of_node(dn.node_page) != ofs_of_node(page)); + + for (; start < end; start++) { + block_t src, dest; + + src = datablock_addr(dn.node_page, dn.ofs_in_node); + dest = datablock_addr(page, dn.ofs_in_node); + + if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR) { + if (src == NULL_ADDR) { + err = reserve_new_block(&dn); + /* We should not get -ENOSPC */ + f2fs_bug_on(err); + if (err) + f2fs_msg(sbi->sb, KERN_INFO, + "%s: reserve_new_block failed: %d", + __func__, err); + } + + /* Check the previous node page having this index */ + err = check_index_in_prev_nodes(sbi, dest, &dn); + if (err) + goto err; + + set_summary(&sum, dn.nid, dn.ofs_in_node, ni.version); + + /* write dummy data page */ + recover_data_page(sbi, NULL, &sum, src, dest); + update_extent_cache(dest, &dn); + recovered++; + } + dn.ofs_in_node++; + } + + /* write node page in place */ + set_summary(&sum, dn.nid, 0, 0); + if (IS_INODE(dn.node_page)) + sync_inode_page(&dn); + + copy_node_footer(dn.node_page, page); + fill_node_footer(dn.node_page, dn.nid, ni.ino, + ofs_of_node(page), false); + set_page_dirty(dn.node_page); + + recover_node_page(sbi, dn.node_page, &sum, &ni, blkaddr); +err: + f2fs_put_dnode(&dn); + f2fs_unlock_op(sbi); +out: + f2fs_msg(sbi->sb, KERN_DEBUG, + "recover_data: ino = %lx, recovered = %d blocks, err = %d", + inode->i_ino, recovered, err); + return err; +} + +static int recover_data(struct f2fs_sb_info *sbi, + struct list_head *head, int type) +{ + unsigned long long cp_ver = cur_cp_version(F2FS_CKPT(sbi)); + struct curseg_info *curseg; + struct page *page; + int err = 0; + block_t blkaddr; + + /* get node pages in the current segment */ + curseg = CURSEG_I(sbi, type); + blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); + + /* read node page */ + page = alloc_page(GFP_F2FS_ZERO); + if (!page) + return -ENOMEM; + + lock_page(page); + + while (1) { + struct fsync_inode_entry *entry; + + err = f2fs_submit_page_bio(sbi, page, blkaddr, READ_SYNC); + if (err) { + f2fs_msg(sbi->sb, KERN_INFO, + "%s: f2fs_readpage failed: %d", + __func__, err); + return err; + } + + lock_page(page); + + if (cp_ver != cpver_of_node(page)) + break; + + entry = get_fsync_inode(head, ino_of_node(page)); + if (!entry) + goto next; + + err = do_recover_data(sbi, entry->inode, page, blkaddr); + if (err) { + f2fs_msg(sbi->sb, KERN_INFO, + "%s: do_recover_data failed: %d", + __func__, err); + break; + } + + if (entry->blkaddr == blkaddr) { + iput(entry->inode); + list_del(&entry->list); + kmem_cache_free(fsync_entry_slab, entry); + } +next: + /* check next segment */ + blkaddr = next_blkaddr_of_node(page); + } + + unlock_page(page); + __free_pages(page, 0); + + if (!err) + allocate_new_segments(sbi); + return err; +} + +int recover_fsync_data(struct f2fs_sb_info *sbi) +{ + struct list_head inode_list; + int err; + bool need_writecp = false; + + fsync_entry_slab = f2fs_kmem_cache_create("f2fs_fsync_inode_entry", + sizeof(struct fsync_inode_entry)); + if (!fsync_entry_slab) + return -ENOMEM; + + INIT_LIST_HEAD(&inode_list); + + /* step #1: find fsynced inode numbers */ + sbi->por_doing = true; + err = find_fsync_dnodes(sbi, &inode_list); + if (err) { + f2fs_msg(sbi->sb, KERN_INFO, + "%s: find_fsync_dnodes failed: %d", __func__, err); + goto out; + } + + if (list_empty(&inode_list)) + goto out; + + need_writecp = true; + + /* step #2: recover data */ + err = recover_data(sbi, &inode_list, CURSEG_WARM_NODE); + if (!list_empty(&inode_list)) { + f2fs_handle_error(sbi); + err = -EIO; + } +out: + destroy_fsync_dnodes(&inode_list); + kmem_cache_destroy(fsync_entry_slab); + sbi->por_doing = false; + if (!err && need_writecp) { + f2fs_msg(sbi->sb, KERN_INFO, "recovery complete"); + write_checkpoint(sbi, false); + } else + f2fs_msg(sbi->sb, KERN_ERR, "recovery did not fully complete"); + + return err; +} diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c new file mode 100644 index 00000000000..113a8ad4e94 --- /dev/null +++ b/fs/f2fs/segment.c @@ -0,0 +1,2046 @@ +/* + * fs/f2fs/segment.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "segment.h" +#include "node.h" +#include + +#define __reverse_ffz(x) __reverse_ffs(~(x)) + +static struct kmem_cache *discard_entry_slab; + +/* + * __reverse_ffs is copied from include/asm-generic/bitops/__ffs.h since + * MSB and LSB are reversed in a byte by f2fs_set_bit. + */ +static inline unsigned long __reverse_ffs(unsigned long word) +{ + int num = 0; + +#if BITS_PER_LONG == 64 + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } +#endif + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf0) == 0) + num += 4; + else + word >>= 4; + if ((word & 0xc) == 0) + num += 2; + else + word >>= 2; + if ((word & 0x2) == 0) + num += 1; + return num; +} + +/* + * __find_rev_next(_zero)_bit is copied from lib/find_next_bit.c becasue + * f2fs_set_bit makes MSB and LSB reversed in a byte. + * Example: + * LSB <--> MSB + * f2fs_set_bit(0, bitmap) => 0000 0001 + * f2fs_set_bit(7, bitmap) => 1000 0000 + */ +static unsigned long __find_rev_next_bit(const unsigned long *addr, + unsigned long size, unsigned long offset) +{ + const unsigned long *p = addr + BIT_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG - 1); + unsigned long tmp; + unsigned long mask, submask; + unsigned long quot, rest; + + if (offset >= size) + return size; + + size -= result; + offset %= BITS_PER_LONG; + if (!offset) + goto aligned; + + tmp = *(p++); + quot = (offset >> 3) << 3; + rest = offset & 0x7; + mask = ~0UL << quot; + submask = (unsigned char)(0xff << rest) >> rest; + submask <<= quot; + mask &= submask; + tmp &= mask; + if (size < BITS_PER_LONG) + goto found_first; + if (tmp) + goto found_middle; + + size -= BITS_PER_LONG; + result += BITS_PER_LONG; +aligned: + while (size & ~(BITS_PER_LONG-1)) { + tmp = *(p++); + if (tmp) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; +found_first: + tmp &= (~0UL >> (BITS_PER_LONG - size)); + if (tmp == 0UL) /* Are any bits set? */ + return result + size; /* Nope. */ +found_middle: + return result + __reverse_ffs(tmp); +} + +static unsigned long __find_rev_next_zero_bit(const unsigned long *addr, + unsigned long size, unsigned long offset) +{ + const unsigned long *p = addr + BIT_WORD(offset); + unsigned long result = offset & ~(BITS_PER_LONG - 1); + unsigned long tmp; + unsigned long mask, submask; + unsigned long quot, rest; + + if (offset >= size) + return size; + + size -= result; + offset %= BITS_PER_LONG; + if (!offset) + goto aligned; + + tmp = *(p++); + quot = (offset >> 3) << 3; + rest = offset & 0x7; + mask = ~(~0UL << quot); + submask = (unsigned char)~((unsigned char)(0xff << rest) >> rest); + submask <<= quot; + mask += submask; + tmp |= mask; + if (size < BITS_PER_LONG) + goto found_first; + if (~tmp) + goto found_middle; + + size -= BITS_PER_LONG; + result += BITS_PER_LONG; +aligned: + while (size & ~(BITS_PER_LONG - 1)) { + tmp = *(p++); + if (~tmp) + goto found_middle; + result += BITS_PER_LONG; + size -= BITS_PER_LONG; + } + if (!size) + return result; + tmp = *p; + +found_first: + tmp |= ~0UL << size; + if (tmp == ~0UL) /* Are any bits zero? */ + return result + size; /* Nope. */ +found_middle: + return result + __reverse_ffz(tmp); +} + +/* + * This function balances dirty node and dentry pages. + * In addition, it controls garbage collection. + */ +void f2fs_balance_fs(struct f2fs_sb_info *sbi) +{ + /* + * We should do GC or end up with checkpoint, if there are so many dirty + * dir/node pages without enough free segments. + */ + if (has_not_enough_free_secs(sbi, 0)) { + mutex_lock(&sbi->gc_mutex); + f2fs_gc(sbi); + } +} + +void f2fs_balance_fs_bg(struct f2fs_sb_info *sbi) +{ + /* check the # of cached NAT entries and prefree segments */ + if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK) || + excess_prefree_segs(sbi)) + f2fs_sync_fs(sbi->sb, true); +} + +int issue_flush_thread(void *data) +{ +#define test 0 + struct f2fs_sb_info *sbi = data; + struct f2fs_sm_info *sm_i = SM_I(sbi); + wait_queue_head_t *q = &sm_i->flush_wait_queue; + /*struct flush_cmd_control *fcc = SM_I(sbi)->cmd_control_info; + wait_queue_head_t *q = &fcc->flush_wait_queue;*/ +repeat: + if (kthread_should_stop()) + return 0; + + spin_lock(&sm_i->issue_lock); + if (sm_i->issue_list) { + sm_i->dispatch_list = sm_i->issue_list; + sm_i->issue_list = sm_i->issue_tail = NULL; + } + spin_unlock(&sm_i->issue_lock); + + if (sm_i->dispatch_list) { + struct bio *bio = bio_alloc(GFP_NOIO, 0); + struct flush_cmd *cmd, *next; + int ret; + + bio->bi_bdev = sbi->sb->s_bdev; + ret = submit_bio_wait(WRITE_FLUSH, bio); + + for (cmd = sm_i->dispatch_list; cmd; cmd = next) { + cmd->ret = ret; + next = cmd->next; + complete(&cmd->wait); + } + bio_put(bio); + sm_i->dispatch_list = NULL; + } + + wait_event_interruptible(*q, kthread_should_stop() || sm_i->issue_list); + goto repeat; +} + +int f2fs_issue_flush(struct f2fs_sb_info *sbi) +{ + struct f2fs_sm_info *sm_i = SM_I(sbi); + struct flush_cmd cmd; + + if (!test_opt(sbi, FLUSH_MERGE)) + return blkdev_issue_flush(sbi->sb->s_bdev, GFP_KERNEL, NULL); + + init_completion(&cmd.wait); + cmd.next = NULL; + + spin_lock(&sm_i->issue_lock); + if (sm_i->issue_list) + sm_i->issue_tail->next = &cmd; + else + sm_i->issue_list = &cmd; + sm_i->issue_tail = &cmd; + spin_unlock(&sm_i->issue_lock); + + if (!sm_i->dispatch_list) + wake_up(&sm_i->flush_wait_queue); + + wait_for_completion(&cmd.wait); + + return cmd.ret; +} + +static void __locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, + enum dirty_type dirty_type) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + + /* need not be added */ + if (IS_CURSEG(sbi, segno)) + return; + + if (!test_and_set_bit(segno, dirty_i->dirty_segmap[dirty_type])) + dirty_i->nr_dirty[dirty_type]++; + + if (dirty_type == DIRTY) { + struct seg_entry *sentry = get_seg_entry(sbi, segno); + enum dirty_type t = sentry->type; + + if (!test_and_set_bit(segno, dirty_i->dirty_segmap[t])) + dirty_i->nr_dirty[t]++; + } +} + +static void __remove_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno, + enum dirty_type dirty_type) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + + if (test_and_clear_bit(segno, dirty_i->dirty_segmap[dirty_type])) + dirty_i->nr_dirty[dirty_type]--; + + if (dirty_type == DIRTY) { + struct seg_entry *sentry = get_seg_entry(sbi, segno); + enum dirty_type t = sentry->type; + + if (test_and_clear_bit(segno, dirty_i->dirty_segmap[t])) + dirty_i->nr_dirty[t]--; + + if (get_valid_blocks(sbi, segno, sbi->segs_per_sec) == 0) + clear_bit(GET_SECNO(sbi, segno), + dirty_i->victim_secmap); + } +} + +/* + * Should not occur error such as -ENOMEM. + * Adding dirty entry into seglist is not critical operation. + * If a given segment is one of current working segments, it won't be added. + */ +static void locate_dirty_segment(struct f2fs_sb_info *sbi, unsigned int segno) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned short valid_blocks; + + if (segno == NULL_SEGNO || IS_CURSEG(sbi, segno)) + return; + + mutex_lock(&dirty_i->seglist_lock); + + valid_blocks = get_valid_blocks(sbi, segno, 0); + + if (valid_blocks == 0) { + __locate_dirty_segment(sbi, segno, PRE); + __remove_dirty_segment(sbi, segno, DIRTY); + } else if (valid_blocks < sbi->blocks_per_seg) { + __locate_dirty_segment(sbi, segno, DIRTY); + } else { + /* Recovery routine with SSR needs this */ + __remove_dirty_segment(sbi, segno, DIRTY); + } + + mutex_unlock(&dirty_i->seglist_lock); +} + +static int f2fs_issue_discard(struct f2fs_sb_info *sbi, + block_t blkstart, block_t blklen) +{ + sector_t start = SECTOR_FROM_BLOCK(sbi, blkstart); + sector_t len = SECTOR_FROM_BLOCK(sbi, blklen); + trace_f2fs_issue_discard(sbi->sb, blkstart, blklen); + return blkdev_issue_discard(sbi->sb->s_bdev, start, len, GFP_NOFS, 0); +} + +void discard_next_dnode(struct f2fs_sb_info *sbi) +{ + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); + block_t blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); + + if (f2fs_issue_discard(sbi, blkaddr, 1)) { + struct page *page = grab_meta_page(sbi, blkaddr); + /* zero-filled page */ + set_page_dirty(page); + f2fs_put_page(page, 1); + } +} + +static void add_discard_addrs(struct f2fs_sb_info *sbi, + unsigned int segno, struct seg_entry *se) +{ + struct list_head *head = &SM_I(sbi)->discard_list; + struct discard_entry *new; + int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); + int max_blocks = sbi->blocks_per_seg; + unsigned long *cur_map = (unsigned long *)se->cur_valid_map; + unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map; + unsigned long dmap[entries]; + unsigned int start = 0, end = -1; + int i; + + if (!test_opt(sbi, DISCARD)) + return; + + /* zero block will be discarded through the prefree list */ + if (!se->valid_blocks || se->valid_blocks == max_blocks) + return; + + /* SIT_VBLOCK_MAP_SIZE should be multiple of sizeof(unsigned long) */ + for (i = 0; i < entries; i++) + dmap[i] = (cur_map[i] ^ ckpt_map[i]) & ckpt_map[i]; + + while (SM_I(sbi)->nr_discards <= SM_I(sbi)->max_discards) { + start = __find_rev_next_bit(dmap, max_blocks, end + 1); + if (start >= max_blocks) + break; + + end = __find_rev_next_zero_bit(dmap, max_blocks, start + 1); + + new = f2fs_kmem_cache_alloc(discard_entry_slab, GFP_NOFS); + INIT_LIST_HEAD(&new->list); + new->blkaddr = START_BLOCK(sbi, segno) + start; + new->len = end - start; + + list_add_tail(&new->list, head); + SM_I(sbi)->nr_discards += end - start; + } +} + +/* + * Should call clear_prefree_segments after checkpoint is done. + */ +static void set_prefree_as_free_segments(struct f2fs_sb_info *sbi) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned int segno = -1; + unsigned int total_segs = TOTAL_SEGS(sbi); + + mutex_lock(&dirty_i->seglist_lock); + while (1) { + segno = find_next_bit(dirty_i->dirty_segmap[PRE], total_segs, + segno + 1); + if (segno >= total_segs) + break; + __set_test_and_free(sbi, segno); + } + mutex_unlock(&dirty_i->seglist_lock); +} + +void clear_prefree_segments(struct f2fs_sb_info *sbi) +{ + struct list_head *head = &(SM_I(sbi)->discard_list); + struct discard_entry *entry, *this; + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned long *prefree_map = dirty_i->dirty_segmap[PRE]; + unsigned int total_segs = TOTAL_SEGS(sbi); + unsigned int start = 0, end = -1; + + mutex_lock(&dirty_i->seglist_lock); + + while (1) { + int i; + start = find_next_bit(prefree_map, total_segs, end + 1); + if (start >= total_segs) + break; + end = find_next_zero_bit(prefree_map, total_segs, start + 1); + + for (i = start; i < end; i++) + clear_bit(i, prefree_map); + + dirty_i->nr_dirty[PRE] -= end - start; + + if (!test_opt(sbi, DISCARD)) + continue; + + f2fs_issue_discard(sbi, START_BLOCK(sbi, start), + (end - start) << sbi->log_blocks_per_seg); + } + mutex_unlock(&dirty_i->seglist_lock); + + /* send small discards */ + list_for_each_entry_safe(entry, this, head, list) { + f2fs_issue_discard(sbi, entry->blkaddr, entry->len); + list_del(&entry->list); + SM_I(sbi)->nr_discards -= entry->len; + kmem_cache_free(discard_entry_slab, entry); + } +} + +static void __mark_sit_entry_dirty(struct f2fs_sb_info *sbi, unsigned int segno) +{ + struct sit_info *sit_i = SIT_I(sbi); + if (!__test_and_set_bit(segno, sit_i->dirty_sentries_bitmap)) + sit_i->dirty_sentries++; +} + +static void __set_sit_entry_type(struct f2fs_sb_info *sbi, int type, + unsigned int segno, int modified) +{ + struct seg_entry *se = get_seg_entry(sbi, segno); + se->type = type; + if (modified) + __mark_sit_entry_dirty(sbi, segno); +} + +static void update_sit_entry(struct f2fs_sb_info *sbi, block_t blkaddr, int del) +{ + struct seg_entry *se; + unsigned int segno, offset; + long int new_vblocks; + bool check_map = false; + + segno = GET_SEGNO(sbi, blkaddr); + + se = get_seg_entry(sbi, segno); + new_vblocks = se->valid_blocks + del; + offset = GET_BLKOFF_FROM_SEG0(sbi, blkaddr); + + if (new_vblocks < 0 || new_vblocks > sbi->blocks_per_seg || + (new_vblocks >> (sizeof(unsigned short) << 3))) + if (f2fs_handle_error(sbi)) + check_map = true; + + se->mtime = get_mtime(sbi); + SIT_I(sbi)->max_mtime = se->mtime; + + /* Update valid block bitmap */ + if (del > 0) { + if (f2fs_set_bit(offset, se->cur_valid_map)) + if (f2fs_handle_error(sbi)) + check_map = true; + } else { + if (!f2fs_clear_bit(offset, se->cur_valid_map)) + if (f2fs_handle_error(sbi)) + check_map = true; + } + + if (unlikely(check_map)) { + int i; + long int vblocks = 0; + + f2fs_msg(sbi->sb, KERN_ERR, + "cannot %svalidate block %u in segment %u with %hu valid blocks", + (del < 0) ? "in" : "", + offset, segno, se->valid_blocks); + + /* assume the count was stale to start */ + del = 0; + for (i = 0; i < sbi->blocks_per_seg; i++) + if (f2fs_test_bit(i, se->cur_valid_map)) + vblocks++; + if (vblocks != se->valid_blocks) { + f2fs_msg(sbi->sb, KERN_INFO, "correcting valid block " + "counts %d -> %ld", se->valid_blocks, vblocks); + /* make accounting corrections */ + del = vblocks - se->valid_blocks; + } + } + se->valid_blocks += del; + + if (!f2fs_test_bit(offset, se->ckpt_valid_map)) + se->ckpt_valid_blocks += del; + + __mark_sit_entry_dirty(sbi, segno); + + /* update total number of valid blocks to be written in ckpt area */ + SIT_I(sbi)->written_valid_blocks += del; + + if (sbi->segs_per_sec > 1) + get_sec_entry(sbi, segno)->valid_blocks += del; +} + +void refresh_sit_entry(struct f2fs_sb_info *sbi, block_t old, block_t new) +{ + update_sit_entry(sbi, new, 1); + if (GET_SEGNO(sbi, old) != NULL_SEGNO) + update_sit_entry(sbi, old, -1); + + locate_dirty_segment(sbi, GET_SEGNO(sbi, old)); + locate_dirty_segment(sbi, GET_SEGNO(sbi, new)); +} + +void invalidate_blocks(struct f2fs_sb_info *sbi, block_t addr) +{ + unsigned int segno = GET_SEGNO(sbi, addr); + struct sit_info *sit_i = SIT_I(sbi); + + f2fs_bug_on(addr == NULL_ADDR); + if (addr == NEW_ADDR) + return; + + if (segno >= TOTAL_SEGS(sbi)) { + f2fs_msg(sbi->sb, KERN_ERR, "invalid segment number %u", segno); + if (f2fs_handle_error(sbi)) + return; + } + + /* add it into sit main buffer */ + mutex_lock(&sit_i->sentry_lock); + + update_sit_entry(sbi, addr, -1); + + /* add it into dirty seglist */ + locate_dirty_segment(sbi, segno); + + mutex_unlock(&sit_i->sentry_lock); +} + +/* + * This function should be resided under the curseg_mutex lock + */ +static void __add_sum_entry(struct f2fs_sb_info *sbi, int type, + struct f2fs_summary *sum) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + void *addr = curseg->sum_blk; + addr += curseg->next_blkoff * sizeof(struct f2fs_summary); + memcpy(addr, sum, sizeof(struct f2fs_summary)); +} + +/* + * Calculate the number of current summary pages for writing + */ +int npages_for_summary_flush(struct f2fs_sb_info *sbi) +{ + int valid_sum_count = 0; + int i, sum_in_page; + + for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { + if (sbi->ckpt->alloc_type[i] == SSR) + valid_sum_count += sbi->blocks_per_seg; + else + valid_sum_count += curseg_blkoff(sbi, i); + } + + sum_in_page = (PAGE_CACHE_SIZE - 2 * SUM_JOURNAL_SIZE - + SUM_FOOTER_SIZE) / SUMMARY_SIZE; + if (valid_sum_count <= sum_in_page) + return 1; + else if ((valid_sum_count - sum_in_page) <= + (PAGE_CACHE_SIZE - SUM_FOOTER_SIZE) / SUMMARY_SIZE) + return 2; + return 3; +} + +/* + * Caller should put this summary page + */ +struct page *get_sum_page(struct f2fs_sb_info *sbi, unsigned int segno) +{ + return get_meta_page(sbi, GET_SUM_BLOCK(sbi, segno)); +} + +static void write_sum_page(struct f2fs_sb_info *sbi, + struct f2fs_summary_block *sum_blk, block_t blk_addr) +{ + struct page *page = grab_meta_page(sbi, blk_addr); + void *kaddr = page_address(page); + memcpy(kaddr, sum_blk, PAGE_CACHE_SIZE); + set_page_dirty(page); + f2fs_put_page(page, 1); +} + +static int is_next_segment_free(struct f2fs_sb_info *sbi, int type) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + unsigned int segno = curseg->segno + 1; + struct free_segmap_info *free_i = FREE_I(sbi); + + if (segno < TOTAL_SEGS(sbi) && segno % sbi->segs_per_sec) + return !test_bit(segno, free_i->free_segmap); + return 0; +} + +/* + * Find a new segment from the free segments bitmap to right order + * This function should be returned with success, otherwise BUG + */ +static void get_new_segment(struct f2fs_sb_info *sbi, + unsigned int *newseg, bool new_sec, int dir) +{ + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int segno, secno, zoneno; + unsigned int total_zones = TOTAL_SECS(sbi) / sbi->secs_per_zone; + unsigned int hint = *newseg / sbi->segs_per_sec; + unsigned int old_zoneno = GET_ZONENO_FROM_SEGNO(sbi, *newseg); + unsigned int left_start = hint; + bool init = true; + int go_left = 0; + int i; + + write_lock(&free_i->segmap_lock); + + if (!new_sec && ((*newseg + 1) % sbi->segs_per_sec)) { + segno = find_next_zero_bit(free_i->free_segmap, + TOTAL_SEGS(sbi), *newseg + 1); + if (segno - *newseg < sbi->segs_per_sec - + (*newseg % sbi->segs_per_sec)) + goto got_it; + } +find_other_zone: + secno = find_next_zero_bit(free_i->free_secmap, TOTAL_SECS(sbi), hint); + if (secno >= TOTAL_SECS(sbi)) { + if (dir == ALLOC_RIGHT) { + secno = find_next_zero_bit(free_i->free_secmap, + TOTAL_SECS(sbi), 0); + f2fs_bug_on(secno >= TOTAL_SECS(sbi)); + } else { + go_left = 1; + left_start = hint - 1; + } + } + if (go_left == 0) + goto skip_left; + + while (test_bit(left_start, free_i->free_secmap)) { + if (left_start > 0) { + left_start--; + continue; + } + left_start = find_next_zero_bit(free_i->free_secmap, + TOTAL_SECS(sbi), 0); + f2fs_bug_on(left_start >= TOTAL_SECS(sbi)); + break; + } + secno = left_start; +skip_left: + hint = secno; + segno = secno * sbi->segs_per_sec; + zoneno = secno / sbi->secs_per_zone; + + /* give up on finding another zone */ + if (!init) + goto got_it; + if (sbi->secs_per_zone == 1) + goto got_it; + if (zoneno == old_zoneno) + goto got_it; + if (dir == ALLOC_LEFT) { + if (!go_left && zoneno + 1 >= total_zones) + goto got_it; + if (go_left && zoneno == 0) + goto got_it; + } + for (i = 0; i < NR_CURSEG_TYPE; i++) + if (CURSEG_I(sbi, i)->zone == zoneno) + break; + + if (i < NR_CURSEG_TYPE) { + /* zone is in user, try another */ + if (go_left) + hint = zoneno * sbi->secs_per_zone - 1; + else if (zoneno + 1 >= total_zones) + hint = 0; + else + hint = (zoneno + 1) * sbi->secs_per_zone; + init = false; + goto find_other_zone; + } +got_it: + /* set it as dirty segment in free segmap */ + f2fs_bug_on(test_bit(segno, free_i->free_segmap)); + __set_inuse(sbi, segno); + *newseg = segno; + write_unlock(&free_i->segmap_lock); +} + +static void reset_curseg(struct f2fs_sb_info *sbi, int type, int modified) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + struct summary_footer *sum_footer; + + curseg->segno = curseg->next_segno; + curseg->zone = GET_ZONENO_FROM_SEGNO(sbi, curseg->segno); + curseg->next_blkoff = 0; + curseg->next_segno = NULL_SEGNO; + + sum_footer = &(curseg->sum_blk->footer); + memset(sum_footer, 0, sizeof(struct summary_footer)); + if (IS_DATASEG(type)) + SET_SUM_TYPE(sum_footer, SUM_TYPE_DATA); + if (IS_NODESEG(type)) + SET_SUM_TYPE(sum_footer, SUM_TYPE_NODE); + __set_sit_entry_type(sbi, type, curseg->segno, modified); +} + +/* + * Allocate a current working segment. + * This function always allocates a free segment in LFS manner. + */ +static void new_curseg(struct f2fs_sb_info *sbi, int type, bool new_sec) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + unsigned int segno = curseg->segno; + int dir = ALLOC_LEFT; + + write_sum_page(sbi, curseg->sum_blk, + GET_SUM_BLOCK(sbi, segno)); + if (type == CURSEG_WARM_DATA || type == CURSEG_COLD_DATA) + dir = ALLOC_RIGHT; + + if (test_opt(sbi, NOHEAP)) + dir = ALLOC_RIGHT; + + get_new_segment(sbi, &segno, new_sec, dir); + curseg->next_segno = segno; + reset_curseg(sbi, type, 1); + curseg->alloc_type = LFS; +} + +static void __next_free_blkoff(struct f2fs_sb_info *sbi, + struct curseg_info *seg, block_t start) +{ + struct seg_entry *se = get_seg_entry(sbi, seg->segno); + int entries = SIT_VBLOCK_MAP_SIZE / sizeof(unsigned long); + unsigned long target_map[entries]; + unsigned long *ckpt_map = (unsigned long *)se->ckpt_valid_map; + unsigned long *cur_map = (unsigned long *)se->cur_valid_map; + int i, pos; + + for (i = 0; i < entries; i++) + target_map[i] = ckpt_map[i] | cur_map[i]; + + pos = __find_rev_next_zero_bit(target_map, sbi->blocks_per_seg, start); + + seg->next_blkoff = pos; +} + +/* + * If a segment is written by LFS manner, next block offset is just obtained + * by increasing the current block offset. However, if a segment is written by + * SSR manner, next block offset obtained by calling __next_free_blkoff + */ +static void __refresh_next_blkoff(struct f2fs_sb_info *sbi, + struct curseg_info *seg) +{ + if (seg->alloc_type == SSR) + __next_free_blkoff(sbi, seg, seg->next_blkoff + 1); + else + seg->next_blkoff++; +} + +/* + * This function always allocates a used segment (from dirty seglist) by SSR + * manner, so it should recover the existing segment information of valid blocks + */ +static void change_curseg(struct f2fs_sb_info *sbi, int type, bool reuse) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + struct curseg_info *curseg = CURSEG_I(sbi, type); + unsigned int new_segno = curseg->next_segno; + struct f2fs_summary_block *sum_node; + struct page *sum_page; + + write_sum_page(sbi, curseg->sum_blk, + GET_SUM_BLOCK(sbi, curseg->segno)); + __set_test_and_inuse(sbi, new_segno); + + mutex_lock(&dirty_i->seglist_lock); + __remove_dirty_segment(sbi, new_segno, PRE); + __remove_dirty_segment(sbi, new_segno, DIRTY); + mutex_unlock(&dirty_i->seglist_lock); + + reset_curseg(sbi, type, 1); + curseg->alloc_type = SSR; + __next_free_blkoff(sbi, curseg, 0); + + if (reuse) { + sum_page = get_sum_page(sbi, new_segno); + sum_node = (struct f2fs_summary_block *)page_address(sum_page); + memcpy(curseg->sum_blk, sum_node, SUM_ENTRY_SIZE); + f2fs_put_page(sum_page, 1); + } +} + +static int get_ssr_segment(struct f2fs_sb_info *sbi, int type) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + const struct victim_selection *v_ops = DIRTY_I(sbi)->v_ops; + + if (IS_NODESEG(type) || !has_not_enough_free_secs(sbi, 0)) + return v_ops->get_victim(sbi, + &(curseg)->next_segno, BG_GC, type, SSR); + + /* For data segments, let's do SSR more intensively */ + for (; type >= CURSEG_HOT_DATA; type--) + if (v_ops->get_victim(sbi, &(curseg)->next_segno, + BG_GC, type, SSR)) + return 1; + return 0; +} + +/* + * flush out current segment and replace it with new segment + * This function should be returned with success, otherwise BUG + */ +static void allocate_segment_by_default(struct f2fs_sb_info *sbi, + int type, bool force) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + + if (force) + new_curseg(sbi, type, true); + else if (type == CURSEG_WARM_NODE) + new_curseg(sbi, type, false); + else if (curseg->alloc_type == LFS && is_next_segment_free(sbi, type)) + new_curseg(sbi, type, false); + else if (need_SSR(sbi) && get_ssr_segment(sbi, type)) + change_curseg(sbi, type, true); + else + new_curseg(sbi, type, false); + + stat_inc_seg_type(sbi, curseg); +} + +void allocate_new_segments(struct f2fs_sb_info *sbi) +{ + struct curseg_info *curseg; + unsigned int old_curseg; + int i; + + for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { + curseg = CURSEG_I(sbi, i); + old_curseg = curseg->segno; + SIT_I(sbi)->s_ops->allocate_segment(sbi, i, true); + locate_dirty_segment(sbi, old_curseg); + } +} + +static const struct segment_allocation default_salloc_ops = { + .allocate_segment = allocate_segment_by_default, +}; + +static bool __has_curseg_space(struct f2fs_sb_info *sbi, int type) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + if (curseg->next_blkoff < sbi->blocks_per_seg) + return true; + return false; +} + +static int __get_segment_type_2(struct page *page, enum page_type p_type) +{ + if (p_type == DATA) + return CURSEG_HOT_DATA; + else + return CURSEG_HOT_NODE; +} + +static int __get_segment_type_4(struct page *page, enum page_type p_type) +{ + if (p_type == DATA) { + struct inode *inode = page->mapping->host; + + if (S_ISDIR(inode->i_mode)) + return CURSEG_HOT_DATA; + else + return CURSEG_COLD_DATA; + } else { + if (IS_DNODE(page) && !is_cold_node(page)) + return CURSEG_HOT_NODE; + else + return CURSEG_COLD_NODE; + } +} + +static int __get_segment_type_6(struct page *page, enum page_type p_type) +{ + if (p_type == DATA) { + struct inode *inode = page->mapping->host; + + if (S_ISDIR(inode->i_mode)) + return CURSEG_HOT_DATA; + else if (is_cold_data(page) || file_is_cold(inode)) + return CURSEG_COLD_DATA; + else + return CURSEG_WARM_DATA; + } else { + if (IS_DNODE(page)) + return is_cold_node(page) ? CURSEG_WARM_NODE : + CURSEG_HOT_NODE; + else + return CURSEG_COLD_NODE; + } +} + +static int __get_segment_type(struct page *page, enum page_type p_type) +{ + struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); + switch (sbi->active_logs) { + case 2: + return __get_segment_type_2(page, p_type); + case 4: + return __get_segment_type_4(page, p_type); + } + /* NR_CURSEG_TYPE(6) logs by default */ + f2fs_bug_on(sbi->active_logs != NR_CURSEG_TYPE); + return __get_segment_type_6(page, p_type); +} + +void allocate_data_block(struct f2fs_sb_info *sbi, struct page *page, + block_t old_blkaddr, block_t *new_blkaddr, + struct f2fs_summary *sum, int type) +{ + struct sit_info *sit_i = SIT_I(sbi); + struct curseg_info *curseg; + unsigned int old_cursegno; + + curseg = CURSEG_I(sbi, type); + + mutex_lock(&curseg->curseg_mutex); + + *new_blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); + old_cursegno = curseg->segno; + + /* + * __add_sum_entry should be resided under the curseg_mutex + * because, this function updates a summary entry in the + * current summary block. + */ + __add_sum_entry(sbi, type, sum); + + mutex_lock(&sit_i->sentry_lock); + __refresh_next_blkoff(sbi, curseg); + + stat_inc_block_count(sbi, curseg); + + if (!__has_curseg_space(sbi, type)) + sit_i->s_ops->allocate_segment(sbi, type, false); + /* + * SIT information should be updated before segment allocation, + * since SSR needs latest valid block information. + */ + refresh_sit_entry(sbi, old_blkaddr, *new_blkaddr); + locate_dirty_segment(sbi, old_cursegno); + + mutex_unlock(&sit_i->sentry_lock); + + if (page && IS_NODESEG(type)) + fill_node_footer_blkaddr(page, NEXT_FREE_BLKADDR(sbi, curseg)); + + mutex_unlock(&curseg->curseg_mutex); +} + +static void do_write_page(struct f2fs_sb_info *sbi, struct page *page, + block_t old_blkaddr, block_t *new_blkaddr, + struct f2fs_summary *sum, struct f2fs_io_info *fio) +{ + int type = __get_segment_type(page, fio->type); + + allocate_data_block(sbi, page, old_blkaddr, new_blkaddr, sum, type); + + /* writeout dirty page into bdev */ + f2fs_submit_page_mbio(sbi, page, *new_blkaddr, fio); +} + +void write_meta_page(struct f2fs_sb_info *sbi, struct page *page) +{ + struct f2fs_io_info fio = { + .type = META, + .rw = WRITE_SYNC | REQ_META | REQ_PRIO + }; + + set_page_writeback(page); + f2fs_submit_page_mbio(sbi, page, page->index, &fio); +} + +void write_node_page(struct f2fs_sb_info *sbi, struct page *page, + struct f2fs_io_info *fio, + unsigned int nid, block_t old_blkaddr, block_t *new_blkaddr) +{ + struct f2fs_summary sum; + set_summary(&sum, nid, 0, 0); + do_write_page(sbi, page, old_blkaddr, new_blkaddr, &sum, fio); +} + +void write_data_page(struct page *page, struct dnode_of_data *dn, + block_t *new_blkaddr, struct f2fs_io_info *fio) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dn->inode->i_sb); + struct f2fs_summary sum; + struct node_info ni; + + f2fs_bug_on(dn->data_blkaddr == NULL_ADDR); + get_node_info(sbi, dn->nid, &ni); + set_summary(&sum, dn->nid, dn->ofs_in_node, ni.version); + + do_write_page(sbi, page, dn->data_blkaddr, new_blkaddr, &sum, fio); +} + +void rewrite_data_page(struct page *page, block_t old_blkaddr, + struct f2fs_io_info *fio) +{ + struct inode *inode = page->mapping->host; + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + f2fs_submit_page_mbio(sbi, page, old_blkaddr, fio); +} + +void recover_data_page(struct f2fs_sb_info *sbi, + struct page *page, struct f2fs_summary *sum, + block_t old_blkaddr, block_t new_blkaddr) +{ + struct sit_info *sit_i = SIT_I(sbi); + struct curseg_info *curseg; + unsigned int segno, old_cursegno; + struct seg_entry *se; + int type; + + segno = GET_SEGNO(sbi, new_blkaddr); + se = get_seg_entry(sbi, segno); + type = se->type; + + if (se->valid_blocks == 0 && !IS_CURSEG(sbi, segno)) { + if (old_blkaddr == NULL_ADDR) + type = CURSEG_COLD_DATA; + else + type = CURSEG_WARM_DATA; + } + curseg = CURSEG_I(sbi, type); + + mutex_lock(&curseg->curseg_mutex); + mutex_lock(&sit_i->sentry_lock); + + old_cursegno = curseg->segno; + + /* change the current segment */ + if (segno != curseg->segno) { + curseg->next_segno = segno; + change_curseg(sbi, type, true); + } + + curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr); + __add_sum_entry(sbi, type, sum); + + refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); + locate_dirty_segment(sbi, old_cursegno); + + mutex_unlock(&sit_i->sentry_lock); + mutex_unlock(&curseg->curseg_mutex); +} + +void rewrite_node_page(struct f2fs_sb_info *sbi, + struct page *page, struct f2fs_summary *sum, + block_t old_blkaddr, block_t new_blkaddr) +{ + struct sit_info *sit_i = SIT_I(sbi); + int type = CURSEG_WARM_NODE; + struct curseg_info *curseg; + unsigned int segno, old_cursegno; + block_t next_blkaddr = next_blkaddr_of_node(page); + unsigned int next_segno = GET_SEGNO(sbi, next_blkaddr); + struct f2fs_io_info fio = { + .type = NODE, + .rw = WRITE_SYNC, + }; + + curseg = CURSEG_I(sbi, type); + + mutex_lock(&curseg->curseg_mutex); + mutex_lock(&sit_i->sentry_lock); + + segno = GET_SEGNO(sbi, new_blkaddr); + old_cursegno = curseg->segno; + + /* change the current segment */ + if (segno != curseg->segno) { + curseg->next_segno = segno; + change_curseg(sbi, type, true); + } + curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, new_blkaddr); + __add_sum_entry(sbi, type, sum); + + /* change the current log to the next block addr in advance */ + if (next_segno != segno) { + curseg->next_segno = next_segno; + change_curseg(sbi, type, true); + } + curseg->next_blkoff = GET_BLKOFF_FROM_SEG0(sbi, next_blkaddr); + + /* rewrite node page */ + set_page_writeback(page); + f2fs_submit_page_mbio(sbi, page, new_blkaddr, &fio); + f2fs_submit_merged_bio(sbi, NODE, WRITE); + refresh_sit_entry(sbi, old_blkaddr, new_blkaddr); + locate_dirty_segment(sbi, old_cursegno); + + mutex_unlock(&sit_i->sentry_lock); + mutex_unlock(&curseg->curseg_mutex); +} + +static inline bool is_merged_page(struct f2fs_sb_info *sbi, + struct page *page, enum page_type type) +{ + enum page_type btype = PAGE_TYPE_OF_BIO(type); + struct f2fs_bio_info *io = &sbi->write_io[btype]; + struct bio_vec *bvec; + int i; + + down_read(&io->io_rwsem); + if (!io->bio) + goto out; + + bio_for_each_segment_all(bvec, io->bio, i) { + if (page == bvec->bv_page) { + up_read(&io->io_rwsem); + return true; + } + } + +out: + up_read(&io->io_rwsem); + return false; +} + +void f2fs_wait_on_page_writeback(struct page *page, + enum page_type type) +{ + struct f2fs_sb_info *sbi = F2FS_SB(page->mapping->host->i_sb); + if (PageWriteback(page)) { + if (is_merged_page(sbi, page, type)) + f2fs_submit_merged_bio(sbi, type, WRITE); + wait_on_page_writeback(page); + } +} + +static int read_compacted_summaries(struct f2fs_sb_info *sbi) +{ + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + struct curseg_info *seg_i; + unsigned char *kaddr; + struct page *page; + block_t start; + int i, j, offset; + + start = start_sum_block(sbi); + + page = get_meta_page(sbi, start++); + kaddr = (unsigned char *)page_address(page); + + /* Step 1: restore nat cache */ + seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA); + memcpy(&seg_i->sum_blk->n_nats, kaddr, SUM_JOURNAL_SIZE); + + /* Step 2: restore sit cache */ + seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA); + memcpy(&seg_i->sum_blk->n_sits, kaddr + SUM_JOURNAL_SIZE, + SUM_JOURNAL_SIZE); + offset = 2 * SUM_JOURNAL_SIZE; + + /* Step 3: restore summary entries */ + for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { + unsigned short blk_off; + unsigned int segno; + + seg_i = CURSEG_I(sbi, i); + segno = le32_to_cpu(ckpt->cur_data_segno[i]); + blk_off = le16_to_cpu(ckpt->cur_data_blkoff[i]); + seg_i->next_segno = segno; + reset_curseg(sbi, i, 0); + seg_i->alloc_type = ckpt->alloc_type[i]; + seg_i->next_blkoff = blk_off; + + if (seg_i->alloc_type == SSR) + blk_off = sbi->blocks_per_seg; + + for (j = 0; j < blk_off; j++) { + struct f2fs_summary *s; + s = (struct f2fs_summary *)(kaddr + offset); + seg_i->sum_blk->entries[j] = *s; + offset += SUMMARY_SIZE; + if (offset + SUMMARY_SIZE <= PAGE_CACHE_SIZE - + SUM_FOOTER_SIZE) + continue; + + f2fs_put_page(page, 1); + page = NULL; + + page = get_meta_page(sbi, start++); + kaddr = (unsigned char *)page_address(page); + offset = 0; + } + } + f2fs_put_page(page, 1); + return 0; +} + +static int read_normal_summaries(struct f2fs_sb_info *sbi, int type) +{ + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + struct f2fs_summary_block *sum; + struct curseg_info *curseg; + struct page *new; + unsigned short blk_off; + unsigned int segno = 0; + block_t blk_addr = 0; + + /* get segment number and block addr */ + if (IS_DATASEG(type)) { + segno = le32_to_cpu(ckpt->cur_data_segno[type]); + blk_off = le16_to_cpu(ckpt->cur_data_blkoff[type - + CURSEG_HOT_DATA]); + if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) + blk_addr = sum_blk_addr(sbi, NR_CURSEG_TYPE, type); + else + blk_addr = sum_blk_addr(sbi, NR_CURSEG_DATA_TYPE, type); + } else { + segno = le32_to_cpu(ckpt->cur_node_segno[type - + CURSEG_HOT_NODE]); + blk_off = le16_to_cpu(ckpt->cur_node_blkoff[type - + CURSEG_HOT_NODE]); + if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) + blk_addr = sum_blk_addr(sbi, NR_CURSEG_NODE_TYPE, + type - CURSEG_HOT_NODE); + else + blk_addr = GET_SUM_BLOCK(sbi, segno); + } + + new = get_meta_page(sbi, blk_addr); + sum = (struct f2fs_summary_block *)page_address(new); + + if (IS_NODESEG(type)) { + if (is_set_ckpt_flags(ckpt, CP_UMOUNT_FLAG)) { + struct f2fs_summary *ns = &sum->entries[0]; + int i; + for (i = 0; i < sbi->blocks_per_seg; i++, ns++) { + ns->version = 0; + ns->ofs_in_node = 0; + } + } else { + int err; + + err = restore_node_summary(sbi, segno, sum); + if (err) { + f2fs_put_page(new, 1); + return err; + } + } + } + + /* set uncompleted segment to curseg */ + curseg = CURSEG_I(sbi, type); + mutex_lock(&curseg->curseg_mutex); + memcpy(curseg->sum_blk, sum, PAGE_CACHE_SIZE); + curseg->next_segno = segno; + reset_curseg(sbi, type, 0); + curseg->alloc_type = ckpt->alloc_type[type]; + curseg->next_blkoff = blk_off; + mutex_unlock(&curseg->curseg_mutex); + f2fs_put_page(new, 1); + return 0; +} + +static int restore_curseg_summaries(struct f2fs_sb_info *sbi) +{ + int type = CURSEG_HOT_DATA; + int err; + + if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) { + /* restore for compacted data summary */ + if (read_compacted_summaries(sbi)) + return -EINVAL; + type = CURSEG_HOT_NODE; + } + + for (; type <= CURSEG_COLD_NODE; type++) { + err = read_normal_summaries(sbi, type); + if (err) + return err; + } + + return 0; +} + +static void write_compacted_summaries(struct f2fs_sb_info *sbi, block_t blkaddr) +{ + struct page *page; + unsigned char *kaddr; + struct f2fs_summary *summary; + struct curseg_info *seg_i; + int written_size = 0; + int i, j; + + page = grab_meta_page(sbi, blkaddr++); + kaddr = (unsigned char *)page_address(page); + + /* Step 1: write nat cache */ + seg_i = CURSEG_I(sbi, CURSEG_HOT_DATA); + memcpy(kaddr, &seg_i->sum_blk->n_nats, SUM_JOURNAL_SIZE); + written_size += SUM_JOURNAL_SIZE; + + /* Step 2: write sit cache */ + seg_i = CURSEG_I(sbi, CURSEG_COLD_DATA); + memcpy(kaddr + written_size, &seg_i->sum_blk->n_sits, + SUM_JOURNAL_SIZE); + written_size += SUM_JOURNAL_SIZE; + + /* Step 3: write summary entries */ + for (i = CURSEG_HOT_DATA; i <= CURSEG_COLD_DATA; i++) { + unsigned short blkoff; + seg_i = CURSEG_I(sbi, i); + if (sbi->ckpt->alloc_type[i] == SSR) + blkoff = sbi->blocks_per_seg; + else + blkoff = curseg_blkoff(sbi, i); + + for (j = 0; j < blkoff; j++) { + if (!page) { + page = grab_meta_page(sbi, blkaddr++); + kaddr = (unsigned char *)page_address(page); + written_size = 0; + } + summary = (struct f2fs_summary *)(kaddr + written_size); + *summary = seg_i->sum_blk->entries[j]; + written_size += SUMMARY_SIZE; + + if (written_size + SUMMARY_SIZE <= PAGE_CACHE_SIZE - + SUM_FOOTER_SIZE) + continue; + + set_page_dirty(page); + f2fs_put_page(page, 1); + page = NULL; + } + } + if (page) { + set_page_dirty(page); + f2fs_put_page(page, 1); + } +} + +static void write_normal_summaries(struct f2fs_sb_info *sbi, + block_t blkaddr, int type) +{ + int i, end; + if (IS_DATASEG(type)) + end = type + NR_CURSEG_DATA_TYPE; + else + end = type + NR_CURSEG_NODE_TYPE; + + for (i = type; i < end; i++) { + struct curseg_info *sum = CURSEG_I(sbi, i); + mutex_lock(&sum->curseg_mutex); + write_sum_page(sbi, sum->sum_blk, blkaddr + (i - type)); + mutex_unlock(&sum->curseg_mutex); + } +} + +void write_data_summaries(struct f2fs_sb_info *sbi, block_t start_blk) +{ + if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_COMPACT_SUM_FLAG)) + write_compacted_summaries(sbi, start_blk); + else + write_normal_summaries(sbi, start_blk, CURSEG_HOT_DATA); +} + +void write_node_summaries(struct f2fs_sb_info *sbi, block_t start_blk) +{ + if (is_set_ckpt_flags(F2FS_CKPT(sbi), CP_UMOUNT_FLAG)) + write_normal_summaries(sbi, start_blk, CURSEG_HOT_NODE); +} + +int lookup_journal_in_cursum(struct f2fs_summary_block *sum, int type, + unsigned int val, int alloc) +{ + int i; + + if (type == NAT_JOURNAL) { + for (i = 0; i < nats_in_cursum(sum); i++) { + if (le32_to_cpu(nid_in_journal(sum, i)) == val) + return i; + } + if (alloc && nats_in_cursum(sum) < NAT_JOURNAL_ENTRIES) + return update_nats_in_cursum(sum, 1); + } else if (type == SIT_JOURNAL) { + for (i = 0; i < sits_in_cursum(sum); i++) + if (le32_to_cpu(segno_in_journal(sum, i)) == val) + return i; + if (alloc && sits_in_cursum(sum) < SIT_JOURNAL_ENTRIES) + return update_sits_in_cursum(sum, 1); + } + return -1; +} + +static struct page *get_current_sit_page(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + struct sit_info *sit_i = SIT_I(sbi); + unsigned int offset = SIT_BLOCK_OFFSET(sit_i, segno); + block_t blk_addr = sit_i->sit_base_addr + offset; + + check_seg_range(sbi, segno); + + /* calculate sit block address */ + if (f2fs_test_bit(offset, sit_i->sit_bitmap)) + blk_addr += sit_i->sit_blocks; + + return get_meta_page(sbi, blk_addr); +} + +static struct page *get_next_sit_page(struct f2fs_sb_info *sbi, + unsigned int start) +{ + struct sit_info *sit_i = SIT_I(sbi); + struct page *src_page, *dst_page; + pgoff_t src_off, dst_off; + void *src_addr, *dst_addr; + + src_off = current_sit_addr(sbi, start); + dst_off = next_sit_addr(sbi, src_off); + + /* get current sit block page without lock */ + src_page = get_meta_page(sbi, src_off); + dst_page = grab_meta_page(sbi, dst_off); + f2fs_bug_on(PageDirty(src_page)); + + src_addr = page_address(src_page); + dst_addr = page_address(dst_page); + memcpy(dst_addr, src_addr, PAGE_CACHE_SIZE); + + set_page_dirty(dst_page); + f2fs_put_page(src_page, 1); + + set_to_next_sit(sit_i, start); + + return dst_page; +} + +static bool flush_sits_in_journal(struct f2fs_sb_info *sbi) +{ + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); + struct f2fs_summary_block *sum = curseg->sum_blk; + int i; + + /* + * If the journal area in the current summary is full of sit entries, + * all the sit entries will be flushed. Otherwise the sit entries + * are not able to replace with newly hot sit entries. + */ + if (sits_in_cursum(sum) >= SIT_JOURNAL_ENTRIES) { + for (i = sits_in_cursum(sum) - 1; i >= 0; i--) { + unsigned int segno; + segno = le32_to_cpu(segno_in_journal(sum, i)); + __mark_sit_entry_dirty(sbi, segno); + } + update_sits_in_cursum(sum, -sits_in_cursum(sum)); + return true; + } + return false; +} + +/* + * CP calls this function, which flushes SIT entries including sit_journal, + * and moves prefree segs to free segs. + */ +void flush_sit_entries(struct f2fs_sb_info *sbi) +{ + struct sit_info *sit_i = SIT_I(sbi); + unsigned long *bitmap = sit_i->dirty_sentries_bitmap; + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); + struct f2fs_summary_block *sum = curseg->sum_blk; + unsigned long nsegs = TOTAL_SEGS(sbi); + struct page *page = NULL; + struct f2fs_sit_block *raw_sit = NULL; + unsigned int start = 0, end = 0; + unsigned int segno = -1; + bool flushed; + + mutex_lock(&curseg->curseg_mutex); + mutex_lock(&sit_i->sentry_lock); + + /* + * "flushed" indicates whether sit entries in journal are flushed + * to the SIT area or not. + */ + flushed = flush_sits_in_journal(sbi); + + while ((segno = find_next_bit(bitmap, nsegs, segno + 1)) < nsegs) { + struct seg_entry *se = get_seg_entry(sbi, segno); + int sit_offset, offset; + + sit_offset = SIT_ENTRY_OFFSET(sit_i, segno); + + /* add discard candidates */ + if (SM_I(sbi)->nr_discards < SM_I(sbi)->max_discards) + add_discard_addrs(sbi, segno, se); + + if (flushed) + goto to_sit_page; + + offset = lookup_journal_in_cursum(sum, SIT_JOURNAL, segno, 1); + if (offset >= 0) { + segno_in_journal(sum, offset) = cpu_to_le32(segno); + seg_info_to_raw_sit(se, &sit_in_journal(sum, offset)); + goto flush_done; + } +to_sit_page: + if (!page || (start > segno) || (segno > end)) { + if (page) { + f2fs_put_page(page, 1); + page = NULL; + } + + start = START_SEGNO(sit_i, segno); + end = start + SIT_ENTRY_PER_BLOCK - 1; + + /* read sit block that will be updated */ + page = get_next_sit_page(sbi, start); + raw_sit = page_address(page); + } + + /* udpate entry in SIT block */ + seg_info_to_raw_sit(se, &raw_sit->entries[sit_offset]); +flush_done: + __clear_bit(segno, bitmap); + sit_i->dirty_sentries--; + } + mutex_unlock(&sit_i->sentry_lock); + mutex_unlock(&curseg->curseg_mutex); + + /* writeout last modified SIT block */ + f2fs_put_page(page, 1); + + set_prefree_as_free_segments(sbi); +} + +static int build_sit_info(struct f2fs_sb_info *sbi) +{ + struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + struct sit_info *sit_i; + unsigned int sit_segs, start; + char *src_bitmap, *dst_bitmap; + unsigned int bitmap_size; + + /* allocate memory for SIT information */ + sit_i = kzalloc(sizeof(struct sit_info), GFP_KERNEL); + if (!sit_i) + return -ENOMEM; + + SM_I(sbi)->sit_info = sit_i; + + sit_i->sentries = vzalloc(TOTAL_SEGS(sbi) * sizeof(struct seg_entry)); + if (!sit_i->sentries) + return -ENOMEM; + + bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); + sit_i->dirty_sentries_bitmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!sit_i->dirty_sentries_bitmap) + return -ENOMEM; + + for (start = 0; start < TOTAL_SEGS(sbi); start++) { + sit_i->sentries[start].cur_valid_map + = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); + sit_i->sentries[start].ckpt_valid_map + = kzalloc(SIT_VBLOCK_MAP_SIZE, GFP_KERNEL); + if (!sit_i->sentries[start].cur_valid_map + || !sit_i->sentries[start].ckpt_valid_map) + return -ENOMEM; + } + + if (sbi->segs_per_sec > 1) { + sit_i->sec_entries = vzalloc(TOTAL_SECS(sbi) * + sizeof(struct sec_entry)); + if (!sit_i->sec_entries) + return -ENOMEM; + } + + /* get information related with SIT */ + sit_segs = le32_to_cpu(raw_super->segment_count_sit) >> 1; + + /* setup SIT bitmap from ckeckpoint pack */ + bitmap_size = __bitmap_size(sbi, SIT_BITMAP); + src_bitmap = __bitmap_ptr(sbi, SIT_BITMAP); + + dst_bitmap = kmemdup(src_bitmap, bitmap_size, GFP_KERNEL); + if (!dst_bitmap) + return -ENOMEM; + + /* init SIT information */ + sit_i->s_ops = &default_salloc_ops; + + sit_i->sit_base_addr = le32_to_cpu(raw_super->sit_blkaddr); + sit_i->sit_blocks = sit_segs << sbi->log_blocks_per_seg; + sit_i->written_valid_blocks = le64_to_cpu(ckpt->valid_block_count); + sit_i->sit_bitmap = dst_bitmap; + sit_i->bitmap_size = bitmap_size; + sit_i->dirty_sentries = 0; + sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK; + sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time); + sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec; + mutex_init(&sit_i->sentry_lock); + return 0; +} + +static int build_free_segmap(struct f2fs_sb_info *sbi) +{ + struct f2fs_sm_info *sm_info = SM_I(sbi); + struct free_segmap_info *free_i; + unsigned int bitmap_size, sec_bitmap_size; + + /* allocate memory for free segmap information */ + free_i = kzalloc(sizeof(struct free_segmap_info), GFP_KERNEL); + if (!free_i) + return -ENOMEM; + + SM_I(sbi)->free_info = free_i; + + bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); + free_i->free_segmap = kmalloc(bitmap_size, GFP_KERNEL); + if (!free_i->free_segmap) + return -ENOMEM; + + sec_bitmap_size = f2fs_bitmap_size(TOTAL_SECS(sbi)); + free_i->free_secmap = kmalloc(sec_bitmap_size, GFP_KERNEL); + if (!free_i->free_secmap) + return -ENOMEM; + + /* set all segments as dirty temporarily */ + memset(free_i->free_segmap, 0xff, bitmap_size); + memset(free_i->free_secmap, 0xff, sec_bitmap_size); + + /* init free segmap information */ + free_i->start_segno = + (unsigned int) GET_SEGNO_FROM_SEG0(sbi, sm_info->main_blkaddr); + free_i->free_segments = 0; + free_i->free_sections = 0; + rwlock_init(&free_i->segmap_lock); + return 0; +} + +static int build_curseg(struct f2fs_sb_info *sbi) +{ + struct curseg_info *array; + int i; + + array = kcalloc(NR_CURSEG_TYPE, sizeof(*array), GFP_KERNEL); + if (!array) + return -ENOMEM; + + SM_I(sbi)->curseg_array = array; + + for (i = 0; i < NR_CURSEG_TYPE; i++) { + mutex_init(&array[i].curseg_mutex); + array[i].sum_blk = kzalloc(PAGE_CACHE_SIZE, GFP_KERNEL); + if (!array[i].sum_blk) + return -ENOMEM; + array[i].segno = NULL_SEGNO; + array[i].next_blkoff = 0; + } + return restore_curseg_summaries(sbi); +} + +static void build_sit_entries(struct f2fs_sb_info *sbi) +{ + struct sit_info *sit_i = SIT_I(sbi); + struct curseg_info *curseg = CURSEG_I(sbi, CURSEG_COLD_DATA); + struct f2fs_summary_block *sum = curseg->sum_blk; + int sit_blk_cnt = SIT_BLK_CNT(sbi); + unsigned int i, start, end; + unsigned int readed, start_blk = 0; + int nrpages = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); + + do { + readed = ra_meta_pages(sbi, start_blk, nrpages, META_SIT); + + start = start_blk * sit_i->sents_per_block; + end = (start_blk + readed) * sit_i->sents_per_block; + + for (; start < end && start < TOTAL_SEGS(sbi); start++) { + struct seg_entry *se = &sit_i->sentries[start]; + struct f2fs_sit_block *sit_blk; + struct f2fs_sit_entry sit; + struct page *page; + + mutex_lock(&curseg->curseg_mutex); + for (i = 0; i < sits_in_cursum(sum); i++) { + if (le32_to_cpu(segno_in_journal(sum, i)) + == start) { + sit = sit_in_journal(sum, i); + mutex_unlock(&curseg->curseg_mutex); + goto got_it; + } + } + mutex_unlock(&curseg->curseg_mutex); + + page = get_current_sit_page(sbi, start); + sit_blk = (struct f2fs_sit_block *)page_address(page); + sit = sit_blk->entries[SIT_ENTRY_OFFSET(sit_i, start)]; + f2fs_put_page(page, 1); +got_it: + check_block_count(sbi, start, &sit); + seg_info_from_raw_sit(se, &sit); + if (sbi->segs_per_sec > 1) { + struct sec_entry *e = get_sec_entry(sbi, start); + e->valid_blocks += se->valid_blocks; + } + } + start_blk += readed; + } while (start_blk < sit_blk_cnt); +} + +static void init_free_segmap(struct f2fs_sb_info *sbi) +{ + unsigned int start; + int type; + + for (start = 0; start < TOTAL_SEGS(sbi); start++) { + struct seg_entry *sentry = get_seg_entry(sbi, start); + if (!sentry->valid_blocks) + __set_free(sbi, start); + } + + /* set use the current segments */ + for (type = CURSEG_HOT_DATA; type <= CURSEG_COLD_NODE; type++) { + struct curseg_info *curseg_t = CURSEG_I(sbi, type); + __set_test_and_inuse(sbi, curseg_t->segno); + } +} + +static void init_dirty_segmap(struct f2fs_sb_info *sbi) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int segno = 0, offset = 0, total_segs = TOTAL_SEGS(sbi); + unsigned short valid_blocks; + + while (1) { + /* find dirty segment based on free segmap */ + segno = find_next_inuse(free_i, total_segs, offset); + if (segno >= total_segs) + break; + offset = segno + 1; + valid_blocks = get_valid_blocks(sbi, segno, 0); + if (valid_blocks >= sbi->blocks_per_seg || !valid_blocks) + continue; + mutex_lock(&dirty_i->seglist_lock); + __locate_dirty_segment(sbi, segno, DIRTY); + mutex_unlock(&dirty_i->seglist_lock); + } +} + +static int init_victim_secmap(struct f2fs_sb_info *sbi) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + unsigned int bitmap_size = f2fs_bitmap_size(TOTAL_SECS(sbi)); + + dirty_i->victim_secmap = kzalloc(bitmap_size, GFP_KERNEL); + if (!dirty_i->victim_secmap) + return -ENOMEM; + return 0; +} + +static int build_dirty_segmap(struct f2fs_sb_info *sbi) +{ + struct dirty_seglist_info *dirty_i; + unsigned int bitmap_size, i; + + /* allocate memory for dirty segments list information */ + dirty_i = kzalloc(sizeof(struct dirty_seglist_info), GFP_KERNEL); + if (!dirty_i) + return -ENOMEM; + + SM_I(sbi)->dirty_info = dirty_i; + mutex_init(&dirty_i->seglist_lock); + + bitmap_size = f2fs_bitmap_size(TOTAL_SEGS(sbi)); + + for (i = 0; i < NR_DIRTY_TYPE; i++) { + dirty_i->dirty_segmap[i] = kzalloc(bitmap_size, GFP_KERNEL); + if (!dirty_i->dirty_segmap[i]) + return -ENOMEM; + } + + init_dirty_segmap(sbi); + return init_victim_secmap(sbi); +} + +/* + * Update min, max modified time for cost-benefit GC algorithm + */ +static void init_min_max_mtime(struct f2fs_sb_info *sbi) +{ + struct sit_info *sit_i = SIT_I(sbi); + unsigned int segno; + + mutex_lock(&sit_i->sentry_lock); + + sit_i->min_mtime = LLONG_MAX; + + for (segno = 0; segno < TOTAL_SEGS(sbi); segno += sbi->segs_per_sec) { + unsigned int i; + unsigned long long mtime = 0; + + for (i = 0; i < sbi->segs_per_sec; i++) + mtime += get_seg_entry(sbi, segno + i)->mtime; + + mtime = div_u64(mtime, sbi->segs_per_sec); + + if (sit_i->min_mtime > mtime) + sit_i->min_mtime = mtime; + } + sit_i->max_mtime = get_mtime(sbi); + mutex_unlock(&sit_i->sentry_lock); +} + +int build_segment_manager(struct f2fs_sb_info *sbi) +{ + struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + dev_t dev = sbi->sb->s_bdev->bd_dev; + struct f2fs_sm_info *sm_info; + int err; + + sm_info = kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL); + if (!sm_info) + return -ENOMEM; + + /* init sm info */ + sbi->sm_info = sm_info; + sm_info->seg0_blkaddr = le32_to_cpu(raw_super->segment0_blkaddr); + sm_info->main_blkaddr = le32_to_cpu(raw_super->main_blkaddr); + sm_info->segment_count = le32_to_cpu(raw_super->segment_count); + sm_info->reserved_segments = le32_to_cpu(ckpt->rsvd_segment_count); + sm_info->ovp_segments = le32_to_cpu(ckpt->overprov_segment_count); + sm_info->main_segments = le32_to_cpu(raw_super->segment_count_main); + sm_info->ssa_blkaddr = le32_to_cpu(raw_super->ssa_blkaddr); + sm_info->rec_prefree_segments = sm_info->main_segments * + DEF_RECLAIM_PREFREE_SEGMENTS / 100; + sm_info->ipu_policy = F2FS_IPU_DISABLE; + sm_info->min_ipu_util = DEF_MIN_IPU_UTIL; + + INIT_LIST_HEAD(&sm_info->discard_list); + sm_info->nr_discards = 0; + sm_info->max_discards = 0; + + if (test_opt(sbi, FLUSH_MERGE) && !f2fs_readonly(sbi->sb)) { + spin_lock_init(&sm_info->issue_lock); + init_waitqueue_head(&sm_info->flush_wait_queue); + sm_info->f2fs_issue_flush = kthread_run(issue_flush_thread, sbi, + "f2fs_flush-%u:%u", MAJOR(dev), MINOR(dev)); + if (IS_ERR(sm_info->f2fs_issue_flush)) + return PTR_ERR(sm_info->f2fs_issue_flush); + } + + err = build_sit_info(sbi); + if (err) + return err; + err = build_free_segmap(sbi); + if (err) + return err; + err = build_curseg(sbi); + if (err) + return err; + + /* reinit free segmap based on SIT */ + build_sit_entries(sbi); + + init_free_segmap(sbi); + err = build_dirty_segmap(sbi); + if (err) + return err; + + init_min_max_mtime(sbi); + return 0; +} + +static void discard_dirty_segmap(struct f2fs_sb_info *sbi, + enum dirty_type dirty_type) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + + mutex_lock(&dirty_i->seglist_lock); + kfree(dirty_i->dirty_segmap[dirty_type]); + dirty_i->nr_dirty[dirty_type] = 0; + mutex_unlock(&dirty_i->seglist_lock); +} + +static void destroy_victim_secmap(struct f2fs_sb_info *sbi) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + kfree(dirty_i->victim_secmap); +} + +static void destroy_dirty_segmap(struct f2fs_sb_info *sbi) +{ + struct dirty_seglist_info *dirty_i = DIRTY_I(sbi); + int i; + + if (!dirty_i) + return; + + /* discard pre-free/dirty segments list */ + for (i = 0; i < NR_DIRTY_TYPE; i++) + discard_dirty_segmap(sbi, i); + + destroy_victim_secmap(sbi); + SM_I(sbi)->dirty_info = NULL; + kfree(dirty_i); +} + +static void destroy_curseg(struct f2fs_sb_info *sbi) +{ + struct curseg_info *array = SM_I(sbi)->curseg_array; + int i; + + if (!array) + return; + SM_I(sbi)->curseg_array = NULL; + for (i = 0; i < NR_CURSEG_TYPE; i++) + kfree(array[i].sum_blk); + kfree(array); +} + +static void destroy_free_segmap(struct f2fs_sb_info *sbi) +{ + struct free_segmap_info *free_i = SM_I(sbi)->free_info; + if (!free_i) + return; + SM_I(sbi)->free_info = NULL; + kfree(free_i->free_segmap); + kfree(free_i->free_secmap); + kfree(free_i); +} + +static void destroy_sit_info(struct f2fs_sb_info *sbi) +{ + struct sit_info *sit_i = SIT_I(sbi); + unsigned int start; + + if (!sit_i) + return; + + if (sit_i->sentries) { + for (start = 0; start < TOTAL_SEGS(sbi); start++) { + kfree(sit_i->sentries[start].cur_valid_map); + kfree(sit_i->sentries[start].ckpt_valid_map); + } + } + vfree(sit_i->sentries); + vfree(sit_i->sec_entries); + kfree(sit_i->dirty_sentries_bitmap); + + SM_I(sbi)->sit_info = NULL; + kfree(sit_i->sit_bitmap); + kfree(sit_i); +} + +void destroy_segment_manager(struct f2fs_sb_info *sbi) +{ + struct f2fs_sm_info *sm_info = SM_I(sbi); + if (!sm_info) + return; + if (sm_info->f2fs_issue_flush) + kthread_stop(sm_info->f2fs_issue_flush); + destroy_dirty_segmap(sbi); + destroy_curseg(sbi); + destroy_free_segmap(sbi); + destroy_sit_info(sbi); + sbi->sm_info = NULL; + kfree(sm_info); +} + +int __init create_segment_manager_caches(void) +{ + discard_entry_slab = f2fs_kmem_cache_create("discard_entry", + sizeof(struct discard_entry)); + if (!discard_entry_slab) + return -ENOMEM; + return 0; +} + +void destroy_segment_manager_caches(void) +{ + kmem_cache_destroy(discard_entry_slab); +} diff --git a/fs/f2fs/segment.h b/fs/f2fs/segment.h new file mode 100644 index 00000000000..7091204680f --- /dev/null +++ b/fs/f2fs/segment.h @@ -0,0 +1,709 @@ +/* + * fs/f2fs/segment.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include + +/* constant macro */ +#define NULL_SEGNO ((unsigned int)(~0)) +#define NULL_SECNO ((unsigned int)(~0)) + +#define DEF_RECLAIM_PREFREE_SEGMENTS 5 /* 5% over total segments */ + +/* L: Logical segment # in volume, R: Relative segment # in main area */ +#define GET_L2R_SEGNO(free_i, segno) (segno - free_i->start_segno) +#define GET_R2L_SEGNO(free_i, segno) (segno + free_i->start_segno) + +#define IS_DATASEG(t) (t <= CURSEG_COLD_DATA) +#define IS_NODESEG(t) (t >= CURSEG_HOT_NODE) + +#define IS_CURSEG(sbi, seg) \ + ((seg == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno) || \ + (seg == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno) || \ + (seg == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno) || \ + (seg == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno) || \ + (seg == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno) || \ + (seg == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno)) + +#define IS_CURSEC(sbi, secno) \ + ((secno == CURSEG_I(sbi, CURSEG_HOT_DATA)->segno / \ + sbi->segs_per_sec) || \ + (secno == CURSEG_I(sbi, CURSEG_WARM_DATA)->segno / \ + sbi->segs_per_sec) || \ + (secno == CURSEG_I(sbi, CURSEG_COLD_DATA)->segno / \ + sbi->segs_per_sec) || \ + (secno == CURSEG_I(sbi, CURSEG_HOT_NODE)->segno / \ + sbi->segs_per_sec) || \ + (secno == CURSEG_I(sbi, CURSEG_WARM_NODE)->segno / \ + sbi->segs_per_sec) || \ + (secno == CURSEG_I(sbi, CURSEG_COLD_NODE)->segno / \ + sbi->segs_per_sec)) \ + +#define START_BLOCK(sbi, segno) \ + (SM_I(sbi)->seg0_blkaddr + \ + (GET_R2L_SEGNO(FREE_I(sbi), segno) << sbi->log_blocks_per_seg)) +#define NEXT_FREE_BLKADDR(sbi, curseg) \ + (START_BLOCK(sbi, curseg->segno) + curseg->next_blkoff) + +#define MAIN_BASE_BLOCK(sbi) (SM_I(sbi)->main_blkaddr) + +#define GET_SEGOFF_FROM_SEG0(sbi, blk_addr) \ + ((blk_addr) - SM_I(sbi)->seg0_blkaddr) +#define GET_SEGNO_FROM_SEG0(sbi, blk_addr) \ + (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) >> sbi->log_blocks_per_seg) +#define GET_BLKOFF_FROM_SEG0(sbi, blk_addr) \ + (GET_SEGOFF_FROM_SEG0(sbi, blk_addr) & (sbi->blocks_per_seg - 1)) + +#define GET_SEGNO(sbi, blk_addr) \ + (((blk_addr == NULL_ADDR) || (blk_addr == NEW_ADDR)) ? \ + NULL_SEGNO : GET_L2R_SEGNO(FREE_I(sbi), \ + GET_SEGNO_FROM_SEG0(sbi, blk_addr))) +#define GET_SECNO(sbi, segno) \ + ((segno) / sbi->segs_per_sec) +#define GET_ZONENO_FROM_SEGNO(sbi, segno) \ + ((segno / sbi->segs_per_sec) / sbi->secs_per_zone) + +#define GET_SUM_BLOCK(sbi, segno) \ + ((sbi->sm_info->ssa_blkaddr) + segno) + +#define GET_SUM_TYPE(footer) ((footer)->entry_type) +#define SET_SUM_TYPE(footer, type) ((footer)->entry_type = type) + +#define SIT_ENTRY_OFFSET(sit_i, segno) \ + (segno % sit_i->sents_per_block) +#define SIT_BLOCK_OFFSET(sit_i, segno) \ + (segno / SIT_ENTRY_PER_BLOCK) +#define START_SEGNO(sit_i, segno) \ + (SIT_BLOCK_OFFSET(sit_i, segno) * SIT_ENTRY_PER_BLOCK) +#define SIT_BLK_CNT(sbi) \ + ((TOTAL_SEGS(sbi) + SIT_ENTRY_PER_BLOCK - 1) / SIT_ENTRY_PER_BLOCK) +#define f2fs_bitmap_size(nr) \ + (BITS_TO_LONGS(nr) * sizeof(unsigned long)) +#define TOTAL_SEGS(sbi) (SM_I(sbi)->main_segments) +#define TOTAL_SECS(sbi) (sbi->total_sections) + +#define SECTOR_FROM_BLOCK(sbi, blk_addr) \ + (((sector_t)blk_addr) << (sbi)->log_sectors_per_block) +#define SECTOR_TO_BLOCK(sbi, sectors) \ + (sectors >> (sbi)->log_sectors_per_block) +#define MAX_BIO_BLOCKS(max_hw_blocks) \ + (min((int)max_hw_blocks, BIO_MAX_PAGES)) + +/* + * indicate a block allocation direction: RIGHT and LEFT. + * RIGHT means allocating new sections towards the end of volume. + * LEFT means the opposite direction. + */ +enum { + ALLOC_RIGHT = 0, + ALLOC_LEFT +}; + +/* + * In the victim_sel_policy->alloc_mode, there are two block allocation modes. + * LFS writes data sequentially with cleaning operations. + * SSR (Slack Space Recycle) reuses obsolete space without cleaning operations. + */ +enum { + LFS = 0, + SSR +}; + +/* + * In the victim_sel_policy->gc_mode, there are two gc, aka cleaning, modes. + * GC_CB is based on cost-benefit algorithm. + * GC_GREEDY is based on greedy algorithm. + */ +enum { + GC_CB = 0, + GC_GREEDY +}; + +/* + * BG_GC means the background cleaning job. + * FG_GC means the on-demand cleaning job. + */ +enum { + BG_GC = 0, + FG_GC +}; + +/* for a function parameter to select a victim segment */ +struct victim_sel_policy { + int alloc_mode; /* LFS or SSR */ + int gc_mode; /* GC_CB or GC_GREEDY */ + unsigned long *dirty_segmap; /* dirty segment bitmap */ + unsigned int max_search; /* maximum # of segments to search */ + unsigned int offset; /* last scanned bitmap offset */ + unsigned int ofs_unit; /* bitmap search unit */ + unsigned int min_cost; /* minimum cost */ + unsigned int min_segno; /* segment # having min. cost */ +}; + +struct seg_entry { + unsigned short valid_blocks; /* # of valid blocks */ + unsigned char *cur_valid_map; /* validity bitmap of blocks */ + /* + * # of valid blocks and the validity bitmap stored in the the last + * checkpoint pack. This information is used by the SSR mode. + */ + unsigned short ckpt_valid_blocks; + unsigned char *ckpt_valid_map; + unsigned char type; /* segment type like CURSEG_XXX_TYPE */ + unsigned long long mtime; /* modification time of the segment */ +}; + +struct sec_entry { + unsigned int valid_blocks; /* # of valid blocks in a section */ +}; + +struct segment_allocation { + void (*allocate_segment)(struct f2fs_sb_info *, int, bool); +}; + +struct sit_info { + const struct segment_allocation *s_ops; + + block_t sit_base_addr; /* start block address of SIT area */ + block_t sit_blocks; /* # of blocks used by SIT area */ + block_t written_valid_blocks; /* # of valid blocks in main area */ + char *sit_bitmap; /* SIT bitmap pointer */ + unsigned int bitmap_size; /* SIT bitmap size */ + + unsigned long *dirty_sentries_bitmap; /* bitmap for dirty sentries */ + unsigned int dirty_sentries; /* # of dirty sentries */ + unsigned int sents_per_block; /* # of SIT entries per block */ + struct mutex sentry_lock; /* to protect SIT cache */ + struct seg_entry *sentries; /* SIT segment-level cache */ + struct sec_entry *sec_entries; /* SIT section-level cache */ + + /* for cost-benefit algorithm in cleaning procedure */ + unsigned long long elapsed_time; /* elapsed time after mount */ + unsigned long long mounted_time; /* mount time */ + unsigned long long min_mtime; /* min. modification time */ + unsigned long long max_mtime; /* max. modification time */ +}; + +struct free_segmap_info { + unsigned int start_segno; /* start segment number logically */ + unsigned int free_segments; /* # of free segments */ + unsigned int free_sections; /* # of free sections */ + rwlock_t segmap_lock; /* free segmap lock */ + unsigned long *free_segmap; /* free segment bitmap */ + unsigned long *free_secmap; /* free section bitmap */ +}; + +/* Notice: The order of dirty type is same with CURSEG_XXX in f2fs.h */ +enum dirty_type { + DIRTY_HOT_DATA, /* dirty segments assigned as hot data logs */ + DIRTY_WARM_DATA, /* dirty segments assigned as warm data logs */ + DIRTY_COLD_DATA, /* dirty segments assigned as cold data logs */ + DIRTY_HOT_NODE, /* dirty segments assigned as hot node logs */ + DIRTY_WARM_NODE, /* dirty segments assigned as warm node logs */ + DIRTY_COLD_NODE, /* dirty segments assigned as cold node logs */ + DIRTY, /* to count # of dirty segments */ + PRE, /* to count # of entirely obsolete segments */ + NR_DIRTY_TYPE +}; + +struct dirty_seglist_info { + const struct victim_selection *v_ops; /* victim selction operation */ + unsigned long *dirty_segmap[NR_DIRTY_TYPE]; + struct mutex seglist_lock; /* lock for segment bitmaps */ + int nr_dirty[NR_DIRTY_TYPE]; /* # of dirty segments */ + unsigned long *victim_secmap; /* background GC victims */ +}; + +/* victim selection function for cleaning and SSR */ +struct victim_selection { + int (*get_victim)(struct f2fs_sb_info *, unsigned int *, + int, int, char); +}; + +/* for active log information */ +struct curseg_info { + struct mutex curseg_mutex; /* lock for consistency */ + struct f2fs_summary_block *sum_blk; /* cached summary block */ + unsigned char alloc_type; /* current allocation type */ + unsigned int segno; /* current segment number */ + unsigned short next_blkoff; /* next block offset to write */ + unsigned int zone; /* current zone number */ + unsigned int next_segno; /* preallocated segment */ +}; + +/* + * inline functions + */ +static inline struct curseg_info *CURSEG_I(struct f2fs_sb_info *sbi, int type) +{ + return (struct curseg_info *)(SM_I(sbi)->curseg_array + type); +} + +static inline struct seg_entry *get_seg_entry(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + struct sit_info *sit_i = SIT_I(sbi); + return &sit_i->sentries[segno]; +} + +static inline struct sec_entry *get_sec_entry(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + struct sit_info *sit_i = SIT_I(sbi); + return &sit_i->sec_entries[GET_SECNO(sbi, segno)]; +} + +static inline unsigned int get_valid_blocks(struct f2fs_sb_info *sbi, + unsigned int segno, int section) +{ + /* + * In order to get # of valid blocks in a section instantly from many + * segments, f2fs manages two counting structures separately. + */ + if (section > 1) + return get_sec_entry(sbi, segno)->valid_blocks; + else + return get_seg_entry(sbi, segno)->valid_blocks; +} + +static inline void seg_info_from_raw_sit(struct seg_entry *se, + struct f2fs_sit_entry *rs) +{ + se->valid_blocks = GET_SIT_VBLOCKS(rs); + se->ckpt_valid_blocks = GET_SIT_VBLOCKS(rs); + memcpy(se->cur_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); + memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); + se->type = GET_SIT_TYPE(rs); + se->mtime = le64_to_cpu(rs->mtime); +} + +static inline void seg_info_to_raw_sit(struct seg_entry *se, + struct f2fs_sit_entry *rs) +{ + unsigned short raw_vblocks = (se->type << SIT_VBLOCKS_SHIFT) | + se->valid_blocks; + rs->vblocks = cpu_to_le16(raw_vblocks); + memcpy(rs->valid_map, se->cur_valid_map, SIT_VBLOCK_MAP_SIZE); + memcpy(se->ckpt_valid_map, rs->valid_map, SIT_VBLOCK_MAP_SIZE); + se->ckpt_valid_blocks = se->valid_blocks; + rs->mtime = cpu_to_le64(se->mtime); +} + +static inline unsigned int find_next_inuse(struct free_segmap_info *free_i, + unsigned int max, unsigned int segno) +{ + unsigned int ret; + read_lock(&free_i->segmap_lock); + ret = find_next_bit(free_i->free_segmap, max, segno); + read_unlock(&free_i->segmap_lock); + return ret; +} + +static inline void __set_free(struct f2fs_sb_info *sbi, unsigned int segno) +{ + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int secno = segno / sbi->segs_per_sec; + unsigned int start_segno = secno * sbi->segs_per_sec; + unsigned int next; + + write_lock(&free_i->segmap_lock); + clear_bit(segno, free_i->free_segmap); + free_i->free_segments++; + + next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), start_segno); + if (next >= start_segno + sbi->segs_per_sec) { + clear_bit(secno, free_i->free_secmap); + free_i->free_sections++; + } + write_unlock(&free_i->segmap_lock); +} + +static inline void __set_inuse(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int secno = segno / sbi->segs_per_sec; + set_bit(segno, free_i->free_segmap); + free_i->free_segments--; + if (!test_and_set_bit(secno, free_i->free_secmap)) + free_i->free_sections--; +} + +static inline void __set_test_and_free(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int secno = segno / sbi->segs_per_sec; + unsigned int start_segno = secno * sbi->segs_per_sec; + unsigned int next; + + write_lock(&free_i->segmap_lock); + if (test_and_clear_bit(segno, free_i->free_segmap)) { + free_i->free_segments++; + + next = find_next_bit(free_i->free_segmap, TOTAL_SEGS(sbi), + start_segno); + if (next >= start_segno + sbi->segs_per_sec) { + if (test_and_clear_bit(secno, free_i->free_secmap)) + free_i->free_sections++; + } + } + write_unlock(&free_i->segmap_lock); +} + +static inline void __set_test_and_inuse(struct f2fs_sb_info *sbi, + unsigned int segno) +{ + struct free_segmap_info *free_i = FREE_I(sbi); + unsigned int secno = segno / sbi->segs_per_sec; + write_lock(&free_i->segmap_lock); + if (!test_and_set_bit(segno, free_i->free_segmap)) { + free_i->free_segments--; + if (!test_and_set_bit(secno, free_i->free_secmap)) + free_i->free_sections--; + } + write_unlock(&free_i->segmap_lock); +} + +static inline void get_sit_bitmap(struct f2fs_sb_info *sbi, + void *dst_addr) +{ + struct sit_info *sit_i = SIT_I(sbi); + memcpy(dst_addr, sit_i->sit_bitmap, sit_i->bitmap_size); +} + +static inline block_t written_block_count(struct f2fs_sb_info *sbi) +{ + return SIT_I(sbi)->written_valid_blocks; +} + +static inline unsigned int free_segments(struct f2fs_sb_info *sbi) +{ + return FREE_I(sbi)->free_segments; +} + +static inline int reserved_segments(struct f2fs_sb_info *sbi) +{ + return SM_I(sbi)->reserved_segments; +} + +static inline unsigned int free_sections(struct f2fs_sb_info *sbi) +{ + return FREE_I(sbi)->free_sections; +} + +static inline unsigned int prefree_segments(struct f2fs_sb_info *sbi) +{ + return DIRTY_I(sbi)->nr_dirty[PRE]; +} + +static inline unsigned int dirty_segments(struct f2fs_sb_info *sbi) +{ + return DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_DATA] + + DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_DATA] + + DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_DATA] + + DIRTY_I(sbi)->nr_dirty[DIRTY_HOT_NODE] + + DIRTY_I(sbi)->nr_dirty[DIRTY_WARM_NODE] + + DIRTY_I(sbi)->nr_dirty[DIRTY_COLD_NODE]; +} + +static inline int overprovision_segments(struct f2fs_sb_info *sbi) +{ + return SM_I(sbi)->ovp_segments; +} + +static inline int overprovision_sections(struct f2fs_sb_info *sbi) +{ + return ((unsigned int) overprovision_segments(sbi)) / sbi->segs_per_sec; +} + +static inline int reserved_sections(struct f2fs_sb_info *sbi) +{ + return ((unsigned int) reserved_segments(sbi)) / sbi->segs_per_sec; +} + +static inline bool need_SSR(struct f2fs_sb_info *sbi) +{ + return (prefree_segments(sbi) / sbi->segs_per_sec) + + free_sections(sbi) < overprovision_sections(sbi); +} + +static inline bool has_not_enough_free_secs(struct f2fs_sb_info *sbi, int freed) +{ + int node_secs = get_blocktype_secs(sbi, F2FS_DIRTY_NODES); + int dent_secs = get_blocktype_secs(sbi, F2FS_DIRTY_DENTS); + + if (unlikely(sbi->por_doing)) + return false; + + return (free_sections(sbi) + freed) <= (node_secs + 2 * dent_secs + + reserved_sections(sbi)); +} + +static inline bool excess_prefree_segs(struct f2fs_sb_info *sbi) +{ + return prefree_segments(sbi) > SM_I(sbi)->rec_prefree_segments; +} + +static inline int utilization(struct f2fs_sb_info *sbi) +{ + return div_u64((u64)valid_user_blocks(sbi) * 100, + sbi->user_block_count); +} + +/* + * Sometimes f2fs may be better to drop out-of-place update policy. + * And, users can control the policy through sysfs entries. + * There are five policies with triggering conditions as follows. + * F2FS_IPU_FORCE - all the time, + * F2FS_IPU_SSR - if SSR mode is activated, + * F2FS_IPU_UTIL - if FS utilization is over threashold, + * F2FS_IPU_SSR_UTIL - if SSR mode is activated and FS utilization is over + * threashold, + * F2FS_IPUT_DISABLE - disable IPU. (=default option) + */ +#define DEF_MIN_IPU_UTIL 70 + +enum { + F2FS_IPU_FORCE, + F2FS_IPU_SSR, + F2FS_IPU_UTIL, + F2FS_IPU_SSR_UTIL, + F2FS_IPU_DISABLE, +}; + +static inline bool need_inplace_update(struct inode *inode) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + + /* IPU can be done only for the user data */ + if (S_ISDIR(inode->i_mode)) + return false; + + switch (SM_I(sbi)->ipu_policy) { + case F2FS_IPU_FORCE: + return true; + case F2FS_IPU_SSR: + if (need_SSR(sbi)) + return true; + break; + case F2FS_IPU_UTIL: + if (utilization(sbi) > SM_I(sbi)->min_ipu_util) + return true; + break; + case F2FS_IPU_SSR_UTIL: + if (need_SSR(sbi) && utilization(sbi) > SM_I(sbi)->min_ipu_util) + return true; + break; + case F2FS_IPU_DISABLE: + break; + } + return false; +} + +static inline unsigned int curseg_segno(struct f2fs_sb_info *sbi, + int type) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + return curseg->segno; +} + +static inline unsigned char curseg_alloc_type(struct f2fs_sb_info *sbi, + int type) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + return curseg->alloc_type; +} + +static inline unsigned short curseg_blkoff(struct f2fs_sb_info *sbi, int type) +{ + struct curseg_info *curseg = CURSEG_I(sbi, type); + return curseg->next_blkoff; +} + +#ifdef CONFIG_F2FS_CHECK_FS +static inline void check_seg_range(struct f2fs_sb_info *sbi, unsigned int segno) +{ + unsigned int end_segno = SM_I(sbi)->segment_count - 1; + BUG_ON(segno > end_segno); +} + +static inline void verify_block_addr(struct f2fs_sb_info *sbi, block_t blk_addr) +{ + struct f2fs_sm_info *sm_info = SM_I(sbi); + block_t total_blks = sm_info->segment_count << sbi->log_blocks_per_seg; + block_t start_addr = sm_info->seg0_blkaddr; + block_t end_addr = start_addr + total_blks - 1; + BUG_ON(blk_addr < start_addr); + BUG_ON(blk_addr > end_addr); +} + +/* + * Summary block is always treated as invalid block + */ +static inline void check_block_count(struct f2fs_sb_info *sbi, + int segno, struct f2fs_sit_entry *raw_sit) +{ + struct f2fs_sm_info *sm_info = SM_I(sbi); + unsigned int end_segno = sm_info->segment_count - 1; + bool is_valid = test_bit_le(0, raw_sit->valid_map) ? true : false; + int valid_blocks = 0; + int cur_pos = 0, next_pos; + + /* check segment usage */ + BUG_ON(GET_SIT_VBLOCKS(raw_sit) > sbi->blocks_per_seg); + + /* check boundary of a given segment number */ + BUG_ON(segno > end_segno); + + /* check bitmap with valid block count */ + do { + if (is_valid) { + next_pos = find_next_zero_bit_le(&raw_sit->valid_map, + sbi->blocks_per_seg, + cur_pos); + valid_blocks += next_pos - cur_pos; + } else + next_pos = find_next_bit_le(&raw_sit->valid_map, + sbi->blocks_per_seg, + cur_pos); + cur_pos = next_pos; + is_valid = !is_valid; + } while (cur_pos < sbi->blocks_per_seg); + BUG_ON(GET_SIT_VBLOCKS(raw_sit) != valid_blocks); +} +#else +#define check_seg_range(sbi, segno) +#define verify_block_addr(sbi, blk_addr) +#define check_block_count(sbi, segno, raw_sit) +#endif + +static inline pgoff_t current_sit_addr(struct f2fs_sb_info *sbi, + unsigned int start) +{ + struct sit_info *sit_i = SIT_I(sbi); + unsigned int offset = SIT_BLOCK_OFFSET(sit_i, start); + block_t blk_addr = sit_i->sit_base_addr + offset; + + check_seg_range(sbi, start); + + /* calculate sit block address */ + if (f2fs_test_bit(offset, sit_i->sit_bitmap)) + blk_addr += sit_i->sit_blocks; + + return blk_addr; +} + +static inline pgoff_t next_sit_addr(struct f2fs_sb_info *sbi, + pgoff_t block_addr) +{ + struct sit_info *sit_i = SIT_I(sbi); + block_addr -= sit_i->sit_base_addr; + if (block_addr < sit_i->sit_blocks) + block_addr += sit_i->sit_blocks; + else + block_addr -= sit_i->sit_blocks; + + return block_addr + sit_i->sit_base_addr; +} + +static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start) +{ + unsigned int block_off = SIT_BLOCK_OFFSET(sit_i, start); + + if (f2fs_test_bit(block_off, sit_i->sit_bitmap)) + f2fs_clear_bit(block_off, sit_i->sit_bitmap); + else + f2fs_set_bit(block_off, sit_i->sit_bitmap); +} + +static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi) +{ + struct sit_info *sit_i = SIT_I(sbi); + return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec - + sit_i->mounted_time; +} + +static inline void set_summary(struct f2fs_summary *sum, nid_t nid, + unsigned int ofs_in_node, unsigned char version) +{ + sum->nid = cpu_to_le32(nid); + sum->ofs_in_node = cpu_to_le16(ofs_in_node); + sum->version = version; +} + +static inline block_t start_sum_block(struct f2fs_sb_info *sbi) +{ + return __start_cp_addr(sbi) + + le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_start_sum); +} + +static inline block_t sum_blk_addr(struct f2fs_sb_info *sbi, int base, int type) +{ + return __start_cp_addr(sbi) + + le32_to_cpu(F2FS_CKPT(sbi)->cp_pack_total_block_count) + - (base + 1) + type; +} + +static inline bool sec_usage_check(struct f2fs_sb_info *sbi, unsigned int secno) +{ + if (IS_CURSEC(sbi, secno) || (sbi->cur_victim_sec == secno)) + return true; + return false; +} + +static inline unsigned int max_hw_blocks(struct f2fs_sb_info *sbi) +{ + struct block_device *bdev = sbi->sb->s_bdev; + struct request_queue *q = bdev_get_queue(bdev); + return SECTOR_TO_BLOCK(sbi, queue_max_sectors(q)); +} + +/* + * It is very important to gather dirty pages and write at once, so that we can + * submit a big bio without interfering other data writes. + * By default, 512 pages for directory data, + * 512 pages (2MB) * 3 for three types of nodes, and + * max_bio_blocks for meta are set. + */ +static inline int nr_pages_to_skip(struct f2fs_sb_info *sbi, int type) +{ + if (type == DATA) + return sbi->blocks_per_seg; + else if (type == NODE) + return 3 * sbi->blocks_per_seg; + else if (type == META) + return MAX_BIO_BLOCKS(max_hw_blocks(sbi)); + else + return 0; +} + +/* + * When writing pages, it'd better align nr_to_write for segment size. + */ +static inline long nr_pages_to_write(struct f2fs_sb_info *sbi, int type, + struct writeback_control *wbc) +{ + long nr_to_write, desired; + + if (wbc->sync_mode != WB_SYNC_NONE) + return 0; + + nr_to_write = wbc->nr_to_write; + + if (type == DATA) + desired = 4096; + else if (type == NODE) + desired = 3 * max_hw_blocks(sbi); + else + desired = MAX_BIO_BLOCKS(max_hw_blocks(sbi)); + + wbc->nr_to_write = desired; + return desired - nr_to_write; +} diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c new file mode 100644 index 00000000000..87f04bbcfa7 --- /dev/null +++ b/fs/f2fs/super.c @@ -0,0 +1,1312 @@ +/* + * fs/f2fs/super.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "f2fs.h" +#include "node.h" +#include "segment.h" +#include "xattr.h" +#include "gc.h" + +#define CREATE_TRACE_POINTS +#include + +static struct proc_dir_entry *f2fs_proc_root; +static struct kmem_cache *f2fs_inode_cachep; +static struct kset *f2fs_kset; + +enum { + Opt_gc_background, + Opt_disable_roll_forward, + Opt_discard, + Opt_noheap, + Opt_user_xattr, + Opt_nouser_xattr, + Opt_acl, + Opt_noacl, + Opt_active_logs, + Opt_disable_ext_identify, + Opt_inline_xattr, + Opt_android_emu, + Opt_err_continue, + Opt_err_panic, + Opt_err_recover, + Opt_inline_data, + Opt_flush_merge, + Opt_err, +}; + +static match_table_t f2fs_tokens = { + {Opt_gc_background, "background_gc=%s"}, + {Opt_disable_roll_forward, "disable_roll_forward"}, + {Opt_discard, "discard"}, + {Opt_noheap, "no_heap"}, + {Opt_user_xattr, "user_xattr"}, + {Opt_nouser_xattr, "nouser_xattr"}, + {Opt_acl, "acl"}, + {Opt_noacl, "noacl"}, + {Opt_active_logs, "active_logs=%u"}, + {Opt_disable_ext_identify, "disable_ext_identify"}, + {Opt_inline_xattr, "inline_xattr"}, + {Opt_android_emu, "android_emu=%s"}, + {Opt_err_continue, "errors=continue"}, + {Opt_err_panic, "errors=panic"}, + {Opt_err_recover, "errors=recover"}, + {Opt_inline_data, "inline_data"}, + {Opt_flush_merge, "flush_merge"}, + {Opt_err, NULL}, +}; + +/* Sysfs support for f2fs */ +enum { + GC_THREAD, /* struct f2fs_gc_thread */ + SM_INFO, /* struct f2fs_sm_info */ + NM_INFO, /* struct f2fs_nm_info */ + F2FS_SBI, /* struct f2fs_sb_info */ +}; + +struct f2fs_attr { + struct attribute attr; + ssize_t (*show)(struct f2fs_attr *, struct f2fs_sb_info *, char *); + ssize_t (*store)(struct f2fs_attr *, struct f2fs_sb_info *, + const char *, size_t); + int struct_type; + int offset; +}; + +static unsigned char *__struct_ptr(struct f2fs_sb_info *sbi, int struct_type) +{ + if (struct_type == GC_THREAD) + return (unsigned char *)sbi->gc_thread; + else if (struct_type == SM_INFO) + return (unsigned char *)SM_I(sbi); + else if (struct_type == NM_INFO) + return (unsigned char *)NM_I(sbi); + else if (struct_type == F2FS_SBI) + return (unsigned char *)sbi; + return NULL; +} + +static ssize_t f2fs_sbi_show(struct f2fs_attr *a, + struct f2fs_sb_info *sbi, char *buf) +{ + unsigned char *ptr = NULL; + unsigned int *ui; + + ptr = __struct_ptr(sbi, a->struct_type); + if (!ptr) + return -EINVAL; + + ui = (unsigned int *)(ptr + a->offset); + + return snprintf(buf, PAGE_SIZE, "%u\n", *ui); +} + +static ssize_t f2fs_sbi_store(struct f2fs_attr *a, + struct f2fs_sb_info *sbi, + const char *buf, size_t count) +{ + unsigned char *ptr; + unsigned long t; + unsigned int *ui; + ssize_t ret; + + ptr = __struct_ptr(sbi, a->struct_type); + if (!ptr) + return -EINVAL; + + ui = (unsigned int *)(ptr + a->offset); + + ret = kstrtoul(skip_spaces(buf), 0, &t); + if (ret < 0) + return ret; + *ui = t; + return count; +} + +static ssize_t f2fs_attr_show(struct kobject *kobj, + struct attribute *attr, char *buf) +{ + struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, + s_kobj); + struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); + + return a->show ? a->show(a, sbi, buf) : 0; +} + +static ssize_t f2fs_attr_store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t len) +{ + struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, + s_kobj); + struct f2fs_attr *a = container_of(attr, struct f2fs_attr, attr); + + return a->store ? a->store(a, sbi, buf, len) : 0; +} + +static void f2fs_sb_release(struct kobject *kobj) +{ + struct f2fs_sb_info *sbi = container_of(kobj, struct f2fs_sb_info, + s_kobj); + complete(&sbi->s_kobj_unregister); +} + +#define F2FS_ATTR_OFFSET(_struct_type, _name, _mode, _show, _store, _offset) \ +static struct f2fs_attr f2fs_attr_##_name = { \ + .attr = {.name = __stringify(_name), .mode = _mode }, \ + .show = _show, \ + .store = _store, \ + .struct_type = _struct_type, \ + .offset = _offset \ +} + +#define F2FS_RW_ATTR(struct_type, struct_name, name, elname) \ + F2FS_ATTR_OFFSET(struct_type, name, 0644, \ + f2fs_sbi_show, f2fs_sbi_store, \ + offsetof(struct struct_name, elname)) + +F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_min_sleep_time, min_sleep_time); +F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_max_sleep_time, max_sleep_time); +F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_no_gc_sleep_time, no_gc_sleep_time); +F2FS_RW_ATTR(GC_THREAD, f2fs_gc_kthread, gc_idle, gc_idle); +F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, reclaim_segments, rec_prefree_segments); +F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, max_small_discards, max_discards); +F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, ipu_policy, ipu_policy); +F2FS_RW_ATTR(SM_INFO, f2fs_sm_info, min_ipu_util, min_ipu_util); +F2FS_RW_ATTR(NM_INFO, f2fs_nm_info, ram_thresh, ram_thresh); +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, max_victim_search, max_victim_search); +F2FS_RW_ATTR(F2FS_SBI, f2fs_sb_info, dir_level, dir_level); + +#define ATTR_LIST(name) (&f2fs_attr_##name.attr) +static struct attribute *f2fs_attrs[] = { + ATTR_LIST(gc_min_sleep_time), + ATTR_LIST(gc_max_sleep_time), + ATTR_LIST(gc_no_gc_sleep_time), + ATTR_LIST(gc_idle), + ATTR_LIST(reclaim_segments), + ATTR_LIST(max_small_discards), + ATTR_LIST(ipu_policy), + ATTR_LIST(min_ipu_util), + ATTR_LIST(max_victim_search), + ATTR_LIST(dir_level), + ATTR_LIST(ram_thresh), + NULL, +}; + +static const struct sysfs_ops f2fs_attr_ops = { + .show = f2fs_attr_show, + .store = f2fs_attr_store, +}; + +static struct kobj_type f2fs_ktype = { + .default_attrs = f2fs_attrs, + .sysfs_ops = &f2fs_attr_ops, + .release = f2fs_sb_release, +}; + +void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...) +{ + struct va_format vaf; + va_list args; + + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + printk("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf); + va_end(args); +} + +static void init_once(void *foo) +{ + struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo; + + inode_init_once(&fi->vfs_inode); +} + +static int parse_android_emu(struct f2fs_sb_info *sbi, char *args) +{ + char *sep = args; + char *sepres; + int ret; + + if (!sep) + return -EINVAL; + + sepres = strsep(&sep, ":"); + if (!sep) + return -EINVAL; + ret = kstrtou32(sepres, 0, &sbi->android_emu_uid); + if (ret) + return ret; + + sepres = strsep(&sep, ":"); + if (!sep) + return -EINVAL; + ret = kstrtou32(sepres, 0, &sbi->android_emu_gid); + if (ret) + return ret; + + sepres = strsep(&sep, ":"); + ret = kstrtou16(sepres, 8, &sbi->android_emu_mode); + if (ret) + return ret; + + if (sep && strstr(sep, "nocase")) + sbi->android_emu_flags = F2FS_ANDROID_EMU_NOCASE; + + return 0; +} + +static int parse_options(struct super_block *sb, char *options) +{ + struct f2fs_sb_info *sbi = F2FS_SB(sb); + substring_t args[MAX_OPT_ARGS]; + char *p, *name; + int arg = 0; + + if (!options) + return 0; + + while ((p = strsep(&options, ",")) != NULL) { + int token; + if (!*p) + continue; + /* + * Initialize args struct so we know whether arg was + * found; some options take optional arguments. + */ + args[0].to = args[0].from = NULL; + token = match_token(p, f2fs_tokens, args); + + switch (token) { + case Opt_gc_background: + name = match_strdup(&args[0]); + + if (!name) + return -ENOMEM; + if (strlen(name) == 2 && !strncmp(name, "on", 2)) + set_opt(sbi, BG_GC); + else if (strlen(name) == 3 && !strncmp(name, "off", 3)) + clear_opt(sbi, BG_GC); + else { + kfree(name); + return -EINVAL; + } + kfree(name); + break; + case Opt_disable_roll_forward: + set_opt(sbi, DISABLE_ROLL_FORWARD); + break; + case Opt_discard: + set_opt(sbi, DISCARD); + break; + case Opt_noheap: + set_opt(sbi, NOHEAP); + break; +#ifdef CONFIG_F2FS_FS_XATTR + case Opt_user_xattr: + set_opt(sbi, XATTR_USER); + break; + case Opt_nouser_xattr: + clear_opt(sbi, XATTR_USER); + break; + case Opt_inline_xattr: + set_opt(sbi, INLINE_XATTR); + break; +#else + case Opt_user_xattr: + f2fs_msg(sb, KERN_INFO, + "user_xattr options not supported"); + break; + case Opt_nouser_xattr: + f2fs_msg(sb, KERN_INFO, + "nouser_xattr options not supported"); + break; + case Opt_inline_xattr: + f2fs_msg(sb, KERN_INFO, + "inline_xattr options not supported"); + break; +#endif +#ifdef CONFIG_F2FS_FS_POSIX_ACL + case Opt_acl: + set_opt(sbi, POSIX_ACL); + break; + case Opt_noacl: + clear_opt(sbi, POSIX_ACL); + break; +#else + case Opt_acl: + f2fs_msg(sb, KERN_INFO, "acl options not supported"); + break; + case Opt_noacl: + f2fs_msg(sb, KERN_INFO, "noacl options not supported"); + break; +#endif + case Opt_active_logs: + if (args->from && match_int(args, &arg)) + return -EINVAL; + if (arg != 2 && arg != 4 && arg != NR_CURSEG_TYPE) + return -EINVAL; + sbi->active_logs = arg; + break; + case Opt_disable_ext_identify: + set_opt(sbi, DISABLE_EXT_IDENTIFY); + break; + case Opt_err_continue: + clear_opt(sbi, ERRORS_RECOVER); + clear_opt(sbi, ERRORS_PANIC); + break; + case Opt_err_panic: + set_opt(sbi, ERRORS_PANIC); + clear_opt(sbi, ERRORS_RECOVER); + break; + case Opt_err_recover: + set_opt(sbi, ERRORS_RECOVER); + clear_opt(sbi, ERRORS_PANIC); + break; + case Opt_android_emu: + if (args->from) { + int ret; + char *perms = match_strdup(args); + + ret = parse_android_emu(sbi, perms); + kfree(perms); + + if (ret) + return -EINVAL; + + set_opt(sbi, ANDROID_EMU); + } else + return -EINVAL; + break; + case Opt_inline_data: + set_opt(sbi, INLINE_DATA); + break; + case Opt_flush_merge: + set_opt(sbi, FLUSH_MERGE); + break; + default: + f2fs_msg(sb, KERN_ERR, + "Unrecognized mount option \"%s\" or missing value", + p); + return -EINVAL; + } + } + return 0; +} + +static struct inode *f2fs_alloc_inode(struct super_block *sb) +{ + struct f2fs_inode_info *fi; + + fi = kmem_cache_alloc(f2fs_inode_cachep, GFP_F2FS_ZERO); + if (!fi) + return NULL; + + init_once((void *) fi); + + /* Initialize f2fs-specific inode info */ + fi->vfs_inode.i_version = 1; + atomic_set(&fi->dirty_dents, 0); + fi->i_current_depth = 1; + fi->i_advise = 0; + rwlock_init(&fi->ext.ext_lock); + init_rwsem(&fi->i_sem); + + set_inode_flag(fi, FI_NEW_INODE); + + if (test_opt(F2FS_SB(sb), INLINE_XATTR)) + set_inode_flag(fi, FI_INLINE_XATTR); + + /* Will be used by directory only */ + fi->i_dir_level = F2FS_SB(sb)->dir_level; + + return &fi->vfs_inode; +} + +static int f2fs_drop_inode(struct inode *inode) +{ + /* + * This is to avoid a deadlock condition like below. + * writeback_single_inode(inode) + * - f2fs_write_data_page + * - f2fs_gc -> iput -> evict + * - inode_wait_for_writeback(inode) + */ + if (!inode_unhashed(inode) && inode->i_state & I_SYNC) + return 0; + return generic_drop_inode(inode); +} + +/* + * f2fs_dirty_inode() is called from __mark_inode_dirty() + * + * We should call set_dirty_inode to write the dirty inode through write_inode. + */ +static void f2fs_dirty_inode(struct inode *inode, int flags) +{ + set_inode_flag(F2FS_I(inode), FI_DIRTY_INODE); +} + +static void f2fs_i_callback(struct rcu_head *head) +{ + struct inode *inode = container_of(head, struct inode, i_rcu); + kmem_cache_free(f2fs_inode_cachep, F2FS_I(inode)); +} + +static void f2fs_destroy_inode(struct inode *inode) +{ + call_rcu(&inode->i_rcu, f2fs_i_callback); +} + +static void f2fs_put_super(struct super_block *sb) +{ + struct f2fs_sb_info *sbi = F2FS_SB(sb); + + if (sbi->s_proc) { + remove_proc_entry("segment_info", sbi->s_proc); + remove_proc_entry(sb->s_id, f2fs_proc_root); + } + kobject_del(&sbi->s_kobj); + + f2fs_destroy_stats(sbi); + stop_gc_thread(sbi); + + /* We don't need to do checkpoint when it's clean */ + if (sbi->s_dirty && get_pages(sbi, F2FS_DIRTY_NODES)) + write_checkpoint(sbi, true); + + iput(sbi->node_inode); + iput(sbi->meta_inode); + + /* destroy f2fs internal modules */ + destroy_node_manager(sbi); + destroy_segment_manager(sbi); + + kfree(sbi->ckpt); + kobject_put(&sbi->s_kobj); + wait_for_completion(&sbi->s_kobj_unregister); + + sb->s_fs_info = NULL; + brelse(sbi->raw_super_buf); + kfree(sbi); +} + +int f2fs_sync_fs(struct super_block *sb, int sync) +{ + struct f2fs_sb_info *sbi = F2FS_SB(sb); + + trace_f2fs_sync_fs(sb, sync); + + if (!sbi->s_dirty && !get_pages(sbi, F2FS_DIRTY_NODES)) + return 0; + + if (sync) { + mutex_lock(&sbi->gc_mutex); + write_checkpoint(sbi, false); + mutex_unlock(&sbi->gc_mutex); + } else { + f2fs_balance_fs(sbi); + } + + return 0; +} + +static int f2fs_statfs(struct dentry *dentry, struct kstatfs *buf) +{ + struct super_block *sb = dentry->d_sb; + struct f2fs_sb_info *sbi = F2FS_SB(sb); + u64 id = huge_encode_dev(sb->s_bdev->bd_dev); + block_t total_count, user_block_count, start_count, ovp_count; + + total_count = le64_to_cpu(sbi->raw_super->block_count); + user_block_count = sbi->user_block_count; + start_count = le32_to_cpu(sbi->raw_super->segment0_blkaddr); + ovp_count = SM_I(sbi)->ovp_segments << sbi->log_blocks_per_seg; + buf->f_type = F2FS_SUPER_MAGIC; + buf->f_bsize = sbi->blocksize; + + buf->f_blocks = total_count - start_count; + buf->f_bfree = buf->f_blocks - valid_user_blocks(sbi) - ovp_count; + buf->f_bavail = user_block_count - valid_user_blocks(sbi); + + buf->f_files = sbi->total_node_count; + buf->f_ffree = sbi->total_node_count - valid_inode_count(sbi); + + buf->f_namelen = F2FS_NAME_LEN; + buf->f_fsid.val[0] = (u32)id; + buf->f_fsid.val[1] = (u32)(id >> 32); + + return 0; +} + +static int f2fs_show_options(struct seq_file *seq, struct dentry *root) +{ + struct f2fs_sb_info *sbi = F2FS_SB(root->d_sb); + + if (!f2fs_readonly(sbi->sb) && test_opt(sbi, BG_GC)) + seq_printf(seq, ",background_gc=%s", "on"); + else + seq_printf(seq, ",background_gc=%s", "off"); + if (test_opt(sbi, DISABLE_ROLL_FORWARD)) + seq_puts(seq, ",disable_roll_forward"); + if (test_opt(sbi, DISCARD)) + seq_puts(seq, ",discard"); + if (test_opt(sbi, NOHEAP)) + seq_puts(seq, ",no_heap_alloc"); +#ifdef CONFIG_F2FS_FS_XATTR + if (test_opt(sbi, XATTR_USER)) + seq_puts(seq, ",user_xattr"); + else + seq_puts(seq, ",nouser_xattr"); + if (test_opt(sbi, INLINE_XATTR)) + seq_puts(seq, ",inline_xattr"); +#endif +#ifdef CONFIG_F2FS_FS_POSIX_ACL + if (test_opt(sbi, POSIX_ACL)) + seq_puts(seq, ",acl"); + else + seq_puts(seq, ",noacl"); +#endif + if (test_opt(sbi, ERRORS_PANIC)) + seq_puts(seq, ",errors=panic"); + else if (test_opt(sbi, ERRORS_RECOVER)) + seq_puts(seq, ",errors=recover"); + else + seq_puts(seq, ",errors=continue"); + if (test_opt(sbi, DISABLE_EXT_IDENTIFY)) + seq_puts(seq, ",disable_ext_identify"); + + if (test_opt(sbi, ANDROID_EMU)) + seq_printf(seq, ",android_emu=%u:%u:%ho%s", + sbi->android_emu_uid, + sbi->android_emu_gid, + sbi->android_emu_mode, + (sbi->android_emu_flags & + F2FS_ANDROID_EMU_NOCASE) ? + ":nocase" : ""); + + if (test_opt(sbi, INLINE_DATA)) + seq_puts(seq, ",inline_data"); + if (!f2fs_readonly(sbi->sb) && test_opt(sbi, FLUSH_MERGE)) + seq_puts(seq, ",flush_merge"); + seq_printf(seq, ",active_logs=%u", sbi->active_logs); + + return 0; +} + +static int segment_info_seq_show(struct seq_file *seq, void *offset) +{ + struct super_block *sb = seq->private; + struct f2fs_sb_info *sbi = F2FS_SB(sb); + unsigned int total_segs = + le32_to_cpu(sbi->raw_super->segment_count_main); + int i; + + seq_puts(seq, "format: segment_type|valid_blocks\n" + "segment_type(0:HD, 1:WD, 2:CD, 3:HN, 4:WN, 5:CN)\n"); + + for (i = 0; i < total_segs; i++) { + struct seg_entry *se = get_seg_entry(sbi, i); + + if ((i % 10) == 0) + seq_printf(seq, "%-5d", i); + seq_printf(seq, "%d|%-3u", se->type, + get_valid_blocks(sbi, i, 1)); + if ((i % 10) == 9 || i == (total_segs - 1)) + seq_putc(seq, '\n'); + else + seq_putc(seq, ' '); + } + + return 0; +} + +static int segment_info_open_fs(struct inode *inode, struct file *file) +{ + return single_open(file, segment_info_seq_show, + PROC_I(inode)->pde->data); +} + +static const struct file_operations f2fs_seq_segment_info_fops = { + .owner = THIS_MODULE, + .open = segment_info_open_fs, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static int f2fs_remount(struct super_block *sb, int *flags, char *data) +{ + struct f2fs_sb_info *sbi = F2FS_SB(sb); + struct f2fs_mount_info org_mount_opt; + int err, active_logs; + bool need_restart_gc = false; + bool need_stop_gc = false; + + /* + * Save the old mount options in case we + * need to restore them. + */ + org_mount_opt = sbi->mount_opt; + active_logs = sbi->active_logs; + + /* parse mount options */ + err = parse_options(sb, data); + if (err) + goto restore_opts; + + /* + * Previous and new state of filesystem is RO, + * so skip checking GC and FLUSH_MERGE conditions. + */ + if ((sb->s_flags & MS_RDONLY) && (*flags & MS_RDONLY)) + goto skip; + + /* + * We stop the GC thread if FS is mounted as RO + * or if background_gc = off is passed in mount + * option. Also sync the filesystem. + */ + if ((*flags & MS_RDONLY) || !test_opt(sbi, BG_GC)) { + if (sbi->gc_thread) { + stop_gc_thread(sbi); + f2fs_sync_fs(sb, 1); + need_restart_gc = true; + } + } else if (test_opt(sbi, BG_GC) && !sbi->gc_thread) { + err = start_gc_thread(sbi); + if (err) + goto restore_opts; + need_stop_gc = true; + } + + /* + * We stop issue flush thread if FS is mounted as RO + * or if flush_merge is not passed in mount option. + */ + if ((*flags & MS_RDONLY) || !test_opt(sbi, FLUSH_MERGE)) { + struct f2fs_sm_info *sm_info = sbi->sm_info; + + if (sm_info->f2fs_issue_flush) + kthread_stop(sm_info->f2fs_issue_flush); + sm_info->issue_list = sm_info->dispatch_list = NULL; + sm_info->f2fs_issue_flush = NULL; + } else if (test_opt(sbi, FLUSH_MERGE) && + !sbi->sm_info->f2fs_issue_flush) { + dev_t dev = sbi->sb->s_bdev->bd_dev; + struct f2fs_sm_info *sm_info = + kzalloc(sizeof(struct f2fs_sm_info), GFP_KERNEL); + + if (!sm_info) { + err = -ENOMEM; + goto restore_gc; + } + spin_lock_init(&sm_info->issue_lock); + init_waitqueue_head(&sm_info->flush_wait_queue); + sm_info->f2fs_issue_flush = kthread_run(issue_flush_thread, sbi, + "f2fs_flush-%u:%u", MAJOR(dev), MINOR(dev)); + if (IS_ERR(sm_info->f2fs_issue_flush)) { + err = PTR_ERR(sm_info->f2fs_issue_flush); + sm_info->f2fs_issue_flush = NULL; + goto restore_gc; + } + } +skip: + /* Update the POSIXACL Flag */ + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | + (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); + return 0; +restore_gc: + if (need_restart_gc) { + if (start_gc_thread(sbi)) + f2fs_msg(sbi->sb, KERN_WARNING, + "background gc thread is stop"); + } else if (need_stop_gc) { + stop_gc_thread(sbi); + } +restore_opts: + sbi->mount_opt = org_mount_opt; + sbi->active_logs = active_logs; + return err; +} + +static struct super_operations f2fs_sops = { + .alloc_inode = f2fs_alloc_inode, + .drop_inode = f2fs_drop_inode, + .destroy_inode = f2fs_destroy_inode, + .write_inode = f2fs_write_inode, + .dirty_inode = f2fs_dirty_inode, + .show_options = f2fs_show_options, + .evict_inode = f2fs_evict_inode, + .put_super = f2fs_put_super, + .sync_fs = f2fs_sync_fs, + .statfs = f2fs_statfs, + .remount_fs = f2fs_remount, +}; + +static struct inode *f2fs_nfs_get_inode(struct super_block *sb, + u64 ino, u32 generation) +{ + struct f2fs_sb_info *sbi = F2FS_SB(sb); + struct inode *inode; + + if (check_nid_range(sbi, ino)) + return ERR_PTR(-ESTALE); + + /* + * f2fs_iget isn't quite right if the inode is currently unallocated! + * However f2fs_iget currently does appropriate checks to handle stale + * inodes so everything is OK. + */ + inode = f2fs_iget(sb, ino); + if (IS_ERR(inode)) + return ERR_CAST(inode); + if (unlikely(generation && inode->i_generation != generation)) { + /* we didn't find the right inode.. */ + iput(inode); + return ERR_PTR(-ESTALE); + } + return inode; +} + +static struct dentry *f2fs_fh_to_dentry(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_dentry(sb, fid, fh_len, fh_type, + f2fs_nfs_get_inode); +} + +static struct dentry *f2fs_fh_to_parent(struct super_block *sb, struct fid *fid, + int fh_len, int fh_type) +{ + return generic_fh_to_parent(sb, fid, fh_len, fh_type, + f2fs_nfs_get_inode); +} + +static const struct export_operations f2fs_export_ops = { + .fh_to_dentry = f2fs_fh_to_dentry, + .fh_to_parent = f2fs_fh_to_parent, + .get_parent = f2fs_get_parent, +}; + +static loff_t max_file_size(unsigned bits) +{ + loff_t result = (DEF_ADDRS_PER_INODE - F2FS_INLINE_XATTR_ADDRS); + loff_t leaf_count = ADDRS_PER_BLOCK; + + /* two direct node blocks */ + result += (leaf_count * 2); + + /* two indirect node blocks */ + leaf_count *= NIDS_PER_BLOCK; + result += (leaf_count * 2); + + /* one double indirect node block */ + leaf_count *= NIDS_PER_BLOCK; + result += leaf_count; + + result <<= bits; + return result; +} + +static int sanity_check_raw_super(struct super_block *sb, + struct f2fs_super_block *raw_super) +{ + unsigned int blocksize; + + if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) { + f2fs_msg(sb, KERN_INFO, + "Magic Mismatch, valid(0x%x) - read(0x%x)", + F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic)); + return 1; + } + + /* Currently, support only 4KB page cache size */ + if (F2FS_BLKSIZE != PAGE_CACHE_SIZE) { + f2fs_msg(sb, KERN_INFO, + "Invalid page_cache_size (%lu), supports only 4KB\n", + PAGE_CACHE_SIZE); + return 1; + } + + /* Currently, support only 4KB block size */ + blocksize = 1 << le32_to_cpu(raw_super->log_blocksize); + if (blocksize != F2FS_BLKSIZE) { + f2fs_msg(sb, KERN_INFO, + "Invalid blocksize (%u), supports only 4KB\n", + blocksize); + return 1; + } + + if (le32_to_cpu(raw_super->log_sectorsize) != + F2FS_LOG_SECTOR_SIZE) { + f2fs_msg(sb, KERN_INFO, "Invalid log sectorsize"); + return 1; + } + if (le32_to_cpu(raw_super->log_sectors_per_block) != + F2FS_LOG_SECTORS_PER_BLOCK) { + f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block"); + return 1; + } + return 0; +} + +static int sanity_check_ckpt(struct f2fs_sb_info *sbi) +{ + unsigned int total, fsmeta; + struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi); + struct f2fs_checkpoint *ckpt = F2FS_CKPT(sbi); + + total = le32_to_cpu(raw_super->segment_count); + fsmeta = le32_to_cpu(raw_super->segment_count_ckpt); + fsmeta += le32_to_cpu(raw_super->segment_count_sit); + fsmeta += le32_to_cpu(raw_super->segment_count_nat); + fsmeta += le32_to_cpu(ckpt->rsvd_segment_count); + fsmeta += le32_to_cpu(raw_super->segment_count_ssa); + + if (unlikely(fsmeta >= total)) + return 1; + + if (unlikely(is_set_ckpt_flags(ckpt, CP_ERROR_FLAG))) { + f2fs_msg(sbi->sb, KERN_ERR, "A bug case: need to run fsck"); + return 1; + } + return 0; +} + +static void init_sb_info(struct f2fs_sb_info *sbi) +{ + struct f2fs_super_block *raw_super = sbi->raw_super; + int i; + + sbi->log_sectors_per_block = + le32_to_cpu(raw_super->log_sectors_per_block); + sbi->log_blocksize = le32_to_cpu(raw_super->log_blocksize); + sbi->blocksize = 1 << sbi->log_blocksize; + sbi->log_blocks_per_seg = le32_to_cpu(raw_super->log_blocks_per_seg); + sbi->blocks_per_seg = 1 << sbi->log_blocks_per_seg; + sbi->segs_per_sec = le32_to_cpu(raw_super->segs_per_sec); + sbi->secs_per_zone = le32_to_cpu(raw_super->secs_per_zone); + sbi->total_sections = le32_to_cpu(raw_super->section_count); + sbi->total_node_count = + (le32_to_cpu(raw_super->segment_count_nat) / 2) + * sbi->blocks_per_seg * NAT_ENTRY_PER_BLOCK; + sbi->root_ino_num = le32_to_cpu(raw_super->root_ino); + sbi->node_ino_num = le32_to_cpu(raw_super->node_ino); + sbi->meta_ino_num = le32_to_cpu(raw_super->meta_ino); + sbi->cur_victim_sec = NULL_SECNO; + sbi->max_victim_search = DEF_MAX_VICTIM_SEARCH; + + for (i = 0; i < NR_COUNT_TYPE; i++) + atomic_set(&sbi->nr_pages[i], 0); + + sbi->dir_level = DEF_DIR_LEVEL; +} + +/* + * Read f2fs raw super block. + * Because we have two copies of super block, so read the first one at first, + * if the first one is invalid, move to read the second one. + */ +static int read_raw_super_block(struct super_block *sb, + struct f2fs_super_block **raw_super, + struct buffer_head **raw_super_buf) +{ + int block = 0; + +retry: + *raw_super_buf = sb_bread(sb, block); + if (!*raw_super_buf) { + f2fs_msg(sb, KERN_ERR, "Unable to read %dth superblock", + block + 1); + if (block == 0) { + block++; + goto retry; + } else { + return -EIO; + } + } + + *raw_super = (struct f2fs_super_block *) + ((char *)(*raw_super_buf)->b_data + F2FS_SUPER_OFFSET); + + /* sanity checking of raw super */ + if (sanity_check_raw_super(sb, *raw_super)) { + brelse(*raw_super_buf); + f2fs_msg(sb, KERN_ERR, + "Can't find valid F2FS filesystem in %dth superblock", + block + 1); + if (block == 0) { + block++; + goto retry; + } else { + return -EINVAL; + } + } + + return 0; +} + +static int f2fs_fill_super(struct super_block *sb, void *data, int silent) +{ + struct f2fs_sb_info *sbi; + struct f2fs_super_block *raw_super; + struct buffer_head *raw_super_buf; + struct inode *root; + long err = -EINVAL; + const char *descr = ""; + int i; + + f2fs_msg(sb, KERN_INFO, "mounting.."); + /* allocate memory for f2fs-specific super block info */ + sbi = kzalloc(sizeof(struct f2fs_sb_info), GFP_KERNEL); + if (!sbi) + return -ENOMEM; + + /* set a block size */ + if (unlikely(!sb_set_blocksize(sb, F2FS_BLKSIZE))) { + f2fs_msg(sb, KERN_ERR, "unable to set blocksize"); + goto free_sbi; + } + + err = read_raw_super_block(sb, &raw_super, &raw_super_buf); + if (err) + goto free_sbi; + + sb->s_fs_info = sbi; + /* init some FS parameters */ + sbi->active_logs = NR_CURSEG_TYPE; + + set_opt(sbi, BG_GC); + +#ifdef CONFIG_F2FS_FS_XATTR + set_opt(sbi, XATTR_USER); +#endif +#ifdef CONFIG_F2FS_FS_POSIX_ACL + set_opt(sbi, POSIX_ACL); +#endif + /* parse mount options */ + err = parse_options(sb, (char *)data); + if (err) + goto free_sb_buf; + + sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize)); + sb->s_max_links = F2FS_LINK_MAX; + get_random_bytes(&sbi->s_next_generation, sizeof(u32)); + + sb->s_op = &f2fs_sops; + sb->s_xattr = f2fs_xattr_handlers; + sb->s_export_op = &f2fs_export_ops; + sb->s_magic = F2FS_SUPER_MAGIC; + sb->s_time_gran = 1; + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | + (test_opt(sbi, POSIX_ACL) ? MS_POSIXACL : 0); + memcpy(sb->s_uuid, raw_super->uuid, sizeof(raw_super->uuid)); + + /* init f2fs-specific super block info */ + sbi->sb = sb; + sbi->raw_super = raw_super; + sbi->raw_super_buf = raw_super_buf; + mutex_init(&sbi->gc_mutex); + mutex_init(&sbi->writepages); + mutex_init(&sbi->cp_mutex); + mutex_init(&sbi->node_write); + sbi->por_doing = false; + spin_lock_init(&sbi->stat_lock); + + init_rwsem(&sbi->read_io.io_rwsem); + sbi->read_io.sbi = sbi; + sbi->read_io.bio = NULL; + for (i = 0; i < NR_PAGE_TYPE; i++) { + init_rwsem(&sbi->write_io[i].io_rwsem); + sbi->write_io[i].sbi = sbi; + sbi->write_io[i].bio = NULL; + } + + init_rwsem(&sbi->cp_rwsem); + init_waitqueue_head(&sbi->cp_wait); + init_sb_info(sbi); + + /* get an inode for meta space */ + sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi)); + if (IS_ERR(sbi->meta_inode)) { + f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode"); + err = PTR_ERR(sbi->meta_inode); + goto free_sb_buf; + } + + err = get_valid_checkpoint(sbi); + if (err) { + f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint"); + goto free_meta_inode; + } + + /* sanity checking of checkpoint */ + err = -EINVAL; + if (sanity_check_ckpt(sbi)) { + f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint"); + goto free_cp; + } + + sbi->total_valid_node_count = + le32_to_cpu(sbi->ckpt->valid_node_count); + sbi->total_valid_inode_count = + le32_to_cpu(sbi->ckpt->valid_inode_count); + sbi->user_block_count = le64_to_cpu(sbi->ckpt->user_block_count); + sbi->total_valid_block_count = + le64_to_cpu(sbi->ckpt->valid_block_count); + sbi->last_valid_block_count = sbi->total_valid_block_count; + sbi->alloc_valid_block_count = 0; + INIT_LIST_HEAD(&sbi->dir_inode_list); + spin_lock_init(&sbi->dir_inode_lock); + + init_orphan_info(sbi); + + /* setup f2fs internal modules */ + err = build_segment_manager(sbi); + if (err) { + f2fs_msg(sb, KERN_ERR, + "Failed to initialize F2FS segment manager"); + goto free_sm; + } + err = build_node_manager(sbi); + if (err) { + f2fs_msg(sb, KERN_ERR, + "Failed to initialize F2FS node manager"); + goto free_nm; + } + + build_gc_manager(sbi); + + /* get an inode for node space */ + sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi)); + if (IS_ERR(sbi->node_inode)) { + f2fs_msg(sb, KERN_ERR, "Failed to read node inode"); + err = PTR_ERR(sbi->node_inode); + goto free_nm; + } + + /* if there are nt orphan nodes free them */ + recover_orphan_inodes(sbi); + + /* read root inode and dentry */ + root = f2fs_iget(sb, F2FS_ROOT_INO(sbi)); + if (IS_ERR(root)) { + f2fs_msg(sb, KERN_ERR, "Failed to read root inode"); + err = PTR_ERR(root); + goto free_node_inode; + } + if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { + err = -EINVAL; + goto free_root_inode; + } + + sb->s_root = d_make_root(root); /* allocate root dentry */ + if (!sb->s_root) { + err = -ENOMEM; + goto free_root_inode; + } + + err = f2fs_build_stats(sbi); + if (err) + goto free_root_inode; + + if (f2fs_proc_root) + sbi->s_proc = proc_mkdir(sb->s_id, f2fs_proc_root); + + if (sbi->s_proc) + proc_create_data("segment_info", S_IRUGO, sbi->s_proc, + &f2fs_seq_segment_info_fops, sb); + + if (test_opt(sbi, DISCARD)) { + struct request_queue *q = bdev_get_queue(sb->s_bdev); + if (!blk_queue_discard(q)) + f2fs_msg(sb, KERN_WARNING, + "mounting with \"discard\" option, but " + "the device does not support discard"); + } + + if (test_opt(sbi, ANDROID_EMU)) + descr = " with android sdcard emulation"; + f2fs_msg(sb, KERN_INFO, "mounted filesystem%s", descr); + + sbi->s_kobj.kset = f2fs_kset; + init_completion(&sbi->s_kobj_unregister); + err = kobject_init_and_add(&sbi->s_kobj, &f2fs_ktype, NULL, + "%s", sb->s_id); + if (err) + goto free_proc; + + /* recover fsynced data */ + if (!test_opt(sbi, DISABLE_ROLL_FORWARD)) { + err = recover_fsync_data(sbi); + if (err) + f2fs_msg(sb, KERN_ERR, + "Cannot recover all fsync data errno=%ld", err); + } + + /* + * If filesystem is not mounted as read-only then + * do start the gc_thread. + */ + if (!(sb->s_flags & MS_RDONLY)) { + /* After POR, we can run background GC thread.*/ + err = start_gc_thread(sbi); + if (err) + goto free_kobj; + } + return 0; + +free_kobj: + kobject_del(&sbi->s_kobj); +free_proc: + if (sbi->s_proc) { + remove_proc_entry("segment_info", sbi->s_proc); + remove_proc_entry(sb->s_id, f2fs_proc_root); + } + f2fs_destroy_stats(sbi); +free_root_inode: + dput(sb->s_root); + sb->s_root = NULL; +free_node_inode: + iput(sbi->node_inode); +free_nm: + destroy_node_manager(sbi); +free_sm: + destroy_segment_manager(sbi); +free_cp: + kfree(sbi->ckpt); +free_meta_inode: + make_bad_inode(sbi->meta_inode); + iput(sbi->meta_inode); +free_sb_buf: + brelse(raw_super_buf); +free_sbi: + kfree(sbi); + f2fs_msg(sb, KERN_ERR, "mount failed"); + return err; +} + +static struct dentry *f2fs_mount(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data) +{ + return mount_bdev(fs_type, flags, dev_name, data, f2fs_fill_super); +} + +static struct file_system_type f2fs_fs_type = { + .owner = THIS_MODULE, + .name = "f2fs", + .mount = f2fs_mount, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, +}; + +static int __init init_inodecache(void) +{ + f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache", + sizeof(struct f2fs_inode_info)); + if (!f2fs_inode_cachep) + return -ENOMEM; + return 0; +} + +static void destroy_inodecache(void) +{ + /* + * Make sure all delayed rcu free inodes are flushed before we + * destroy cache. + */ + rcu_barrier(); + kmem_cache_destroy(f2fs_inode_cachep); +} + +static int __init init_f2fs_fs(void) +{ + int err; + + err = init_inodecache(); + if (err) + goto fail; + err = create_node_manager_caches(); + if (err) + goto free_inodecache; + err = create_segment_manager_caches(); + if (err) + goto free_node_manager_caches; + err = create_gc_caches(); + if (err) + goto free_segment_manager_caches; + err = create_checkpoint_caches(); + if (err) + goto free_gc_caches; + f2fs_kset = kset_create_and_add("f2fs", NULL, fs_kobj); + if (!f2fs_kset) { + err = -ENOMEM; + goto free_checkpoint_caches; + } + err = register_filesystem(&f2fs_fs_type); + if (err) + goto free_kset; + f2fs_create_root_stats(); + f2fs_proc_root = proc_mkdir("fs/f2fs", NULL); + return 0; + +free_kset: + kset_unregister(f2fs_kset); +free_checkpoint_caches: + destroy_checkpoint_caches(); +free_gc_caches: + destroy_gc_caches(); +free_segment_manager_caches: + destroy_segment_manager_caches(); +free_node_manager_caches: + destroy_node_manager_caches(); +free_inodecache: + destroy_inodecache(); +fail: + return err; +} + +static void __exit exit_f2fs_fs(void) +{ + remove_proc_entry("fs/f2fs", NULL); + f2fs_destroy_root_stats(); + unregister_filesystem(&f2fs_fs_type); + destroy_checkpoint_caches(); + destroy_gc_caches(); + destroy_segment_manager_caches(); + destroy_node_manager_caches(); + destroy_inodecache(); + kset_unregister(f2fs_kset); +} + +module_init(init_f2fs_fs) +module_exit(exit_f2fs_fs) + +MODULE_AUTHOR("Samsung Electronics's Praesto Team"); +MODULE_DESCRIPTION("Flash Friendly File System"); +MODULE_LICENSE("GPL"); diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c new file mode 100644 index 00000000000..0bb9bc8580f --- /dev/null +++ b/fs/f2fs/xattr.c @@ -0,0 +1,617 @@ +/* + * fs/f2fs/xattr.c + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Portions of this code from linux/fs/ext2/xattr.c + * + * Copyright (C) 2001-2003 Andreas Gruenbacher + * + * Fix by Harrison Xing . + * Extended attributes for symlinks and special files added per + * suggestion of Luka Renko . + * xattr consolidation Copyright (c) 2004 James Morris , + * Red Hat Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include "f2fs.h" +#include "xattr.h" + +static size_t f2fs_xattr_generic_list(struct dentry *dentry, char *list, + size_t list_size, const char *name, size_t len, int type) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); + int total_len, prefix_len = 0; + const char *prefix = NULL; + + switch (type) { + case F2FS_XATTR_INDEX_USER: + if (!test_opt(sbi, XATTR_USER)) + return -EOPNOTSUPP; + prefix = XATTR_USER_PREFIX; + prefix_len = XATTR_USER_PREFIX_LEN; + break; + case F2FS_XATTR_INDEX_TRUSTED: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + prefix = XATTR_TRUSTED_PREFIX; + prefix_len = XATTR_TRUSTED_PREFIX_LEN; + break; + case F2FS_XATTR_INDEX_SECURITY: + prefix = XATTR_SECURITY_PREFIX; + prefix_len = XATTR_SECURITY_PREFIX_LEN; + break; + default: + return -EINVAL; + } + + total_len = prefix_len + len + 1; + if (list && total_len <= list_size) { + memcpy(list, prefix, prefix_len); + memcpy(list + prefix_len, name, len); + list[prefix_len + len] = '\0'; + } + return total_len; +} + +static int f2fs_xattr_generic_get(struct dentry *dentry, const char *name, + void *buffer, size_t size, int type) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); + + switch (type) { + case F2FS_XATTR_INDEX_USER: + if (!test_opt(sbi, XATTR_USER)) + return -EOPNOTSUPP; + break; + case F2FS_XATTR_INDEX_TRUSTED: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + break; + case F2FS_XATTR_INDEX_SECURITY: + break; + default: + return -EINVAL; + } + if (strcmp(name, "") == 0) + return -EINVAL; + return f2fs_getxattr(dentry->d_inode, type, name, buffer, size); +} + +static int f2fs_xattr_generic_set(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, int type) +{ + struct f2fs_sb_info *sbi = F2FS_SB(dentry->d_sb); + + switch (type) { + case F2FS_XATTR_INDEX_USER: + if (!test_opt(sbi, XATTR_USER)) + return -EOPNOTSUPP; + break; + case F2FS_XATTR_INDEX_TRUSTED: + if (!capable(CAP_SYS_ADMIN)) + return -EPERM; + break; + case F2FS_XATTR_INDEX_SECURITY: + break; + default: + return -EINVAL; + } + if (strcmp(name, "") == 0) + return -EINVAL; + + return f2fs_setxattr(dentry->d_inode, type, name, + value, size, NULL, flags); +} + +static size_t f2fs_xattr_advise_list(struct dentry *dentry, char *list, + size_t list_size, const char *name, size_t len, int type) +{ + const char *xname = F2FS_SYSTEM_ADVISE_PREFIX; + size_t size; + + if (type != F2FS_XATTR_INDEX_ADVISE) + return 0; + + size = strlen(xname) + 1; + if (list && size <= list_size) + memcpy(list, xname, size); + return size; +} + +static int f2fs_xattr_advise_get(struct dentry *dentry, const char *name, + void *buffer, size_t size, int type) +{ + struct inode *inode = dentry->d_inode; + + if (!name || strcmp(name, "") != 0) + return -EINVAL; + + if (buffer) + *((char *)buffer) = F2FS_I(inode)->i_advise; + return sizeof(char); +} + +static int f2fs_xattr_advise_set(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, int type) +{ + struct inode *inode = dentry->d_inode; + + if (!name || strcmp(name, "") != 0) + return -EINVAL; + if (!inode_owner_or_capable(inode)) + return -EPERM; + if (value == NULL) + return -EINVAL; + + F2FS_I(inode)->i_advise = *(char *)value; + return 0; +} + +#ifdef CONFIG_F2FS_FS_SECURITY +static int f2fs_initxattrs(struct inode *inode, const struct xattr *xattr_array, + void *page) +{ + const struct xattr *xattr; + int err = 0; + + for (xattr = xattr_array; xattr->name != NULL; xattr++) { + err = f2fs_setxattr(inode, F2FS_XATTR_INDEX_SECURITY, + xattr->name, xattr->value, + xattr->value_len, (struct page *)page, 0); + if (err < 0) + break; + } + return err; +} + +int f2fs_init_security(struct inode *inode, struct inode *dir, + const struct qstr *qstr, struct page *ipage) +{ + return security_inode_init_security(inode, dir, qstr, + &f2fs_initxattrs, ipage); +} +#endif + +const struct xattr_handler f2fs_xattr_user_handler = { + .prefix = XATTR_USER_PREFIX, + .flags = F2FS_XATTR_INDEX_USER, + .list = f2fs_xattr_generic_list, + .get = f2fs_xattr_generic_get, + .set = f2fs_xattr_generic_set, +}; + +const struct xattr_handler f2fs_xattr_trusted_handler = { + .prefix = XATTR_TRUSTED_PREFIX, + .flags = F2FS_XATTR_INDEX_TRUSTED, + .list = f2fs_xattr_generic_list, + .get = f2fs_xattr_generic_get, + .set = f2fs_xattr_generic_set, +}; + +const struct xattr_handler f2fs_xattr_advise_handler = { + .prefix = F2FS_SYSTEM_ADVISE_PREFIX, + .flags = F2FS_XATTR_INDEX_ADVISE, + .list = f2fs_xattr_advise_list, + .get = f2fs_xattr_advise_get, + .set = f2fs_xattr_advise_set, +}; + +const struct xattr_handler f2fs_xattr_security_handler = { + .prefix = XATTR_SECURITY_PREFIX, + .flags = F2FS_XATTR_INDEX_SECURITY, + .list = f2fs_xattr_generic_list, + .get = f2fs_xattr_generic_get, + .set = f2fs_xattr_generic_set, +}; + +static const struct xattr_handler *f2fs_xattr_handler_map[] = { + [F2FS_XATTR_INDEX_USER] = &f2fs_xattr_user_handler, +#ifdef CONFIG_F2FS_FS_POSIX_ACL + [F2FS_XATTR_INDEX_POSIX_ACL_ACCESS] = &posix_acl_access_xattr_handler, + [F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT] = &posix_acl_default_xattr_handler, +#endif + [F2FS_XATTR_INDEX_TRUSTED] = &f2fs_xattr_trusted_handler, +#ifdef CONFIG_F2FS_FS_SECURITY + [F2FS_XATTR_INDEX_SECURITY] = &f2fs_xattr_security_handler, +#endif + [F2FS_XATTR_INDEX_ADVISE] = &f2fs_xattr_advise_handler, +}; + +const struct xattr_handler *f2fs_xattr_handlers[] = { + &f2fs_xattr_user_handler, +#ifdef CONFIG_F2FS_FS_POSIX_ACL + &posix_acl_access_xattr_handler, + &posix_acl_default_xattr_handler, +#endif + &f2fs_xattr_trusted_handler, +#ifdef CONFIG_F2FS_FS_SECURITY + &f2fs_xattr_security_handler, +#endif + &f2fs_xattr_advise_handler, + NULL, +}; + +static inline const struct xattr_handler *f2fs_xattr_handler(int index) +{ + const struct xattr_handler *handler = NULL; + + if (index > 0 && index < ARRAY_SIZE(f2fs_xattr_handler_map)) + handler = f2fs_xattr_handler_map[index]; + return handler; +} + +static struct f2fs_xattr_entry *__find_xattr(void *base_addr, int index, + size_t len, const char *name) +{ + struct f2fs_xattr_entry *entry; + + list_for_each_xattr(entry, base_addr) { + if (entry->e_name_index != index) + continue; + if (entry->e_name_len != len) + continue; + if (!memcmp(entry->e_name, name, len)) + break; + } + return entry; +} + +static void *read_all_xattrs(struct inode *inode, struct page *ipage) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct f2fs_xattr_header *header; + size_t size = PAGE_SIZE, inline_size = 0; + void *txattr_addr; + + inline_size = inline_xattr_size(inode); + + txattr_addr = kzalloc(inline_size + size, GFP_F2FS_ZERO); + if (!txattr_addr) + return NULL; + + /* read from inline xattr */ + if (inline_size) { + struct page *page = NULL; + void *inline_addr; + + if (ipage) { + inline_addr = inline_xattr_addr(ipage); + } else { + page = get_node_page(sbi, inode->i_ino); + if (IS_ERR(page)) + goto fail; + inline_addr = inline_xattr_addr(page); + } + memcpy(txattr_addr, inline_addr, inline_size); + f2fs_put_page(page, 1); + } + + /* read from xattr node block */ + if (F2FS_I(inode)->i_xattr_nid) { + struct page *xpage; + void *xattr_addr; + + /* The inode already has an extended attribute block. */ + xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid); + if (IS_ERR(xpage)) + goto fail; + + xattr_addr = page_address(xpage); + memcpy(txattr_addr + inline_size, xattr_addr, PAGE_SIZE); + f2fs_put_page(xpage, 1); + } + + header = XATTR_HDR(txattr_addr); + + /* never been allocated xattrs */ + if (le32_to_cpu(header->h_magic) != F2FS_XATTR_MAGIC) { + header->h_magic = cpu_to_le32(F2FS_XATTR_MAGIC); + header->h_refcount = cpu_to_le32(1); + } + return txattr_addr; +fail: + kzfree(txattr_addr); + return NULL; +} + +static inline int write_all_xattrs(struct inode *inode, __u32 hsize, + void *txattr_addr, struct page *ipage) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + size_t inline_size = 0; + void *xattr_addr; + struct page *xpage; + nid_t new_nid = 0; + int err; + + inline_size = inline_xattr_size(inode); + + if (hsize > inline_size && !F2FS_I(inode)->i_xattr_nid) + if (!alloc_nid(sbi, &new_nid)) + return -ENOSPC; + + /* write to inline xattr */ + if (inline_size) { + struct page *page = NULL; + void *inline_addr; + + if (ipage) { + inline_addr = inline_xattr_addr(ipage); + f2fs_wait_on_page_writeback(ipage, NODE); + } else { + page = get_node_page(sbi, inode->i_ino); + if (IS_ERR(page)) { + alloc_nid_failed(sbi, new_nid); + return PTR_ERR(page); + } + inline_addr = inline_xattr_addr(page); + f2fs_wait_on_page_writeback(page, NODE); + } + memcpy(inline_addr, txattr_addr, inline_size); + f2fs_put_page(page, 1); + + /* no need to use xattr node block */ + if (hsize <= inline_size) { + err = truncate_xattr_node(inode, ipage); + alloc_nid_failed(sbi, new_nid); + return err; + } + } + + /* write to xattr node block */ + if (F2FS_I(inode)->i_xattr_nid) { + xpage = get_node_page(sbi, F2FS_I(inode)->i_xattr_nid); + if (IS_ERR(xpage)) { + alloc_nid_failed(sbi, new_nid); + return PTR_ERR(xpage); + } + f2fs_bug_on(new_nid); + f2fs_wait_on_page_writeback(xpage, NODE); + } else { + struct dnode_of_data dn; + set_new_dnode(&dn, inode, NULL, NULL, new_nid); + xpage = new_node_page(&dn, XATTR_NODE_OFFSET, ipage); + if (IS_ERR(xpage)) { + alloc_nid_failed(sbi, new_nid); + return PTR_ERR(xpage); + } + alloc_nid_done(sbi, new_nid); + } + + xattr_addr = page_address(xpage); + memcpy(xattr_addr, txattr_addr + inline_size, PAGE_SIZE - + sizeof(struct node_footer)); + set_page_dirty(xpage); + f2fs_put_page(xpage, 1); + + /* need to checkpoint during fsync */ + F2FS_I(inode)->xattr_ver = cur_cp_version(F2FS_CKPT(sbi)); + return 0; +} + +int f2fs_getxattr(struct inode *inode, int index, const char *name, + void *buffer, size_t buffer_size) +{ + struct f2fs_xattr_entry *entry; + void *base_addr; + int error = 0; + size_t size, len; + + if (name == NULL) + return -EINVAL; + len = strlen(name); + if (len > F2FS_NAME_LEN) + return -ERANGE; + + base_addr = read_all_xattrs(inode, NULL); + if (!base_addr) + return -ENOMEM; + + entry = __find_xattr(base_addr, index, len, name); + if (IS_XATTR_LAST_ENTRY(entry)) { + error = -ENODATA; + goto cleanup; + } + + size = le16_to_cpu(entry->e_value_size); + + if (buffer && size > buffer_size) { + error = -ERANGE; + goto cleanup; + } + + if (buffer) { + char *pval = entry->e_name + entry->e_name_len; + memcpy(buffer, pval, size); + } + error = size; + +cleanup: + kzfree(base_addr); + return error; +} + +ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) +{ + struct inode *inode = dentry->d_inode; + struct f2fs_xattr_entry *entry; + void *base_addr; + int error = 0; + size_t rest = buffer_size; + + base_addr = read_all_xattrs(inode, NULL); + if (!base_addr) + return -ENOMEM; + + list_for_each_xattr(entry, base_addr) { + const struct xattr_handler *handler = + f2fs_xattr_handler(entry->e_name_index); + size_t size; + + if (!handler) + continue; + + size = handler->list(dentry, buffer, rest, entry->e_name, + entry->e_name_len, handler->flags); + if (buffer && size > rest) { + error = -ERANGE; + goto cleanup; + } + + if (buffer) + buffer += size; + rest -= size; + } + error = buffer_size - rest; +cleanup: + kzfree(base_addr); + return error; +} + +static int __f2fs_setxattr(struct inode *inode, int index, + const char *name, const void *value, size_t size, + struct page *ipage, int flags) +{ + struct f2fs_inode_info *fi = F2FS_I(inode); + struct f2fs_xattr_entry *here, *last; + void *base_addr; + int found, newsize; + size_t len; + __u32 new_hsize; + int error = -ENOMEM; + + if (name == NULL) + return -EINVAL; + + if (value == NULL) + size = 0; + + len = strlen(name); + + if (len > F2FS_NAME_LEN || size > MAX_VALUE_LEN(inode)) + return -ERANGE; + + base_addr = read_all_xattrs(inode, ipage); + if (!base_addr) + goto exit; + + /* find entry with wanted name. */ + here = __find_xattr(base_addr, index, len, name); + + found = IS_XATTR_LAST_ENTRY(here) ? 0 : 1; + + if ((flags & XATTR_REPLACE) && !found) { + error = -ENODATA; + goto exit; + } else if ((flags & XATTR_CREATE) && found) { + error = -EEXIST; + goto exit; + } + + last = here; + + while (!IS_XATTR_LAST_ENTRY(last)) + last = XATTR_NEXT_ENTRY(last); + + newsize = XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + len + size); + + /* 1. Check space */ + if (value) { + int free; + /* + * If value is NULL, it is remove operation. + * In case of update operation, we caculate free. + */ + free = MIN_OFFSET(inode) - ((char *)last - (char *)base_addr); + if (found) + free = free + ENTRY_SIZE(here); + + if (unlikely(free < newsize)) { + error = -ENOSPC; + goto exit; + } + } + + /* 2. Remove old entry */ + if (found) { + /* + * If entry is found, remove old entry. + * If not found, remove operation is not needed. + */ + struct f2fs_xattr_entry *next = XATTR_NEXT_ENTRY(here); + int oldsize = ENTRY_SIZE(here); + + memmove(here, next, (char *)last - (char *)next); + last = (struct f2fs_xattr_entry *)((char *)last - oldsize); + memset(last, 0, oldsize); + } + + new_hsize = (char *)last - (char *)base_addr; + + /* 3. Write new entry */ + if (value) { + char *pval; + /* + * Before we come here, old entry is removed. + * We just write new entry. + */ + memset(last, 0, newsize); + last->e_name_index = index; + last->e_name_len = len; + memcpy(last->e_name, name, len); + pval = last->e_name + len; + memcpy(pval, value, size); + last->e_value_size = cpu_to_le16(size); + new_hsize += newsize; + } + + error = write_all_xattrs(inode, new_hsize, base_addr, ipage); + if (error) + goto exit; + + if (is_inode_flag_set(fi, FI_ACL_MODE)) { + inode->i_mode = fi->i_acl_mode; + inode->i_ctime = CURRENT_TIME; + clear_inode_flag(fi, FI_ACL_MODE); + } + + if (ipage) + update_inode(inode, ipage); + else + update_inode_page(inode); +exit: + kzfree(base_addr); + return error; +} + +int f2fs_setxattr(struct inode *inode, int index, const char *name, + const void *value, size_t size, + struct page *ipage, int flags) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + int err; + + /* this case is only from init_inode_metadata */ + if (ipage) + return __f2fs_setxattr(inode, index, name, value, + size, ipage, flags); + f2fs_balance_fs(sbi); + + f2fs_lock_op(sbi); + /* protect xattr_ver */ + down_write(&F2FS_I(inode)->i_sem); + err = __f2fs_setxattr(inode, index, name, value, size, ipage, flags); + up_write(&F2FS_I(inode)->i_sem); + f2fs_unlock_op(sbi); + + return err; +} diff --git a/fs/f2fs/xattr.h b/fs/f2fs/xattr.h new file mode 100644 index 00000000000..34ab7dbcf5e --- /dev/null +++ b/fs/f2fs/xattr.h @@ -0,0 +1,150 @@ +/* + * fs/f2fs/xattr.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.com/ + * + * Portions of this code from linux/fs/ext2/xattr.h + * + * On-disk format of extended attributes for the ext2 filesystem. + * + * (C) 2001 Andreas Gruenbacher, + * + * 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 __F2FS_XATTR_H__ +#define __F2FS_XATTR_H__ + +#include +#include + +/* Magic value in attribute blocks */ +#define F2FS_XATTR_MAGIC 0xF2F52011 + +/* Maximum number of references to one attribute block */ +#define F2FS_XATTR_REFCOUNT_MAX 1024 + +/* Name indexes */ +#define F2FS_SYSTEM_ADVISE_PREFIX "system.advise" +#define F2FS_XATTR_INDEX_USER 1 +#define F2FS_XATTR_INDEX_POSIX_ACL_ACCESS 2 +#define F2FS_XATTR_INDEX_POSIX_ACL_DEFAULT 3 +#define F2FS_XATTR_INDEX_TRUSTED 4 +#define F2FS_XATTR_INDEX_LUSTRE 5 +#define F2FS_XATTR_INDEX_SECURITY 6 +#define F2FS_XATTR_INDEX_ADVISE 7 + +struct f2fs_xattr_header { + __le32 h_magic; /* magic number for identification */ + __le32 h_refcount; /* reference count */ + __u32 h_reserved[4]; /* zero right now */ +}; + +struct f2fs_xattr_entry { + __u8 e_name_index; + __u8 e_name_len; + __le16 e_value_size; /* size of attribute value */ + char e_name[0]; /* attribute name */ +}; + +#define XATTR_HDR(ptr) ((struct f2fs_xattr_header *)(ptr)) +#define XATTR_ENTRY(ptr) ((struct f2fs_xattr_entry *)(ptr)) +#define XATTR_FIRST_ENTRY(ptr) (XATTR_ENTRY(XATTR_HDR(ptr) + 1)) +#define XATTR_ROUND (3) + +#define XATTR_ALIGN(size) ((size + XATTR_ROUND) & ~XATTR_ROUND) + +#define ENTRY_SIZE(entry) (XATTR_ALIGN(sizeof(struct f2fs_xattr_entry) + \ + entry->e_name_len + le16_to_cpu(entry->e_value_size))) + +#define XATTR_NEXT_ENTRY(entry) ((struct f2fs_xattr_entry *)((char *)(entry) +\ + ENTRY_SIZE(entry))) + +#define IS_XATTR_LAST_ENTRY(entry) (*(__u32 *)(entry) == 0) + +#define list_for_each_xattr(entry, addr) \ + for (entry = XATTR_FIRST_ENTRY(addr);\ + !IS_XATTR_LAST_ENTRY(entry);\ + entry = XATTR_NEXT_ENTRY(entry)) + +#define MIN_OFFSET(i) XATTR_ALIGN(inline_xattr_size(i) + PAGE_SIZE - \ + sizeof(struct node_footer) - sizeof(__u32)) + +#define MAX_VALUE_LEN(i) (MIN_OFFSET(i) - \ + sizeof(struct f2fs_xattr_header) - \ + sizeof(struct f2fs_xattr_entry)) + +/* + * On-disk structure of f2fs_xattr + * We use inline xattrs space + 1 block for xattr. + * + * +--------------------+ + * | f2fs_xattr_header | + * | | + * +--------------------+ + * | f2fs_xattr_entry | + * | .e_name_index = 1 | + * | .e_name_len = 3 | + * | .e_value_size = 14 | + * | .e_name = "foo" | + * | "value_of_xattr" |<- value_offs = e_name + e_name_len + * +--------------------+ + * | f2fs_xattr_entry | + * | .e_name_index = 4 | + * | .e_name = "bar" | + * +--------------------+ + * | | + * | Free | + * | | + * +--------------------+<- MIN_OFFSET + * | node_footer | + * | (nid, ino, offset) | + * +--------------------+ + * + **/ + +#ifdef CONFIG_F2FS_FS_XATTR +extern const struct xattr_handler f2fs_xattr_user_handler; +extern const struct xattr_handler f2fs_xattr_trusted_handler; +extern const struct xattr_handler f2fs_xattr_advise_handler; +extern const struct xattr_handler f2fs_xattr_security_handler; + +extern const struct xattr_handler *f2fs_xattr_handlers[]; + +extern int f2fs_setxattr(struct inode *, int, const char *, + const void *, size_t, struct page *, int); +extern int f2fs_getxattr(struct inode *, int, const char *, void *, size_t); +extern ssize_t f2fs_listxattr(struct dentry *, char *, size_t); +#else + +#define f2fs_xattr_handlers NULL +static inline int f2fs_setxattr(struct inode *inode, int index, + const char *name, const void *value, size_t size, int flags) +{ + return -EOPNOTSUPP; +} +static inline int f2fs_getxattr(struct inode *inode, int index, + const char *name, void *buffer, size_t buffer_size) +{ + return -EOPNOTSUPP; +} +static inline ssize_t f2fs_listxattr(struct dentry *dentry, char *buffer, + size_t buffer_size) +{ + return -EOPNOTSUPP; +} +#endif + +#ifdef CONFIG_F2FS_FS_SECURITY +extern int f2fs_init_security(struct inode *, struct inode *, + const struct qstr *, struct page *); +#else +static inline int f2fs_init_security(struct inode *inode, struct inode *dir, + const struct qstr *qstr, struct page *ipage) +{ + return 0; +} +#endif +#endif /* __F2FS_XATTR_H__ */ diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 65e174bd065..eed0657a887 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -887,7 +887,7 @@ EXPORT_SYMBOL_GPL(fat_get_dotdot_entry); int fat_dir_empty(struct inode *dir) { struct buffer_head *bh; - struct msdos_dir_entry *de; + struct msdos_dir_entry *de = NULL; loff_t cpos; int result = 0; @@ -913,7 +913,7 @@ EXPORT_SYMBOL_GPL(fat_dir_empty); int fat_subdirs(struct inode *dir) { struct buffer_head *bh; - struct msdos_dir_entry *de; + struct msdos_dir_entry *de = NULL; loff_t cpos; int count = 0; diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1b21e0a061d..07de22815e5 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -46,6 +46,7 @@ struct wb_writeback_work { unsigned int for_kupdate:1; unsigned int range_cyclic:1; unsigned int for_background:1; + unsigned int for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ enum wb_reason reason; /* why was writeback initiated? */ struct list_head list; /* pending work list */ @@ -411,9 +412,11 @@ writeback_single_inode(struct inode *inode, struct bdi_writeback *wb, /* * Make sure to wait on the data before writing out the metadata. * This is important for filesystems that modify metadata on data - * I/O completion. + * I/O completion. We don't do it for sync(2) writeback because it has a + * separate, external IO completion path and ->sync_fs for guaranteeing + * inode metadata is written back correctly. */ - if (wbc->sync_mode == WB_SYNC_ALL) { + if (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync) { int err = filemap_fdatawait(mapping); if (ret == 0) ret = err; @@ -540,6 +543,7 @@ static long writeback_sb_inodes(struct super_block *sb, .tagged_writepages = work->tagged_writepages, .for_kupdate = work->for_kupdate, .for_background = work->for_background, + .for_sync = work->for_sync, .range_cyclic = work->range_cyclic, .range_start = 0, .range_end = LLONG_MAX, @@ -677,10 +681,6 @@ static bool over_bground_thresh(struct backing_dev_info *bdi) global_dirty_limits(&background_thresh, &dirty_thresh); - if (global_page_state(NR_FILE_DIRTY) + - global_page_state(NR_UNSTABLE_NFS) > background_thresh) - return true; - if (bdi_stat(bdi, BDI_RECLAIMABLE) > bdi_dirty_limit(bdi, background_thresh)) return true; @@ -948,7 +948,7 @@ int bdi_writeback_thread(void *data) */ set_user_nice(current, 0); - trace_writeback_thread_start(bdi); +// trace_writeback_thread_start(bdi); while (!kthread_freezable_should_stop(NULL)) { /* @@ -959,7 +959,7 @@ int bdi_writeback_thread(void *data) pages_written = wb_do_writeback(wb, 0); - trace_writeback_pages_written(pages_written); +// trace_writeback_pages_written(pages_written); if (pages_written) wb->last_active = jiffies; @@ -986,7 +986,7 @@ int bdi_writeback_thread(void *data) if (!list_empty(&bdi->work_list)) wb_do_writeback(wb, 1); - trace_writeback_thread_stop(bdi); +// trace_writeback_thread_stop(bdi); return 0; } @@ -999,10 +999,8 @@ void wakeup_flusher_threads(long nr_pages, enum wb_reason reason) { struct backing_dev_info *bdi; - if (!nr_pages) { - nr_pages = global_page_state(NR_FILE_DIRTY) + - global_page_state(NR_UNSTABLE_NFS); - } + if (!nr_pages) + nr_pages = get_nr_dirty_pages(); rcu_read_lock(); list_for_each_entry_rcu(bdi, &bdi_list, bdi_list) { @@ -1308,6 +1306,7 @@ void sync_inodes_sb(struct super_block *sb) .range_cyclic = 0, .done = &done, .reason = WB_REASON_SYNC, + .for_sync = 1, }; WARN_ON(!rwsem_is_locked(&sb->s_umount)); diff --git a/fs/fuse/control.c b/fs/fuse/control.c index 42593c587d4..2f0b4f34ab9 100644 --- a/fs/fuse/control.c +++ b/fs/fuse/control.c @@ -123,7 +123,7 @@ static ssize_t fuse_conn_max_background_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned val; + unsigned val = 0; ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, @@ -160,7 +160,7 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { - unsigned val; + unsigned val = 0; ssize_t ret; ret = fuse_conn_limit_write(file, buf, count, ppos, &val, diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 0971e921780..2d4fa2f5a2f 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -680,7 +680,7 @@ int journal_bmap(journal_t *journal, unsigned int blocknr, struct journal_head *journal_get_descriptor_buffer(journal_t *journal) { struct buffer_head *bh; - unsigned int blocknr; + unsigned int blocknr = 0; int err; err = journal_next_log_block(journal, &blocknr); @@ -824,7 +824,7 @@ journal_t * journal_init_inode (struct inode *inode) journal_t *journal = journal_init_common(); int err; int n; - unsigned int blocknr; + unsigned int blocknr = 0; if (!journal) return NULL; @@ -936,7 +936,7 @@ static int journal_reset(journal_t *journal) **/ int journal_create(journal_t *journal) { - unsigned int blocknr; + unsigned int blocknr = 0; struct buffer_head *bh; journal_superblock_t *sb; int i, err; diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 1afb701622b..06fae82896c 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -518,20 +518,17 @@ int jbd2_log_start_commit(journal_t *journal, tid_t tid) } /* - * Force and wait upon a commit if the calling process is not within - * transaction. This is used for forcing out undo-protected data which contains - * bitmaps, when the fs is running out of space. - * - * We can only force the running transaction if we don't have an active handle; - * otherwise, we will deadlock. - * - * Returns true if a transaction was started. + * Force and wait any uncommitted transactions. We can only force the running + * transaction if we don't have an active handle, otherwise, we will deadlock. + * Returns: <0 in case of error, + * 0 if nothing to commit, + * 1 if transaction was successfully committed. */ -int jbd2_journal_force_commit_nested(journal_t *journal) +static int __jbd2_journal_force_commit(journal_t *journal) { transaction_t *transaction = NULL; tid_t tid; - int need_to_start = 0; + int need_to_start = 0, ret = 0; read_lock(&journal->j_state_lock); if (journal->j_running_transaction && !current->journal_info) { @@ -542,16 +539,53 @@ int jbd2_journal_force_commit_nested(journal_t *journal) transaction = journal->j_committing_transaction; if (!transaction) { + /* Nothing to commit */ read_unlock(&journal->j_state_lock); - return 0; /* Nothing to retry */ + return 0; } - tid = transaction->t_tid; read_unlock(&journal->j_state_lock); if (need_to_start) jbd2_log_start_commit(journal, tid); - jbd2_log_wait_commit(journal, tid); - return 1; + ret = jbd2_log_wait_commit(journal, tid); + if (!ret) + ret = 1; + + return ret; +} + +/** + * Force and wait upon a commit if the calling process is not within + * transaction. This is used for forcing out undo-protected data which contains + * bitmaps, when the fs is running out of space. + * + * @journal: journal to force + * Returns true if progress was made. + */ +int jbd2_journal_force_commit_nested(journal_t *journal) +{ + int ret; + + ret = __jbd2_journal_force_commit(journal); + return ret > 0; +} + +/** + * int journal_force_commit() - force any uncommitted transactions + * @journal: journal to force + * + * Caller want unconditional commit. We can only force the running transaction + * if we don't have an active handle, otherwise, we will deadlock. + */ +int jbd2_journal_force_commit(journal_t *journal) +{ + int ret; + + J_ASSERT(!current->journal_info); + ret = __jbd2_journal_force_commit(journal); + if (ret > 0) + ret = 0; + return ret; } /* @@ -667,7 +701,7 @@ int jbd2_log_wait_commit(journal_t *journal, tid_t tid) int jbd2_journal_next_log_block(journal_t *journal, unsigned long long *retp) { - unsigned long blocknr; + unsigned long blocknr = 0; write_lock(&journal->j_state_lock); J_ASSERT(journal->j_free > 1); @@ -724,7 +758,7 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, struct journal_head *jbd2_journal_get_descriptor_buffer(journal_t *journal) { struct buffer_head *bh; - unsigned long long blocknr; + unsigned long long blocknr = 0; int err; err = jbd2_journal_next_log_block(journal, &blocknr); @@ -1098,7 +1132,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode) char *p; int err; int n; - unsigned long long blocknr; + unsigned long long blocknr = 0; if (!journal) return NULL; diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index ddcd3549c6c..ccf27b9f23e 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1495,29 +1495,6 @@ int jbd2_journal_stop(handle_t *handle) return err; } -/** - * int jbd2_journal_force_commit() - force any uncommitted transactions - * @journal: journal to force - * - * For synchronous operations: force any uncommitted transactions - * to disk. May seem kludgy, but it reuses all the handle batching - * code in a very simple manner. - */ -int jbd2_journal_force_commit(journal_t *journal) -{ - handle_t *handle; - int ret; - - handle = jbd2_journal_start(journal, 1); - if (IS_ERR(handle)) { - ret = PTR_ERR(handle); - } else { - handle->h_sync = 1; - ret = jbd2_journal_stop(handle); - } - return ret; -} - /* * * List management code snippets: various functions for manipulating the diff --git a/fs/namei.c b/fs/namei.c index c42791914f8..4a353b8aad1 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2743,7 +2743,7 @@ int vfs_rmdir(struct inode *dir, struct dentry *dentry) static long do_rmdir(int dfd, const char __user *pathname) { int error = 0; - char * name; + char * name = NULL; struct dentry *dentry; struct nameidata nd; @@ -2839,7 +2839,7 @@ int vfs_unlink(struct inode *dir, struct dentry *dentry) static long do_unlinkat(int dfd, const char __user *pathname) { int error; - char *name; + char *name = NULL; struct dentry *dentry; struct nameidata nd; struct inode *inode = NULL; @@ -3239,8 +3239,8 @@ SYSCALL_DEFINE4(renameat, int, olddfd, const char __user *, oldname, struct dentry *old_dentry, *new_dentry; struct dentry *trap; struct nameidata oldnd, newnd; - char *from; - char *to; + char *from = NULL; + char *to = NULL; int error; error = user_path_parent(olddfd, oldname, &oldnd, &from); diff --git a/fs/namespace.c b/fs/namespace.c index e6081996c9a..0968eb5d8f5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -2141,6 +2141,35 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, if (data_page) ((char *)data_page)[PAGE_SIZE - 1] = 0; +#ifdef CONFIG_RESTRICT_ROOTFS_SLAVE + /* Check if this is an attempt to mark "/" as recursive-slave. */ + if (strcmp(dir_name, "/") == 0 && flags == (MS_SLAVE | MS_REC)) { + static const char storage[] = "/storage"; + static const char source[] = "/mnt/shell/emulated"; + long res; + + /* Mark /storage as recursive-slave instead. */ + if ((res = do_mount(NULL, (char *)storage, NULL, (MS_SLAVE | MS_REC), NULL)) == 0) { + /* Unfortunately bind mounts from outside /storage may retain the + * recursive-shared property (bug?). This means any additional + * namespace-specific bind mounts (e.g., /storage/emulated/0/Android/obb) + * will also appear, shared in all namespaces, at their respective source + * paths (e.g., /mnt/shell/emulated/0/Android/obb), possibly leading to + * hundreds of /proc/mounts-visible bind mounts. As a workaround, mark + * /mnt/shell/emulated also as recursive-slave so that subsequent bind + * mounts are confined to their namespaces. */ + if ((res = do_mount(NULL, (char *)source, NULL, (MS_SLAVE | MS_REC), NULL)) == 0) + /* Both paths successfully marked as slave, leave the rest of the + * filesystem hierarchy alone. */ + return 0; + else + pr_warn("Failed to mount %s as MS_SLAVE: %ld\n", source, res); + } else { + pr_warn("Failed to mount %s as MS_SLAVE: %ld\n", storage, res); + } + /* Fallback: Mark rootfs as recursive-slave as requested. */ + } +#endif /* ... and get the mountpoint */ retval = kern_path(dir_name, LOOKUP_FOLLOW, &path); if (retval) @@ -2361,9 +2390,9 @@ SYSCALL_DEFINE5(mount, char __user *, dev_name, char __user *, dir_name, char __user *, type, unsigned long, flags, void __user *, data) { int ret; - char *kernel_type; + char *kernel_type = NULL; char *kernel_dir; - char *kernel_dev; + char *kernel_dev = NULL; unsigned long data_page; ret = copy_mount_string(type, &kernel_type); diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index e8bbfa5b350..2c0c609a45a 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -79,7 +79,7 @@ int nfs_wait_bit_killable(void *word) { if (fatal_signal_pending(current)) return -ERESTARTSYS; - freezable_schedule(); + freezable_schedule_unsafe(); return 0; } diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c index 5242eae6711..2ab36b4caa6 100644 --- a/fs/nfs/nfs3proc.c +++ b/fs/nfs/nfs3proc.c @@ -33,7 +33,7 @@ nfs3_rpc_wrapper(struct rpc_clnt *clnt, struct rpc_message *msg, int flags) res = rpc_call_sync(clnt, msg, flags); if (res != -EJUKEBOX && res != -EKEYEXPIRED) break; - freezable_schedule_timeout_killable(NFS_JUKEBOX_RETRY_TIME); + freezable_schedule_timeout_killable_unsafe(NFS_JUKEBOX_RETRY_TIME); res = -ERESTARTSYS; } while (!fatal_signal_pending(current)); return res; diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 99650aaf893..bf6b8dfa3e2 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -248,7 +248,7 @@ static int nfs4_delay(struct rpc_clnt *clnt, long *timeout) *timeout = NFS4_POLL_RETRY_MIN; if (*timeout > NFS4_POLL_RETRY_MAX) *timeout = NFS4_POLL_RETRY_MAX; - freezable_schedule_timeout_killable(*timeout); + freezable_schedule_timeout_killable_unsafe(*timeout); if (fatal_signal_pending(current)) res = -ERESTARTSYS; *timeout <<= 1; @@ -4161,7 +4161,7 @@ int nfs4_proc_delegreturn(struct inode *inode, struct rpc_cred *cred, const nfs4 static unsigned long nfs4_set_lock_task_retry(unsigned long timeout) { - freezable_schedule_timeout_killable(timeout); + freezable_schedule_timeout_killable_unsafe(timeout); timeout <<= 1; if (timeout > NFS4_LOCK_MAXTIMEOUT) return NFS4_LOCK_MAXTIMEOUT; diff --git a/fs/posix_acl.c b/fs/posix_acl.c index 5e325a42e33..e740f0c5002 100644 --- a/fs/posix_acl.c +++ b/fs/posix_acl.c @@ -18,7 +18,10 @@ #include #include #include +#include +#include #include +#include #include @@ -28,6 +31,33 @@ EXPORT_SYMBOL(posix_acl_valid); EXPORT_SYMBOL(posix_acl_equiv_mode); EXPORT_SYMBOL(posix_acl_from_mode); +struct posix_acl *get_acl(struct inode *inode, int type) +{ + struct posix_acl *acl; + + acl = get_cached_acl(inode, type); + if (acl != ACL_NOT_CACHED) + return acl; + + if (!IS_POSIXACL(inode)) + return NULL; + + /* + * A filesystem can force a ACL callback by just never filling the + * ACL cache. But normally you'd fill the cache either at inode + * instantiation time, or on the first ->get_acl call. + * + * If the filesystem doesn't have a get_acl() function at all, we'll + * just create the negative cache entry. + */ + if (!inode->i_op->get_acl) { + set_cached_acl(inode, type, NULL); + return NULL; + } + return inode->i_op->get_acl(inode, type); +} +EXPORT_SYMBOL(get_acl); + /* * Init a fresh posix_acl */ @@ -384,7 +414,7 @@ static int posix_acl_chmod_masq(struct posix_acl *acl, umode_t mode) } int -posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p) +__posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p) { struct posix_acl *clone = posix_acl_clone(*acl, gfp); int err = -ENOMEM; @@ -399,10 +429,10 @@ posix_acl_create(struct posix_acl **acl, gfp_t gfp, umode_t *mode_p) *acl = clone; return err; } -EXPORT_SYMBOL(posix_acl_create); +EXPORT_SYMBOL(__posix_acl_create); int -posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode) +__posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode) { struct posix_acl *clone = posix_acl_clone(*acl, gfp); int err = -ENOMEM; @@ -417,4 +447,346 @@ posix_acl_chmod(struct posix_acl **acl, gfp_t gfp, umode_t mode) *acl = clone; return err; } +EXPORT_SYMBOL(__posix_acl_chmod); + +int +posix_acl_chmod(struct inode *inode, umode_t mode) +{ + struct posix_acl *acl; + int ret = 0; + + if (!IS_POSIXACL(inode)) + return 0; + if (!inode->i_op->set_acl) + return -EOPNOTSUPP; + + acl = get_acl(inode, ACL_TYPE_ACCESS); + if (IS_ERR_OR_NULL(acl)) + return PTR_ERR(acl); + + ret = __posix_acl_chmod(&acl, GFP_KERNEL, mode); + if (ret) + return ret; + ret = inode->i_op->set_acl(inode, acl, ACL_TYPE_ACCESS); + posix_acl_release(acl); + return ret; +} EXPORT_SYMBOL(posix_acl_chmod); + +int +posix_acl_create(struct inode *dir, umode_t *mode, + struct posix_acl **default_acl, struct posix_acl **acl) +{ + struct posix_acl *p; + int ret; + + if (S_ISLNK(*mode) || !IS_POSIXACL(dir)) + goto no_acl; + + p = get_acl(dir, ACL_TYPE_DEFAULT); + if (IS_ERR(p)) + return PTR_ERR(p); + + if (!p) { + *mode &= ~current_umask(); + goto no_acl; + } + + *acl = posix_acl_clone(p, GFP_NOFS); + if (!*acl) + return -ENOMEM; + + ret = posix_acl_create_masq(*acl, mode); + if (ret < 0) { + posix_acl_release(*acl); + return -ENOMEM; + } + + if (ret == 0) { + posix_acl_release(*acl); + *acl = NULL; + } + + if (!S_ISDIR(*mode)) { + posix_acl_release(p); + *default_acl = NULL; + } else { + *default_acl = p; + } + return 0; + +no_acl: + *default_acl = NULL; + *acl = NULL; + return 0; +} +EXPORT_SYMBOL_GPL(posix_acl_create); + +/* + * Fix up the uids and gids in posix acl extended attributes in place. + */ +static void posix_acl_fix_xattr_userns( + struct user_namespace *to, struct user_namespace *from, + void *value, size_t size) +{ + posix_acl_xattr_header *header = (posix_acl_xattr_header *)value; + posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end; + int count; + kuid_t uid; + kgid_t gid; + + if (!value) + return; + if (size < sizeof(posix_acl_xattr_header)) + return; + if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) + return; + + count = posix_acl_xattr_count(size); + if (count < 0) + return; + if (count == 0) + return; + + for (end = entry + count; entry != end; entry++) { + switch(le16_to_cpu(entry->e_tag)) { + case ACL_USER: + uid = make_kuid(from, le32_to_cpu(entry->e_id)); + entry->e_id = cpu_to_le32(from_kuid(to, uid)); + break; + case ACL_GROUP: + gid = make_kgid(from, le32_to_cpu(entry->e_id)); + entry->e_id = cpu_to_le32(from_kgid(to, gid)); + break; + default: + break; + } + } +} + +void posix_acl_fix_xattr_from_user(void *value, size_t size) +{ + struct user_namespace *user_ns = current_user_ns(); + if (user_ns == &init_user_ns) + return; + posix_acl_fix_xattr_userns(&init_user_ns, user_ns, value, size); +} + +void posix_acl_fix_xattr_to_user(void *value, size_t size) +{ + struct user_namespace *user_ns = current_user_ns(); + if (user_ns == &init_user_ns) + return; + posix_acl_fix_xattr_userns(user_ns, &init_user_ns, value, size); +} + +/* + * Convert from extended attribute to in-memory representation. + */ +struct posix_acl * +posix_acl_from_xattr(struct user_namespace *user_ns, + const void *value, size_t size) +{ + posix_acl_xattr_header *header = (posix_acl_xattr_header *)value; + posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end; + int count; + struct posix_acl *acl; + struct posix_acl_entry *acl_e; + + if (!value) + return NULL; + if (size < sizeof(posix_acl_xattr_header)) + return ERR_PTR(-EINVAL); + if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) + return ERR_PTR(-EOPNOTSUPP); + + count = posix_acl_xattr_count(size); + if (count < 0) + return ERR_PTR(-EINVAL); + if (count == 0) + return NULL; + + acl = posix_acl_alloc(count, GFP_NOFS); + if (!acl) + return ERR_PTR(-ENOMEM); + acl_e = acl->a_entries; + + for (end = entry + count; entry != end; acl_e++, entry++) { + acl_e->e_tag = le16_to_cpu(entry->e_tag); + acl_e->e_perm = le16_to_cpu(entry->e_perm); + + switch(acl_e->e_tag) { + case ACL_USER_OBJ: + case ACL_GROUP_OBJ: + case ACL_MASK: + case ACL_OTHER: + break; + + case ACL_USER: + acl_e->e_uid = + make_kuid(user_ns, + le32_to_cpu(entry->e_id)); + if (!uid_valid(acl_e->e_uid)) + goto fail; + break; + case ACL_GROUP: + acl_e->e_gid = + make_kgid(user_ns, + le32_to_cpu(entry->e_id)); + if (!gid_valid(acl_e->e_gid)) + goto fail; + break; + + default: + goto fail; + } + } + return acl; + +fail: + posix_acl_release(acl); + return ERR_PTR(-EINVAL); +} +EXPORT_SYMBOL (posix_acl_from_xattr); + +/* + * Convert from in-memory to extended attribute representation. + */ +int +posix_acl_to_xattr(struct user_namespace *user_ns, const struct posix_acl *acl, + void *buffer, size_t size) +{ + posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer; + posix_acl_xattr_entry *ext_entry = ext_acl->a_entries; + int real_size, n; + + real_size = posix_acl_xattr_size(acl->a_count); + if (!buffer) + return real_size; + if (real_size > size) + return -ERANGE; + + ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); + + for (n=0; n < acl->a_count; n++, ext_entry++) { + const struct posix_acl_entry *acl_e = &acl->a_entries[n]; + ext_entry->e_tag = cpu_to_le16(acl_e->e_tag); + ext_entry->e_perm = cpu_to_le16(acl_e->e_perm); + switch(acl_e->e_tag) { + case ACL_USER: + ext_entry->e_id = + cpu_to_le32(from_kuid(user_ns, acl_e->e_uid)); + break; + case ACL_GROUP: + ext_entry->e_id = + cpu_to_le32(from_kgid(user_ns, acl_e->e_gid)); + break; + default: + ext_entry->e_id = cpu_to_le32(ACL_UNDEFINED_ID); + break; + } + } + return real_size; +} +EXPORT_SYMBOL (posix_acl_to_xattr); + +static int +posix_acl_xattr_get(struct dentry *dentry, const char *name, + void *value, size_t size, int type) +{ + struct posix_acl *acl; + int error; + + if (!IS_POSIXACL(dentry->d_inode)) + return -EOPNOTSUPP; + if (S_ISLNK(dentry->d_inode->i_mode)) + return -EOPNOTSUPP; + + acl = get_acl(dentry->d_inode, type); + if (IS_ERR(acl)) + return PTR_ERR(acl); + if (acl == NULL) + return -ENODATA; + + error = posix_acl_to_xattr(&init_user_ns, acl, value, size); + posix_acl_release(acl); + + return error; +} + +static int +posix_acl_xattr_set(struct dentry *dentry, const char *name, + const void *value, size_t size, int flags, int type) +{ + struct inode *inode = dentry->d_inode; + struct posix_acl *acl = NULL; + int ret; + + if (!IS_POSIXACL(inode)) + return -EOPNOTSUPP; + if (!inode->i_op->set_acl) + return -EOPNOTSUPP; + + if (type == ACL_TYPE_DEFAULT && !S_ISDIR(inode->i_mode)) + return value ? -EACCES : 0; + if (!inode_owner_or_capable(inode)) + return -EPERM; + + if (value) { + acl = posix_acl_from_xattr(&init_user_ns, value, size); + if (IS_ERR(acl)) + return PTR_ERR(acl); + + if (acl) { + ret = posix_acl_valid(acl); + if (ret) + goto out; + } + } + + ret = inode->i_op->set_acl(inode, acl, type); +out: + posix_acl_release(acl); + return ret; +} + +static size_t +posix_acl_xattr_list(struct dentry *dentry, char *list, size_t list_size, + const char *name, size_t name_len, int type) +{ + const char *xname; + size_t size; + + if (!IS_POSIXACL(dentry->d_inode)) + return -EOPNOTSUPP; + if (S_ISLNK(dentry->d_inode->i_mode)) + return -EOPNOTSUPP; + + if (type == ACL_TYPE_ACCESS) + xname = POSIX_ACL_XATTR_ACCESS; + else + xname = POSIX_ACL_XATTR_DEFAULT; + + size = strlen(xname) + 1; + if (list && size <= list_size) + memcpy(list, xname, size); + return size; +} + +const struct xattr_handler posix_acl_access_xattr_handler = { + .prefix = POSIX_ACL_XATTR_ACCESS, + .flags = ACL_TYPE_ACCESS, + .list = posix_acl_xattr_list, + .get = posix_acl_xattr_get, + .set = posix_acl_xattr_set, +}; +EXPORT_SYMBOL_GPL(posix_acl_access_xattr_handler); + +const struct xattr_handler posix_acl_default_xattr_handler = { + .prefix = POSIX_ACL_XATTR_DEFAULT, + .flags = ACL_TYPE_DEFAULT, + .list = posix_acl_xattr_list, + .get = posix_acl_xattr_get, + .set = posix_acl_xattr_set, +}; +EXPORT_SYMBOL_GPL(posix_acl_default_xattr_handler); diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c index 80e4645f799..33f9e9b8176 100644 --- a/fs/proc/meminfo.c +++ b/fs/proc/meminfo.c @@ -87,6 +87,9 @@ static int meminfo_proc_show(struct seq_file *m, void *v) "SUnreclaim: %8lu kB\n" "KernelStack: %8lu kB\n" "PageTables: %8lu kB\n" +#ifdef CONFIG_UKSM + "KsmZeroPages: %8lu kB\n" +#endif #ifdef CONFIG_QUICKLIST "Quicklists: %8lu kB\n" #endif @@ -146,6 +149,9 @@ static int meminfo_proc_show(struct seq_file *m, void *v) K(global_page_state(NR_SLAB_UNRECLAIMABLE)), global_page_state(NR_KERNEL_STACK) * THREAD_SIZE / 1024, K(global_page_state(NR_PAGETABLE)), +#ifdef CONFIG_UKSM + K(global_page_state(NR_UKSM_ZERO_PAGES)), +#endif #ifdef CONFIG_QUICKLIST K(quicklist_total_size()), #endif diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 1030a716d15..a789934737e 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -90,6 +90,56 @@ static void pad_len_spaces(struct seq_file *m, int len) seq_printf(m, "%*c", len, ' '); } +static void seq_print_vma_name(struct seq_file *m, struct vm_area_struct *vma) +{ + const char __user *name = vma_get_anon_name(vma); + struct mm_struct *mm = vma->vm_mm; + + unsigned long page_start_vaddr; + unsigned long page_offset; + unsigned long num_pages; + unsigned long max_len = NAME_MAX; + int i; + + page_start_vaddr = (unsigned long)name & PAGE_MASK; + page_offset = (unsigned long)name - page_start_vaddr; + num_pages = DIV_ROUND_UP(page_offset + max_len, PAGE_SIZE); + + seq_puts(m, "[anon:"); + + for (i = 0; i < num_pages; i++) { + int len; + int write_len; + const char *kaddr; + long pages_pinned; + struct page *page; + + pages_pinned = get_user_pages(current, mm, page_start_vaddr, + 1, 0, 0, &page, NULL); + if (pages_pinned < 1) { + seq_puts(m, "]"); + return; + } + + kaddr = (const char *)kmap(page); + len = min(max_len, PAGE_SIZE - page_offset); + write_len = strnlen(kaddr + page_offset, len); + seq_write(m, kaddr + page_offset, write_len); + kunmap(page); + put_page(page); + + /* if strnlen hit a null terminator then we're done */ + if (write_len != len) + break; + + max_len -= len; + page_offset = 0; + page_start_vaddr += PAGE_SIZE; + } + + seq_putc(m, ']'); +} + static void vma_stop(struct proc_maps_private *priv, struct vm_area_struct *vma) { if (vma && vma != priv->tail_vma) { @@ -289,6 +339,12 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) pad_len_spaces(m, len); seq_printf(m, "[stack:%d]", tid); } + goto done; + } + + if (vma_get_anon_name(vma)) { + pad_len_spaces(m, len); + seq_print_vma_name(m, vma); } } @@ -521,6 +577,12 @@ static int show_smap(struct seq_file *m, void *v, int is_pid) (vma->vm_flags & VM_LOCKED) ? (unsigned long)(mss.pss >> (10 + PSS_SHIFT)) : 0); + if (vma_get_anon_name(vma)) { + seq_puts(m, "Name: "); + seq_print_vma_name(m, vma); + seq_putc(m, '\n'); + } + if (m->count < m->size) /* vma is copied successfully */ m->version = (vma != get_gate_vma(task->mm)) ? vma->vm_start : 0; diff --git a/fs/read_write.c b/fs/read_write.c index ffc99d22e0a..9de0f4acd2f 100644 --- a/fs/read_write.c +++ b/fs/read_write.c @@ -50,6 +50,98 @@ static loff_t lseek_execute(struct file *file, struct inode *inode, return offset; } +/** + * vfs_setpos - update the file offset for lseek + * @file: file structure in question + * @offset: file offset to seek to + * @maxsize: maximum file size + * + * This is a low-level filesystem helper for updating the file offset to + * the value specified by @offset if the given offset is valid and it is + * not equal to the current file offset. + * + * Return the specified offset on success and -EINVAL on invalid offset. + */ +loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize) +{ + if (offset < 0 && !unsigned_offsets(file)) + return -EINVAL; + if (offset > maxsize) + return -EINVAL; + + if (offset != file->f_pos) { + file->f_pos = offset; + file->f_version = 0; + } + return offset; +} +EXPORT_SYMBOL(vfs_setpos); + +/** + * generic_file_llseek_size - generic llseek implementation for regular files + * @file: file structure to seek on + * @offset: file offset to seek to + * @whence: type of seek + * @size: max size of this file in file system + * @eof: offset used for SEEK_END position + * + * This is a variant of generic_file_llseek that allows passing in a custom + * maximum file size and a custom EOF position, for e.g. hashed directories + * + * Synchronization: + * SEEK_SET and SEEK_END are unsynchronized (but atomic on 64bit platforms) + * SEEK_CUR is synchronized against other SEEK_CURs, but not read/writes. + * read/writes behave like SEEK_SET against seeks. + */ +loff_t +__generic_file_llseek_size(struct file *file, loff_t offset, int whence, + loff_t maxsize, loff_t eof) +{ + switch (whence) { + case SEEK_END: + offset += eof; + break; + case SEEK_CUR: + /* + * Here we special-case the lseek(fd, 0, SEEK_CUR) + * position-querying operation. Avoid rewriting the "same" + * f_pos value back to the file because a concurrent read(), + * write() or lseek() might have altered it + */ + if (offset == 0) + return file->f_pos; + /* + * f_lock protects against read/modify/write race with other + * SEEK_CURs. Note that parallel writes and reads behave + * like SEEK_SET. + */ + spin_lock(&file->f_lock); + offset = vfs_setpos(file, file->f_pos + offset, maxsize); + spin_unlock(&file->f_lock); + return offset; + case SEEK_DATA: + /* + * In the generic case the entire file is data, so as long as + * offset isn't at the end of the file then the offset is data. + */ + if (offset >= eof) + return -ENXIO; + break; + case SEEK_HOLE: + /* + * There is a virtual hole at the end of the file, so as long as + * offset isn't i_size or larger, return i_size. + */ + if (offset >= eof) + return -ENXIO; + offset = eof; + break; + } + + return vfs_setpos(file, offset, maxsize); +} +EXPORT_SYMBOL(__generic_file_llseek_size); + /** * generic_file_llseek_size - generic llseek implementation for regular files * @file: file structure to seek on diff --git a/fs/select.c b/fs/select.c index 17d33d09fc1..ca7e8e31a19 100644 --- a/fs/select.c +++ b/fs/select.c @@ -26,6 +26,7 @@ #include #include #include +#include #include @@ -236,7 +237,8 @@ int poll_schedule_timeout(struct poll_wqueues *pwq, int state, set_current_state(state); if (!pwq->triggered) - rc = schedule_hrtimeout_range(expires, slack, HRTIMER_MODE_ABS); + rc = freezable_schedule_hrtimeout_range(expires, slack, + HRTIMER_MODE_ABS); __set_current_state(TASK_RUNNING); /* diff --git a/fs/seq_file.c b/fs/seq_file.c index 0cbd0494b79..b857a379616 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c @@ -132,6 +132,7 @@ static int traverse(struct seq_file *m, loff_t offset) Eoverflow: m->op->stop(m, p); kfree(m->buf); + m->count = 0; m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); return !m->buf ? -ENOMEM : -EAGAIN; } @@ -228,10 +229,10 @@ ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos) goto Fill; m->op->stop(m, p); kfree(m->buf); + m->count = 0; m->buf = kmalloc(m->size <<= 1, GFP_KERNEL); if (!m->buf) goto Enomem; - m->count = 0; m->version = 0; pos = m->index; p = m->op->start(m, &pos); @@ -324,6 +325,8 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin) m->read_pos = offset; retval = file->f_pos = offset; } + } else { + file->f_pos = offset; } } file->f_version = m->version; diff --git a/fs/sync.c b/fs/sync.c index 0e8db939d96..45493399aa2 100644 --- a/fs/sync.c +++ b/fs/sync.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,11 @@ #include #include "internal.h" +#ifdef CONFIG_DYNAMIC_FSYNC +extern bool early_suspend_active; +extern bool dyn_fsync_active; +#endif + #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \ SYNC_FILE_RANGE_WAIT_AFTER) @@ -86,7 +92,7 @@ static void sync_one_sb(struct super_block *sb, void *arg) * Sync all the data for all the filesystems (called by sys_sync() and * emergency sync) */ -static void sync_filesystems(int wait) +void sync_filesystems(int wait) { iterate_supers(sync_one_sb, &wait); } @@ -95,13 +101,67 @@ static void sync_filesystems(int wait) * sync everything. Start out by waking pdflush, because that writes back * all queues in parallel. */ -SYSCALL_DEFINE0(sync) +static void do_sync(void) { wakeup_flusher_threads(0, WB_REASON_SYNC); sync_filesystems(0); sync_filesystems(1); if (unlikely(laptop_mode)) laptop_sync_completion(); + return; +} + +static DEFINE_MUTEX(sync_mutex); /* One do_sync() at a time. */ +static unsigned long sync_seq; /* Many sync()s from one do_sync(). */ + /* Overflow harmless, extra wait. */ + +/* + * Only allow one task to do sync() at a time, and further allow + * concurrent sync() calls to be satisfied by a single do_sync() + * invocation. + */ +SYSCALL_DEFINE0(sync) +{ + unsigned long snap; + unsigned long snap_done; + + snap = ACCESS_ONCE(sync_seq); + smp_mb(); /* Prevent above from bleeding into critical section. */ + mutex_lock(&sync_mutex); + snap_done = sync_seq; + + /* + * If the value in snap is odd, we need to wait for the current + * do_sync() to complete, then wait for the next one, in other + * words, we need the value of snap_done to be three larger than + * the value of snap. On the other hand, if the value in snap is + * even, we only have to wait for the next request to complete, + * in other words, we need the value of snap_done to be only two + * greater than the value of snap. The "(snap + 3) & 0x1" computes + * this for us (thank you, Linus!). + */ + if (ULONG_CMP_GE(snap_done, (snap + 3) & ~0x1)) { + /* + * A full do_sync() executed between our two fetches from + * sync_seq, so our work is done! + */ + smp_mb(); /* Order test with caller's subsequent code. */ + mutex_unlock(&sync_mutex); + return 0; + } + + /* Record the start of do_sync(). */ + ACCESS_ONCE(sync_seq)++; + WARN_ON_ONCE((sync_seq & 0x1) != 1); + smp_mb(); /* Keep prior increment out of do_sync(). */ + + do_sync(); + + /* Record the end of do_sync(). */ + smp_mb(); /* Keep subsequent increment out of do_sync(). */ + ACCESS_ONCE(sync_seq)++; + WARN_ON_ONCE((sync_seq & 0x1) != 0); + mutex_unlock(&sync_mutex); return 0; } @@ -164,9 +224,17 @@ SYSCALL_DEFINE1(syncfs, int, fd) */ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync) { +#ifdef CONFIG_DYNAMIC_FSYNC + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else { +#endif if (!file->f_op || !file->f_op->fsync) return -EINVAL; return file->f_op->fsync(file, start, end, datasync); +#ifdef CONFIG_DYNAMIC_FSYNC + } +#endif } EXPORT_SYMBOL(vfs_fsync_range); @@ -179,7 +247,7 @@ EXPORT_SYMBOL(vfs_fsync_range); * set only metadata needed to access modified file data is written. */ int vfs_fsync(struct file *file, int datasync) -{ +{ return vfs_fsync_range(file, 0, LLONG_MAX, datasync); } EXPORT_SYMBOL(vfs_fsync); @@ -188,22 +256,33 @@ static int do_fsync(unsigned int fd, int datasync) { struct file *file; int ret = -EBADF; - - file = fget(fd); + int fput_needed; + + file = fget_light(fd, &fput_needed); if (file) { ret = vfs_fsync(file, datasync); - fput(file); + fput_light(file, fput_needed); } return ret; } SYSCALL_DEFINE1(fsync, unsigned int, fd) { +#ifdef CONFIG_DYNAMIC_FSYNC + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else +#endif return do_fsync(fd, 0); } SYSCALL_DEFINE1(fdatasync, unsigned int, fd) { +#if 0 + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else +#endif return do_fsync(fd, 1); } @@ -216,7 +295,7 @@ SYSCALL_DEFINE1(fdatasync, unsigned int, fd) * This is just a simple wrapper about our general syncing function. */ int generic_write_sync(struct file *file, loff_t pos, loff_t count) -{ +{ if (!(file->f_flags & O_DSYNC) && !IS_SYNC(file->f_mapping->host)) return 0; return vfs_fsync_range(file, pos, pos + count - 1, @@ -274,6 +353,12 @@ EXPORT_SYMBOL(generic_write_sync); SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes, unsigned int flags) { +#ifdef CONFIG_DYNAMIC_FSYNC + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else { +#endif + int ret; struct file *file; struct address_space *mapping; @@ -353,6 +438,9 @@ SYSCALL_DEFINE(sync_file_range)(int fd, loff_t offset, loff_t nbytes, fput_light(file, fput_needed); out: return ret; +#ifdef CONFIG_DYNAMIC_FSYNC + } +#endif } #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS asmlinkage long SyS_sync_file_range(long fd, loff_t offset, loff_t nbytes, @@ -369,6 +457,11 @@ SYSCALL_ALIAS(sys_sync_file_range, SyS_sync_file_range); SYSCALL_DEFINE(sync_file_range2)(int fd, unsigned int flags, loff_t offset, loff_t nbytes) { +#ifdef CONFIG_DYNAMIC_FSYNC + if (likely(dyn_fsync_active && !early_suspend_active)) + return 0; + else +#endif return sys_sync_file_range(fd, offset, nbytes, flags); } #ifdef CONFIG_HAVE_SYSCALL_WRAPPERS diff --git a/fs/xattr_acl.c b/fs/xattr_acl.c deleted file mode 100644 index 69d06b07b16..00000000000 --- a/fs/xattr_acl.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * linux/fs/xattr_acl.c - * - * Almost all from linux/fs/ext2/acl.c: - * Copyright (C) 2001 by Andreas Gruenbacher, - */ - -#include -#include -#include -#include - - -/* - * Convert from extended attribute to in-memory representation. - */ -struct posix_acl * -posix_acl_from_xattr(const void *value, size_t size) -{ - posix_acl_xattr_header *header = (posix_acl_xattr_header *)value; - posix_acl_xattr_entry *entry = (posix_acl_xattr_entry *)(header+1), *end; - int count; - struct posix_acl *acl; - struct posix_acl_entry *acl_e; - - if (!value) - return NULL; - if (size < sizeof(posix_acl_xattr_header)) - return ERR_PTR(-EINVAL); - if (header->a_version != cpu_to_le32(POSIX_ACL_XATTR_VERSION)) - return ERR_PTR(-EOPNOTSUPP); - - count = posix_acl_xattr_count(size); - if (count < 0) - return ERR_PTR(-EINVAL); - if (count == 0) - return NULL; - - acl = posix_acl_alloc(count, GFP_NOFS); - if (!acl) - return ERR_PTR(-ENOMEM); - acl_e = acl->a_entries; - - for (end = entry + count; entry != end; acl_e++, entry++) { - acl_e->e_tag = le16_to_cpu(entry->e_tag); - acl_e->e_perm = le16_to_cpu(entry->e_perm); - - switch(acl_e->e_tag) { - case ACL_USER_OBJ: - case ACL_GROUP_OBJ: - case ACL_MASK: - case ACL_OTHER: - acl_e->e_id = ACL_UNDEFINED_ID; - break; - - case ACL_USER: - case ACL_GROUP: - acl_e->e_id = le32_to_cpu(entry->e_id); - break; - - default: - goto fail; - } - } - return acl; - -fail: - posix_acl_release(acl); - return ERR_PTR(-EINVAL); -} -EXPORT_SYMBOL (posix_acl_from_xattr); - -/* - * Convert from in-memory to extended attribute representation. - */ -int -posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size) -{ - posix_acl_xattr_header *ext_acl = (posix_acl_xattr_header *)buffer; - posix_acl_xattr_entry *ext_entry = ext_acl->a_entries; - int real_size, n; - - real_size = posix_acl_xattr_size(acl->a_count); - if (!buffer) - return real_size; - if (real_size > size) - return -ERANGE; - - ext_acl->a_version = cpu_to_le32(POSIX_ACL_XATTR_VERSION); - - for (n=0; n < acl->a_count; n++, ext_entry++) { - ext_entry->e_tag = cpu_to_le16(acl->a_entries[n].e_tag); - ext_entry->e_perm = cpu_to_le16(acl->a_entries[n].e_perm); - ext_entry->e_id = cpu_to_le32(acl->a_entries[n].e_id); - } - return real_size; -} -EXPORT_SYMBOL (posix_acl_to_xattr); diff --git a/glitch.sh b/glitch.sh new file mode 100755 index 00000000000..6e0db454802 --- /dev/null +++ b/glitch.sh @@ -0,0 +1,171 @@ +#!/bin/bash + +# Glitch kernel build-script (Aroma Edition) # +# # +# Options : # +# # +# clean : clean the build directory # +# cleank : clean the built kernel packages # +################################################# + +############## Basic configuration ############## + +# Device options : + target_name="N7" #defines the flashable zip device name + target_variant="" #defines the flashable zip additional name for variants + target_device="N7-2013" #defines the name of device-related folders (can be the same as $target_name) + target_defconfig="Glitch_flo_defconfig" #defines the config to use for the build + +# Toolchain selection : +# (default path is "kernel_tree_folder/../toolchains") +# -------linux-x86 + #export CROSS_PREFIX="arm-eabi-4.6/bin/arm-eabi-" + #export CROSS_PREFIX="sabermod-androideabi-4.8.3/bin/arm-linux-androideabi-" + export CROSS_PREFIX="arm-cortex_a15-linux-gnueabihf-linaro_4.9.2-2014.09/bin/arm-cortex_a15-linux-gnueabihf-" + +# -------darwin-x86 + #export CROSS_PREFIX="" + +########## End of basic configuration ############ + +setup () +{ +function mka() { + case `uname -s` in + Darwin) + make -j `sysctl hw.ncpu|cut -d" " -f2` "$@" + ;; + *) + schedtool -B -n 1 -e ionice -n 1 make -j `cat /proc/cpuinfo | grep "^processor" | wc -l` "$@" + ;; + esac +}; + +# Arch-dependent definitions + case `uname -s` in + Darwin) + KERNEL_DIR="$(dirname "$(greadlink -f "$0")")" + CROSS_PREFIX="$KERNEL_DIR/../toolchains/$CROSS_PREFIX" + ;; + *) + KERNEL_DIR="$(dirname "$(readlink -f "$0")")" + CROSS_PREFIX="$KERNEL_DIR/../toolchains/$CROSS_PREFIX" + ;; + esac + + BUILD_DIR="../glitch-build/kernel" + + if [ x = "x$NO_CCACHE" ] && ccache -V &>/dev/null ; then + CCACHE=ccache + CCACHE_BASEDIR="$KERNEL_DIR" + CCACHE_COMPRESS=1 + CCACHE_DIR="$KERNEL_DIR/../.ccache" + export CCACHE_DIR CCACHE_COMPRESS CCACHE_BASEDIR + else + CCACHE="" + fi + +} + +build () +{ + export ARCH="arm" + local target=$target_device + echo "-----------------------------------------" + echo "Building for $target_device" + local target_dir="$BUILD_DIR/$target_device" + local module + rm -fr "$target_dir" + rm -f $KERNEL_DIR/tmp_$target_defconfig + rm -f $KERNEL_DIR/arch/arm/configs/release_$target_defconfig + mkdir -p "$target_dir" + +. $KERNEL_DIR/../rev + +counter=$((counter + 1)) + +echo "-----------------------------------------" +echo "Write release number in config (r"$counter")" +releasenumber='CONFIG_LOCALVERSION="-Glitch-N7-AOSP-r'$counter'"' +cp arch/arm/configs/$target_defconfig tmp_$target_defconfig; +sed "43s/.*/$releasenumber/g" tmp_$target_defconfig > release_$target_defconfig; +mv release_$target_defconfig arch/arm/configs/release_$target_defconfig +rm -f $KERNEL_DIR/tmp_$target_defconfig + + mka -C "$KERNEL_DIR" O="$target_dir" release_$target_defconfig HOSTCC="$CCACHE gcc" + mka -C "$KERNEL_DIR" O="$target_dir" HOSTCC="$CCACHE gcc" CROSS_COMPILE="$CCACHE $CROSS_PREFIX" zImage modules + +[[ -d release ]] || { + echo "-----------------------------------------" + echo "must be in kernel root dir" + exit 1; +} + +echo "-----------------------------------------" +echo "copying modules and zImage" +mkdir -p $KERNEL_DIR/release/aroma/system/lib/modules/ +cd $target_dir +find -name '*.ko' -exec cp -av {} $KERNEL_DIR/release/aroma/system/lib/modules/ \; +"$CROSS_PREFIX"strip --strip-unneeded $KERNEL_DIR/release/aroma/system/lib/modules/* +cd $KERNEL_DIR +mv $target_dir/arch/arm/boot/zImage $KERNEL_DIR/release/aroma/boot/glitch.zImage + +cd $KERNEL_DIR +rm -f arch/arm/configs/release_$target_defconfig +echo "-----------------------------------------" +echo "Setting date in Aroma conf ("$(date +%B)" "$(date +%e)" "$(date +%Y)")" +AromaDateReplace='ini_set("rom_date", "'$(date +%B)' '$(date +%e)' '$(date +%Y)'");' +sed "37s/.*/$AromaDateReplace/g" ./release/aroma/META-INF/com/google/android/aroma-config > ./aroma-config.tmp; +mv ./aroma-config.tmp ./release/aroma/META-INF/com/google/android/aroma-config + +echo "-----------------------------------------" +echo "packaging it up" +cd release/aroma + +mkdir -p $KERNEL_DIR/release/$target_device +REL=Glitch-$target_name-r$counter$target_variant.zip + + zip -q -r ${REL} boot config META-INF system wifi_mod + #sha256sum ${REL} > ${REL}.sha256sum + mv ${REL}* $KERNEL_DIR/release/$target_device/ + +echo counter=$counter > $KERNEL_DIR/../rev; + +rm boot/glitch.zImage +rm -r system/lib/modules/* + +echo "-----------------------------------------" +echo ${REL} +} + +setup + +if [ "$1" = clean ] ; then + rm -fr "$BUILD_DIR"/* + cd release + rm `find ./ -name '*.*~'` -rf + rm `find ./ -name '*~'` -rf + cd $KERNEL_DIR + rm -f $KERNEL_DIR/tmp_$target_defconfig + rm -f arch/arm/configs/release_$target_defconfig + echo "-----------------------------" + echo "Previous build folder cleaned" + echo "-----------------------------" + +else + +if [ "$1" = cleank ] ; then + rm -fr "$KERNEL_DIR"/release/$target_device/* + echo "---------------------" + echo "Built kernels cleaned" + echo "---------------------" + +else + +time { + + build $target_device + +} +fi +fi diff --git a/include/drm/kgsl_drm.h b/include/drm/kgsl_drm.h index f1c7f4e22f3..8a4d56f94be 100644 --- a/include/drm/kgsl_drm.h +++ b/include/drm/kgsl_drm.h @@ -19,6 +19,12 @@ #define DRM_KGSL_GEM_UNLOCK_HANDLE 0x0C #define DRM_KGSL_GEM_UNLOCK_ON_TS 0x0D #define DRM_KGSL_GEM_CREATE_FD 0x0E +#define DRM_KGSL_GEM_GET_ION_FD 0x0F +#define DRM_KGSL_GEM_CREATE_FROM_ION 0x10 +#define DRM_KGSL_GEM_SET_GLOCK_HANDLES_INFO 0x11 +#define DRM_KGSL_GEM_GET_GLOCK_HANDLES_INFO 0x12 +#define DRM_KGSL_GEM_GET_BUFCOUNT 0x13 + #define DRM_IOCTL_KGSL_GEM_CREATE \ DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE, struct drm_kgsl_gem_create) @@ -55,6 +61,10 @@ DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_BUFINFO, \ DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_BUFCOUNT, \ struct drm_kgsl_gem_bufcount) +#define DRM_IOCTL_KGSL_GEM_GET_BUFCOUNT \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_BUFCOUNT, \ + struct drm_kgsl_gem_bufcount) + #define DRM_IOCTL_KGSL_GEM_SET_ACTIVE \ DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_ACTIVE, \ struct drm_kgsl_gem_active) @@ -75,6 +85,24 @@ struct drm_kgsl_gem_unlock_on_ts) DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FD, \ struct drm_kgsl_gem_create_fd) +#define DRM_IOCTL_KGSL_GEM_GET_ION_FD \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_ION_FD, \ +struct drm_kgsl_gem_get_ion_fd) + +#define DRM_IOCTL_KGSL_GEM_CREATE_FROM_ION \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_CREATE_FROM_ION, \ +struct drm_kgsl_gem_create_from_ion) + +#define DRM_IOCTL_KGSL_GEM_SET_GLOCK_HANDLES_INFO \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_SET_GLOCK_HANDLES_INFO, \ +struct drm_kgsl_gem_glockinfo) + +#define DRM_IOCTL_KGSL_GEM_GET_GLOCK_HANDLES_INFO \ +DRM_IOWR(DRM_COMMAND_BASE + DRM_KGSL_GEM_GET_GLOCK_HANDLES_INFO, \ +struct drm_kgsl_gem_glockinfo) + + + /* Maximum number of sub buffers per GEM object */ #define DRM_KGSL_GEM_MAX_BUFFERS 2 @@ -157,6 +185,11 @@ struct drm_kgsl_gem_bufinfo { uint32_t gpuaddr[DRM_KGSL_GEM_MAX_BUFFERS]; }; +struct drm_kgsl_gem_glockinfo { + uint32_t handle; + int glockhandle[DRM_KGSL_GEM_MAX_BUFFERS]; +}; + struct drm_kgsl_gem_bufcount { uint32_t handle; uint32_t bufcount; @@ -189,4 +222,14 @@ struct drm_kgsl_gem_create_fd { uint32_t handle; }; +struct drm_kgsl_gem_get_ion_fd { + uint32_t ion_fd; + uint32_t handle; +}; + +struct drm_kgsl_gem_create_from_ion { + uint32_t ion_fd; + uint32_t handle; +}; + #endif diff --git a/include/linux/alarmtimer.h b/include/linux/alarmtimer.h index 96c5c249b08..f122c9fbf8c 100644 --- a/include/linux/alarmtimer.h +++ b/include/linux/alarmtimer.h @@ -35,6 +35,7 @@ enum alarmtimer_restart { */ struct alarm { struct timerqueue_node node; + struct hrtimer timer; enum alarmtimer_restart (*function)(struct alarm *, ktime_t now); enum alarmtimer_type type; int state; @@ -43,7 +44,7 @@ struct alarm { void alarm_init(struct alarm *alarm, enum alarmtimer_type type, enum alarmtimer_restart (*function)(struct alarm *, ktime_t)); -void alarm_start(struct alarm *alarm, ktime_t start); +int alarm_start(struct alarm *alarm, ktime_t start); int alarm_try_to_cancel(struct alarm *alarm); int alarm_cancel(struct alarm *alarm); diff --git a/include/linux/audit.h b/include/linux/audit.h index ed3ef197249..513486e4675 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -27,6 +27,7 @@ #include #include #include +#include /* The netlink messages for the audit system is divided into blocks: * 1000 - 1099 are for commanding the audit system @@ -441,6 +442,8 @@ struct audit_krule { struct audit_field { u32 type; u32 val; + kuid_t uid; + kgid_t gid; u32 op; char *lsm_str; void *lsm_rule; diff --git a/include/linux/bio.h b/include/linux/bio.h index 4d94eb8bcbc..5fabe5040a7 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -135,6 +135,13 @@ static inline int bio_has_allocated_vec(struct bio *bio) #define bio_io_error(bio) bio_endio((bio), -EIO) +/* + * drivers should _never_ use the all version - the bio may have been split + * before it got to the driver and the driver won't own all of it + */ +#define bio_for_each_segment_all(bvl, bio, i) \ + for (i = 0, bvl = (bio)->bi_io_vec; i < (bio)->bi_vcnt; i++, bvl++) + /* * drivers should not use the __ version unless they _really_ want to * run through the entire bio and not just pending pieces @@ -222,6 +229,8 @@ extern void bio_endio(struct bio *, int); struct request_queue; extern int bio_phys_segments(struct request_queue *, struct bio *); +extern int submit_bio_wait(int rw, struct bio *bio); + extern void __bio_clone(struct bio *, struct bio *); extern struct bio *bio_clone(struct bio *, gfp_t); diff --git a/include/linux/bitops.h b/include/linux/bitops.h index a3b6b82108b..c1dde8e00d2 100644 --- a/include/linux/bitops.h +++ b/include/linux/bitops.h @@ -185,6 +185,21 @@ static inline unsigned long __ffs64(u64 word) #ifdef __KERNEL__ +#ifndef set_mask_bits +#define set_mask_bits(ptr, _mask, _bits) \ +({ \ + const typeof(*ptr) mask = (_mask), bits = (_bits); \ + typeof(*ptr) old, new; \ + \ + do { \ + old = ACCESS_ONCE(*ptr); \ + new = (old & ~mask) | bits; \ + } while (cmpxchg(ptr, old, new) != old); \ + \ + new; \ +}) +#endif + #ifndef find_last_bit /** * find_last_bit - find the last set bit in a memory region diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index 9c49d17cbe1..2b4542a285b 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -135,7 +135,7 @@ enum rq_flag_bits { * throttling rules. Don't do it again. */ /* request only flags */ - __REQ_SORTED, /* elevator knows about this request */ + __REQ_SORTED = __REQ_RAHEAD, /* elevator knows about this request */ __REQ_SOFTBARRIER, /* may not be passed by ioscheduler */ __REQ_NOMERGE, /* don't touch this for merging */ __REQ_STARTED, /* drive already may have started this one */ @@ -151,6 +151,7 @@ enum rq_flag_bits { __REQ_IO_STAT, /* account I/O stat */ __REQ_MIXED_MERGE, /* merge of different types, fail separately */ __REQ_SANITIZE, /* sanitize */ + __REQ_URGENT, /* urgent request */ __REQ_NR_BITS, /* stops here */ }; @@ -163,6 +164,7 @@ enum rq_flag_bits { #define REQ_PRIO (1 << __REQ_PRIO) #define REQ_DISCARD (1 << __REQ_DISCARD) #define REQ_SANITIZE (1 << __REQ_SANITIZE) +#define REQ_URGENT (1 << __REQ_URGENT) #define REQ_NOIDLE (1 << __REQ_NOIDLE) #define REQ_FAILFAST_MASK \ diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index e76b0ae3368..65028417fbc 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -282,6 +282,7 @@ struct request_queue { struct request_list rq; request_fn_proc *request_fn; + request_fn_proc *urgent_request_fn; make_request_fn *make_request_fn; prep_rq_fn *prep_rq_fn; unprep_rq_fn *unprep_rq_fn; @@ -365,6 +366,8 @@ struct request_queue { struct list_head icq_list; struct queue_limits limits; + bool notified_urgent; + bool dispatched_urgent; /* * sg stuff @@ -673,6 +676,8 @@ extern struct request *blk_get_request(struct request_queue *, int, gfp_t); extern struct request *blk_make_request(struct request_queue *, struct bio *, gfp_t); extern void blk_requeue_request(struct request_queue *, struct request *); +extern int blk_reinsert_request(struct request_queue *q, struct request *rq); +extern bool blk_reinsert_req_sup(struct request_queue *q); extern void blk_add_request_payload(struct request *rq, struct page *page, unsigned int len); extern int blk_rq_check_limits(struct request_queue *q, struct request *rq); @@ -822,6 +827,7 @@ extern struct request_queue *blk_init_queue_node(request_fn_proc *rfn, extern struct request_queue *blk_init_queue(request_fn_proc *, spinlock_t *); extern struct request_queue *blk_init_allocated_queue(struct request_queue *, request_fn_proc *, spinlock_t *); +extern void blk_urgent_request(struct request_queue *q, request_fn_proc *fn); extern void blk_cleanup_queue(struct request_queue *); extern void blk_queue_make_request(struct request_queue *, make_request_fn *); extern void blk_queue_bounce_limit(struct request_queue *, u64); diff --git a/include/linux/completion.h b/include/linux/completion.h index a5b2e1ca5ce..33f0280fd53 100644 --- a/include/linux/completion.h +++ b/include/linux/completion.h @@ -82,6 +82,8 @@ extern int wait_for_completion_interruptible(struct completion *x); extern int wait_for_completion_killable(struct completion *x); extern unsigned long wait_for_completion_timeout(struct completion *x, unsigned long timeout); +extern unsigned long wait_for_completion_io_timeout(struct completion *x, + unsigned long timeout); extern long wait_for_completion_interruptible_timeout( struct completion *x, unsigned long timeout); extern long wait_for_completion_killable_timeout( diff --git a/include/linux/console.h b/include/linux/console.h index 7201ce4280c..dffe4772a53 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -153,6 +153,7 @@ extern int braille_register_console(struct console *, int index, extern int braille_unregister_console(struct console *); extern void console_sysfs_notify(void); extern bool console_suspend_enabled; +extern int is_console_suspended(void); /* Suspend and resume console messages over PM events */ extern void suspend_console(void); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 34edac89eca..f38193f2cf6 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -373,12 +373,18 @@ extern struct cpufreq_governor cpufreq_gov_userspace; #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND) extern struct cpufreq_governor cpufreq_gov_ondemand; #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_ondemand) +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_ELEMENTALX) +extern struct cpufreq_governor cpufreq_gov_elementalx; +#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_elementalx) #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE) extern struct cpufreq_governor cpufreq_gov_conservative; #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative) #elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTERACTIVE) extern struct cpufreq_governor cpufreq_gov_interactive; #define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_interactive) +#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_INTELLIDEMAND) +extern struct cpufreq_governor cpufreq_gov_intellidemand; +#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_intellidemand) #endif diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h index 6c26a3da0e0..fa7d3dcd36f 100644 --- a/include/linux/cpuidle.h +++ b/include/linux/cpuidle.h @@ -34,6 +34,7 @@ struct cpuidle_driver; struct cpuidle_state_usage { void *driver_data; + unsigned long long disable; unsigned long long usage; unsigned long long time; /* in US */ }; @@ -46,7 +47,6 @@ struct cpuidle_state { unsigned int exit_latency; /* in US */ int power_usage; /* in mW */ unsigned int target_residency; /* in US */ - unsigned int disable; int (*enter) (struct cpuidle_device *dev, struct cpuidle_driver *drv, @@ -124,9 +124,9 @@ struct cpuidle_driver { const char *name; struct module *owner; - unsigned int power_specified:1; /* set to 1 to use the core cpuidle time keeping (for all states). */ unsigned int en_core_tk_irqen:1; + /* states array must be ordered in decreasing power consumption */ struct cpuidle_state states[CPUIDLE_STATE_MAX]; int state_count; int safe_state_index; diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 7e11f141820..960f5a21ebb 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -114,6 +114,7 @@ struct dentry { } d_u; struct list_head d_subdirs; /* our children */ struct list_head d_alias; /* inode alias list */ + struct hlist_node __d_alias; /* inode alias list V3.15*/ }; /* @@ -227,6 +228,8 @@ extern struct dentry * d_make_root(struct inode *); /* - the ramfs-type tree */ extern void d_genocide(struct dentry *); +extern void d_tmpfile(struct dentry *, struct inode *); + extern struct dentry *d_find_alias(struct inode *); extern void d_prune_aliases(struct inode *); diff --git a/include/linux/debug_locks.h b/include/linux/debug_locks.h index 3bd46f76675..a975de1ff59 100644 --- a/include/linux/debug_locks.h +++ b/include/linux/debug_locks.h @@ -51,7 +51,7 @@ struct task_struct; extern void debug_show_all_locks(void); extern void debug_show_held_locks(struct task_struct *task); extern void debug_check_no_locks_freed(const void *from, unsigned long len); -extern void debug_check_no_locks_held(struct task_struct *task); +extern void debug_check_no_locks_held(void); #else static inline void debug_show_all_locks(void) { @@ -67,7 +67,7 @@ debug_check_no_locks_freed(const void *from, unsigned long len) } static inline void -debug_check_no_locks_held(struct task_struct *task) +debug_check_no_locks_held(void) { } #endif diff --git a/include/linux/decompress/unlz4.h b/include/linux/decompress/unlz4.h new file mode 100644 index 00000000000..d5b68bf3ec9 --- /dev/null +++ b/include/linux/decompress/unlz4.h @@ -0,0 +1,10 @@ +#ifndef DECOMPRESS_UNLZ4_H +#define DECOMPRESS_UNLZ4_H + +int unlz4(unsigned char *inbuf, int len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *pos, + void(*error)(char *x)); +#endif diff --git a/include/linux/elevator.h b/include/linux/elevator.h index 7d4e0356f32..b36b28ffd31 100644 --- a/include/linux/elevator.h +++ b/include/linux/elevator.h @@ -22,6 +22,9 @@ typedef void (elevator_bio_merged_fn) (struct request_queue *, typedef int (elevator_dispatch_fn) (struct request_queue *, int); typedef void (elevator_add_req_fn) (struct request_queue *, struct request *); +typedef int (elevator_reinsert_req_fn) (struct request_queue *, + struct request *); +typedef bool (elevator_is_urgent_fn) (struct request_queue *); typedef struct request *(elevator_request_list_fn) (struct request_queue *, struct request *); typedef void (elevator_completed_req_fn) (struct request_queue *, struct request *); typedef int (elevator_may_queue_fn) (struct request_queue *, int); @@ -46,6 +49,9 @@ struct elevator_ops elevator_dispatch_fn *elevator_dispatch_fn; elevator_add_req_fn *elevator_add_req_fn; + elevator_reinsert_req_fn *elevator_reinsert_req_fn; + elevator_is_urgent_fn *elevator_is_urgent_fn; + elevator_activate_req_fn *elevator_activate_req_fn; elevator_deactivate_req_fn *elevator_deactivate_req_fn; @@ -122,6 +128,7 @@ extern void elv_merged_request(struct request_queue *, struct request *, int); extern void elv_bio_merged(struct request_queue *q, struct request *, struct bio *); extern void elv_requeue_request(struct request_queue *, struct request *); +extern int elv_reinsert_request(struct request_queue *, struct request *); extern struct request *elv_former_request(struct request_queue *, struct request *); extern struct request *elv_latter_request(struct request_queue *, struct request *); extern int elv_register_queue(struct request_queue *q); diff --git a/include/linux/f2fs_fs.h b/include/linux/f2fs_fs.h new file mode 100644 index 00000000000..a99354b1897 --- /dev/null +++ b/include/linux/f2fs_fs.h @@ -0,0 +1,436 @@ +/** + * include/linux/f2fs_fs.h + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. + * http://www.samsung.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 _LINUX_F2FS_FS_H +#define _LINUX_F2FS_FS_H + +#include +#include + +#define F2FS_SUPER_OFFSET 1024 /* byte-size offset */ +#define F2FS_LOG_SECTOR_SIZE 9 /* 9 bits for 512 byte */ +#define F2FS_LOG_SECTORS_PER_BLOCK 3 /* 4KB: F2FS_BLKSIZE */ +#define F2FS_BLKSIZE 4096 /* support only 4KB block */ +#define F2FS_MAX_EXTENSION 64 /* # of extension entries */ +#define F2FS_BLK_ALIGN(x) (((x) + F2FS_BLKSIZE - 1) / F2FS_BLKSIZE) + +#define NULL_ADDR ((block_t)0) /* used as block_t addresses */ +#define NEW_ADDR ((block_t)-1) /* used as block_t addresses */ + +#define F2FS_ROOT_INO(sbi) (sbi->root_ino_num) +#define F2FS_NODE_INO(sbi) (sbi->node_ino_num) +#define F2FS_META_INO(sbi) (sbi->meta_ino_num) + +/* This flag is used by node and meta inodes, and by recovery */ +#define GFP_F2FS_ZERO (GFP_NOFS | __GFP_ZERO) + +/* + * For further optimization on multi-head logs, on-disk layout supports maximum + * 16 logs by default. The number, 16, is expected to cover all the cases + * enoughly. The implementaion currently uses no more than 6 logs. + * Half the logs are used for nodes, and the other half are used for data. + */ +#define MAX_ACTIVE_LOGS 16 +#define MAX_ACTIVE_NODE_LOGS 8 +#define MAX_ACTIVE_DATA_LOGS 8 + +/* + * For superblock + */ +struct f2fs_super_block { + __le32 magic; /* Magic Number */ + __le16 major_ver; /* Major Version */ + __le16 minor_ver; /* Minor Version */ + __le32 log_sectorsize; /* log2 sector size in bytes */ + __le32 log_sectors_per_block; /* log2 # of sectors per block */ + __le32 log_blocksize; /* log2 block size in bytes */ + __le32 log_blocks_per_seg; /* log2 # of blocks per segment */ + __le32 segs_per_sec; /* # of segments per section */ + __le32 secs_per_zone; /* # of sections per zone */ + __le32 checksum_offset; /* checksum offset inside super block */ + __le64 block_count; /* total # of user blocks */ + __le32 section_count; /* total # of sections */ + __le32 segment_count; /* total # of segments */ + __le32 segment_count_ckpt; /* # of segments for checkpoint */ + __le32 segment_count_sit; /* # of segments for SIT */ + __le32 segment_count_nat; /* # of segments for NAT */ + __le32 segment_count_ssa; /* # of segments for SSA */ + __le32 segment_count_main; /* # of segments for main area */ + __le32 segment0_blkaddr; /* start block address of segment 0 */ + __le32 cp_blkaddr; /* start block address of checkpoint */ + __le32 sit_blkaddr; /* start block address of SIT */ + __le32 nat_blkaddr; /* start block address of NAT */ + __le32 ssa_blkaddr; /* start block address of SSA */ + __le32 main_blkaddr; /* start block address of main area */ + __le32 root_ino; /* root inode number */ + __le32 node_ino; /* node inode number */ + __le32 meta_ino; /* meta inode number */ + __u8 uuid[16]; /* 128-bit uuid for volume */ + __le16 volume_name[512]; /* volume name */ + __le32 extension_count; /* # of extensions below */ + __u8 extension_list[F2FS_MAX_EXTENSION][8]; /* extension array */ + __le32 cp_payload; +} __packed; + +/* + * For checkpoint + */ +#define CP_ERROR_FLAG 0x00000008 +#define CP_COMPACT_SUM_FLAG 0x00000004 +#define CP_ORPHAN_PRESENT_FLAG 0x00000002 +#define CP_UMOUNT_FLAG 0x00000001 + +struct f2fs_checkpoint { + __le64 checkpoint_ver; /* checkpoint block version number */ + __le64 user_block_count; /* # of user blocks */ + __le64 valid_block_count; /* # of valid blocks in main area */ + __le32 rsvd_segment_count; /* # of reserved segments for gc */ + __le32 overprov_segment_count; /* # of overprovision segments */ + __le32 free_segment_count; /* # of free segments in main area */ + + /* information of current node segments */ + __le32 cur_node_segno[MAX_ACTIVE_NODE_LOGS]; + __le16 cur_node_blkoff[MAX_ACTIVE_NODE_LOGS]; + /* information of current data segments */ + __le32 cur_data_segno[MAX_ACTIVE_DATA_LOGS]; + __le16 cur_data_blkoff[MAX_ACTIVE_DATA_LOGS]; + __le32 ckpt_flags; /* Flags : umount and journal_present */ + __le32 cp_pack_total_block_count; /* total # of one cp pack */ + __le32 cp_pack_start_sum; /* start block number of data summary */ + __le32 valid_node_count; /* Total number of valid nodes */ + __le32 valid_inode_count; /* Total number of valid inodes */ + __le32 next_free_nid; /* Next free node number */ + __le32 sit_ver_bitmap_bytesize; /* Default value 64 */ + __le32 nat_ver_bitmap_bytesize; /* Default value 256 */ + __le32 checksum_offset; /* checksum offset inside cp block */ + __le64 elapsed_time; /* mounted time */ + /* allocation type of current segment */ + unsigned char alloc_type[MAX_ACTIVE_LOGS]; + + /* SIT and NAT version bitmap */ + unsigned char sit_nat_version_bitmap[1]; +} __packed; + +/* + * For orphan inode management + */ +#define F2FS_ORPHANS_PER_BLOCK 1020 + +struct f2fs_orphan_block { + __le32 ino[F2FS_ORPHANS_PER_BLOCK]; /* inode numbers */ + __le32 reserved; /* reserved */ + __le16 blk_addr; /* block index in current CP */ + __le16 blk_count; /* Number of orphan inode blocks in CP */ + __le32 entry_count; /* Total number of orphan nodes in current CP */ + __le32 check_sum; /* CRC32 for orphan inode block */ +} __packed; + +/* + * For NODE structure + */ +struct f2fs_extent { + __le32 fofs; /* start file offset of the extent */ + __le32 blk_addr; /* start block address of the extent */ + __le32 len; /* lengh of the extent */ +} __packed; + +#define F2FS_NAME_LEN 255 +#define F2FS_INLINE_XATTR_ADDRS 50 /* 200 bytes for inline xattrs */ +#define DEF_ADDRS_PER_INODE 923 /* Address Pointers in an Inode */ +#define ADDRS_PER_INODE(fi) addrs_per_inode(fi) +#define ADDRS_PER_BLOCK 1018 /* Address Pointers in a Direct Block */ +#define NIDS_PER_BLOCK 1018 /* Node IDs in an Indirect Block */ + +#define NODE_DIR1_BLOCK (DEF_ADDRS_PER_INODE + 1) +#define NODE_DIR2_BLOCK (DEF_ADDRS_PER_INODE + 2) +#define NODE_IND1_BLOCK (DEF_ADDRS_PER_INODE + 3) +#define NODE_IND2_BLOCK (DEF_ADDRS_PER_INODE + 4) +#define NODE_DIND_BLOCK (DEF_ADDRS_PER_INODE + 5) + +#define F2FS_INLINE_XATTR 0x01 /* file inline xattr flag */ +#define F2FS_INLINE_DATA 0x02 /* file inline data flag */ + +#define MAX_INLINE_DATA (sizeof(__le32) * (DEF_ADDRS_PER_INODE - \ + F2FS_INLINE_XATTR_ADDRS - 1)) + +#define INLINE_DATA_OFFSET (PAGE_CACHE_SIZE - sizeof(struct node_footer) \ + - sizeof(__le32) * (DEF_ADDRS_PER_INODE + 5 - 1)) + +struct f2fs_inode { + __le16 i_mode; /* file mode */ + __u8 i_advise; /* file hints */ + __u8 i_inline; /* file inline flags */ + __le32 i_uid; /* user ID */ + __le32 i_gid; /* group ID */ + __le32 i_links; /* links count */ + __le64 i_size; /* file size in bytes */ + __le64 i_blocks; /* file size in blocks */ + __le64 i_atime; /* access time */ + __le64 i_ctime; /* change time */ + __le64 i_mtime; /* modification time */ + __le32 i_atime_nsec; /* access time in nano scale */ + __le32 i_ctime_nsec; /* change time in nano scale */ + __le32 i_mtime_nsec; /* modification time in nano scale */ + __le32 i_generation; /* file version (for NFS) */ + __le32 i_current_depth; /* only for directory depth */ + __le32 i_xattr_nid; /* nid to save xattr */ + __le32 i_flags; /* file attributes */ + __le32 i_pino; /* parent inode number */ + __le32 i_namelen; /* file name length */ + __u8 i_name[F2FS_NAME_LEN]; /* file name for SPOR */ + __u8 i_dir_level; /* dentry_level for large dir */ + + struct f2fs_extent i_ext; /* caching a largest extent */ + + __le32 i_addr[DEF_ADDRS_PER_INODE]; /* Pointers to data blocks */ + + __le32 i_nid[5]; /* direct(2), indirect(2), + double_indirect(1) node id */ +} __packed; + +struct direct_node { + __le32 addr[ADDRS_PER_BLOCK]; /* array of data block address */ +} __packed; + +struct indirect_node { + __le32 nid[NIDS_PER_BLOCK]; /* array of data block address */ +} __packed; + +enum { + COLD_BIT_SHIFT = 0, + FSYNC_BIT_SHIFT, + DENT_BIT_SHIFT, + OFFSET_BIT_SHIFT +}; + +struct node_footer { + __le32 nid; /* node id */ + __le32 ino; /* inode nunmber */ + __le32 flag; /* include cold/fsync/dentry marks and offset */ + __le64 cp_ver; /* checkpoint version */ + __le32 next_blkaddr; /* next node page block address */ +} __packed; + +struct f2fs_node { + /* can be one of three types: inode, direct, and indirect types */ + union { + struct f2fs_inode i; + struct direct_node dn; + struct indirect_node in; + }; + struct node_footer footer; +} __packed; + +/* + * For NAT entries + */ +#define NAT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_nat_entry)) + +struct f2fs_nat_entry { + __u8 version; /* latest version of cached nat entry */ + __le32 ino; /* inode number */ + __le32 block_addr; /* block address */ +} __packed; + +struct f2fs_nat_block { + struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK]; +} __packed; + +/* + * For SIT entries + * + * Each segment is 2MB in size by default so that a bitmap for validity of + * there-in blocks should occupy 64 bytes, 512 bits. + * Not allow to change this. + */ +#define SIT_VBLOCK_MAP_SIZE 64 +#define SIT_ENTRY_PER_BLOCK (PAGE_CACHE_SIZE / sizeof(struct f2fs_sit_entry)) + +/* + * Note that f2fs_sit_entry->vblocks has the following bit-field information. + * [15:10] : allocation type such as CURSEG_XXXX_TYPE + * [9:0] : valid block count + */ +#define SIT_VBLOCKS_SHIFT 10 +#define SIT_VBLOCKS_MASK ((1 << SIT_VBLOCKS_SHIFT) - 1) +#define GET_SIT_VBLOCKS(raw_sit) \ + (le16_to_cpu((raw_sit)->vblocks) & SIT_VBLOCKS_MASK) +#define GET_SIT_TYPE(raw_sit) \ + ((le16_to_cpu((raw_sit)->vblocks) & ~SIT_VBLOCKS_MASK) \ + >> SIT_VBLOCKS_SHIFT) + +struct f2fs_sit_entry { + __le16 vblocks; /* reference above */ + __u8 valid_map[SIT_VBLOCK_MAP_SIZE]; /* bitmap for valid blocks */ + __le64 mtime; /* segment age for cleaning */ +} __packed; + +struct f2fs_sit_block { + struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK]; +} __packed; + +/* + * For segment summary + * + * One summary block contains exactly 512 summary entries, which represents + * exactly 2MB segment by default. Not allow to change the basic units. + * + * NOTE: For initializing fields, you must use set_summary + * + * - If data page, nid represents dnode's nid + * - If node page, nid represents the node page's nid. + * + * The ofs_in_node is used by only data page. It represents offset + * from node's page's beginning to get a data block address. + * ex) data_blkaddr = (block_t)(nodepage_start_address + ofs_in_node) + */ +#define ENTRIES_IN_SUM 512 +#define SUMMARY_SIZE (7) /* sizeof(struct summary) */ +#define SUM_FOOTER_SIZE (5) /* sizeof(struct summary_footer) */ +#define SUM_ENTRY_SIZE (SUMMARY_SIZE * ENTRIES_IN_SUM) + +/* a summary entry for a 4KB-sized block in a segment */ +struct f2fs_summary { + __le32 nid; /* parent node id */ + union { + __u8 reserved[3]; + struct { + __u8 version; /* node version number */ + __le16 ofs_in_node; /* block index in parent node */ + } __packed; + }; +} __packed; + +/* summary block type, node or data, is stored to the summary_footer */ +#define SUM_TYPE_NODE (1) +#define SUM_TYPE_DATA (0) + +struct summary_footer { + unsigned char entry_type; /* SUM_TYPE_XXX */ + __u32 check_sum; /* summary checksum */ +} __packed; + +#define SUM_JOURNAL_SIZE (F2FS_BLKSIZE - SUM_FOOTER_SIZE -\ + SUM_ENTRY_SIZE) +#define NAT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\ + sizeof(struct nat_journal_entry)) +#define NAT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\ + sizeof(struct nat_journal_entry)) +#define SIT_JOURNAL_ENTRIES ((SUM_JOURNAL_SIZE - 2) /\ + sizeof(struct sit_journal_entry)) +#define SIT_JOURNAL_RESERVED ((SUM_JOURNAL_SIZE - 2) %\ + sizeof(struct sit_journal_entry)) +/* + * frequently updated NAT/SIT entries can be stored in the spare area in + * summary blocks + */ +enum { + NAT_JOURNAL = 0, + SIT_JOURNAL +}; + +struct nat_journal_entry { + __le32 nid; + struct f2fs_nat_entry ne; +} __packed; + +struct nat_journal { + struct nat_journal_entry entries[NAT_JOURNAL_ENTRIES]; + __u8 reserved[NAT_JOURNAL_RESERVED]; +} __packed; + +struct sit_journal_entry { + __le32 segno; + struct f2fs_sit_entry se; +} __packed; + +struct sit_journal { + struct sit_journal_entry entries[SIT_JOURNAL_ENTRIES]; + __u8 reserved[SIT_JOURNAL_RESERVED]; +} __packed; + +/* 4KB-sized summary block structure */ +struct f2fs_summary_block { + struct f2fs_summary entries[ENTRIES_IN_SUM]; + union { + __le16 n_nats; + __le16 n_sits; + }; + /* spare area is used by NAT or SIT journals */ + union { + struct nat_journal nat_j; + struct sit_journal sit_j; + }; + struct summary_footer footer; +} __packed; + +/* + * For directory operations + */ +#define F2FS_DOT_HASH 0 +#define F2FS_DDOT_HASH F2FS_DOT_HASH +#define F2FS_MAX_HASH (~((0x3ULL) << 62)) +#define F2FS_HASH_COL_BIT ((0x1ULL) << 63) + +typedef __le32 f2fs_hash_t; + +/* One directory entry slot covers 8bytes-long file name */ +#define F2FS_SLOT_LEN 8 +#define F2FS_SLOT_LEN_BITS 3 + +#define GET_DENTRY_SLOTS(x) ((x + F2FS_SLOT_LEN - 1) >> F2FS_SLOT_LEN_BITS) + +/* the number of dentry in a block */ +#define NR_DENTRY_IN_BLOCK 214 + +/* MAX level for dir lookup */ +#define MAX_DIR_HASH_DEPTH 63 + +/* MAX buckets in one level of dir */ +#define MAX_DIR_BUCKETS (1 << ((MAX_DIR_HASH_DEPTH / 2) - 1)) + +#define SIZE_OF_DIR_ENTRY 11 /* by byte */ +#define SIZE_OF_DENTRY_BITMAP ((NR_DENTRY_IN_BLOCK + BITS_PER_BYTE - 1) / \ + BITS_PER_BYTE) +#define SIZE_OF_RESERVED (PAGE_SIZE - ((SIZE_OF_DIR_ENTRY + \ + F2FS_SLOT_LEN) * \ + NR_DENTRY_IN_BLOCK + SIZE_OF_DENTRY_BITMAP)) + +/* One directory entry slot representing F2FS_SLOT_LEN-sized file name */ +struct f2fs_dir_entry { + __le32 hash_code; /* hash code of file name */ + __le32 ino; /* inode number */ + __le16 name_len; /* lengh of file name */ + __u8 file_type; /* file type */ +} __packed; + +/* 4KB-sized directory entry block */ +struct f2fs_dentry_block { + /* validity bitmap for directory entries in each block */ + __u8 dentry_bitmap[SIZE_OF_DENTRY_BITMAP]; + __u8 reserved[SIZE_OF_RESERVED]; + struct f2fs_dir_entry dentry[NR_DENTRY_IN_BLOCK]; + __u8 filename[NR_DENTRY_IN_BLOCK][F2FS_SLOT_LEN]; +} __packed; + +/* file types used in inode_info->flags */ +enum { + F2FS_FT_UNKNOWN, + F2FS_FT_REG_FILE, + F2FS_FT_DIR, + F2FS_FT_CHRDEV, + F2FS_FT_BLKDEV, + F2FS_FT_FIFO, + F2FS_FT_SOCK, + F2FS_FT_SYMLINK, + F2FS_FT_MAX +}; + +#endif /* _LINUX_F2FS_FS_H */ diff --git a/include/linux/fastchg.h b/include/linux/fastchg.h new file mode 100644 index 00000000000..0570e039e22 --- /dev/null +++ b/include/linux/fastchg.h @@ -0,0 +1,23 @@ +/* + * Author: Chad Froebel + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + * + */ + +#ifndef _LINUX_FASTCHG_H +#define _LINUX_FASTCHG_H + +extern int force_fast_charge; + +#define FAST_CHARGE_DISABLED 0 /* default */ +#define FAST_CHARGE_FORCE_AC 1 + +#endif diff --git a/include/linux/freezer.h b/include/linux/freezer.h index 80e7faee928..ba9b9133f54 100644 --- a/include/linux/freezer.h +++ b/include/linux/freezer.h @@ -3,6 +3,7 @@ #ifndef FREEZER_H_INCLUDED #define FREEZER_H_INCLUDED +#include #include #include #include @@ -41,17 +42,36 @@ extern int freeze_kernel_threads(void); extern void thaw_processes(void); extern void thaw_kernel_threads(void); -static inline bool try_to_freeze(void) +/* + * HACK: prevent sleeping while atomic warnings due to ARM signal handling + * disabling irqs + */ +static inline bool try_to_freeze_nowarn(void) { -/* This causes problems for ARM targets and is a known - * problem upstream. - * might_sleep(); + if (likely(!freezing(current))) + return false; + return __refrigerator(false); +} + +/* + * DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION + * If try_to_freeze causes a lockdep warning it means the caller may deadlock */ +static inline bool try_to_freeze_unsafe(void) +{ + might_sleep(); if (likely(!freezing(current))) return false; return __refrigerator(false); } +static inline bool try_to_freeze(void) +{ + if (!(current->flags & PF_NOFREEZE)) + debug_check_no_locks_held(); + return try_to_freeze_unsafe(); +} + extern bool freeze_task(struct task_struct *p); extern bool set_freezable(void); @@ -78,54 +98,154 @@ static inline bool cgroup_freezing(struct task_struct *task) */ -/* Tell the freezer not to count the current task as freezable. */ +/** + * freezer_do_not_count - tell freezer to ignore %current + * + * Tell freezers to ignore the current task when determining whether the + * target frozen state is reached. IOW, the current task will be + * considered frozen enough by freezers. + * + * The caller shouldn't do anything which isn't allowed for a frozen task + * until freezer_cont() is called. Usually, freezer[_do_not]_count() pair + * wrap a scheduling operation and nothing much else. + */ static inline void freezer_do_not_count(void) { current->flags |= PF_FREEZER_SKIP; } -/* - * Tell the freezer to count the current task as freezable again and try to - * freeze it. +/** + * freezer_count - tell freezer to stop ignoring %current + * + * Undo freezer_do_not_count(). It tells freezers that %current should be + * considered again and tries to freeze if freezing condition is already in + * effect. */ static inline void freezer_count(void) { current->flags &= ~PF_FREEZER_SKIP; + /* + * If freezing is in progress, the following paired with smp_mb() + * in freezer_should_skip() ensures that either we see %true + * freezing() or freezer_should_skip() sees !PF_FREEZER_SKIP. + */ + smp_mb(); try_to_freeze(); } -/* - * Check if the task should be counted as freezable by the freezer +/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ +static inline void freezer_count_unsafe(void) +{ + current->flags &= ~PF_FREEZER_SKIP; + smp_mb(); + try_to_freeze_unsafe(); +} + +/** + * freezer_should_skip - whether to skip a task when determining frozen + * state is reached + * @p: task in quesion + * + * This function is used by freezers after establishing %true freezing() to + * test whether a task should be skipped when determining the target frozen + * state is reached. IOW, if this function returns %true, @p is considered + * frozen enough. */ -static inline int freezer_should_skip(struct task_struct *p) +static inline bool freezer_should_skip(struct task_struct *p) { - return !!(p->flags & PF_FREEZER_SKIP); + /* + * The following smp_mb() paired with the one in freezer_count() + * ensures that either freezer_count() sees %true freezing() or we + * see cleared %PF_FREEZER_SKIP and return %false. This makes it + * impossible for a task to slip frozen state testing after + * clearing %PF_FREEZER_SKIP. + */ + smp_mb(); + return p->flags & PF_FREEZER_SKIP; } /* - * These macros are intended to be used whenever you want allow a task that's + * These functions are intended to be used whenever you want allow a task that's * sleeping in TASK_UNINTERRUPTIBLE or TASK_KILLABLE state to be frozen. Note * that neither return any clear indication of whether a freeze event happened * while in this function. */ /* Like schedule(), but should not block the freezer. */ -#define freezable_schedule() \ -({ \ - freezer_do_not_count(); \ - schedule(); \ - freezer_count(); \ -}) +static inline void freezable_schedule(void) +{ + freezer_do_not_count(); + schedule(); + freezer_count(); +} + +/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ +static inline void freezable_schedule_unsafe(void) +{ + freezer_do_not_count(); + schedule(); + freezer_count_unsafe(); +} + +/* + * Like freezable_schedule_timeout(), but should not block the freezer. Do not + * call this with locks held. + */ +static inline long freezable_schedule_timeout(long timeout) +{ + long __retval; + freezer_do_not_count(); + __retval = schedule_timeout(timeout); + freezer_count(); + return __retval; +} + +/* + * Like schedule_timeout_interruptible(), but should not block the freezer. Do not + * call this with locks held. + */ +static inline long freezable_schedule_timeout_interruptible(long timeout) +{ + long __retval; + freezer_do_not_count(); + __retval = schedule_timeout_interruptible(timeout); + freezer_count(); + return __retval; +} /* Like schedule_timeout_killable(), but should not block the freezer. */ -#define freezable_schedule_timeout_killable(timeout) \ -({ \ - long __retval; \ - freezer_do_not_count(); \ - __retval = schedule_timeout_killable(timeout); \ - freezer_count(); \ - __retval; \ -}) +static inline long freezable_schedule_timeout_killable(long timeout) +{ + long __retval; + freezer_do_not_count(); + __retval = schedule_timeout_killable(timeout); + freezer_count(); + return __retval; +} + +/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ +static inline long freezable_schedule_timeout_killable_unsafe(long timeout) +{ + long __retval; + freezer_do_not_count(); + __retval = schedule_timeout_killable(timeout); + freezer_count_unsafe(); + return __retval; +} + +/* + * Like schedule_hrtimeout_range(), but should not block the freezer. Do not + * call this with locks held. + */ +static inline int freezable_schedule_hrtimeout_range(ktime_t *expires, + unsigned long delta, const enum hrtimer_mode mode) +{ + int __retval; + freezer_do_not_count(); + __retval = schedule_hrtimeout_range(expires, delta, mode); + freezer_count(); + return __retval; +} /* * Freezer-friendly wrappers around wait_event_interruptible(), @@ -142,33 +262,45 @@ static inline int freezer_should_skip(struct task_struct *p) __retval; \ }) +/* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ +#define wait_event_freezekillable_unsafe(wq, condition) \ +({ \ + int __retval; \ + freezer_do_not_count(); \ + __retval = wait_event_killable(wq, (condition)); \ + freezer_count_unsafe(); \ + __retval; \ +}) + #define wait_event_freezable(wq, condition) \ ({ \ int __retval; \ - for (;;) { \ - __retval = wait_event_interruptible(wq, \ - (condition) || freezing(current)); \ - if (__retval || (condition)) \ - break; \ - try_to_freeze(); \ - } \ + freezer_do_not_count(); \ + __retval = wait_event_interruptible(wq, (condition)); \ + freezer_count(); \ __retval; \ }) #define wait_event_freezable_timeout(wq, condition, timeout) \ ({ \ long __retval = timeout; \ - for (;;) { \ - __retval = wait_event_interruptible_timeout(wq, \ - (condition) || freezing(current), \ - __retval); \ - if (__retval <= 0 || (condition)) \ - break; \ - try_to_freeze(); \ - } \ + freezer_do_not_count(); \ + __retval = wait_event_interruptible_timeout(wq, (condition), \ + __retval); \ + freezer_count(); \ + __retval; \ +}) + +#define wait_event_freezable_exclusive(wq, condition) \ +({ \ + int __retval; \ + freezer_do_not_count(); \ + __retval = wait_event_interruptible_exclusive(wq, condition); \ + freezer_count(); \ __retval; \ }) + #else /* !CONFIG_FREEZER */ static inline bool frozen(struct task_struct *p) { return false; } static inline bool freezing(struct task_struct *p) { return false; } @@ -189,18 +321,37 @@ static inline void set_freezable(void) {} #define freezable_schedule() schedule() +#define freezable_schedule_unsafe() schedule() + +#define freezable_schedule_timeout(timeout) schedule_timeout(timeout) + +#define freezable_schedule_timeout_interruptible(timeout) \ + schedule_timeout_interruptible(timeout) + #define freezable_schedule_timeout_killable(timeout) \ schedule_timeout_killable(timeout) +#define freezable_schedule_timeout_killable_unsafe(timeout) \ + schedule_timeout_killable(timeout) + +#define freezable_schedule_hrtimeout_range(expires, delta, mode) \ + schedule_hrtimeout_range(expires, delta, mode) + #define wait_event_freezable(wq, condition) \ wait_event_interruptible(wq, condition) #define wait_event_freezable_timeout(wq, condition, timeout) \ wait_event_interruptible_timeout(wq, condition, timeout) +#define wait_event_freezable_exclusive(wq, condition) \ + wait_event_interruptible_exclusive(wq, condition) + #define wait_event_freezekillable(wq, condition) \ wait_event_killable(wq, condition) +#define wait_event_freezekillable_unsafe(wq, condition) \ + wait_event_killable(wq, condition) + #endif /* !CONFIG_FREEZER */ #endif /* FREEZER_H_INCLUDED */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 093f0b8878c..5adfd1f5354 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1665,6 +1665,8 @@ struct inode_operations { void (*truncate_range)(struct inode *, loff_t, loff_t); int (*fiemap)(struct inode *, struct fiemap_extent_info *, u64 start, u64 len); + int (*tmpfile) (struct inode *, struct dentry *, umode_t); + int (*set_acl)(struct inode *, struct posix_acl *, int); } ____cacheline_aligned; struct seq_file; @@ -2079,6 +2081,7 @@ static inline int thaw_bdev(struct block_device *bdev, struct super_block *sb) } #endif extern int sync_filesystem(struct super_block *); +extern void sync_filesystems(int wait); extern const struct file_operations def_blk_fops; extern const struct file_operations def_chr_fops; extern const struct file_operations bad_sock_fops; @@ -2401,9 +2404,12 @@ extern void file_ra_state_init(struct file_ra_state *ra, struct address_space *mapping); extern loff_t noop_llseek(struct file *file, loff_t offset, int origin); extern loff_t no_llseek(struct file *file, loff_t offset, int origin); +extern loff_t vfs_setpos(struct file *file, loff_t offset, loff_t maxsize); extern loff_t generic_file_llseek(struct file *file, loff_t offset, int origin); extern loff_t generic_file_llseek_size(struct file *file, loff_t offset, int origin, loff_t maxsize); +extern loff_t __generic_file_llseek_size(struct file *file, loff_t offset, + int whence, loff_t maxsize, loff_t eof); extern int generic_file_open(struct inode * inode, struct file * filp); extern int nonseekable_open(struct inode * inode, struct file * filp); diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h index a2b59d795ae..1ca1b835902 100644 --- a/include/linux/ieee80211.h +++ b/include/linux/ieee80211.h @@ -1074,6 +1074,90 @@ struct ieee80211_ht_info { #define WLAN_HT_SMPS_CONTROL_STATIC 1 #define WLAN_HT_SMPS_CONTROL_DYNAMIC 3 +/** + * struct ieee80211_vht_mcs_info - VHT MCS information + * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams + * @rx_highest: Indicates highest long GI VHT PPDU data rate + * STA can receive. Rate expressed in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. + * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams + * @tx_highest: Indicates highest long GI VHT PPDU data rate + * STA can transmit. Rate expressed in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest TX data rate supported. + */ +struct ieee80211_vht_mcs_info { + __le16 rx_mcs_map; + __le16 rx_highest; + __le16 tx_mcs_map; + __le16 tx_highest; +} __packed; + +/** + * struct ieee80211_vht_cap - VHT capabilities + * + * This structure is the "VHT capabilities element" as + * described in 802.11ac D3.0 8.4.2.160 + * @vht_cap_info: VHT capability info + * @supp_mcs: VHT MCS supported rates + */ +struct ieee80211_vht_cap { + __le32 vht_cap_info; + struct ieee80211_vht_mcs_info supp_mcs; +} __packed; + +/** + * struct ieee80211_vht_operation - VHT operation IE + * + * This structure is the "VHT operation element" as + * described in 802.11ac D3.0 8.4.2.161 + * @chan_width: Operating channel width + * @center_freq_seg1_idx: center freq segment 1 index + * @center_freq_seg2_idx: center freq segment 2 index + * @basic_mcs_set: VHT Basic MCS rate set + */ +struct ieee80211_vht_operation { + u8 chan_width; + u8 center_freq_seg1_idx; + u8 center_freq_seg2_idx; + __le16 basic_mcs_set; +} __packed; + + +#define IEEE80211_VHT_MCS_ZERO_TO_SEVEN_SUPPORT 0 +#define IEEE80211_VHT_MCS_ZERO_TO_EIGHT_SUPPORT 1 +#define IEEE80211_VHT_MCS_ZERO_TO_NINE_SUPPORT 2 +#define IEEE80211_VHT_MCS_NOT_SUPPORTED 3 + +/* 802.11ac VHT Capabilities */ +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 +#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 +#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 +#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 +#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 +#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 +#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 +#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 +#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 +#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 +#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 +#define IEEE80211_VHT_CAP_BEAMFORMER_ANTENNAS_MAX 0x00006000 +#define IEEE80211_VHT_CAP_SOUNDING_DIMENTION_MAX 0x00030000 +#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 +#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 +#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 +#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 +#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT 0x00800000 +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 +#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 +#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 + /* Authentication algorithms */ #define WLAN_AUTH_OPEN 0 #define WLAN_AUTH_SHARED_KEY 1 @@ -1334,6 +1418,9 @@ enum ieee80211_eid { WLAN_EID_DSE_REGISTERED_LOCATION = 58, WLAN_EID_SUPPORTED_REGULATORY_CLASSES = 59, WLAN_EID_EXT_CHANSWITCH_ANN = 60, + + WLAN_EID_VHT_CAPABILITY = 191, + WLAN_EID_VHT_OPERATION = 192, }; /* Action category code */ diff --git a/include/linux/input.h b/include/linux/input.h index d4cdb02c9de..798443e090c 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1171,6 +1171,18 @@ struct ff_effect { #include #include +/** + * struct input_value - input value representation + * @type: type of value (EV_KEY, EV_ABS, etc) + * @code: the value code + * @value: the value + */ +struct input_value { + __u16 type; + __u16 code; + __s32 value; +}; + /** * struct input_dev - represents an input device * @name: name of the device @@ -1247,7 +1259,6 @@ struct ff_effect { * last user closes the device * @going_away: marks devices that are in a middle of unregistering and * causes input_open_device*() fail with -ENODEV. - * @sync: set to %true when there were no new events since last EV_SYN * @dev: driver model's view of this device * @h_list: list of input handles associated with the device. When * accessing the list dev->mutex must be held @@ -1315,12 +1326,14 @@ struct input_dev { unsigned int users; bool going_away; - bool sync; - struct device dev; struct list_head h_list; struct list_head node; + + unsigned int num_vals; + unsigned int max_vals; + struct input_value *vals; }; #define to_input_dev(d) container_of(d, struct input_dev, dev) @@ -1381,6 +1394,9 @@ struct input_handle; * @event: event handler. This method is being called by input core with * interrupts disabled and dev->event_lock spinlock held and so * it may not sleep + * @events: event sequence handler. This method is being called by + * input core with interrupts disabled and dev->event_lock + * spinlock held and so it may not sleep * @filter: similar to @event; separates normal event handlers from * "filters". * @match: called after comparing device's id with handler's id_table @@ -1417,6 +1433,8 @@ struct input_handler { void *private; void (*event)(struct input_handle *handle, unsigned int type, unsigned int code, int value); + void (*events)(struct input_handle *handle, + const struct input_value *vals, unsigned int count); bool (*filter)(struct input_handle *handle, unsigned int type, unsigned int code, int value); bool (*match)(struct input_handler *handler, struct input_dev *dev); int (*connect)(struct input_handler *handler, struct input_dev *dev, const struct input_device_id *id); diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 95b15d6ef6c..dbe13ba323a 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -37,12 +37,13 @@ struct iommu_domain; #define IOMMU_FAULT_WRITE 0x1 typedef int (*iommu_fault_handler_t)(struct iommu_domain *, - struct device *, unsigned long, int); + struct device *, unsigned long, int, void *); struct iommu_domain { struct iommu_ops *ops; void *priv; iommu_fault_handler_t handler; + void *handler_token; }; #define IOMMU_CAP_CACHE_COHERENCY 0x1 @@ -107,7 +108,7 @@ extern int iommu_domain_has_cap(struct iommu_domain *domain, unsigned long cap); extern phys_addr_t iommu_get_pt_base_addr(struct iommu_domain *domain); extern void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler); + iommu_fault_handler_t handler, void *token); extern int iommu_device_group(struct device *dev, unsigned int *groupid); /** @@ -144,7 +145,8 @@ static inline int report_iommu_fault(struct iommu_domain *domain, * invoke it. */ if (domain->handler) - ret = domain->handler(domain, dev, iova, flags); + ret = domain->handler(domain, dev, iova, flags, + domain->handler_token); return ret; } @@ -221,7 +223,7 @@ static inline phys_addr_t iommu_get_pt_base_addr(struct iommu_domain *domain) } static inline void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler) + iommu_fault_handler_t handler, void *token) { } diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 771cb354348..4d22be25b48 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h @@ -39,7 +39,6 @@ struct module; */ struct irq_desc { struct irq_data irq_data; - struct timer_rand_state *timer_rand_state; unsigned int __percpu *kstat_irqs; irq_flow_handler_t handle_irq; #ifdef CONFIG_IRQ_PREFLOW_FASTEOI diff --git a/include/linux/jbd2.h b/include/linux/jbd2.h index 912c30a8ddb..9d75a5de72e 100644 --- a/include/linux/jbd2.h +++ b/include/linux/jbd2.h @@ -1100,6 +1100,7 @@ extern void jbd2_journal_ack_err (journal_t *); extern int jbd2_journal_clear_err (journal_t *); extern int jbd2_journal_bmap(journal_t *, unsigned long, unsigned long long *); extern int jbd2_journal_force_commit(journal_t *); +extern int jbd2_journal_force_commit_nested(journal_t *); extern int jbd2_journal_file_inode(handle_t *handle, struct jbd2_inode *inode); extern int jbd2_journal_begin_ordered_truncate(journal_t *journal, struct jbd2_inode *inode, loff_t new_size); @@ -1174,7 +1175,6 @@ int __jbd2_log_space_left(journal_t *); /* Called with journal locked */ int jbd2_log_start_commit(journal_t *journal, tid_t tid); int __jbd2_log_start_commit(journal_t *journal, tid_t tid); int jbd2_journal_start_commit(journal_t *journal, tid_t *tid); -int jbd2_journal_force_commit_nested(journal_t *journal); int jbd2_log_wait_commit(journal_t *journal, tid_t tid); int jbd2_log_do_checkpoint(journal_t *journal); int jbd2_trans_will_send_data_barrier(journal_t *journal, tid_t tid); diff --git a/include/linux/kexec.h b/include/linux/kexec.h index af84a25ef6b..a4509adc86a 100644 --- a/include/linux/kexec.h +++ b/include/linux/kexec.h @@ -111,6 +111,10 @@ struct kimage { #define KEXEC_TYPE_CRASH 1 unsigned int preserve_context : 1; +#ifdef CONFIG_KEXEC_HARDBOOT + unsigned int hardboot : 1; +#endif + #ifdef ARCH_HAS_KIMAGE_ARCH struct kimage_arch arch; #endif @@ -178,6 +182,11 @@ extern struct kimage *kexec_crash_image; #define KEXEC_ON_CRASH 0x00000001 #define KEXEC_PRESERVE_CONTEXT 0x00000002 + +#ifdef CONFIG_KEXEC_HARDBOOT +#define KEXEC_HARDBOOT 0x00000004 +#endif + #define KEXEC_ARCH_MASK 0xffff0000 /* These values match the ELF architecture values. @@ -196,10 +205,14 @@ extern struct kimage *kexec_crash_image; #define KEXEC_ARCH_MIPS ( 8 << 16) /* List of defined/legal kexec flags */ -#ifndef CONFIG_KEXEC_JUMP -#define KEXEC_FLAGS KEXEC_ON_CRASH -#else +#if defined(CONFIG_KEXEC_JUMP) && defined(CONFIG_KEXEC_HARDBOOT) +#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT | KEXEC_HARDBOOT) +#elif defined(CONFIG_KEXEC_JUMP) #define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_PRESERVE_CONTEXT) +#elif defined(CONFIG_KEXEC_HARDBOOT) +#define KEXEC_FLAGS (KEXEC_ON_CRASH | KEXEC_HARDBOOT) +#else +#define KEXEC_FLAGS (KEXEC_ON_CRASH) #endif #define VMCOREINFO_BYTES (4096) diff --git a/include/linux/kref.h b/include/linux/kref.h index 9c07dcebded..aa5acc26019 100644 --- a/include/linux/kref.h +++ b/include/linux/kref.h @@ -93,4 +93,26 @@ static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref) { return kref_sub(kref, 1, release); } + + +/** + * kref_get_unless_zero - Increment refcount for object unless it is zero. + * @kref: object. + * + * Return non-zero if the increment succeeded. Otherwise return 0. + * + * This function is intended to simplify locking around refcounting for + * objects that can be looked up from a lookup structure, and which are + * removed from that lookup structure in the object destructor. + * Operations on such objects require at least a read lock around + * lookup + kref_get, and a write lock around kref_put + remove from lookup + * structure. Furthermore, RCU implementations become extremely tricky. + * With a lookup followed by a kref_get_unless_zero *with return value check* + * locking in the kref_put path can be deferred to the actual removal from + * the lookup structure and RCU lookups become trivial. + */ +static inline int __must_check kref_get_unless_zero(struct kref *kref) +{ + return atomic_add_unless(&kref->refcount, 1, 0); +} #endif /* _KREF_H_ */ diff --git a/include/linux/ksm.h b/include/linux/ksm.h index 3319a696762..f4edf33e699 100644 --- a/include/linux/ksm.h +++ b/include/linux/ksm.h @@ -22,21 +22,6 @@ struct page *ksm_does_need_to_copy(struct page *page, #ifdef CONFIG_KSM int ksm_madvise(struct vm_area_struct *vma, unsigned long start, unsigned long end, int advice, unsigned long *vm_flags); -int __ksm_enter(struct mm_struct *mm); -void __ksm_exit(struct mm_struct *mm); - -static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) -{ - if (test_bit(MMF_VM_MERGEABLE, &oldmm->flags)) - return __ksm_enter(mm); - return 0; -} - -static inline void ksm_exit(struct mm_struct *mm) -{ - if (test_bit(MMF_VM_MERGEABLE, &mm->flags)) - __ksm_exit(mm); -} /* * A KSM page is one of those write-protected "shared pages" or "merged pages" @@ -90,6 +75,33 @@ int rmap_walk_ksm(struct page *page, int (*rmap_one)(struct page *, struct vm_area_struct *, unsigned long, void *), void *arg); void ksm_migrate_page(struct page *newpage, struct page *oldpage); +#ifdef CONFIG_KSM_LEGACY +int __ksm_enter(struct mm_struct *mm); +void __ksm_exit(struct mm_struct *mm); +static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) +{ + if (test_bit(MMF_VM_MERGEABLE, &oldmm->flags)) + return __ksm_enter(mm); + return 0; +} + +static inline void ksm_exit(struct mm_struct *mm) +{ + if (test_bit(MMF_VM_MERGEABLE, &mm->flags)) + __ksm_exit(mm); +} + +#elif defined(CONFIG_UKSM) +static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) +{ + return 0; +} + +static inline void ksm_exit(struct mm_struct *mm) +{ +} +#endif /* !CONFIG_UKSM */ + #else /* !CONFIG_KSM */ static inline int ksm_fork(struct mm_struct *mm, struct mm_struct *oldmm) @@ -142,4 +154,6 @@ static inline void ksm_migrate_page(struct page *newpage, struct page *oldpage) #endif /* CONFIG_MMU */ #endif /* !CONFIG_KSM */ +#include + #endif /* __LINUX_KSM_H */ diff --git a/include/linux/lz4.h b/include/linux/lz4.h new file mode 100644 index 00000000000..4356686b0a3 --- /dev/null +++ b/include/linux/lz4.h @@ -0,0 +1,87 @@ +#ifndef __LZ4_H__ +#define __LZ4_H__ +/* + * LZ4 Kernel Interface + * + * Copyright (C) 2013, LG Electronics, Kyungsik Lee + * + * 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. + */ +#define LZ4_MEM_COMPRESS (4096 * sizeof(unsigned char *)) +#define LZ4HC_MEM_COMPRESS (65538 * sizeof(unsigned char *)) + +/* + * lz4_compressbound() + * Provides the maximum size that LZ4 may output in a "worst case" scenario + * (input data not compressible) + */ +static inline size_t lz4_compressbound(size_t isize) +{ + return isize + (isize / 255) + 16; +} + +/* + * lz4_compress() + * src : source address of the original data + * src_len : size of the original data + * dst : output buffer address of the compressed data + * This requires 'dst' of size LZ4_COMPRESSBOUND. + * dst_len : is the output size, which is returned after compress done + * workmem : address of the working memory. + * This requires 'workmem' of size LZ4_MEM_COMPRESS. + * return : Success if return 0 + * Error if return (< 0) + * note : Destination buffer and workmem must be already allocated with + * the defined size. + */ +int lz4_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem); + + /* + * lz4hc_compress() + * src : source address of the original data + * src_len : size of the original data + * dst : output buffer address of the compressed data + * This requires 'dst' of size LZ4_COMPRESSBOUND. + * dst_len : is the output size, which is returned after compress done + * workmem : address of the working memory. + * This requires 'workmem' of size LZ4HC_MEM_COMPRESS. + * return : Success if return 0 + * Error if return (< 0) + * note : Destination buffer and workmem must be already allocated with + * the defined size. + */ +int lz4hc_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem); + +/* + * lz4_decompress() + * src : source address of the compressed data + * src_len : is the input size, whcih is returned after decompress done + * dest : output buffer address of the decompressed data + * actual_dest_len: is the size of uncompressed data, supposing it's known + * return : Success if return 0 + * Error if return (< 0) + * note : Destination buffer must be already allocated. + * slightly faster than lz4_decompress_unknownoutputsize() + */ +int lz4_decompress(const unsigned char *src, size_t *src_len, + unsigned char *dest, size_t actual_dest_len); + +/* + * lz4_decompress_unknownoutputsize() + * src : source address of the compressed data + * src_len : is the input size, therefore the compressed size + * dest : output buffer address of the decompressed data + * dest_len: is the max size of the destination buffer, which is + * returned with actual size of decompressed data after + * decompress done + * return : Success if return 0 + * Error if return (< 0) + * note : Destination buffer must be already allocated. + */ +int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len, + unsigned char *dest, size_t *dest_len); +#endif diff --git a/include/linux/magic.h b/include/linux/magic.h index e15192cb9cf..66353ffd06a 100644 --- a/include/linux/magic.h +++ b/include/linux/magic.h @@ -23,6 +23,7 @@ #define EXT4_SUPER_MAGIC 0xEF53 #define BTRFS_SUPER_MAGIC 0x9123683E #define NILFS_SUPER_MAGIC 0x3434 +#define F2FS_SUPER_MAGIC 0xF2F52010 #define HPFS_SUPER_MAGIC 0xf995e849 #define ISOFS_SUPER_MAGIC 0x9660 #define JFFS2_SUPER_MAGIC 0x72b6 diff --git a/include/linux/memcopy.h b/include/linux/memcopy.h new file mode 100644 index 00000000000..a7b157391fd --- /dev/null +++ b/include/linux/memcopy.h @@ -0,0 +1,226 @@ +/* + * memcopy.h -- definitions for memory copy functions. Generic C version. + * + * 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.1 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. + * + * 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * The code is derived from the GNU C Library. + * Copyright (C) 1991, 1992, 1993, 1997, 2004 Free Software Foundation, Inc. + */ +#ifndef _LINUX_MEMCOPY_H_ +#define _LINUX_MEMCOPY_H_ + +/* + * The strategy of the memory functions is: + * + * 1. Copy bytes until the destination pointer is aligned. + * + * 2. Copy words in unrolled loops. If the source and destination + * are not aligned in the same way, use word memory operations, + * but shift and merge two read words before writing. + * + * 3. Copy the few remaining bytes. + * + * This is fast on processors that have at least 10 registers for + * allocation by GCC, and that can access memory at reg+const in one + * instruction. + */ + +#include +#include +#include + +/* + * The macros defined in this file are: + * + * BYTE_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy) + * + * BYTE_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy) + * + * WORD_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_remaining, nbytes_to_copy) + * + * WORD_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_remaining, nbytes_to_copy) + * + * MERGE(old_word, sh_1, new_word, sh_2) + * + * MEM_COPY_FWD(dst_beg_ptr, src_beg_ptr, nbytes_to_copy) + * + * MEM_COPY_BWD(dst_end_ptr, src_end_ptr, nbytes_to_copy) + */ + +#define OP_T_THRESHOLD 16 + +/* + * Type to use for aligned memory operations. + * This should normally be the biggest type supported by a single load + * and store. + */ +#define op_t unsigned long int +#define OPSIZ (sizeof(op_t)) + +/* Type to use for unaligned operations. */ +typedef unsigned char byte; + +#ifndef MERGE +# ifdef __LITTLE_ENDIAN +# define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2))) +# elif defined(__BIG_ENDIAN) +# define MERGE(w0, sh_1, w1, sh_2) (((w0) << (sh_1)) | ((w1) >> (sh_2))) +# else +# error "Macro MERGE() hasn't defined!" +# endif +#endif + +/* + * Copy exactly NBYTES bytes from SRC_BP to DST_BP, + * without any assumptions about alignment of the pointers. + */ +#ifndef BYTE_COPY_FWD +#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) \ +do { \ + size_t __nbytes = (nbytes); \ + while (__nbytes > 0) { \ + byte __x = ((byte *) src_bp)[0]; \ + src_bp += 1; \ + __nbytes -= 1; \ + ((byte *) dst_bp)[0] = __x; \ + dst_bp += 1; \ + } \ +} while (0) +#endif + +/* + * Copy exactly NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, + * beginning at the bytes right before the pointers and continuing towards + * smaller addresses. Don't assume anything about alignment of the + * pointers. + */ +#ifndef BYTE_COPY_BWD +#define BYTE_COPY_BWD(dst_ep, src_ep, nbytes) \ +do { \ + size_t __nbytes = (nbytes); \ + while (__nbytes > 0) { \ + byte __x; \ + src_ep -= 1; \ + __x = ((byte *) src_ep)[0]; \ + dst_ep -= 1; \ + __nbytes -= 1; \ + ((byte *) dst_ep)[0] = __x; \ + } \ +} while (0) +#endif +/* + * Copy *up to* NBYTES bytes from SRC_BP to DST_BP, with + * the assumption that DST_BP is aligned on an OPSIZ multiple. If + * not all bytes could be easily copied, store remaining number of bytes + * in NBYTES_LEFT, otherwise store 0. + */ +extern void _wordcopy_fwd_aligned(long int, long int, size_t); +extern void _wordcopy_fwd_dest_aligned(long int, long int, size_t); +#ifndef WORD_COPY_FWD +#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \ +do { \ + if (src_bp % OPSIZ == 0) \ + _wordcopy_fwd_aligned (dst_bp, src_bp, (nbytes) / OPSIZ); \ + else \ + _wordcopy_fwd_dest_aligned (dst_bp, src_bp, (nbytes) / OPSIZ);\ + \ + src_bp += (nbytes) & -OPSIZ; \ + dst_bp += (nbytes) & -OPSIZ; \ + (nbytes_left) = (nbytes) % OPSIZ; \ +} while (0) +#endif + +/* + * Copy *up to* NBYTES_TO_COPY bytes from SRC_END_PTR to DST_END_PTR, + * beginning at the words (of type op_t) right before the pointers and + * continuing towards smaller addresses. May take advantage of that + * DST_END_PTR is aligned on an OPSIZ multiple. If not all bytes could be + * easily copied, store remaining number of bytes in NBYTES_REMAINING, + * otherwise store 0. + */ +extern void _wordcopy_bwd_aligned(long int, long int, size_t); +extern void _wordcopy_bwd_dest_aligned(long int, long int, size_t); +#ifndef WORD_COPY_BWD +#define WORD_COPY_BWD(dst_ep, src_ep, nbytes_left, nbytes) \ +do { \ + if (src_ep % OPSIZ == 0) \ + _wordcopy_bwd_aligned (dst_ep, src_ep, (nbytes) / OPSIZ); \ + else \ + _wordcopy_bwd_dest_aligned (dst_ep, src_ep, (nbytes) / OPSIZ);\ + \ + src_ep -= (nbytes) & -OPSIZ; \ + dst_ep -= (nbytes) & -OPSIZ; \ + (nbytes_left) = (nbytes) % OPSIZ; \ +} while (0) +#endif + +/* Copy memory from the beginning to the end */ +#ifndef MEM_COPY_FWD +static __always_inline void mem_copy_fwd(unsigned long dstp, + unsigned long srcp, + size_t count) +{ + /* If there not too few bytes to copy, use word copy. */ + if (count >= OP_T_THRESHOLD) { + /* Copy just a few bytes to make dstp aligned. */ + count -= (-dstp) % OPSIZ; + BYTE_COPY_FWD(dstp, srcp, (-dstp) % OPSIZ); + + /* + * Copy from srcp to dstp taking advantage of the known + * alignment of dstp. Number if bytes remaining is put in + * the third argument. + */ + WORD_COPY_FWD(dstp, srcp, count, count); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_FWD(dstp, srcp, count); +} +#endif + +/* Copy memory from the end to the beginning. */ +#ifndef MEM_COPY_BWD +static __always_inline void mem_copy_bwd(unsigned long dstp, + unsigned long srcp, + size_t count) +{ + srcp += count; + dstp += count; + + /* If there not too few bytes to copy, use word copy. */ + if (count >= OP_T_THRESHOLD) { + /* Copy just a few bytes to make dstp aligned. */ + count -= dstp % OPSIZ; + BYTE_COPY_BWD(dstp, srcp, dstp % OPSIZ); + + /* + * Copy from srcp to dstp taking advantage of the known + * alignment of dstp. Number if bytes remaining is put in + * the third argument. + */ + WORD_COPY_BWD(dstp, srcp, count, count); + + /* Fall out and copy the tail. */ + } + + /* There are just a few bytes to copy. Use byte memory operations. */ + BYTE_COPY_BWD (dstp, srcp, count); +} +#endif + +#endif diff --git a/include/linux/mfd/pm8xxx/pm8921-bms.h b/include/linux/mfd/pm8xxx/pm8921-bms.h index 722ecda7dd3..21f9873edec 100644 --- a/include/linux/mfd/pm8xxx/pm8921-bms.h +++ b/include/linux/mfd/pm8xxx/pm8921-bms.h @@ -220,6 +220,15 @@ int pm8921_bms_get_rbatt(void); * soc stored in a coincell backed register */ void pm8921_bms_invalidate_shutdown_soc(void); + +/** + * pm8921_bms_cc_uah - function to get the coulomb counter based charge. Note + * that the coulomb counter are reset when the current + * consumption is low (below 8mA for more than 5 minutes), + * This will lead in a very low coulomb counter charge + * value upon wakeup from sleep. + */ +int pm8921_bms_cc_uah(int *cc_uah); #else static inline int pm8921_bms_get_vsense_avg(int *result) { @@ -258,6 +267,10 @@ static inline int pm8921_bms_get_rbatt(void) static inline void pm8921_bms_invalidate_shutdown_soc(void) { } +static inline int pm8921_bms_cc_uah(int *cc_uah) +{ + return -ENXIO; +} #endif #endif diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h index 508bf3bb55e..40e3a83790c 100644 --- a/include/linux/mfd/wcd9xxx/core.h +++ b/include/linux/mfd/wcd9xxx/core.h @@ -161,6 +161,9 @@ struct wcd9xxx { }; int wcd9xxx_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg); +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +int wcd9xxx_reg_read_safe(struct wcd9xxx *wcd9xxx, unsigned short reg); +#endif int wcd9xxx_reg_write(struct wcd9xxx *wcd9xxx, unsigned short reg, u8 val); int wcd9xxx_interface_reg_read(struct wcd9xxx *wcd9xxx, unsigned short reg); diff --git a/include/linux/mm.h b/include/linux/mm.h index ddfb7c5dd51..fd1baead0d8 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1369,7 +1369,7 @@ extern int vma_adjust(struct vm_area_struct *vma, unsigned long start, extern struct vm_area_struct *vma_merge(struct mm_struct *, struct vm_area_struct *prev, unsigned long addr, unsigned long end, unsigned long vm_flags, struct anon_vma *, struct file *, pgoff_t, - struct mempolicy *); + struct mempolicy *, const char __user *); extern struct anon_vma *find_mergeable_anon_vma(struct vm_area_struct *); extern int split_vma(struct mm_struct *, struct vm_area_struct *, unsigned long addr, int new_below); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 3cc3062b376..e928a484b7e 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -216,6 +216,10 @@ struct vm_area_struct { * linkage into the address_space->i_mmap prio tree, or * linkage to the list of like vmas hanging off its node, or * linkage of vma in the address_space->i_mmap_nonlinear list. + * + * For private anonymous mappings, a pointer to a null terminated string + * in the user process containing the name given to the vma, or NULL + * if unnamed. */ union { struct { @@ -225,6 +229,7 @@ struct vm_area_struct { } vm_set; struct raw_prio_tree_node prio_tree_node; + const char __user *anon_name; } shared; /* @@ -252,6 +257,9 @@ struct vm_area_struct { #ifdef CONFIG_NUMA struct mempolicy *vm_policy; /* NUMA policy for the VMA */ #endif +#ifdef CONFIG_UKSM + struct vma_slot *uksm_vma_slot; +#endif }; struct core_thread { @@ -344,17 +352,6 @@ struct mm_struct { /* Architecture-specific MM context */ mm_context_t context; - /* Swap token stuff */ - /* - * Last value of global fault stamp as seen by this process. - * In other words, this value gives an indication of how long - * it has been since this task got the token. - * Look at mm/thrash.c - */ - unsigned int faultstamp; - unsigned int token_priority; - unsigned int last_interval; - unsigned long flags; /* Must use atomic bitops to access the bits */ struct core_state *core_state; /* coredumping support */ @@ -403,4 +400,14 @@ static inline cpumask_t *mm_cpumask(struct mm_struct *mm) return mm->cpu_vm_mask_var; } + +/* Return the name for an anonymous mapping or NULL for a file-backed mapping */ +static inline const char __user *vma_get_anon_name(struct vm_area_struct *vma) +{ + if (vma->vm_file) + return NULL; + + return vma->shared.anon_name; +} + #endif /* _LINUX_MM_TYPES_H */ diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index ca7a586f05c..cc451a604dd 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -152,6 +152,9 @@ enum zone_stat_item { NUMA_OTHER, /* allocation from other node */ #endif NR_ANON_TRANSPARENT_HUGEPAGES, +#ifdef CONFIG_UKSM + NR_UKSM_ZERO_PAGES, +#endif NR_FREE_CMA_PAGES, NR_VM_ZONE_STAT_ITEMS }; @@ -799,7 +802,7 @@ static inline int is_normal_idx(enum zone_type idx) } /** - * is_highmem - helper function to quickly check if a struct zone is a + * is_highmem - helper function to quickly check if a struct zone is a * highmem zone or not. This is an attempt to keep references * to ZONE_{DMA/NORMAL/HIGHMEM/etc} in general code to a minimum. * @zone - pointer to struct zone variable diff --git a/include/linux/msm_kgsl.h b/include/linux/msm_kgsl.h index 0af811c86ab..a36e60d97e7 100644 --- a/include/linux/msm_kgsl.h +++ b/include/linux/msm_kgsl.h @@ -230,6 +230,7 @@ struct kgsl_version { #define KGSL_PERFCOUNTER_GROUP_VBIF_PWR 0xE #define KGSL_PERFCOUNTER_NOT_USED 0xFFFFFFFF +#define KGSL_PERFCOUNTER_BROKEN 0xFFFFFFFE /* structure holds list of ibs */ struct kgsl_ibdesc { diff --git a/include/linux/msm_thermal.h b/include/linux/msm_thermal.h index 2c9a613ab84..0d1c23efbf2 100644 --- a/include/linux/msm_thermal.h +++ b/include/linux/msm_thermal.h @@ -14,12 +14,14 @@ #ifndef __MSM_THERMAL_H #define __MSM_THERMAL_H +extern int throttled_bin; + struct msm_thermal_data { uint32_t sensor_id; - uint32_t poll_ms; +/* uint32_t poll_ms; uint32_t limit_temp_degC; uint32_t temp_hysteresis_degC; - uint32_t freq_step; + uint32_t freq_step;*/ }; #ifdef CONFIG_THERMAL_MONITOR diff --git a/include/linux/msm_tsens.h b/include/linux/msm_tsens.h index 5837094b05e..ef23d70f26b 100644 --- a/include/linux/msm_tsens.h +++ b/include/linux/msm_tsens.h @@ -39,6 +39,8 @@ struct tsens_device { uint32_t sensor_num; }; +int tsens_set_tz_warm_temp_degC(int sensor_num, int temp, struct work_struct *work); +int tsens_set_tz_cool_temp_degC(int sensor_num, int temp, struct work_struct *work); int32_t tsens_get_temp(struct tsens_device *dev, unsigned long *temp); int msm_tsens_early_init(struct tsens_platform_data *pdata); diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 61989d0e909..760db5c3fcb 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h @@ -170,6 +170,9 @@ * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, * %NL80211_ATTR_AUTH_TYPE and %NL80211_ATTR_INACTIVITY_TIMEOUT. + * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. + * The channel to use can be set on the interface or be given using the + * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP @@ -554,6 +557,64 @@ * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether * No Acknowledgement Policy should be applied. * + * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels + * independently of the userspace SME, send this event indicating + * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the + * attributes determining channel width. + * + * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. It must have been created with + * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the + * P2P Device can be used for P2P operations, e.g. remain-on-channel and + * public action frame TX. + * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. + * + * @NL80211_CMD_CONN_FAILED: connection request to an AP failed; used to + * notify userspace that AP has rejected the connection request from a + * station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON + * is used for this. + * + * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames + * for IBSS or MESH vif. + * + * @NL80211_CMD_SET_MAC_ACL: sets ACL for MAC address based access control. + * This is to be used with the drivers advertising the support of MAC + * address based access control. List of MAC addresses is passed in + * %NL80211_ATTR_MAC_ADDRS and ACL policy is passed in + * %NL80211_ATTR_ACL_POLICY. Driver will enable ACL with this list, if it + * is not already done. The new list will replace any existing list. Driver + * will clear its ACL when the list of MAC addresses passed is empty. This + * command is used in AP/P2P GO mode. Driver has to make sure to clear its + * ACL list during %NL80211_CMD_STOP_AP. + * + * @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once + * a radar is detected or the channel availability scan (CAC) has finished + * or was aborted, or a radar was detected, usermode will be notified with + * this event. This command is also used to notify userspace about radars + * while operating on this channel. + * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the + * event. + * + * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features, + * i.e. features for the nl80211 protocol rather than device features. + * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap. + * + * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition + * Information Element to the WLAN driver + * + * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver + * to the supplicant. This will carry the target AP's MAC address along + * with the relevant Information Elements. This event is used to report + * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). + * + * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running + * a critical protocol that needs more reliability in the connection to + * complete. + * + * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can + * return back to normal. + * * @NL80211_CMD_MAX: highest used command number * @__NL80211_CMD_AFTER_LAST: internal use */ @@ -695,6 +756,28 @@ enum nl80211_commands { NL80211_CMD_SET_NOACK_MAP, + + NL80211_CMD_CH_SWITCH_NOTIFY, + + NL80211_CMD_START_P2P_DEVICE, + NL80211_CMD_STOP_P2P_DEVICE, + + NL80211_CMD_CONN_FAILED, + + NL80211_CMD_SET_MCAST_RATE, + + NL80211_CMD_SET_MAC_ACL, + + NL80211_CMD_RADAR_DETECT, + + NL80211_CMD_GET_PROTOCOL_FEATURES, + + NL80211_CMD_UPDATE_FT_IES, + NL80211_CMD_FT_EVENT, + + NL80211_CMD_CRIT_PROTOCOL_START, + NL80211_CMD_CRIT_PROTOCOL_STOP, + /* add new commands above here */ /* used to define NL80211_CMD_MAX below */ @@ -1221,6 +1304,82 @@ enum nl80211_commands { * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds * or 0 to disable background scan. * + * @NL80211_ATTR_USER_REG_HINT_TYPE: type of regulatory hint passed from + * userspace. If unset it is assumed the hint comes directly from + * a user. If set code could specify exactly what type of source + * was used to provide the hint. For the different types of + * allowed user regulatory hints see nl80211_user_reg_hint_type. + * + * @NL80211_ATTR_CONN_FAILED_REASON: The reason for which AP has rejected + * the connection request from a station. nl80211_connect_failed_reason + * enum has different reasons of connection failure. + * + * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts + * with the Authentication transaction sequence number field. + * + * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * + * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) + * + * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with + * the START_AP and SET_BSS commands + * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the + * START_AP and SET_BSS commands. This can have the values 0 or 1; + * if not given in START_AP 0 is assumed, if not given in SET_BSS + * no change is made. + * + * @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode + * defined in &enum nl80211_mesh_power_mode. + * + * @NL80211_ATTR_ACL_POLICY: ACL policy, see &enum nl80211_acl_policy, + * carried in a u32 attribute + * + * @NL80211_ATTR_MAC_ADDRS: Array of nested MAC addresses, used for + * MAC ACL. + * + * @NL80211_ATTR_MAC_ACL_MAX: u32 attribute to advertise the maximum + * number of MAC addresses that a device can support for MAC + * ACL. + * + * @NL80211_ATTR_RADAR_EVENT: Type of radar event for notification to userspace, + * contains a value of enum nl80211_radar_event (u32). + * + * @NL80211_ATTR_EXT_CAPA: 802.11 extended capabilities that the kernel driver + * has and handles. The format is the same as the IE contents. See + * 802.11-2012 8.4.2.29 for more information. + * @NL80211_ATTR_EXT_CAPA_MASK: Extended capabilities that the kernel driver + * has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields. + * + * @NL80211_ATTR_STA_CAPABILITY: Station capabilities (u16) are advertised to + * the driver, e.g., to enable TDLS power save (PU-APSD). + * + * @NL80211_ATTR_STA_EXT_CAPABILITY: Station extended capabilities are + * advertised to the driver, e.g., to enable TDLS off channel operations + * and PU-APSD. + * + * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see + * &enum nl80211_protocol_features, the attribute is a u32. + * + * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports + * receiving the data for a single wiphy split across multiple + * messages, given with wiphy dump message + * + * @NL80211_ATTR_MDID: Mobility Domain Identifier + * + * @NL80211_ATTR_IE_RIC: Resource Information Container Information + * Element + * + * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased + * reliability, see &enum nl80211_crit_proto_id (u16). + * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which + * the connection should have increased reliability (u16). + * + * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16). + * This is similar to @NL80211_ATTR_STA_AID but with a difference of being + * allowed to be used with the first @NL80211_CMD_SET_STATION command to + * update a TDLS peer STA entry. + * * @NL80211_ATTR_MAX: highest attribute number currently defined * @__NL80211_ATTR_AFTER_LAST: internal use */ @@ -1472,6 +1631,55 @@ enum nl80211_attrs { NL80211_ATTR_BG_SCAN_PERIOD, + NL80211_ATTR_WDEV, + + NL80211_ATTR_USER_REG_HINT_TYPE, + + NL80211_ATTR_CONN_FAILED_REASON, + + NL80211_ATTR_SAE_DATA, + + NL80211_ATTR_VHT_CAPABILITY, + + NL80211_ATTR_SCAN_FLAGS, + + NL80211_ATTR_CHANNEL_WIDTH, + NL80211_ATTR_CENTER_FREQ1, + NL80211_ATTR_CENTER_FREQ2, + + NL80211_ATTR_P2P_CTWINDOW, + NL80211_ATTR_P2P_OPPPS, + + NL80211_ATTR_LOCAL_MESH_POWER_MODE, + + NL80211_ATTR_ACL_POLICY, + + NL80211_ATTR_MAC_ADDRS, + + NL80211_ATTR_MAC_ACL_MAX, + + NL80211_ATTR_RADAR_EVENT, + + NL80211_ATTR_EXT_CAPA, + NL80211_ATTR_EXT_CAPA_MASK, + + NL80211_ATTR_STA_CAPABILITY, + NL80211_ATTR_STA_EXT_CAPABILITY, + + NL80211_ATTR_PROTOCOL_FEATURES, + NL80211_ATTR_SPLIT_WIPHY_DUMP, + + NL80211_ATTR_DISABLE_VHT, + NL80211_ATTR_VHT_CAPABILITY_MASK, + + NL80211_ATTR_MDID, + NL80211_ATTR_IE_RIC, + + NL80211_ATTR_CRIT_PROT_ID, + NL80211_ATTR_MAX_CRIT_PROT_DURATION, + + NL80211_ATTR_PEER_AID, + /* add attributes here, update the policy in nl80211.c */ __NL80211_ATTR_AFTER_LAST, @@ -1515,6 +1723,7 @@ enum nl80211_attrs { #define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 #define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 #define NL80211_HT_CAPABILITY_LEN 26 +#define NL80211_VHT_CAPABILITY_LEN 12 #define NL80211_MAX_NR_CIPHER_SUITES 5 #define NL80211_MAX_NR_AKM_SUITES 2 @@ -1793,6 +2002,9 @@ enum nl80211_mpath_info { * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n + * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as + * defined in 802.11ac + * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined * @__NL80211_BAND_ATTR_AFTER_LAST: internal use */ @@ -1806,6 +2018,9 @@ enum nl80211_band_attr { NL80211_BAND_ATTR_HT_AMPDU_FACTOR, NL80211_BAND_ATTR_HT_AMPDU_DENSITY, + NL80211_BAND_ATTR_VHT_MCS_SET, + NL80211_BAND_ATTR_VHT_CAPA, + /* keep last */ __NL80211_BAND_ATTR_AFTER_LAST, NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 @@ -2879,4 +3094,53 @@ enum nl80211_probe_resp_offload_support_attr { NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3, }; +/** + * enum nl80211_connect_failed_reason - connection request failed reasons + * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be + * handled by the AP is reached. + * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Connection request is rejected due to ACL. + */ +enum nl80211_connect_failed_reason { + NL80211_CONN_FAIL_MAX_CLIENTS, + NL80211_CONN_FAIL_BLOCKED_CLIENT, +}; + +/** + * enum nl80211_acl_policy - access control policy + * + * Access control policy is applied on a MAC list set by + * %NL80211_CMD_START_AP and %NL80211_CMD_SET_MAC_ACL, to + * be used with %NL80211_ATTR_ACL_POLICY. + * + * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are + * listed in ACL, i.e. allow all the stations which are not listed + * in ACL to authenticate. + * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow the stations which are listed + * in ACL, i.e. deny all the stations which are not listed in ACL. + */ +enum nl80211_acl_policy { + NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED, + NL80211_ACL_POLICY_DENY_UNLESS_LISTED, +}; +/** + * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers + * + * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified. + * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol. + * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol. + * @NL80211_CRIT_PROTO_APIPA: APIPA protocol. + * @NUM_NL80211_CRIT_PROTO: must be kept last. + */ +enum nl80211_crit_proto_id { + NL80211_CRIT_PROTO_UNSPEC, + NL80211_CRIT_PROTO_DHCP, + NL80211_CRIT_PROTO_EAPOL, + NL80211_CRIT_PROTO_APIPA, + /* add other protocols before this one */ + NUM_NL80211_CRIT_PROTO +}; + +/* maximum duration for critical protocol measures */ +#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */ + #endif /* __LINUX_NL80211_H */ diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index c88d2a9451a..86e4c91417d 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h @@ -108,6 +108,7 @@ enum pageflags { #ifdef CONFIG_TRANSPARENT_HUGEPAGE PG_compound_lock, #endif + PG_readahead, /* page in a readahead window */ __NR_PAGEFLAGS, /* Filesystems */ diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h index 11bad91c443..b751c0dd661 100644 --- a/include/linux/posix_acl.h +++ b/include/linux/posix_acl.h @@ -11,6 +11,7 @@ #include #include #include +#include #define ACL_UNDEFINED_ID (-1) @@ -36,7 +37,13 @@ struct posix_acl_entry { short e_tag; unsigned short e_perm; - unsigned int e_id; + union { + kuid_t e_uid; + kgid_t e_gid; +#ifndef CONFIG_UIDGID_STRICT_TYPE_CHECKS + unsigned int e_id; +#endif + }; }; struct posix_acl { @@ -82,13 +89,16 @@ extern int posix_acl_valid(const struct posix_acl *); extern int posix_acl_permission(struct inode *, const struct posix_acl *, int); extern struct posix_acl *posix_acl_from_mode(umode_t, gfp_t); extern int posix_acl_equiv_mode(const struct posix_acl *, umode_t *); -extern int posix_acl_create(struct posix_acl **, gfp_t, umode_t *); -extern int posix_acl_chmod(struct posix_acl **, gfp_t, umode_t); +extern int __posix_acl_create(struct posix_acl **, gfp_t, umode_t *); +extern int __posix_acl_chmod(struct posix_acl **, gfp_t, umode_t); extern struct posix_acl *get_posix_acl(struct inode *, int); extern int set_posix_acl(struct inode *, int, struct posix_acl *); #ifdef CONFIG_FS_POSIX_ACL +extern int posix_acl_chmod(struct inode *, umode_t); +extern int posix_acl_create(struct inode *, umode_t *, struct posix_acl **, + struct posix_acl **); static inline struct posix_acl **acl_by_type(struct inode *inode, int type) { switch (type) { @@ -169,4 +179,6 @@ static inline void cache_no_acl(struct inode *inode) #endif } +struct posix_acl *get_acl(struct inode *inode, int type); + #endif /* __LINUX_POSIX_ACL_H */ diff --git a/include/linux/posix_acl_xattr.h b/include/linux/posix_acl_xattr.h index 6e53c34035c..6f14ee29582 100644 --- a/include/linux/posix_acl_xattr.h +++ b/include/linux/posix_acl_xattr.h @@ -52,7 +52,24 @@ posix_acl_xattr_count(size_t size) return size / sizeof(posix_acl_xattr_entry); } -struct posix_acl *posix_acl_from_xattr(const void *value, size_t size); -int posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size); +#ifdef CONFIG_FS_POSIX_ACL +void posix_acl_fix_xattr_from_user(void *value, size_t size); +void posix_acl_fix_xattr_to_user(void *value, size_t size); +#else +static inline void posix_acl_fix_xattr_from_user(void *value, size_t size) +{ +} +static inline void posix_acl_fix_xattr_to_user(void *value, size_t size) +{ +} +#endif + +struct posix_acl *posix_acl_from_xattr(struct user_namespace *user_ns, + const void *value, size_t size); +int posix_acl_to_xattr(struct user_namespace *user_ns, + const struct posix_acl *acl, void *buffer, size_t size); + +extern const struct xattr_handler posix_acl_access_xattr_handler; +extern const struct xattr_handler posix_acl_default_xattr_handler; #endif /* _POSIX_ACL_XATTR_H */ diff --git a/include/linux/power/cpupower.h b/include/linux/power/cpupower.h new file mode 100644 index 00000000000..9bc7039a03f --- /dev/null +++ b/include/linux/power/cpupower.h @@ -0,0 +1,22 @@ +/* + * cpupower.h + * + * Copyright (c) 2011 Vincent Guittot + * + * This file is released under the GPLv2 + * + */ + +#ifndef _CPUPOWER_H_ +#define _CPUPOWER_H_ + +#define ARM_DEFAULT_SCALE 0 +#define ARM_POWER_SCALE 1 + +struct cputopo_power { + int max; /* max idx in the table */ + unsigned int step; /* frequency step for the table */ + unsigned int *table; /* table of cpu_power */ +}; + +#endif diff --git a/include/linux/prctl.h b/include/linux/prctl.h index e0cfec2490a..2f513409fab 100644 --- a/include/linux/prctl.h +++ b/include/linux/prctl.h @@ -124,4 +124,7 @@ #define PR_SET_CHILD_SUBREAPER 36 #define PR_GET_CHILD_SUBREAPER 37 +#define PR_SET_VMA 0x53564d41 +# define PR_SET_VMA_ANON_NAME 0 + #endif /* _LINUX_PRCTL_H */ diff --git a/include/linux/random.h b/include/linux/random.h index 8f74538c96d..ac621ce886c 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -48,13 +48,13 @@ struct rnd_state { #ifdef __KERNEL__ -extern void rand_initialize_irq(int irq); - +extern void add_device_randomness(const void *, unsigned int); extern void add_input_randomness(unsigned int type, unsigned int code, unsigned int value); -extern void add_interrupt_randomness(int irq); +extern void add_interrupt_randomness(int irq, int irq_flags); extern void get_random_bytes(void *buf, int nbytes); +extern void get_random_bytes_arch(void *buf, int nbytes); void generate_random_uuid(unsigned char uuid_out[16]); #ifndef MODULE diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h index 20fb776a1d4..3ac42da02c2 100644 --- a/include/linux/rcupdate.h +++ b/include/linux/rcupdate.h @@ -909,13 +909,14 @@ static __always_inline bool __is_kfree_rcu_offset(unsigned long offset) return offset < 4096; } +/* + * Intended to be called only from the kfree_rcu() macro. + */ static __always_inline void __kfree_rcu(struct rcu_head *head, unsigned long offset) { typedef void (*rcu_callback)(struct rcu_head *); - BUILD_BUG_ON(!__builtin_constant_p(offset)); - /* See the kfree_rcu() header comment. */ BUILD_BUG_ON(!__is_kfree_rcu_offset(offset)); diff --git a/include/linux/sched.h b/include/linux/sched.h index ff6bb0ff8c9..baffddc570e 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -122,10 +122,10 @@ extern void get_avenrun(unsigned long *loads, unsigned long offset, int shift); #define FSHIFT 11 /* nr of bits of precision */ #define FIXED_1 (1< + +struct task_struct; +/* Cookie handed to the thread_fn*/ +struct smpboot_thread_data; + +/** + * struct smp_hotplug_thread - CPU hotplug related thread descriptor + * @store: Pointer to per cpu storage for the task pointers + * @list: List head for core management + * @thread_should_run: Check whether the thread should run or not. Called with + * preemption disabled. + * @thread_fn: The associated thread function + * @create: Optional setup function, called when the thread gets + * created (Not called from the thread context) + * @setup: Optional setup function, called when the thread gets + * operational the first time + * @cleanup: Optional cleanup function, called when the thread + * should stop (module exit) + * @park: Optional park function, called when the thread is + * parked (cpu offline) + * @unpark: Optional unpark function, called when the thread is + * unparked (cpu online) + * @pre_unpark: Optional unpark function, called before the thread is + * unparked (cpu online). This is not guaranteed to be + * called on the target cpu of the thread. Careful! + * @selfparking: Thread is not parked by the park function. + * @thread_comm: The base name of the thread + */ +struct smp_hotplug_thread { + struct task_struct __percpu **store; + struct list_head list; + int (*thread_should_run)(unsigned int cpu); + void (*thread_fn)(unsigned int cpu); + void (*create)(unsigned int cpu); + void (*setup)(unsigned int cpu); + void (*cleanup)(unsigned int cpu, bool online); + void (*park)(unsigned int cpu); + void (*unpark)(unsigned int cpu); + void (*pre_unpark)(unsigned int cpu); + bool selfparking; + const char *thread_comm; +}; + +int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread); +void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread); +int smpboot_thread_schedule(void); + +#endif diff --git a/include/linux/sradix-tree.h b/include/linux/sradix-tree.h new file mode 100644 index 00000000000..6780fdb0a7a --- /dev/null +++ b/include/linux/sradix-tree.h @@ -0,0 +1,77 @@ +#ifndef _LINUX_SRADIX_TREE_H +#define _LINUX_SRADIX_TREE_H + + +#define INIT_SRADIX_TREE(root, mask) \ +do { \ + (root)->height = 0; \ + (root)->gfp_mask = (mask); \ + (root)->rnode = NULL; \ +} while (0) + +#define ULONG_BITS (sizeof(unsigned long) * 8) +#define SRADIX_TREE_INDEX_BITS (8 /* CHAR_BIT */ * sizeof(unsigned long)) +//#define SRADIX_TREE_MAP_SHIFT 6 +//#define SRADIX_TREE_MAP_SIZE (1UL << SRADIX_TREE_MAP_SHIFT) +//#define SRADIX_TREE_MAP_MASK (SRADIX_TREE_MAP_SIZE-1) + +struct sradix_tree_node { + unsigned int height; /* Height from the bottom */ + unsigned int count; + unsigned int fulls; /* Number of full sublevel trees */ + struct sradix_tree_node *parent; + void *stores[0]; +}; + +/* A simple radix tree implementation */ +struct sradix_tree_root { + unsigned int height; + struct sradix_tree_node *rnode; + + /* Where found to have available empty stores in its sublevels */ + struct sradix_tree_node *enter_node; + unsigned int shift; + unsigned int stores_size; + unsigned int mask; + unsigned long min; /* The first hole index */ + unsigned long num; + //unsigned long *height_to_maxindex; + + /* How the node is allocated and freed. */ + struct sradix_tree_node *(*alloc)(void); + void (*free)(struct sradix_tree_node *node); + + /* When a new node is added and removed */ + void (*extend)(struct sradix_tree_node *parent, struct sradix_tree_node *child); + void (*assign)(struct sradix_tree_node *node, unsigned index, void *item); + void (*rm)(struct sradix_tree_node *node, unsigned offset); +}; + +struct sradix_tree_path { + struct sradix_tree_node *node; + int offset; +}; + +static inline +void init_sradix_tree_root(struct sradix_tree_root *root, unsigned long shift) +{ + root->height = 0; + root->rnode = NULL; + root->shift = shift; + root->stores_size = 1UL << shift; + root->mask = root->stores_size - 1; +} + + +extern void *sradix_tree_next(struct sradix_tree_root *root, + struct sradix_tree_node *node, unsigned long index, + int (*iter)(void *, unsigned long)); + +extern int sradix_tree_enter(struct sradix_tree_root *root, void **item, int num); + +extern void sradix_tree_delete_from_leaf(struct sradix_tree_root *root, + struct sradix_tree_node *node, unsigned long index); + +extern void *sradix_tree_lookup(struct sradix_tree_root *root, unsigned long index); + +#endif /* _LINUX_SRADIX_TREE_H */ diff --git a/include/linux/swap.h b/include/linux/swap.h index b1fd5c7925f..bc3073ce95c 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -355,23 +355,6 @@ extern int reuse_swap_page(struct page *); extern int try_to_free_swap(struct page *); struct backing_dev_info; -/* linux/mm/thrash.c */ -extern struct mm_struct *swap_token_mm; -extern void grab_swap_token(struct mm_struct *); -extern void __put_swap_token(struct mm_struct *); -extern void disable_swap_token(struct mem_cgroup *memcg); - -static inline int has_swap_token(struct mm_struct *mm) -{ - return (mm == swap_token_mm); -} - -static inline void put_swap_token(struct mm_struct *mm) -{ - if (has_swap_token(mm)) - __put_swap_token(mm); -} - #ifdef CONFIG_CGROUP_MEM_RES_CTLR extern void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent, bool swapout); @@ -476,24 +459,6 @@ static inline swp_entry_t get_swap_page(void) return entry; } -/* linux/mm/thrash.c */ -static inline void put_swap_token(struct mm_struct *mm) -{ -} - -static inline void grab_swap_token(struct mm_struct *mm) -{ -} - -static inline int has_swap_token(struct mm_struct *mm) -{ - return 0; -} - -static inline void disable_swap_token(struct mem_cgroup *memcg) -{ -} - static inline void mem_cgroup_uncharge_swapcache(struct page *page, swp_entry_t ent) { diff --git a/include/linux/sweep2wake.h b/include/linux/sweep2wake.h new file mode 100644 index 00000000000..d2a00a77ed6 --- /dev/null +++ b/include/linux/sweep2wake.h @@ -0,0 +1,24 @@ +/* +* include/linux/sweep2wake.h +* +* Copyright (c) 2013, Aaron Segaert (flar2) asegaert at gmail.com +* +* 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. +* +* 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. +*/ + + +extern void sweep2wake_setdev(struct input_dev * input_device); +extern int pwr_key_pressed; +extern int lid_closed; diff --git a/include/linux/tick.h b/include/linux/tick.h index 494a3141dba..94759671062 100644 --- a/include/linux/tick.h +++ b/include/linux/tick.h @@ -140,4 +140,10 @@ static inline u64 get_cpu_idle_time_us(int cpu, u64 *unused) { return -1; } static inline u64 get_cpu_iowait_time_us(int cpu, u64 *unused) { return -1; } # endif /* !NO_HZ */ +# ifdef CONFIG_CPU_IDLE_GOV_MENU +extern void menu_hrtimer_cancel(void); +# else +static inline void menu_hrtimer_cancel(void) {} +# endif /* CONFIG_CPU_IDLE_GOV_MENU */ + #endif diff --git a/include/linux/uidgid.h b/include/linux/uidgid.h new file mode 100644 index 00000000000..8e522cbcef2 --- /dev/null +++ b/include/linux/uidgid.h @@ -0,0 +1,200 @@ +#ifndef _LINUX_UIDGID_H +#define _LINUX_UIDGID_H + +/* + * A set of types for the internal kernel types representing uids and gids. + * + * The types defined in this header allow distinguishing which uids and gids in + * the kernel are values used by userspace and which uid and gid values are + * the internal kernel values. With the addition of user namespaces the values + * can be different. Using the type system makes it possible for the compiler + * to detect when we overlook these differences. + * + */ +#include +#include + +struct user_namespace; +extern struct user_namespace init_user_ns; + +#ifdef CONFIG_UIDGID_STRICT_TYPE_CHECKS + +typedef struct { + uid_t val; +} kuid_t; + + +typedef struct { + gid_t val; +} kgid_t; + +#define KUIDT_INIT(value) (kuid_t){ value } +#define KGIDT_INIT(value) (kgid_t){ value } + +static inline uid_t __kuid_val(kuid_t uid) +{ + return uid.val; +} + +static inline gid_t __kgid_val(kgid_t gid) +{ + return gid.val; +} + +#else + +typedef uid_t kuid_t; +typedef gid_t kgid_t; + +static inline uid_t __kuid_val(kuid_t uid) +{ + return uid; +} + +static inline gid_t __kgid_val(kgid_t gid) +{ + return gid; +} + +#define KUIDT_INIT(value) ((kuid_t) value ) +#define KGIDT_INIT(value) ((kgid_t) value ) + +#endif + +#define GLOBAL_ROOT_UID KUIDT_INIT(0) +#define GLOBAL_ROOT_GID KGIDT_INIT(0) + +#define INVALID_UID KUIDT_INIT(-1) +#define INVALID_GID KGIDT_INIT(-1) + +static inline bool uid_eq(kuid_t left, kuid_t right) +{ + return __kuid_val(left) == __kuid_val(right); +} + +static inline bool gid_eq(kgid_t left, kgid_t right) +{ + return __kgid_val(left) == __kgid_val(right); +} + +static inline bool uid_gt(kuid_t left, kuid_t right) +{ + return __kuid_val(left) > __kuid_val(right); +} + +static inline bool gid_gt(kgid_t left, kgid_t right) +{ + return __kgid_val(left) > __kgid_val(right); +} + +static inline bool uid_gte(kuid_t left, kuid_t right) +{ + return __kuid_val(left) >= __kuid_val(right); +} + +static inline bool gid_gte(kgid_t left, kgid_t right) +{ + return __kgid_val(left) >= __kgid_val(right); +} + +static inline bool uid_lt(kuid_t left, kuid_t right) +{ + return __kuid_val(left) < __kuid_val(right); +} + +static inline bool gid_lt(kgid_t left, kgid_t right) +{ + return __kgid_val(left) < __kgid_val(right); +} + +static inline bool uid_lte(kuid_t left, kuid_t right) +{ + return __kuid_val(left) <= __kuid_val(right); +} + +static inline bool gid_lte(kgid_t left, kgid_t right) +{ + return __kgid_val(left) <= __kgid_val(right); +} + +static inline bool uid_valid(kuid_t uid) +{ + return !uid_eq(uid, INVALID_UID); +} + +static inline bool gid_valid(kgid_t gid) +{ + return !gid_eq(gid, INVALID_GID); +} + +#ifdef CONFIG_USER_NS + +extern kuid_t make_kuid(struct user_namespace *from, uid_t uid); +extern kgid_t make_kgid(struct user_namespace *from, gid_t gid); + +extern uid_t from_kuid(struct user_namespace *to, kuid_t uid); +extern gid_t from_kgid(struct user_namespace *to, kgid_t gid); +extern uid_t from_kuid_munged(struct user_namespace *to, kuid_t uid); +extern gid_t from_kgid_munged(struct user_namespace *to, kgid_t gid); + +static inline bool kuid_has_mapping(struct user_namespace *ns, kuid_t uid) +{ + return from_kuid(ns, uid) != (uid_t) -1; +} + +static inline bool kgid_has_mapping(struct user_namespace *ns, kgid_t gid) +{ + return from_kgid(ns, gid) != (gid_t) -1; +} + +#else + +static inline kuid_t make_kuid(struct user_namespace *from, uid_t uid) +{ + return KUIDT_INIT(uid); +} + +static inline kgid_t make_kgid(struct user_namespace *from, gid_t gid) +{ + return KGIDT_INIT(gid); +} + +static inline uid_t from_kuid(struct user_namespace *to, kuid_t kuid) +{ + return __kuid_val(kuid); +} + +static inline gid_t from_kgid(struct user_namespace *to, kgid_t kgid) +{ + return __kgid_val(kgid); +} + +static inline uid_t from_kuid_munged(struct user_namespace *to, kuid_t kuid) +{ + uid_t uid = from_kuid(to, kuid); + if (uid == (uid_t)-1) + uid = overflowuid; + return uid; +} + +static inline gid_t from_kgid_munged(struct user_namespace *to, kgid_t kgid) +{ + gid_t gid = from_kgid(to, kgid); + if (gid == (gid_t)-1) + gid = overflowgid; + return gid; +} + +static inline bool kuid_has_mapping(struct user_namespace *ns, kuid_t uid) +{ + return true; +} + +static inline bool kgid_has_mapping(struct user_namespace *ns, kgid_t gid) +{ + return true; +} + +#endif /* CONFIG_USER_NS */ + +#endif /* _LINUX_UIDGID_H */ diff --git a/include/linux/uksm.h b/include/linux/uksm.h new file mode 100644 index 00000000000..361eee2bc7d --- /dev/null +++ b/include/linux/uksm.h @@ -0,0 +1,145 @@ +#ifndef __LINUX_UKSM_H +#define __LINUX_UKSM_H +/* + * Memory merging support. + * + * This code enables dynamic sharing of identical pages found in different + * memory areas, even if they are not shared by fork(). + */ + +/* if !CONFIG_UKSM this file should not be compiled at all. */ +#ifdef CONFIG_UKSM + +#include +#include +#include +#include +#include + +extern unsigned long zero_pfn __read_mostly; +extern unsigned long uksm_zero_pfn __read_mostly; +extern struct page *empty_uksm_zero_page; + +/* must be done before linked to mm */ +extern void uksm_vma_add_new(struct vm_area_struct *vma); +extern void uksm_remove_vma(struct vm_area_struct *vma); + +#define UKSM_SLOT_NEED_SORT (1 << 0) +#define UKSM_SLOT_NEED_RERAND (1 << 1) +#define UKSM_SLOT_SCANNED (1 << 2) /* It's scanned in this round */ +#define UKSM_SLOT_FUL_SCANNED (1 << 3) +#define UKSM_SLOT_IN_UKSM (1 << 4) + +struct vma_slot { + struct sradix_tree_node *snode; + unsigned long sindex; + + struct list_head slot_list; + unsigned long fully_scanned_round; + unsigned long dedup_num; + unsigned long pages_scanned; + unsigned long last_scanned; + unsigned long pages_to_scan; + struct scan_rung *rung; + struct page **rmap_list_pool; + unsigned int *pool_counts; + unsigned long pool_size; + struct vm_area_struct *vma; + struct mm_struct *mm; + unsigned long ctime_j; + unsigned long pages; + unsigned long flags; + unsigned long pages_cowed; /* pages cowed this round */ + unsigned long pages_merged; /* pages merged this round */ + unsigned long pages_bemerged; + + /* when it has page merged in this eval round */ + struct list_head dedup_list; +}; + +static inline void uksm_unmap_zero_page(pte_t pte) +{ + if (pte_pfn(pte) == uksm_zero_pfn) + __dec_zone_page_state(empty_uksm_zero_page, NR_UKSM_ZERO_PAGES); +} + +static inline void uksm_map_zero_page(pte_t pte) +{ + if (pte_pfn(pte) == uksm_zero_pfn) + __inc_zone_page_state(empty_uksm_zero_page, NR_UKSM_ZERO_PAGES); +} + +static inline void uksm_cow_page(struct vm_area_struct *vma, struct page *page) +{ + if (vma->uksm_vma_slot && PageKsm(page)) + vma->uksm_vma_slot->pages_cowed++; +} + +static inline void uksm_cow_pte(struct vm_area_struct *vma, pte_t pte) +{ + if (vma->uksm_vma_slot && pte_pfn(pte) == uksm_zero_pfn) + vma->uksm_vma_slot->pages_cowed++; +} + +static inline int uksm_flags_can_scan(unsigned long vm_flags) +{ + return !(vm_flags & (VM_PFNMAP | VM_IO | VM_DONTEXPAND | + VM_RESERVED | VM_HUGETLB | VM_INSERTPAGE | + VM_NONLINEAR | VM_MIXEDMAP | VM_SAO | + VM_SHARED | VM_MAYSHARE | VM_GROWSUP + | VM_GROWSDOWN)); +} + +static inline void uksm_vm_flags_mod(unsigned long *vm_flags_p) +{ + if (uksm_flags_can_scan(*vm_flags_p)) + *vm_flags_p |= VM_MERGEABLE; +} + +/* + * Just a wrapper for BUG_ON for where ksm_zeropage must not be. TODO: it will + * be removed when uksm zero page patch is stable enough. + */ +static inline void uksm_bugon_zeropage(pte_t pte) +{ + BUG_ON(pte_pfn(pte) == uksm_zero_pfn); +} +#else +static inline void uksm_vma_add_new(struct vm_area_struct *vma) +{ +} + +static inline void uksm_remove_vma(struct vm_area_struct *vma) +{ +} + +static inline void uksm_unmap_zero_page(pte_t pte) +{ +} + +static inline void uksm_map_zero_page(pte_t pte) +{ +} + +static inline void uksm_cow_page(struct vm_area_struct *vma, struct page *page) +{ +} + +static inline void uksm_cow_pte(struct vm_area_struct *vma, pte_t pte) +{ +} + +static inline int uksm_flags_can_scan(unsigned long vm_flags) +{ + return 0; +} + +static inline void uksm_vm_flags_mod(unsigned long *vm_flags_p) +{ +} + +static inline void uksm_bugon_zeropage(pte_t pte) +{ +} +#endif /* !CONFIG_UKSM */ +#endif /* __LINUX_UKSM_H */ diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h index d6ffea7101c..14459bf6832 100644 --- a/include/linux/usb/msm_hsusb.h +++ b/include/linux/usb/msm_hsusb.h @@ -333,6 +333,7 @@ struct msm_otg { enum usb_chg_type chg_type; unsigned dcd_time; struct wake_lock wlock; + struct wake_lock cable_lock; struct notifier_block usbdev_nb; unsigned mA_port; struct timer_list id_timer; diff --git a/include/linux/wcnss_wlan.h b/include/linux/wcnss_wlan.h index eaf7ed383dc..766e5c61527 100644 --- a/include/linux/wcnss_wlan.h +++ b/include/linux/wcnss_wlan.h @@ -25,6 +25,12 @@ struct wcnss_wlan_config { int use_48mhz_xo; }; +enum { + WCNSS_XO_48MHZ = 1, + WCNSS_XO_19MHZ, + WCNSS_XO_INVALID, +}; + #define WCNSS_WLAN_IRQ_INVALID -1 #define HAVE_WCNSS_RESET_INTR 1 @@ -54,6 +60,7 @@ void wcnss_prevent_suspend(void); void wcnss_ssr_boot_notify(void); void wcnss_reset_intr(void); int wcnss_cold_boot_done(void); +int wcnss_wlan_iris_xo_mode(void); #define wcnss_wlan_get_drvdata(dev) dev_get_drvdata(dev) #define wcnss_wlan_set_drvdata(dev, data) dev_set_drvdata((dev), (data)) diff --git a/include/linux/writeback.h b/include/linux/writeback.h index a2b84f598e2..57b36957a3c 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -76,6 +76,7 @@ struct writeback_control { unsigned tagged_writepages:1; /* tag-and-write to avoid livelock */ unsigned for_reclaim:1; /* Invoked from the page allocator */ unsigned range_cyclic:1; /* range_start is cyclic */ + unsigned for_sync:1; /* sync(2) WB_SYNC_ALL writeback */ }; /* diff --git a/include/net/af_unix.h b/include/net/af_unix.h index ca68e2cef23..64c513b9fe1 100644 --- a/include/net/af_unix.h +++ b/include/net/af_unix.h @@ -14,10 +14,11 @@ extern struct sock *unix_get_socket(struct file *filp); extern struct sock *unix_peer_get(struct sock *); #define UNIX_HASH_SIZE 256 +#define UNIX_HASH_BITS 8 extern unsigned int unix_tot_inflight; extern spinlock_t unix_table_lock; -extern struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; +extern struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; struct unix_address { atomic_t refcnt; diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index d29c15790f8..63ffb52ad8e 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -210,6 +210,22 @@ struct ieee80211_sta_ht_cap { struct ieee80211_mcs_info mcs; }; +/** + * struct ieee80211_sta_vht_cap - STA's VHT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11ac VHT capabilities for an STA. + * + * @vht_supported: is VHT supported by the STA + * @cap: VHT capabilities map as described in 802.11ac spec + * @vht_mcs: Supported VHT MCS rates + */ +struct ieee80211_sta_vht_cap { + bool vht_supported; + u32 cap; /* use IEEE80211_VHT_CAP_ */ + struct ieee80211_vht_mcs_info vht_mcs; +}; + /** * struct ieee80211_supported_band - frequency band definition * @@ -233,6 +249,7 @@ struct ieee80211_supported_band { int n_channels; int n_bitrates; struct ieee80211_sta_ht_cap ht_cap; + struct ieee80211_sta_vht_cap vht_cap; }; /* @@ -399,6 +416,26 @@ struct cfg80211_beacon_data { size_t probe_resp_len; }; +struct mac_address { + u8 addr[ETH_ALEN]; +}; + +/** + * struct cfg80211_acl_data - Access control list data + * + * @acl_policy: ACL policy to be applied on the station's + * entry specified by mac_addr + * @n_acl_entries: Number of MAC address entries passed + * @mac_addrs: List of MAC addresses of stations to be used for ACL + */ +struct cfg80211_acl_data { + enum nl80211_acl_policy acl_policy; + int n_acl_entries; + + /* Keep it last */ + struct mac_address mac_addrs[]; +}; + /** * struct cfg80211_ap_settings - AP configuration * @@ -415,6 +452,8 @@ struct cfg80211_beacon_data { * @privacy: the BSS uses privacy * @auth_type: Authentication type (algorithm) * @inactivity_timeout: time in seconds to determine station's inactivity. + * @acl: ACL configuration used by the drivers which has support for + * MAC address based access control */ struct cfg80211_ap_settings { struct cfg80211_beacon_data beacon; @@ -427,6 +466,7 @@ struct cfg80211_ap_settings { bool privacy; enum nl80211_auth_type auth_type; int inactivity_timeout; + const struct cfg80211_acl_data *acl; }; /** @@ -445,12 +485,14 @@ enum plink_actions { /** * enum station_parameters_apply_mask - station parameter values to apply * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) + * @STATION_PARAM_APPLY_CAPABILITY: apply new capability * * Not all station parameters have in-band "no change" signalling, * for those that don't these flags will are used. */ enum station_parameters_apply_mask { STATION_PARAM_APPLY_UAPSD = BIT(0), + STATION_PARAM_APPLY_CAPABILITY = BIT(1), }; /** @@ -471,6 +513,7 @@ enum station_parameters_apply_mask { * @plink_action: plink action to take * @plink_state: set the peer link state for a station * @ht_capa: HT capabilities of station + * @vht_capa: VHT capabilities of station * @uapsd_queues: bitmap of queues configured for uapsd. same format * as the AC bitmap in the QoS info field * @max_sp: max Service Period. same format as the MAX_SP in the @@ -478,6 +521,9 @@ enum station_parameters_apply_mask { * @sta_modify_mask: bitmap indicating which parameters changed * (for those that don't have a natural "no change" value), * see &enum station_parameters_apply_mask + * @capability: station capability + * @ext_capab: extended capabilities of the station + * @ext_capab_len: number of extended capabilities */ struct station_parameters { u8 *supported_rates; @@ -490,8 +536,12 @@ struct station_parameters { u8 plink_action; u8 plink_state; struct ieee80211_ht_cap *ht_capa; + struct ieee80211_vht_cap *vht_capa; u8 uapsd_queues; u8 max_sp; + u16 capability; + u8 *ext_capab; + u8 ext_capab_len; }; /** @@ -1331,6 +1381,21 @@ struct cfg80211_gtk_rekey_data { u8 replay_ctr[NL80211_REPLAY_CTR_LEN]; }; +/** + * struct cfg80211_update_ft_ies_params - FT IE Information + * + * This structure provides information needed to update the fast transition IE + * + * @md: The Mobility Domain ID, 2 Octet value + * @ie: Fast Transition IEs + * @ie_len: Length of ft_ie in octets + */ +struct cfg80211_update_ft_ies_params { + u16 md; + const u8 *ie; + size_t ie_len; +}; + /** * struct cfg80211_ops - backend description for wireless configuration * @@ -1515,6 +1580,13 @@ struct cfg80211_gtk_rekey_data { * later passes to cfg80211_probe_status(). * * @set_noack_map: Set the NoAck Map for the TIDs. + * @set_mac_acl: Sets MAC address control list in AP and P2P GO mode. + * Parameters include ACL policy, an array of MAC address of stations + * and the number of MAC addresses. If there is already a list in driver + * this new list replaces the existing one. Driver has to clear its ACL + * when number of MAC addresses entries is passed as 0. Drivers which + * advertise the support for MAC based ACL have to implement this callback. + * */ struct cfg80211_ops { int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow); @@ -1711,6 +1783,11 @@ struct cfg80211_ops { u16 noack_map); struct ieee80211_channel *(*get_channel)(struct wiphy *wiphy); + int (*update_ft_ies)(struct wiphy *wiphy, struct net_device *dev, + struct cfg80211_update_ft_ies_params *ftie); + + int (*set_mac_acl)(struct wiphy *wiphy, struct net_device *dev, + const struct cfg80211_acl_data *params); }; /* @@ -1722,22 +1799,28 @@ struct cfg80211_ops { * enum wiphy_flags - wiphy capability flags * * @WIPHY_FLAG_CUSTOM_REGULATORY: tells us the driver for this device - * has its own custom regulatory domain and cannot identify the - * ISO / IEC 3166 alpha2 it belongs to. When this is enabled - * we will disregard the first regulatory hint (when the - * initiator is %REGDOM_SET_BY_CORE). - * @WIPHY_FLAG_STRICT_REGULATORY: tells us the driver for this device will - * ignore regulatory domain settings until it gets its own regulatory - * domain via its regulatory_hint() unless the regulatory hint is - * from a country IE. After its gets its own regulatory domain it will - * only allow further regulatory domain settings to further enhance - * compliance. For example if channel 13 and 14 are disabled by this - * regulatory domain no user regulatory domain can enable these channels - * at a later time. This can be used for devices which do not have - * calibration information guaranteed for frequencies or settings - * outside of its regulatory domain. If used in combination with - * WIPHY_FLAG_CUSTOM_REGULATORY the inspected country IE power settings - * will be followed. + * has its own custom regulatory domain and cannot identify the + * ISO / IEC 3166 alpha2 it belongs to. When this is enabled + * we will disregard the first regulatory hint (when the + * initiator is %REGDOM_SET_BY_CORE). wiphys can set the custom + * regulatory domain using wiphy_apply_custom_regulatory() + * prior to wiphy registration. + * @WIPHY_FLAG_STRICT_REGULATORY: tells us that the wiphy for this device + * has regulatory domain that it wishes to be considered as the + * superset for regulatory rules. After this device gets its regulatory + * domain programmed further regulatory hints shall only be considered + * for this device to enhance regulatory compliance, forcing the + * device to only possibly use subsets of the original regulatory + * rules. For example if channel 13 and 14 are disabled by this + * device's regulatory domain no user specified regulatory hint which + * has these channels enabled would enable them for this wiphy, + * the device's original regulatory domain will be trusted as the + * base. You can program the superset of regulatory rules for this + * wiphy with regulatory_hint() for cards programmed with an + * ISO3166-alpha2 country code. wiphys that use regulatory_hint() + * will have their wiphy->regd programmed once the regulatory + * domain is set, and all other regulatory hints will be ignored + * until their own regulatory domain gets programmed. * @WIPHY_FLAG_DISABLE_BEACON_HINTS: enable this if your driver needs to ensure * that passive scan flags and beaconing flags may not be lifted by * cfg80211 due to regulatory beacon hints. For more information on beacon @@ -1804,6 +1887,34 @@ enum wiphy_flags { WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL = BIT(21), }; +/** + * enum nl80211_country_ie_pref - country IE processing preferences + * + * enumerates the different preferences a 802.11 card can advertize + * for parsing the country IEs. As per the current implementation + * country IEs are only used derive the apha2, the information + * for power settings that comes with the country IE is ignored + * and we use the power settings from regdb. + * + * @NL80211_COUNTRY_IE_FOLLOW_CORE - This is the default behaviour. + * It allows the core to update channel flags according to the + * ISO3166-alpha2 in the country IE. The applied power is - + * MIN(power specified by custom domain, power obtained from regdb) + * @NL80211_COUNTRY_IE_FOLLOW_POWER - for devices that have a + * preference that even though they may have programmed their own + * custom power setting prior to wiphy registration, they want + * to ensure their channel power settings are updated for this + * connection with the power settings derived from alpha2 of the + * country IE. + * @NL80211_COUNTRY_IE_IGNORE_CORE - for devices that have a preference to + * to ignore all country IE information processed by the core. + */ +enum nl80211_country_ie_pref { + NL80211_COUNTRY_IE_FOLLOW_CORE, + NL80211_COUNTRY_IE_FOLLOW_POWER, + NL80211_COUNTRY_IE_IGNORE_CORE, +}; + /** * struct ieee80211_iface_limit - limit on certain interface types * @max: maximum number of interfaces of these types @@ -1878,10 +1989,6 @@ struct ieee80211_iface_combination { bool beacon_int_infra_match; }; -struct mac_address { - u8 addr[ETH_ALEN]; -}; - struct ieee80211_txrx_stypes { u16 tx, rx; }; @@ -2022,6 +2129,11 @@ struct wiphy_wowlan_support { * @ap_sme_capa: AP SME capabilities, flags from &enum nl80211_ap_sme_features. * @ht_capa_mod_mask: Specify what ht_cap values can be over-ridden. * If null, then none can be over-ridden. + * + * @max_acl_mac_addrs: Maximum number of MAC addresses that the device + * supports for ACL. + * @country_ie_pref: country IE processing preferences specified + * by enum nl80211_country_ie_pref */ struct wiphy { /* assign these fields before you register the wiphy */ @@ -2043,6 +2155,8 @@ struct wiphy { /* Supported interface modes, OR together BIT(NL80211_IFTYPE_...) */ u16 interface_modes; + u16 max_acl_mac_addrs; + u32 flags, features; u32 ap_sme_capa; @@ -2084,6 +2198,8 @@ struct wiphy { */ u32 probe_resp_offload; + u8 country_ie_pref; + /* If multiple wiphys are registered and you're handed e.g. * a regular netdev with assigned ieee80211_ptr, you won't * know whether it points to a wiphy your driver has registered @@ -3381,6 +3497,31 @@ void cfg80211_tdls_oper_request(struct net_device *dev, const u8 *peer, */ u16 cfg80211_calculate_bitrate(struct rate_info *rate); +/** + * struct cfg80211_ft_event - FT Information Elements + * @ies: FT IEs + * @ies_len: length of the FT IE in bytes + * @target_ap: target AP's MAC address + * @ric_ies: RIC IE + * @ric_ies_len: length of the RIC IE in bytes + */ +struct cfg80211_ft_event_params { + const u8 *ies; + size_t ies_len; + const u8 *target_ap; + const u8 *ric_ies; + size_t ric_ies_len; +}; + +/** + * cfg80211_ft_event - notify userspace about FT IE and RIC IE + * @netdev: network device + * @ft_event: IE information + */ +void cfg80211_ft_event(struct net_device *netdev, + struct cfg80211_ft_event_params *ft_event); + + /* Logging, debugging and troubleshooting/diagnostic helpers. */ /* wiphy_printk helpers, similar to dev_printk */ diff --git a/include/net/inet6_hashtables.h b/include/net/inet6_hashtables.h index 00cbb4384c7..2da45ce8acb 100644 --- a/include/net/inet6_hashtables.h +++ b/include/net/inet6_hashtables.h @@ -28,16 +28,16 @@ struct inet_hashinfo; -/* I have no idea if this is a good hash for v6 or not. -DaveM */ static inline unsigned int inet6_ehashfn(struct net *net, const struct in6_addr *laddr, const u16 lport, const struct in6_addr *faddr, const __be16 fport) { - u32 ports = (lport ^ (__force u16)fport); + u32 ports = (((u32)lport) << 16) | (__force u32)fport; return jhash_3words((__force u32)laddr->s6_addr32[3], - (__force u32)faddr->s6_addr32[3], - ports, inet_ehash_secret + net_hash_mix(net)); + ipv6_addr_jhash(faddr), + ports, + inet_ehash_secret + net_hash_mix(net)); } static inline int inet6_sk_ehashfn(const struct sock *sk) diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h index ae17e1352d7..8cd2e1d0ec3 100644 --- a/include/net/inet_sock.h +++ b/include/net/inet_sock.h @@ -202,6 +202,7 @@ static inline void inet_sk_copy_descendant(struct sock *sk_to, extern int inet_sk_rebuild_header(struct sock *sk); extern u32 inet_ehash_secret; +extern u32 ipv6_hash_secret; extern void build_ehash_secret(void); static inline unsigned int inet_ehashfn(struct net *net, diff --git a/include/net/ipv6.h b/include/net/ipv6.h index e4170a22fc6..5381973f099 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -252,6 +253,14 @@ static inline void fl6_sock_release(struct ip6_flowlabel *fl) atomic_dec(&fl->users); } +extern void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info); + +int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct icmp6hdr *thdr, int len); + +struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, + struct sock *sk, struct flowi6 *fl6); + extern int ip6_ra_control(struct sock *sk, int sel); extern int ipv6_parse_hopopts(struct sk_buff *skb); @@ -294,6 +303,18 @@ static inline int ipv6_addr_src_scope(const struct in6_addr *addr) return __ipv6_addr_src_scope(__ipv6_addr_type(addr)); } +static inline bool __ipv6_addr_needs_scope_id(int type) +{ + return type & IPV6_ADDR_LINKLOCAL || + (type & IPV6_ADDR_MULTICAST && + (type & (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL))); +} + +static inline __u32 ipv6_iface_scope_id(const struct in6_addr *addr, int iface) +{ + return __ipv6_addr_needs_scope_id(__ipv6_addr_type(addr)) ? iface : 0; +} + static inline int ipv6_addr_cmp(const struct in6_addr *a1, const struct in6_addr *a2) { return memcmp(a1, a2, sizeof(struct in6_addr)); @@ -396,6 +417,17 @@ static inline int ipv6_addr_any(const struct in6_addr *a) a->s6_addr32[2] | a->s6_addr32[3]) == 0; } +/* more secured version of ipv6_addr_hash() */ +static inline u32 ipv6_addr_jhash(const struct in6_addr *a) +{ + u32 v = (__force u32)a->s6_addr32[0] ^ (__force u32)a->s6_addr32[1]; + + return jhash_3words(v, + (__force u32)a->s6_addr32[2], + (__force u32)a->s6_addr32[3], + ipv6_hash_secret); +} + static inline int ipv6_addr_loopback(const struct in6_addr *a) { return (a->s6_addr32[0] | a->s6_addr32[1] | diff --git a/include/net/ping.h b/include/net/ping.h index 682b5ae9af5..b1717ae93da 100644 --- a/include/net/ping.h +++ b/include/net/ping.h @@ -13,6 +13,7 @@ #ifndef _PING_H #define _PING_H +#include #include /* PING_HTABLE_SIZE must be power of 2 */ @@ -28,6 +29,18 @@ */ #define GID_T_MAX (((gid_t)~0U) >> 1) +/* Compatibility glue so we can support IPv6 when it's compiled as a module */ +struct pingv6_ops { + int (*ipv6_recv_error)(struct sock *sk, struct msghdr *msg, int len); + int (*datagram_recv_ctl)(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb); + int (*icmpv6_err_convert)(u8 type, u8 code, int *err); + void (*ipv6_icmp_error)(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload); + int (*ipv6_chk_addr)(struct net *net, const struct in6_addr *addr, + struct net_device *dev, int strict); +}; + struct ping_table { struct hlist_nulls_head hash[PING_HTABLE_SIZE]; rwlock_t lock; @@ -39,10 +52,40 @@ struct ping_iter_state { }; extern struct proto ping_prot; +extern struct ping_table ping_table; +#if IS_ENABLED(CONFIG_IPV6) +extern struct pingv6_ops pingv6_ops; +#endif +struct pingfakehdr { + struct icmphdr icmph; + struct iovec *iov; + sa_family_t family; + __wsum wcheck; +}; -extern void ping_rcv(struct sk_buff *); -extern void ping_err(struct sk_buff *, u32 info); +int ping_get_port(struct sock *sk, unsigned short ident); +void ping_hash(struct sock *sk); +void ping_unhash(struct sock *sk); + +int ping_init_sock(struct sock *sk); +void ping_close(struct sock *sk, long timeout); +int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len); +void ping_err(struct sk_buff *skb, int offset, u32 info); +void ping_v4_err(struct sk_buff *skb, u32 info); +int ping_getfrag(void *from, char *to, int offset, int fraglen, int odd, + struct sk_buff *); + +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len); +int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len); +int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len); +int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); +void ping_rcv(struct sk_buff *skb); #ifdef CONFIG_PROC_FS extern int __init ping_proc_init(void); @@ -50,6 +93,7 @@ extern void ping_proc_exit(void); #endif void __init ping_init(void); - +int __init pingv6_init(void); +void pingv6_exit(void); #endif /* _PING_H */ diff --git a/include/net/secure_seq.h b/include/net/secure_seq.h index c2e542b27a5..6ca975bebd3 100644 --- a/include/net/secure_seq.h +++ b/include/net/secure_seq.h @@ -3,6 +3,7 @@ #include +extern void net_secret_init(void); extern __u32 secure_ip_id(__be32 daddr); extern __u32 secure_ipv6_id(const __be32 daddr[4]); extern u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport); diff --git a/include/net/tcp.h b/include/net/tcp.h index 50660b3e72b..93934e48544 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -252,6 +252,7 @@ extern int sysctl_tcp_max_ssthresh; extern int sysctl_tcp_cookie_size; extern int sysctl_tcp_thin_linear_timeouts; extern int sysctl_tcp_thin_dupack; +extern int sysctl_tcp_default_init_rwnd; extern atomic_long_t tcp_memory_allocated; extern struct percpu_counter tcp_sockets_allocated; diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 498433dd067..48b42ea9c2f 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h @@ -11,6 +11,7 @@ extern struct proto rawv6_prot; extern struct proto udpv6_prot; extern struct proto udplitev6_prot; extern struct proto tcpv6_prot; +extern struct proto pingv6_prot; struct flowi6; @@ -21,6 +22,8 @@ extern int ipv6_frag_init(void); extern void ipv6_frag_exit(void); /* transport protocols */ +extern int pingv6_init(void); +extern void pingv6_exit(void); extern int rawv6_init(void); extern void rawv6_exit(void); extern int udpv6_init(void); diff --git a/include/trace/events/f2fs.h b/include/trace/events/f2fs.h new file mode 100644 index 00000000000..81e131ed4fd --- /dev/null +++ b/include/trace/events/f2fs.h @@ -0,0 +1,932 @@ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM f2fs + +#if !defined(_TRACE_F2FS_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_F2FS_H + +#include + +#define show_dev(entry) MAJOR(entry->dev), MINOR(entry->dev) +#define show_dev_ino(entry) show_dev(entry), (unsigned long)entry->ino + +#define show_block_type(type) \ + __print_symbolic(type, \ + { NODE, "NODE" }, \ + { DATA, "DATA" }, \ + { META, "META" }, \ + { META_FLUSH, "META_FLUSH" }) + +#define F2FS_BIO_MASK(t) (t & (READA | WRITE_FLUSH_FUA)) +#define F2FS_BIO_EXTRA_MASK(t) (t & (REQ_META | REQ_PRIO)) + +#define show_bio_type(type) show_bio_base(type), show_bio_extra(type) + +#define show_bio_base(type) \ + __print_symbolic(F2FS_BIO_MASK(type), \ + { READ, "READ" }, \ + { READA, "READAHEAD" }, \ + { READ_SYNC, "READ_SYNC" }, \ + { WRITE, "WRITE" }, \ + { WRITE_SYNC, "WRITE_SYNC" }, \ + { WRITE_FLUSH, "WRITE_FLUSH" }, \ + { WRITE_FUA, "WRITE_FUA" }, \ + { WRITE_FLUSH_FUA, "WRITE_FLUSH_FUA" }) + +#define show_bio_extra(type) \ + __print_symbolic(F2FS_BIO_EXTRA_MASK(type), \ + { REQ_META, "(M)" }, \ + { REQ_PRIO, "(P)" }, \ + { REQ_META | REQ_PRIO, "(MP)" }, \ + { 0, " \b" }) + +#define show_data_type(type) \ + __print_symbolic(type, \ + { CURSEG_HOT_DATA, "Hot DATA" }, \ + { CURSEG_WARM_DATA, "Warm DATA" }, \ + { CURSEG_COLD_DATA, "Cold DATA" }, \ + { CURSEG_HOT_NODE, "Hot NODE" }, \ + { CURSEG_WARM_NODE, "Warm NODE" }, \ + { CURSEG_COLD_NODE, "Cold NODE" }, \ + { NO_CHECK_TYPE, "No TYPE" }) + +#define show_file_type(type) \ + __print_symbolic(type, \ + { 0, "FILE" }, \ + { 1, "DIR" }) + +#define show_gc_type(type) \ + __print_symbolic(type, \ + { FG_GC, "Foreground GC" }, \ + { BG_GC, "Background GC" }) + +#define show_alloc_mode(type) \ + __print_symbolic(type, \ + { LFS, "LFS-mode" }, \ + { SSR, "SSR-mode" }) + +#define show_victim_policy(type) \ + __print_symbolic(type, \ + { GC_GREEDY, "Greedy" }, \ + { GC_CB, "Cost-Benefit" }) + +struct victim_sel_policy; + +DECLARE_EVENT_CLASS(f2fs__inode, + + TP_PROTO(struct inode *inode), + + TP_ARGS(inode), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(ino_t, pino) + __field(umode_t, mode) + __field(loff_t, size) + __field(unsigned int, nlink) + __field(blkcnt_t, blocks) + __field(__u8, advise) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->pino = F2FS_I(inode)->i_pino; + __entry->mode = inode->i_mode; + __entry->nlink = inode->i_nlink; + __entry->size = inode->i_size; + __entry->blocks = inode->i_blocks; + __entry->advise = F2FS_I(inode)->i_advise; + ), + + TP_printk("dev = (%d,%d), ino = %lu, pino = %lu, i_mode = 0x%hx, " + "i_size = %lld, i_nlink = %u, i_blocks = %llu, i_advise = 0x%x", + show_dev_ino(__entry), + (unsigned long)__entry->pino, + __entry->mode, + __entry->size, + (unsigned int)__entry->nlink, + (unsigned long long)__entry->blocks, + (unsigned char)__entry->advise) +); + +DECLARE_EVENT_CLASS(f2fs__inode_exit, + + TP_PROTO(struct inode *inode, int ret), + + TP_ARGS(inode, ret), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(int, ret) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->ret = ret; + ), + + TP_printk("dev = (%d,%d), ino = %lu, ret = %d", + show_dev_ino(__entry), + __entry->ret) +); + +DEFINE_EVENT(f2fs__inode, f2fs_sync_file_enter, + + TP_PROTO(struct inode *inode), + + TP_ARGS(inode) +); + +TRACE_EVENT(f2fs_sync_file_exit, + + TP_PROTO(struct inode *inode, bool need_cp, int datasync, int ret), + + TP_ARGS(inode, need_cp, datasync, ret), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(bool, need_cp) + __field(int, datasync) + __field(int, ret) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->need_cp = need_cp; + __entry->datasync = datasync; + __entry->ret = ret; + ), + + TP_printk("dev = (%d,%d), ino = %lu, checkpoint is %s, " + "datasync = %d, ret = %d", + show_dev_ino(__entry), + __entry->need_cp ? "needed" : "not needed", + __entry->datasync, + __entry->ret) +); + +TRACE_EVENT(f2fs_sync_fs, + + TP_PROTO(struct super_block *sb, int wait), + + TP_ARGS(sb, wait), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(int, dirty) + __field(int, wait) + ), + + TP_fast_assign( + __entry->dev = sb->s_dev; + __entry->dirty = F2FS_SB(sb)->s_dirty; + __entry->wait = wait; + ), + + TP_printk("dev = (%d,%d), superblock is %s, wait = %d", + show_dev(__entry), + __entry->dirty ? "dirty" : "not dirty", + __entry->wait) +); + +DEFINE_EVENT(f2fs__inode, f2fs_iget, + + TP_PROTO(struct inode *inode), + + TP_ARGS(inode) +); + +DEFINE_EVENT(f2fs__inode_exit, f2fs_iget_exit, + + TP_PROTO(struct inode *inode, int ret), + + TP_ARGS(inode, ret) +); + +DEFINE_EVENT(f2fs__inode, f2fs_evict_inode, + + TP_PROTO(struct inode *inode), + + TP_ARGS(inode) +); + +DEFINE_EVENT(f2fs__inode_exit, f2fs_new_inode, + + TP_PROTO(struct inode *inode, int ret), + + TP_ARGS(inode, ret) +); + +TRACE_EVENT(f2fs_unlink_enter, + + TP_PROTO(struct inode *dir, struct dentry *dentry), + + TP_ARGS(dir, dentry), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(loff_t, size) + __field(blkcnt_t, blocks) + __field(const char *, name) + ), + + TP_fast_assign( + __entry->dev = dir->i_sb->s_dev; + __entry->ino = dir->i_ino; + __entry->size = dir->i_size; + __entry->blocks = dir->i_blocks; + __entry->name = dentry->d_name.name; + ), + + TP_printk("dev = (%d,%d), dir ino = %lu, i_size = %lld, " + "i_blocks = %llu, name = %s", + show_dev_ino(__entry), + __entry->size, + (unsigned long long)__entry->blocks, + __entry->name) +); + +DEFINE_EVENT(f2fs__inode_exit, f2fs_unlink_exit, + + TP_PROTO(struct inode *inode, int ret), + + TP_ARGS(inode, ret) +); + +DEFINE_EVENT(f2fs__inode, f2fs_truncate, + + TP_PROTO(struct inode *inode), + + TP_ARGS(inode) +); + +TRACE_EVENT(f2fs_truncate_data_blocks_range, + + TP_PROTO(struct inode *inode, nid_t nid, unsigned int ofs, int free), + + TP_ARGS(inode, nid, ofs, free), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(nid_t, nid) + __field(unsigned int, ofs) + __field(int, free) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->nid = nid; + __entry->ofs = ofs; + __entry->free = free; + ), + + TP_printk("dev = (%d,%d), ino = %lu, nid = %u, offset = %u, freed = %d", + show_dev_ino(__entry), + (unsigned int)__entry->nid, + __entry->ofs, + __entry->free) +); + +DECLARE_EVENT_CLASS(f2fs__truncate_op, + + TP_PROTO(struct inode *inode, u64 from), + + TP_ARGS(inode, from), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(loff_t, size) + __field(blkcnt_t, blocks) + __field(u64, from) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->size = inode->i_size; + __entry->blocks = inode->i_blocks; + __entry->from = from; + ), + + TP_printk("dev = (%d,%d), ino = %lu, i_size = %lld, i_blocks = %llu, " + "start file offset = %llu", + show_dev_ino(__entry), + __entry->size, + (unsigned long long)__entry->blocks, + (unsigned long long)__entry->from) +); + +DEFINE_EVENT(f2fs__truncate_op, f2fs_truncate_blocks_enter, + + TP_PROTO(struct inode *inode, u64 from), + + TP_ARGS(inode, from) +); + +DEFINE_EVENT(f2fs__inode_exit, f2fs_truncate_blocks_exit, + + TP_PROTO(struct inode *inode, int ret), + + TP_ARGS(inode, ret) +); + +DEFINE_EVENT(f2fs__truncate_op, f2fs_truncate_inode_blocks_enter, + + TP_PROTO(struct inode *inode, u64 from), + + TP_ARGS(inode, from) +); + +DEFINE_EVENT(f2fs__inode_exit, f2fs_truncate_inode_blocks_exit, + + TP_PROTO(struct inode *inode, int ret), + + TP_ARGS(inode, ret) +); + +DECLARE_EVENT_CLASS(f2fs__truncate_node, + + TP_PROTO(struct inode *inode, nid_t nid, block_t blk_addr), + + TP_ARGS(inode, nid, blk_addr), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(nid_t, nid) + __field(block_t, blk_addr) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->nid = nid; + __entry->blk_addr = blk_addr; + ), + + TP_printk("dev = (%d,%d), ino = %lu, nid = %u, block_address = 0x%llx", + show_dev_ino(__entry), + (unsigned int)__entry->nid, + (unsigned long long)__entry->blk_addr) +); + +DEFINE_EVENT(f2fs__truncate_node, f2fs_truncate_nodes_enter, + + TP_PROTO(struct inode *inode, nid_t nid, block_t blk_addr), + + TP_ARGS(inode, nid, blk_addr) +); + +DEFINE_EVENT(f2fs__inode_exit, f2fs_truncate_nodes_exit, + + TP_PROTO(struct inode *inode, int ret), + + TP_ARGS(inode, ret) +); + +DEFINE_EVENT(f2fs__truncate_node, f2fs_truncate_node, + + TP_PROTO(struct inode *inode, nid_t nid, block_t blk_addr), + + TP_ARGS(inode, nid, blk_addr) +); + +TRACE_EVENT(f2fs_truncate_partial_nodes, + + TP_PROTO(struct inode *inode, nid_t nid[], int depth, int err), + + TP_ARGS(inode, nid, depth, err), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(nid_t, nid[3]) + __field(int, depth) + __field(int, err) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->nid[0] = nid[0]; + __entry->nid[1] = nid[1]; + __entry->nid[2] = nid[2]; + __entry->depth = depth; + __entry->err = err; + ), + + TP_printk("dev = (%d,%d), ino = %lu, " + "nid[0] = %u, nid[1] = %u, nid[2] = %u, depth = %d, err = %d", + show_dev_ino(__entry), + (unsigned int)__entry->nid[0], + (unsigned int)__entry->nid[1], + (unsigned int)__entry->nid[2], + __entry->depth, + __entry->err) +); + +TRACE_EVENT_CONDITION(f2fs_submit_page_bio, + + TP_PROTO(struct page *page, sector_t blkaddr, int type), + + TP_ARGS(page, blkaddr, type), + + TP_CONDITION(page->mapping), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(pgoff_t, index) + __field(sector_t, blkaddr) + __field(int, type) + ), + + TP_fast_assign( + __entry->dev = page->mapping->host->i_sb->s_dev; + __entry->ino = page->mapping->host->i_ino; + __entry->index = page->index; + __entry->blkaddr = blkaddr; + __entry->type = type; + ), + + TP_printk("dev = (%d,%d), ino = %lu, page_index = 0x%lx, " + "blkaddr = 0x%llx, bio_type = %s%s", + show_dev_ino(__entry), + (unsigned long)__entry->index, + (unsigned long long)__entry->blkaddr, + show_bio_type(__entry->type)) +); + +TRACE_EVENT(f2fs_get_data_block, + TP_PROTO(struct inode *inode, sector_t iblock, + struct buffer_head *bh, int ret), + + TP_ARGS(inode, iblock, bh, ret), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(sector_t, iblock) + __field(sector_t, bh_start) + __field(size_t, bh_size) + __field(int, ret) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->iblock = iblock; + __entry->bh_start = bh->b_blocknr; + __entry->bh_size = bh->b_size; + __entry->ret = ret; + ), + + TP_printk("dev = (%d,%d), ino = %lu, file offset = %llu, " + "start blkaddr = 0x%llx, len = 0x%llx bytes, err = %d", + show_dev_ino(__entry), + (unsigned long long)__entry->iblock, + (unsigned long long)__entry->bh_start, + (unsigned long long)__entry->bh_size, + __entry->ret) +); + +TRACE_EVENT(f2fs_get_victim, + + TP_PROTO(struct super_block *sb, int type, int gc_type, + struct victim_sel_policy *p, unsigned int pre_victim, + unsigned int prefree, unsigned int free), + + TP_ARGS(sb, type, gc_type, p, pre_victim, prefree, free), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(int, type) + __field(int, gc_type) + __field(int, alloc_mode) + __field(int, gc_mode) + __field(unsigned int, victim) + __field(unsigned int, ofs_unit) + __field(unsigned int, pre_victim) + __field(unsigned int, prefree) + __field(unsigned int, free) + ), + + TP_fast_assign( + __entry->dev = sb->s_dev; + __entry->type = type; + __entry->gc_type = gc_type; + __entry->alloc_mode = p->alloc_mode; + __entry->gc_mode = p->gc_mode; + __entry->victim = p->min_segno; + __entry->ofs_unit = p->ofs_unit; + __entry->pre_victim = pre_victim; + __entry->prefree = prefree; + __entry->free = free; + ), + + TP_printk("dev = (%d,%d), type = %s, policy = (%s, %s, %s), victim = %u " + "ofs_unit = %u, pre_victim_secno = %d, prefree = %u, free = %u", + show_dev(__entry), + show_data_type(__entry->type), + show_gc_type(__entry->gc_type), + show_alloc_mode(__entry->alloc_mode), + show_victim_policy(__entry->gc_mode), + __entry->victim, + __entry->ofs_unit, + (int)__entry->pre_victim, + __entry->prefree, + __entry->free) +); + +TRACE_EVENT(f2fs_fallocate, + + TP_PROTO(struct inode *inode, int mode, + loff_t offset, loff_t len, int ret), + + TP_ARGS(inode, mode, offset, len, ret), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(int, mode) + __field(loff_t, offset) + __field(loff_t, len) + __field(loff_t, size) + __field(blkcnt_t, blocks) + __field(int, ret) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->mode = mode; + __entry->offset = offset; + __entry->len = len; + __entry->size = inode->i_size; + __entry->blocks = inode->i_blocks; + __entry->ret = ret; + ), + + TP_printk("dev = (%d,%d), ino = %lu, mode = %x, offset = %lld, " + "len = %lld, i_size = %lld, i_blocks = %llu, ret = %d", + show_dev_ino(__entry), + __entry->mode, + (unsigned long long)__entry->offset, + (unsigned long long)__entry->len, + (unsigned long long)__entry->size, + (unsigned long long)__entry->blocks, + __entry->ret) +); + +TRACE_EVENT(f2fs_reserve_new_block, + + TP_PROTO(struct inode *inode, nid_t nid, unsigned int ofs_in_node), + + TP_ARGS(inode, nid, ofs_in_node), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(nid_t, nid) + __field(unsigned int, ofs_in_node) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->nid = nid; + __entry->ofs_in_node = ofs_in_node; + ), + + TP_printk("dev = (%d,%d), nid = %u, ofs_in_node = %u", + show_dev(__entry), + (unsigned int)__entry->nid, + __entry->ofs_in_node) +); + +DECLARE_EVENT_CLASS(f2fs__submit_bio, + + TP_PROTO(struct super_block *sb, int rw, int type, struct bio *bio), + + TP_ARGS(sb, rw, type, bio), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(int, rw) + __field(int, type) + __field(sector_t, sector) + __field(unsigned int, size) + ), + + TP_fast_assign( + __entry->dev = sb->s_dev; + __entry->rw = rw; + __entry->type = type; + __entry->sector = bio->bi_sector; + __entry->size = bio->bi_size; + ), + + TP_printk("dev = (%d,%d), %s%s, %s, sector = %lld, size = %u", + show_dev(__entry), + show_bio_type(__entry->rw), + show_block_type(__entry->type), + (unsigned long long)__entry->sector, + __entry->size) +); + +DEFINE_EVENT_CONDITION(f2fs__submit_bio, f2fs_submit_write_bio, + + TP_PROTO(struct super_block *sb, int rw, int type, struct bio *bio), + + TP_ARGS(sb, rw, type, bio), + + TP_CONDITION(bio) +); + +DEFINE_EVENT_CONDITION(f2fs__submit_bio, f2fs_submit_read_bio, + + TP_PROTO(struct super_block *sb, int rw, int type, struct bio *bio), + + TP_ARGS(sb, rw, type, bio), + + TP_CONDITION(bio) +); + +TRACE_EVENT(f2fs_write_begin, + + TP_PROTO(struct inode *inode, loff_t pos, unsigned int len, + unsigned int flags), + + TP_ARGS(inode, pos, len, flags), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(loff_t, pos) + __field(unsigned int, len) + __field(unsigned int, flags) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->pos = pos; + __entry->len = len; + __entry->flags = flags; + ), + + TP_printk("dev = (%d,%d), ino = %lu, pos = %llu, len = %u, flags = %u", + show_dev_ino(__entry), + (unsigned long long)__entry->pos, + __entry->len, + __entry->flags) +); + +TRACE_EVENT(f2fs_write_end, + + TP_PROTO(struct inode *inode, loff_t pos, unsigned int len, + unsigned int copied), + + TP_ARGS(inode, pos, len, copied), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(loff_t, pos) + __field(unsigned int, len) + __field(unsigned int, copied) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->pos = pos; + __entry->len = len; + __entry->copied = copied; + ), + + TP_printk("dev = (%d,%d), ino = %lu, pos = %llu, len = %u, copied = %u", + show_dev_ino(__entry), + (unsigned long long)__entry->pos, + __entry->len, + __entry->copied) +); + +DECLARE_EVENT_CLASS(f2fs__page, + + TP_PROTO(struct page *page, int type), + + TP_ARGS(page, type), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(int, type) + __field(int, dir) + __field(pgoff_t, index) + __field(int, dirty) + __field(int, uptodate) + ), + + TP_fast_assign( + __entry->dev = page->mapping->host->i_sb->s_dev; + __entry->ino = page->mapping->host->i_ino; + __entry->type = type; + __entry->dir = S_ISDIR(page->mapping->host->i_mode); + __entry->index = page->index; + __entry->dirty = PageDirty(page); + __entry->uptodate = PageUptodate(page); + ), + + TP_printk("dev = (%d,%d), ino = %lu, %s, %s, index = %lu, " + "dirty = %d, uptodate = %d", + show_dev_ino(__entry), + show_block_type(__entry->type), + show_file_type(__entry->dir), + (unsigned long)__entry->index, + __entry->dirty, + __entry->uptodate) +); + +DEFINE_EVENT(f2fs__page, f2fs_writepage, + + TP_PROTO(struct page *page, int type), + + TP_ARGS(page, type) +); + +DEFINE_EVENT(f2fs__page, f2fs_readpage, + + TP_PROTO(struct page *page, int type), + + TP_ARGS(page, type) +); + +DEFINE_EVENT(f2fs__page, f2fs_set_page_dirty, + + TP_PROTO(struct page *page, int type), + + TP_ARGS(page, type) +); + +DEFINE_EVENT(f2fs__page, f2fs_vm_page_mkwrite, + + TP_PROTO(struct page *page, int type), + + TP_ARGS(page, type) +); + +TRACE_EVENT(f2fs_writepages, + + TP_PROTO(struct inode *inode, struct writeback_control *wbc, int type), + + TP_ARGS(inode, wbc, type), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(int, type) + __field(int, dir) + __field(long, nr_to_write) + __field(long, pages_skipped) + __field(loff_t, range_start) + __field(loff_t, range_end) + __field(pgoff_t, writeback_index) + __field(int, sync_mode) + __field(char, for_kupdate) + __field(char, for_background) + __field(char, tagged_writepages) + __field(char, for_reclaim) + __field(char, range_cyclic) + __field(char, for_sync) + ), + + TP_fast_assign( + __entry->dev = inode->i_sb->s_dev; + __entry->ino = inode->i_ino; + __entry->type = type; + __entry->dir = S_ISDIR(inode->i_mode); + __entry->nr_to_write = wbc->nr_to_write; + __entry->pages_skipped = wbc->pages_skipped; + __entry->range_start = wbc->range_start; + __entry->range_end = wbc->range_end; + __entry->writeback_index = inode->i_mapping->writeback_index; + __entry->sync_mode = wbc->sync_mode; + __entry->for_kupdate = wbc->for_kupdate; + __entry->for_background = wbc->for_background; + __entry->tagged_writepages = wbc->tagged_writepages; + __entry->for_reclaim = wbc->for_reclaim; + __entry->range_cyclic = wbc->range_cyclic; + __entry->for_sync = wbc->for_sync; + ), + + TP_printk("dev = (%d,%d), ino = %lu, %s, %s, nr_to_write %ld, " + "skipped %ld, start %lld, end %lld, wb_idx %lu, sync_mode %d, " + "kupdate %u background %u tagged %u reclaim %u cyclic %u sync %u", + show_dev_ino(__entry), + show_block_type(__entry->type), + show_file_type(__entry->dir), + __entry->nr_to_write, + __entry->pages_skipped, + __entry->range_start, + __entry->range_end, + (unsigned long)__entry->writeback_index, + __entry->sync_mode, + __entry->for_kupdate, + __entry->for_background, + __entry->tagged_writepages, + __entry->for_reclaim, + __entry->range_cyclic, + __entry->for_sync) +); + +TRACE_EVENT(f2fs_submit_page_mbio, + + TP_PROTO(struct page *page, int rw, int type, block_t blk_addr), + + TP_ARGS(page, rw, type, blk_addr), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(ino_t, ino) + __field(int, rw) + __field(int, type) + __field(pgoff_t, index) + __field(block_t, block) + ), + + TP_fast_assign( + __entry->dev = page->mapping->host->i_sb->s_dev; + __entry->ino = page->mapping->host->i_ino; + __entry->rw = rw; + __entry->type = type; + __entry->index = page->index; + __entry->block = blk_addr; + ), + + TP_printk("dev = (%d,%d), ino = %lu, %s%s, %s, index = %lu, blkaddr = 0x%llx", + show_dev_ino(__entry), + show_bio_type(__entry->rw), + show_block_type(__entry->type), + (unsigned long)__entry->index, + (unsigned long long)__entry->block) +); + +TRACE_EVENT(f2fs_write_checkpoint, + + TP_PROTO(struct super_block *sb, bool is_umount, char *msg), + + TP_ARGS(sb, is_umount, msg), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(bool, is_umount) + __field(char *, msg) + ), + + TP_fast_assign( + __entry->dev = sb->s_dev; + __entry->is_umount = is_umount; + __entry->msg = msg; + ), + + TP_printk("dev = (%d,%d), checkpoint for %s, state = %s", + show_dev(__entry), + __entry->is_umount ? "clean umount" : "consistency", + __entry->msg) +); + +TRACE_EVENT(f2fs_issue_discard, + + TP_PROTO(struct super_block *sb, block_t blkstart, block_t blklen), + + TP_ARGS(sb, blkstart, blklen), + + TP_STRUCT__entry( + __field(dev_t, dev) + __field(block_t, blkstart) + __field(block_t, blklen) + ), + + TP_fast_assign( + __entry->dev = sb->s_dev; + __entry->blkstart = blkstart; + __entry->blklen = blklen; + ), + + TP_printk("dev = (%d,%d), blkstart = 0x%llx, blklen = 0x%llx", + show_dev(__entry), + (unsigned long long)__entry->blkstart, + (unsigned long long)__entry->blklen) +); +#endif /* _TRACE_F2FS_H */ + + /* This part must be outside protection */ +#include diff --git a/include/trace/events/vmscan.h b/include/trace/events/vmscan.h index f64560e204b..572195459d5 100644 --- a/include/trace/events/vmscan.h +++ b/include/trace/events/vmscan.h @@ -395,88 +395,6 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive, show_reclaim_flags(__entry->reclaim_flags)) ); -TRACE_EVENT(replace_swap_token, - TP_PROTO(struct mm_struct *old_mm, - struct mm_struct *new_mm), - - TP_ARGS(old_mm, new_mm), - - TP_STRUCT__entry( - __field(struct mm_struct*, old_mm) - __field(unsigned int, old_prio) - __field(struct mm_struct*, new_mm) - __field(unsigned int, new_prio) - ), - - TP_fast_assign( - __entry->old_mm = old_mm; - __entry->old_prio = old_mm ? old_mm->token_priority : 0; - __entry->new_mm = new_mm; - __entry->new_prio = new_mm->token_priority; - ), - - TP_printk("old_token_mm=%p old_prio=%u new_token_mm=%p new_prio=%u", - __entry->old_mm, __entry->old_prio, - __entry->new_mm, __entry->new_prio) -); - -DECLARE_EVENT_CLASS(put_swap_token_template, - TP_PROTO(struct mm_struct *swap_token_mm), - - TP_ARGS(swap_token_mm), - - TP_STRUCT__entry( - __field(struct mm_struct*, swap_token_mm) - ), - - TP_fast_assign( - __entry->swap_token_mm = swap_token_mm; - ), - - TP_printk("token_mm=%p", __entry->swap_token_mm) -); - -DEFINE_EVENT(put_swap_token_template, put_swap_token, - TP_PROTO(struct mm_struct *swap_token_mm), - TP_ARGS(swap_token_mm) -); - -DEFINE_EVENT_CONDITION(put_swap_token_template, disable_swap_token, - TP_PROTO(struct mm_struct *swap_token_mm), - TP_ARGS(swap_token_mm), - TP_CONDITION(swap_token_mm != NULL) -); - -TRACE_EVENT_CONDITION(update_swap_token_priority, - TP_PROTO(struct mm_struct *mm, - unsigned int old_prio, - struct mm_struct *swap_token_mm), - - TP_ARGS(mm, old_prio, swap_token_mm), - - TP_CONDITION(mm->token_priority != old_prio), - - TP_STRUCT__entry( - __field(struct mm_struct*, mm) - __field(unsigned int, old_prio) - __field(unsigned int, new_prio) - __field(struct mm_struct*, swap_token_mm) - __field(unsigned int, swap_token_prio) - ), - - TP_fast_assign( - __entry->mm = mm; - __entry->old_prio = old_prio; - __entry->new_prio = mm->token_priority; - __entry->swap_token_mm = swap_token_mm; - __entry->swap_token_prio = swap_token_mm ? swap_token_mm->token_priority : 0; - ), - - TP_printk("mm=%p old_prio=%u new_prio=%u swap_token_mm=%p token_prio=%u", - __entry->mm, __entry->old_prio, __entry->new_prio, - __entry->swap_token_mm, __entry->swap_token_prio) -); - #endif /* _TRACE_VMSCAN_H */ /* This part must be outside protection */ diff --git a/init/Kconfig b/init/Kconfig index e4b67a1dddf..ff42e365970 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -130,10 +130,13 @@ config HAVE_KERNEL_XZ config HAVE_KERNEL_LZO bool +config HAVE_KERNEL_LZ4 + bool + choice prompt "Kernel compression mode" default KERNEL_GZIP - depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO + depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO || HAVE_KERNEL_LZ4 help The linux kernel is a kind of self-extracting executable. Several compression algorithms are available, which differ @@ -201,6 +204,18 @@ config KERNEL_LZO size is about 10% bigger than gzip; however its speed (both compression and decompression) is the fastest. +config KERNEL_LZ4 + bool "LZ4" + depends on HAVE_KERNEL_LZ4 + help + LZ4 is an LZ77-type compressor with a fixed, byte-oriented encoding. + A preliminary version of LZ4 de/compression tool is available at + . + + Its compression ratio is worse than LZO. The size of the kernel + is about 8% bigger than LZO. But the decompression speed is + faster than LZO. + endchoice config DEFAULT_HOSTNAME @@ -939,13 +954,20 @@ source "usr/Kconfig" endif +choice + prompt "Optimization level" + default CC_OPTIMIZE_DEFAULT + config CC_OPTIMIZE_FOR_SIZE - bool "Optimize for size" - help - Enabling this option will pass "-Os" instead of "-O2" to gcc - resulting in a smaller kernel. + bool "Use -Os" - If unsure, say Y. +config CC_OPTIMIZE_DEFAULT + bool "Use -O2" + +config CC_OPTIMIZE_ALOT + bool "Use -O3" + +endchoice config SYSCTL bool diff --git a/ipc/shm.c b/ipc/shm.c index 406c5b20819..cb4c16cf374 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -1087,7 +1087,7 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr) SYSCALL_DEFINE3(shmat, int, shmid, char __user *, shmaddr, int, shmflg) { - unsigned long ret; + unsigned long ret = 0; long err; err = do_shmat(shmid, shmaddr, shmflg, &ret); diff --git a/kernel/auditsc.c b/kernel/auditsc.c index af1de0f34ea..3efa83ad6f4 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -852,7 +852,7 @@ static int audit_filter_rules(struct task_struct *tsk, static enum audit_state audit_filter_task(struct task_struct *tsk, char **key) { struct audit_entry *e; - enum audit_state state; + enum audit_state state = 0; rcu_read_lock(); list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) { @@ -913,7 +913,7 @@ static int audit_filter_inode_name(struct task_struct *tsk, int h = audit_hash_ino((u32)n->ino); struct list_head *list = &audit_inode_hash[h]; struct audit_entry *e; - enum audit_state state; + enum audit_state state = 0; word = AUDIT_WORD(ctx->major); bit = AUDIT_BIT(ctx->major); diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 2f0d7542c0d..5303ec8591b 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -2880,6 +2880,7 @@ int cgroup_scan_tasks(struct cgroup_scanner *scan) struct ptr_heap tmp_heap; struct ptr_heap *heap; struct timespec latest_time = { 0, 0 }; + it.task = NULL; if (scan->heap) { /* The caller supplied our heap and pre-allocated its memory */ @@ -3216,6 +3217,7 @@ int cgroupstats_build(struct cgroupstats *stats, struct dentry *dentry) struct cgroup *cgrp; struct cgroup_iter it; struct task_struct *tsk; + it.task = NULL; /* * Validate dentry by checking the superblock operations, diff --git a/kernel/exit.c b/kernel/exit.c index 6096e809bf9..bc7d69084fd 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -1030,7 +1030,7 @@ void do_exit(long code) /* * Make sure we are holding no locks: */ - debug_check_no_locks_held(tsk); + debug_check_no_locks_held(); /* * We can do this unlocked here. The futex code uses this flag * just to verify whether the pi state cleanup has been done diff --git a/kernel/fork.c b/kernel/fork.c index 0de735c9b6b..995a2727317 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -377,7 +377,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) goto fail_nomem; charge = len; } - tmp = kmem_cache_alloc(vm_area_cachep, GFP_KERNEL); + tmp = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); if (!tmp) goto fail_nomem; *tmp = *mpnt; @@ -429,7 +429,7 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) __vma_link_rb(mm, tmp, rb_link, rb_parent); rb_link = &tmp->vm_rb.rb_right; rb_parent = &tmp->vm_rb; - + uksm_vma_add_new(tmp); mm->map_count++; retval = copy_page_range(mm, oldmm, mpnt); @@ -597,7 +597,6 @@ int mmput(struct mm_struct *mm) list_del(&mm->mmlist); spin_unlock(&mmlist_lock); } - put_swap_token(mm); if (mm->binfmt) module_put(mm->binfmt->module); mmdrop(mm); @@ -815,10 +814,6 @@ struct mm_struct *dup_mm(struct task_struct *tsk) memcpy(mm, oldmm, sizeof(*mm)); mm_init_cpumask(mm); - /* Initializing for Swap token stuff */ - mm->token_priority = 0; - mm->last_interval = 0; - #ifdef CONFIG_TRANSPARENT_HUGEPAGE mm->pmd_huge_pte = NULL; #endif @@ -896,10 +891,6 @@ static int copy_mm(unsigned long clone_flags, struct task_struct *tsk) goto fail_nomem; good_mm: - /* Initializing for Swap token stuff */ - mm->token_priority = 0; - mm->last_interval = 0; - tsk->mm = mm; tsk->active_mm = mm; return 0; diff --git a/kernel/freezer.c b/kernel/freezer.c index 11f82a4d4ea..d1db42318b3 100644 --- a/kernel/freezer.c +++ b/kernel/freezer.c @@ -110,6 +110,18 @@ bool freeze_task(struct task_struct *p) { unsigned long flags; + /* + * This check can race with freezer_do_not_count, but worst case that + * will result in an extra wakeup being sent to the task. It does not + * race with freezer_count(), the barriers in freezer_count() and + * freezer_should_skip() ensure that either freezer_count() sees + * freezing == true in try_to_freeze() and freezes, or + * freezer_should_skip() sees !PF_FREEZE_SKIP and freezes the task + * normally. + */ + if (freezer_should_skip(p)) + return false; + spin_lock_irqsave(&freezer_lock, flags); if (!freezing(p) || frozen(p)) { spin_unlock_irqrestore(&freezer_lock, flags); diff --git a/kernel/futex.c b/kernel/futex.c index e2b0fb9a0b3..04fc7bb6f0e 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -60,6 +60,7 @@ #include #include #include +#include #include @@ -587,9 +588,59 @@ void exit_pi_state_list(struct task_struct *curr) raw_spin_unlock_irq(&curr->pi_lock); } +/* + * We need to check the following states: + * + * Waiter | pi_state | pi->owner | uTID | uODIED | ? + * + * [1] NULL | --- | --- | 0 | 0/1 | Valid + * [2] NULL | --- | --- | >0 | 0/1 | Valid + * + * [3] Found | NULL | -- | Any | 0/1 | Invalid + * + * [4] Found | Found | NULL | 0 | 1 | Valid + * [5] Found | Found | NULL | >0 | 1 | Invalid + * + * [6] Found | Found | task | 0 | 1 | Valid + * + * [7] Found | Found | NULL | Any | 0 | Invalid + * + * [8] Found | Found | task | ==taskTID | 0/1 | Valid + * [9] Found | Found | task | 0 | 0 | Invalid + * [10] Found | Found | task | !=taskTID | 0/1 | Invalid + * + * [1] Indicates that the kernel can acquire the futex atomically. We + * came came here due to a stale FUTEX_WAITERS/FUTEX_OWNER_DIED bit. + * + * [2] Valid, if TID does not belong to a kernel thread. If no matching + * thread is found then it indicates that the owner TID has died. + * + * [3] Invalid. The waiter is queued on a non PI futex + * + * [4] Valid state after exit_robust_list(), which sets the user space + * value to FUTEX_WAITERS | FUTEX_OWNER_DIED. + * + * [5] The user space value got manipulated between exit_robust_list() + * and exit_pi_state_list() + * + * [6] Valid state after exit_pi_state_list() which sets the new owner in + * the pi_state but cannot access the user space value. + * + * [7] pi_state->owner can only be NULL when the OWNER_DIED bit is set. + * + * [8] Owner and user space value match + * + * [9] There is no transient state which sets the user space TID to 0 + * except exit_robust_list(), but this is indicated by the + * FUTEX_OWNER_DIED bit. See [4] + * + * [10] There is no transient state which leaves owner and user space + * TID out of sync. + */ static int lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, - union futex_key *key, struct futex_pi_state **ps) + union futex_key *key, struct futex_pi_state **ps, + struct task_struct *task) { struct futex_pi_state *pi_state = NULL; struct futex_q *this, *next; @@ -602,12 +653,13 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, plist_for_each_entry_safe(this, next, head, list) { if (match_futex(&this->key, key)) { /* - * Another waiter already exists - bump up - * the refcount and return its pi_state: + * Sanity check the waiter before increasing + * the refcount and attaching to it. */ pi_state = this->pi_state; /* - * Userspace might have messed up non-PI and PI futexes + * Userspace might have messed up non-PI and + * PI futexes [3] */ if (unlikely(!pi_state)) return -EINVAL; @@ -615,34 +667,80 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, WARN_ON(!atomic_read(&pi_state->refcount)); /* - * When pi_state->owner is NULL then the owner died - * and another waiter is on the fly. pi_state->owner - * is fixed up by the task which acquires - * pi_state->rt_mutex. - * - * We do not check for pid == 0 which can happen when - * the owner died and robust_list_exit() cleared the - * TID. + * Handle the owner died case: */ - if (pid && pi_state->owner) { + if (uval & FUTEX_OWNER_DIED) { /* - * Bail out if user space manipulated the - * futex value. + * exit_pi_state_list sets owner to NULL and + * wakes the topmost waiter. The task which + * acquires the pi_state->rt_mutex will fixup + * owner. */ - if (pid != task_pid_vnr(pi_state->owner)) + if (!pi_state->owner) { + /* + * No pi state owner, but the user + * space TID is not 0. Inconsistent + * state. [5] + */ + if (pid) + return -EINVAL; + /* + * Take a ref on the state and + * return. [4] + */ + goto out_state; + } + + /* + * If TID is 0, then either the dying owner + * has not yet executed exit_pi_state_list() + * or some waiter acquired the rtmutex in the + * pi state, but did not yet fixup the TID in + * user space. + * + * Take a ref on the state and return. [6] + */ + if (!pid) + goto out_state; + } else { + /* + * If the owner died bit is not set, + * then the pi_state must have an + * owner. [7] + */ + if (!pi_state->owner) return -EINVAL; } + /* + * Bail out if user space manipulated the + * futex value. If pi state exists then the + * owner TID must be the same as the user + * space TID. [9/10] + */ + if (pid != task_pid_vnr(pi_state->owner)) + return -EINVAL; + + /* + * Protect against a corrupted uval. If uval + * is 0x80000000 then pid is 0 and the waiter + * bit is set. So the deadlock check in the + * calling code has failed and we did not fall + * into the check above due to !pid. + */ + if (task && pi_state->owner == task) + return -EDEADLK; + + out_state: atomic_inc(&pi_state->refcount); *ps = pi_state; - return 0; } } /* * We are the first waiter - try to look up the real owner and attach - * the new pi_state to it, but bail out when TID = 0 + * the new pi_state to it, but bail out when TID = 0 [1] */ if (!pid) return -ESRCH; @@ -650,6 +748,11 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, if (!p) return -ESRCH; + if (!p->mm) { + put_task_struct(p); + return -EPERM; + } + /* * We need to look at the task state flags to figure out, * whether the task is exiting. To protect against the do_exit @@ -670,6 +773,9 @@ lookup_pi_state(u32 uval, struct futex_hash_bucket *hb, return ret; } + /* + * No existing pi state. First waiter. [2] + */ pi_state = alloc_pi_state(); /* @@ -784,7 +890,7 @@ static int futex_lock_pi_atomic(u32 __user *uaddr, struct futex_hash_bucket *hb, * We dont have the lock. Look up the PI state (or create it if * we are the first waiter): */ - ret = lookup_pi_state(uval, hb, key, ps); + ret = lookup_pi_state(uval, hb, key, ps, task); if (unlikely(ret)) { switch (ret) { @@ -868,6 +974,7 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) struct task_struct *new_owner; struct futex_pi_state *pi_state = this->pi_state; u32 uninitialized_var(curval), newval; + int ret = 0; if (!pi_state) return -EINVAL; @@ -891,23 +998,19 @@ static int wake_futex_pi(u32 __user *uaddr, u32 uval, struct futex_q *this) new_owner = this->task; /* - * We pass it to the next owner. (The WAITERS bit is always - * kept enabled while there is PI state around. We must also - * preserve the owner died bit.) + * We pass it to the next owner. The WAITERS bit is always + * kept enabled while there is PI state around. We cleanup the + * owner died bit, because we are the owner. */ - if (!(uval & FUTEX_OWNER_DIED)) { - int ret = 0; - - newval = FUTEX_WAITERS | task_pid_vnr(new_owner); + newval = FUTEX_WAITERS | task_pid_vnr(new_owner); - if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) - ret = -EFAULT; - else if (curval != uval) - ret = -EINVAL; - if (ret) { - raw_spin_unlock(&pi_state->pi_mutex.wait_lock); - return ret; - } + if (cmpxchg_futex_value_locked(&curval, uaddr, uval, newval)) + ret = -EFAULT; + else if (curval != uval) + ret = -EINVAL; + if (ret) { + raw_spin_unlock(&pi_state->pi_mutex.wait_lock); + return ret; } raw_spin_lock_irq(&pi_state->owner->pi_lock); @@ -1175,9 +1278,15 @@ void requeue_pi_wake_futex(struct futex_q *q, union futex_key *key, * then direct futex_lock_pi_atomic() to force setting the FUTEX_WAITERS bit. * hb1 and hb2 must be held by the caller. * +<<<<<<< HEAD * Returns: * 0 - failed to acquire the lock atomicly * 1 - acquired the lock +======= + * Return: + * 0 - failed to acquire the lock atomically; + * >0 - acquired the lock, return value is vpid of the top_waiter +>>>>>>> 866293e... futex: Add another early deadlock detection check * <0 - error */ static int futex_proxy_trylock_atomic(u32 __user *pifutex, @@ -1188,7 +1297,7 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex, { struct futex_q *top_waiter = NULL; u32 curval; - int ret; + int ret, vpid; if (get_futex_value_locked(&curval, pifutex)) return -EFAULT; @@ -1216,11 +1325,13 @@ static int futex_proxy_trylock_atomic(u32 __user *pifutex, * the contended case or if set_waiters is 1. The pi_state is returned * in ps in contended cases. */ + vpid = task_pid_vnr(top_waiter->task); ret = futex_lock_pi_atomic(pifutex, hb2, key2, ps, top_waiter->task, set_waiters); - if (ret == 1) + if (ret == 1) { requeue_pi_wake_futex(top_waiter, key2, hb2); - + return vpid; + } return ret; } @@ -1252,9 +1363,15 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, struct futex_hash_bucket *hb1, *hb2; struct plist_head *head1; struct futex_q *this, *next; - u32 curval2; if (requeue_pi) { + /* + * Requeue PI only works on two distinct uaddrs. This + * check is only valid for private futexes. See below. + */ + if (uaddr1 == uaddr2) + return -EINVAL; + /* * requeue_pi requires a pi_state, try to allocate it now * without any locks in case it fails. @@ -1293,6 +1410,15 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, if (unlikely(ret != 0)) goto out_put_key1; + /* + * The check above which compares uaddrs is not sufficient for + * shared futexes. We need to compare the keys: + */ + if (requeue_pi && match_futex(&key1, &key2)) { + ret = -EINVAL; + goto out_put_keys; + } + hb1 = hash_futex(&key1); hb2 = hash_futex(&key2); @@ -1338,16 +1464,25 @@ static int futex_requeue(u32 __user *uaddr1, unsigned int flags, * At this point the top_waiter has either taken uaddr2 or is * waiting on it. If the former, then the pi_state will not * exist yet, look it up one more time to ensure we have a - * reference to it. + * reference to it. If the lock was taken, ret contains the + * vpid of the top waiter task. */ - if (ret == 1) { + if (ret > 0) { WARN_ON(pi_state); drop_count++; task_count++; - ret = get_futex_value_locked(&curval2, uaddr2); - if (!ret) - ret = lookup_pi_state(curval2, hb2, &key2, - &pi_state); + /* + * If we acquired the lock, then the user + * space value of uaddr2 should be vpid. It + * cannot be changed by the top waiter as it + * is blocked on hb2 lock if it tries to do + * so. If something fiddled with it behind our + * back the pi state lookup might unearth + * it. So we rather use the known value than + * rereading and handing potential crap to + * lookup_pi_state. + */ + ret = lookup_pi_state(ret, hb2, &key2, &pi_state, NULL); } switch (ret) { @@ -1786,7 +1921,7 @@ static void futex_wait_queue_me(struct futex_hash_bucket *hb, struct futex_q *q, * is no timeout, or if it has yet to expire. */ if (!timeout || timeout->task) - schedule(); + freezable_schedule(); } __set_current_state(TASK_RUNNING); } @@ -2113,9 +2248,10 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags) /* * To avoid races, try to do the TID -> 0 atomic transition * again. If it succeeds then we can return without waking - * anyone else up: + * anyone else up. We only try this if neither the waiters nor + * the owner died bit are set. */ - if (!(uval & FUTEX_OWNER_DIED) && + if (!(uval & ~FUTEX_TID_MASK) && cmpxchg_futex_value_locked(&uval, uaddr, vpid, 0)) goto pi_faulted; /* @@ -2147,11 +2283,9 @@ static int futex_unlock_pi(u32 __user *uaddr, unsigned int flags) /* * No waiters - kernel unlocks the futex: */ - if (!(uval & FUTEX_OWNER_DIED)) { - ret = unlock_futex_pi(uaddr, uval); - if (ret == -EFAULT) - goto pi_faulted; - } + ret = unlock_futex_pi(uaddr, uval); + if (ret == -EFAULT) + goto pi_faulted; out_unlock: spin_unlock(&hb->lock); @@ -2308,6 +2442,15 @@ static int futex_wait_requeue_pi(u32 __user *uaddr, unsigned int flags, if (ret) goto out_key2; + /* + * The check above which compares uaddrs is not sufficient for + * shared futexes. We need to compare the keys: + */ + if (match_futex(&q.key, &key2)) { + ret = -EINVAL; + goto out_put_keys; + } + /* Queue the futex_q, drop the hb lock, wait for wakeup. */ futex_wait_queue_me(hb, &q, to); diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index d1e73a4eed9..f08e1b5e184 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -45,6 +45,7 @@ #include #include #include +#include #include @@ -1502,7 +1503,7 @@ static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mod t->task = NULL; if (likely(t->task)) - schedule(); + freezable_schedule(); hrtimer_cancel(&t->timer); mode = HRTIMER_MODE_ABS; diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index bdb18032555..131ca176b49 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c @@ -133,7 +133,7 @@ irqreturn_t handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) { irqreturn_t retval = IRQ_NONE; - unsigned int random = 0, irq = desc->irq_data.irq; + unsigned int flags = 0, irq = desc->irq_data.irq; do { irqreturn_t res; @@ -161,7 +161,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) /* Fall through to add to randomness */ case IRQ_HANDLED: - random |= action->flags; + flags |= action->flags; break; default: @@ -172,8 +172,7 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) action = action->next; } while (action); - if (random & IRQF_SAMPLE_RANDOM) - add_interrupt_randomness(irq); + add_interrupt_randomness(irq, flags); if (!noirqdebug) note_interrupt(irq, desc, retval); diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 165d5dc53fd..8550d4b3437 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c @@ -916,22 +916,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) return -ENOSYS; if (!try_module_get(desc->owner)) return -ENODEV; - /* - * Some drivers like serial.c use request_irq() heavily, - * so we have to be careful not to interfere with a - * running system. - */ - if (new->flags & IRQF_SAMPLE_RANDOM) { - /* - * This function might sleep, we want to call it first, - * outside of the atomic block. - * Yes, this might clear the entropy pool if the wrong - * driver is attempted to be loaded, without actually - * installing a new handler, but is this really a problem, - * only the sysadmin is able to do this. - */ - rand_initialize_irq(irq); - } /* * Check whether the interrupt nests into another interrupt @@ -1372,7 +1356,6 @@ EXPORT_SYMBOL(free_irq); * Flags: * * IRQF_SHARED Interrupt is shared - * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy * IRQF_TRIGGER_* Specify active edge(s) or level * */ diff --git a/kernel/kexec.c b/kernel/kexec.c index 4e2e472f6ae..aef789344c2 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c @@ -1004,6 +1004,10 @@ SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, if (flags & KEXEC_PRESERVE_CONTEXT) image->preserve_context = 1; +#ifdef CONFIG_KEXEC_HARDBOOT + if (flags & KEXEC_HARDBOOT) + image->hardboot = 1; +#endif result = machine_kexec_prepare(image); if (result) goto out; diff --git a/kernel/lockdep.c b/kernel/lockdep.c index ea9ee4518c3..fdcf7ec6c88 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c @@ -4044,7 +4044,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) } EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); -static void print_held_locks_bug(struct task_struct *curr) +static void print_held_locks_bug(void) { if (!debug_locks_off()) return; @@ -4053,22 +4053,21 @@ static void print_held_locks_bug(struct task_struct *curr) printk("\n"); printk("=====================================\n"); - printk("[ BUG: lock held at task exit time! ]\n"); + printk("[ BUG: %s/%d still has locks held! ]\n", + current->comm, task_pid_nr(current)); print_kernel_ident(); printk("-------------------------------------\n"); - printk("%s/%d is exiting with locks still held!\n", - curr->comm, task_pid_nr(curr)); - lockdep_print_held_locks(curr); - + lockdep_print_held_locks(current); printk("\nstack backtrace:\n"); dump_stack(); } -void debug_check_no_locks_held(struct task_struct *task) +void debug_check_no_locks_held(void) { - if (unlikely(task->lockdep_depth > 0)) - print_held_locks_bug(task); + if (unlikely(current->lockdep_depth > 0)) + print_held_locks_bug(); } +EXPORT_SYMBOL_GPL(debug_check_no_locks_held); void debug_show_all_locks(void) { diff --git a/kernel/panic.c b/kernel/panic.c index 4ffbce815c5..2bd000132e0 100644 --- a/kernel/panic.c +++ b/kernel/panic.c @@ -24,6 +24,7 @@ #include #include #include +#include #define PANIC_TIMER_STEP 100 #define PANIC_BLINK_SPD 18 @@ -133,6 +134,10 @@ void panic(const char *fmt, ...) kmsg_dump(KMSG_DUMP_PANIC); + /* print last_kmsg even after console suspend */ + if (is_console_suspended()) + resume_console(); + /* * Note smp_send_stop is the usual smp shutdown function, which * unfortunately means it may not be hardened to work in a panic diff --git a/kernel/power/process.c b/kernel/power/process.c index 00259a85c85..fa899042eec 100644 --- a/kernel/power/process.c +++ b/kernel/power/process.c @@ -32,9 +32,10 @@ static int try_to_freeze_tasks(bool user_only) unsigned int todo; bool wq_busy = false; struct timeval start, end; - u64 elapsed_csecs64; - unsigned int elapsed_csecs; + u64 elapsed_msecs64; + unsigned int elapsed_msecs; bool wakeup = false; + int sleep_usecs = USEC_PER_MSEC; do_gettimeofday(&start); @@ -71,10 +72,6 @@ static int try_to_freeze_tasks(bool user_only) todo += wq_busy; } - if (todo && has_wake_lock(WAKE_LOCK_SUSPEND)) { - wakeup = 1; - break; - } if (!todo || time_after(jiffies, end_time)) break; @@ -85,49 +82,39 @@ static int try_to_freeze_tasks(bool user_only) /* * We need to retry, but first give the freezing tasks some - * time to enter the regrigerator. + * time to enter the refrigerator. Start with an initial + * 1 ms sleep followed by exponential backoff until 8 ms. */ - msleep(10); + usleep_range(sleep_usecs / 2, sleep_usecs); + if (sleep_usecs < 8 * USEC_PER_MSEC) + sleep_usecs *= 2; } do_gettimeofday(&end); - elapsed_csecs64 = timeval_to_ns(&end) - timeval_to_ns(&start); - do_div(elapsed_csecs64, NSEC_PER_SEC / 100); - elapsed_csecs = elapsed_csecs64; + elapsed_msecs64 = timeval_to_ns(&end) - timeval_to_ns(&start); + do_div(elapsed_msecs64, NSEC_PER_MSEC); + elapsed_msecs = elapsed_msecs64; if (todo) { - /* This does not unfreeze processes that are already frozen - * (we have slightly ugly calling convention in that respect, - * and caller must call thaw_processes() if something fails), - * but it cleans up leftover PF_FREEZE requests. - */ - if(wakeup) { - printk("\n"); - printk(KERN_ERR "Freezing of %s aborted\n", - user_only ? "user space " : "tasks "); - } - else { - printk("\n"); - printk(KERN_ERR "Freezing of tasks %s after %d.%02d seconds " - "(%d tasks refusing to freeze, wq_busy=%d):\n", - wakeup ? "aborted" : "failed", - elapsed_csecs / 100, elapsed_csecs % 100, - todo - wq_busy, wq_busy); - } + printk("\n"); + printk(KERN_ERR "Freezing of tasks %s after %d.%03d seconds " + "(%d tasks refusing to freeze, wq_busy=%d):\n", + wakeup ? "aborted" : "failed", + elapsed_msecs / 1000, elapsed_msecs % 1000, + todo - wq_busy, wq_busy); if (!wakeup) { read_lock(&tasklist_lock); do_each_thread(g, p) { if (p != current && !freezer_should_skip(p) - && freezing(p) && !frozen(p) && - elapsed_csecs > 100) + && freezing(p) && !frozen(p)) sched_show_task(p); } while_each_thread(g, p); read_unlock(&tasklist_lock); } } else { - printk("(elapsed %d.%02d seconds) ", elapsed_csecs / 100, - elapsed_csecs % 100); + printk("(elapsed %d.%03d seconds) ", elapsed_msecs / 1000, + elapsed_msecs % 1000); } return todo ? -EBUSY : 0; diff --git a/kernel/printk.c b/kernel/printk.c index 8e3af827913..ecb4ce36390 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -1188,6 +1188,12 @@ module_param_named(console_suspend, console_suspend_enabled, MODULE_PARM_DESC(console_suspend, "suspend console during suspend" " and hibernate operations"); +/* check current suspend/resume status of the console */ +int is_console_suspended(void) +{ + return console_suspended; +} + /** * suspend_console - suspend the console subsystem * diff --git a/kernel/sched/Makefile b/kernel/sched/Makefile index 3ede7d92480..4ef7ddeddb8 100644 --- a/kernel/sched/Makefile +++ b/kernel/sched/Makefile @@ -2,15 +2,6 @@ ifdef CONFIG_FUNCTION_TRACER CFLAGS_REMOVE_clock.o = -pg endif -ifneq ($(CONFIG_SCHED_OMIT_FRAME_POINTER),y) -# According to Alan Modra , the -fno-omit-frame-pointer is -# needed for x86 only. Why this used to be enabled for all architectures is beyond -# me. I suspect most platforms don't need this, but until we know that for sure -# I turn this off for IA-64 only. Andreas Schwab says it's also needed on m68k -# to get a correct value for the wait-channel (WCHAN in ps). --davidm -CFLAGS_core.o := $(PROFILING) -fno-omit-frame-pointer -endif - obj-y += core.o clock.o idle_task.o fair.o rt.o stop_task.o sched_avg.o obj-$(CONFIG_SMP) += cpupri.o obj-$(CONFIG_SCHED_AUTOGROUP) += auto_group.o diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 1cee48f07d9..028e8c1d0e5 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -112,6 +112,10 @@ void start_bandwidth_timer(struct hrtimer *period_timer, ktime_t period) DEFINE_MUTEX(sched_domains_mutex); DEFINE_PER_CPU_SHARED_ALIGNED(struct rq, runqueues); +#ifdef CONFIG_INTELLI_PLUG +DEFINE_PER_CPU_SHARED_ALIGNED(struct nr_stats_s, runqueue_stats); +#endif + static void update_rq_clock_task(struct rq *rq, s64 delta); void update_rq_clock(struct rq *rq) @@ -621,7 +625,19 @@ void wake_up_idle_cpu(int cpu) static inline bool got_nohz_idle_kick(void) { int cpu = smp_processor_id(); - return idle_cpu(cpu) && test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)); + + if (!test_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu))) + return false; + + if (idle_cpu(cpu) && !need_resched()) + return true; + + /* + * We can't run Idle Load Balance on this CPU for this time so we + * cancel it and clear NOHZ_BALANCE_KICK + */ + clear_bit(NOHZ_BALANCE_KICK, nohz_flags(cpu)); + return false; } #else /* CONFIG_NO_HZ */ @@ -1517,7 +1533,7 @@ void scheduler_ipi(void) /* * Check if someone kicked us for doing the nohz idle load balance. */ - if (unlikely(got_nohz_idle_kick() && !need_resched())) { + if (unlikely(got_nohz_idle_kick())) { this_rq()->idle_balance = 1; raise_softirq_irqoff(SCHED_SOFTIRQ); } @@ -2177,6 +2193,108 @@ unsigned long this_cpu_load(void) return this->cpu_load[0]; } +#ifdef CONFIG_INTELLI_PLUG +unsigned long avg_nr_running(void) +{ + unsigned long i, sum = 0; + unsigned int seqcnt, ave_nr_running; + + for_each_online_cpu(i) { + struct nr_stats_s *stats = &per_cpu(runqueue_stats, i); + struct rq *q = cpu_rq(i); + + /* + * Update average to avoid reading stalled value if there were + * no run-queue changes for a long time. On the other hand if + * the changes are happening right now, just read current value + * directly. + */ + seqcnt = read_seqcount_begin(&stats->ave_seqcnt); + ave_nr_running = do_avg_nr_running(q); + if (read_seqcount_retry(&stats->ave_seqcnt, seqcnt)) { + read_seqcount_begin(&stats->ave_seqcnt); + ave_nr_running = stats->ave_nr_running; + } + + sum += ave_nr_running; + } + + return sum; +} +EXPORT_SYMBOL(avg_nr_running); + +unsigned long avg_cpu_nr_running(unsigned int cpu) +{ + unsigned int seqcnt, ave_nr_running; + + struct nr_stats_s *stats = &per_cpu(runqueue_stats, cpu); + struct rq *q = cpu_rq(cpu); + + /* + * Update average to avoid reading stalled value if there were + * no run-queue changes for a long time. On the other hand if + * the changes are happening right now, just read current value + * directly. + */ + seqcnt = read_seqcount_begin(&stats->ave_seqcnt); + ave_nr_running = do_avg_nr_running(q); + if (read_seqcount_retry(&stats->ave_seqcnt, seqcnt)) { + read_seqcount_begin(&stats->ave_seqcnt); + ave_nr_running = stats->ave_nr_running; + } + + return ave_nr_running; +} +EXPORT_SYMBOL(avg_cpu_nr_running); +#endif + +/* + * Global load-average calculations + * + * We take a distributed and async approach to calculating the global load-avg + * in order to minimize overhead. + * + * The global load average is an exponentially decaying average of nr_running + + * nr_uninterruptible. + * + * Once every LOAD_FREQ: + * + * nr_active = 0; + * for_each_possible_cpu(cpu) + * nr_active += cpu_of(cpu)->nr_running + cpu_of(cpu)->nr_uninterruptible; + * + * avenrun[n] = avenrun[0] * exp_n + nr_active * (1 - exp_n) + * + * Due to a number of reasons the above turns in the mess below: + * + * - for_each_possible_cpu() is prohibitively expensive on machines with + * serious number of cpus, therefore we need to take a distributed approach + * to calculating nr_active. + * + * \Sum_i x_i(t) = \Sum_i x_i(t) - x_i(t_0) | x_i(t_0) := 0 + * = \Sum_i { \Sum_j=1 x_i(t_j) - x_i(t_j-1) } + * + * So assuming nr_active := 0 when we start out -- true per definition, we + * can simply take per-cpu deltas and fold those into a global accumulate + * to obtain the same result. See calc_load_fold_active(). + * + * Furthermore, in order to avoid synchronizing all per-cpu delta folding + * across the machine, we assume 10 ticks is sufficient time for every + * cpu to have completed this task. + * + * This places an upper-bound on the IRQ-off latency of the machine. Then + * again, being late doesn't loose the delta, just wrecks the sample. + * + * - cpu_rq()->nr_uninterruptible isn't accurately tracked per-cpu because + * this would add another cross-cpu cacheline miss and atomic operation + * to the wakeup path. Instead we increment on whatever cpu the task ran + * when it went into uninterruptible state and decrement on whatever cpu + * did the wakeup. This means that only the sum of nr_uninterruptible over + * all cpus yields the correct result. + * + * This covers the NO_HZ=n code, for extra head-aches, see the comment below. + */ + /* Variables and functions for calc_load */ static atomic_long_t calc_load_tasks; @@ -3560,7 +3678,8 @@ void complete_all(struct completion *x) EXPORT_SYMBOL(complete_all); static inline long __sched -do_wait_for_common(struct completion *x, long timeout, int state, int iowait) +do_wait_for_common(struct completion *x, + long (*action)(long), long timeout, int state) { if (!x->done) { DECLARE_WAITQUEUE(wait, current); @@ -3573,10 +3692,7 @@ do_wait_for_common(struct completion *x, long timeout, int state, int iowait) } __set_current_state(state); spin_unlock_irq(&x->wait.lock); - if (iowait) - timeout = io_schedule_timeout(timeout); - else - timeout = schedule_timeout(timeout); + timeout = action(timeout); spin_lock_irq(&x->wait.lock); } while (!x->done && timeout); __remove_wait_queue(&x->wait, &wait); @@ -3587,17 +3703,30 @@ do_wait_for_common(struct completion *x, long timeout, int state, int iowait) return timeout ?: 1; } -static long __sched -wait_for_common(struct completion *x, long timeout, int state, int iowait) +static inline long __sched +__wait_for_common(struct completion *x, + long (*action)(long), long timeout, int state) { might_sleep(); spin_lock_irq(&x->wait.lock); - timeout = do_wait_for_common(x, timeout, state, iowait); + timeout = do_wait_for_common(x, action, timeout, state); spin_unlock_irq(&x->wait.lock); return timeout; } +static long __sched +wait_for_common(struct completion *x, long timeout, int state) +{ + return __wait_for_common(x, schedule_timeout, timeout, state); +} + +static long __sched +wait_for_common_io(struct completion *x, long timeout, int state) +{ + return __wait_for_common(x, io_schedule_timeout, timeout, state); +} + /** * wait_for_completion: - waits for completion of a task * @x: holds the state of this particular completion @@ -3610,7 +3739,7 @@ wait_for_common(struct completion *x, long timeout, int state, int iowait) */ void __sched wait_for_completion(struct completion *x) { - wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE, 0); + wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(wait_for_completion); @@ -3623,7 +3752,7 @@ EXPORT_SYMBOL(wait_for_completion); */ void __sched wait_for_completion_io(struct completion *x) { - wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE, 1); + wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(wait_for_completion_io); @@ -3643,10 +3772,29 @@ EXPORT_SYMBOL(wait_for_completion_io); unsigned long __sched wait_for_completion_timeout(struct completion *x, unsigned long timeout) { - return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE, 0); + return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE); } EXPORT_SYMBOL(wait_for_completion_timeout); +/** + * wait_for_completion_io_timeout: - waits for completion of a task (w/timeout) + * @x: holds the state of this particular completion + * @timeout: timeout value in jiffies + * + * This waits for either a completion of a specific task to be signaled or for a + * specified timeout to expire. The timeout is in jiffies. It is not + * interruptible. The caller is accounted as waiting for IO. + * + * The return value is 0 if timed out, and positive (at least 1, or number of + * jiffies left till timeout) if completed. + */ +unsigned long __sched +wait_for_completion_io_timeout(struct completion *x, unsigned long timeout) +{ + return wait_for_common_io(x, timeout, TASK_UNINTERRUPTIBLE); +} +EXPORT_SYMBOL(wait_for_completion_io_timeout); + /** * wait_for_completion_interruptible: - waits for completion of a task (w/intr) * @x: holds the state of this particular completion @@ -3659,7 +3807,7 @@ EXPORT_SYMBOL(wait_for_completion_timeout); int __sched wait_for_completion_interruptible(struct completion *x) { long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, - TASK_INTERRUPTIBLE, 0); + TASK_INTERRUPTIBLE); if (t == -ERESTARTSYS) return t; return 0; @@ -3681,7 +3829,7 @@ long __sched wait_for_completion_interruptible_timeout(struct completion *x, unsigned long timeout) { - return wait_for_common(x, timeout, TASK_INTERRUPTIBLE, 0); + return wait_for_common(x, timeout, TASK_INTERRUPTIBLE); } EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); @@ -3696,7 +3844,7 @@ EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); */ int __sched wait_for_completion_killable(struct completion *x) { - long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE, 0); + long t = wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_KILLABLE); if (t == -ERESTARTSYS) return t; return 0; @@ -3719,7 +3867,7 @@ long __sched wait_for_completion_killable_timeout(struct completion *x, unsigned long timeout) { - return wait_for_common(x, timeout, TASK_KILLABLE, 0); + return wait_for_common(x, timeout, TASK_KILLABLE); } EXPORT_SYMBOL(wait_for_completion_killable_timeout); @@ -5866,18 +6014,23 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu) * two cpus are in the same cache domain, see cpus_share_cache(). */ DEFINE_PER_CPU(struct sched_domain *, sd_llc); +DEFINE_PER_CPU(int, sd_llc_size); DEFINE_PER_CPU(int, sd_llc_id); static void update_top_cache_domain(int cpu) { struct sched_domain *sd; int id = cpu; + int size = 1; sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES); - if (sd) + if (sd) { id = cpumask_first(sched_domain_span(sd)); + size = cpumask_weight(sched_domain_span(sd)); + } rcu_assign_pointer(per_cpu(sd_llc, cpu), sd); + per_cpu(sd_llc_size, cpu) = size; per_cpu(sd_llc_id, cpu) = id; } diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c index 09acaa15161..31e4f61a162 100644 --- a/kernel/sched/debug.c +++ b/kernel/sched/debug.c @@ -202,7 +202,7 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) SPLIT_NS(spread0)); SEQ_printf(m, " .%-30s: %d\n", "nr_spread_over", cfs_rq->nr_spread_over); - SEQ_printf(m, " .%-30s: %ld\n", "nr_running", cfs_rq->nr_running); + SEQ_printf(m, " .%-30s: %d\n", "nr_running", cfs_rq->nr_running); SEQ_printf(m, " .%-30s: %ld\n", "load", cfs_rq->load.weight); #ifdef CONFIG_FAIR_GROUP_SCHED #ifdef CONFIG_SMP diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c index fc60d5b3a25..e01a2e4f087 100644 --- a/kernel/sched/fair.c +++ b/kernel/sched/fair.c @@ -2331,6 +2331,23 @@ static unsigned long cpu_avg_load_per_task(int cpu) return 0; } +static void record_wakee(struct task_struct *p) +{ + /* + * Rough decay (wiping) for cost saving, don't worry + * about the boundary, really active task won't care + * about the loss. + */ + if (jiffies > current->wakee_flip_decay_ts + HZ) { + current->wakee_flips = 0; + current->wakee_flip_decay_ts = jiffies; + } + + if (current->last_wakee != p) { + current->last_wakee = p; + current->wakee_flips++; + } +} static void task_waking_fair(struct task_struct *p) { @@ -2351,6 +2368,7 @@ static void task_waking_fair(struct task_struct *p) #endif se->vruntime -= min_vruntime; + record_wakee(p); } #ifdef CONFIG_FAIR_GROUP_SCHED @@ -2469,6 +2487,28 @@ static inline unsigned long effective_load(struct task_group *tg, int cpu, #endif +static int wake_wide(struct task_struct *p) +{ + int factor = this_cpu_read(sd_llc_size); + + /* + * Yeah, it's the switching-frequency, could means many wakee or + * rapidly switch, use factor here will just help to automatically + * adjust the loose-degree, so bigger node will lead to more pull. + */ + if (p->wakee_flips > factor) { + /* + * wakee is somewhat hot, it needs certain amount of cpu + * resource, so if waker is far more hot, prefer to leave + * it alone. + */ + if (current->wakee_flips > (factor * p->wakee_flips)) + return 1; + } + + return 0; +} + static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) { s64 this_load, load; @@ -2478,6 +2518,13 @@ static int wake_affine(struct sched_domain *sd, struct task_struct *p, int sync) unsigned long weight; int balanced; + /* + * If we wake multiple tasks be careful to not bounce + * ourselves around too much. + */ + if (wake_wide(p)) + return 0; + idx = sd->wake_idx; this_cpu = smp_processor_id(); prev_cpu = task_cpu(p); @@ -2634,25 +2681,18 @@ find_idlest_cpu(struct sched_group *group, struct task_struct *p, int this_cpu) */ static int select_idle_sibling(struct task_struct *p, int target) { - int cpu = smp_processor_id(); - int prev_cpu = task_cpu(p); struct sched_domain *sd; struct sched_group *sg; - int i; + int i = task_cpu(p); - /* - * If the task is going to be woken-up on this cpu and if it is - * already idle, then it is the right target. - */ - if (target == cpu && idle_cpu(cpu)) - return cpu; + if (idle_cpu(target)) + return target; /* - * If the task is going to be woken-up on the cpu where it previously - * ran and if it is currently idle, then it the right target. + * If the prevous cpu is cache affine and idle, don't be stupid. */ - if (target == prev_cpu && idle_cpu(prev_cpu)) - return prev_cpu; + if (i != target && cpus_share_cache(i, target) && idle_cpu(i)) + return i; /* * Otherwise, iterate the domains and find an elegible idle cpu. @@ -2666,7 +2706,7 @@ static int select_idle_sibling(struct task_struct *p, int target) goto next; for_each_cpu(i, sched_group_cpus(sg)) { - if (!idle_cpu(i)) + if (i == target || !idle_cpu(i)) goto next; } @@ -4451,10 +4491,10 @@ static int load_balance(int this_cpu, struct rq *this_rq, * correctly treated as an imbalance. */ env.flags |= LBF_ALL_PINNED; - env.load_move = imbalance; - env.src_cpu = busiest->cpu; - env.src_rq = busiest; - env.loop_max = min_t(unsigned long, sysctl_sched_nr_migrate, busiest->nr_running); + env.load_move = imbalance; + env.src_cpu = busiest->cpu; + env.src_rq = busiest; + env.loop_max = min(sysctl_sched_nr_migrate, busiest->nr_running); more_balance: local_irq_save(flags); diff --git a/kernel/sched/features.h b/kernel/sched/features.h index de00a486c5c..d98ae909e32 100644 --- a/kernel/sched/features.h +++ b/kernel/sched/features.h @@ -42,7 +42,7 @@ SCHED_FEAT(CACHE_HOT_BUDDY, true) /* * Use arch dependent cpu power functions */ -SCHED_FEAT(ARCH_POWER, false) +SCHED_FEAT(ARCH_POWER, true) SCHED_FEAT(HRTICK, false) SCHED_FEAT(DOUBLE_TICK, false) diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 5370bcb8e77..a367141a8ca 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -203,7 +203,7 @@ struct cfs_bandwidth { }; /* CFS-related fields in a runqueue */ struct cfs_rq { struct load_weight load; - unsigned long nr_running, h_nr_running; + unsigned int nr_running, h_nr_running; u64 exec_clock; u64 min_vruntime; @@ -281,7 +281,7 @@ static inline int rt_bandwidth_enabled(void) /* Real-Time classes' related field in a runqueue: */ struct rt_rq { struct rt_prio_array active; - unsigned long rt_nr_running; + unsigned int rt_nr_running; #if defined CONFIG_SMP || defined CONFIG_RT_GROUP_SCHED struct { int curr; /* highest queued rt task prio */ @@ -355,7 +355,7 @@ struct rq { * nr_running and cpu_load should be in the same cacheline because * remote CPUs use both these fields when doing load calculation. */ - unsigned long nr_running; + unsigned int nr_running; #define CPU_LOAD_IDX_MAX 5 unsigned long cpu_load[CPU_LOAD_IDX_MAX]; unsigned long last_load_update_tick; @@ -484,6 +484,22 @@ DECLARE_PER_CPU(struct rq, runqueues); #define cpu_curr(cpu) (cpu_rq(cpu)->curr) #define raw_rq() (&__raw_get_cpu_var(runqueues)) +#ifdef CONFIG_INTELLI_PLUG +struct nr_stats_s { + /* time-based average load */ + u64 nr_last_stamp; + unsigned int ave_nr_running; + seqcount_t ave_seqcnt; +}; + +#define NR_AVE_PERIOD_EXP 27 +#define NR_AVE_SCALE(x) ((x) << FSHIFT) +#define NR_AVE_PERIOD (1 << NR_AVE_PERIOD_EXP) +#define NR_AVE_DIV_PERIOD(x) ((x) >> NR_AVE_PERIOD_EXP) + +DECLARE_PER_CPU(struct nr_stats_s, runqueue_stats); +#endif + #ifdef CONFIG_SMP #define rcu_dereference_check_sched_domain(p) \ @@ -526,6 +542,7 @@ static inline struct sched_domain *highest_flag_domain(int cpu, int flag) } DECLARE_PER_CPU(struct sched_domain *, sd_llc); +DECLARE_PER_CPU(int, sd_llc_size); DECLARE_PER_CPU(int, sd_llc_id); #endif /* CONFIG_SMP */ @@ -924,16 +941,61 @@ extern void cpuacct_charge(struct task_struct *tsk, u64 cputime); static inline void cpuacct_charge(struct task_struct *tsk, u64 cputime) {} #endif +#ifdef CONFIG_INTELLI_PLUG +static inline unsigned int do_avg_nr_running(struct rq *rq) +{ + + struct nr_stats_s *nr_stats = &per_cpu(runqueue_stats, rq->cpu); + unsigned int ave_nr_running = nr_stats->ave_nr_running; + s64 nr, deltax; + + deltax = rq->clock_task - nr_stats->nr_last_stamp; + nr = NR_AVE_SCALE(rq->nr_running); + + if (deltax > NR_AVE_PERIOD) + ave_nr_running = nr; + else + ave_nr_running += + NR_AVE_DIV_PERIOD(deltax * (nr - ave_nr_running)); + + return ave_nr_running; +} +#endif + static inline void inc_nr_running(struct rq *rq) { +#ifdef CONFIG_INTELLI_PLUG + struct nr_stats_s *nr_stats = &per_cpu(runqueue_stats, rq->cpu); +#endif + sched_update_nr_prod(cpu_of(rq), rq->nr_running, true); +#ifdef CONFIG_INTELLI_PLUG + write_seqcount_begin(&nr_stats->ave_seqcnt); + nr_stats->ave_nr_running = do_avg_nr_running(rq); + nr_stats->nr_last_stamp = rq->clock_task; +#endif rq->nr_running++; +#ifdef CONFIG_INTELLI_PLUG + write_seqcount_end(&nr_stats->ave_seqcnt); +#endif } static inline void dec_nr_running(struct rq *rq) { +#ifdef CONFIG_INTELLI_PLUG + struct nr_stats_s *nr_stats = &per_cpu(runqueue_stats, rq->cpu); +#endif + sched_update_nr_prod(cpu_of(rq), rq->nr_running, false); +#ifdef CONFIG_INTELLI_PLUG + write_seqcount_begin(&nr_stats->ave_seqcnt); + nr_stats->ave_nr_running = do_avg_nr_running(rq); + nr_stats->nr_last_stamp = rq->clock_task; +#endif rq->nr_running--; +#ifdef CONFIG_INTELLI_PLUG + write_seqcount_end(&nr_stats->ave_seqcnt); +#endif } extern void update_rq_clock(struct rq *rq); diff --git a/kernel/signal.c b/kernel/signal.c index 9f70f45f944..cd0e615b558 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -2211,7 +2211,7 @@ int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, * Now that we woke up, it's crucial if we're supposed to be * frozen that we freeze now before running anything substantial. */ - try_to_freeze(); + try_to_freeze_nowarn(); spin_lock_irq(&sighand->siglock); /* @@ -2764,7 +2764,7 @@ int do_sigtimedwait(const sigset_t *which, siginfo_t *info, recalc_sigpending(); spin_unlock_irq(&tsk->sighand->siglock); - timeout = schedule_timeout_interruptible(timeout); + timeout = freezable_schedule_timeout_interruptible(timeout); spin_lock_irq(&tsk->sighand->siglock); __set_task_blocked(tsk, &tsk->real_blocked); diff --git a/kernel/smpboot.c b/kernel/smpboot.c new file mode 100644 index 00000000000..905b27482eb --- /dev/null +++ b/kernel/smpboot.c @@ -0,0 +1,313 @@ +/* + * Common SMP CPU bringup/teardown functions + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "smpboot.h" + +#ifdef CONFIG_SMP + +#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD +/* + * For the hotplug case we keep the task structs around and reuse + * them. + */ +static DEFINE_PER_CPU(struct task_struct *, idle_threads); + +struct task_struct * idle_thread_get(unsigned int cpu) +{ + struct task_struct *tsk = per_cpu(idle_threads, cpu); + + if (!tsk) + return ERR_PTR(-ENOMEM); + init_idle(tsk, cpu); + return tsk; +} + +void __init idle_thread_set_boot_cpu(void) +{ + per_cpu(idle_threads, smp_processor_id()) = current; +} + +/** + * idle_init - Initialize the idle thread for a cpu + * @cpu: The cpu for which the idle thread should be initialized + * + * Creates the thread if it does not exist. + */ +static inline void idle_init(unsigned int cpu) +{ + struct task_struct *tsk = per_cpu(idle_threads, cpu); + + if (!tsk) { + tsk = fork_idle(cpu); + if (IS_ERR(tsk)) + pr_err("SMP: fork_idle() failed for CPU %u\n", cpu); + else + per_cpu(idle_threads, cpu) = tsk; + } +} + +/** + * idle_threads_init - Initialize idle threads for all cpus + */ +void __init idle_threads_init(void) +{ + unsigned int cpu, boot_cpu; + + boot_cpu = smp_processor_id(); + + for_each_possible_cpu(cpu) { + if (cpu != boot_cpu) + idle_init(cpu); + } +} +#endif + +#endif /* #ifdef CONFIG_SMP */ + +static LIST_HEAD(hotplug_threads); +static DEFINE_MUTEX(smpboot_threads_lock); + +struct smpboot_thread_data { + unsigned int cpu; + unsigned int status; + struct smp_hotplug_thread *ht; +}; + +enum { + HP_THREAD_NONE = 0, + HP_THREAD_ACTIVE, + HP_THREAD_PARKED, +}; + +/** + * smpboot_thread_fn - percpu hotplug thread loop function + * @data: thread data pointer + * + * Checks for thread stop and park conditions. Calls the necessary + * setup, cleanup, park and unpark functions for the registered + * thread. + * + * Returns 1 when the thread should exit, 0 otherwise. + */ +static int smpboot_thread_fn(void *data) +{ + struct smpboot_thread_data *td = data; + struct smp_hotplug_thread *ht = td->ht; + + while (1) { + set_current_state(TASK_INTERRUPTIBLE); + preempt_disable(); + if (kthread_should_stop()) { + set_current_state(TASK_RUNNING); + preempt_enable(); + if (ht->cleanup) + ht->cleanup(td->cpu, cpu_online(td->cpu)); + kfree(td); + return 0; + } + + if (kthread_should_park()) { + __set_current_state(TASK_RUNNING); + preempt_enable(); + if (ht->park && td->status == HP_THREAD_ACTIVE) { + BUG_ON(td->cpu != smp_processor_id()); + ht->park(td->cpu); + td->status = HP_THREAD_PARKED; + } + kthread_parkme(); + /* We might have been woken for stop */ + continue; + } + + BUG_ON(td->cpu != smp_processor_id()); + + /* Check for state change setup */ + switch (td->status) { + case HP_THREAD_NONE: + preempt_enable(); + if (ht->setup) + ht->setup(td->cpu); + td->status = HP_THREAD_ACTIVE; + preempt_disable(); + break; + case HP_THREAD_PARKED: + preempt_enable(); + if (ht->unpark) + ht->unpark(td->cpu); + td->status = HP_THREAD_ACTIVE; + preempt_disable(); + break; + } + + if (!ht->thread_should_run(td->cpu)) { + preempt_enable(); + schedule(); + } else { + set_current_state(TASK_RUNNING); + preempt_enable(); + ht->thread_fn(td->cpu); + } + } +} + +static int +__smpboot_create_thread(struct smp_hotplug_thread *ht, unsigned int cpu) +{ + struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + struct smpboot_thread_data *td; + + if (tsk) + return 0; + + td = kzalloc_node(sizeof(*td), GFP_KERNEL, cpu_to_node(cpu)); + if (!td) + return -ENOMEM; + td->cpu = cpu; + td->ht = ht; + + tsk = kthread_create_on_cpu(smpboot_thread_fn, td, cpu, + ht->thread_comm); + if (IS_ERR(tsk)) { + kfree(td); + return PTR_ERR(tsk); + } + get_task_struct(tsk); + *per_cpu_ptr(ht->store, cpu) = tsk; + if (ht->create) { + /* + * Make sure that the task has actually scheduled out + * into park position, before calling the create + * callback. At least the migration thread callback + * requires that the task is off the runqueue. + */ + if (!wait_task_inactive(tsk, TASK_PARKED)) + WARN_ON(1); + else + ht->create(cpu); + } + return 0; +} + +int smpboot_create_threads(unsigned int cpu) +{ + struct smp_hotplug_thread *cur; + int ret = 0; + + mutex_lock(&smpboot_threads_lock); + list_for_each_entry(cur, &hotplug_threads, list) { + ret = __smpboot_create_thread(cur, cpu); + if (ret) + break; + } + mutex_unlock(&smpboot_threads_lock); + return ret; +} + +static void smpboot_unpark_thread(struct smp_hotplug_thread *ht, unsigned int cpu) +{ + struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + + if (ht->pre_unpark) + ht->pre_unpark(cpu); + kthread_unpark(tsk); +} + +void smpboot_unpark_threads(unsigned int cpu) +{ + struct smp_hotplug_thread *cur; + + mutex_lock(&smpboot_threads_lock); + list_for_each_entry(cur, &hotplug_threads, list) + smpboot_unpark_thread(cur, cpu); + mutex_unlock(&smpboot_threads_lock); +} + +static void smpboot_park_thread(struct smp_hotplug_thread *ht, unsigned int cpu) +{ + struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + + if (tsk && !ht->selfparking) + kthread_park(tsk); +} + +void smpboot_park_threads(unsigned int cpu) +{ + struct smp_hotplug_thread *cur; + + mutex_lock(&smpboot_threads_lock); + list_for_each_entry_reverse(cur, &hotplug_threads, list) + smpboot_park_thread(cur, cpu); + mutex_unlock(&smpboot_threads_lock); +} + +static void smpboot_destroy_threads(struct smp_hotplug_thread *ht) +{ + unsigned int cpu; + + /* We need to destroy also the parked threads of offline cpus */ + for_each_possible_cpu(cpu) { + struct task_struct *tsk = *per_cpu_ptr(ht->store, cpu); + + if (tsk) { + kthread_stop(tsk); + put_task_struct(tsk); + *per_cpu_ptr(ht->store, cpu) = NULL; + } + } +} + +/** + * smpboot_register_percpu_thread - Register a per_cpu thread related to hotplug + * @plug_thread: Hotplug thread descriptor + * + * Creates and starts the threads on all online cpus. + */ +int smpboot_register_percpu_thread(struct smp_hotplug_thread *plug_thread) +{ + unsigned int cpu; + int ret = 0; + + mutex_lock(&smpboot_threads_lock); + for_each_online_cpu(cpu) { + ret = __smpboot_create_thread(plug_thread, cpu); + if (ret) { + smpboot_destroy_threads(plug_thread); + goto out; + } + smpboot_unpark_thread(plug_thread, cpu); + } + list_add(&plug_thread->list, &hotplug_threads); +out: + mutex_unlock(&smpboot_threads_lock); + return ret; +} +EXPORT_SYMBOL_GPL(smpboot_register_percpu_thread); + +/** + * smpboot_unregister_percpu_thread - Unregister a per_cpu thread related to hotplug + * @plug_thread: Hotplug thread descriptor + * + * Stops all threads on all possible cpus. + */ +void smpboot_unregister_percpu_thread(struct smp_hotplug_thread *plug_thread) +{ + get_online_cpus(); + mutex_lock(&smpboot_threads_lock); + list_del(&plug_thread->list); + smpboot_destroy_threads(plug_thread); + mutex_unlock(&smpboot_threads_lock); + put_online_cpus(); +} +EXPORT_SYMBOL_GPL(smpboot_unregister_percpu_thread); diff --git a/kernel/smpboot.h b/kernel/smpboot.h new file mode 100644 index 00000000000..72415a0eb95 --- /dev/null +++ b/kernel/smpboot.h @@ -0,0 +1,20 @@ +#ifndef SMPBOOT_H +#define SMPBOOT_H + +struct task_struct; + +#ifdef CONFIG_GENERIC_SMP_IDLE_THREAD +struct task_struct *idle_thread_get(unsigned int cpu); +void idle_thread_set_boot_cpu(void); +void idle_threads_init(void); +#else +static inline struct task_struct *idle_thread_get(unsigned int cpu) { return NULL; } +static inline void idle_thread_set_boot_cpu(void) { } +static inline void idle_threads_init(void) { } +#endif + +int smpboot_create_threads(unsigned int cpu); +void smpboot_park_threads(unsigned int cpu); +void smpboot_unpark_threads(unsigned int cpu); + +#endif diff --git a/kernel/softirq.c b/kernel/softirq.c index 671f9594e36..7704722e47b 100644 --- a/kernel/softirq.c +++ b/kernel/softirq.c @@ -194,21 +194,21 @@ void local_bh_enable_ip(unsigned long ip) EXPORT_SYMBOL(local_bh_enable_ip); /* - * We restart softirq processing MAX_SOFTIRQ_RESTART times, - * and we fall back to softirqd after that. + * We restart softirq processing for at most 2 ms, + * and if need_resched() is not set. * - * This number has been established via experimentation. + * These limits have been established via experimentation. * The two things to balance is latency against fairness - * we want to handle softirqs as soon as possible, but they * should not be able to lock up the box. */ -#define MAX_SOFTIRQ_RESTART 10 +#define MAX_SOFTIRQ_TIME msecs_to_jiffies(2) asmlinkage void __do_softirq(void) { struct softirq_action *h; __u32 pending; - int max_restart = MAX_SOFTIRQ_RESTART; + unsigned long end = jiffies + MAX_SOFTIRQ_TIME; int cpu; pending = local_softirq_pending(); @@ -255,11 +255,12 @@ asmlinkage void __do_softirq(void) local_irq_disable(); pending = local_softirq_pending(); - if (pending && --max_restart) - goto restart; + if (pending) { + if (time_before(jiffies, end) && !need_resched()) + goto restart; - if (pending) wakeup_softirqd(); + } lockdep_softirq_exit(); diff --git a/kernel/sys.c b/kernel/sys.c index 6e08068f359..a5b2aec06ee 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include @@ -650,6 +652,7 @@ static int set_user(struct cred *new) free_uid(new->user); new->user = new_user; + sched_autogroup_create_attach(current); return 0; } @@ -1159,7 +1162,7 @@ SYSCALL_DEFINE0(setsid) write_unlock_irq(&tasklist_lock); if (err > 0) { proc_sid_connector(group_leader); - sched_autogroup_create_attach(group_leader); + } return err; } @@ -1821,6 +1824,146 @@ static int prctl_set_mm(int opt, unsigned long addr, } #endif + +static int prctl_update_vma_anon_name(struct vm_area_struct *vma, + struct vm_area_struct **prev, + unsigned long start, unsigned long end, + const char __user *name_addr) +{ + struct mm_struct * mm = vma->vm_mm; + int error = 0; + pgoff_t pgoff; + + if (name_addr == vma_get_anon_name(vma)) { + *prev = vma; + goto out; + } + + pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); + *prev = vma_merge(mm, *prev, start, end, vma->vm_flags, vma->anon_vma, + vma->vm_file, pgoff, vma_policy(vma), + name_addr); + if (*prev) { + vma = *prev; + goto success; + } + + *prev = vma; + + if (start != vma->vm_start) { + error = split_vma(mm, vma, start, 1); + if (error) + goto out; + } + + if (end != vma->vm_end) { + error = split_vma(mm, vma, end, 0); + if (error) + goto out; + } + +success: + if (!vma->vm_file) + vma->shared.anon_name = name_addr; + +out: + if (error == -ENOMEM) + error = -EAGAIN; + return error; +} + +static int prctl_set_vma_anon_name(unsigned long start, unsigned long end, + unsigned long arg) +{ + unsigned long tmp; + struct vm_area_struct * vma, *prev; + int unmapped_error = 0; + int error = -EINVAL; + + /* + * If the interval [start,end) covers some unmapped address + * ranges, just ignore them, but return -ENOMEM at the end. + * - this matches the handling in madvise. + */ + vma = find_vma_prev(current->mm, start, &prev); + if (vma && start > vma->vm_start) + prev = vma; + + for (;;) { + /* Still start < end. */ + error = -ENOMEM; + if (!vma) + return error; + + /* Here start < (end|vma->vm_end). */ + if (start < vma->vm_start) { + unmapped_error = -ENOMEM; + start = vma->vm_start; + if (start >= end) + return error; + } + + /* Here vma->vm_start <= start < (end|vma->vm_end) */ + tmp = vma->vm_end; + if (end < tmp) + tmp = end; + + /* Here vma->vm_start <= start < tmp <= (end|vma->vm_end). */ + error = prctl_update_vma_anon_name(vma, &prev, start, end, + (const char __user *)arg); + if (error) + return error; + start = tmp; + if (prev && start < prev->vm_end) + start = prev->vm_end; + error = unmapped_error; + if (start >= end) + return error; + if (prev) + vma = prev->vm_next; + else /* madvise_remove dropped mmap_sem */ + vma = find_vma(current->mm, start); + } +} + +static int prctl_set_vma(unsigned long opt, unsigned long start, + unsigned long len_in, unsigned long arg) +{ + struct mm_struct *mm = current->mm; + int error; + unsigned long len; + unsigned long end; + + if (start & ~PAGE_MASK) + return -EINVAL; + len = (len_in + ~PAGE_MASK) & PAGE_MASK; + + /* Check to see whether len was rounded up from small -ve to zero */ + if (len_in && !len) + return -EINVAL; + + end = start + len; + if (end < start) + return -EINVAL; + + if (end == start) + return 0; + + down_write(&mm->mmap_sem); + + switch (opt) { + case PR_SET_VMA_ANON_NAME: + error = prctl_set_vma_anon_name(start, end, arg); + break; + default: + error = -EINVAL; + } + + up_write(&mm->mmap_sem); + + return error; +} + SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, unsigned long, arg4, unsigned long, arg5) { @@ -1981,6 +2124,9 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, error = put_user(me->signal->is_child_subreaper, (int __user *) arg2); break; + case PR_SET_VMA: + error = prctl_set_vma(arg2, arg3, arg4, arg5); + break; default: error = -EINVAL; break; diff --git a/kernel/sysctl.c b/kernel/sysctl.c index b69314289ae..aa06d5eb860 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -359,7 +359,7 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_autogroup_enabled, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec_minmax, + .proc_handler = proc_dointvec, .extra1 = &zero, .extra2 = &one, }, @@ -1822,7 +1822,7 @@ static int __do_proc_dointvec(void *tbl_data, struct ctl_table *table, int *i, vleft, first = 1, err = 0; unsigned long page = 0; size_t left; - char *kbuf; + char *kbuf = NULL; if (!tbl_data || !table->maxlen || !*lenp || (*ppos && !write)) { *lenp = 0; @@ -2040,7 +2040,7 @@ static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int int vleft, first = 1, err = 0; unsigned long page = 0; size_t left; - char *kbuf; + char *kbuf = NULL; if (!data || !table->maxlen || !*lenp || (*ppos && !write)) { *lenp = 0; diff --git a/kernel/time/alarmtimer.c b/kernel/time/alarmtimer.c index aa27d391bfc..b07241cc809 100644 --- a/kernel/time/alarmtimer.c +++ b/kernel/time/alarmtimer.c @@ -37,7 +37,6 @@ static struct alarm_base { spinlock_t lock; struct timerqueue_head timerqueue; - struct hrtimer timer; ktime_t (*gettime)(void); clockid_t base_clockid; } alarm_bases[ALARM_NUMTYPE]; @@ -46,6 +45,8 @@ static struct alarm_base { static ktime_t freezer_delta; static DEFINE_SPINLOCK(freezer_delta_lock); +static struct wakeup_source *ws; + #ifdef CONFIG_RTC_CLASS /* rtc timer and device for setting alarm wakeups at suspend */ static struct rtc_timer rtctimer; @@ -130,21 +131,17 @@ static inline void alarmtimer_rtc_timer_init(void) { } * @base: pointer to the base where the timer is being run * @alarm: pointer to alarm being enqueued. * - * Adds alarm to a alarm_base timerqueue and if necessary sets - * an hrtimer to run. + * Adds alarm to a alarm_base timerqueue * * Must hold base->lock when calling. */ static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) { + if (alarm->state & ALARMTIMER_STATE_ENQUEUED) + timerqueue_del(&base->timerqueue, &alarm->node); + timerqueue_add(&base->timerqueue, &alarm->node); alarm->state |= ALARMTIMER_STATE_ENQUEUED; - - if (&alarm->node == timerqueue_getnext(&base->timerqueue)) { - hrtimer_try_to_cancel(&base->timer); - hrtimer_start(&base->timer, alarm->node.expires, - HRTIMER_MODE_ABS); - } } /** @@ -152,28 +149,17 @@ static void alarmtimer_enqueue(struct alarm_base *base, struct alarm *alarm) * @base: pointer to the base where the timer is running * @alarm: pointer to alarm being removed * - * Removes alarm to a alarm_base timerqueue and if necessary sets - * a new timer to run. + * Removes alarm to a alarm_base timerqueue * * Must hold base->lock when calling. */ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) { - struct timerqueue_node *next = timerqueue_getnext(&base->timerqueue); - if (!(alarm->state & ALARMTIMER_STATE_ENQUEUED)) return; timerqueue_del(&base->timerqueue, &alarm->node); alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; - - if (next == &alarm->node) { - hrtimer_try_to_cancel(&base->timer); - next = timerqueue_getnext(&base->timerqueue); - if (!next) - return; - hrtimer_start(&base->timer, next->expires, HRTIMER_MODE_ABS); - } } @@ -188,42 +174,23 @@ static void alarmtimer_remove(struct alarm_base *base, struct alarm *alarm) */ static enum hrtimer_restart alarmtimer_fired(struct hrtimer *timer) { - struct alarm_base *base = container_of(timer, struct alarm_base, timer); - struct timerqueue_node *next; + struct alarm *alarm = container_of(timer, struct alarm, timer); + struct alarm_base *base = &alarm_bases[alarm->type]; unsigned long flags; - ktime_t now; int ret = HRTIMER_NORESTART; int restart = ALARMTIMER_NORESTART; spin_lock_irqsave(&base->lock, flags); - now = base->gettime(); - while ((next = timerqueue_getnext(&base->timerqueue))) { - struct alarm *alarm; - ktime_t expired = next->expires; - - if (expired.tv64 > now.tv64) - break; - - alarm = container_of(next, struct alarm, node); - - timerqueue_del(&base->timerqueue, &alarm->node); - alarm->state &= ~ALARMTIMER_STATE_ENQUEUED; - - alarm->state |= ALARMTIMER_STATE_CALLBACK; - spin_unlock_irqrestore(&base->lock, flags); - if (alarm->function) - restart = alarm->function(alarm, now); - spin_lock_irqsave(&base->lock, flags); - alarm->state &= ~ALARMTIMER_STATE_CALLBACK; + alarmtimer_remove(base, alarm); + spin_unlock_irqrestore(&base->lock, flags); - if (restart != ALARMTIMER_NORESTART) { - timerqueue_add(&base->timerqueue, &alarm->node); - alarm->state |= ALARMTIMER_STATE_ENQUEUED; - } - } + if (alarm->function) + restart = alarm->function(alarm, base->gettime()); - if (next) { - hrtimer_set_expires(&base->timer, next->expires); + spin_lock_irqsave(&base->lock, flags); + if (restart != ALARMTIMER_NORESTART) { + hrtimer_set_expires(&alarm->timer, alarm->node.expires); + alarmtimer_enqueue(base, alarm); ret = HRTIMER_RESTART; } spin_unlock_irqrestore(&base->lock, flags); @@ -250,6 +217,7 @@ static int alarmtimer_suspend(struct device *dev) unsigned long flags; struct rtc_device *rtc; int i; + int ret; spin_lock_irqsave(&freezer_delta_lock, flags); min = freezer_delta; @@ -279,8 +247,10 @@ static int alarmtimer_suspend(struct device *dev) if (min.tv64 == 0) return 0; - /* XXX - Should we enforce a minimum sleep time? */ - WARN_ON(min.tv64 < NSEC_PER_SEC); + if (ktime_to_ns(min) < 2 * NSEC_PER_SEC) { + __pm_wakeup_event(ws, 2 * MSEC_PER_SEC); + return -EBUSY; + } /* Setup an rtc timer to fire that far in the future */ rtc_timer_cancel(rtc, &rtctimer); @@ -288,9 +258,11 @@ static int alarmtimer_suspend(struct device *dev) now = rtc_tm_to_ktime(tm); now = ktime_add(now, min); - rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); - - return 0; + /* Set alarm, if in the past reject suspend briefly to handle */ + ret = rtc_timer_start(rtc, &rtctimer, now, ktime_set(0, 0)); + if (ret < 0) + __pm_wakeup_event(ws, 1 * MSEC_PER_SEC); + return ret; } #else static int alarmtimer_suspend(struct device *dev) @@ -324,6 +296,9 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type, enum alarmtimer_restart (*function)(struct alarm *, ktime_t)) { timerqueue_init(&alarm->node); + hrtimer_init(&alarm->timer, alarm_bases[type].base_clockid, + HRTIMER_MODE_ABS); + alarm->timer.function = alarmtimer_fired; alarm->function = function; alarm->type = type; alarm->state = ALARMTIMER_STATE_INACTIVE; @@ -334,17 +309,19 @@ void alarm_init(struct alarm *alarm, enum alarmtimer_type type, * @alarm: ptr to alarm to set * @start: time to run the alarm */ -void alarm_start(struct alarm *alarm, ktime_t start) +int alarm_start(struct alarm *alarm, ktime_t start) { struct alarm_base *base = &alarm_bases[alarm->type]; unsigned long flags; + int ret; spin_lock_irqsave(&base->lock, flags); - if (alarmtimer_active(alarm)) - alarmtimer_remove(base, alarm); alarm->node.expires = start; alarmtimer_enqueue(base, alarm); + ret = hrtimer_start(&alarm->timer, alarm->node.expires, + HRTIMER_MODE_ABS); spin_unlock_irqrestore(&base->lock, flags); + return ret; } /** @@ -358,18 +335,12 @@ int alarm_try_to_cancel(struct alarm *alarm) { struct alarm_base *base = &alarm_bases[alarm->type]; unsigned long flags; - int ret = -1; - spin_lock_irqsave(&base->lock, flags); + int ret; - if (alarmtimer_callback_running(alarm)) - goto out; - - if (alarmtimer_is_queued(alarm)) { + spin_lock_irqsave(&base->lock, flags); + ret = hrtimer_try_to_cancel(&alarm->timer); + if (ret >= 0) alarmtimer_remove(base, alarm); - ret = 1; - } else - ret = 0; -out: spin_unlock_irqrestore(&base->lock, flags); return ret; } @@ -802,10 +773,6 @@ static int __init alarmtimer_init(void) for (i = 0; i < ALARM_NUMTYPE; i++) { timerqueue_init_head(&alarm_bases[i].timerqueue); spin_lock_init(&alarm_bases[i].lock); - hrtimer_init(&alarm_bases[i].timer, - alarm_bases[i].base_clockid, - HRTIMER_MODE_ABS); - alarm_bases[i].timer.function = alarmtimer_fired; } error = alarmtimer_rtc_interface_setup(); @@ -821,6 +788,7 @@ static int __init alarmtimer_init(void) error = PTR_ERR(pdev); goto out_drv; } + ws = wakeup_source_register("alarmtimer"); return 0; out_drv: diff --git a/kernel/time/tick-sched.c b/kernel/time/tick-sched.c index c6cd85b8852..7eba0df92e6 100644 --- a/kernel/time/tick-sched.c +++ b/kernel/time/tick-sched.c @@ -337,11 +337,12 @@ static void tick_nohz_stop_sched_tick(struct tick_sched *ts) next_jiffies = get_next_timer_interrupt(last_jiffies); delta_jiffies = next_jiffies - last_jiffies; } + /* - * Do not stop the tick, if we are only one off - * or if the cpu is required for rcu + * Do not stop the tick, if we are only one off (or less) + * or if the cpu is required for RCU: */ - if (!ts->tick_stopped && delta_jiffies == 1) + if (!ts->tick_stopped && delta_jiffies <= 1) goto out; /* Schedule the tick, if we are at least one jiffie off */ @@ -503,7 +504,9 @@ void tick_nohz_irq_exit(void) if (!ts->inidle) return; - + + /* Cancel the timer because CPU already waken up from the C-states*/ + menu_hrtimer_cancel(); tick_nohz_stop_sched_tick(ts); } @@ -567,6 +570,8 @@ void tick_nohz_idle_exit(void) ts->inidle = 0; + /* Cancel the timer because CPU already waken up from the C-states*/ + menu_hrtimer_cancel(); if (ts->idle_active || ts->tick_stopped) now = ktime_get(); diff --git a/kernel/timeconst.pl b/kernel/timeconst.pl index eb51d76e058..04612394c53 100644 --- a/kernel/timeconst.pl +++ b/kernel/timeconst.pl @@ -370,7 +370,7 @@ (@) } @val = @{$canned_values{$hz}}; - if (!defined(@val)) { + if (!@val) { @val = compute_values($hz); } output($hz, @val); diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index bfc6704f1d1..00586680b93 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig @@ -148,6 +148,7 @@ config FUNCTION_TRACER select KALLSYMS select GENERIC_TRACER select CONTEXT_SWITCH_TRACER + default n help Enable the kernel to trace every kernel function. This is done by using a compiler feature to insert a small, 5-byte No-Operation @@ -328,6 +329,7 @@ config STACK_TRACER select FUNCTION_TRACER select STACKTRACE select KALLSYMS + default n help This special tracer records the maximum stack footprint of the kernel and displays it in /sys/kernel/debug/tracing/stack_trace. @@ -392,7 +394,7 @@ config DYNAMIC_FTRACE bool "enable/disable ftrace tracepoints dynamically" depends on FUNCTION_TRACER depends on HAVE_DYNAMIC_FTRACE - default y + default n help This option will modify all the calls to ftrace dynamically (will patch them out of the binary image and replace them diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 7da267c8d0d..43b7e95f967 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -3660,7 +3660,12 @@ void freeze_workqueues_begin(void) gcwq->flags |= GCWQ_FREEZING; list_for_each_entry(wq, &workqueues, list) { - struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); + + struct cpu_workqueue_struct *cwq; + if (cpu < CONFIG_NR_CPUS) + cwq = get_cwq(cpu, wq); + else + continue; if (cwq && wq->flags & WQ_FREEZABLE) cwq->max_active = 0; @@ -3701,7 +3706,12 @@ bool freeze_workqueues_busy(void) * to peek without lock. */ list_for_each_entry(wq, &workqueues, list) { - struct cpu_workqueue_struct *cwq = get_cwq(cpu, wq); + + struct cpu_workqueue_struct *cwq; + if (cpu < CONFIG_NR_CPUS) + cwq = get_cwq(cpu, wq); + else + continue; if (!cwq || !(wq->flags & WQ_FREEZABLE)) continue; diff --git a/lib/Kconfig b/lib/Kconfig index 4a8aba2e5cc..19f47779117 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -177,6 +177,15 @@ config LZO_COMPRESS config LZO_DECOMPRESS tristate +config LZ4_COMPRESS + tristate + +config LZ4HC_COMPRESS + tristate + +config LZ4_DECOMPRESS + tristate + source "lib/xz/Kconfig" # @@ -201,6 +210,10 @@ config DECOMPRESS_LZO select LZO_DECOMPRESS tristate +config DECOMPRESS_LZ4 + select LZ4_DECOMPRESS + tristate + # # Generic allocator support is selected if needed # diff --git a/lib/Makefile b/lib/Makefile index acd68695763..2004b1da426 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -8,11 +8,12 @@ KBUILD_CFLAGS = $(subst -pg,,$(ORIG_CFLAGS)) endif lib-y := ctype.o string.o vsprintf.o cmdline.o \ - rbtree.o radix-tree.o dump_stack.o timerqueue.o\ + rbtree.o radix-tree.o sradix-tree.o dump_stack.o timerqueue.o\ idr.o int_sqrt.o extable.o prio_tree.o \ sha1.o md5.o irq_regs.o reciprocal_div.o argv_split.o \ proportions.o prio_heap.o ratelimit.o show_mem.o \ - is_single_threaded.o plist.o decompress.o memory_alloc.o + is_single_threaded.o plist.o decompress.o memory_alloc.o \ + memcopy.o lib-$(CONFIG_MMU) += ioremap.o lib-$(CONFIG_SMP) += cpumask.o @@ -71,6 +72,9 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/ obj-$(CONFIG_BCH) += bch.o obj-$(CONFIG_LZO_COMPRESS) += lzo/ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ +obj-$(CONFIG_LZ4_COMPRESS) += lz4/ +obj-$(CONFIG_LZ4HC_COMPRESS) += lz4/ +obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/ obj-$(CONFIG_XZ_DEC) += xz/ obj-$(CONFIG_RAID6_PQ) += raid6/ @@ -79,6 +83,7 @@ lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o +lib-$(CONFIG_DECOMPRESS_LZ4) += decompress_unlz4.o obj-$(CONFIG_TEXTSEARCH) += textsearch.o obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o diff --git a/lib/decompress.c b/lib/decompress.c index 3d766b7f60a..fc3f2dda8c3 100644 --- a/lib/decompress.c +++ b/lib/decompress.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -30,6 +31,9 @@ #ifndef CONFIG_DECOMPRESS_LZO # define unlzo NULL #endif +#ifndef CONFIG_DECOMPRESS_LZ4 +# define unlz4 NULL +#endif static const struct compress_format { unsigned char magic[2]; @@ -42,6 +46,7 @@ static const struct compress_format { { {0x5d, 0x00}, "lzma", unlzma }, { {0xfd, 0x37}, "xz", unxz }, { {0x89, 0x4c}, "lzo", unlzo }, + { {0x02, 0x21}, "lz4", unlz4 }, { {0, 0}, NULL, NULL } }; diff --git a/lib/decompress_unlz4.c b/lib/decompress_unlz4.c new file mode 100644 index 00000000000..7d1e83caf8a --- /dev/null +++ b/lib/decompress_unlz4.c @@ -0,0 +1,188 @@ +/* + * Wrapper for decompressing LZ4-compressed kernel, initramfs, and initrd + * + * Copyright (C) 2013, LG Electronics, Kyungsik Lee + * + * 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. + */ + +#ifdef STATIC +#define PREBOOT +#include "lz4/lz4_decompress.c" +#else +#include +#endif +#include +#include +#include +#include + +#include + +/* + * Note: Uncompressed chunk size is used in the compressor side + * (userspace side for compression). + * It is hardcoded because there is not proper way to extract it + * from the binary stream which is generated by the preliminary + * version of LZ4 tool so far. + */ +#define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20) +#define ARCHIVE_MAGICNUMBER 0x184C2102 + +STATIC inline int INIT unlz4(u8 *input, int in_len, + int (*fill) (void *, unsigned int), + int (*flush) (void *, unsigned int), + u8 *output, int *posp, + void (*error) (char *x)) +{ + int ret = -1; + size_t chunksize = 0; + size_t uncomp_chunksize = LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE; + u8 *inp; + u8 *inp_start; + u8 *outp; + int size = in_len; +#ifdef PREBOOT + size_t out_len = get_unaligned_le32(input + in_len); +#endif + size_t dest_len; + + + if (output) { + outp = output; + } else if (!flush) { + error("NULL output pointer and no flush function provided"); + goto exit_0; + } else { + outp = large_malloc(uncomp_chunksize); + if (!outp) { + error("Could not allocate output buffer"); + goto exit_0; + } + } + + if (input && fill) { + error("Both input pointer and fill function provided,"); + goto exit_1; + } else if (input) { + inp = input; + } else if (!fill) { + error("NULL input pointer and missing fill function"); + goto exit_1; + } else { + inp = large_malloc(lz4_compressbound(uncomp_chunksize)); + if (!inp) { + error("Could not allocate input buffer"); + goto exit_1; + } + } + inp_start = inp; + + if (posp) + *posp = 0; + + if (fill) + fill(inp, 4); + + chunksize = get_unaligned_le32(inp); + if (chunksize == ARCHIVE_MAGICNUMBER) { + inp += 4; + size -= 4; + } else { + error("invalid header"); + goto exit_2; + } + + if (posp) + *posp += 4; + + for (;;) { + + if (fill) + fill(inp, 4); + + chunksize = get_unaligned_le32(inp); + if (chunksize == ARCHIVE_MAGICNUMBER) { + inp += 4; + size -= 4; + if (posp) + *posp += 4; + continue; + } + inp += 4; + size -= 4; + + if (posp) + *posp += 4; + + if (fill) { + if (chunksize > lz4_compressbound(uncomp_chunksize)) { + error("chunk length is longer than allocated"); + goto exit_2; + } + fill(inp, chunksize); + } +#ifdef PREBOOT + if (out_len >= uncomp_chunksize) { + dest_len = uncomp_chunksize; + out_len -= dest_len; + } else + dest_len = out_len; + ret = lz4_decompress(inp, &chunksize, outp, dest_len); +#else + dest_len = uncomp_chunksize; + ret = lz4_decompress_unknownoutputsize(inp, chunksize, outp, + &dest_len); +#endif + if (ret < 0) { + error("Decoding failed"); + goto exit_2; + } + + ret = -1; + if (flush && flush(outp, dest_len) != dest_len) + goto exit_2; + if (output) + outp += dest_len; + if (posp) + *posp += chunksize; + + size -= chunksize; + + if (size == 0) + break; + else if (size < 0) { + error("data corrupted"); + goto exit_2; + } + + inp += chunksize; + if (fill) + inp = inp_start; + } + + ret = 0; +exit_2: + if (!input) + large_free(inp_start); +exit_1: + if (!output) + large_free(outp); +exit_0: + return ret; +} + +#ifdef PREBOOT +STATIC int INIT decompress(unsigned char *buf, int in_len, + int(*fill)(void*, unsigned int), + int(*flush)(void*, unsigned int), + unsigned char *output, + int *posp, + void(*error)(char *x) + ) +{ + return unlz4(buf, in_len - 4, fill, flush, output, posp, error); +} +#endif diff --git a/lib/int_sqrt.c b/lib/int_sqrt.c index fc2eeb7cb2e..1ef4cc34497 100644 --- a/lib/int_sqrt.c +++ b/lib/int_sqrt.c @@ -1,3 +1,9 @@ +/* + * Copyright (C) 2013 Davidlohr Bueso + * + * Based on the shift-and-subtract algorithm for computing integer + * square root from Guy L. Steele. + */ #include #include @@ -10,23 +16,23 @@ */ unsigned long int_sqrt(unsigned long x) { - unsigned long op, res, one; + unsigned long b, m, y = 0; - op = x; - res = 0; + if (x <= 1) + return x; - one = 1UL << (BITS_PER_LONG - 2); - while (one > op) - one >>= 2; + m = 1UL << (BITS_PER_LONG - 2); + while (m != 0) { + b = y + m; + y >>= 1; - while (one != 0) { - if (op >= res + one) { - op = op - (res + one); - res = res + 2 * one; + if (x >= b) { + x -= b; + y += m; } - res /= 2; - one /= 4; + m >>= 2; } - return res; + + return y; } EXPORT_SYMBOL(int_sqrt); diff --git a/lib/lz4/Makefile b/lib/lz4/Makefile new file mode 100644 index 00000000000..8085d04e930 --- /dev/null +++ b/lib/lz4/Makefile @@ -0,0 +1,3 @@ +obj-$(CONFIG_LZ4_COMPRESS) += lz4_compress.o +obj-$(CONFIG_LZ4HC_COMPRESS) += lz4hc_compress.o +obj-$(CONFIG_LZ4_DECOMPRESS) += lz4_decompress.o diff --git a/lib/lz4/lz4_compress.c b/lib/lz4/lz4_compress.c new file mode 100644 index 00000000000..28321d8f75e --- /dev/null +++ b/lib/lz4/lz4_compress.c @@ -0,0 +1,443 @@ +/* + * LZ4 - Fast LZ compression algorithm + * Copyright (C) 2011-2012, Yann Collet. + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at : + * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + * - LZ4 source repository : http://code.google.com/p/lz4/ + * + * Changed for kernel use by: + * Chanho Min + */ + +#include +#include +#include +#include +#include "lz4defs.h" + +/* + * LZ4_compressCtx : + * ----------------- + * Compress 'isize' bytes from 'source' into an output buffer 'dest' of + * maximum size 'maxOutputSize'. * If it cannot achieve it, compression + * will stop, and result of the function will be zero. + * return : the number of bytes written in buffer 'dest', or 0 if the + * compression fails + */ +static inline int lz4_compressctx(void *ctx, + const char *source, + char *dest, + int isize, + int maxoutputsize) +{ + HTYPE *hashtable = (HTYPE *)ctx; + const u8 *ip = (u8 *)source; +#if LZ4_ARCH64 + const BYTE * const base = ip; +#else + const int base = 0; +#endif + const u8 *anchor = ip; + const u8 *const iend = ip + isize; + const u8 *const mflimit = iend - MFLIMIT; + #define MATCHLIMIT (iend - LASTLITERALS) + + u8 *op = (u8 *) dest; + u8 *const oend = op + maxoutputsize; + int length; + const int skipstrength = SKIPSTRENGTH; + u32 forwardh; + int lastrun; + + /* Init */ + if (isize < MINLENGTH) + goto _last_literals; + + memset((void *)hashtable, 0, LZ4_MEM_COMPRESS); + + /* First Byte */ + hashtable[LZ4_HASH_VALUE(ip)] = ip - base; + ip++; + forwardh = LZ4_HASH_VALUE(ip); + + /* Main Loop */ + for (;;) { + int findmatchattempts = (1U << skipstrength) + 3; + const u8 *forwardip = ip; + const u8 *ref; + u8 *token; + + /* Find a match */ + do { + u32 h = forwardh; + int step = findmatchattempts++ >> skipstrength; + ip = forwardip; + forwardip = ip + step; + + if (unlikely(forwardip > mflimit)) + goto _last_literals; + + forwardh = LZ4_HASH_VALUE(forwardip); + ref = base + hashtable[h]; + hashtable[h] = ip - base; + } while ((ref < ip - MAX_DISTANCE) || (A32(ref) != A32(ip))); + + /* Catch up */ + while ((ip > anchor) && (ref > (u8 *)source) && + unlikely(ip[-1] == ref[-1])) { + ip--; + ref--; + } + + /* Encode Literal length */ + length = (int)(ip - anchor); + token = op++; + /* check output limit */ + if (unlikely(op + length + (2 + 1 + LASTLITERALS) + + (length >> 8) > oend)) + return 0; + + if (length >= (int)RUN_MASK) { + int len; + *token = (RUN_MASK << ML_BITS); + len = length - RUN_MASK; + for (; len > 254 ; len -= 255) + *op++ = 255; + *op++ = (u8)len; + } else + *token = (length << ML_BITS); + + /* Copy Literals */ + LZ4_BLINDCOPY(anchor, op, length); +_next_match: + /* Encode Offset */ + LZ4_WRITE_LITTLEENDIAN_16(op, (u16)(ip - ref)); + + /* Start Counting */ + ip += MINMATCH; + /* MinMatch verified */ + ref += MINMATCH; + anchor = ip; + while (likely(ip < MATCHLIMIT - (STEPSIZE - 1))) { + #if LZ4_ARCH64 + u64 diff = A64(ref) ^ A64(ip); + #else + u32 diff = A32(ref) ^ A32(ip); + #endif + if (!diff) { + ip += STEPSIZE; + ref += STEPSIZE; + continue; + } + ip += LZ4_NBCOMMONBYTES(diff); + goto _endcount; + } + #if LZ4_ARCH64 + if ((ip < (MATCHLIMIT - 3)) && (A32(ref) == A32(ip))) { + ip += 4; + ref += 4; + } + #endif + if ((ip < (MATCHLIMIT - 1)) && (A16(ref) == A16(ip))) { + ip += 2; + ref += 2; + } + if ((ip < MATCHLIMIT) && (*ref == *ip)) + ip++; +_endcount: + /* Encode MatchLength */ + length = (int)(ip - anchor); + /* Check output limit */ + if (unlikely(op + (1 + LASTLITERALS) + (length >> 8) > oend)) + return 0; + if (length >= (int)ML_MASK) { + *token += ML_MASK; + length -= ML_MASK; + for (; length > 509 ; length -= 510) { + *op++ = 255; + *op++ = 255; + } + if (length > 254) { + length -= 255; + *op++ = 255; + } + *op++ = (u8)length; + } else + *token += length; + + /* Test end of chunk */ + if (ip > mflimit) { + anchor = ip; + break; + } + + /* Fill table */ + hashtable[LZ4_HASH_VALUE(ip-2)] = ip - 2 - base; + + /* Test next position */ + ref = base + hashtable[LZ4_HASH_VALUE(ip)]; + hashtable[LZ4_HASH_VALUE(ip)] = ip - base; + if ((ref > ip - (MAX_DISTANCE + 1)) && (A32(ref) == A32(ip))) { + token = op++; + *token = 0; + goto _next_match; + } + + /* Prepare next loop */ + anchor = ip++; + forwardh = LZ4_HASH_VALUE(ip); + } + +_last_literals: + /* Encode Last Literals */ + lastrun = (int)(iend - anchor); + if (((char *)op - dest) + lastrun + 1 + + ((lastrun + 255 - RUN_MASK) / 255) > (u32)maxoutputsize) + return 0; + + if (lastrun >= (int)RUN_MASK) { + *op++ = (RUN_MASK << ML_BITS); + lastrun -= RUN_MASK; + for (; lastrun > 254 ; lastrun -= 255) + *op++ = 255; + *op++ = (u8)lastrun; + } else + *op++ = (lastrun << ML_BITS); + memcpy(op, anchor, iend - anchor); + op += iend - anchor; + + /* End */ + return (int)(((char *)op) - dest); +} + +static inline int lz4_compress64kctx(void *ctx, + const char *source, + char *dest, + int isize, + int maxoutputsize) +{ + u16 *hashtable = (u16 *)ctx; + const u8 *ip = (u8 *) source; + const u8 *anchor = ip; + const u8 *const base = ip; + const u8 *const iend = ip + isize; + const u8 *const mflimit = iend - MFLIMIT; + #define MATCHLIMIT (iend - LASTLITERALS) + + u8 *op = (u8 *) dest; + u8 *const oend = op + maxoutputsize; + int len, length; + const int skipstrength = SKIPSTRENGTH; + u32 forwardh; + int lastrun; + + /* Init */ + if (isize < MINLENGTH) + goto _last_literals; + + memset((void *)hashtable, 0, LZ4_MEM_COMPRESS); + + /* First Byte */ + ip++; + forwardh = LZ4_HASH64K_VALUE(ip); + + /* Main Loop */ + for (;;) { + int findmatchattempts = (1U << skipstrength) + 3; + const u8 *forwardip = ip; + const u8 *ref; + u8 *token; + + /* Find a match */ + do { + u32 h = forwardh; + int step = findmatchattempts++ >> skipstrength; + ip = forwardip; + forwardip = ip + step; + + if (forwardip > mflimit) + goto _last_literals; + + forwardh = LZ4_HASH64K_VALUE(forwardip); + ref = base + hashtable[h]; + hashtable[h] = (u16)(ip - base); + } while (A32(ref) != A32(ip)); + + /* Catch up */ + while ((ip > anchor) && (ref > (u8 *)source) + && (ip[-1] == ref[-1])) { + ip--; + ref--; + } + + /* Encode Literal length */ + length = (int)(ip - anchor); + token = op++; + /* Check output limit */ + if (unlikely(op + length + (2 + 1 + LASTLITERALS) + + (length >> 8) > oend)) + return 0; + if (length >= (int)RUN_MASK) { + *token = (RUN_MASK << ML_BITS); + len = length - RUN_MASK; + for (; len > 254 ; len -= 255) + *op++ = 255; + *op++ = (u8)len; + } else + *token = (length << ML_BITS); + + /* Copy Literals */ + LZ4_BLINDCOPY(anchor, op, length); + +_next_match: + /* Encode Offset */ + LZ4_WRITE_LITTLEENDIAN_16(op, (u16)(ip - ref)); + + /* Start Counting */ + ip += MINMATCH; + /* MinMatch verified */ + ref += MINMATCH; + anchor = ip; + + while (ip < MATCHLIMIT - (STEPSIZE - 1)) { + #if LZ4_ARCH64 + u64 diff = A64(ref) ^ A64(ip); + #else + u32 diff = A32(ref) ^ A32(ip); + #endif + + if (!diff) { + ip += STEPSIZE; + ref += STEPSIZE; + continue; + } + ip += LZ4_NBCOMMONBYTES(diff); + goto _endcount; + } + #if LZ4_ARCH64 + if ((ip < (MATCHLIMIT - 3)) && (A32(ref) == A32(ip))) { + ip += 4; + ref += 4; + } + #endif + if ((ip < (MATCHLIMIT - 1)) && (A16(ref) == A16(ip))) { + ip += 2; + ref += 2; + } + if ((ip < MATCHLIMIT) && (*ref == *ip)) + ip++; +_endcount: + + /* Encode MatchLength */ + len = (int)(ip - anchor); + /* Check output limit */ + if (unlikely(op + (1 + LASTLITERALS) + (len >> 8) > oend)) + return 0; + if (len >= (int)ML_MASK) { + *token += ML_MASK; + len -= ML_MASK; + for (; len > 509 ; len -= 510) { + *op++ = 255; + *op++ = 255; + } + if (len > 254) { + len -= 255; + *op++ = 255; + } + *op++ = (u8)len; + } else + *token += len; + + /* Test end of chunk */ + if (ip > mflimit) { + anchor = ip; + break; + } + + /* Fill table */ + hashtable[LZ4_HASH64K_VALUE(ip-2)] = (u16)(ip - 2 - base); + + /* Test next position */ + ref = base + hashtable[LZ4_HASH64K_VALUE(ip)]; + hashtable[LZ4_HASH64K_VALUE(ip)] = (u16)(ip - base); + if (A32(ref) == A32(ip)) { + token = op++; + *token = 0; + goto _next_match; + } + + /* Prepare next loop */ + anchor = ip++; + forwardh = LZ4_HASH64K_VALUE(ip); + } + +_last_literals: + /* Encode Last Literals */ + lastrun = (int)(iend - anchor); + if (op + lastrun + 1 + (lastrun - RUN_MASK + 255) / 255 > oend) + return 0; + if (lastrun >= (int)RUN_MASK) { + *op++ = (RUN_MASK << ML_BITS); + lastrun -= RUN_MASK; + for (; lastrun > 254 ; lastrun -= 255) + *op++ = 255; + *op++ = (u8)lastrun; + } else + *op++ = (lastrun << ML_BITS); + memcpy(op, anchor, iend - anchor); + op += iend - anchor; + /* End */ + return (int)(((char *)op) - dest); +} + +int lz4_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem) +{ + int ret = -1; + int out_len = 0; + + if (src_len < LZ4_64KLIMIT) + out_len = lz4_compress64kctx(wrkmem, src, dst, src_len, + lz4_compressbound(src_len)); + else + out_len = lz4_compressctx(wrkmem, src, dst, src_len, + lz4_compressbound(src_len)); + + if (out_len < 0) + goto exit; + + *dst_len = out_len; + + return 0; +exit: + return ret; +} +EXPORT_SYMBOL(lz4_compress); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("LZ4 compressor"); diff --git a/lib/lz4/lz4_decompress.c b/lib/lz4/lz4_decompress.c new file mode 100644 index 00000000000..7a85967060a --- /dev/null +++ b/lib/lz4/lz4_decompress.c @@ -0,0 +1,334 @@ +/* + * LZ4 Decompressor for Linux kernel + * + * Copyright (C) 2013, LG Electronics, Kyungsik Lee + * + * Based on LZ4 implementation by Yann Collet. + * + * LZ4 - Fast LZ compression algorithm + * Copyright (C) 2011-2012, Yann Collet. + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at : + * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + * - LZ4 source repository : http://code.google.com/p/lz4/ + */ + +#ifndef STATIC +#include +#include +#endif +#include + +#include + +#include "lz4defs.h" + +static int lz4_uncompress(const char *source, char *dest, int osize) +{ + const BYTE *ip = (const BYTE *) source; + const BYTE *ref; + BYTE *op = (BYTE *) dest; + BYTE * const oend = op + osize; + BYTE *cpy; + unsigned token; + size_t length; + size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; +#if LZ4_ARCH64 + size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; +#endif + + while (1) { + + /* get runlength */ + token = *ip++; + length = (token >> ML_BITS); + if (length == RUN_MASK) { + size_t len; + + len = *ip++; + for (; len == 255; length += 255) + len = *ip++; + if (unlikely(length > (size_t)(length + len))) + goto _output_error; + length += len; + } + + /* copy literals */ + cpy = op + length; + if (unlikely(cpy > oend - COPYLENGTH)) { + /* + * Error: not enough place for another match + * (min 4) + 5 literals + */ + if (cpy != oend) + goto _output_error; + + memcpy(op, ip, length); + ip += length; + break; /* EOF */ + } + LZ4_WILDCOPY(ip, op, cpy); + ip -= (op - cpy); + op = cpy; + + /* get offset */ + LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); + ip += 2; + + /* Error: offset create reference outside destination buffer */ + if (unlikely(ref < (BYTE *const) dest)) + goto _output_error; + + /* get matchlength */ + length = token & ML_MASK; + if (length == ML_MASK) { + for (; *ip == 255; length += 255) + ip++; + if (unlikely(length > (size_t)(length + *ip))) + goto _output_error; + length += *ip++; + } + + /* copy repeated sequence */ + if (unlikely((op - ref) < STEPSIZE)) { +#if LZ4_ARCH64 + size_t dec64 = dec64table[op - ref]; +#else + const int dec64 = 0; +#endif + op[0] = ref[0]; + op[1] = ref[1]; + op[2] = ref[2]; + op[3] = ref[3]; + op += 4; + ref += 4; + ref -= dec32table[op-ref]; + PUT4(ref, op); + op += STEPSIZE - 4; + ref -= dec64; + } else { + LZ4_COPYSTEP(ref, op); + } + cpy = op + length - (STEPSIZE - 4); + if (cpy > (oend - COPYLENGTH)) { + + /* Error: request to write beyond destination buffer */ + if (cpy > oend) + goto _output_error; + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; + op = cpy; + /* + * Check EOF (should never happen, since last 5 bytes + * are supposed to be literals) + */ + if (op == oend) + goto _output_error; + continue; + } + LZ4_SECURECOPY(ref, op, cpy); + op = cpy; /* correction */ + } + /* end of decoding */ + return (int) (((char *)ip) - source); + + /* write overflow error detected */ +_output_error: + return -1; +} + +static int lz4_uncompress_unknownoutputsize(const char *source, char *dest, + int isize, size_t maxoutputsize) +{ + const BYTE *ip = (const BYTE *) source; + const BYTE *const iend = ip + isize; + const BYTE *ref; + + + BYTE *op = (BYTE *) dest; + BYTE * const oend = op + maxoutputsize; + BYTE *cpy; + + size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; +#if LZ4_ARCH64 + size_t dec64table[] = {0, 0, 0, -1, 0, 1, 2, 3}; +#endif + + /* Main Loop */ + while (ip < iend) { + + unsigned token; + size_t length; + + /* get runlength */ + token = *ip++; + length = (token >> ML_BITS); + if (length == RUN_MASK) { + int s = 255; + while ((ip < iend) && (s == 255)) { + s = *ip++; + if (unlikely(length > (size_t)(length + s))) + goto _output_error; + length += s; + } + } + /* copy literals */ + cpy = op + length; + if ((cpy > oend - COPYLENGTH) || + (ip + length > iend - COPYLENGTH)) { + + if (cpy > oend) + goto _output_error;/* writes beyond buffer */ + + if (ip + length != iend) + goto _output_error;/* + * Error: LZ4 format requires + * to consume all input + * at this stage + */ + memcpy(op, ip, length); + op += length; + break;/* Necessarily EOF, due to parsing restrictions */ + } + LZ4_WILDCOPY(ip, op, cpy); + ip -= (op - cpy); + op = cpy; + + /* get offset */ + LZ4_READ_LITTLEENDIAN_16(ref, cpy, ip); + ip += 2; + if (ref < (BYTE * const) dest) + goto _output_error; + /* + * Error : offset creates reference + * outside of destination buffer + */ + + /* get matchlength */ + length = (token & ML_MASK); + if (length == ML_MASK) { + while (ip < iend) { + int s = *ip++; + if (unlikely(length > (size_t)(length + s))) + goto _output_error; + length += s; + if (s == 255) + continue; + break; + } + } + + /* copy repeated sequence */ + if (unlikely((op - ref) < STEPSIZE)) { +#if LZ4_ARCH64 + size_t dec64 = dec64table[op - ref]; +#else + const int dec64 = 0; +#endif + op[0] = ref[0]; + op[1] = ref[1]; + op[2] = ref[2]; + op[3] = ref[3]; + op += 4; + ref += 4; + ref -= dec32table[op - ref]; + PUT4(ref, op); + op += STEPSIZE - 4; + ref -= dec64; + } else { + LZ4_COPYSTEP(ref, op); + } + cpy = op + length - (STEPSIZE-4); + if (cpy > oend - COPYLENGTH) { + if (cpy > oend) + goto _output_error; /* write outside of buf */ + + LZ4_SECURECOPY(ref, op, (oend - COPYLENGTH)); + while (op < cpy) + *op++ = *ref++; + op = cpy; + /* + * Check EOF (should never happen, since last 5 bytes + * are supposed to be literals) + */ + if (op == oend) + goto _output_error; + continue; + } + LZ4_SECURECOPY(ref, op, cpy); + op = cpy; /* correction */ + } + /* end of decoding */ + return (int) (((char *) op) - dest); + + /* write overflow error detected */ +_output_error: + return -1; +} + +int lz4_decompress(const unsigned char *src, size_t *src_len, + unsigned char *dest, size_t actual_dest_len) +{ + int ret = -1; + int input_len = 0; + + input_len = lz4_uncompress(src, dest, actual_dest_len); + if (input_len < 0) + goto exit_0; + *src_len = input_len; + + return 0; +exit_0: + return ret; +} +#ifndef STATIC +EXPORT_SYMBOL(lz4_decompress); +#endif + +int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len, + unsigned char *dest, size_t *dest_len) +{ + int ret = -1; + int out_len = 0; + + out_len = lz4_uncompress_unknownoutputsize(src, dest, src_len, + *dest_len); + if (out_len < 0) + goto exit_0; + *dest_len = out_len; + + return 0; +exit_0: + return ret; +} +#ifndef STATIC +EXPORT_SYMBOL(lz4_decompress_unknownoutputsize); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("LZ4 Decompressor"); +#endif diff --git a/lib/lz4/lz4defs.h b/lib/lz4/lz4defs.h new file mode 100644 index 00000000000..abcecdc2d0f --- /dev/null +++ b/lib/lz4/lz4defs.h @@ -0,0 +1,156 @@ +/* + * lz4defs.h -- architecture specific defines + * + * Copyright (C) 2013, LG Electronics, Kyungsik Lee + * + * 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. + */ + +/* + * Detects 64 bits mode + */ +#if (defined(__x86_64__) || defined(__x86_64) || defined(__amd64__) \ + || defined(__ppc64__) || defined(__LP64__)) +#define LZ4_ARCH64 1 +#else +#define LZ4_ARCH64 0 +#endif + +/* + * Architecture-specific macros + */ +#define BYTE u8 +typedef struct _U16_S { u16 v; } U16_S; +typedef struct _U32_S { u32 v; } U32_S; +typedef struct _U64_S { u64 v; } U64_S; +#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) \ + || defined(CONFIG_ARM) && __LINUX_ARM_ARCH__ >= 6 \ + && defined(ARM_EFFICIENT_UNALIGNED_ACCESS) + +#define A16(x) (((U16_S *)(x))->v) +#define A32(x) (((U32_S *)(x))->v) +#define A64(x) (((U64_S *)(x))->v) + +#define PUT4(s, d) (A32(d) = A32(s)) +#define PUT8(s, d) (A64(d) = A64(s)) +#define LZ4_WRITE_LITTLEENDIAN_16(p, v) \ + do { \ + A16(p) = v; \ + p += 2; \ + } while (0) +#else /* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS */ + +#define A64(x) get_unaligned((u64 *)&(((U16_S *)(x))->v)) +#define A32(x) get_unaligned((u32 *)&(((U16_S *)(x))->v)) +#define A16(x) get_unaligned((u16 *)&(((U16_S *)(x))->v)) + +#define PUT4(s, d) \ + put_unaligned(get_unaligned((const u32 *) s), (u32 *) d) +#define PUT8(s, d) \ + put_unaligned(get_unaligned((const u64 *) s), (u64 *) d) + +#define LZ4_WRITE_LITTLEENDIAN_16(p, v) \ + do { \ + put_unaligned(v, (u16 *)(p)); \ + p += 2; \ + } while (0) +#endif + +#define COPYLENGTH 8 +#define ML_BITS 4 +#define ML_MASK ((1U << ML_BITS) - 1) +#define RUN_BITS (8 - ML_BITS) +#define RUN_MASK ((1U << RUN_BITS) - 1) +#define MEMORY_USAGE 14 +#define MINMATCH 4 +#define SKIPSTRENGTH 6 +#define LASTLITERALS 5 +#define MFLIMIT (COPYLENGTH + MINMATCH) +#define MINLENGTH (MFLIMIT + 1) +#define MAXD_LOG 16 +#define MAXD (1 << MAXD_LOG) +#define MAXD_MASK (u32)(MAXD - 1) +#define MAX_DISTANCE (MAXD - 1) +#define HASH_LOG (MAXD_LOG - 1) +#define HASHTABLESIZE (1 << HASH_LOG) +#define MAX_NB_ATTEMPTS 256 +#define OPTIMAL_ML (int)((ML_MASK-1)+MINMATCH) +#define LZ4_64KLIMIT ((1<<16) + (MFLIMIT - 1)) +#define HASHLOG64K ((MEMORY_USAGE - 2) + 1) +#define HASH64KTABLESIZE (1U << HASHLOG64K) +#define LZ4_HASH_VALUE(p) (((A32(p)) * 2654435761U) >> \ + ((MINMATCH * 8) - (MEMORY_USAGE-2))) +#define LZ4_HASH64K_VALUE(p) (((A32(p)) * 2654435761U) >> \ + ((MINMATCH * 8) - HASHLOG64K)) +#define HASH_VALUE(p) (((A32(p)) * 2654435761U) >> \ + ((MINMATCH * 8) - HASH_LOG)) + +#if LZ4_ARCH64/* 64-bit */ +#define STEPSIZE 8 + +#define LZ4_COPYSTEP(s, d) \ + do { \ + PUT8(s, d); \ + d += 8; \ + s += 8; \ + } while (0) + +#define LZ4_COPYPACKET(s, d) LZ4_COPYSTEP(s, d) + +#define LZ4_SECURECOPY(s, d, e) \ + do { \ + if (d < e) { \ + LZ4_WILDCOPY(s, d, e); \ + } \ + } while (0) +#define HTYPE u32 + +#ifdef __BIG_ENDIAN +#define LZ4_NBCOMMONBYTES(val) (__builtin_clzll(val) >> 3) +#else +#define LZ4_NBCOMMONBYTES(val) (__builtin_ctzll(val) >> 3) +#endif + +#else /* 32-bit */ +#define STEPSIZE 4 + +#define LZ4_COPYSTEP(s, d) \ + do { \ + PUT4(s, d); \ + d += 4; \ + s += 4; \ + } while (0) + +#define LZ4_COPYPACKET(s, d) \ + do { \ + LZ4_COPYSTEP(s, d); \ + LZ4_COPYSTEP(s, d); \ + } while (0) + +#define LZ4_SECURECOPY LZ4_WILDCOPY +#define HTYPE const u8* + +#ifdef __BIG_ENDIAN +#define LZ4_NBCOMMONBYTES(val) (__builtin_clz(val) >> 3) +#else +#define LZ4_NBCOMMONBYTES(val) (__builtin_ctz(val) >> 3) +#endif + +#endif + +#define LZ4_READ_LITTLEENDIAN_16(d, s, p) \ + (d = s - get_unaligned_le16(p)) + +#define LZ4_WILDCOPY(s, d, e) \ + do { \ + LZ4_COPYPACKET(s, d); \ + } while (d < e) + +#define LZ4_BLINDCOPY(s, d, l) \ + do { \ + u8 *e = (d) + l; \ + LZ4_WILDCOPY(s, d, e); \ + d = e; \ + } while (0) diff --git a/lib/lz4/lz4hc_compress.c b/lib/lz4/lz4hc_compress.c new file mode 100644 index 00000000000..f344f76b655 --- /dev/null +++ b/lib/lz4/lz4hc_compress.c @@ -0,0 +1,539 @@ +/* + * LZ4 HC - High Compression Mode of LZ4 + * Copyright (C) 2011-2012, Yann Collet. + * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * You can contact the author at : + * - LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html + * - LZ4 source repository : http://code.google.com/p/lz4/ + * + * Changed for kernel use by: + * Chanho Min + */ + +#include +#include +#include +#include +#include "lz4defs.h" + +struct lz4hc_data { + const u8 *base; + HTYPE hashtable[HASHTABLESIZE]; + u16 chaintable[MAXD]; + const u8 *nexttoupdate; +} __attribute__((__packed__)); + +static inline int lz4hc_init(struct lz4hc_data *hc4, const u8 *base) +{ + memset((void *)hc4->hashtable, 0, sizeof(hc4->hashtable)); + memset(hc4->chaintable, 0xFF, sizeof(hc4->chaintable)); + +#if LZ4_ARCH64 + hc4->nexttoupdate = base + 1; +#else + hc4->nexttoupdate = base; +#endif + hc4->base = base; + return 1; +} + +/* Update chains up to ip (excluded) */ +static inline void lz4hc_insert(struct lz4hc_data *hc4, const u8 *ip) +{ + u16 *chaintable = hc4->chaintable; + HTYPE *hashtable = hc4->hashtable; +#if LZ4_ARCH64 + const BYTE * const base = hc4->base; +#else + const int base = 0; +#endif + + while (hc4->nexttoupdate < ip) { + const u8 *p = hc4->nexttoupdate; + size_t delta = p - (hashtable[HASH_VALUE(p)] + base); + if (delta > MAX_DISTANCE) + delta = MAX_DISTANCE; + chaintable[(size_t)(p) & MAXD_MASK] = (u16)delta; + hashtable[HASH_VALUE(p)] = (p) - base; + hc4->nexttoupdate++; + } +} + +static inline size_t lz4hc_commonlength(const u8 *p1, const u8 *p2, + const u8 *const matchlimit) +{ + const u8 *p1t = p1; + + while (p1t < matchlimit - (STEPSIZE - 1)) { +#if LZ4_ARCH64 + u64 diff = A64(p2) ^ A64(p1t); +#else + u32 diff = A32(p2) ^ A32(p1t); +#endif + if (!diff) { + p1t += STEPSIZE; + p2 += STEPSIZE; + continue; + } + p1t += LZ4_NBCOMMONBYTES(diff); + return p1t - p1; + } +#if LZ4_ARCH64 + if ((p1t < (matchlimit-3)) && (A32(p2) == A32(p1t))) { + p1t += 4; + p2 += 4; + } +#endif + + if ((p1t < (matchlimit - 1)) && (A16(p2) == A16(p1t))) { + p1t += 2; + p2 += 2; + } + if ((p1t < matchlimit) && (*p2 == *p1t)) + p1t++; + return p1t - p1; +} + +static inline int lz4hc_insertandfindbestmatch(struct lz4hc_data *hc4, + const u8 *ip, const u8 *const matchlimit, const u8 **matchpos) +{ + u16 *const chaintable = hc4->chaintable; + HTYPE *const hashtable = hc4->hashtable; + const u8 *ref; +#if LZ4_ARCH64 + const BYTE * const base = hc4->base; +#else + const int base = 0; +#endif + int nbattempts = MAX_NB_ATTEMPTS; + size_t repl = 0, ml = 0; + u16 delta; + + /* HC4 match finder */ + lz4hc_insert(hc4, ip); + ref = hashtable[HASH_VALUE(ip)] + base; + + /* potential repetition */ + if (ref >= ip-4) { + /* confirmed */ + if (A32(ref) == A32(ip)) { + delta = (u16)(ip-ref); + repl = ml = lz4hc_commonlength(ip + MINMATCH, + ref + MINMATCH, matchlimit) + MINMATCH; + *matchpos = ref; + } + ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK]; + } + + while ((ref >= ip - MAX_DISTANCE) && nbattempts) { + nbattempts--; + if (*(ref + ml) == *(ip + ml)) { + if (A32(ref) == A32(ip)) { + size_t mlt = + lz4hc_commonlength(ip + MINMATCH, + ref + MINMATCH, matchlimit) + MINMATCH; + if (mlt > ml) { + ml = mlt; + *matchpos = ref; + } + } + } + ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK]; + } + + /* Complete table */ + if (repl) { + const BYTE *ptr = ip; + const BYTE *end; + end = ip + repl - (MINMATCH-1); + /* Pre-Load */ + while (ptr < end - delta) { + chaintable[(size_t)(ptr) & MAXD_MASK] = delta; + ptr++; + } + do { + chaintable[(size_t)(ptr) & MAXD_MASK] = delta; + /* Head of chain */ + hashtable[HASH_VALUE(ptr)] = (ptr) - base; + ptr++; + } while (ptr < end); + hc4->nexttoupdate = end; + } + + return (int)ml; +} + +static inline int lz4hc_insertandgetwidermatch(struct lz4hc_data *hc4, + const u8 *ip, const u8 *startlimit, const u8 *matchlimit, int longest, + const u8 **matchpos, const u8 **startpos) +{ + u16 *const chaintable = hc4->chaintable; + HTYPE *const hashtable = hc4->hashtable; +#if LZ4_ARCH64 + const BYTE * const base = hc4->base; +#else + const int base = 0; +#endif + const u8 *ref; + int nbattempts = MAX_NB_ATTEMPTS; + int delta = (int)(ip - startlimit); + + /* First Match */ + lz4hc_insert(hc4, ip); + ref = hashtable[HASH_VALUE(ip)] + base; + + while ((ref >= ip - MAX_DISTANCE) && (ref >= hc4->base) + && (nbattempts)) { + nbattempts--; + if (*(startlimit + longest) == *(ref - delta + longest)) { + if (A32(ref) == A32(ip)) { + const u8 *reft = ref + MINMATCH; + const u8 *ipt = ip + MINMATCH; + const u8 *startt = ip; + + while (ipt < matchlimit-(STEPSIZE - 1)) { + #if LZ4_ARCH64 + u64 diff = A64(reft) ^ A64(ipt); + #else + u32 diff = A32(reft) ^ A32(ipt); + #endif + + if (!diff) { + ipt += STEPSIZE; + reft += STEPSIZE; + continue; + } + ipt += LZ4_NBCOMMONBYTES(diff); + goto _endcount; + } + #if LZ4_ARCH64 + if ((ipt < (matchlimit - 3)) + && (A32(reft) == A32(ipt))) { + ipt += 4; + reft += 4; + } + ipt += 2; + #endif + if ((ipt < (matchlimit - 1)) + && (A16(reft) == A16(ipt))) { + reft += 2; + } + if ((ipt < matchlimit) && (*reft == *ipt)) + ipt++; +_endcount: + reft = ref; + + while ((startt > startlimit) + && (reft > hc4->base) + && (startt[-1] == reft[-1])) { + startt--; + reft--; + } + + if ((ipt - startt) > longest) { + longest = (int)(ipt - startt); + *matchpos = reft; + *startpos = startt; + } + } + } + ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK]; + } + return longest; +} + +static inline int lz4_encodesequence(const u8 **ip, u8 **op, const u8 **anchor, + int ml, const u8 *ref) +{ + int length, len; + u8 *token; + + /* Encode Literal length */ + length = (int)(*ip - *anchor); + token = (*op)++; + if (length >= (int)RUN_MASK) { + *token = (RUN_MASK << ML_BITS); + len = length - RUN_MASK; + for (; len > 254 ; len -= 255) + *(*op)++ = 255; + *(*op)++ = (u8)len; + } else + *token = (length << ML_BITS); + + /* Copy Literals */ + LZ4_BLINDCOPY(*anchor, *op, length); + + /* Encode Offset */ + LZ4_WRITE_LITTLEENDIAN_16(*op, (u16)(*ip - ref)); + + /* Encode MatchLength */ + len = (int)(ml - MINMATCH); + if (len >= (int)ML_MASK) { + *token += ML_MASK; + len -= ML_MASK; + for (; len > 509 ; len -= 510) { + *(*op)++ = 255; + *(*op)++ = 255; + } + if (len > 254) { + len -= 255; + *(*op)++ = 255; + } + *(*op)++ = (u8)len; + } else + *token += len; + + /* Prepare next loop */ + *ip += ml; + *anchor = *ip; + + return 0; +} + +static int lz4_compresshcctx(struct lz4hc_data *ctx, + const char *source, + char *dest, + int isize) +{ + const u8 *ip = (const u8 *)source; + const u8 *anchor = ip; + const u8 *const iend = ip + isize; + const u8 *const mflimit = iend - MFLIMIT; + const u8 *const matchlimit = (iend - LASTLITERALS); + + u8 *op = (u8 *)dest; + + int ml, ml2, ml3, ml0; + const u8 *ref = NULL; + const u8 *start2 = NULL; + const u8 *ref2 = NULL; + const u8 *start3 = NULL; + const u8 *ref3 = NULL; + const u8 *start0; + const u8 *ref0; + int lastrun; + + ip++; + + /* Main Loop */ + while (ip < mflimit) { + ml = lz4hc_insertandfindbestmatch(ctx, ip, matchlimit, (&ref)); + if (!ml) { + ip++; + continue; + } + + /* saved, in case we would skip too much */ + start0 = ip; + ref0 = ref; + ml0 = ml; +_search2: + if (ip+ml < mflimit) + ml2 = lz4hc_insertandgetwidermatch(ctx, ip + ml - 2, + ip + 1, matchlimit, ml, &ref2, &start2); + else + ml2 = ml; + /* No better match */ + if (ml2 == ml) { + lz4_encodesequence(&ip, &op, &anchor, ml, ref); + continue; + } + + if (start0 < ip) { + /* empirical */ + if (start2 < ip + ml0) { + ip = start0; + ref = ref0; + ml = ml0; + } + } + /* + * Here, start0==ip + * First Match too small : removed + */ + if ((start2 - ip) < 3) { + ml = ml2; + ip = start2; + ref = ref2; + goto _search2; + } + +_search3: + /* + * Currently we have : + * ml2 > ml1, and + * ip1+3 <= ip2 (usually < ip1+ml1) + */ + if ((start2 - ip) < OPTIMAL_ML) { + int correction; + int new_ml = ml; + if (new_ml > OPTIMAL_ML) + new_ml = OPTIMAL_ML; + if (ip + new_ml > start2 + ml2 - MINMATCH) + new_ml = (int)(start2 - ip) + ml2 - MINMATCH; + correction = new_ml - (int)(start2 - ip); + if (correction > 0) { + start2 += correction; + ref2 += correction; + ml2 -= correction; + } + } + /* + * Now, we have start2 = ip+new_ml, + * with new_ml=min(ml, OPTIMAL_ML=18) + */ + if (start2 + ml2 < mflimit) + ml3 = lz4hc_insertandgetwidermatch(ctx, + start2 + ml2 - 3, start2, matchlimit, + ml2, &ref3, &start3); + else + ml3 = ml2; + + /* No better match : 2 sequences to encode */ + if (ml3 == ml2) { + /* ip & ref are known; Now for ml */ + if (start2 < ip+ml) + ml = (int)(start2 - ip); + + /* Now, encode 2 sequences */ + lz4_encodesequence(&ip, &op, &anchor, ml, ref); + ip = start2; + lz4_encodesequence(&ip, &op, &anchor, ml2, ref2); + continue; + } + + /* Not enough space for match 2 : remove it */ + if (start3 < ip + ml + 3) { + /* + * can write Seq1 immediately ==> Seq2 is removed, + * so Seq3 becomes Seq1 + */ + if (start3 >= (ip + ml)) { + if (start2 < ip + ml) { + int correction = + (int)(ip + ml - start2); + start2 += correction; + ref2 += correction; + ml2 -= correction; + if (ml2 < MINMATCH) { + start2 = start3; + ref2 = ref3; + ml2 = ml3; + } + } + + lz4_encodesequence(&ip, &op, &anchor, ml, ref); + ip = start3; + ref = ref3; + ml = ml3; + + start0 = start2; + ref0 = ref2; + ml0 = ml2; + goto _search2; + } + + start2 = start3; + ref2 = ref3; + ml2 = ml3; + goto _search3; + } + + /* + * OK, now we have 3 ascending matches; let's write at least + * the first one ip & ref are known; Now for ml + */ + if (start2 < ip + ml) { + if ((start2 - ip) < (int)ML_MASK) { + int correction; + if (ml > OPTIMAL_ML) + ml = OPTIMAL_ML; + if (ip + ml > start2 + ml2 - MINMATCH) + ml = (int)(start2 - ip) + ml2 + - MINMATCH; + correction = ml - (int)(start2 - ip); + if (correction > 0) { + start2 += correction; + ref2 += correction; + ml2 -= correction; + } + } else + ml = (int)(start2 - ip); + } + lz4_encodesequence(&ip, &op, &anchor, ml, ref); + + ip = start2; + ref = ref2; + ml = ml2; + + start2 = start3; + ref2 = ref3; + ml2 = ml3; + + goto _search3; + } + + /* Encode Last Literals */ + lastrun = (int)(iend - anchor); + if (lastrun >= (int)RUN_MASK) { + *op++ = (RUN_MASK << ML_BITS); + lastrun -= RUN_MASK; + for (; lastrun > 254 ; lastrun -= 255) + *op++ = 255; + *op++ = (u8) lastrun; + } else + *op++ = (lastrun << ML_BITS); + memcpy(op, anchor, iend - anchor); + op += iend - anchor; + /* End */ + return (int) (((char *)op) - dest); +} + +int lz4hc_compress(const unsigned char *src, size_t src_len, + unsigned char *dst, size_t *dst_len, void *wrkmem) +{ + int ret = -1; + int out_len = 0; + + struct lz4hc_data *hc4 = (struct lz4hc_data *)wrkmem; + lz4hc_init(hc4, (const u8 *)src); + out_len = lz4_compresshcctx((struct lz4hc_data *)hc4, (const u8 *)src, + (char *)dst, (int)src_len); + + if (out_len < 0) + goto exit; + + *dst_len = out_len; + return 0; + +exit: + return ret; +} +EXPORT_SYMBOL(lz4hc_compress); + +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_DESCRIPTION("LZ4HC compressor"); diff --git a/lib/memcopy.c b/lib/memcopy.c new file mode 100644 index 00000000000..d2d3376f738 --- /dev/null +++ b/lib/memcopy.c @@ -0,0 +1,403 @@ +/* + * memcopy.c -- subroutines for memory copy functions. + * + * 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.1 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. + * + * 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., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * The code is derived from the GNU C Library. + * Copyright (C) 1991, 1992, 1993, 1997, 2004 Free Software Foundation, Inc. + */ + +/* BE VERY CAREFUL IF YOU CHANGE THIS CODE...! */ + +#include + +/* + * _wordcopy_fwd_aligned -- Copy block beginning at SRCP to block beginning + * at DSTP with LEN `op_t' words (not LEN bytes!). + * Both SRCP and DSTP should be aligned for memory operations on `op_t's. + */ +void _wordcopy_fwd_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1; + + switch (len % 8) { + case 2: + a0 = ((op_t *) srcp)[0]; + srcp -= 6 * OPSIZ; + dstp -= 7 * OPSIZ; + len += 6; + goto do1; + case 3: + a1 = ((op_t *) srcp)[0]; + srcp -= 5 * OPSIZ; + dstp -= 6 * OPSIZ; + len += 5; + goto do2; + case 4: + a0 = ((op_t *) srcp)[0]; + srcp -= 4 * OPSIZ; + dstp -= 5 * OPSIZ; + len += 4; + goto do3; + case 5: + a1 = ((op_t *) srcp)[0]; + srcp -= 3 * OPSIZ; + dstp -= 4 * OPSIZ; + len += 3; + goto do4; + case 6: + a0 = ((op_t *) srcp)[0]; + srcp -= 2 * OPSIZ; + dstp -= 3 * OPSIZ; + len += 2; + goto do5; + case 7: + a1 = ((op_t *) srcp)[0]; + srcp -= 1 * OPSIZ; + dstp -= 2 * OPSIZ; + len += 1; + goto do6; + case 0: + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + return; + a0 = ((op_t *) srcp)[0]; + srcp -= 0 * OPSIZ; + dstp -= 1 * OPSIZ; + goto do7; + case 1: + a1 = ((op_t *) srcp)[0]; + srcp -=-1 * OPSIZ; + dstp -= 0 * OPSIZ; + len -= 1; + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + goto do0; + goto do8; /* No-op. */ + } + + do { +do8: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = a1; +do7: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = a0; +do6: + a0 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = a1; +do5: + a1 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = a0; +do4: + a0 = ((op_t *) srcp)[4]; + ((op_t *) dstp)[4] = a1; +do3: + a1 = ((op_t *) srcp)[5]; + ((op_t *) dstp)[5] = a0; +do2: + a0 = ((op_t *) srcp)[6]; + ((op_t *) dstp)[6] = a1; +do1: + a1 = ((op_t *) srcp)[7]; + ((op_t *) dstp)[7] = a0; + + srcp += 8 * OPSIZ; + dstp += 8 * OPSIZ; + len -= 8; + } while (len != 0); + + /* + * This is the right position for do0. Please don't move it into + * the loop. + */ +do0: + ((op_t *) dstp)[0] = a1; +} + +/* + * _wordcopy_fwd_dest_aligned -- Copy block beginning at SRCP to block + * beginning at DSTP with LEN `op_t' words (not LEN bytes!). DSTP should + * be aligned for memory operations on `op_t's, but SRCP must *not* be aligned. + */ + +void _wordcopy_fwd_dest_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1, a2, a3; + int sh_1, sh_2; + + /* + * Calculate how to shift a word read at the memory operation aligned + * srcp to make it aligned for copy. + */ + sh_1 = 8 * (srcp % OPSIZ); + sh_2 = 8 * OPSIZ - sh_1; + + /* + * Make SRCP aligned by rounding it down to the beginning of the `op_t' + * it points in the middle of. + */ + srcp &= -OPSIZ; + + switch (len % 4) { + case 2: + a1 = ((op_t *) srcp)[0]; + a2 = ((op_t *) srcp)[1]; + srcp -= 1 * OPSIZ; + dstp -= 3 * OPSIZ; + len += 2; + goto do1; + case 3: + a0 = ((op_t *) srcp)[0]; + a1 = ((op_t *) srcp)[1]; + srcp -= 0 * OPSIZ; + dstp -= 2 * OPSIZ; + len += 1; + goto do2; + case 0: + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + return; + a3 = ((op_t *) srcp)[0]; + a0 = ((op_t *) srcp)[1]; + srcp -=-1 * OPSIZ; + dstp -= 1 * OPSIZ; + len += 0; + goto do3; + case 1: + a2 = ((op_t *) srcp)[0]; + a3 = ((op_t *) srcp)[1]; + srcp -=-2 * OPSIZ; + dstp -= 0 * OPSIZ; + len -= 1; + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do { +do4: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); +do3: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = MERGE (a3, sh_1, a0, sh_2); +do2: + a2 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = MERGE (a0, sh_1, a1, sh_2); +do1: + a3 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = MERGE (a1, sh_1, a2, sh_2); + + srcp += 4 * OPSIZ; + dstp += 4 * OPSIZ; + len -= 4; + } while (len != 0); + + /* + * This is the right position for do0. Please don't move it into + * the loop. + */ +do0: + ((op_t *) dstp)[0] = MERGE (a2, sh_1, a3, sh_2); +} + +/* + * _wordcopy_bwd_aligned -- Copy block finishing right before + * SRCP to block finishing right before DSTP with LEN `op_t' words (not LEN + * bytes!). Both SRCP and DSTP should be aligned for memory operations + * on `op_t's. + */ +void _wordcopy_bwd_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1; + + switch (len % 8) { + case 2: + srcp -= 2 * OPSIZ; + dstp -= 1 * OPSIZ; + a0 = ((op_t *) srcp)[1]; + len += 6; + goto do1; + case 3: + srcp -= 3 * OPSIZ; + dstp -= 2 * OPSIZ; + a1 = ((op_t *) srcp)[2]; + len += 5; + goto do2; + case 4: + srcp -= 4 * OPSIZ; + dstp -= 3 * OPSIZ; + a0 = ((op_t *) srcp)[3]; + len += 4; + goto do3; + case 5: + srcp -= 5 * OPSIZ; + dstp -= 4 * OPSIZ; + a1 = ((op_t *) srcp)[4]; + len += 3; + goto do4; + case 6: + srcp -= 6 * OPSIZ; + dstp -= 5 * OPSIZ; + a0 = ((op_t *) srcp)[5]; + len += 2; + goto do5; + case 7: + srcp -= 7 * OPSIZ; + dstp -= 6 * OPSIZ; + a1 = ((op_t *) srcp)[6]; + len += 1; + goto do6; + case 0: + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + return; + srcp -= 8 * OPSIZ; + dstp -= 7 * OPSIZ; + a0 = ((op_t *) srcp)[7]; + goto do7; + case 1: + srcp -= 9 * OPSIZ; + dstp -= 8 * OPSIZ; + a1 = ((op_t *) srcp)[8]; + len -= 1; + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + goto do0; + goto do8; /* No-op. */ + } + + do { +do8: + a0 = ((op_t *) srcp)[7]; + ((op_t *) dstp)[7] = a1; +do7: + a1 = ((op_t *) srcp)[6]; + ((op_t *) dstp)[6] = a0; +do6: + a0 = ((op_t *) srcp)[5]; + ((op_t *) dstp)[5] = a1; +do5: + a1 = ((op_t *) srcp)[4]; + ((op_t *) dstp)[4] = a0; +do4: + a0 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = a1; +do3: + a1 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = a0; +do2: + a0 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = a1; +do1: + a1 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = a0; + + srcp -= 8 * OPSIZ; + dstp -= 8 * OPSIZ; + len -= 8; + } while (len != 0); + + /* + * This is the right position for do0. Please don't move it into + * the loop. + */ +do0: + ((op_t *) dstp)[7] = a1; +} + +/* + * _wordcopy_bwd_dest_aligned -- Copy block finishing right before SRCP to + * block finishing right before DSTP with LEN `op_t' words (not LEN bytes!). + * DSTP should be aligned for memory operations on `op_t', but SRCP must *not* + * be aligned. + */ +void _wordcopy_bwd_dest_aligned (long int dstp, long int srcp, size_t len) +{ + op_t a0, a1, a2, a3; + int sh_1, sh_2; + + /* + * Calculate how to shift a word read at the memory operation aligned + * srcp to make it aligned for copy. + */ + + sh_1 = 8 * (srcp % OPSIZ); + sh_2 = 8 * OPSIZ - sh_1; + + /* + * Make srcp aligned by rounding it down to the beginning of the op_t + * it points in the middle of. + */ + srcp &= -OPSIZ; + srcp += OPSIZ; + + switch (len % 4) { + case 2: + srcp -= 3 * OPSIZ; + dstp -= 1 * OPSIZ; + a2 = ((op_t *) srcp)[2]; + a1 = ((op_t *) srcp)[1]; + len += 2; + goto do1; + case 3: + srcp -= 4 * OPSIZ; + dstp -= 2 * OPSIZ; + a3 = ((op_t *) srcp)[3]; + a2 = ((op_t *) srcp)[2]; + len += 1; + goto do2; + case 0: + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + return; + srcp -= 5 * OPSIZ; + dstp -= 3 * OPSIZ; + a0 = ((op_t *) srcp)[4]; + a3 = ((op_t *) srcp)[3]; + goto do3; + case 1: + srcp -= 6 * OPSIZ; + dstp -= 4 * OPSIZ; + a1 = ((op_t *) srcp)[5]; + a0 = ((op_t *) srcp)[4]; + len -= 1; + if (OP_T_THRESHOLD <= 3 * OPSIZ && len == 0) + goto do0; + goto do4; /* No-op. */ + } + + do { +do4: + a3 = ((op_t *) srcp)[3]; + ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); +do3: + a2 = ((op_t *) srcp)[2]; + ((op_t *) dstp)[2] = MERGE (a3, sh_1, a0, sh_2); +do2: + a1 = ((op_t *) srcp)[1]; + ((op_t *) dstp)[1] = MERGE (a2, sh_1, a3, sh_2); +do1: + a0 = ((op_t *) srcp)[0]; + ((op_t *) dstp)[0] = MERGE (a1, sh_1, a2, sh_2); + + srcp -= 4 * OPSIZ; + dstp -= 4 * OPSIZ; + len -= 4; + } while (len != 0); + + /* + * This is the right position for do0. Please don't move it into + * the loop. + */ +do0: + ((op_t *) dstp)[3] = MERGE (a0, sh_1, a1, sh_2); +} + diff --git a/lib/sradix-tree.c b/lib/sradix-tree.c new file mode 100644 index 00000000000..8d0632917e8 --- /dev/null +++ b/lib/sradix-tree.c @@ -0,0 +1,476 @@ +#include +#include +#include +#include +#include +#include +#include + +static inline int sradix_node_full(struct sradix_tree_root *root, struct sradix_tree_node *node) +{ + return node->fulls == root->stores_size || + (node->height == 1 && node->count == root->stores_size); +} + +/* + * Extend a sradix tree so it can store key @index. + */ +static int sradix_tree_extend(struct sradix_tree_root *root, unsigned long index) +{ + struct sradix_tree_node *node; + unsigned int height; + + if (unlikely(root->rnode == NULL)) { + if (!(node = root->alloc())) + return -ENOMEM; + + node->height = 1; + root->rnode = node; + root->height = 1; + } + + /* Figure out what the height should be. */ + height = root->height; + index >>= root->shift * height; + + while (index) { + index >>= root->shift; + height++; + } + + while (height > root->height) { + unsigned int newheight; + if (!(node = root->alloc())) + return -ENOMEM; + + /* Increase the height. */ + node->stores[0] = root->rnode; + root->rnode->parent = node; + if (root->extend) + root->extend(node, root->rnode); + + newheight = root->height + 1; + node->height = newheight; + node->count = 1; + if (sradix_node_full(root, root->rnode)) + node->fulls = 1; + + root->rnode = node; + root->height = newheight; + } + + return 0; +} + +/* + * Search the next item from the current node, that is not NULL + * and can satify root->iter(). + */ +void *sradix_tree_next(struct sradix_tree_root *root, + struct sradix_tree_node *node, unsigned long index, + int (*iter)(void *item, unsigned long height)) +{ + unsigned long offset; + void *item; + + if (unlikely(node == NULL)) { + node = root->rnode; + for (offset = 0; offset < root->stores_size; offset++) { + item = node->stores[offset]; + if (item && (!iter || iter(item, node->height))) + break; + } + + if (unlikely(offset >= root->stores_size)) + return NULL; + + if (node->height == 1) + return item; + else + goto go_down; + } + + while (node) { + offset = (index & root->mask) + 1; + for (;offset < root->stores_size; offset++) { + item = node->stores[offset]; + if (item && (!iter || iter(item, node->height))) + break; + } + + if (offset < root->stores_size) + break; + + node = node->parent; + index >>= root->shift; + } + + if (!node) + return NULL; + + while (node->height > 1) { +go_down: + node = item; + for (offset = 0; offset < root->stores_size; offset++) { + item = node->stores[offset]; + if (item && (!iter || iter(item, node->height))) + break; + } + + if (unlikely(offset >= root->stores_size)) + return NULL; + } + + BUG_ON(offset > root->stores_size); + + return item; +} + +/* + * Blindly insert the item to the tree. Typically, we reuse the + * first empty store item. + */ +int sradix_tree_enter(struct sradix_tree_root *root, void **item, int num) +{ + unsigned long index; + unsigned int height; + struct sradix_tree_node *node, *tmp = NULL; + int offset, offset_saved; + void **store = NULL; + int error, i, j, shift; + +go_on: + index = root->min; + + if (root->enter_node && !sradix_node_full(root, root->enter_node)) { + node = root->enter_node; + BUG_ON((index >> (root->shift * root->height))); + } else { + node = root->rnode; + if (node == NULL || (index >> (root->shift * root->height)) + || sradix_node_full(root, node)) { + error = sradix_tree_extend(root, index); + if (error) + return error; + + node = root->rnode; + } + } + + + height = node->height; + shift = (height - 1) * root->shift; + offset = (index >> shift) & root->mask; + while (shift > 0) { + offset_saved = offset; + for (; offset < root->stores_size; offset++) { + store = &node->stores[offset]; + tmp = *store; + + if (!tmp || !sradix_node_full(root, tmp)) + break; + } + BUG_ON(offset >= root->stores_size); + + if (offset != offset_saved) { + index += (offset - offset_saved) << shift; + index &= ~((1UL << shift) - 1); + } + + if (!tmp) { + if (!(tmp = root->alloc())) + return -ENOMEM; + + tmp->height = shift / root->shift; + *store = tmp; + tmp->parent = node; + node->count++; +// if (root->extend) +// root->extend(node, tmp); + } + + node = tmp; + shift -= root->shift; + offset = (index >> shift) & root->mask; + } + + BUG_ON(node->height != 1); + + + store = &node->stores[offset]; + for (i = 0, j = 0; + j < root->stores_size - node->count && + i < root->stores_size - offset && j < num; i++) { + if (!store[i]) { + store[i] = item[j]; + if (root->assign) + root->assign(node, index + i, item[j]); + j++; + } + } + + node->count += j; + root->num += j; + num -= j; + + while (sradix_node_full(root, node)) { + node = node->parent; + if (!node) + break; + + node->fulls++; + } + + if (unlikely(!node)) { + /* All nodes are full */ + root->min = 1 << (root->height * root->shift); + root->enter_node = NULL; + } else { + root->min = index + i - 1; + root->min |= (1UL << (node->height - 1)) - 1; + root->min++; + root->enter_node = node; + } + + if (num) { + item += j; + goto go_on; + } + + return 0; +} + + +/** + * sradix_tree_shrink - shrink height of a sradix tree to minimal + * @root sradix tree root + * + */ +static inline void sradix_tree_shrink(struct sradix_tree_root *root) +{ + /* try to shrink tree height */ + while (root->height > 1) { + struct sradix_tree_node *to_free = root->rnode; + + /* + * The candidate node has more than one child, or its child + * is not at the leftmost store, we cannot shrink. + */ + if (to_free->count != 1 || !to_free->stores[0]) + break; + + root->rnode = to_free->stores[0]; + root->rnode->parent = NULL; + root->height--; + if (unlikely(root->enter_node == to_free)) { + root->enter_node = NULL; + } + root->free(to_free); + } +} + +/* + * Del the item on the known leaf node and index + */ +void sradix_tree_delete_from_leaf(struct sradix_tree_root *root, + struct sradix_tree_node *node, unsigned long index) +{ + unsigned int offset; + struct sradix_tree_node *start, *end; + + BUG_ON(node->height != 1); + + start = node; + while (node && !(--node->count)) + node = node->parent; + + end = node; + if (!node) { + root->rnode = NULL; + root->height = 0; + root->min = 0; + root->num = 0; + root->enter_node = NULL; + } else { + offset = (index >> (root->shift * (node->height - 1))) & root->mask; + if (root->rm) + root->rm(node, offset); + node->stores[offset] = NULL; + root->num--; + if (root->min > index) { + root->min = index; + root->enter_node = node; + } + } + + if (start != end) { + do { + node = start; + start = start->parent; + if (unlikely(root->enter_node == node)) + root->enter_node = end; + root->free(node); + } while (start != end); + + /* + * Note that shrink may free "end", so enter_node still need to + * be checked inside. + */ + sradix_tree_shrink(root); + } else if (node->count == root->stores_size - 1) { + /* It WAS a full leaf node. Update the ancestors */ + node = node->parent; + while (node) { + node->fulls--; + if (node->fulls != root->stores_size - 1) + break; + + node = node->parent; + } + } +} + +void *sradix_tree_lookup(struct sradix_tree_root *root, unsigned long index) +{ + unsigned int height, offset; + struct sradix_tree_node *node; + int shift; + + node = root->rnode; + if (node == NULL || (index >> (root->shift * root->height))) + return NULL; + + height = root->height; + shift = (height - 1) * root->shift; + + do { + offset = (index >> shift) & root->mask; + node = node->stores[offset]; + if (!node) + return NULL; + + shift -= root->shift; + } while (shift >= 0); + + return node; +} + +/* + * Return the item if it exists, otherwise create it in place + * and return the created item. + */ +void *sradix_tree_lookup_create(struct sradix_tree_root *root, + unsigned long index, void *(*item_alloc)(void)) +{ + unsigned int height, offset; + struct sradix_tree_node *node, *tmp; + void *item; + int shift, error; + + if (root->rnode == NULL || (index >> (root->shift * root->height))) { + if (item_alloc) { + error = sradix_tree_extend(root, index); + if (error) + return NULL; + } else { + return NULL; + } + } + + node = root->rnode; + height = root->height; + shift = (height - 1) * root->shift; + + do { + offset = (index >> shift) & root->mask; + if (!node->stores[offset]) { + if (!(tmp = root->alloc())) + return NULL; + + tmp->height = shift / root->shift; + node->stores[offset] = tmp; + tmp->parent = node; + node->count++; + node = tmp; + } else { + node = node->stores[offset]; + } + + shift -= root->shift; + } while (shift > 0); + + BUG_ON(node->height != 1); + offset = index & root->mask; + if (node->stores[offset]) { + return node->stores[offset]; + } else if (item_alloc) { + if (!(item = item_alloc())) + return NULL; + + node->stores[offset] = item; + + /* + * NOTE: we do NOT call root->assign here, since this item is + * newly created by us having no meaning. Caller can call this + * if it's necessary to do so. + */ + + node->count++; + root->num++; + + while (sradix_node_full(root, node)) { + node = node->parent; + if (!node) + break; + + node->fulls++; + } + + if (unlikely(!node)) { + /* All nodes are full */ + root->min = 1 << (root->height * root->shift); + } else { + if (root->min == index) { + root->min |= (1UL << (node->height - 1)) - 1; + root->min++; + root->enter_node = node; + } + } + + return item; + } else { + return NULL; + } + +} + +int sradix_tree_delete(struct sradix_tree_root *root, unsigned long index) +{ + unsigned int height, offset; + struct sradix_tree_node *node; + int shift; + + node = root->rnode; + if (node == NULL || (index >> (root->shift * root->height))) + return -ENOENT; + + height = root->height; + shift = (height - 1) * root->shift; + + do { + offset = (index >> shift) & root->mask; + node = node->stores[offset]; + if (!node) + return -ENOENT; + + shift -= root->shift; + } while (shift > 0); + + offset = index & root->mask; + if (!node->stores[offset]) + return -ENOENT; + + sradix_tree_delete_from_leaf(root, node, index); + + return 0; +} diff --git a/lib/string.c b/lib/string.c index e5878de4f10..070a3edbeb3 100644 --- a/lib/string.c +++ b/lib/string.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifndef __HAVE_ARCH_STRNICMP /** @@ -598,11 +599,11 @@ EXPORT_SYMBOL(memset); */ void *memcpy(void *dest, const void *src, size_t count) { - char *tmp = dest; - const char *s = src; + unsigned long dstp = (unsigned long)dest; + unsigned long srcp = (unsigned long)src; - while (count--) - *tmp++ = *s++; + /* Copy from the beginning to the end */ + mem_copy_fwd(dstp, srcp, count); return dest; } EXPORT_SYMBOL(memcpy); @@ -619,21 +620,15 @@ EXPORT_SYMBOL(memcpy); */ void *memmove(void *dest, const void *src, size_t count) { - char *tmp; - const char *s; + unsigned long dstp = (unsigned long)dest; + unsigned long srcp = (unsigned long)src; - if (dest <= src) { - tmp = dest; - s = src; - while (count--) - *tmp++ = *s++; + if (dest - src >= count) { + /* Copy from the beginning to the end */ + mem_copy_fwd(dstp, srcp, count); } else { - tmp = dest; - tmp += count; - s = src; - s += count; - while (count--) - *--tmp = *--s; + /* Copy from the end to the beginning */ + mem_copy_bwd(dstp, srcp, count); } return dest; } diff --git a/mm/Kconfig b/mm/Kconfig index 84489cda5aa..51b7063ebf5 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -245,6 +245,32 @@ config KSM See Documentation/vm/ksm.txt for more information: KSM is inactive until a program has madvised that an area is MADV_MERGEABLE, and root has set /sys/kernel/mm/ksm/run to 1 (if CONFIG_SYSFS is set). +choice + prompt "Choose UKSM/KSM strategy" + default UKSM + depends on KSM + help + This option allows to select a UKSM/KSM stragety. + +config UKSM + bool "Ultra-KSM for page merging" + depends on KSM + help + UKSM is inspired by the Linux kernel project \u2014 KSM(Kernel Same + page Merging), but with a fundamentally rewritten core algorithm. With + an advanced algorithm, UKSM now can transparently scans all anonymously + mapped user space applications with an significantly improved scan speed + and CPU efficiency. Since KVM is friendly to KSM, KVM can also benefit from + UKSM. Now UKSM has its first stable release and first real world enterprise user. + For more information, please goto its project page. + (www.kerneldedup.org) + +config KSM_LEGACY + bool "Legacy KSM implementation" + depends on KSM + help + The legacy KSM implementation from Redhat. +endchoice config DEFAULT_MMAP_MIN_ADDR int "Low address space to protect from user allocation" diff --git a/mm/Makefile b/mm/Makefile index 8aada89efbb..2056f9bdd92 100644 --- a/mm/Makefile +++ b/mm/Makefile @@ -25,7 +25,7 @@ endif obj-$(CONFIG_HAVE_MEMBLOCK) += memblock.o obj-$(CONFIG_BOUNCE) += bounce.o -obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o thrash.o +obj-$(CONFIG_SWAP) += page_io.o swap_state.o swapfile.o obj-$(CONFIG_HAS_DMA) += dmapool.o obj-$(CONFIG_HUGETLBFS) += hugetlb.o obj-$(CONFIG_NUMA) += mempolicy.o @@ -33,7 +33,8 @@ obj-$(CONFIG_SPARSEMEM) += sparse.o obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o obj-$(CONFIG_SLOB) += slob.o obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o -obj-$(CONFIG_KSM) += ksm.o +obj-$(CONFIG_KSM_LEGACY) += ksm.o +obj-$(CONFIG_UKSM) += uksm.o obj-$(CONFIG_PAGE_POISONING) += debug-pagealloc.o obj-$(CONFIG_SLAB) += slab.o obj-$(CONFIG_SLUB) += slub.o diff --git a/mm/madvise.c b/mm/madvise.c index 55f645c85a3..b075d1d1f6c 100644 --- a/mm/madvise.c +++ b/mm/madvise.c @@ -93,7 +93,8 @@ static long madvise_behavior(struct vm_area_struct * vma, pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); *prev = vma_merge(mm, *prev, start, end, new_flags, vma->anon_vma, - vma->vm_file, pgoff, vma_policy(vma)); + vma->vm_file, pgoff, vma_policy(vma), + vma_get_anon_name(vma)); if (*prev) { vma = *prev; goto success; diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7685d4a0b3c..8c8e6da7543 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5610,7 +5610,6 @@ static void mem_cgroup_move_task(struct cgroup *cont, if (mm) { if (mc.to) mem_cgroup_move_charge(mm); - put_swap_token(mm); mmput(mm); } if (mc.to) diff --git a/mm/memory.c b/mm/memory.c index a240b04d084..b0997dae503 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -113,6 +113,37 @@ __setup("norandmaps", disable_randmaps); unsigned long zero_pfn __read_mostly; unsigned long highest_memmap_pfn __read_mostly; +#ifdef CONFIG_UKSM +unsigned long uksm_zero_pfn __read_mostly; +struct page *empty_uksm_zero_page; + +static int __init setup_uksm_zero_page(void) +{ + unsigned long addr; + addr = __get_free_pages(GFP_KERNEL | __GFP_ZERO, 0); + if (!addr) + panic("Oh boy, that early out of memory?"); + + empty_uksm_zero_page = virt_to_page((void *) addr); + SetPageReserved(empty_uksm_zero_page); + + uksm_zero_pfn = page_to_pfn(empty_uksm_zero_page); + + return 0; +} +core_initcall(setup_uksm_zero_page); + +static inline int is_uksm_zero_pfn(unsigned long pfn) +{ + return pfn == uksm_zero_pfn; +} +#else +static inline int is_uksm_zero_pfn(unsigned long pfn) +{ + return 0; +} +#endif + /* * CONFIG_MMU architectures set up ZERO_PAGE in their paging_init() */ @@ -124,6 +155,7 @@ static int __init init_zero_pfn(void) core_initcall(init_zero_pfn); + #if defined(SPLIT_RSS_COUNTING) void sync_mm_rss(struct mm_struct *mm) @@ -717,8 +749,10 @@ static inline int is_cow_mapping(vm_flags_t flags) #ifndef is_zero_pfn static inline int is_zero_pfn(unsigned long pfn) { - return pfn == zero_pfn; + return (pfn == zero_pfn) || (is_uksm_zero_pfn(pfn)); } +#else +#define is_zero_pfn(pfn) (is_zero_pfn(pfn) || is_uksm_zero_pfn(pfn)) #endif #ifndef my_zero_pfn @@ -904,6 +938,11 @@ copy_one_pte(struct mm_struct *dst_mm, struct mm_struct *src_mm, rss[MM_ANONPAGES]++; else rss[MM_FILEPAGES]++; + + /* Should return NULL in vm_normal_page() */ + uksm_bugon_zeropage(pte); + } else { + uksm_map_zero_page(pte); } out_set_pte: @@ -1139,8 +1178,10 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, ptent = ptep_get_and_clear_full(mm, addr, pte, tlb->fullmm); tlb_remove_tlb_entry(tlb, pte, addr); - if (unlikely(!page)) + if (unlikely(!page)) { + uksm_unmap_zero_page(ptent); continue; + } if (unlikely(details) && details->nonlinear_vma && linear_page_index(details->nonlinear_vma, addr) != page->index) @@ -1666,7 +1707,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, VM_BUG_ON(!!pages != !!(gup_flags & FOLL_GET)); - /* + /* * Require read or write permissions. * If FOLL_FORCE is set, we only require the "MAY" flags. */ @@ -1713,7 +1754,7 @@ int __get_user_pages(struct task_struct *tsk, struct mm_struct *mm, page = vm_normal_page(vma, start, *pte); if (!page) { if (!(gup_flags & FOLL_DUMP) && - is_zero_pfn(pte_pfn(*pte))) + (is_zero_pfn(pte_pfn(*pte)))) page = pte_page(*pte); else { pte_unmap(pte); @@ -2473,8 +2514,10 @@ static inline void cow_user_page(struct page *dst, struct page *src, unsigned lo clear_page(kaddr); kunmap_atomic(kaddr); flush_dcache_page(dst); - } else + } else { copy_user_highpage(dst, src, va, vma); + uksm_cow_page(vma, src); + } } /* @@ -2672,6 +2715,7 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, new_page = alloc_zeroed_user_highpage_movable(vma, address); if (!new_page) goto oom; + uksm_cow_pte(vma, orig_pte); } else { new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); if (!new_page) @@ -2693,8 +2737,11 @@ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct *vma, dec_mm_counter_fast(mm, MM_FILEPAGES); inc_mm_counter_fast(mm, MM_ANONPAGES); } - } else + uksm_bugon_zeropage(orig_pte); + } else { + uksm_unmap_zero_page(orig_pte); inc_mm_counter_fast(mm, MM_ANONPAGES); + } flush_cache_page(vma, address, pte_pfn(orig_pte)); entry = mk_pte(new_page, vma->vm_page_prot); entry = maybe_mkwrite(pte_mkdirty(entry), vma); @@ -2922,7 +2969,6 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, delayacct_set_flag(DELAYACCT_PF_SWAPIN); page = lookup_swap_cache(entry); if (!page) { - grab_swap_token(mm); /* Contend for token _before_ read-in */ page = swapin_readahead(entry, GFP_HIGHUSER_MOVABLE, vma, address); if (!page) { @@ -2952,6 +2998,7 @@ static int do_swap_page(struct mm_struct *mm, struct vm_area_struct *vma, } locked = lock_page_or_retry(page, mm, flags); + delayacct_clear_flag(DELAYACCT_PF_SWAPIN); if (!locked) { ret |= VM_FAULT_RETRY; diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b1956913752..a78698098f5 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -660,7 +660,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, ((vmstart - vma->vm_start) >> PAGE_SHIFT); prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags, vma->anon_vma, vma->vm_file, pgoff, - new_pol); + new_pol, vma_get_anon_name(name)); if (prev) { vma = prev; next = vma->vm_next; diff --git a/mm/mlock.c b/mm/mlock.c index ef726e8aa8e..263e49dd1ba 100644 --- a/mm/mlock.c +++ b/mm/mlock.c @@ -329,7 +329,8 @@ static int mlock_fixup(struct vm_area_struct *vma, struct vm_area_struct **prev, pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); *prev = vma_merge(mm, *prev, start, end, newflags, vma->anon_vma, - vma->vm_file, pgoff, vma_policy(vma)); + vma->vm_file, pgoff, vma_policy(vma), + vma_get_anon_name(vma)); if (*prev) { vma = *prev; goto success; diff --git a/mm/mmap.c b/mm/mmap.c index 848ef52d960..fe38f4de309 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -65,7 +66,7 @@ static void unmap_region(struct mm_struct *mm, * MAP_SHARED r: (no) no r: (yes) yes r: (no) yes r: (no) yes * w: (no) no w: (no) no w: (yes) yes w: (no) no * x: (no) no x: (no) yes x: (no) yes x: (yes) yes - * + * * MAP_PRIVATE r: (no) no r: (yes) yes r: (no) yes r: (no) yes * w: (no) no w: (no) no w: (copy) copy w: (no) no * x: (no) no x: (no) yes x: (no) yes x: (yes) yes @@ -236,6 +237,7 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma) removed_exe_file_vma(vma->vm_mm); } mpol_put(vma_policy(vma)); + uksm_remove_vma(vma); kmem_cache_free(vm_area_cachep, vma); return next; } @@ -501,9 +503,16 @@ int vma_adjust(struct vm_area_struct *vma, unsigned long start, long adjust_next = 0; int remove_next = 0; +/* + * to avoid deadlock, ksm_remove_vma must be done before any spin_lock is + * acquired + */ + uksm_remove_vma(vma); + if (next && !insert) { struct vm_area_struct *exporter = NULL; + uksm_remove_vma(next); if (end >= next->vm_end) { /* * vma expands, overlapping all the next, and @@ -579,10 +588,10 @@ again: remove_next = 1 + (end > next->vm_end); if (adjust_next) vma_prio_tree_remove(next, root); } - vma->vm_start = start; vma->vm_end = end; vma->vm_pgoff = pgoff; + if (adjust_next) { next->vm_start += adjust_next << PAGE_SHIFT; next->vm_pgoff += adjust_next; @@ -635,10 +644,15 @@ again: remove_next = 1 + (end > next->vm_end); */ if (remove_next == 2) { next = vma->vm_next; + uksm_remove_vma(next); goto again; } + } else { + if (next && !insert) + uksm_vma_add_new(next); } + uksm_vma_add_new(vma); validate_mm(mm); return 0; @@ -649,7 +663,8 @@ again: remove_next = 1 + (end > next->vm_end); * per-vma resources, so we don't attempt to merge those. */ static inline int is_mergeable_vma(struct vm_area_struct *vma, - struct file *file, unsigned long vm_flags) + struct file *file, unsigned long vm_flags, + const char __user *anon_name) { /* VM_CAN_NONLINEAR may get set later by f_op->mmap() */ if ((vma->vm_flags ^ vm_flags) & ~VM_CAN_NONLINEAR) @@ -658,6 +673,8 @@ static inline int is_mergeable_vma(struct vm_area_struct *vma, return 0; if (vma->vm_ops && vma->vm_ops->close) return 0; + if (vma_get_anon_name(vma) != anon_name) + return 0; return 1; } @@ -688,9 +705,10 @@ static inline int is_mergeable_anon_vma(struct anon_vma *anon_vma1, */ static int can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags, - struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff) + struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff, + const char __user *anon_name) { - if (is_mergeable_vma(vma, file, vm_flags) && + if (is_mergeable_vma(vma, file, vm_flags, anon_name) && is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) { if (vma->vm_pgoff == vm_pgoff) return 1; @@ -707,9 +725,10 @@ can_vma_merge_before(struct vm_area_struct *vma, unsigned long vm_flags, */ static int can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, - struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff) + struct anon_vma *anon_vma, struct file *file, pgoff_t vm_pgoff, + const char __user *anon_name) { - if (is_mergeable_vma(vma, file, vm_flags) && + if (is_mergeable_vma(vma, file, vm_flags, anon_name) && is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) { pgoff_t vm_pglen; vm_pglen = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; @@ -720,9 +739,9 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags, } /* - * Given a mapping request (addr,end,vm_flags,file,pgoff), figure out - * whether that can be merged with its predecessor or its successor. - * Or both (it neatly fills a hole). + * Given a mapping request (addr,end,vm_flags,file,pgoff,anon_name), + * figure out whether that can be merged with its predecessor or its + * successor. Or both (it neatly fills a hole). * * In most cases - when called for mmap, brk or mremap - [addr,end) is * certain not to be mapped by the time vma_merge is called; but when @@ -752,7 +771,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, struct vm_area_struct *prev, unsigned long addr, unsigned long end, unsigned long vm_flags, struct anon_vma *anon_vma, struct file *file, - pgoff_t pgoff, struct mempolicy *policy) + pgoff_t pgoff, struct mempolicy *policy, + const char __user *anon_name) { pgoff_t pglen = (end - addr) >> PAGE_SHIFT; struct vm_area_struct *area, *next; @@ -778,15 +798,15 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, */ if (prev && prev->vm_end == addr && mpol_equal(vma_policy(prev), policy) && - can_vma_merge_after(prev, vm_flags, - anon_vma, file, pgoff)) { + can_vma_merge_after(prev, vm_flags, anon_vma, + file, pgoff, anon_name)) { /* * OK, it can. Can we now merge in the successor as well? */ if (next && end == next->vm_start && mpol_equal(policy, vma_policy(next)) && - can_vma_merge_before(next, vm_flags, - anon_vma, file, pgoff+pglen) && + can_vma_merge_before(next, vm_flags, anon_vma, + file, pgoff+pglen, anon_name) && is_mergeable_anon_vma(prev->anon_vma, next->anon_vma, NULL)) { /* cases 1, 6 */ @@ -806,8 +826,8 @@ struct vm_area_struct *vma_merge(struct mm_struct *mm, */ if (next && end == next->vm_start && mpol_equal(policy, vma_policy(next)) && - can_vma_merge_before(next, vm_flags, - anon_vma, file, pgoff+pglen)) { + can_vma_merge_before(next, vm_flags, anon_vma, + file, pgoff+pglen, anon_name)) { if (prev && addr < prev->vm_end) /* case 4 */ err = vma_adjust(prev, prev->vm_start, addr, prev->vm_pgoff, NULL); @@ -1006,6 +1026,9 @@ static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, vm_flags = calc_vm_prot_bits(prot) | calc_vm_flag_bits(flags) | mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; + /* If uksm is enabled, we add VM_MERGABLE to new VMAs. */ + uksm_vm_flags_mod(&vm_flags); + if (flags & MAP_LOCKED) if (!can_do_mlock()) return -EPERM; @@ -1282,7 +1305,8 @@ unsigned long mmap_region(struct file *file, unsigned long addr, /* * Can we just expand an old mapping? */ - vma = vma_merge(mm, prev, addr, addr + len, vm_flags, NULL, file, pgoff, NULL); + vma = vma_merge(mm, prev, addr, addr + len, vm_flags, NULL, file, pgoff, + NULL, NULL); if (vma) goto out; @@ -1357,6 +1381,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, vma_link(mm, vma, prev, rb_link, rb_parent); file = vma->vm_file; + uksm_vma_add_new(vma); /* Once vma denies write, undo our temporary denial count */ if (correct_wcount) @@ -1383,6 +1408,7 @@ unsigned long mmap_region(struct file *file, unsigned long addr, unmap_region(mm, vma, prev, vma->vm_start, vma->vm_end); charged = 0; free_vma: + uksm_remove_vma(vma); kmem_cache_free(vm_area_cachep, vma); unacct_error: if (charged) @@ -1458,7 +1484,7 @@ arch_get_unmapped_area(struct file *filp, unsigned long addr, addr = vma->vm_end; } } -#endif +#endif void arch_unmap_area(struct mm_struct *mm, unsigned long addr) { @@ -2012,6 +2038,8 @@ static int __split_vma(struct mm_struct * mm, struct vm_area_struct * vma, else err = vma_adjust(vma, vma->vm_start, addr, vma->vm_pgoff, new); + uksm_vma_add_new(new); + /* Success. */ if (!err) return 0; @@ -2185,6 +2213,7 @@ static unsigned long do_brk(unsigned long addr, unsigned long len) return error; flags = VM_DATA_DEFAULT_FLAGS | VM_ACCOUNT | mm->def_flags; + uksm_vm_flags_mod(&flags); error = get_unmapped_area(NULL, addr, len, 0, MAP_FIXED); if (error & ~PAGE_MASK) @@ -2232,7 +2261,7 @@ static unsigned long do_brk(unsigned long addr, unsigned long len) /* Can we just expand an old private anonymous mapping? */ vma = vma_merge(mm, prev, addr, addr + len, flags, - NULL, NULL, pgoff, NULL); + NULL, NULL, pgoff, NULL, NULL); if (vma) goto out; @@ -2253,6 +2282,7 @@ static unsigned long do_brk(unsigned long addr, unsigned long len) vma->vm_flags = flags; vma->vm_page_prot = vm_get_page_prot(flags); vma_link(mm, vma, prev, rb_link, rb_parent); + uksm_vma_add_new(vma); out: perf_event_mmap(vma); mm->total_vm += len >> PAGE_SHIFT; @@ -2285,6 +2315,12 @@ void exit_mmap(struct mm_struct *mm) /* mm's last user has gone, and its about to be pulled down */ mmu_notifier_release(mm); + /* + * Taking write lock on mmap_sem does not harm others, + * but it's crucial for uksm to avoid races. + */ + down_write(&mm->mmap_sem); + if (mm->locked_vm) { vma = mm->mmap; while (vma) { @@ -2318,6 +2354,11 @@ void exit_mmap(struct mm_struct *mm) while (vma) vma = remove_vma(vma); + mm->mmap = NULL; + mm->mm_rb = RB_ROOT; + mm->mmap_cache = NULL; + up_write(&mm->mmap_sem); + BUG_ON(mm->nr_ptes > (FIRST_USER_ADDRESS+PMD_SIZE-1)>>PMD_SHIFT); } @@ -2382,7 +2423,8 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, find_vma_prepare(mm, addr, &prev, &rb_link, &rb_parent); new_vma = vma_merge(mm, prev, addr, addr + len, vma->vm_flags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma)); + vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), + vma_get_anon_name(vma)); if (new_vma) { /* * Source vma may have been merged into new_vma @@ -2427,6 +2469,7 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap, if (new_vma->vm_ops && new_vma->vm_ops->open) new_vma->vm_ops->open(new_vma); vma_link(mm, new_vma, prev, rb_link, rb_parent); + uksm_vma_add_new(new_vma); } } return new_vma; @@ -2532,10 +2575,10 @@ int install_special_mapping(struct mm_struct *mm, ret = insert_vm_struct(mm, vma); if (ret) goto out; - mm->total_vm += len >> PAGE_SHIFT; perf_event_mmap(vma); + uksm_vma_add_new(vma); return 0; diff --git a/mm/mprotect.c b/mm/mprotect.c index a40992610ab..10add6b44c5 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -179,7 +179,8 @@ mprotect_fixup(struct vm_area_struct *vma, struct vm_area_struct **pprev, */ pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); *pprev = vma_merge(mm, *pprev, start, end, newflags, - vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma)); + vma->anon_vma, vma->vm_file, pgoff, vma_policy(vma), + vma_get_anon_name(vma)); if (*pprev) { vma = *pprev; goto success; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 69b952153ba..129baf33b85 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -6104,6 +6104,7 @@ static struct trace_print_flags pageflag_names[] = { #ifdef CONFIG_MEMORY_FAILURE {1UL << PG_hwpoison, "hwpoison" }, #endif + {1UL << PG_readahead, "PG_readahead" }, {-1UL, NULL }, }; diff --git a/mm/readahead.c b/mm/readahead.c index cbcbb02f3e2..cae9a44ab22 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -184,6 +184,9 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, if (!page) break; page->index = page_offset; + + page->flags |= (1L << PG_readahead); + list_add(&page->lru, &page_pool); if (page_idx == nr_to_read - lookahead_size) SetPageReadahead(page); @@ -369,10 +372,10 @@ static int try_context_readahead(struct address_space *mapping, size = count_history_pages(mapping, ra, offset, max); /* - * no history pages: + * not enough history pages: * it could be a random read */ - if (!size) + if (size <= req_size) return 0; /* @@ -383,8 +386,8 @@ static int try_context_readahead(struct address_space *mapping, size *= 2; ra->start = offset; - ra->size = get_init_ra_size(size + req_size, max); - ra->async_size = ra->size; + ra->size = min(size + req_size, max); + ra->async_size = 1; return 1; } diff --git a/mm/rmap.c b/mm/rmap.c index 5b5ad584ffb..8c5e6e137ad 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -755,12 +755,6 @@ int page_referenced_one(struct page *page, struct vm_area_struct *vma, pte_unmap_unlock(pte, ptl); } - /* Pretend the page is referenced if the task has the - swap token and is in the middle of a page fault. */ - if (mm != current->mm && has_swap_token(mm) && - rwsem_is_locked(&mm->mmap_sem)) - referenced++; - (*mapcount)--; if (referenced) @@ -1014,9 +1008,9 @@ void page_move_anon_rmap(struct page *page, /** * __page_set_anon_rmap - set up new anonymous rmap - * @page: Page to add to rmap + * @page: Page to add to rmap * @vma: VM area to add page to. - * @address: User virtual address of the mapping + * @address: User virtual address of the mapping * @exclusive: the page is exclusively owned by the current process */ static void __page_set_anon_rmap(struct page *page, diff --git a/mm/slub.c b/mm/slub.c index 925484e795d..aae6586b24f 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -2629,7 +2629,7 @@ EXPORT_SYMBOL(kmem_cache_free); * take the list_lock. */ static int slub_min_order; -static int slub_max_order = PAGE_ALLOC_COSTLY_ORDER; +static int slub_max_order; static int slub_min_objects; /* diff --git a/mm/thrash.c b/mm/thrash.c deleted file mode 100644 index 57ad495dbd5..00000000000 --- a/mm/thrash.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * mm/thrash.c - * - * Copyright (C) 2004, Red Hat, Inc. - * Copyright (C) 2004, Rik van Riel - * Released under the GPL, see the file COPYING for details. - * - * Simple token based thrashing protection, using the algorithm - * described in: http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/abs05-1.html - * - * Sep 2006, Ashwin Chaugule - * Improved algorithm to pass token: - * Each task has a priority which is incremented if it contended - * for the token in an interval less than its previous attempt. - * If the token is acquired, that task's priority is boosted to prevent - * the token from bouncing around too often and to let the task make - * some progress in its execution. - */ - -#include -#include -#include -#include -#include - -#include - -#define TOKEN_AGING_INTERVAL (0xFF) - -static DEFINE_SPINLOCK(swap_token_lock); -struct mm_struct *swap_token_mm; -static struct mem_cgroup *swap_token_memcg; - -#ifdef CONFIG_CGROUP_MEM_RES_CTLR -static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) -{ - struct mem_cgroup *memcg; - - memcg = try_get_mem_cgroup_from_mm(mm); - if (memcg) - css_put(mem_cgroup_css(memcg)); - - return memcg; -} -#else -static struct mem_cgroup *swap_token_memcg_from_mm(struct mm_struct *mm) -{ - return NULL; -} -#endif - -void grab_swap_token(struct mm_struct *mm) -{ - int current_interval; - unsigned int old_prio = mm->token_priority; - static unsigned int global_faults; - static unsigned int last_aging; - - global_faults++; - - current_interval = global_faults - mm->faultstamp; - - if (!spin_trylock(&swap_token_lock)) - return; - - /* First come first served */ - if (!swap_token_mm) - goto replace_token; - - /* - * Usually, we don't need priority aging because long interval faults - * makes priority decrease quickly. But there is one exception. If the - * token owner task is sleeping, it never make long interval faults. - * Thus, we need a priority aging mechanism instead. The requirements - * of priority aging are - * 1) An aging interval is reasonable enough long. Too short aging - * interval makes quick swap token lost and decrease performance. - * 2) The swap token owner task have to get priority aging even if - * it's under sleep. - */ - if ((global_faults - last_aging) > TOKEN_AGING_INTERVAL) { - swap_token_mm->token_priority /= 2; - last_aging = global_faults; - } - - if (mm == swap_token_mm) { - mm->token_priority += 2; - goto update_priority; - } - - if (current_interval < mm->last_interval) - mm->token_priority++; - else { - if (likely(mm->token_priority > 0)) - mm->token_priority--; - } - - /* Check if we deserve the token */ - if (mm->token_priority > swap_token_mm->token_priority) - goto replace_token; - -update_priority: - trace_update_swap_token_priority(mm, old_prio, swap_token_mm); - -out: - mm->faultstamp = global_faults; - mm->last_interval = current_interval; - spin_unlock(&swap_token_lock); - return; - -replace_token: - mm->token_priority += 2; - trace_replace_swap_token(swap_token_mm, mm); - swap_token_mm = mm; - swap_token_memcg = swap_token_memcg_from_mm(mm); - last_aging = global_faults; - goto out; -} - -/* Called on process exit. */ -void __put_swap_token(struct mm_struct *mm) -{ - spin_lock(&swap_token_lock); - if (likely(mm == swap_token_mm)) { - trace_put_swap_token(swap_token_mm); - swap_token_mm = NULL; - swap_token_memcg = NULL; - } - spin_unlock(&swap_token_lock); -} - -static bool match_memcg(struct mem_cgroup *a, struct mem_cgroup *b) -{ - if (!a) - return true; - if (!b) - return true; - if (a == b) - return true; - return false; -} - -void disable_swap_token(struct mem_cgroup *memcg) -{ - /* memcg reclaim don't disable unrelated mm token. */ - if (match_memcg(memcg, swap_token_memcg)) { - spin_lock(&swap_token_lock); - if (match_memcg(memcg, swap_token_memcg)) { - trace_disable_swap_token(swap_token_mm); - swap_token_mm = NULL; - swap_token_memcg = NULL; - } - spin_unlock(&swap_token_lock); - } -} diff --git a/mm/uksm.c b/mm/uksm.c new file mode 100644 index 00000000000..3821fd1d207 --- /dev/null +++ b/mm/uksm.c @@ -0,0 +1,5623 @@ +/* + * Ultra KSM. Copyright (C) 2011-2012 Nai Xia + * + * This is an improvement upon KSM. Some basic data structures and routines + * are borrowed from ksm.c . + * + * Its new features: + * 1. Full system scan: + * It automatically scans all user processes' anonymous VMAs. Kernel-user + * interaction to submit a memory area to KSM is no longer needed. + * + * 2. Rich area detection: + * It automatically detects rich areas containing abundant duplicated + * pages based. Rich areas are given a full scan speed. Poor areas are + * sampled at a reasonable speed with very low CPU consumption. + * + * 3. Ultra Per-page scan speed improvement: + * A new hash algorithm is proposed. As a result, on a machine with + * Core(TM)2 Quad Q9300 CPU in 32-bit mode and 800MHZ DDR2 main memory, it + * can scan memory areas that does not contain duplicated pages at speed of + * 627MB/sec ~ 2445MB/sec and can merge duplicated areas at speed of + * 477MB/sec ~ 923MB/sec. + * + * 4. Thrashing area avoidance: + * Thrashing area(an VMA that has frequent Ksm page break-out) can be + * filtered out. My benchmark shows it's more efficient than KSM's per-page + * hash value based volatile page detection. + * + * + * 5. Misc changes upon KSM: + * * It has a fully x86-opitmized memcmp dedicated for 4-byte-aligned page + * comparison. It's much faster than default C version on x86. + * * rmap_item now has an struct *page member to loosely cache a + * address-->page mapping, which reduces too much time-costly + * follow_page(). + * * The VMA creation/exit procedures are hooked to let the Ultra KSM know. + * * try_to_merge_two_pages() now can revert a pte if it fails. No break_ + * ksm is needed for this case. + * + * 6. Full Zero Page consideration(contributed by Figo Zhang) + * Now uksmd consider full zero pages as special pages and merge them to an + * special unswappable uksm zero page. + */ + +#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 "internal.h" + +#ifdef CONFIG_X86 +#undef memcmp + +#ifdef CONFIG_X86_32 +#define memcmp memcmpx86_32 +/* + * Compare 4-byte-aligned address s1 and s2, with length n + */ +int memcmpx86_32(void *s1, void *s2, size_t n) +{ + size_t num = n / 4; + register int res; + + __asm__ __volatile__ + ( + "testl %3,%3\n\t" + "repe; cmpsd\n\t" + "je 1f\n\t" + "sbbl %0,%0\n\t" + "orl $1,%0\n" + "1:" + : "=&a" (res), "+&S" (s1), "+&D" (s2), "+&c" (num) + : "0" (0) + : "cc"); + + return res; +} + +/* + * Check the page is all zero ? + */ +static int is_full_zero(const void *s1, size_t len) +{ + unsigned char same; + + len /= 4; + + __asm__ __volatile__ + ("repe; scasl;" + "sete %0" + : "=qm" (same), "+D" (s1), "+c" (len) + : "a" (0) + : "cc"); + + return same; +} + + +#elif defined(CONFIG_X86_64) +#define memcmp memcmpx86_64 +/* + * Compare 8-byte-aligned address s1 and s2, with length n + */ +int memcmpx86_64(void *s1, void *s2, size_t n) +{ + size_t num = n / 8; + register int res; + + __asm__ __volatile__ + ( + "testq %q3,%q3\n\t" + "repe; cmpsq\n\t" + "je 1f\n\t" + "sbbq %q0,%q0\n\t" + "orq $1,%q0\n" + "1:" + : "=&a" (res), "+&S" (s1), "+&D" (s2), "+&c" (num) + : "0" (0) + : "cc"); + + return res; +} + +static int is_full_zero(const void *s1, size_t len) +{ + unsigned char same; + + len /= 8; + + __asm__ __volatile__ + ("repe; scasq;" + "sete %0" + : "=qm" (same), "+D" (s1), "+c" (len) + : "a" (0) + : "cc"); + + return same; +} + +#endif +#else +static int is_full_zero(const void *s1, size_t len) +{ + const unsigned long *src = s1; + int i; + + len /= sizeof(*src); + + for (i = 0; i < len; i++) { + if (src[i]) + return 0; + } + + return 1; +} +#endif + +#define U64_MAX (~((u64)0)) +#define UKSM_RUNG_ROUND_FINISHED (1 << 0) +#define TIME_RATIO_SCALE 10000 + +#define SLOT_TREE_NODE_SHIFT 8 +#define SLOT_TREE_NODE_STORE_SIZE (1UL << SLOT_TREE_NODE_SHIFT) +struct slot_tree_node { + unsigned long size; + struct sradix_tree_node snode; + void *stores[SLOT_TREE_NODE_STORE_SIZE]; +}; + +static struct kmem_cache *slot_tree_node_cachep; + +static struct sradix_tree_node *slot_tree_node_alloc(void) +{ + struct slot_tree_node *p; + p = kmem_cache_zalloc(slot_tree_node_cachep, GFP_KERNEL); + if (!p) + return NULL; + + return &p->snode; +} + +static void slot_tree_node_free(struct sradix_tree_node *node) +{ + struct slot_tree_node *p; + + p = container_of(node, struct slot_tree_node, snode); + kmem_cache_free(slot_tree_node_cachep, p); +} + +static void slot_tree_node_extend(struct sradix_tree_node *parent, + struct sradix_tree_node *child) +{ + struct slot_tree_node *p, *c; + + p = container_of(parent, struct slot_tree_node, snode); + c = container_of(child, struct slot_tree_node, snode); + + p->size += c->size; +} + +void slot_tree_node_assign(struct sradix_tree_node *node, + unsigned index, void *item) +{ + struct vma_slot *slot = item; + struct slot_tree_node *cur; + + slot->snode = node; + slot->sindex = index; + + while (node) { + cur = container_of(node, struct slot_tree_node, snode); + cur->size += slot->pages; + node = node->parent; + } +} + +void slot_tree_node_rm(struct sradix_tree_node *node, unsigned offset) +{ + struct vma_slot *slot; + struct slot_tree_node *cur; + unsigned long pages; + + if (node->height == 1) { + slot = node->stores[offset]; + pages = slot->pages; + } else { + cur = container_of(node->stores[offset], + struct slot_tree_node, snode); + pages = cur->size; + } + + while (node) { + cur = container_of(node, struct slot_tree_node, snode); + cur->size -= pages; + node = node->parent; + } +} + +unsigned long slot_iter_index; +int slot_iter(void *item, unsigned long height) +{ + struct slot_tree_node *node; + struct vma_slot *slot; + + if (height == 1) { + slot = item; + if (slot_iter_index < slot->pages) { + /*in this one*/ + return 1; + } else { + slot_iter_index -= slot->pages; + return 0; + } + + } else { + node = container_of(item, struct slot_tree_node, snode); + if (slot_iter_index < node->size) { + /*in this one*/ + return 1; + } else { + slot_iter_index -= node->size; + return 0; + } + } +} + + +static inline void slot_tree_init_root(struct sradix_tree_root *root) +{ + init_sradix_tree_root(root, SLOT_TREE_NODE_SHIFT); + root->alloc = slot_tree_node_alloc; + root->free = slot_tree_node_free; + root->extend = slot_tree_node_extend; + root->assign = slot_tree_node_assign; + root->rm = slot_tree_node_rm; +} + +void slot_tree_init(void) +{ + slot_tree_node_cachep = kmem_cache_create("slot_tree_node", + sizeof(struct slot_tree_node), 0, + SLAB_PANIC | SLAB_RECLAIM_ACCOUNT, + NULL); +} + + +/* Each rung of this ladder is a list of VMAs having a same scan ratio */ +struct scan_rung { + //struct list_head scanned_list; + struct sradix_tree_root vma_root; + struct sradix_tree_root vma_root2; + + struct vma_slot *current_scan; + unsigned long current_offset; + + /* + * The initial value for current_offset, it should loop over + * [0~ step - 1] to let all slot have its chance to be scanned. + */ + unsigned long offset_init; + unsigned long step; /* dynamic step for current_offset */ + unsigned int flags; + unsigned long pages_to_scan; + //unsigned long fully_scanned_slots; + /* + * a little bit tricky - if cpu_time_ratio > 0, then the value is the + * the cpu time ratio it can spend in rung_i for every scan + * period. if < 0, then it is the cpu time ratio relative to the + * max cpu percentage user specified. Both in unit of + * 1/TIME_RATIO_SCALE + */ + int cpu_ratio; + + /* + * How long it will take for all slots in this rung to be fully + * scanned? If it's zero, we don't care about the cover time: + * it's fully scanned. + */ + unsigned int cover_msecs; + //unsigned long vma_num; + //unsigned long pages; /* Sum of all slot's pages in rung */ +}; + +/** + * node of either the stable or unstale rbtree + * + */ +struct tree_node { + struct rb_node node; /* link in the main (un)stable rbtree */ + struct rb_root sub_root; /* rb_root for sublevel collision rbtree */ + u32 hash; + unsigned long count; /* TODO: merged with sub_root */ + struct list_head all_list; /* all tree nodes in stable/unstable tree */ +}; + +/** + * struct stable_node - node of the stable rbtree + * @node: rb node of this ksm page in the stable tree + * @hlist: hlist head of rmap_items using this ksm page + * @kpfn: page frame number of this ksm page + */ +struct stable_node { + struct rb_node node; /* link in sub-rbtree */ + struct tree_node *tree_node; /* it's tree node root in stable tree, NULL if it's in hell list */ + struct hlist_head hlist; + unsigned long kpfn; + u32 hash_max; /* if ==0 then it's not been calculated yet */ + struct list_head all_list; /* in a list for all stable nodes */ +}; + +/** + * struct node_vma - group rmap_items linked in a same stable + * node together. + */ +struct node_vma { + union { + struct vma_slot *slot; + unsigned long key; /* slot is used as key sorted on hlist */ + }; + struct hlist_node hlist; + struct hlist_head rmap_hlist; + struct stable_node *head; +}; + +/** + * struct rmap_item - reverse mapping item for virtual addresses + * @rmap_list: next rmap_item in mm_slot's singly-linked rmap_list + * @anon_vma: pointer to anon_vma for this mm,address, when in stable tree + * @mm: the memory structure this rmap_item is pointing into + * @address: the virtual address this rmap_item tracks (+ flags in low bits) + * @node: rb node of this rmap_item in the unstable tree + * @head: pointer to stable_node heading this list in the stable tree + * @hlist: link into hlist of rmap_items hanging off that stable_node + */ +struct rmap_item { + struct vma_slot *slot; + struct page *page; + unsigned long address; /* + low bits used for flags below */ + unsigned long hash_round; + unsigned long entry_index; + union { + struct {/* when in unstable tree */ + struct rb_node node; + struct tree_node *tree_node; + u32 hash_max; + }; + struct { /* when in stable tree */ + struct node_vma *head; + struct hlist_node hlist; + struct anon_vma *anon_vma; + }; + }; +} __attribute__((aligned(4))); + +struct rmap_list_entry { + union { + struct rmap_item *item; + unsigned long addr; + }; + /* lowest bit is used for is_addr tag */ +} __attribute__((aligned(4))); /* 4 aligned to fit in to pages*/ + + +/* Basic data structure definition ends */ + + +/* + * Flags for rmap_item to judge if it's listed in the stable/unstable tree. + * The flags use the low bits of rmap_item.address + */ +#define UNSTABLE_FLAG 0x1 +#define STABLE_FLAG 0x2 +#define get_rmap_addr(x) ((x)->address & PAGE_MASK) + +/* + * rmap_list_entry helpers + */ +#define IS_ADDR_FLAG 1 +#define is_addr(ptr) ((unsigned long)(ptr) & IS_ADDR_FLAG) +#define set_is_addr(ptr) ((ptr) |= IS_ADDR_FLAG) +#define get_clean_addr(ptr) (((ptr) & ~(__typeof__(ptr))IS_ADDR_FLAG)) + + +/* + * High speed caches for frequently allocated and freed structs + */ +static struct kmem_cache *rmap_item_cache; +static struct kmem_cache *stable_node_cache; +static struct kmem_cache *node_vma_cache; +static struct kmem_cache *vma_slot_cache; +static struct kmem_cache *tree_node_cache; +#define UKSM_KMEM_CACHE(__struct, __flags) kmem_cache_create("uksm_"#__struct,\ + sizeof(struct __struct), __alignof__(struct __struct),\ + (__flags), NULL) + +/* Array of all scan_rung, uksm_scan_ladder[0] having the minimum scan ratio */ +#define SCAN_LADDER_SIZE 4 +static struct scan_rung uksm_scan_ladder[SCAN_LADDER_SIZE]; + +/* The evaluation rounds uksmd has finished */ +static unsigned long long uksm_eval_round = 1; + +/* + * we add 1 to this var when we consider we should rebuild the whole + * unstable tree. + */ +static unsigned long uksm_hash_round = 1; + +/* + * How many times the whole memory is scanned. + */ +static unsigned long long fully_scanned_round = 1; + +/* The total number of virtual pages of all vma slots */ +static u64 uksm_pages_total; + +/* The number of pages has been scanned since the start up */ +static u64 uksm_pages_scanned; + +static u64 scanned_virtual_pages; + +/* The number of pages has been scanned since last encode_benefit call */ +static u64 uksm_pages_scanned_last; + +/* If the scanned number is tooo large, we encode it here */ +static u64 pages_scanned_stored; + +static unsigned long pages_scanned_base; + +/* The number of nodes in the stable tree */ +static unsigned long uksm_pages_shared; + +/* The number of page slots additionally sharing those nodes */ +static unsigned long uksm_pages_sharing; + +/* The number of nodes in the unstable tree */ +static unsigned long uksm_pages_unshared; + +/* + * Milliseconds ksmd should sleep between scans, + * >= 100ms to be consistent with + * scan_time_to_sleep_msec() + */ +static unsigned int uksm_sleep_jiffies; + +/* The real value for the uksmd next sleep */ +static unsigned int uksm_sleep_real; + +/* Saved value for user input uksm_sleep_jiffies when it's enlarged */ +static unsigned int uksm_sleep_saved; + +/* Max percentage of cpu utilization ksmd can take to scan in one batch */ +static unsigned int uksm_max_cpu_percentage; + +static int uksm_cpu_governor; + +static char *uksm_cpu_governor_str[4] = { "full", "medium", "low", "quiet" }; + +struct uksm_cpu_preset_s { + int cpu_ratio[SCAN_LADDER_SIZE]; + unsigned int cover_msecs[SCAN_LADDER_SIZE]; + unsigned int max_cpu; /* percentage */ +}; + +struct uksm_cpu_preset_s uksm_cpu_preset[4] = { + { {20, 40, -2500, -10000}, {1000, 500, 200, 50}, 95}, + { {20, 30, -2500, -10000}, {1000, 500, 400, 100}, 50}, + { {10, 20, -5000, -10000}, {1500, 1000, 1000, 250}, 20}, + { {10, 20, 40, 75}, {2000, 1000, 1000, 1000}, 1}, +}; + +/* The default value for uksm_ema_page_time if it's not initialized */ +#define UKSM_PAGE_TIME_DEFAULT 500 + +/*cost to scan one page by expotional moving average in nsecs */ +static unsigned long uksm_ema_page_time = UKSM_PAGE_TIME_DEFAULT; + +/* The expotional moving average alpha weight, in percentage. */ +#define EMA_ALPHA 20 + +/* + * The threshold used to filter out thrashing areas, + * If it == 0, filtering is disabled, otherwise it's the percentage up-bound + * of the thrashing ratio of all areas. Any area with a bigger thrashing ratio + * will be considered as having a zero duplication ratio. + */ +static unsigned int uksm_thrash_threshold = 50; + +/* How much dedup ratio is considered to be abundant*/ +static unsigned int uksm_abundant_threshold = 10; + +/* All slots having merged pages in this eval round. */ +struct list_head vma_slot_dedup = LIST_HEAD_INIT(vma_slot_dedup); + +/* How many times the ksmd has slept since startup */ +static unsigned long long uksm_sleep_times; + +#define UKSM_RUN_STOP 0 +#define UKSM_RUN_MERGE 1 +static unsigned int uksm_run = 1; + +static DECLARE_WAIT_QUEUE_HEAD(uksm_thread_wait); +static DEFINE_MUTEX(uksm_thread_mutex); + +/* + * List vma_slot_new is for newly created vma_slot waiting to be added by + * ksmd. If one cannot be added(e.g. due to it's too small), it's moved to + * vma_slot_noadd. vma_slot_del is the list for vma_slot whose corresponding + * VMA has been removed/freed. + */ +struct list_head vma_slot_new = LIST_HEAD_INIT(vma_slot_new); +struct list_head vma_slot_noadd = LIST_HEAD_INIT(vma_slot_noadd); +struct list_head vma_slot_del = LIST_HEAD_INIT(vma_slot_del); +static DEFINE_SPINLOCK(vma_slot_list_lock); + +/* The unstable tree heads */ +static struct rb_root root_unstable_tree = RB_ROOT; + +/* + * All tree_nodes are in a list to be freed at once when unstable tree is + * freed after each scan round. + */ +static struct list_head unstable_tree_node_list = + LIST_HEAD_INIT(unstable_tree_node_list); + +/* List contains all stable nodes */ +static struct list_head stable_node_list = LIST_HEAD_INIT(stable_node_list); + +/* + * When the hash strength is changed, the stable tree must be delta_hashed and + * re-structured. We use two set of below structs to speed up the + * re-structuring of stable tree. + */ +static struct list_head +stable_tree_node_list[2] = {LIST_HEAD_INIT(stable_tree_node_list[0]), + LIST_HEAD_INIT(stable_tree_node_list[1])}; + +static struct list_head *stable_tree_node_listp = &stable_tree_node_list[0]; +static struct rb_root root_stable_tree[2] = {RB_ROOT, RB_ROOT}; +static struct rb_root *root_stable_treep = &root_stable_tree[0]; +static unsigned long stable_tree_index; + +/* The hash strength needed to hash a full page */ +#define HASH_STRENGTH_FULL (PAGE_SIZE / sizeof(u32)) + +/* The hash strength needed for loop-back hashing */ +#define HASH_STRENGTH_MAX (HASH_STRENGTH_FULL + 10) + +/* The random offsets in a page */ +static u32 *random_nums; + +/* The hash strength */ +static unsigned long hash_strength = HASH_STRENGTH_FULL >> 4; + +/* The delta value each time the hash strength increases or decreases */ +static unsigned long hash_strength_delta; +#define HASH_STRENGTH_DELTA_MAX 5 + +/* The time we have saved due to random_sample_hash */ +static u64 rshash_pos; + +/* The time we have wasted due to hash collision */ +static u64 rshash_neg; + +struct uksm_benefit { + u64 pos; + u64 neg; + u64 scanned; + unsigned long base; +} benefit; + +/* + * The relative cost of memcmp, compared to 1 time unit of random sample + * hash, this value is tested when ksm module is initialized + */ +static unsigned long memcmp_cost; + +static unsigned long rshash_neg_cont_zero; +static unsigned long rshash_cont_obscure; + +/* The possible states of hash strength adjustment heuristic */ +enum rshash_states { + RSHASH_STILL, + RSHASH_TRYUP, + RSHASH_TRYDOWN, + RSHASH_NEW, + RSHASH_PRE_STILL, +}; + +/* The possible direction we are about to adjust hash strength */ +enum rshash_direct { + GO_UP, + GO_DOWN, + OBSCURE, + STILL, +}; + +/* random sampling hash state machine */ +static struct { + enum rshash_states state; + enum rshash_direct pre_direct; + u8 below_count; + /* Keep a lookup window of size 5, iff above_count/below_count > 3 + * in this window we stop trying. + */ + u8 lookup_window_index; + u64 stable_benefit; + unsigned long turn_point_down; + unsigned long turn_benefit_down; + unsigned long turn_point_up; + unsigned long turn_benefit_up; + unsigned long stable_point; +} rshash_state; + +/*zero page hash table, hash_strength [0 ~ HASH_STRENGTH_MAX]*/ +static u32 *zero_hash_table; + +static inline struct node_vma *alloc_node_vma(void) +{ + struct node_vma *node_vma; + node_vma = kmem_cache_zalloc(node_vma_cache, GFP_KERNEL); + if (node_vma) { + INIT_HLIST_HEAD(&node_vma->rmap_hlist); + INIT_HLIST_NODE(&node_vma->hlist); + } + return node_vma; +} + +static inline void free_node_vma(struct node_vma *node_vma) +{ + kmem_cache_free(node_vma_cache, node_vma); +} + + +static inline struct vma_slot *alloc_vma_slot(void) +{ + struct vma_slot *slot; + + /* + * In case ksm is not initialized by now. + * Oops, we need to consider the call site of uksm_init() in the future. + */ + if (!vma_slot_cache) + return NULL; + + slot = kmem_cache_zalloc(vma_slot_cache, GFP_KERNEL); + if (slot) { + INIT_LIST_HEAD(&slot->slot_list); + INIT_LIST_HEAD(&slot->dedup_list); + slot->flags |= UKSM_SLOT_NEED_RERAND; + } + return slot; +} + +static inline void free_vma_slot(struct vma_slot *vma_slot) +{ + kmem_cache_free(vma_slot_cache, vma_slot); +} + + + +static inline struct rmap_item *alloc_rmap_item(void) +{ + struct rmap_item *rmap_item; + + rmap_item = kmem_cache_zalloc(rmap_item_cache, GFP_KERNEL); + if (rmap_item) { + /* bug on lowest bit is not clear for flag use */ + BUG_ON(is_addr(rmap_item)); + } + return rmap_item; +} + +static inline void free_rmap_item(struct rmap_item *rmap_item) +{ + rmap_item->slot = NULL; /* debug safety */ + kmem_cache_free(rmap_item_cache, rmap_item); +} + +static inline struct stable_node *alloc_stable_node(void) +{ + struct stable_node *node; + node = kmem_cache_alloc(stable_node_cache, GFP_KERNEL | GFP_ATOMIC); + if (!node) + return NULL; + + INIT_HLIST_HEAD(&node->hlist); + list_add(&node->all_list, &stable_node_list); + return node; +} + +static inline void free_stable_node(struct stable_node *stable_node) +{ + list_del(&stable_node->all_list); + kmem_cache_free(stable_node_cache, stable_node); +} + +static inline struct tree_node *alloc_tree_node(struct list_head *list) +{ + struct tree_node *node; + node = kmem_cache_zalloc(tree_node_cache, GFP_KERNEL | GFP_ATOMIC); + if (!node) + return NULL; + + list_add(&node->all_list, list); + return node; +} + +static inline void free_tree_node(struct tree_node *node) +{ + list_del(&node->all_list); + kmem_cache_free(tree_node_cache, node); +} + +static void uksm_drop_anon_vma(struct rmap_item *rmap_item) +{ + struct anon_vma *anon_vma = rmap_item->anon_vma; + + put_anon_vma(anon_vma); +} + + +/** + * Remove a stable node from stable_tree, may unlink from its tree_node and + * may remove its parent tree_node if no other stable node is pending. + * + * @stable_node The node need to be removed + * @unlink_rb Will this node be unlinked from the rbtree? + * @remove_tree_ node Will its tree_node be removed if empty? + */ +static void remove_node_from_stable_tree(struct stable_node *stable_node, + int unlink_rb, int remove_tree_node) +{ + struct node_vma *node_vma; + struct rmap_item *rmap_item; + struct hlist_node *hlist, *rmap_hlist, *n; + + if (!hlist_empty(&stable_node->hlist)) { + hlist_for_each_entry_safe(node_vma, hlist, n, + &stable_node->hlist, hlist) { + hlist_for_each_entry(rmap_item, rmap_hlist, + &node_vma->rmap_hlist, hlist) { + uksm_pages_sharing--; + + uksm_drop_anon_vma(rmap_item); + rmap_item->address &= PAGE_MASK; + } + free_node_vma(node_vma); + cond_resched(); + } + + /* the last one is counted as shared */ + uksm_pages_shared--; + uksm_pages_sharing++; + } + + if (stable_node->tree_node && unlink_rb) { + rb_erase(&stable_node->node, + &stable_node->tree_node->sub_root); + + if (RB_EMPTY_ROOT(&stable_node->tree_node->sub_root) && + remove_tree_node) { + rb_erase(&stable_node->tree_node->node, + root_stable_treep); + free_tree_node(stable_node->tree_node); + } else { + stable_node->tree_node->count--; + } + } + + free_stable_node(stable_node); +} + + +/* + * get_uksm_page: checks if the page indicated by the stable node + * is still its ksm page, despite having held no reference to it. + * In which case we can trust the content of the page, and it + * returns the gotten page; but if the page has now been zapped, + * remove the stale node from the stable tree and return NULL. + * + * You would expect the stable_node to hold a reference to the ksm page. + * But if it increments the page's count, swapping out has to wait for + * ksmd to come around again before it can free the page, which may take + * seconds or even minutes: much too unresponsive. So instead we use a + * "keyhole reference": access to the ksm page from the stable node peeps + * out through its keyhole to see if that page still holds the right key, + * pointing back to this stable node. This relies on freeing a PageAnon + * page to reset its page->mapping to NULL, and relies on no other use of + * a page to put something that might look like our key in page->mapping. + * + * include/linux/pagemap.h page_cache_get_speculative() is a good reference, + * but this is different - made simpler by uksm_thread_mutex being held, but + * interesting for assuming that no other use of the struct page could ever + * put our expected_mapping into page->mapping (or a field of the union which + * coincides with page->mapping). The RCU calls are not for KSM at all, but + * to keep the page_count protocol described with page_cache_get_speculative. + * + * Note: it is possible that get_uksm_page() will return NULL one moment, + * then page the next, if the page is in between page_freeze_refs() and + * page_unfreeze_refs(): this shouldn't be a problem anywhere, the page + * is on its way to being freed; but it is an anomaly to bear in mind. + * + * @unlink_rb: if the removal of this node will firstly unlink from + * its rbtree. stable_node_reinsert will prevent this when restructuring the + * node from its old tree. + * + * @remove_tree_node: if this is the last one of its tree_node, will the + * tree_node be freed ? If we are inserting stable node, this tree_node may + * be reused, so don't free it. + */ +static struct page *get_uksm_page(struct stable_node *stable_node, + int unlink_rb, int remove_tree_node) +{ + struct page *page; + void *expected_mapping; + + page = pfn_to_page(stable_node->kpfn); + expected_mapping = (void *)stable_node + + (PAGE_MAPPING_ANON | PAGE_MAPPING_KSM); + rcu_read_lock(); + if (page->mapping != expected_mapping) + goto stale; + if (!get_page_unless_zero(page)) + goto stale; + if (page->mapping != expected_mapping) { + put_page(page); + goto stale; + } + rcu_read_unlock(); + return page; +stale: + rcu_read_unlock(); + remove_node_from_stable_tree(stable_node, unlink_rb, remove_tree_node); + + return NULL; +} + +/* + * Removing rmap_item from stable or unstable tree. + * This function will clean the information from the stable/unstable tree. + */ +static inline void remove_rmap_item_from_tree(struct rmap_item *rmap_item) +{ + if (rmap_item->address & STABLE_FLAG) { + struct stable_node *stable_node; + struct node_vma *node_vma; + struct page *page; + + node_vma = rmap_item->head; + stable_node = node_vma->head; + page = get_uksm_page(stable_node, 1, 1); + if (!page) + goto out; + + /* + * page lock is needed because it's racing with + * try_to_unmap_ksm(), etc. + */ + lock_page(page); + hlist_del(&rmap_item->hlist); + + if (hlist_empty(&node_vma->rmap_hlist)) { + hlist_del(&node_vma->hlist); + free_node_vma(node_vma); + } + unlock_page(page); + + put_page(page); + if (hlist_empty(&stable_node->hlist)) { + /* do NOT call remove_node_from_stable_tree() here, + * it's possible for a forked rmap_item not in + * stable tree while the in-tree rmap_items were + * deleted. + */ + uksm_pages_shared--; + } else + uksm_pages_sharing--; + + + uksm_drop_anon_vma(rmap_item); + } else if (rmap_item->address & UNSTABLE_FLAG) { + if (rmap_item->hash_round == uksm_hash_round) { + + rb_erase(&rmap_item->node, + &rmap_item->tree_node->sub_root); + if (RB_EMPTY_ROOT(&rmap_item->tree_node->sub_root)) { + rb_erase(&rmap_item->tree_node->node, + &root_unstable_tree); + + free_tree_node(rmap_item->tree_node); + } else + rmap_item->tree_node->count--; + } + uksm_pages_unshared--; + } + + rmap_item->address &= PAGE_MASK; + rmap_item->hash_max = 0; + +out: + cond_resched(); /* we're called from many long loops */ +} + +static inline int slot_in_uksm(struct vma_slot *slot) +{ + return list_empty(&slot->slot_list); +} + +/* + * Test if the mm is exiting + */ +static inline bool uksm_test_exit(struct mm_struct *mm) +{ + return atomic_read(&mm->mm_users) == 0; +} + +/** + * Need to do two things: + * 1. check if slot was moved to del list + * 2. make sure the mmap_sem is manipulated under valid vma. + * + * My concern here is that in some cases, this may make + * vma_slot_list_lock() waiters to serialized further by some + * sem->wait_lock, can this really be expensive? + * + * + * @return + * 0: if successfully locked mmap_sem + * -ENOENT: this slot was moved to del list + * -EBUSY: vma lock failed + */ +static int try_down_read_slot_mmap_sem(struct vma_slot *slot) +{ + struct vm_area_struct *vma; + struct mm_struct *mm; + struct rw_semaphore *sem; + + spin_lock(&vma_slot_list_lock); + + /* the slot_list was removed and inited from new list, when it enters + * uksm_list. If now it's not empty, then it must be moved to del list + */ + if (!slot_in_uksm(slot)) { + spin_unlock(&vma_slot_list_lock); + return -ENOENT; + } + + BUG_ON(slot->pages != vma_pages(slot->vma)); + /* Ok, vma still valid */ + vma = slot->vma; + mm = vma->vm_mm; + sem = &mm->mmap_sem; + + if (uksm_test_exit(mm)) { + spin_unlock(&vma_slot_list_lock); + return -ENOENT; + } + + if (down_read_trylock(sem)) { + spin_unlock(&vma_slot_list_lock); + return 0; + } + + spin_unlock(&vma_slot_list_lock); + return -EBUSY; +} + +static inline unsigned long +vma_page_address(struct page *page, struct vm_area_struct *vma) +{ + pgoff_t pgoff = page->index << (PAGE_CACHE_SHIFT - PAGE_SHIFT); + unsigned long address; + + address = vma->vm_start + ((pgoff - vma->vm_pgoff) << PAGE_SHIFT); + if (unlikely(address < vma->vm_start || address >= vma->vm_end)) { + /* page should be within @vma mapping range */ + return -EFAULT; + } + return address; +} + + +/* return 0 on success with the item's mmap_sem locked */ +static inline int get_mergeable_page_lock_mmap(struct rmap_item *item) +{ + struct mm_struct *mm; + struct vma_slot *slot = item->slot; + int err = -EINVAL; + + struct page *page; + + /* + * try_down_read_slot_mmap_sem() returns non-zero if the slot + * has been removed by uksm_remove_vma(). + */ + if (try_down_read_slot_mmap_sem(slot)) + return -EBUSY; + + mm = slot->vma->vm_mm; + + if (uksm_test_exit(mm)) + goto failout_up; + + page = item->page; + rcu_read_lock(); + if (!get_page_unless_zero(page)) { + rcu_read_unlock(); + goto failout_up; + } + + /* No need to consider huge page here. */ + if (item->slot->vma->anon_vma != page_anon_vma(page) || + vma_page_address(page, item->slot->vma) != get_rmap_addr(item)) { + /* + * TODO: + * should we release this item becase of its stale page + * mapping? + */ + put_page(page); + rcu_read_unlock(); + goto failout_up; + } + rcu_read_unlock(); + return 0; + +failout_up: + up_read(&mm->mmap_sem); + return err; +} + +/* + * What kind of VMA is considered ? + */ +static inline int vma_can_enter(struct vm_area_struct *vma) +{ + return uksm_flags_can_scan(vma->vm_flags); +} + +/* + * Called whenever a fresh new vma is created A new vma_slot. + * is created and inserted into a global list Must be called. + * after vma is inserted to its mm . + */ +void uksm_vma_add_new(struct vm_area_struct *vma) +{ + struct vma_slot *slot; + + if (!vma_can_enter(vma)) { + vma->uksm_vma_slot = NULL; + return; + } + + slot = alloc_vma_slot(); + if (!slot) { + vma->uksm_vma_slot = NULL; + return; + } + + vma->uksm_vma_slot = slot; + vma->vm_flags |= VM_MERGEABLE; + slot->vma = vma; + slot->mm = vma->vm_mm; + slot->ctime_j = jiffies; + slot->pages = vma_pages(vma); + spin_lock(&vma_slot_list_lock); + list_add_tail(&slot->slot_list, &vma_slot_new); + spin_unlock(&vma_slot_list_lock); +} + +/* + * Called after vma is unlinked from its mm + */ +void uksm_remove_vma(struct vm_area_struct *vma) +{ + struct vma_slot *slot; + + if (!vma->uksm_vma_slot) + return; + + slot = vma->uksm_vma_slot; + spin_lock(&vma_slot_list_lock); + if (slot_in_uksm(slot)) { + /** + * This slot has been added by ksmd, so move to the del list + * waiting ksmd to free it. + */ + list_add_tail(&slot->slot_list, &vma_slot_del); + } else { + /** + * It's still on new list. It's ok to free slot directly. + */ + list_del(&slot->slot_list); + free_vma_slot(slot); + } + spin_unlock(&vma_slot_list_lock); + vma->uksm_vma_slot = NULL; +} + +/* 32/3 < they < 32/2 */ +#define shiftl 8 +#define shiftr 12 + +#define HASH_FROM_TO(from, to) \ +for (index = from; index < to; index++) { \ + pos = random_nums[index]; \ + hash += key[pos]; \ + hash += (hash << shiftl); \ + hash ^= (hash >> shiftr); \ +} + + +#define HASH_FROM_DOWN_TO(from, to) \ +for (index = from - 1; index >= to; index--) { \ + hash ^= (hash >> shiftr); \ + hash ^= (hash >> (shiftr*2)); \ + hash -= (hash << shiftl); \ + hash += (hash << (shiftl*2)); \ + pos = random_nums[index]; \ + hash -= key[pos]; \ +} + +/* + * The main random sample hash function. + */ +static u32 random_sample_hash(void *addr, u32 hash_strength) +{ + u32 hash = 0xdeadbeef; + int index, pos, loop = hash_strength; + u32 *key = (u32 *)addr; + + if (loop > HASH_STRENGTH_FULL) + loop = HASH_STRENGTH_FULL; + + HASH_FROM_TO(0, loop); + + if (hash_strength > HASH_STRENGTH_FULL) { + loop = hash_strength - HASH_STRENGTH_FULL; + HASH_FROM_TO(0, loop); + } + + return hash; +} + + +/** + * It's used when hash strength is adjusted + * + * @addr The page's virtual address + * @from The original hash strength + * @to The hash strength changed to + * @hash The hash value generated with "from" hash value + * + * return the hash value + */ +static u32 delta_hash(void *addr, int from, int to, u32 hash) +{ + u32 *key = (u32 *)addr; + int index, pos; /* make sure they are int type */ + + if (to > from) { + if (from >= HASH_STRENGTH_FULL) { + from -= HASH_STRENGTH_FULL; + to -= HASH_STRENGTH_FULL; + HASH_FROM_TO(from, to); + } else if (to <= HASH_STRENGTH_FULL) { + HASH_FROM_TO(from, to); + } else { + HASH_FROM_TO(from, HASH_STRENGTH_FULL); + HASH_FROM_TO(0, to - HASH_STRENGTH_FULL); + } + } else { + if (from <= HASH_STRENGTH_FULL) { + HASH_FROM_DOWN_TO(from, to); + } else if (to >= HASH_STRENGTH_FULL) { + from -= HASH_STRENGTH_FULL; + to -= HASH_STRENGTH_FULL; + HASH_FROM_DOWN_TO(from, to); + } else { + HASH_FROM_DOWN_TO(from - HASH_STRENGTH_FULL, 0); + HASH_FROM_DOWN_TO(HASH_STRENGTH_FULL, to); + } + } + + return hash; +} + + + + +#define CAN_OVERFLOW_U64(x, delta) (U64_MAX - (x) < (delta)) + +/** + * + * Called when: rshash_pos or rshash_neg is about to overflow or a scan round + * has finished. + * + * return 0 if no page has been scanned since last call, 1 otherwise. + */ +static inline int encode_benefit(void) +{ + u64 scanned_delta, pos_delta, neg_delta; + unsigned long base = benefit.base; + + scanned_delta = uksm_pages_scanned - uksm_pages_scanned_last; + + if (!scanned_delta) + return 0; + + scanned_delta >>= base; + pos_delta = rshash_pos >> base; + neg_delta = rshash_neg >> base; + + if (CAN_OVERFLOW_U64(benefit.pos, pos_delta) || + CAN_OVERFLOW_U64(benefit.neg, neg_delta) || + CAN_OVERFLOW_U64(benefit.scanned, scanned_delta)) { + benefit.scanned >>= 1; + benefit.neg >>= 1; + benefit.pos >>= 1; + benefit.base++; + scanned_delta >>= 1; + pos_delta >>= 1; + neg_delta >>= 1; + } + + benefit.pos += pos_delta; + benefit.neg += neg_delta; + benefit.scanned += scanned_delta; + + BUG_ON(!benefit.scanned); + + rshash_pos = rshash_neg = 0; + uksm_pages_scanned_last = uksm_pages_scanned; + + return 1; +} + +static inline void reset_benefit(void) +{ + benefit.pos = 0; + benefit.neg = 0; + benefit.base = 0; + benefit.scanned = 0; +} + +static inline void inc_rshash_pos(unsigned long delta) +{ + if (CAN_OVERFLOW_U64(rshash_pos, delta)) + encode_benefit(); + + rshash_pos += delta; +} + +static inline void inc_rshash_neg(unsigned long delta) +{ + if (CAN_OVERFLOW_U64(rshash_neg, delta)) + encode_benefit(); + + rshash_neg += delta; +} + + +static inline u32 page_hash(struct page *page, unsigned long hash_strength, + int cost_accounting) +{ + u32 val; + unsigned long delta; + + void *addr = kmap_atomic(page); + + val = random_sample_hash(addr, hash_strength); + kunmap_atomic(addr); + + if (cost_accounting) { + if (HASH_STRENGTH_FULL > hash_strength) + delta = HASH_STRENGTH_FULL - hash_strength; + else + delta = 0; + + inc_rshash_pos(delta); + } + + return val; +} + +static int memcmp_pages(struct page *page1, struct page *page2, + int cost_accounting) +{ + char *addr1, *addr2; + int ret; + + addr1 = kmap_atomic(page1); + addr2 = kmap_atomic(page2); + ret = memcmp(addr1, addr2, PAGE_SIZE); + kunmap_atomic(addr2); + kunmap_atomic(addr1); + + if (cost_accounting) + inc_rshash_neg(memcmp_cost); + + return ret; +} + +static inline int pages_identical(struct page *page1, struct page *page2) +{ + return !memcmp_pages(page1, page2, 0); +} + +static inline int is_page_full_zero(struct page *page) +{ + char *addr; + int ret; + + addr = kmap_atomic(page); + ret = is_full_zero(addr, PAGE_SIZE); + kunmap_atomic(addr); + + return ret; +} + +static int write_protect_page(struct vm_area_struct *vma, struct page *page, + pte_t *orig_pte, pte_t *old_pte) +{ + struct mm_struct *mm = vma->vm_mm; + unsigned long addr; + pte_t *ptep; + spinlock_t *ptl; + int swapped; + int err = -EFAULT; + + addr = page_address_in_vma(page, vma); + if (addr == -EFAULT) + goto out; + + BUG_ON(PageTransCompound(page)); + ptep = page_check_address(page, mm, addr, &ptl, 0); + if (!ptep) + goto out; + + if (old_pte) + *old_pte = *ptep; + + if (pte_write(*ptep) || pte_dirty(*ptep)) { + pte_t entry; + + swapped = PageSwapCache(page); + flush_cache_page(vma, addr, page_to_pfn(page)); + /* + * Ok this is tricky, when get_user_pages_fast() run it doesnt + * take any lock, therefore the check that we are going to make + * with the pagecount against the mapcount is racey and + * O_DIRECT can happen right after the check. + * So we clear the pte and flush the tlb before the check + * this assure us that no O_DIRECT can happen after the check + * or in the middle of the check. + */ + entry = ptep_clear_flush(vma, addr, ptep); + /* + * Check that no O_DIRECT or similar I/O is in progress on the + * page + */ + if (page_mapcount(page) + 1 + swapped != page_count(page)) { + set_pte_at(mm, addr, ptep, entry); + goto out_unlock; + } + if (pte_dirty(entry)) + set_page_dirty(page); + entry = pte_mkclean(pte_wrprotect(entry)); + set_pte_at_notify(mm, addr, ptep, entry); + } + *orig_pte = *ptep; + err = 0; + +out_unlock: + pte_unmap_unlock(ptep, ptl); +out: + return err; +} + +#define MERGE_ERR_PGERR 1 /* the page is invalid cannot continue */ +#define MERGE_ERR_COLLI 2 /* there is a collision */ +#define MERGE_ERR_COLLI_MAX 3 /* collision at the max hash strength */ +#define MERGE_ERR_CHANGED 4 /* the page has changed since last hash */ + + +/** + * replace_page - replace page in vma by new ksm page + * @vma: vma that holds the pte pointing to page + * @page: the page we are replacing by kpage + * @kpage: the ksm page we replace page by + * @orig_pte: the original value of the pte + * + * Returns 0 on success, MERGE_ERR_PGERR on failure. + */ +static int replace_page(struct vm_area_struct *vma, struct page *page, + struct page *kpage, pte_t orig_pte) +{ + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *ptep; + spinlock_t *ptl; + pte_t entry; + + unsigned long addr; + int err = MERGE_ERR_PGERR; + + addr = page_address_in_vma(page, vma); + if (addr == -EFAULT) + goto out; + + pgd = pgd_offset(mm, addr); + if (!pgd_present(*pgd)) + goto out; + + pud = pud_offset(pgd, addr); + if (!pud_present(*pud)) + goto out; + + pmd = pmd_offset(pud, addr); + BUG_ON(pmd_trans_huge(*pmd)); + if (!pmd_present(*pmd)) + goto out; + + ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); + if (!pte_same(*ptep, orig_pte)) { + pte_unmap_unlock(ptep, ptl); + goto out; + } + + flush_cache_page(vma, addr, pte_pfn(*ptep)); + ptep_clear_flush(vma, addr, ptep); + entry = mk_pte(kpage, vma->vm_page_prot); + + /* special treatment is needed for zero_page */ + if ((page_to_pfn(kpage) == uksm_zero_pfn) || + (page_to_pfn(kpage) == zero_pfn)) + entry = pte_mkspecial(entry); + else { + get_page(kpage); + page_add_anon_rmap(kpage, vma, addr); + } + + set_pte_at_notify(mm, addr, ptep, entry); + + page_remove_rmap(page); + if (!page_mapped(page)) + try_to_free_swap(page); + put_page(page); + + pte_unmap_unlock(ptep, ptl); + err = 0; +out: + return err; +} + + +/** + * Fully hash a page with HASH_STRENGTH_MAX return a non-zero hash value. The + * zero hash value at HASH_STRENGTH_MAX is used to indicated that its + * hash_max member has not been calculated. + * + * @page The page needs to be hashed + * @hash_old The hash value calculated with current hash strength + * + * return the new hash value calculated at HASH_STRENGTH_MAX + */ +static inline u32 page_hash_max(struct page *page, u32 hash_old) +{ + u32 hash_max = 0; + void *addr; + + addr = kmap_atomic(page); + hash_max = delta_hash(addr, hash_strength, + HASH_STRENGTH_MAX, hash_old); + + kunmap_atomic(addr); + + if (!hash_max) + hash_max = 1; + + inc_rshash_neg(HASH_STRENGTH_MAX - hash_strength); + return hash_max; +} + +/* + * We compare the hash again, to ensure that it is really a hash collision + * instead of being caused by page write. + */ +static inline int check_collision(struct rmap_item *rmap_item, + u32 hash) +{ + int err; + struct page *page = rmap_item->page; + + /* if this rmap_item has already been hash_maxed, then the collision + * must appears in the second-level rbtree search. In this case we check + * if its hash_max value has been changed. Otherwise, the collision + * happens in the first-level rbtree search, so we check against it's + * current hash value. + */ + if (rmap_item->hash_max) { + inc_rshash_neg(memcmp_cost); + inc_rshash_neg(HASH_STRENGTH_MAX - hash_strength); + + if (rmap_item->hash_max == page_hash_max(page, hash)) + err = MERGE_ERR_COLLI; + else + err = MERGE_ERR_CHANGED; + } else { + inc_rshash_neg(memcmp_cost + hash_strength); + + if (page_hash(page, hash_strength, 0) == hash) + err = MERGE_ERR_COLLI; + else + err = MERGE_ERR_CHANGED; + } + + return err; +} + +static struct page *page_trans_compound_anon(struct page *page) +{ + if (PageTransCompound(page)) { + struct page *head = compound_trans_head(page); + /* + * head may actually be splitted and freed from under + * us but it's ok here. + */ + if (PageAnon(head)) + return head; + } + return NULL; +} + +static int page_trans_compound_anon_split(struct page *page) +{ + int ret = 0; + struct page *transhuge_head = page_trans_compound_anon(page); + if (transhuge_head) { + /* Get the reference on the head to split it. */ + if (get_page_unless_zero(transhuge_head)) { + /* + * Recheck we got the reference while the head + * was still anonymous. + */ + if (PageAnon(transhuge_head)) + ret = split_huge_page(transhuge_head); + else + /* + * Retry later if split_huge_page run + * from under us. + */ + ret = 1; + put_page(transhuge_head); + } else + /* Retry later if split_huge_page run from under us. */ + ret = 1; + } + return ret; +} + +/** + * Try to merge a rmap_item.page with a kpage in stable node. kpage must + * already be a ksm page. + * + * @return 0 if the pages were merged, -EFAULT otherwise. + */ +static int try_to_merge_with_uksm_page(struct rmap_item *rmap_item, + struct page *kpage, u32 hash) +{ + struct vm_area_struct *vma = rmap_item->slot->vma; + struct mm_struct *mm = vma->vm_mm; + pte_t orig_pte = __pte(0); + int err = MERGE_ERR_PGERR; + struct page *page; + + if (uksm_test_exit(mm)) + goto out; + + page = rmap_item->page; + + if (page == kpage) { /* ksm page forked */ + err = 0; + goto out; + } + + if (PageTransCompound(page) && page_trans_compound_anon_split(page)) + goto out; + BUG_ON(PageTransCompound(page)); + + if (!PageAnon(page) || !PageKsm(kpage)) + goto out; + + /* + * We need the page lock to read a stable PageSwapCache in + * write_protect_page(). We use trylock_page() instead of + * lock_page() because we don't want to wait here - we + * prefer to continue scanning and merging different pages, + * then come back to this page when it is unlocked. + */ + if (!trylock_page(page)) + goto out; + /* + * If this anonymous page is mapped only here, its pte may need + * to be write-protected. If it's mapped elsewhere, all of its + * ptes are necessarily already write-protected. But in either + * case, we need to lock and check page_count is not raised. + */ + if (write_protect_page(vma, page, &orig_pte, NULL) == 0) { + if (pages_identical(page, kpage)) + err = replace_page(vma, page, kpage, orig_pte); + else + err = check_collision(rmap_item, hash); + } + + if ((vma->vm_flags & VM_LOCKED) && kpage && !err) { + munlock_vma_page(page); + if (!PageMlocked(kpage)) { + unlock_page(page); + lock_page(kpage); + mlock_vma_page(kpage); + page = kpage; /* for final unlock */ + } + } + + unlock_page(page); +out: + return err; +} + + + +/** + * If two pages fail to merge in try_to_merge_two_pages, then we have a chance + * to restore a page mapping that has been changed in try_to_merge_two_pages. + * + * @return 0 on success. + */ +static int restore_uksm_page_pte(struct vm_area_struct *vma, unsigned long addr, + pte_t orig_pte, pte_t wprt_pte) +{ + struct mm_struct *mm = vma->vm_mm; + pgd_t *pgd; + pud_t *pud; + pmd_t *pmd; + pte_t *ptep; + spinlock_t *ptl; + + int err = -EFAULT; + + pgd = pgd_offset(mm, addr); + if (!pgd_present(*pgd)) + goto out; + + pud = pud_offset(pgd, addr); + if (!pud_present(*pud)) + goto out; + + pmd = pmd_offset(pud, addr); + if (!pmd_present(*pmd)) + goto out; + + ptep = pte_offset_map_lock(mm, pmd, addr, &ptl); + if (!pte_same(*ptep, wprt_pte)) { + /* already copied, let it be */ + pte_unmap_unlock(ptep, ptl); + goto out; + } + + /* + * Good boy, still here. When we still get the ksm page, it does not + * return to the free page pool, there is no way that a pte was changed + * to other page and gets back to this page. And remind that ksm page + * do not reuse in do_wp_page(). So it's safe to restore the original + * pte. + */ + flush_cache_page(vma, addr, pte_pfn(*ptep)); + ptep_clear_flush(vma, addr, ptep); + set_pte_at_notify(mm, addr, ptep, orig_pte); + + pte_unmap_unlock(ptep, ptl); + err = 0; +out: + return err; +} + +/** + * try_to_merge_two_pages() - take two identical pages and prepare + * them to be merged into one page(rmap_item->page) + * + * @return 0 if we successfully merged two identical pages into + * one ksm page. MERGE_ERR_COLLI if it's only a hash collision + * search in rbtree. MERGE_ERR_CHANGED if rmap_item has been + * changed since it's hashed. MERGE_ERR_PGERR otherwise. + * + */ +static int try_to_merge_two_pages(struct rmap_item *rmap_item, + struct rmap_item *tree_rmap_item, + u32 hash) +{ + pte_t orig_pte1 = __pte(0), orig_pte2 = __pte(0); + pte_t wprt_pte1 = __pte(0), wprt_pte2 = __pte(0); + struct vm_area_struct *vma1 = rmap_item->slot->vma; + struct vm_area_struct *vma2 = tree_rmap_item->slot->vma; + struct page *page = rmap_item->page; + struct page *tree_page = tree_rmap_item->page; + int err = MERGE_ERR_PGERR; + struct address_space *saved_mapping; + + + if (rmap_item->page == tree_rmap_item->page) + goto out; + + if (PageTransCompound(page) && page_trans_compound_anon_split(page)) + goto out; + BUG_ON(PageTransCompound(page)); + + if (PageTransCompound(tree_page) && page_trans_compound_anon_split(tree_page)) + goto out; + BUG_ON(PageTransCompound(tree_page)); + + if (!PageAnon(page) || !PageAnon(tree_page)) + goto out; + + if (!trylock_page(page)) + goto out; + + + if (write_protect_page(vma1, page, &wprt_pte1, &orig_pte1) != 0) { + unlock_page(page); + goto out; + } + + /* + * While we hold page lock, upgrade page from + * PageAnon+anon_vma to PageKsm+NULL stable_node: + * stable_tree_insert() will update stable_node. + */ + saved_mapping = page->mapping; + set_page_stable_node(page, NULL); + mark_page_accessed(page); + unlock_page(page); + + if (!trylock_page(tree_page)) + goto restore_out; + + if (write_protect_page(vma2, tree_page, &wprt_pte2, &orig_pte2) != 0) { + unlock_page(tree_page); + goto restore_out; + } + + if (pages_identical(page, tree_page)) { + err = replace_page(vma2, tree_page, page, wprt_pte2); + if (err) { + unlock_page(tree_page); + goto restore_out; + } + + if ((vma2->vm_flags & VM_LOCKED)) { + munlock_vma_page(tree_page); + if (!PageMlocked(page)) { + unlock_page(tree_page); + lock_page(page); + mlock_vma_page(page); + tree_page = page; /* for final unlock */ + } + } + + unlock_page(tree_page); + + goto out; /* success */ + + } else { + if (tree_rmap_item->hash_max && + tree_rmap_item->hash_max == rmap_item->hash_max) { + err = MERGE_ERR_COLLI_MAX; + } else if (page_hash(page, hash_strength, 0) == + page_hash(tree_page, hash_strength, 0)) { + inc_rshash_neg(memcmp_cost + hash_strength * 2); + err = MERGE_ERR_COLLI; + } else { + err = MERGE_ERR_CHANGED; + } + + unlock_page(tree_page); + } + +restore_out: + lock_page(page); + if (!restore_uksm_page_pte(vma1, get_rmap_addr(rmap_item), + orig_pte1, wprt_pte1)) + page->mapping = saved_mapping; + + unlock_page(page); +out: + return err; +} + +static inline int hash_cmp(u32 new_val, u32 node_val) +{ + if (new_val > node_val) + return 1; + else if (new_val < node_val) + return -1; + else + return 0; +} + +static inline u32 rmap_item_hash_max(struct rmap_item *item, u32 hash) +{ + u32 hash_max = item->hash_max; + + if (!hash_max) { + hash_max = page_hash_max(item->page, hash); + + item->hash_max = hash_max; + } + + return hash_max; +} + + + +/** + * stable_tree_search() - search the stable tree for a page + * + * @item: the rmap_item we are comparing with + * @hash: the hash value of this item->page already calculated + * + * @return the page we have found, NULL otherwise. The page returned has + * been gotten. + */ +static struct page *stable_tree_search(struct rmap_item *item, u32 hash) +{ + struct rb_node *node = root_stable_treep->rb_node; + struct tree_node *tree_node; + unsigned long hash_max; + struct page *page = item->page; + struct stable_node *stable_node; + + stable_node = page_stable_node(page); + if (stable_node) { + /* ksm page forked, that is + * if (PageKsm(page) && !in_stable_tree(rmap_item)) + * it's actually gotten once outside. + */ + get_page(page); + return page; + } + + while (node) { + int cmp; + + tree_node = rb_entry(node, struct tree_node, node); + + cmp = hash_cmp(hash, tree_node->hash); + + if (cmp < 0) + node = node->rb_left; + else if (cmp > 0) + node = node->rb_right; + else + break; + } + + if (!node) + return NULL; + + if (tree_node->count == 1) { + stable_node = rb_entry(tree_node->sub_root.rb_node, + struct stable_node, node); + BUG_ON(!stable_node); + + goto get_page_out; + } + + /* + * ok, we have to search the second + * level subtree, hash the page to a + * full strength. + */ + node = tree_node->sub_root.rb_node; + BUG_ON(!node); + hash_max = rmap_item_hash_max(item, hash); + + while (node) { + int cmp; + + stable_node = rb_entry(node, struct stable_node, node); + + cmp = hash_cmp(hash_max, stable_node->hash_max); + + if (cmp < 0) + node = node->rb_left; + else if (cmp > 0) + node = node->rb_right; + else + goto get_page_out; + } + + return NULL; + +get_page_out: + page = get_uksm_page(stable_node, 1, 1); + return page; +} + +static int try_merge_rmap_item(struct rmap_item *item, + struct page *kpage, + struct page *tree_page) +{ + spinlock_t *ptl; + pte_t *ptep; + unsigned long addr; + struct vm_area_struct *vma = item->slot->vma; + + addr = get_rmap_addr(item); + ptep = page_check_address(kpage, vma->vm_mm, addr, &ptl, 0); + if (!ptep) + return 0; + + if (pte_write(*ptep)) { + /* has changed, abort! */ + pte_unmap_unlock(ptep, ptl); + return 0; + } + + get_page(tree_page); + page_add_anon_rmap(tree_page, vma, addr); + + flush_cache_page(vma, addr, pte_pfn(*ptep)); + ptep_clear_flush(vma, addr, ptep); + set_pte_at_notify(vma->vm_mm, addr, ptep, + mk_pte(tree_page, vma->vm_page_prot)); + + page_remove_rmap(kpage); + put_page(kpage); + + pte_unmap_unlock(ptep, ptl); + + return 1; +} + +/** + * try_to_merge_with_stable_page() - when two rmap_items need to be inserted + * into stable tree, the page was found to be identical to a stable ksm page, + * this is the last chance we can merge them into one. + * + * @item1: the rmap_item holding the page which we wanted to insert + * into stable tree. + * @item2: the other rmap_item we found when unstable tree search + * @oldpage: the page currently mapped by the two rmap_items + * @tree_page: the page we found identical in stable tree node + * @success1: return if item1 is successfully merged + * @success2: return if item2 is successfully merged + */ +static void try_merge_with_stable(struct rmap_item *item1, + struct rmap_item *item2, + struct page **kpage, + struct page *tree_page, + int *success1, int *success2) +{ + struct vm_area_struct *vma1 = item1->slot->vma; + struct vm_area_struct *vma2 = item2->slot->vma; + *success1 = 0; + *success2 = 0; + + if (unlikely(*kpage == tree_page)) { + /* I don't think this can really happen */ + printk(KERN_WARNING "UKSM: unexpected condition detected in " + "try_merge_with_stable() -- *kpage == tree_page !\n"); + *success1 = 1; + *success2 = 1; + return; + } + + if (!PageAnon(*kpage) || !PageKsm(*kpage)) + goto failed; + + if (!trylock_page(tree_page)) + goto failed; + + /* If the oldpage is still ksm and still pointed + * to in the right place, and still write protected, + * we are confident it's not changed, no need to + * memcmp anymore. + * be ware, we cannot take nested pte locks, + * deadlock risk. + */ + if (!try_merge_rmap_item(item1, *kpage, tree_page)) + goto unlock_failed; + + /* ok, then vma2, remind that pte1 already set */ + if (!try_merge_rmap_item(item2, *kpage, tree_page)) + goto success_1; + + *success2 = 1; +success_1: + *success1 = 1; + + + if ((*success1 && vma1->vm_flags & VM_LOCKED) || + (*success2 && vma2->vm_flags & VM_LOCKED)) { + munlock_vma_page(*kpage); + if (!PageMlocked(tree_page)) + mlock_vma_page(tree_page); + } + + /* + * We do not need oldpage any more in the caller, so can break the lock + * now. + */ + unlock_page(*kpage); + *kpage = tree_page; /* Get unlocked outside. */ + return; + +unlock_failed: + unlock_page(tree_page); +failed: + return; +} + +static inline void stable_node_hash_max(struct stable_node *node, + struct page *page, u32 hash) +{ + u32 hash_max = node->hash_max; + + if (!hash_max) { + hash_max = page_hash_max(page, hash); + node->hash_max = hash_max; + } +} + +static inline +struct stable_node *new_stable_node(struct tree_node *tree_node, + struct page *kpage, u32 hash_max) +{ + struct stable_node *new_stable_node; + + new_stable_node = alloc_stable_node(); + if (!new_stable_node) + return NULL; + + new_stable_node->kpfn = page_to_pfn(kpage); + new_stable_node->hash_max = hash_max; + new_stable_node->tree_node = tree_node; + set_page_stable_node(kpage, new_stable_node); + + return new_stable_node; +} + +static inline +struct stable_node *first_level_insert(struct tree_node *tree_node, + struct rmap_item *rmap_item, + struct rmap_item *tree_rmap_item, + struct page **kpage, u32 hash, + int *success1, int *success2) +{ + int cmp; + struct page *tree_page; + u32 hash_max = 0; + struct stable_node *stable_node, *new_snode; + struct rb_node *parent = NULL, **new; + + /* this tree node contains no sub-tree yet */ + stable_node = rb_entry(tree_node->sub_root.rb_node, + struct stable_node, node); + + tree_page = get_uksm_page(stable_node, 1, 0); + if (tree_page) { + cmp = memcmp_pages(*kpage, tree_page, 1); + if (!cmp) { + try_merge_with_stable(rmap_item, tree_rmap_item, kpage, + tree_page, success1, success2); + put_page(tree_page); + if (!*success1 && !*success2) + goto failed; + + return stable_node; + + } else { + /* + * collision in first level try to create a subtree. + * A new node need to be created. + */ + put_page(tree_page); + + stable_node_hash_max(stable_node, tree_page, + tree_node->hash); + hash_max = rmap_item_hash_max(rmap_item, hash); + cmp = hash_cmp(hash_max, stable_node->hash_max); + + parent = &stable_node->node; + if (cmp < 0) { + new = &parent->rb_left; + } else if (cmp > 0) { + new = &parent->rb_right; + } else { + goto failed; + } + } + + } else { + /* the only stable_node deleted, we reuse its tree_node. + */ + parent = NULL; + new = &tree_node->sub_root.rb_node; + } + + new_snode = new_stable_node(tree_node, *kpage, hash_max); + if (!new_snode) + goto failed; + + rb_link_node(&new_snode->node, parent, new); + rb_insert_color(&new_snode->node, &tree_node->sub_root); + tree_node->count++; + *success1 = *success2 = 1; + + return new_snode; + +failed: + return NULL; +} + +static inline +struct stable_node *stable_subtree_insert(struct tree_node *tree_node, + struct rmap_item *rmap_item, + struct rmap_item *tree_rmap_item, + struct page **kpage, u32 hash, + int *success1, int *success2) +{ + struct page *tree_page; + u32 hash_max; + struct stable_node *stable_node, *new_snode; + struct rb_node *parent, **new; + +research: + parent = NULL; + new = &tree_node->sub_root.rb_node; + BUG_ON(!*new); + hash_max = rmap_item_hash_max(rmap_item, hash); + while (*new) { + int cmp; + + stable_node = rb_entry(*new, struct stable_node, node); + + cmp = hash_cmp(hash_max, stable_node->hash_max); + + if (cmp < 0) { + parent = *new; + new = &parent->rb_left; + } else if (cmp > 0) { + parent = *new; + new = &parent->rb_right; + } else { + tree_page = get_uksm_page(stable_node, 1, 0); + if (tree_page) { + cmp = memcmp_pages(*kpage, tree_page, 1); + if (!cmp) { + try_merge_with_stable(rmap_item, + tree_rmap_item, kpage, + tree_page, success1, success2); + + put_page(tree_page); + if (!*success1 && !*success2) + goto failed; + /* + * successfully merged with a stable + * node + */ + return stable_node; + } else { + put_page(tree_page); + goto failed; + } + } else { + /* + * stable node may be deleted, + * and subtree maybe + * restructed, cannot + * continue, research it. + */ + if (tree_node->count) { + goto research; + } else { + /* reuse the tree node*/ + parent = NULL; + new = &tree_node->sub_root.rb_node; + } + } + } + } + + new_snode = new_stable_node(tree_node, *kpage, hash_max); + if (!new_snode) + goto failed; + + rb_link_node(&new_snode->node, parent, new); + rb_insert_color(&new_snode->node, &tree_node->sub_root); + tree_node->count++; + *success1 = *success2 = 1; + + return new_snode; + +failed: + return NULL; +} + + +/** + * stable_tree_insert() - try to insert a merged page in unstable tree to + * the stable tree + * + * @kpage: the page need to be inserted + * @hash: the current hash of this page + * @rmap_item: the rmap_item being scanned + * @tree_rmap_item: the rmap_item found on unstable tree + * @success1: return if rmap_item is merged + * @success2: return if tree_rmap_item is merged + * + * @return the stable_node on stable tree if at least one + * rmap_item is inserted into stable tree, NULL + * otherwise. + */ +static struct stable_node * +stable_tree_insert(struct page **kpage, u32 hash, + struct rmap_item *rmap_item, + struct rmap_item *tree_rmap_item, + int *success1, int *success2) +{ + struct rb_node **new = &root_stable_treep->rb_node; + struct rb_node *parent = NULL; + struct stable_node *stable_node; + struct tree_node *tree_node; + u32 hash_max = 0; + + *success1 = *success2 = 0; + + while (*new) { + int cmp; + + tree_node = rb_entry(*new, struct tree_node, node); + + cmp = hash_cmp(hash, tree_node->hash); + + if (cmp < 0) { + parent = *new; + new = &parent->rb_left; + } else if (cmp > 0) { + parent = *new; + new = &parent->rb_right; + } else + break; + } + + if (*new) { + if (tree_node->count == 1) { + stable_node = first_level_insert(tree_node, rmap_item, + tree_rmap_item, kpage, + hash, success1, success2); + } else { + stable_node = stable_subtree_insert(tree_node, + rmap_item, tree_rmap_item, kpage, + hash, success1, success2); + } + } else { + + /* no tree node found */ + tree_node = alloc_tree_node(stable_tree_node_listp); + if (!tree_node) { + stable_node = NULL; + goto out; + } + + stable_node = new_stable_node(tree_node, *kpage, hash_max); + if (!stable_node) { + free_tree_node(tree_node); + goto out; + } + + tree_node->hash = hash; + rb_link_node(&tree_node->node, parent, new); + rb_insert_color(&tree_node->node, root_stable_treep); + parent = NULL; + new = &tree_node->sub_root.rb_node; + + rb_link_node(&stable_node->node, parent, new); + rb_insert_color(&stable_node->node, &tree_node->sub_root); + tree_node->count++; + *success1 = *success2 = 1; + } + +out: + return stable_node; +} + + +/** + * get_tree_rmap_item_page() - try to get the page and lock the mmap_sem + * + * @return 0 on success, -EBUSY if unable to lock the mmap_sem, + * -EINVAL if the page mapping has been changed. + */ +static inline int get_tree_rmap_item_page(struct rmap_item *tree_rmap_item) +{ + int err; + + err = get_mergeable_page_lock_mmap(tree_rmap_item); + + if (err == -EINVAL) { + /* its page map has been changed, remove it */ + remove_rmap_item_from_tree(tree_rmap_item); + } + + /* The page is gotten and mmap_sem is locked now. */ + return err; +} + + +/** + * unstable_tree_search_insert() - search an unstable tree rmap_item with the + * same hash value. Get its page and trylock the mmap_sem + */ +static inline +struct rmap_item *unstable_tree_search_insert(struct rmap_item *rmap_item, + u32 hash) + +{ + struct rb_node **new = &root_unstable_tree.rb_node; + struct rb_node *parent = NULL; + struct tree_node *tree_node; + u32 hash_max; + struct rmap_item *tree_rmap_item; + + while (*new) { + int cmp; + + tree_node = rb_entry(*new, struct tree_node, node); + + cmp = hash_cmp(hash, tree_node->hash); + + if (cmp < 0) { + parent = *new; + new = &parent->rb_left; + } else if (cmp > 0) { + parent = *new; + new = &parent->rb_right; + } else + break; + } + + if (*new) { + /* got the tree_node */ + if (tree_node->count == 1) { + tree_rmap_item = rb_entry(tree_node->sub_root.rb_node, + struct rmap_item, node); + BUG_ON(!tree_rmap_item); + + goto get_page_out; + } + + /* well, search the collision subtree */ + new = &tree_node->sub_root.rb_node; + BUG_ON(!*new); + hash_max = rmap_item_hash_max(rmap_item, hash); + + while (*new) { + int cmp; + + tree_rmap_item = rb_entry(*new, struct rmap_item, + node); + + cmp = hash_cmp(hash_max, tree_rmap_item->hash_max); + parent = *new; + if (cmp < 0) + new = &parent->rb_left; + else if (cmp > 0) + new = &parent->rb_right; + else + goto get_page_out; + } + } else { + /* alloc a new tree_node */ + tree_node = alloc_tree_node(&unstable_tree_node_list); + if (!tree_node) + return NULL; + + tree_node->hash = hash; + rb_link_node(&tree_node->node, parent, new); + rb_insert_color(&tree_node->node, &root_unstable_tree); + parent = NULL; + new = &tree_node->sub_root.rb_node; + } + + /* did not found even in sub-tree */ + rmap_item->tree_node = tree_node; + rmap_item->address |= UNSTABLE_FLAG; + rmap_item->hash_round = uksm_hash_round; + rb_link_node(&rmap_item->node, parent, new); + rb_insert_color(&rmap_item->node, &tree_node->sub_root); + + uksm_pages_unshared++; + return NULL; + +get_page_out: + if (tree_rmap_item->page == rmap_item->page) + return NULL; + + if (get_tree_rmap_item_page(tree_rmap_item)) + return NULL; + + return tree_rmap_item; +} + +static void hold_anon_vma(struct rmap_item *rmap_item, + struct anon_vma *anon_vma) +{ + rmap_item->anon_vma = anon_vma; + get_anon_vma(anon_vma); +} + + +/** + * stable_tree_append() - append a rmap_item to a stable node. Deduplication + * ratio statistics is done in this function. + * + */ +static void stable_tree_append(struct rmap_item *rmap_item, + struct stable_node *stable_node, int logdedup) +{ + struct node_vma *node_vma = NULL, *new_node_vma; + struct hlist_node *hlist = NULL, *cont_p = NULL; + unsigned long key = (unsigned long)rmap_item->slot; + unsigned long factor = rmap_item->slot->rung->step; + + BUG_ON(!stable_node); + rmap_item->address |= STABLE_FLAG; + + if (hlist_empty(&stable_node->hlist)) { + uksm_pages_shared++; + goto node_vma_new; + } else { + uksm_pages_sharing++; + } + + hlist_for_each_entry(node_vma, hlist, &stable_node->hlist, hlist) { + if (node_vma->key >= key) + break; + + if (logdedup) { + node_vma->slot->pages_bemerged += factor; + if (list_empty(&node_vma->slot->dedup_list)) + list_add(&node_vma->slot->dedup_list, + &vma_slot_dedup); + } + } + + if (node_vma) { + if (node_vma->key == key) { + cont_p = hlist->next; + goto node_vma_ok; + } else if (node_vma->key > key) { + cont_p = hlist; + } + } + +node_vma_new: + /* no same vma already in node, alloc a new node_vma */ + new_node_vma = alloc_node_vma(); + BUG_ON(!new_node_vma); + new_node_vma->head = stable_node; + new_node_vma->slot = rmap_item->slot; + + if (!node_vma) { + hlist_add_head(&new_node_vma->hlist, &stable_node->hlist); + } else if (node_vma->key != key) { + if (node_vma->key < key) + hlist_add_after(&node_vma->hlist, &new_node_vma->hlist); + else { + hlist_add_before(&new_node_vma->hlist, + &node_vma->hlist); + } + + } + node_vma = new_node_vma; + +node_vma_ok: /* ok, ready to add to the list */ + rmap_item->head = node_vma; + hlist_add_head(&rmap_item->hlist, &node_vma->rmap_hlist); + hold_anon_vma(rmap_item, rmap_item->slot->vma->anon_vma); + if (logdedup) { + rmap_item->slot->pages_merged++; + if (cont_p) { + hlist_for_each_entry_continue(node_vma, + cont_p, hlist) { + node_vma->slot->pages_bemerged += factor; + if (list_empty(&node_vma->slot->dedup_list)) + list_add(&node_vma->slot->dedup_list, + &vma_slot_dedup); + } + } + } +} + +/* + * We use break_ksm to break COW on a ksm page: it's a stripped down + * + * if (get_user_pages(current, mm, addr, 1, 1, 1, &page, NULL) == 1) + * put_page(page); + * + * but taking great care only to touch a ksm page, in a VM_MERGEABLE vma, + * in case the application has unmapped and remapped mm,addr meanwhile. + * Could a ksm page appear anywhere else? Actually yes, in a VM_PFNMAP + * mmap of /dev/mem or /dev/kmem, where we would not want to touch it. + */ +static int break_ksm(struct vm_area_struct *vma, unsigned long addr) +{ + struct page *page; + int ret = 0; + + do { + cond_resched(); + page = follow_page(vma, addr, FOLL_GET); + if (IS_ERR_OR_NULL(page)) + break; + if (PageKsm(page)) { + ret = handle_mm_fault(vma->vm_mm, vma, addr, + FAULT_FLAG_WRITE); + } else + ret = VM_FAULT_WRITE; + put_page(page); + } while (!(ret & (VM_FAULT_WRITE | VM_FAULT_SIGBUS | 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. + * + * VM_FAULT_WRITE is what we have been hoping for: it indicates that + * COW has been broken, even if the vma does not permit VM_WRITE; + * but note that a concurrent fault might break PageKsm for us. + * + * VM_FAULT_SIGBUS could occur if we race with truncation of the + * backing file, which also invalidates anonymous pages: that's + * okay, that truncation will have unmapped the PageKsm for us. + * + * VM_FAULT_OOM: at the time of writing (late July 2009), setting + * aside mem_cgroup limits, VM_FAULT_OOM would only be set if the + * current task has TIF_MEMDIE set, and will be OOM killed on return + * to user; and ksmd, having no mm, would never be chosen for that. + * + * But if the mm is in a limited mem_cgroup, then the fault may fail + * with VM_FAULT_OOM even if the current task is not TIF_MEMDIE; and + * even ksmd can fail in this way - though it's usually breaking ksm + * just to undo a merge it made a moment before, so unlikely to oom. + * + * That's a pity: we might therefore have more kernel pages allocated + * than we're counting as nodes in the stable tree; but uksm_do_scan + * will retry to break_cow on each pass, so should recover the page + * in due course. The important thing is to not let VM_MERGEABLE + * be cleared while any such pages might remain in the area. + */ + return (ret & VM_FAULT_OOM) ? -ENOMEM : 0; +} + +static void break_cow(struct rmap_item *rmap_item) +{ + struct vm_area_struct *vma = rmap_item->slot->vma; + struct mm_struct *mm = vma->vm_mm; + unsigned long addr = get_rmap_addr(rmap_item); + + if (uksm_test_exit(mm)) + goto out; + + break_ksm(vma, addr); +out: + return; +} + +/* + * Though it's very tempting to unmerge in_stable_tree(rmap_item)s rather + * than check every pte of a given vma, the locking doesn't quite work for + * that - an rmap_item is assigned to the stable tree after inserting ksm + * page and upping mmap_sem. Nor does it fit with the way we skip dup'ing + * rmap_items from parent to child at fork time (so as not to waste time + * if exit comes before the next scan reaches it). + * + * Similarly, although we'd like to remove rmap_items (so updating counts + * and freeing memory) when unmerging an area, it's easier to leave that + * to the next pass of ksmd - consider, for example, how ksmd might be + * in cmp_and_merge_page on one of the rmap_items we would be removing. + */ +inline int unmerge_uksm_pages(struct vm_area_struct *vma, + unsigned long start, unsigned long end) +{ + unsigned long addr; + int err = 0; + + for (addr = start; addr < end && !err; addr += PAGE_SIZE) { + if (uksm_test_exit(vma->vm_mm)) + break; + if (signal_pending(current)) + err = -ERESTARTSYS; + else + err = break_ksm(vma, addr); + } + return err; +} + +static inline void inc_uksm_pages_scanned(void) +{ + u64 delta; + + + if (uksm_pages_scanned == U64_MAX) { + encode_benefit(); + + delta = uksm_pages_scanned >> pages_scanned_base; + + if (CAN_OVERFLOW_U64(pages_scanned_stored, delta)) { + pages_scanned_stored >>= 1; + delta >>= 1; + pages_scanned_base++; + } + + pages_scanned_stored += delta; + + uksm_pages_scanned = uksm_pages_scanned_last = 0; + } + + uksm_pages_scanned++; +} + +static inline int find_zero_page_hash(int strength, u32 hash) +{ + return (zero_hash_table[strength] == hash); +} + +static +int cmp_and_merge_zero_page(struct vm_area_struct *vma, struct page *page) +{ + struct page *zero_page = empty_uksm_zero_page; + struct mm_struct *mm = vma->vm_mm; + pte_t orig_pte = __pte(0); + int err = -EFAULT; + + if (uksm_test_exit(mm)) + goto out; + + if (PageTransCompound(page) && page_trans_compound_anon_split(page)) + goto out; + BUG_ON(PageTransCompound(page)); + + if (!PageAnon(page)) + goto out; + + if (!trylock_page(page)) + goto out; + + if (write_protect_page(vma, page, &orig_pte, 0) == 0) { + if (is_page_full_zero(page)) + err = replace_page(vma, page, zero_page, orig_pte); + } + + unlock_page(page); +out: + return err; +} + +/* + * cmp_and_merge_page() - first see if page can be merged into the stable + * tree; if not, compare hash to previous and if it's the same, see if page + * can be inserted into the unstable tree, or merged with a page already there + * and both transferred to the stable tree. + * + * @page: the page that we are searching identical page to. + * @rmap_item: the reverse mapping into the virtual address of this page + */ +static void cmp_and_merge_page(struct rmap_item *rmap_item, u32 hash) +{ + struct rmap_item *tree_rmap_item; + struct page *page; + struct page *kpage = NULL; + u32 hash_max; + int err; + unsigned int success1, success2; + struct stable_node *snode; + int cmp; + struct rb_node *parent = NULL, **new; + + remove_rmap_item_from_tree(rmap_item); + page = rmap_item->page; + + /* We first start with searching the page inside the stable tree */ + kpage = stable_tree_search(rmap_item, hash); + if (kpage) { + err = try_to_merge_with_uksm_page(rmap_item, kpage, + hash); + if (!err) { + /* + * The page was successfully merged, add + * its rmap_item to the stable tree. + * page lock is needed because it's + * racing with try_to_unmap_ksm(), etc. + */ + lock_page(kpage); + snode = page_stable_node(kpage); + stable_tree_append(rmap_item, snode, 1); + unlock_page(kpage); + put_page(kpage); + return; /* success */ + } + put_page(kpage); + + /* + * if it's a collision and it has been search in sub-rbtree + * (hash_max != 0), we want to abort, because if it is + * successfully merged in unstable tree, the collision trends to + * happen again. + */ + if (err == MERGE_ERR_COLLI && rmap_item->hash_max) + return; + } + + tree_rmap_item = + unstable_tree_search_insert(rmap_item, hash); + if (tree_rmap_item) { + err = try_to_merge_two_pages(rmap_item, tree_rmap_item, hash); + /* + * As soon as we merge this page, we want to remove the + * rmap_item of the page we have merged with from the unstable + * tree, and insert it instead as new node in the stable tree. + */ + if (!err) { + kpage = page; + remove_rmap_item_from_tree(tree_rmap_item); + lock_page(kpage); + snode = stable_tree_insert(&kpage, hash, + rmap_item, tree_rmap_item, + &success1, &success2); + + /* + * Do not log dedup for tree item, it's not counted as + * scanned in this round. + */ + if (success2) + stable_tree_append(tree_rmap_item, snode, 0); + + /* + * The order of these two stable append is important: + * we are scanning rmap_item. + */ + if (success1) + stable_tree_append(rmap_item, snode, 1); + + /* + * The original kpage may be unlocked inside + * stable_tree_insert() already. This page + * should be unlocked before doing + * break_cow(). + */ + unlock_page(kpage); + + if (!success1) + break_cow(rmap_item); + + if (!success2) + break_cow(tree_rmap_item); + + } else if (err == MERGE_ERR_COLLI) { + BUG_ON(tree_rmap_item->tree_node->count > 1); + + rmap_item_hash_max(tree_rmap_item, + tree_rmap_item->tree_node->hash); + + hash_max = rmap_item_hash_max(rmap_item, hash); + cmp = hash_cmp(hash_max, tree_rmap_item->hash_max); + parent = &tree_rmap_item->node; + if (cmp < 0) + new = &parent->rb_left; + else if (cmp > 0) + new = &parent->rb_right; + else + goto put_up_out; + + rmap_item->tree_node = tree_rmap_item->tree_node; + rmap_item->address |= UNSTABLE_FLAG; + rmap_item->hash_round = uksm_hash_round; + rb_link_node(&rmap_item->node, parent, new); + rb_insert_color(&rmap_item->node, + &tree_rmap_item->tree_node->sub_root); + rmap_item->tree_node->count++; + } else { + /* + * either one of the page has changed or they collide + * at the max hash, we consider them as ill items. + */ + remove_rmap_item_from_tree(tree_rmap_item); + } +put_up_out: + put_page(tree_rmap_item->page); + up_read(&tree_rmap_item->slot->vma->vm_mm->mmap_sem); + } +} + + + + +static inline unsigned long get_pool_index(struct vma_slot *slot, + unsigned long index) +{ + unsigned long pool_index; + + pool_index = (sizeof(struct rmap_list_entry *) * index) >> PAGE_SHIFT; + if (pool_index >= slot->pool_size) + BUG(); + return pool_index; +} + +static inline unsigned long index_page_offset(unsigned long index) +{ + return offset_in_page(sizeof(struct rmap_list_entry *) * index); +} + +static inline +struct rmap_list_entry *get_rmap_list_entry(struct vma_slot *slot, + unsigned long index, int need_alloc) +{ + unsigned long pool_index; + struct page *page; + void *addr; + + + pool_index = get_pool_index(slot, index); + if (!slot->rmap_list_pool[pool_index]) { + if (!need_alloc) + return NULL; + + page = alloc_page(GFP_KERNEL | __GFP_ZERO | __GFP_NOWARN); + if (!page) + return NULL; + + slot->rmap_list_pool[pool_index] = page; + } + + addr = kmap(slot->rmap_list_pool[pool_index]); + addr += index_page_offset(index); + + return addr; +} + +static inline void put_rmap_list_entry(struct vma_slot *slot, + unsigned long index) +{ + unsigned long pool_index; + + pool_index = get_pool_index(slot, index); + BUG_ON(!slot->rmap_list_pool[pool_index]); + kunmap(slot->rmap_list_pool[pool_index]); +} + +static inline int entry_is_new(struct rmap_list_entry *entry) +{ + return !entry->item; +} + +static inline unsigned long get_index_orig_addr(struct vma_slot *slot, + unsigned long index) +{ + return slot->vma->vm_start + (index << PAGE_SHIFT); +} + +static inline unsigned long get_entry_address(struct rmap_list_entry *entry) +{ + unsigned long addr; + + if (is_addr(entry->addr)) + addr = get_clean_addr(entry->addr); + else if (entry->item) + addr = get_rmap_addr(entry->item); + else + BUG(); + + return addr; +} + +static inline struct rmap_item *get_entry_item(struct rmap_list_entry *entry) +{ + if (is_addr(entry->addr)) + return NULL; + + return entry->item; +} + +static inline void inc_rmap_list_pool_count(struct vma_slot *slot, + unsigned long index) +{ + unsigned long pool_index; + + pool_index = get_pool_index(slot, index); + BUG_ON(!slot->rmap_list_pool[pool_index]); + slot->pool_counts[pool_index]++; +} + +static inline void dec_rmap_list_pool_count(struct vma_slot *slot, + unsigned long index) +{ + unsigned long pool_index; + + pool_index = get_pool_index(slot, index); + BUG_ON(!slot->rmap_list_pool[pool_index]); + BUG_ON(!slot->pool_counts[pool_index]); + slot->pool_counts[pool_index]--; +} + +static inline int entry_has_rmap(struct rmap_list_entry *entry) +{ + return !is_addr(entry->addr) && entry->item; +} + +static inline void swap_entries(struct rmap_list_entry *entry1, + unsigned long index1, + struct rmap_list_entry *entry2, + unsigned long index2) +{ + struct rmap_list_entry tmp; + + /* swapping two new entries is meaningless */ + BUG_ON(entry_is_new(entry1) && entry_is_new(entry2)); + + tmp = *entry1; + *entry1 = *entry2; + *entry2 = tmp; + + if (entry_has_rmap(entry1)) + entry1->item->entry_index = index1; + + if (entry_has_rmap(entry2)) + entry2->item->entry_index = index2; + + if (entry_has_rmap(entry1) && !entry_has_rmap(entry2)) { + inc_rmap_list_pool_count(entry1->item->slot, index1); + dec_rmap_list_pool_count(entry1->item->slot, index2); + } else if (!entry_has_rmap(entry1) && entry_has_rmap(entry2)) { + inc_rmap_list_pool_count(entry2->item->slot, index2); + dec_rmap_list_pool_count(entry2->item->slot, index1); + } +} + +static inline void free_entry_item(struct rmap_list_entry *entry) +{ + unsigned long index; + struct rmap_item *item; + + if (!is_addr(entry->addr)) { + BUG_ON(!entry->item); + item = entry->item; + entry->addr = get_rmap_addr(item); + set_is_addr(entry->addr); + index = item->entry_index; + remove_rmap_item_from_tree(item); + dec_rmap_list_pool_count(item->slot, index); + free_rmap_item(item); + } +} + +static inline int pool_entry_boundary(unsigned long index) +{ + unsigned long linear_addr; + + linear_addr = sizeof(struct rmap_list_entry *) * index; + return index && !offset_in_page(linear_addr); +} + +static inline void try_free_last_pool(struct vma_slot *slot, + unsigned long index) +{ + unsigned long pool_index; + + pool_index = get_pool_index(slot, index); + if (slot->rmap_list_pool[pool_index] && + !slot->pool_counts[pool_index]) { + __free_page(slot->rmap_list_pool[pool_index]); + slot->rmap_list_pool[pool_index] = NULL; + slot->flags |= UKSM_SLOT_NEED_SORT; + } + +} + +static inline unsigned long vma_item_index(struct vm_area_struct *vma, + struct rmap_item *item) +{ + return (get_rmap_addr(item) - vma->vm_start) >> PAGE_SHIFT; +} + +static int within_same_pool(struct vma_slot *slot, + unsigned long i, unsigned long j) +{ + unsigned long pool_i, pool_j; + + pool_i = get_pool_index(slot, i); + pool_j = get_pool_index(slot, j); + + return (pool_i == pool_j); +} + +static void sort_rmap_entry_list(struct vma_slot *slot) +{ + unsigned long i, j; + struct rmap_list_entry *entry, *swap_entry; + + entry = get_rmap_list_entry(slot, 0, 0); + for (i = 0; i < slot->pages; ) { + + if (!entry) + goto skip_whole_pool; + + if (entry_is_new(entry)) + goto next_entry; + + if (is_addr(entry->addr)) { + entry->addr = 0; + goto next_entry; + } + + j = vma_item_index(slot->vma, entry->item); + if (j == i) + goto next_entry; + + if (within_same_pool(slot, i, j)) + swap_entry = entry + j - i; + else + swap_entry = get_rmap_list_entry(slot, j, 1); + + swap_entries(entry, i, swap_entry, j); + if (!within_same_pool(slot, i, j)) + put_rmap_list_entry(slot, j); + continue; + +skip_whole_pool: + i += PAGE_SIZE / sizeof(*entry); + if (i < slot->pages) + entry = get_rmap_list_entry(slot, i, 0); + continue; + +next_entry: + if (i >= slot->pages - 1 || + !within_same_pool(slot, i, i + 1)) { + put_rmap_list_entry(slot, i); + if (i + 1 < slot->pages) + entry = get_rmap_list_entry(slot, i + 1, 0); + } else + entry++; + i++; + continue; + } + + /* free empty pool entries which contain no rmap_item */ + /* CAN be simplied to based on only pool_counts when bug freed !!!!! */ + for (i = 0; i < slot->pool_size; i++) { + unsigned char has_rmap; + void *addr; + + if (!slot->rmap_list_pool[i]) + continue; + + has_rmap = 0; + addr = kmap(slot->rmap_list_pool[i]); + BUG_ON(!addr); + for (j = 0; j < PAGE_SIZE / sizeof(*entry); j++) { + entry = (struct rmap_list_entry *)addr + j; + if (is_addr(entry->addr)) + continue; + if (!entry->item) + continue; + has_rmap = 1; + } + kunmap(slot->rmap_list_pool[i]); + if (!has_rmap) { + BUG_ON(slot->pool_counts[i]); + __free_page(slot->rmap_list_pool[i]); + slot->rmap_list_pool[i] = NULL; + } + } + + slot->flags &= ~UKSM_SLOT_NEED_SORT; +} + +/* + * vma_fully_scanned() - if all the pages in this slot have been scanned. + */ +static inline int vma_fully_scanned(struct vma_slot *slot) +{ + return slot->pages_scanned == slot->pages; +} + +/** + * get_next_rmap_item() - Get the next rmap_item in a vma_slot according to + * its random permutation. This function is embedded with the random + * permutation index management code. + */ +static struct rmap_item *get_next_rmap_item(struct vma_slot *slot, u32 *hash) +{ + unsigned long rand_range, addr, swap_index, scan_index; + struct rmap_item *item = NULL; + struct rmap_list_entry *scan_entry, *swap_entry = NULL; + struct page *page; + + scan_index = swap_index = slot->pages_scanned % slot->pages; + + if (pool_entry_boundary(scan_index)) + try_free_last_pool(slot, scan_index - 1); + + if (vma_fully_scanned(slot)) { + if (slot->flags & UKSM_SLOT_NEED_SORT) + slot->flags |= UKSM_SLOT_NEED_RERAND; + else + slot->flags &= ~UKSM_SLOT_NEED_RERAND; + if (slot->flags & UKSM_SLOT_NEED_SORT) + sort_rmap_entry_list(slot); + } + + scan_entry = get_rmap_list_entry(slot, scan_index, 1); + if (!scan_entry) + return NULL; + + if (entry_is_new(scan_entry)) { + scan_entry->addr = get_index_orig_addr(slot, scan_index); + set_is_addr(scan_entry->addr); + } + + if (slot->flags & UKSM_SLOT_NEED_RERAND) { + rand_range = slot->pages - scan_index; + BUG_ON(!rand_range); + swap_index = scan_index + (random32() % rand_range); + } + + if (swap_index != scan_index) { + swap_entry = get_rmap_list_entry(slot, swap_index, 1); + if (entry_is_new(swap_entry)) { + swap_entry->addr = get_index_orig_addr(slot, + swap_index); + set_is_addr(swap_entry->addr); + } + swap_entries(scan_entry, scan_index, swap_entry, swap_index); + } + + addr = get_entry_address(scan_entry); + item = get_entry_item(scan_entry); + BUG_ON(addr > slot->vma->vm_end || addr < slot->vma->vm_start); + + page = follow_page(slot->vma, addr, FOLL_GET); + if (IS_ERR_OR_NULL(page)) + goto nopage; + + if (!PageAnon(page) && !page_trans_compound_anon(page)) + goto putpage; + + /*check is zero_page pfn or uksm_zero_page*/ + if ((page_to_pfn(page) == zero_pfn) + || (page_to_pfn(page) == uksm_zero_pfn)) + goto putpage; + + flush_anon_page(slot->vma, page, addr); + flush_dcache_page(page); + + + *hash = page_hash(page, hash_strength, 1); + inc_uksm_pages_scanned(); + /*if the page content all zero, re-map to zero-page*/ + if (find_zero_page_hash(hash_strength, *hash)) { + if (!cmp_and_merge_zero_page(slot->vma, page)) { + slot->pages_merged++; + __inc_zone_page_state(page, NR_UKSM_ZERO_PAGES); + dec_mm_counter(slot->mm, MM_ANONPAGES); + + /* For full-zero pages, no need to create rmap item */ + goto putpage; + } else { + inc_rshash_neg(memcmp_cost / 2); + } + } + + if (!item) { + item = alloc_rmap_item(); + if (item) { + /* It has already been zeroed */ + item->slot = slot; + item->address = addr; + item->entry_index = scan_index; + scan_entry->item = item; + inc_rmap_list_pool_count(slot, scan_index); + } else + goto putpage; + } + + BUG_ON(item->slot != slot); + /* the page may have changed */ + item->page = page; + put_rmap_list_entry(slot, scan_index); + if (swap_entry) + put_rmap_list_entry(slot, swap_index); + return item; + +putpage: + put_page(page); + page = NULL; +nopage: + /* no page, store addr back and free rmap_item if possible */ + free_entry_item(scan_entry); + put_rmap_list_entry(slot, scan_index); + if (swap_entry) + put_rmap_list_entry(slot, swap_index); + return NULL; +} + +static inline int in_stable_tree(struct rmap_item *rmap_item) +{ + return rmap_item->address & STABLE_FLAG; +} + +/** + * scan_vma_one_page() - scan the next page in a vma_slot. Called with + * mmap_sem locked. + */ +static noinline void scan_vma_one_page(struct vma_slot *slot) +{ + u32 hash; + struct mm_struct *mm; + struct rmap_item *rmap_item = NULL; + struct vm_area_struct *vma = slot->vma; + + mm = vma->vm_mm; + BUG_ON(!mm); + BUG_ON(!slot); + + rmap_item = get_next_rmap_item(slot, &hash); + if (!rmap_item) + goto out1; + + if (PageKsm(rmap_item->page) && in_stable_tree(rmap_item)) + goto out2; + + cmp_and_merge_page(rmap_item, hash); +out2: + put_page(rmap_item->page); +out1: + slot->pages_scanned++; + if (slot->fully_scanned_round != fully_scanned_round) + scanned_virtual_pages++; + + if (vma_fully_scanned(slot)) + slot->fully_scanned_round = fully_scanned_round; +} + +static inline unsigned long rung_get_pages(struct scan_rung *rung) +{ + struct slot_tree_node *node; + + if (!rung->vma_root.rnode) + return 0; + + node = container_of(rung->vma_root.rnode, struct slot_tree_node, snode); + + return node->size; +} + +#define RUNG_SAMPLED_MIN 3 + +static inline +void uksm_calc_rung_step(struct scan_rung *rung, + unsigned long page_time, unsigned long ratio) +{ + unsigned long sampled, pages; + + /* will be fully scanned ? */ + if (!rung->cover_msecs) { + rung->step = 1; + return; + } + + sampled = rung->cover_msecs * (NSEC_PER_MSEC / TIME_RATIO_SCALE) + * ratio / page_time; + + /* + * Before we finsish a scan round and expensive per-round jobs, + * we need to have a chance to estimate the per page time. So + * the sampled number can not be too small. + */ + if (sampled < RUNG_SAMPLED_MIN) + sampled = RUNG_SAMPLED_MIN; + + pages = rung_get_pages(rung); + if (likely(pages > sampled)) + rung->step = pages / sampled; + else + rung->step = 1; +} + +static inline int step_need_recalc(struct scan_rung *rung) +{ + unsigned long pages, stepmax; + + pages = rung_get_pages(rung); + stepmax = pages / RUNG_SAMPLED_MIN; + + return pages && (rung->step > pages || + (stepmax && rung->step > stepmax)); +} + +static inline +void reset_current_scan(struct scan_rung *rung, int finished, int step_recalc) +{ + struct vma_slot *slot; + + if (finished) + rung->flags |= UKSM_RUNG_ROUND_FINISHED; + + if (step_recalc || step_need_recalc(rung)) { + uksm_calc_rung_step(rung, uksm_ema_page_time, rung->cpu_ratio); + BUG_ON(step_need_recalc(rung)); + } + + slot_iter_index = random32() % rung->step; + BUG_ON(!rung->vma_root.rnode); + slot = sradix_tree_next(&rung->vma_root, NULL, 0, slot_iter); + BUG_ON(!slot); + + rung->current_scan = slot; + rung->current_offset = slot_iter_index; +} + +static inline struct sradix_tree_root *slot_get_root(struct vma_slot *slot) +{ + return &slot->rung->vma_root; +} + +/* + * return if resetted. + */ +static int advance_current_scan(struct scan_rung *rung) +{ + unsigned short n; + struct vma_slot *slot, *next = NULL; + + BUG_ON(!rung->vma_root.num); + + slot = rung->current_scan; + n = (slot->pages - rung->current_offset) % rung->step; + slot_iter_index = rung->step - n; + next = sradix_tree_next(&rung->vma_root, slot->snode, + slot->sindex, slot_iter); + + if (next) { + rung->current_offset = slot_iter_index; + rung->current_scan = next; + return 0; + } else { + reset_current_scan(rung, 1, 0); + return 1; + } +} + +static inline void rung_rm_slot(struct vma_slot *slot) +{ + struct scan_rung *rung = slot->rung; + struct sradix_tree_root *root; + + if (rung->current_scan == slot) + advance_current_scan(rung); + + root = slot_get_root(slot); + sradix_tree_delete_from_leaf(root, slot->snode, slot->sindex); + slot->snode = NULL; + if (step_need_recalc(rung)) { + uksm_calc_rung_step(rung, uksm_ema_page_time, rung->cpu_ratio); + BUG_ON(step_need_recalc(rung)); + } + + /* In case advance_current_scan loop back to this slot again */ + if (rung->vma_root.num && rung->current_scan == slot) + reset_current_scan(slot->rung, 1, 0); +} + +static inline void rung_add_new_slots(struct scan_rung *rung, + struct vma_slot **slots, unsigned long num) +{ + int err; + struct vma_slot *slot; + unsigned long i; + struct sradix_tree_root *root = &rung->vma_root; + + err = sradix_tree_enter(root, (void **)slots, num); + BUG_ON(err); + + for (i = 0; i < num; i++) { + slot = slots[i]; + slot->rung = rung; + BUG_ON(vma_fully_scanned(slot)); + } + + if (rung->vma_root.num == num) + reset_current_scan(rung, 0, 1); +} + +static inline int rung_add_one_slot(struct scan_rung *rung, + struct vma_slot *slot) +{ + int err; + + err = sradix_tree_enter(&rung->vma_root, (void **)&slot, 1); + if (err) + return err; + + slot->rung = rung; + if (rung->vma_root.num == 1) + reset_current_scan(rung, 0, 1); + + return 0; +} + +/* + * Return true if the slot is deleted from its rung. + */ +static inline int vma_rung_enter(struct vma_slot *slot, struct scan_rung *rung) +{ + struct scan_rung *old_rung = slot->rung; + int err; + + if (old_rung == rung) + return 0; + + rung_rm_slot(slot); + err = rung_add_one_slot(rung, slot); + if (err) { + err = rung_add_one_slot(old_rung, slot); + WARN_ON(err); /* OOPS, badly OOM, we lost this slot */ + } + + return 1; +} + +static inline int vma_rung_up(struct vma_slot *slot) +{ + struct scan_rung *rung; + + rung = slot->rung; + if (slot->rung != &uksm_scan_ladder[SCAN_LADDER_SIZE-1]) + rung++; + + return vma_rung_enter(slot, rung); +} + +static inline int vma_rung_down(struct vma_slot *slot) +{ + struct scan_rung *rung; + + rung = slot->rung; + if (slot->rung != &uksm_scan_ladder[0]) + rung--; + + return vma_rung_enter(slot, rung); +} + +/** + * cal_dedup_ratio() - Calculate the deduplication ratio for this slot. + */ +static unsigned long cal_dedup_ratio(struct vma_slot *slot) +{ + unsigned long ret; + + BUG_ON(slot->pages_scanned == slot->last_scanned); + + ret = slot->pages_merged; + + /* Thrashing area filtering */ + if (ret && uksm_thrash_threshold) { + if (slot->pages_cowed * 100 / slot->pages_merged + > uksm_thrash_threshold) { + ret = 0; + } else { + ret = slot->pages_merged - slot->pages_cowed; + } + } + + return ret; +} + +/** + * cal_dedup_ratio() - Calculate the deduplication ratio for this slot. + */ +static unsigned long cal_dedup_ratio_old(struct vma_slot *slot) +{ + unsigned long ret; + unsigned long pages_scanned; + + pages_scanned = slot->pages_scanned; + if (!pages_scanned) { + if (uksm_thrash_threshold) + return 0; + else + pages_scanned = slot->pages_scanned; + } + + ret = slot->pages_bemerged * 100 / pages_scanned; + + /* Thrashing area filtering */ + if (ret && uksm_thrash_threshold) { + if (slot->pages_cowed * 100 / slot->pages_bemerged + > uksm_thrash_threshold) { + ret = 0; + } else { + ret = slot->pages_bemerged - slot->pages_cowed; + } + } + + return ret; +} + +/** + * stable_node_reinsert() - When the hash_strength has been adjusted, the + * stable tree need to be restructured, this is the function re-inserting the + * stable node. + */ +static inline void stable_node_reinsert(struct stable_node *new_node, + struct page *page, + struct rb_root *root_treep, + struct list_head *tree_node_listp, + u32 hash) +{ + struct rb_node **new = &root_treep->rb_node; + struct rb_node *parent = NULL; + struct stable_node *stable_node; + struct tree_node *tree_node; + struct page *tree_page; + int cmp; + + while (*new) { + int cmp; + + tree_node = rb_entry(*new, struct tree_node, node); + + cmp = hash_cmp(hash, tree_node->hash); + + if (cmp < 0) { + parent = *new; + new = &parent->rb_left; + } else if (cmp > 0) { + parent = *new; + new = &parent->rb_right; + } else + break; + } + + if (*new) { + /* find a stable tree node with same first level hash value */ + stable_node_hash_max(new_node, page, hash); + if (tree_node->count == 1) { + stable_node = rb_entry(tree_node->sub_root.rb_node, + struct stable_node, node); + tree_page = get_uksm_page(stable_node, 1, 0); + if (tree_page) { + stable_node_hash_max(stable_node, + tree_page, hash); + put_page(tree_page); + + /* prepare for stable node insertion */ + + cmp = hash_cmp(new_node->hash_max, + stable_node->hash_max); + parent = &stable_node->node; + if (cmp < 0) + new = &parent->rb_left; + else if (cmp > 0) + new = &parent->rb_right; + else + goto failed; + + goto add_node; + } else { + /* the only stable_node deleted, the tree node + * was not deleted. + */ + goto tree_node_reuse; + } + } + + /* well, search the collision subtree */ + new = &tree_node->sub_root.rb_node; + parent = NULL; + BUG_ON(!*new); + while (*new) { + int cmp; + + stable_node = rb_entry(*new, struct stable_node, node); + + cmp = hash_cmp(new_node->hash_max, + stable_node->hash_max); + + if (cmp < 0) { + parent = *new; + new = &parent->rb_left; + } else if (cmp > 0) { + parent = *new; + new = &parent->rb_right; + } else { + /* oh, no, still a collision */ + goto failed; + } + } + + goto add_node; + } + + /* no tree node found */ + tree_node = alloc_tree_node(tree_node_listp); + if (!tree_node) { + printk(KERN_ERR "UKSM: memory allocation error!\n"); + goto failed; + } else { + tree_node->hash = hash; + rb_link_node(&tree_node->node, parent, new); + rb_insert_color(&tree_node->node, root_treep); + +tree_node_reuse: + /* prepare for stable node insertion */ + parent = NULL; + new = &tree_node->sub_root.rb_node; + } + +add_node: + rb_link_node(&new_node->node, parent, new); + rb_insert_color(&new_node->node, &tree_node->sub_root); + new_node->tree_node = tree_node; + tree_node->count++; + return; + +failed: + /* This can only happen when two nodes have collided + * in two levels. + */ + new_node->tree_node = NULL; + return; +} + +static inline void free_all_tree_nodes(struct list_head *list) +{ + struct tree_node *node, *tmp; + + list_for_each_entry_safe(node, tmp, list, all_list) { + free_tree_node(node); + } +} + +/** + * stable_tree_delta_hash() - Delta hash the stable tree from previous hash + * strength to the current hash_strength. It re-structures the hole tree. + */ +static inline void stable_tree_delta_hash(u32 prev_hash_strength) +{ + struct stable_node *node, *tmp; + struct rb_root *root_new_treep; + struct list_head *new_tree_node_listp; + + stable_tree_index = (stable_tree_index + 1) % 2; + root_new_treep = &root_stable_tree[stable_tree_index]; + new_tree_node_listp = &stable_tree_node_list[stable_tree_index]; + *root_new_treep = RB_ROOT; + BUG_ON(!list_empty(new_tree_node_listp)); + + /* + * we need to be safe, the node could be removed by get_uksm_page() + */ + list_for_each_entry_safe(node, tmp, &stable_node_list, all_list) { + void *addr; + struct page *node_page; + u32 hash; + + /* + * We are completely re-structuring the stable nodes to a new + * stable tree. We don't want to touch the old tree unlinks and + * old tree_nodes. The old tree_nodes will be freed at once. + */ + node_page = get_uksm_page(node, 0, 0); + if (!node_page) + continue; + + if (node->tree_node) { + hash = node->tree_node->hash; + + addr = kmap_atomic(node_page); + + hash = delta_hash(addr, prev_hash_strength, + hash_strength, hash); + kunmap_atomic(addr); + } else { + /* + *it was not inserted to rbtree due to collision in last + *round scan. + */ + hash = page_hash(node_page, hash_strength, 0); + } + + stable_node_reinsert(node, node_page, root_new_treep, + new_tree_node_listp, hash); + put_page(node_page); + } + + root_stable_treep = root_new_treep; + free_all_tree_nodes(stable_tree_node_listp); + BUG_ON(!list_empty(stable_tree_node_listp)); + stable_tree_node_listp = new_tree_node_listp; +} + +static inline void inc_hash_strength(unsigned long delta) +{ + hash_strength += 1 << delta; + if (hash_strength > HASH_STRENGTH_MAX) + hash_strength = HASH_STRENGTH_MAX; +} + +static inline void dec_hash_strength(unsigned long delta) +{ + unsigned long change = 1 << delta; + + if (hash_strength <= change + 1) + hash_strength = 1; + else + hash_strength -= change; +} + +static inline void inc_hash_strength_delta(void) +{ + hash_strength_delta++; + if (hash_strength_delta > HASH_STRENGTH_DELTA_MAX) + hash_strength_delta = HASH_STRENGTH_DELTA_MAX; +} + +/* +static inline unsigned long get_current_neg_ratio(void) +{ + if (!rshash_pos || rshash_neg > rshash_pos) + return 100; + + return div64_u64(100 * rshash_neg , rshash_pos); +} +*/ + +static inline unsigned long get_current_neg_ratio(void) +{ + u64 pos = benefit.pos; + u64 neg = benefit.neg; + + if (!neg) + return 0; + + if (!pos || neg > pos) + return 100; + + if (neg > div64_u64(U64_MAX, 100)) + pos = div64_u64(pos, 100); + else + neg *= 100; + + return div64_u64(neg, pos); +} + +static inline unsigned long get_current_benefit(void) +{ + u64 pos = benefit.pos; + u64 neg = benefit.neg; + u64 scanned = benefit.scanned; + + if (neg > pos) + return 0; + + return div64_u64((pos - neg), scanned); +} + +static inline int judge_rshash_direction(void) +{ + u64 current_neg_ratio, stable_benefit; + u64 current_benefit, delta = 0; + int ret = STILL; + + /* Try to probe a value after the boot, and in case the system + are still for a long time. */ + if ((fully_scanned_round & 0xFFULL) == 10) { + ret = OBSCURE; + goto out; + } + + current_neg_ratio = get_current_neg_ratio(); + + if (current_neg_ratio == 0) { + rshash_neg_cont_zero++; + if (rshash_neg_cont_zero > 2) + return GO_DOWN; + else + return STILL; + } + rshash_neg_cont_zero = 0; + + if (current_neg_ratio > 90) { + ret = GO_UP; + goto out; + } + + current_benefit = get_current_benefit(); + stable_benefit = rshash_state.stable_benefit; + + if (!stable_benefit) { + ret = OBSCURE; + goto out; + } + + if (current_benefit > stable_benefit) + delta = current_benefit - stable_benefit; + else if (current_benefit < stable_benefit) + delta = stable_benefit - current_benefit; + + delta = div64_u64(100 * delta , stable_benefit); + + if (delta > 50) { + rshash_cont_obscure++; + if (rshash_cont_obscure > 2) + return OBSCURE; + else + return STILL; + } + +out: + rshash_cont_obscure = 0; + return ret; +} + +/** + * rshash_adjust() - The main function to control the random sampling state + * machine for hash strength adapting. + * + * return true if hash_strength has changed. + */ +static inline int rshash_adjust(void) +{ + unsigned long prev_hash_strength = hash_strength; + + if (!encode_benefit()) + return 0; + + switch (rshash_state.state) { + case RSHASH_STILL: + switch (judge_rshash_direction()) { + case GO_UP: + if (rshash_state.pre_direct == GO_DOWN) + hash_strength_delta = 0; + + inc_hash_strength(hash_strength_delta); + inc_hash_strength_delta(); + rshash_state.stable_benefit = get_current_benefit(); + rshash_state.pre_direct = GO_UP; + break; + + case GO_DOWN: + if (rshash_state.pre_direct == GO_UP) + hash_strength_delta = 0; + + dec_hash_strength(hash_strength_delta); + inc_hash_strength_delta(); + rshash_state.stable_benefit = get_current_benefit(); + rshash_state.pre_direct = GO_DOWN; + break; + + case OBSCURE: + rshash_state.stable_point = hash_strength; + rshash_state.turn_point_down = hash_strength; + rshash_state.turn_point_up = hash_strength; + rshash_state.turn_benefit_down = get_current_benefit(); + rshash_state.turn_benefit_up = get_current_benefit(); + rshash_state.lookup_window_index = 0; + rshash_state.state = RSHASH_TRYDOWN; + dec_hash_strength(hash_strength_delta); + inc_hash_strength_delta(); + break; + + case STILL: + break; + default: + BUG(); + } + break; + + case RSHASH_TRYDOWN: + if (rshash_state.lookup_window_index++ % 5 == 0) + rshash_state.below_count = 0; + + if (get_current_benefit() < rshash_state.stable_benefit) + rshash_state.below_count++; + else if (get_current_benefit() > + rshash_state.turn_benefit_down) { + rshash_state.turn_point_down = hash_strength; + rshash_state.turn_benefit_down = get_current_benefit(); + } + + if (rshash_state.below_count >= 3 || + judge_rshash_direction() == GO_UP || + hash_strength == 1) { + hash_strength = rshash_state.stable_point; + hash_strength_delta = 0; + inc_hash_strength(hash_strength_delta); + inc_hash_strength_delta(); + rshash_state.lookup_window_index = 0; + rshash_state.state = RSHASH_TRYUP; + hash_strength_delta = 0; + } else { + dec_hash_strength(hash_strength_delta); + inc_hash_strength_delta(); + } + break; + + case RSHASH_TRYUP: + if (rshash_state.lookup_window_index++ % 5 == 0) + rshash_state.below_count = 0; + + if (get_current_benefit() < rshash_state.turn_benefit_down) + rshash_state.below_count++; + else if (get_current_benefit() > rshash_state.turn_benefit_up) { + rshash_state.turn_point_up = hash_strength; + rshash_state.turn_benefit_up = get_current_benefit(); + } + + if (rshash_state.below_count >= 3 || + judge_rshash_direction() == GO_DOWN || + hash_strength == HASH_STRENGTH_MAX) { + hash_strength = rshash_state.turn_benefit_up > + rshash_state.turn_benefit_down ? + rshash_state.turn_point_up : + rshash_state.turn_point_down; + + rshash_state.state = RSHASH_PRE_STILL; + } else { + inc_hash_strength(hash_strength_delta); + inc_hash_strength_delta(); + } + + break; + + case RSHASH_NEW: + case RSHASH_PRE_STILL: + rshash_state.stable_benefit = get_current_benefit(); + rshash_state.state = RSHASH_STILL; + hash_strength_delta = 0; + break; + default: + BUG(); + } + + /* rshash_neg = rshash_pos = 0; */ + reset_benefit(); + + if (prev_hash_strength != hash_strength) + stable_tree_delta_hash(prev_hash_strength); + + return prev_hash_strength != hash_strength; +} + +/** + * round_update_ladder() - The main function to do update of all the + * adjustments whenever a scan round is finished. + */ +static noinline void round_update_ladder(void) +{ + int i; + unsigned long dedup; + struct vma_slot *slot, *tmp_slot; + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + uksm_scan_ladder[i].flags &= ~UKSM_RUNG_ROUND_FINISHED; + } + + list_for_each_entry_safe(slot, tmp_slot, &vma_slot_dedup, dedup_list) { + + /* slot may be rung_rm_slot() when mm exits */ + if (slot->snode) { + dedup = cal_dedup_ratio_old(slot); + if (dedup && dedup >= uksm_abundant_threshold) + vma_rung_up(slot); + } + + slot->pages_bemerged = 0; + slot->pages_cowed = 0; + + list_del_init(&slot->dedup_list); + } +} + +static void uksm_del_vma_slot(struct vma_slot *slot) +{ + int i, j; + struct rmap_list_entry *entry; + + if (slot->snode) { + /* + * In case it just failed when entering the rung, it's not + * necessary. + */ + rung_rm_slot(slot); + } + + if (!list_empty(&slot->dedup_list)) + list_del(&slot->dedup_list); + + if (!slot->rmap_list_pool || !slot->pool_counts) { + /* In case it OOMed in uksm_vma_enter() */ + goto out; + } + + for (i = 0; i < slot->pool_size; i++) { + void *addr; + + if (!slot->rmap_list_pool[i]) + continue; + + addr = kmap(slot->rmap_list_pool[i]); + for (j = 0; j < PAGE_SIZE / sizeof(*entry); j++) { + entry = (struct rmap_list_entry *)addr + j; + if (is_addr(entry->addr)) + continue; + if (!entry->item) + continue; + + remove_rmap_item_from_tree(entry->item); + free_rmap_item(entry->item); + slot->pool_counts[i]--; + } + BUG_ON(slot->pool_counts[i]); + kunmap(slot->rmap_list_pool[i]); + __free_page(slot->rmap_list_pool[i]); + } + kfree(slot->rmap_list_pool); + kfree(slot->pool_counts); + +out: + slot->rung = NULL; + BUG_ON(uksm_pages_total < slot->pages); + if (slot->flags & UKSM_SLOT_IN_UKSM) + uksm_pages_total -= slot->pages; + + if (slot->fully_scanned_round == fully_scanned_round) + scanned_virtual_pages -= slot->pages; + else + scanned_virtual_pages -= slot->pages_scanned; + free_vma_slot(slot); +} + + +#define SPIN_LOCK_PERIOD 32 +static struct vma_slot *cleanup_slots[SPIN_LOCK_PERIOD]; +static inline void cleanup_vma_slots(void) +{ + struct vma_slot *slot; + int i; + + i = 0; + spin_lock(&vma_slot_list_lock); + while (!list_empty(&vma_slot_del)) { + slot = list_entry(vma_slot_del.next, + struct vma_slot, slot_list); + list_del(&slot->slot_list); + cleanup_slots[i++] = slot; + if (i == SPIN_LOCK_PERIOD) { + spin_unlock(&vma_slot_list_lock); + while (--i >= 0) + uksm_del_vma_slot(cleanup_slots[i]); + i = 0; + spin_lock(&vma_slot_list_lock); + } + } + spin_unlock(&vma_slot_list_lock); + + while (--i >= 0) + uksm_del_vma_slot(cleanup_slots[i]); +} + +/* +*expotional moving average formula +*/ +static inline unsigned long ema(unsigned long curr, unsigned long last_ema) +{ + /* + * For a very high burst, even the ema cannot work well, a false very + * high per-page time estimation can result in feedback in very high + * overhead of context swith and rung update -- this will then lead + * to higher per-paper time, this may not converge. + * + * Instead, we try to approach this value in a binary manner. + */ + if (curr > last_ema * 10) + return last_ema * 2; + + return (EMA_ALPHA * curr + (100 - EMA_ALPHA) * last_ema) / 100; +} + +/* + * convert cpu ratio in 1/TIME_RATIO_SCALE configured by user to + * nanoseconds based on current uksm_sleep_jiffies. + */ +static inline unsigned long cpu_ratio_to_nsec(unsigned int ratio) +{ + return NSEC_PER_USEC * jiffies_to_usecs(uksm_sleep_jiffies) / + (TIME_RATIO_SCALE - ratio) * ratio; +} + + +static inline unsigned long rung_real_ratio(int cpu_time_ratio) +{ + unsigned long ret; + + BUG_ON(!cpu_time_ratio); + + if (cpu_time_ratio > 0) + ret = cpu_time_ratio; + else + ret = (unsigned long)(-cpu_time_ratio) * + uksm_max_cpu_percentage / 100UL; + + return ret ? ret : 1; +} + +static noinline void uksm_calc_scan_pages(void) +{ + struct scan_rung *ladder = uksm_scan_ladder; + unsigned long sleep_usecs, nsecs; + unsigned long ratio; + int i; + unsigned long per_page; + + if (uksm_ema_page_time > 100000 || + (((unsigned long) uksm_eval_round & (256UL - 1)) == 0UL)) + uksm_ema_page_time = UKSM_PAGE_TIME_DEFAULT; + + per_page = uksm_ema_page_time; + BUG_ON(!per_page); + + /* + * For every 8 eval round, we try to probe a uksm_sleep_jiffies value + * based on saved user input. + */ + if (((unsigned long) uksm_eval_round & (8UL - 1)) == 0UL) + uksm_sleep_jiffies = uksm_sleep_saved; + + /* We require a rung scan at least 1 page in a period. */ + nsecs = per_page; + ratio = rung_real_ratio(ladder[0].cpu_ratio); + if (cpu_ratio_to_nsec(ratio) < nsecs) { + sleep_usecs = nsecs * (TIME_RATIO_SCALE - ratio) / ratio + / NSEC_PER_USEC; + uksm_sleep_jiffies = usecs_to_jiffies(sleep_usecs) + 1; + } + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + ratio = rung_real_ratio(ladder[i].cpu_ratio); + ladder[i].pages_to_scan = cpu_ratio_to_nsec(ratio) / + per_page; + BUG_ON(!ladder[i].pages_to_scan); + uksm_calc_rung_step(&ladder[i], per_page, ratio); + } +} + +/* + * From the scan time of this round (ns) to next expected min sleep time + * (ms), be careful of the possible overflows. ratio is taken from + * rung_real_ratio() + */ +static inline +unsigned int scan_time_to_sleep(unsigned long long scan_time, unsigned long ratio) +{ + scan_time >>= 20; /* to msec level now */ + BUG_ON(scan_time > (ULONG_MAX / TIME_RATIO_SCALE)); + + return (unsigned int) ((unsigned long) scan_time * + (TIME_RATIO_SCALE - ratio) / ratio); +} + +#define __round_mask(x, y) ((__typeof__(x))((y)-1)) +#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1) + +static inline unsigned long vma_pool_size(struct vma_slot *slot) +{ + return round_up(sizeof(struct rmap_list_entry) * slot->pages, + PAGE_SIZE) >> PAGE_SHIFT; +} + +static void uksm_vma_enter(struct vma_slot **slots, unsigned long num) +{ + struct scan_rung *rung; + unsigned long pool_size, i; + struct vma_slot *slot; + int failed; + + rung = &uksm_scan_ladder[0]; + + failed = 0; + for (i = 0; i < num; i++) { + slot = slots[i]; + + pool_size = vma_pool_size(slot); + slot->rmap_list_pool = kzalloc(sizeof(struct page *) * + pool_size, GFP_KERNEL); + if (!slot->rmap_list_pool) + break; + + slot->pool_counts = kzalloc(sizeof(unsigned int) * pool_size, + GFP_KERNEL); + if (!slot->pool_counts) { + kfree(slot->rmap_list_pool); + break; + } + + slot->pool_size = pool_size; + BUG_ON(CAN_OVERFLOW_U64(uksm_pages_total, slot->pages)); + slot->flags |= UKSM_SLOT_IN_UKSM; + uksm_pages_total += slot->pages; + } + + if (i) + rung_add_new_slots(rung, slots, i); + + return; +} + +static struct vma_slot *batch_slots[SLOT_TREE_NODE_STORE_SIZE]; + +static void uksm_enter_all_slots(void) +{ + struct vma_slot *slot; + unsigned long index; + struct list_head empty_vma_list; + int i; + + i = 0; + index = 0; + INIT_LIST_HEAD(&empty_vma_list); + + spin_lock(&vma_slot_list_lock); + while (!list_empty(&vma_slot_new)) { + slot = list_entry(vma_slot_new.next, + struct vma_slot, slot_list); + + if (!slot->vma->anon_vma) { + list_move(&slot->slot_list, &empty_vma_list); + } else if (vma_can_enter(slot->vma)) { + batch_slots[index++] = slot; + list_del_init(&slot->slot_list); + } else { + list_move(&slot->slot_list, &vma_slot_noadd); + } + + if (++i == SPIN_LOCK_PERIOD || + (index && !(index % SLOT_TREE_NODE_STORE_SIZE))) { + spin_unlock(&vma_slot_list_lock); + + if (index && !(index % SLOT_TREE_NODE_STORE_SIZE)) { + uksm_vma_enter(batch_slots, index); + index = 0; + } + i = 0; + cond_resched(); + spin_lock(&vma_slot_list_lock); + } + } + + list_splice(&empty_vma_list, &vma_slot_new); + + spin_unlock(&vma_slot_list_lock); + + if (index) + uksm_vma_enter(batch_slots, index); + +} + +static inline int rung_round_finished(struct scan_rung *rung) +{ + return rung->flags & UKSM_RUNG_ROUND_FINISHED; +} + +static inline void judge_slot(struct vma_slot *slot) +{ + struct scan_rung *rung = slot->rung; + unsigned long dedup; + int deleted; + + dedup = cal_dedup_ratio(slot); + if (vma_fully_scanned(slot) && uksm_thrash_threshold) + deleted = vma_rung_enter(slot, &uksm_scan_ladder[0]); + else if (dedup && dedup >= uksm_abundant_threshold) + deleted = vma_rung_up(slot); + else + deleted = vma_rung_down(slot); + + slot->pages_merged = 0; + slot->pages_cowed = 0; + + if (vma_fully_scanned(slot)) + slot->pages_scanned = 0; + + slot->last_scanned = slot->pages_scanned; + + /* If its deleted in above, then rung was already advanced. */ + if (!deleted) + advance_current_scan(rung); +} + + +static inline int hash_round_finished(void) +{ + if (scanned_virtual_pages > (uksm_pages_total >> 2)) { + scanned_virtual_pages = 0; + if (uksm_pages_scanned) + fully_scanned_round++; + + return 1; + } else { + return 0; + } +} + +#define UKSM_MMSEM_BATCH 5 +#define BUSY_RETRY 100 + +/** + * uksm_do_scan() - the main worker function. + */ +static noinline void uksm_do_scan(void) +{ + struct vma_slot *slot, *iter; + struct mm_struct *busy_mm; + unsigned char round_finished, all_rungs_emtpy; + int i, err, mmsem_batch; + unsigned long pcost; + long long delta_exec; + unsigned long vpages, max_cpu_ratio; + unsigned long long start_time, end_time, scan_time; + unsigned int expected_jiffies; + + might_sleep(); + + vpages = 0; + + start_time = task_sched_runtime(current); + max_cpu_ratio = 0; + mmsem_batch = 0; + + for (i = 0; i < SCAN_LADDER_SIZE;) { + struct scan_rung *rung = &uksm_scan_ladder[i]; + unsigned long ratio; + int busy_retry; + + if (!rung->pages_to_scan) { + i++; + continue; + } + + if (!rung->vma_root.num) { + rung->pages_to_scan = 0; + i++; + continue; + } + + ratio = rung_real_ratio(rung->cpu_ratio); + if (ratio > max_cpu_ratio) + max_cpu_ratio = ratio; + + busy_retry = BUSY_RETRY; + /* + * Do not consider rung_round_finished() here, just used up the + * rung->pages_to_scan quota. + */ + while (rung->pages_to_scan && rung->vma_root.num && + likely(!freezing(current))) { + int reset = 0; + + slot = rung->current_scan; + + BUG_ON(vma_fully_scanned(slot)); + + if (mmsem_batch) { + err = 0; + } else { + err = try_down_read_slot_mmap_sem(slot); + } + + if (err == -ENOENT) { +rm_slot: + rung_rm_slot(slot); + continue; + } + + busy_mm = slot->mm; + + if (err == -EBUSY) { + /* skip other vmas on the same mm */ + do { + reset = advance_current_scan(rung); + iter = rung->current_scan; + busy_retry--; + if (iter->vma->vm_mm != busy_mm || + !busy_retry || reset) + break; + } while (1); + + if (iter->vma->vm_mm != busy_mm) { + continue; + } else { + /* scan round finsished */ + break; + } + } + + BUG_ON(!vma_can_enter(slot->vma)); + if (uksm_test_exit(slot->vma->vm_mm)) { + mmsem_batch = 0; + up_read(&slot->vma->vm_mm->mmap_sem); + goto rm_slot; + } + + if (mmsem_batch) + mmsem_batch--; + else + mmsem_batch = UKSM_MMSEM_BATCH; + + /* Ok, we have take the mmap_sem, ready to scan */ + scan_vma_one_page(slot); + rung->pages_to_scan--; + vpages++; + + if (rung->current_offset + rung->step > slot->pages - 1 + || vma_fully_scanned(slot)) { + up_read(&slot->vma->vm_mm->mmap_sem); + judge_slot(slot); + mmsem_batch = 0; + } else { + rung->current_offset += rung->step; + if (!mmsem_batch) + up_read(&slot->vma->vm_mm->mmap_sem); + } + + busy_retry = BUSY_RETRY; + cond_resched(); + } + + if (mmsem_batch) { + up_read(&slot->vma->vm_mm->mmap_sem); + mmsem_batch = 0; + } + + if (freezing(current)) + break; + + cond_resched(); + } + end_time = task_sched_runtime(current); + delta_exec = end_time - start_time; + + if (freezing(current)) + return; + + cleanup_vma_slots(); + uksm_enter_all_slots(); + + round_finished = 1; + all_rungs_emtpy = 1; + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + struct scan_rung *rung = &uksm_scan_ladder[i]; + + if (rung->vma_root.num) { + all_rungs_emtpy = 0; + if (!rung_round_finished(rung)) + round_finished = 0; + } + } + + if (all_rungs_emtpy) + round_finished = 0; + + if (round_finished) { + round_update_ladder(); + uksm_eval_round++; + + if (hash_round_finished() && rshash_adjust()) { + /* Reset the unstable root iff hash strength changed */ + uksm_hash_round++; + root_unstable_tree = RB_ROOT; + free_all_tree_nodes(&unstable_tree_node_list); + } + + /* + * A number of pages can hang around indefinitely on per-cpu + * pagevecs, raised page count preventing write_protect_page + * from merging them. Though it doesn't really matter much, + * it is puzzling to see some stuck in pages_volatile until + * other activity jostles them out, and they also prevented + * LTP's KSM test from succeeding deterministically; so drain + * them here (here rather than on entry to uksm_do_scan(), + * so we don't IPI too often when pages_to_scan is set low). + */ + lru_add_drain_all(); + } + + + if (vpages && delta_exec > 0) { + pcost = (unsigned long) delta_exec / vpages; + if (likely(uksm_ema_page_time)) + uksm_ema_page_time = ema(pcost, uksm_ema_page_time); + else + uksm_ema_page_time = pcost; + } + + uksm_calc_scan_pages(); + uksm_sleep_real = uksm_sleep_jiffies; + /* in case of radical cpu bursts, apply the upper bound */ + end_time = task_sched_runtime(current); + if (max_cpu_ratio && end_time > start_time) { + scan_time = end_time - start_time; + expected_jiffies = msecs_to_jiffies( + scan_time_to_sleep(scan_time, max_cpu_ratio)); + + if (expected_jiffies > uksm_sleep_real) + uksm_sleep_real = expected_jiffies; + + /* We have a 1 second up bound for responsiveness. */ + if (jiffies_to_msecs(uksm_sleep_real) > MSEC_PER_SEC) + uksm_sleep_real = msecs_to_jiffies(1000); + } + + return; +} + +static int ksmd_should_run(void) +{ + return uksm_run & UKSM_RUN_MERGE; +} + +static int uksm_scan_thread(void *nothing) +{ + set_freezable(); + set_user_nice(current, 5); + + while (!kthread_should_stop()) { + mutex_lock(&uksm_thread_mutex); + if (ksmd_should_run()) { + uksm_do_scan(); + } + mutex_unlock(&uksm_thread_mutex); + + try_to_freeze(); + + if (ksmd_should_run()) { + schedule_timeout_interruptible(uksm_sleep_real); + uksm_sleep_times++; + } else { + wait_event_freezable(uksm_thread_wait, + ksmd_should_run() || kthread_should_stop()); + } + } + return 0; +} + +int page_referenced_ksm(struct page *page, struct mem_cgroup *memcg, + unsigned long *vm_flags) +{ + struct stable_node *stable_node; + struct node_vma *node_vma; + struct rmap_item *rmap_item; + struct hlist_node *hlist, *rmap_hlist; + unsigned int mapcount = page_mapcount(page); + int referenced = 0; + int search_new_forks = 0; + unsigned long address; + + VM_BUG_ON(!PageKsm(page)); + VM_BUG_ON(!PageLocked(page)); + + stable_node = page_stable_node(page); + if (!stable_node) + return 0; + + +again: + hlist_for_each_entry(node_vma, hlist, &stable_node->hlist, hlist) { + hlist_for_each_entry(rmap_item, rmap_hlist, + &node_vma->rmap_hlist, hlist) { + struct anon_vma *anon_vma = rmap_item->anon_vma; + struct anon_vma_chain *vmac; + struct vm_area_struct *vma; + + anon_vma_lock(anon_vma); + list_for_each_entry(vmac, &anon_vma->head, + same_anon_vma) { + vma = vmac->vma; + address = get_rmap_addr(rmap_item); + + if (address < vma->vm_start || + address >= vma->vm_end) + continue; + /* + * Initially we examine only the vma which + * covers this rmap_item; but later, if there + * is still work to do, we examine covering + * vmas in other mms: in case they were forked + * from the original since ksmd passed. + */ + if ((rmap_item->slot->vma == vma) == + search_new_forks) + continue; + + if (memcg && + !mm_match_cgroup(vma->vm_mm, memcg)) + continue; + + referenced += + page_referenced_one(page, vma, + address, &mapcount, vm_flags); + if (!search_new_forks || !mapcount) + break; + } + + anon_vma_unlock(anon_vma); + if (!mapcount) + goto out; + } + } + if (!search_new_forks++) + goto again; +out: + return referenced; +} + +int try_to_unmap_ksm(struct page *page, enum ttu_flags flags) +{ + struct stable_node *stable_node; + struct node_vma *node_vma; + struct hlist_node *hlist, *rmap_hlist; + struct rmap_item *rmap_item; + int ret = SWAP_AGAIN; + int search_new_forks = 0; + unsigned long address; + + VM_BUG_ON(!PageKsm(page)); + VM_BUG_ON(!PageLocked(page)); + + stable_node = page_stable_node(page); + if (!stable_node) + return SWAP_FAIL; +again: + hlist_for_each_entry(node_vma, hlist, &stable_node->hlist, hlist) { + hlist_for_each_entry(rmap_item, rmap_hlist, + &node_vma->rmap_hlist, hlist) { + struct anon_vma *anon_vma = rmap_item->anon_vma; + struct anon_vma_chain *vmac; + struct vm_area_struct *vma; + + anon_vma_lock(anon_vma); + list_for_each_entry(vmac, &anon_vma->head, + same_anon_vma) { + vma = vmac->vma; + address = get_rmap_addr(rmap_item); + + if (address < vma->vm_start || + address >= vma->vm_end) + continue; + /* + * Initially we examine only the vma which + * covers this rmap_item; but later, if there + * is still work to do, we examine covering + * vmas in other mms: in case they were forked + * from the original since ksmd passed. + */ + if ((rmap_item->slot->vma == vma) == + search_new_forks) + continue; + + ret = try_to_unmap_one(page, vma, + address, flags); + if (ret != SWAP_AGAIN || !page_mapped(page)) { + anon_vma_unlock(anon_vma); + goto out; + } + } + anon_vma_unlock(anon_vma); + } + } + if (!search_new_forks++) + goto again; +out: + return ret; +} + +#ifdef CONFIG_MIGRATION +int rmap_walk_ksm(struct page *page, int (*rmap_one)(struct page *, + struct vm_area_struct *, unsigned long, void *), void *arg) +{ + struct stable_node *stable_node; + struct node_vma *node_vma; + struct hlist_node *hlist, *rmap_hlist; + struct rmap_item *rmap_item; + int ret = SWAP_AGAIN; + int search_new_forks = 0; + unsigned long address; + + VM_BUG_ON(!PageKsm(page)); + VM_BUG_ON(!PageLocked(page)); + + stable_node = page_stable_node(page); + if (!stable_node) + return ret; +again: + hlist_for_each_entry(node_vma, hlist, &stable_node->hlist, hlist) { + hlist_for_each_entry(rmap_item, rmap_hlist, + &node_vma->rmap_hlist, hlist) { + struct anon_vma *anon_vma = rmap_item->anon_vma; + struct anon_vma_chain *vmac; + struct vm_area_struct *vma; + + anon_vma_lock(anon_vma); + list_for_each_entry(vmac, &anon_vma->head, + same_anon_vma) { + vma = vmac->vma; + address = get_rmap_addr(rmap_item); + + if (address < vma->vm_start || + address >= vma->vm_end) + continue; + + if ((rmap_item->slot->vma == vma) == + search_new_forks) + continue; + + ret = rmap_one(page, vma, address, arg); + if (ret != SWAP_AGAIN) { + anon_vma_unlock(anon_vma); + goto out; + } + } + anon_vma_unlock(anon_vma); + } + } + if (!search_new_forks++) + goto again; +out: + return ret; +} + +/* Common ksm interface but may be specific to uksm */ +void ksm_migrate_page(struct page *newpage, struct page *oldpage) +{ + struct stable_node *stable_node; + + VM_BUG_ON(!PageLocked(oldpage)); + VM_BUG_ON(!PageLocked(newpage)); + VM_BUG_ON(newpage->mapping != oldpage->mapping); + + stable_node = page_stable_node(newpage); + if (stable_node) { + VM_BUG_ON(stable_node->kpfn != page_to_pfn(oldpage)); + stable_node->kpfn = page_to_pfn(newpage); + } +} +#endif /* CONFIG_MIGRATION */ + +#ifdef CONFIG_MEMORY_HOTREMOVE +static struct stable_node *uksm_check_stable_tree(unsigned long start_pfn, + unsigned long end_pfn) +{ + struct rb_node *node; + + for (node = rb_first(root_stable_treep); node; node = rb_next(node)) { + struct stable_node *stable_node; + + stable_node = rb_entry(node, struct stable_node, node); + if (stable_node->kpfn >= start_pfn && + stable_node->kpfn < end_pfn) + return stable_node; + } + return NULL; +} + +static int uksm_memory_callback(struct notifier_block *self, + unsigned long action, void *arg) +{ + struct memory_notify *mn = arg; + struct stable_node *stable_node; + + switch (action) { + case MEM_GOING_OFFLINE: + /* + * Keep it very simple for now: just lock out ksmd and + * MADV_UNMERGEABLE while any memory is going offline. + * mutex_lock_nested() is necessary because lockdep was alarmed + * that here we take uksm_thread_mutex inside notifier chain + * mutex, and later take notifier chain mutex inside + * uksm_thread_mutex to unlock it. But that's safe because both + * are inside mem_hotplug_mutex. + */ + mutex_lock_nested(&uksm_thread_mutex, SINGLE_DEPTH_NESTING); + break; + + case MEM_OFFLINE: + /* + * Most of the work is done by page migration; but there might + * be a few stable_nodes left over, still pointing to struct + * pages which have been offlined: prune those from the tree. + */ + while ((stable_node = uksm_check_stable_tree(mn->start_pfn, + mn->start_pfn + mn->nr_pages)) != NULL) + remove_node_from_stable_tree(stable_node, 1, 1); + /* fallthrough */ + + case MEM_CANCEL_OFFLINE: + mutex_unlock(&uksm_thread_mutex); + break; + } + return NOTIFY_OK; +} +#endif /* CONFIG_MEMORY_HOTREMOVE */ + +#ifdef CONFIG_SYSFS +/* + * This all compiles without CONFIG_SYSFS, but is a waste of space. + */ + +#define UKSM_ATTR_RO(_name) \ + static struct kobj_attribute _name##_attr = __ATTR_RO(_name) +#define UKSM_ATTR(_name) \ + static struct kobj_attribute _name##_attr = \ + __ATTR(_name, 0644, _name##_show, _name##_store) + +static ssize_t max_cpu_percentage_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", uksm_max_cpu_percentage); +} + +static ssize_t max_cpu_percentage_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long max_cpu_percentage; + int err; + + err = strict_strtoul(buf, 10, &max_cpu_percentage); + if (err || max_cpu_percentage > 100) + return -EINVAL; + + if (max_cpu_percentage == 100) + max_cpu_percentage = 99; + else if (max_cpu_percentage < 10) + max_cpu_percentage = 10; + + uksm_max_cpu_percentage = max_cpu_percentage; + + return count; +} +UKSM_ATTR(max_cpu_percentage); + +static ssize_t sleep_millisecs_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", jiffies_to_msecs(uksm_sleep_jiffies)); +} + +static ssize_t sleep_millisecs_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + unsigned long msecs; + int err; + + err = strict_strtoul(buf, 10, &msecs); + if (err || msecs > MSEC_PER_SEC) + return -EINVAL; + + uksm_sleep_jiffies = msecs_to_jiffies(msecs); + uksm_sleep_saved = uksm_sleep_jiffies; + + return count; +} +UKSM_ATTR(sleep_millisecs); + + +static ssize_t cpu_governor_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int n = sizeof(uksm_cpu_governor_str) / sizeof(char *); + int i; + + buf[0] = '\0'; + for (i = 0; i < n ; i++) { + if (uksm_cpu_governor == i) + strcat(buf, "["); + + strcat(buf, uksm_cpu_governor_str[i]); + + if (uksm_cpu_governor == i) + strcat(buf, "]"); + + strcat(buf, " "); + } + strcat(buf, "\n"); + + return strlen(buf); +} + +static inline void init_performance_values(void) +{ + int i; + struct scan_rung *rung; + struct uksm_cpu_preset_s *preset = uksm_cpu_preset + uksm_cpu_governor; + + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + rung = uksm_scan_ladder + i; + rung->cpu_ratio = preset->cpu_ratio[i]; + rung->cover_msecs = preset->cover_msecs[i]; + } + + uksm_max_cpu_percentage = preset->max_cpu; +} + +static ssize_t cpu_governor_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int n = sizeof(uksm_cpu_governor_str) / sizeof(char *); + + for (n--; n >=0 ; n--) { + if (!strncmp(buf, uksm_cpu_governor_str[n], + strlen(uksm_cpu_governor_str[n]))) + break; + } + + if (n < 0) + return -EINVAL; + else + uksm_cpu_governor = n; + + init_performance_values(); + + return count; +} +UKSM_ATTR(cpu_governor); + +static ssize_t run_show(struct kobject *kobj, struct kobj_attribute *attr, + char *buf) +{ + return sprintf(buf, "%u\n", uksm_run); +} + +static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int err; + unsigned long flags; + + err = strict_strtoul(buf, 10, &flags); + if (err || flags > UINT_MAX) + return -EINVAL; + if (flags > UKSM_RUN_MERGE) + return -EINVAL; + + mutex_lock(&uksm_thread_mutex); + if (uksm_run != flags) { + uksm_run = flags; + } + mutex_unlock(&uksm_thread_mutex); + + if (flags & UKSM_RUN_MERGE) + wake_up_interruptible(&uksm_thread_wait); + + return count; +} +UKSM_ATTR(run); + +static ssize_t abundant_threshold_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", uksm_abundant_threshold); +} + +static ssize_t abundant_threshold_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int err; + unsigned long flags; + + err = strict_strtoul(buf, 10, &flags); + if (err || flags > 99) + return -EINVAL; + + uksm_abundant_threshold = flags; + + return count; +} +UKSM_ATTR(abundant_threshold); + +static ssize_t thrash_threshold_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", uksm_thrash_threshold); +} + +static ssize_t thrash_threshold_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int err; + unsigned long flags; + + err = strict_strtoul(buf, 10, &flags); + if (err || flags > 99) + return -EINVAL; + + uksm_thrash_threshold = flags; + + return count; +} +UKSM_ATTR(thrash_threshold); + +static ssize_t cpu_ratios_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int i, size; + struct scan_rung *rung; + char *p = buf; + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + rung = &uksm_scan_ladder[i]; + + if (rung->cpu_ratio > 0) + size = sprintf(p, "%d ", rung->cpu_ratio); + else + size = sprintf(p, "MAX/%d ", + TIME_RATIO_SCALE / -rung->cpu_ratio); + + p += size; + } + + *p++ = '\n'; + *p = '\0'; + + return p - buf; +} + +static ssize_t cpu_ratios_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int i, cpuratios[SCAN_LADDER_SIZE], err; + unsigned long value; + struct scan_rung *rung; + char *p, *end = NULL; + + p = kzalloc(count, GFP_KERNEL); + if (!p) + return -ENOMEM; + + memcpy(p, buf, count); + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + if (i != SCAN_LADDER_SIZE -1) { + end = strchr(p, ' '); + if (!end) + return -EINVAL; + + *end = '\0'; + } + + if (strstr(p, "MAX/")) { + p = strchr(p, '/') + 1; + err = strict_strtoul(p, 10, &value); + if (err || value > TIME_RATIO_SCALE || !value) + return -EINVAL; + + cpuratios[i] = - (int) (TIME_RATIO_SCALE / value); + } else { + err = strict_strtoul(p, 10, &value); + if (err || value > TIME_RATIO_SCALE || !value) + return -EINVAL; + + cpuratios[i] = value; + } + + p = end + 1; + } + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + rung = &uksm_scan_ladder[i]; + + rung->cpu_ratio = cpuratios[i]; + } + + return count; +} +UKSM_ATTR(cpu_ratios); + +static ssize_t eval_intervals_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + int i, size; + struct scan_rung *rung; + char *p = buf; + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + rung = &uksm_scan_ladder[i]; + size = sprintf(p, "%u ", rung->cover_msecs); + p += size; + } + + *p++ = '\n'; + *p = '\0'; + + return p - buf; +} + +static ssize_t eval_intervals_store(struct kobject *kobj, + struct kobj_attribute *attr, + const char *buf, size_t count) +{ + int i, err; + unsigned long values[SCAN_LADDER_SIZE]; + struct scan_rung *rung; + char *p, *end = NULL; + + p = kzalloc(count, GFP_KERNEL); + if (!p) + return -ENOMEM; + + memcpy(p, buf, count); + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + if (i != SCAN_LADDER_SIZE -1) { + end = strchr(p, ' '); + if (!end) + return -EINVAL; + + *end = '\0'; + } + + err = strict_strtoul(p, 10, &values[i]); + if (err) + return -EINVAL; + + p = end + 1; + } + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + rung = &uksm_scan_ladder[i]; + + rung->cover_msecs = values[i]; + } + + return count; +} +UKSM_ATTR(eval_intervals); + +static ssize_t ema_per_page_time_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", uksm_ema_page_time); +} +UKSM_ATTR_RO(ema_per_page_time); + +static ssize_t pages_shared_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", uksm_pages_shared); +} +UKSM_ATTR_RO(pages_shared); + +static ssize_t pages_sharing_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", uksm_pages_sharing); +} +UKSM_ATTR_RO(pages_sharing); + +static ssize_t pages_unshared_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", uksm_pages_unshared); +} +UKSM_ATTR_RO(pages_unshared); + +static ssize_t full_scans_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%llu\n", fully_scanned_round); +} +UKSM_ATTR_RO(full_scans); + +static ssize_t pages_scanned_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + unsigned long base = 0; + u64 delta, ret; + + if (pages_scanned_stored) { + base = pages_scanned_base; + ret = pages_scanned_stored; + delta = uksm_pages_scanned >> base; + if (CAN_OVERFLOW_U64(ret, delta)) { + ret >>= 1; + delta >>= 1; + base++; + ret += delta; + } + } else { + ret = uksm_pages_scanned; + } + + while (ret > ULONG_MAX) { + ret >>= 1; + base++; + } + + if (base) + return sprintf(buf, "%lu * 2^%lu\n", (unsigned long)ret, base); + else + return sprintf(buf, "%lu\n", (unsigned long)ret); +} +UKSM_ATTR_RO(pages_scanned); + +static ssize_t hash_strength_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%lu\n", hash_strength); +} +UKSM_ATTR_RO(hash_strength); + +static ssize_t sleep_times_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%llu\n", uksm_sleep_times); +} +UKSM_ATTR_RO(sleep_times); + + +static struct attribute *uksm_attrs[] = { + &max_cpu_percentage_attr.attr, + &sleep_millisecs_attr.attr, + &cpu_governor_attr.attr, + &run_attr.attr, + &ema_per_page_time_attr.attr, + &pages_shared_attr.attr, + &pages_sharing_attr.attr, + &pages_unshared_attr.attr, + &full_scans_attr.attr, + &pages_scanned_attr.attr, + &hash_strength_attr.attr, + &sleep_times_attr.attr, + &thrash_threshold_attr.attr, + &abundant_threshold_attr.attr, + &cpu_ratios_attr.attr, + &eval_intervals_attr.attr, + NULL, +}; + +static struct attribute_group uksm_attr_group = { + .attrs = uksm_attrs, + .name = "uksm", +}; +#endif /* CONFIG_SYSFS */ + +static inline void init_scan_ladder(void) +{ + int i; + struct scan_rung *rung; + + for (i = 0; i < SCAN_LADDER_SIZE; i++) { + rung = uksm_scan_ladder + i; + slot_tree_init_root(&rung->vma_root); + } + + init_performance_values(); + uksm_calc_scan_pages(); +} + +static inline int cal_positive_negative_costs(void) +{ + struct page *p1, *p2; + unsigned char *addr1, *addr2; + unsigned long i, time_start, hash_cost; + unsigned long loopnum = 0; + + /*IMPORTANT: volatile is needed to prevent over-optimization by gcc. */ + volatile u32 hash; + volatile int ret; + + p1 = alloc_page(GFP_KERNEL); + if (!p1) + return -ENOMEM; + + p2 = alloc_page(GFP_KERNEL); + if (!p2) + return -ENOMEM; + + addr1 = kmap_atomic(p1); + addr2 = kmap_atomic(p2); + memset(addr1, random32(), PAGE_SIZE); + memcpy(addr2, addr1, PAGE_SIZE); + + /* make sure that the two pages differ in last byte */ + addr2[PAGE_SIZE-1] = ~addr2[PAGE_SIZE-1]; + kunmap_atomic(addr2); + kunmap_atomic(addr1); + + time_start = jiffies; + while (jiffies - time_start < 100) { + for (i = 0; i < 100; i++) + hash = page_hash(p1, HASH_STRENGTH_FULL, 0); + loopnum += 100; + } + hash_cost = (jiffies - time_start); + + time_start = jiffies; + for (i = 0; i < loopnum; i++) + ret = pages_identical(p1, p2); + memcmp_cost = HASH_STRENGTH_FULL * (jiffies - time_start); + memcmp_cost /= hash_cost; + printk(KERN_INFO "UKSM: relative memcmp_cost = %lu " + "hash=%u cmp_ret=%d.\n", + memcmp_cost, hash, ret); + + __free_page(p1); + __free_page(p2); + return 0; +} + +static int init_zeropage_hash_table(void) +{ + struct page *page; + char *addr; + int i; + + page = alloc_page(GFP_KERNEL); + if (!page) + return -ENOMEM; + + addr = kmap_atomic(page); + memset(addr, 0, PAGE_SIZE); + kunmap_atomic(addr); + + zero_hash_table = kmalloc(HASH_STRENGTH_MAX * sizeof(u32), + GFP_KERNEL); + if (!zero_hash_table) + return -ENOMEM; + + for (i = 0; i < HASH_STRENGTH_MAX; i++) + zero_hash_table[i] = page_hash(page, i, 0); + + __free_page(page); + + return 0; +} + +static inline int init_random_sampling(void) +{ + unsigned long i; + random_nums = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (!random_nums) + return -ENOMEM; + + for (i = 0; i < HASH_STRENGTH_FULL; i++) + random_nums[i] = i; + + for (i = 0; i < HASH_STRENGTH_FULL; i++) { + unsigned long rand_range, swap_index, tmp; + + rand_range = HASH_STRENGTH_FULL - i; + swap_index = i + random32() % rand_range; + tmp = random_nums[i]; + random_nums[i] = random_nums[swap_index]; + random_nums[swap_index] = tmp; + } + + rshash_state.state = RSHASH_NEW; + rshash_state.below_count = 0; + rshash_state.lookup_window_index = 0; + + return cal_positive_negative_costs(); +} + +static int __init uksm_slab_init(void) +{ + rmap_item_cache = UKSM_KMEM_CACHE(rmap_item, 0); + if (!rmap_item_cache) + goto out; + + stable_node_cache = UKSM_KMEM_CACHE(stable_node, 0); + if (!stable_node_cache) + goto out_free1; + + node_vma_cache = UKSM_KMEM_CACHE(node_vma, 0); + if (!node_vma_cache) + goto out_free2; + + vma_slot_cache = UKSM_KMEM_CACHE(vma_slot, 0); + if (!vma_slot_cache) + goto out_free3; + + tree_node_cache = UKSM_KMEM_CACHE(tree_node, 0); + if (!tree_node_cache) + goto out_free4; + + return 0; + +out_free4: + kmem_cache_destroy(vma_slot_cache); +out_free3: + kmem_cache_destroy(node_vma_cache); +out_free2: + kmem_cache_destroy(stable_node_cache); +out_free1: + kmem_cache_destroy(rmap_item_cache); +out: + return -ENOMEM; +} + +static void __init uksm_slab_free(void) +{ + kmem_cache_destroy(stable_node_cache); + kmem_cache_destroy(rmap_item_cache); + kmem_cache_destroy(node_vma_cache); + kmem_cache_destroy(vma_slot_cache); + kmem_cache_destroy(tree_node_cache); +} + +/* Common interface to ksm, different to it. */ +int ksm_madvise(struct vm_area_struct *vma, unsigned long start, + unsigned long end, int advice, unsigned long *vm_flags) +{ + int err; + + switch (advice) { + case MADV_MERGEABLE: + return 0; /* just ignore the advice */ + + case MADV_UNMERGEABLE: + if (!(*vm_flags & VM_MERGEABLE)) + return 0; /* just ignore the advice */ + + if (vma->anon_vma) { + err = unmerge_uksm_pages(vma, start, end); + if (err) + return err; + } + + uksm_remove_vma(vma); + *vm_flags &= ~VM_MERGEABLE; + break; + } + + return 0; +} + +/* Common interface to ksm, actually the same. */ +struct page *ksm_does_need_to_copy(struct page *page, + struct vm_area_struct *vma, unsigned long address) +{ + struct page *new_page; + + new_page = alloc_page_vma(GFP_HIGHUSER_MOVABLE, vma, address); + if (new_page) { + copy_user_highpage(new_page, page, address, vma); + + SetPageDirty(new_page); + __SetPageUptodate(new_page); + SetPageSwapBacked(new_page); + __set_page_locked(new_page); + + if (page_evictable(new_page, vma)) + lru_cache_add_lru(new_page, LRU_ACTIVE_ANON); + else + add_page_to_unevictable_list(new_page); + } + + return new_page; +} + +static int __init uksm_init(void) +{ + struct task_struct *uksm_thread; + int err; + + uksm_sleep_jiffies = msecs_to_jiffies(100); + uksm_sleep_saved = uksm_sleep_jiffies; + + slot_tree_init(); + init_scan_ladder(); + + + err = init_random_sampling(); + if (err) + goto out_free2; + + err = uksm_slab_init(); + if (err) + goto out_free1; + + err = init_zeropage_hash_table(); + if (err) + goto out_free0; + + uksm_thread = kthread_run(uksm_scan_thread, NULL, "uksmd"); + if (IS_ERR(uksm_thread)) { + printk(KERN_ERR "uksm: creating kthread failed\n"); + err = PTR_ERR(uksm_thread); + goto out_free; + } + +#ifdef CONFIG_SYSFS + err = sysfs_create_group(mm_kobj, &uksm_attr_group); + if (err) { + printk(KERN_ERR "uksm: register sysfs failed\n"); + kthread_stop(uksm_thread); + goto out_free; + } +#else + uksm_run = UKSM_RUN_MERGE; /* no way for user to start it */ + +#endif /* CONFIG_SYSFS */ + +#ifdef CONFIG_MEMORY_HOTREMOVE + /* + * Choose a high priority since the callback takes uksm_thread_mutex: + * later callbacks could only be taking locks which nest within that. + */ + hotplug_memory_notifier(uksm_memory_callback, 100); +#endif + return 0; + +out_free: + kfree(zero_hash_table); +out_free0: + uksm_slab_free(); +out_free1: + kfree(random_nums); +out_free2: + kfree(uksm_scan_ladder); + return err; +} + +#ifdef MODULE +module_init(uksm_init) +#else +late_initcall(uksm_init); +#endif + diff --git a/mm/vmscan.c b/mm/vmscan.c index 33dc256033b..ca46080bb07 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -2352,8 +2352,6 @@ static unsigned long do_try_to_free_pages(struct zonelist *zonelist, for (priority = DEF_PRIORITY; priority >= 0; priority--) { sc->nr_scanned = 0; - if (!priority) - disable_swap_token(sc->target_mem_cgroup); aborted_reclaim = shrink_zones(priority, zonelist, sc); /* @@ -2704,10 +2702,6 @@ static unsigned long balance_pgdat(pg_data_t *pgdat, int order, unsigned long lru_pages = 0; int has_under_min_watermark_zone = 0; - /* The swap token gets in the way of swapout... */ - if (!priority) - disable_swap_token(NULL); - all_zones_ok = 1; balanced = 0; diff --git a/mm/vmstat.c b/mm/vmstat.c index 8e18d6b44c1..a932d6a444a 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -722,6 +722,9 @@ const char * const vmstat_text[] = { "numa_other", #endif "nr_anon_transparent_hugepages", +#ifdef CONFIG_UKSM + "nr_uksm_zero_pages", +#endif "nr_free_cma", "nr_dirty_threshold", "nr_dirty_background_threshold", diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 50f73bebdd2..4412e8a276a 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -393,7 +393,7 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], } EXPORT_SYMBOL(hci_le_start_enc); -void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]) +void hci_le_ltk_reply(struct hci_conn *conn, __u8 ltk[16]) { struct hci_dev *hdev = conn->hdev; struct hci_cp_le_ltk_reply cp; @@ -403,7 +403,7 @@ void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]) memset(&cp, 0, sizeof(cp)); cp.handle = cpu_to_le16(conn->handle); - memcpy(cp.ltk, ltk, sizeof(ltk)); + memcpy(cp.ltk, ltk, sizeof(*ltk)); hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); } diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index fd9088a4a54..ce78c73d278 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1781,7 +1781,7 @@ struct sk_buff *l2cap_create_iframe_pdu(struct sock *sk, u16 sdulen, int reseg) { struct sk_buff *skb; - int err, count, hlen; + int err = 0, count = 0, hlen = 0; int reserve = 0; struct l2cap_hdr *lh; u8 fcs = l2cap_pi(sk)->fcs; @@ -3999,7 +3999,7 @@ static void l2cap_conf_ext_fs_get(struct sock *sk, void *rsp, int len) static int l2cap_finish_amp_move(struct sock *sk) { struct l2cap_pinfo *pi; - int err; + int err =0; BT_DBG("sk %p", sk); diff --git a/net/core/dev.c b/net/core/dev.c index 99e1d759f41..70145dcd17f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -1173,6 +1173,7 @@ static int __dev_open(struct net_device *dev) net_dmaengine_get(); dev_set_rx_mode(dev); dev_activate(dev); + add_device_randomness(dev->dev_addr, dev->addr_len); } return ret; @@ -4786,6 +4787,7 @@ int dev_set_mac_address(struct net_device *dev, struct sockaddr *sa) err = ops->ndo_set_mac_address(dev, sa); if (!err) call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); + add_device_randomness(dev->dev_addr, dev->addr_len); return err; } EXPORT_SYMBOL(dev_set_mac_address); @@ -5564,6 +5566,7 @@ int register_netdevice(struct net_device *dev) dev_init_scheduler(dev); dev_hold(dev); list_netdevice(dev); + add_device_randomness(dev->dev_addr, dev->addr_len); /* Notify protocols, that a new device appeared. */ ret = call_netdevice_notifiers(NETDEV_REGISTER, dev); diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index a225089df5b..96c5f0edb4c 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c @@ -35,7 +35,9 @@ bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow) struct iphdr _iph; ip: iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); - if (!iph) + + /* CVE-2013-4348 issue : make sure iph->ihl is not zero ... */ + if (!iph || iph->ihl < 5) return false; if (ip_is_fragment(iph)) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 90430b776ec..c897d512f2c 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1370,6 +1370,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, goto errout; send_addr_notify = 1; modified = 1; + add_device_randomness(dev->dev_addr, dev->addr_len); } if (tb[IFLA_MTU]) { diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 99b2596531b..a4ba3800628 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c @@ -12,12 +12,10 @@ static u32 net_secret[MD5_MESSAGE_BYTES / 4] ____cacheline_aligned; -static int __init net_secret_init(void) +void net_secret_init(void) { get_random_bytes(net_secret, sizeof(net_secret)); - return 0; } -late_initcall(net_secret_init); #ifdef CONFIG_INET static u32 seq_scale(u32 seq) diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index b9868e1fd62..aa74be442df 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c @@ -126,6 +126,9 @@ static int __sock_diag_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) if (nlmsg_len(nlh) < sizeof(*req)) return -EINVAL; + if (req->sdiag_family >= AF_MAX) + return -EINVAL; + hndl = sock_diag_lock_handler(req->sdiag_family); if (hndl == NULL) err = -ENOENT; diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 0b711659ac7..690948330d5 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -115,6 +115,7 @@ #include #include #include +#include #ifdef CONFIG_IP_MROUTE #include #endif @@ -240,8 +241,12 @@ EXPORT_SYMBOL(inet_listen); u32 inet_ehash_secret __read_mostly; EXPORT_SYMBOL(inet_ehash_secret); +u32 ipv6_hash_secret __read_mostly; +EXPORT_SYMBOL(ipv6_hash_secret); + /* - * inet_ehash_secret must be set exactly once + * inet_ehash_secret must be set exactly once, and to a non nul value + * ipv6_hash_secret must be set exactly once. */ void build_ehash_secret(void) { @@ -251,7 +256,10 @@ void build_ehash_secret(void) get_random_bytes(&rnd, sizeof(rnd)); } while (rnd == 0); - cmpxchg(&inet_ehash_secret, 0, rnd); + if (cmpxchg(&inet_ehash_secret, 0, rnd) == 0) { + get_random_bytes(&ipv6_hash_secret, sizeof(ipv6_hash_secret)); + net_secret_init(); + } } EXPORT_SYMBOL(build_ehash_secret); @@ -1559,7 +1567,7 @@ static const struct net_protocol udp_protocol = { static const struct net_protocol icmp_protocol = { .handler = icmp_rcv, - .err_handler = ping_err, + .err_handler = ping_v4_err, .no_policy = 1, .netns_ok = 1, }; diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 2cb2bf84564..2e109ff62ea 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c @@ -788,7 +788,7 @@ static void icmp_redirect(struct sk_buff *skb) if (iph->protocol == IPPROTO_ICMP && iph->ihl >= 5 && pskb_may_pull(skb, (iph->ihl<<2)+8)) { - ping_err(skb, icmp_hdr(skb)->un.gateway); + ping_v4_err(skb, icmp_hdr(skb)->un.gateway); } out: diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 50009c787bc..f441fa6bf17 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include @@ -46,8 +45,18 @@ #include #include +#if IS_ENABLED(CONFIG_IPV6) +#include +#include +#include +#include +#include +#endif -static struct ping_table ping_table; + +struct ping_table ping_table; +struct pingv6_ops pingv6_ops; +EXPORT_SYMBOL_GPL(pingv6_ops); static u16 ping_port_rover; @@ -57,6 +66,7 @@ static inline int ping_hashfn(struct net *net, unsigned num, unsigned mask) pr_debug("hash(%d) = %d\n", num, res); return res; } +EXPORT_SYMBOL_GPL(ping_hash); static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, struct net *net, unsigned num) @@ -64,7 +74,7 @@ static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)]; } -static int ping_v4_get_port(struct sock *sk, unsigned short ident) +int ping_get_port(struct sock *sk, unsigned short ident) { struct hlist_nulls_node *node; struct hlist_nulls_head *hlist; @@ -102,6 +112,10 @@ static int ping_v4_get_port(struct sock *sk, unsigned short ident) ping_portaddr_for_each_entry(sk2, node, hlist) { isk2 = inet_sk(sk2); + /* BUG? Why is this reuse and not reuseaddr? ping.c + * doesn't turn off SO_REUSEADDR, and it doesn't expect + * that other ping processes can steal its packets. + */ if ((isk2->inet_num == ident) && (sk2 != sk) && (!sk2->sk_reuse || !sk->sk_reuse)) @@ -124,17 +138,18 @@ static int ping_v4_get_port(struct sock *sk, unsigned short ident) write_unlock_bh(&ping_table.lock); return 1; } +EXPORT_SYMBOL_GPL(ping_get_port); -static void ping_v4_hash(struct sock *sk) +void ping_hash(struct sock *sk) { - pr_debug("ping_v4_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); + pr_debug("ping_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); BUG(); /* "Please do not press this button again." */ } -static void ping_v4_unhash(struct sock *sk) +void ping_unhash(struct sock *sk) { struct inet_sock *isk = inet_sk(sk); - pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); + pr_debug("ping_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); if (sk_hashed(sk)) { write_lock_bh(&ping_table.lock); hlist_nulls_del(&sk->sk_nulls_node); @@ -145,31 +160,61 @@ static void ping_v4_unhash(struct sock *sk) write_unlock_bh(&ping_table.lock); } } +EXPORT_SYMBOL_GPL(ping_unhash); -static struct sock *ping_v4_lookup(struct net *net, __be32 saddr, __be32 daddr, - u16 ident, int dif) +static struct sock *ping_lookup(struct net *net, struct sk_buff *skb, u16 ident) { struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident); struct sock *sk = NULL; struct inet_sock *isk; struct hlist_nulls_node *hnode; + int dif = skb->dev->ifindex; + + if (skb->protocol == htons(ETH_P_IP)) { + pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", + (int)ident, &ip_hdr(skb)->daddr, dif); +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + pr_debug("try to find: num = %d, daddr = %pI6c, dif = %d\n", + (int)ident, &ipv6_hdr(skb)->daddr, dif); +#endif + } - pr_debug("try to find: num = %d, daddr = %pI4, dif = %d\n", - (int)ident, &daddr, dif); read_lock_bh(&ping_table.lock); ping_portaddr_for_each_entry(sk, hnode, hslot) { isk = inet_sk(sk); - pr_debug("found: %p: num = %d, daddr = %pI4, dif = %d\n", sk, - (int)isk->inet_num, &isk->inet_rcv_saddr, - sk->sk_bound_dev_if); - pr_debug("iterate\n"); if (isk->inet_num != ident) continue; - if (isk->inet_rcv_saddr && isk->inet_rcv_saddr != daddr) - continue; + + if (skb->protocol == htons(ETH_P_IP) && + sk->sk_family == AF_INET) { + pr_debug("found: %p: num=%d, daddr=%pI4, dif=%d\n", sk, + (int) isk->inet_num, &isk->inet_rcv_saddr, + sk->sk_bound_dev_if); + + if (isk->inet_rcv_saddr && + isk->inet_rcv_saddr != ip_hdr(skb)->daddr) + continue; +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6) && + sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + + pr_debug("found: %p: num=%d, daddr=%pI6c, dif=%d\n", sk, + (int) isk->inet_num, + &inet6_sk(sk)->rcv_saddr, + sk->sk_bound_dev_if); + + if (!ipv6_addr_any(&np->rcv_saddr) && + !ipv6_addr_equal(&np->rcv_saddr, + &ipv6_hdr(skb)->daddr)) + continue; +#endif + } + if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) continue; @@ -198,7 +243,7 @@ static void inet_get_ping_group_range_net(struct net *net, gid_t *low, } -static int ping_init_sock(struct sock *sk) +int ping_init_sock(struct sock *sk) { struct net *net = sock_net(sk); gid_t group = current_egid(); @@ -224,8 +269,9 @@ static int ping_init_sock(struct sock *sk) return -EACCES; } +EXPORT_SYMBOL_GPL(ping_init_sock); -static void ping_close(struct sock *sk, long timeout) +void ping_close(struct sock *sk, long timeout) { pr_debug("ping_close(sk=%p,sk->num=%u)\n", inet_sk(sk), inet_sk(sk)->inet_num); @@ -233,36 +279,122 @@ static void ping_close(struct sock *sk, long timeout) sk_common_release(sk); } +EXPORT_SYMBOL_GPL(ping_close); + +/* Checks the bind address and possibly modifies sk->sk_bound_dev_if. */ +int ping_check_bind_addr(struct sock *sk, struct inet_sock *isk, + struct sockaddr *uaddr, int addr_len) { + struct net *net = sock_net(sk); + if (sk->sk_family == AF_INET) { + struct sockaddr_in *addr = (struct sockaddr_in *) uaddr; + int chk_addr_ret; + + if (addr_len < sizeof(*addr)) + return -EINVAL; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI4,port=%d)\n", + sk, &addr->sin_addr.s_addr, ntohs(addr->sin_port)); + + chk_addr_ret = inet_addr_type(net, addr->sin_addr.s_addr); + + if (addr->sin_addr.s_addr == htonl(INADDR_ANY)) + chk_addr_ret = RTN_LOCAL; + + if ((sysctl_ip_nonlocal_bind == 0 && + isk->freebind == 0 && isk->transparent == 0 && + chk_addr_ret != RTN_LOCAL) || + chk_addr_ret == RTN_MULTICAST || + chk_addr_ret == RTN_BROADCAST) + return -EADDRNOTAVAIL; + +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) uaddr; + int addr_type, scoped, has_addr; + struct net_device *dev = NULL; + + if (addr_len < sizeof(*addr)) + return -EINVAL; + + pr_debug("ping_check_bind_addr(sk=%p,addr=%pI6c,port=%d)\n", + sk, addr->sin6_addr.s6_addr, ntohs(addr->sin6_port)); + + addr_type = ipv6_addr_type(&addr->sin6_addr); + scoped = __ipv6_addr_needs_scope_id(addr_type); + if ((addr_type != IPV6_ADDR_ANY && + !(addr_type & IPV6_ADDR_UNICAST)) || + (scoped && !addr->sin6_scope_id)) + return -EINVAL; + + rcu_read_lock(); + if (addr->sin6_scope_id) { + dev = dev_get_by_index_rcu(net, addr->sin6_scope_id); + if (!dev) { + rcu_read_unlock(); + return -ENODEV; + } + } + has_addr = pingv6_ops.ipv6_chk_addr(net, &addr->sin6_addr, dev, + scoped); + rcu_read_unlock(); + + if (!(isk->freebind || isk->transparent || has_addr || + addr_type == IPV6_ADDR_ANY)) + return -EADDRNOTAVAIL; + + if (scoped) + sk->sk_bound_dev_if = addr->sin6_scope_id; +#endif + } else { + return -EAFNOSUPPORT; + } + return 0; +} +void ping_set_saddr(struct sock *sk, struct sockaddr *saddr) +{ + if (saddr->sa_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + struct sockaddr_in *addr = (struct sockaddr_in *) saddr; + isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; +#if IS_ENABLED(CONFIG_IPV6) + } else if (saddr->sa_family == AF_INET6) { + struct sockaddr_in6 *addr = (struct sockaddr_in6 *) saddr; + struct ipv6_pinfo *np = inet6_sk(sk); + np->rcv_saddr = np->saddr = addr->sin6_addr; +#endif + } +} + +void ping_clear_saddr(struct sock *sk, int dif) +{ + sk->sk_bound_dev_if = dif; + if (sk->sk_family == AF_INET) { + struct inet_sock *isk = inet_sk(sk); + isk->inet_rcv_saddr = isk->inet_saddr = 0; +#if IS_ENABLED(CONFIG_IPV6) + } else if (sk->sk_family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + memset(&np->rcv_saddr, 0, sizeof(np->rcv_saddr)); + memset(&np->saddr, 0, sizeof(np->saddr)); +#endif + } +} /* * We need our own bind because there are no privileged id's == local ports. * Moreover, we don't allow binding to multi- and broadcast addresses. */ -static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) +int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) { - struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; struct inet_sock *isk = inet_sk(sk); unsigned short snum; - int chk_addr_ret; int err; + int dif = sk->sk_bound_dev_if; - if (addr_len < sizeof(struct sockaddr_in)) - return -EINVAL; - - pr_debug("ping_v4_bind(sk=%p,sa_addr=%08x,sa_port=%d)\n", - sk, addr->sin_addr.s_addr, ntohs(addr->sin_port)); - - chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); - if (addr->sin_addr.s_addr == htonl(INADDR_ANY)) - chk_addr_ret = RTN_LOCAL; - - if ((sysctl_ip_nonlocal_bind == 0 && - isk->freebind == 0 && isk->transparent == 0 && - chk_addr_ret != RTN_LOCAL) || - chk_addr_ret == RTN_MULTICAST || - chk_addr_ret == RTN_BROADCAST) - return -EADDRNOTAVAIL; + err = ping_check_bind_addr(sk, isk, uaddr, addr_len); + if (err) + return err; lock_sock(sk); @@ -271,42 +403,50 @@ static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) goto out; err = -EADDRINUSE; - isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; - snum = ntohs(addr->sin_port); - if (ping_v4_get_port(sk, snum) != 0) { - isk->inet_saddr = isk->inet_rcv_saddr = 0; + ping_set_saddr(sk, uaddr); + snum = ntohs(((struct sockaddr_in *)uaddr)->sin_port); + if (ping_get_port(sk, snum) != 0) { + ping_clear_saddr(sk, dif); goto out; } - pr_debug("after bind(): num = %d, daddr = %pI4, dif = %d\n", + pr_debug("after bind(): num = %d, dif = %d\n", (int)isk->inet_num, - &isk->inet_rcv_saddr, (int)sk->sk_bound_dev_if); err = 0; - if (isk->inet_rcv_saddr) + if ((sk->sk_family == AF_INET && isk->inet_rcv_saddr) || + (sk->sk_family == AF_INET6 && + !ipv6_addr_any(&inet6_sk(sk)->rcv_saddr))) sk->sk_userlocks |= SOCK_BINDADDR_LOCK; + if (snum) sk->sk_userlocks |= SOCK_BINDPORT_LOCK; isk->inet_sport = htons(isk->inet_num); isk->inet_daddr = 0; isk->inet_dport = 0; + +#if IS_ENABLED(CONFIG_IPV6) + if (sk->sk_family == AF_INET6) + memset(&inet6_sk(sk)->daddr, 0, sizeof(inet6_sk(sk)->daddr)); +#endif + sk_dst_reset(sk); out: release_sock(sk); pr_debug("ping_v4_bind -> %d\n", err); return err; } +EXPORT_SYMBOL_GPL(ping_bind); /* * Is this a supported type of ICMP message? */ -static inline int ping_supported(int type, int code) +static inline int ping_supported(int family, int type, int code) { - if (type == ICMP_ECHO && code == 0) - return 1; - return 0; + return (family == AF_INET && type == ICMP_ECHO && code == 0) || + (family == AF_INET6 && type == ICMPV6_ECHO_REQUEST && code == 0); } /* @@ -314,30 +454,44 @@ static inline int ping_supported(int type, int code) * sort of error condition. */ -static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); - -void ping_err(struct sk_buff *skb, u32 info) +void ping_err(struct sk_buff *skb, int offset, u32 info) { - struct iphdr *iph = (struct iphdr *)skb->data; - struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); + int family; + struct icmphdr *icmph; struct inet_sock *inet_sock; - int type = icmph->type; - int code = icmph->code; + int type; + int code; struct net *net = dev_net(skb->dev); struct sock *sk; int harderr; int err; + if (skb->protocol == htons(ETH_P_IP)) { + struct iphdr *iph = (struct iphdr *)skb->data; + offset = iph->ihl << 2; + family = AF_INET; + type = icmp_hdr(skb)->type; + code = icmp_hdr(skb)->code; + icmph = (struct icmphdr *)(skb->data + offset); + } else if (skb->protocol == htons(ETH_P_IPV6)) { + family = AF_INET6; + type = icmp6_hdr(skb)->icmp6_type; + code = icmp6_hdr(skb)->icmp6_code; + icmph = (struct icmphdr *) (skb->data + offset); + } else { + BUG(); + } + /* We assume the packet has already been checked by icmp_unreach */ - if (!ping_supported(icmph->type, icmph->code)) + if (!ping_supported(family, icmph->type, icmph->code)) return; - pr_debug("ping_err(type=%04x,code=%04x,id=%04x,seq=%04x)\n", type, - code, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence)); + pr_debug("ping_err(proto=0x%x,type=%d,code=%d,id=%04x,seq=%04x)\n", + skb->protocol, type, code, ntohs(icmph->un.echo.id), + ntohs(icmph->un.echo.sequence)); - sk = ping_v4_lookup(net, iph->daddr, iph->saddr, - ntohs(icmph->un.echo.id), skb->dev->ifindex); + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); if (sk == NULL) { pr_debug("no socket, dropping\n"); return; /* No socket for error */ @@ -348,70 +502,85 @@ void ping_err(struct sk_buff *skb, u32 info) harderr = 0; inet_sock = inet_sk(sk); - switch (type) { - default: - case ICMP_TIME_EXCEEDED: - err = EHOSTUNREACH; - break; - case ICMP_SOURCE_QUENCH: - /* This is not a real error but ping wants to see it. - * Report it with some fake errno. */ - err = EREMOTEIO; - break; - case ICMP_PARAMETERPROB: - err = EPROTO; - harderr = 1; - break; - case ICMP_DEST_UNREACH: - if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ - if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { - err = EMSGSIZE; - harderr = 1; - break; + if (skb->protocol == htons(ETH_P_IP)) { + switch (type) { + default: + case ICMP_TIME_EXCEEDED: + err = EHOSTUNREACH; + break; + case ICMP_SOURCE_QUENCH: + /* This is not a real error but ping wants to see it. + * Report it with some fake errno. */ + err = EREMOTEIO; + break; + case ICMP_PARAMETERPROB: + err = EPROTO; + harderr = 1; + break; + case ICMP_DEST_UNREACH: + if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ + if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { + err = EMSGSIZE; + harderr = 1; + break; + } + goto out; } - goto out; - } - err = EHOSTUNREACH; - if (code <= NR_ICMP_UNREACH) { - harderr = icmp_err_convert[code].fatal; - err = icmp_err_convert[code].errno; + err = EHOSTUNREACH; + if (code <= NR_ICMP_UNREACH) { + harderr = icmp_err_convert[code].fatal; + err = icmp_err_convert[code].errno; + } + break; + case ICMP_REDIRECT: + /* See ICMP_SOURCE_QUENCH */ + err = EREMOTEIO; + break; } - break; - case ICMP_REDIRECT: - /* See ICMP_SOURCE_QUENCH */ - err = EREMOTEIO; - break; +#if IS_ENABLED(CONFIG_IPV6) + } else if (skb->protocol == htons(ETH_P_IPV6)) { + harderr = pingv6_ops.icmpv6_err_convert(type, code, &err); +#endif } /* * RFC1122: OK. Passes ICMP errors back to application, as per * 4.1.3.3. */ - if (!inet_sock->recverr) { + if ((family == AF_INET && !inet_sock->recverr) || + (family == AF_INET6 && !inet6_sk(sk)->recverr)) { if (!harderr || sk->sk_state != TCP_ESTABLISHED) goto out; } else { - ip_icmp_error(sk, skb, err, 0 /* no remote port */, - info, (u8 *)icmph); + if (family == AF_INET) { + ip_icmp_error(sk, skb, err, 0 /* no remote port */, + info, (u8 *)icmph); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + pingv6_ops.ipv6_icmp_error(sk, skb, err, 0, + info, (u8 *)icmph); +#endif + } } sk->sk_err = err; sk->sk_error_report(sk); out: sock_put(sk); } +EXPORT_SYMBOL_GPL(ping_err); + +void ping_v4_err(struct sk_buff *skb, u32 info) +{ + ping_err(skb, 0, info); +} /* - * Copy and checksum an ICMP Echo packet from user space into a buffer. + * Copy and checksum an ICMP Echo packet from user space into a buffer + * starting from the payload. */ -struct pingfakehdr { - struct icmphdr icmph; - struct iovec *iov; - __wsum wcheck; -}; - -static int ping_getfrag(void *from, char * to, - int offset, int fraglen, int odd, struct sk_buff *skb) +int ping_getfrag(void *from, char *to, + int offset, int fraglen, int odd, struct sk_buff *skb) { struct pingfakehdr *pfh = (struct pingfakehdr *)from; @@ -422,20 +591,33 @@ static int ping_getfrag(void *from, char * to, pfh->iov, 0, fraglen - sizeof(struct icmphdr), &pfh->wcheck)) return -EFAULT; + } else if (offset < sizeof(struct icmphdr)) { + BUG(); + } else { + if (csum_partial_copy_fromiovecend + (to, pfh->iov, offset - sizeof(struct icmphdr), + fraglen, &pfh->wcheck)) + return -EFAULT; + } - return 0; +#if IS_ENABLED(CONFIG_IPV6) + /* For IPv6, checksum each skb as we go along, as expected by + * icmpv6_push_pending_frames. For IPv4, accumulate the checksum in + * wcheck, it will be finalized in ping_v4_push_pending_frames. + */ + if (pfh->family == AF_INET6) { + skb->csum = pfh->wcheck; + skb->ip_summed = CHECKSUM_NONE; + pfh->wcheck = 0; } - if (offset < sizeof(struct icmphdr)) - BUG(); - if (csum_partial_copy_fromiovecend - (to, pfh->iov, offset - sizeof(struct icmphdr), - fraglen, &pfh->wcheck)) - return -EFAULT; +#endif + return 0; } +EXPORT_SYMBOL_GPL(ping_getfrag); -static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, - struct flowi4 *fl4) +static int ping_v4_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, + struct flowi4 *fl4) { struct sk_buff *skb = skb_peek(&sk->sk_write_queue); @@ -447,24 +629,9 @@ static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, return ip_push_pending_frames(sk, fl4); } -static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len) -{ - struct net *net = sock_net(sk); - struct flowi4 fl4; - struct inet_sock *inet = inet_sk(sk); - struct ipcm_cookie ipc; - struct icmphdr user_icmph; - struct pingfakehdr pfh; - struct rtable *rt = NULL; - struct ip_options_data opt_copy; - int free = 0; - __be32 saddr, daddr, faddr; - u8 tos; - int err; - - pr_debug("ping_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); - +int ping_common_sendmsg(int family, struct msghdr *msg, size_t len, + void *user_icmph, size_t icmph_len) { + u8 type, code; if (len > 0xFFFF) return -EMSGSIZE; @@ -479,15 +646,53 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, /* * Fetch the ICMP header provided by the userland. - * iovec is modified! + * iovec is modified! The ICMP header is consumed. */ - - if (memcpy_fromiovec((u8 *)&user_icmph, msg->msg_iov, - sizeof(struct icmphdr))) + if (memcpy_fromiovec(user_icmph, msg->msg_iov, icmph_len)) return -EFAULT; - if (!ping_supported(user_icmph.type, user_icmph.code)) + + if (family == AF_INET) { + type = ((struct icmphdr *) user_icmph)->type; + code = ((struct icmphdr *) user_icmph)->code; +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + type = ((struct icmp6hdr *) user_icmph)->icmp6_type; + code = ((struct icmp6hdr *) user_icmph)->icmp6_code; +#endif + } else { + BUG(); + } + + if (!ping_supported(family, type, code)) return -EINVAL; + return 0; +} +EXPORT_SYMBOL_GPL(ping_common_sendmsg); + +int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct net *net = sock_net(sk); + struct flowi4 fl4; + struct inet_sock *inet = inet_sk(sk); + struct ipcm_cookie ipc; + struct icmphdr user_icmph; + struct pingfakehdr pfh; + struct rtable *rt = NULL; + struct ip_options_data opt_copy; + int free = 0; + __be32 saddr, daddr, faddr; + u8 tos; + int err; + + pr_debug("ping_v4_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + err = ping_common_sendmsg(AF_INET, msg, len, &user_icmph, + sizeof(user_icmph)); + if (err) + return err; + /* * Get and verify the address. */ @@ -593,13 +798,14 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; pfh.iov = msg->msg_iov; pfh.wcheck = 0; + pfh.family = AF_INET; err = ip_append_data(sk, &fl4, ping_getfrag, &pfh, len, 0, &ipc, &rt, msg->msg_flags); if (err) ip_flush_pending_frames(sk); else - err = ping_push_pending_frames(sk, &pfh, &fl4); + err = ping_v4_push_pending_frames(sk, &pfh, &fl4); release_sock(sk); out: @@ -620,11 +826,13 @@ static int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, goto out; } -static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, - size_t len, int noblock, int flags, int *addr_len) +int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len, int noblock, int flags, int *addr_len) { struct inet_sock *isk = inet_sk(sk); - struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; + int family = sk->sk_family; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; struct sk_buff *skb; int copied, err; @@ -634,11 +842,22 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (flags & MSG_OOB) goto out; - if (addr_len) - *addr_len = sizeof(*sin); + if (addr_len) { + if (family == AF_INET) + *addr_len = sizeof(*sin); + else if (family == AF_INET6 && addr_len) + *addr_len = sizeof(*sin6); + } - if (flags & MSG_ERRQUEUE) - return ip_recv_error(sk, msg, len); + if (flags & MSG_ERRQUEUE) { + if (family == AF_INET) { + return ip_recv_error(sk, msg, len); +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + return pingv6_ops.ipv6_recv_error(sk, msg, len); +#endif + } + } skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) @@ -657,15 +876,45 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, sock_recv_timestamp(msg, sk, skb); - /* Copy the address. */ - if (sin) { - sin->sin_family = AF_INET; - sin->sin_port = 0 /* skb->h.uh->source */; - sin->sin_addr.s_addr = ip_hdr(skb)->saddr; - memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + /* Copy the address and add cmsg data. */ + if (family == AF_INET) { + sin = (struct sockaddr_in *) msg->msg_name; + if (sin) { + sin->sin_family = AF_INET; + sin->sin_port = 0 /* skb->h.uh->source */; + sin->sin_addr.s_addr = ip_hdr(skb)->saddr; + memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); + } + + if (isk->cmsg_flags) + ip_cmsg_recv(msg, skb); + +#if IS_ENABLED(CONFIG_IPV6) + } else if (family == AF_INET6) { + struct ipv6_pinfo *np = inet6_sk(sk); + struct ipv6hdr *ip6 = ipv6_hdr(skb); + sin6 = (struct sockaddr_in6 *) msg->msg_name; + + if (sin6) { + sin6->sin6_family = AF_INET6; + sin6->sin6_port = 0; + sin6->sin6_addr = ip6->saddr; + sin6->sin6_flowinfo = 0; + if (np->sndflow) + sin6->sin6_flowinfo = + *(__be32 *)ip6 & IPV6_FLOWINFO_MASK; + sin6->sin6_scope_id = + ipv6_iface_scope_id(&sin6->sin6_addr, + IP6CB(skb)->iif); + } + + if (inet6_sk(sk)->rxopt.all) + pingv6_ops.datagram_recv_ctl(sk, msg, skb); +#endif + } else { + BUG(); } - if (isk->cmsg_flags) - ip_cmsg_recv(msg, skb); + err = copied; done: @@ -674,8 +923,9 @@ static int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, pr_debug("ping_recvmsg -> %d\n", err); return err; } +EXPORT_SYMBOL_GPL(ping_recvmsg); -static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) +int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) { pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n", inet_sk(sk), inet_sk(sk)->inet_num, skb); @@ -686,6 +936,7 @@ static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) } return 0; } +EXPORT_SYMBOL_GPL(ping_queue_rcv_skb); /* @@ -696,10 +947,7 @@ void ping_rcv(struct sk_buff *skb) { struct sock *sk; struct net *net = dev_net(skb->dev); - struct iphdr *iph = ip_hdr(skb); struct icmphdr *icmph = icmp_hdr(skb); - __be32 saddr = iph->saddr; - __be32 daddr = iph->daddr; /* We assume the packet has already been checked by icmp_rcv */ @@ -709,8 +957,7 @@ void ping_rcv(struct sk_buff *skb) /* Push ICMP header back */ skb_push(skb, skb->data - (u8 *)icmph); - sk = ping_v4_lookup(net, saddr, daddr, ntohs(icmph->un.echo.id), - skb->dev->ifindex); + sk = ping_lookup(net, skb, ntohs(icmph->un.echo.id)); if (sk != NULL) { pr_debug("rcv on socket %p\n", sk); ping_queue_rcv_skb(sk, skb_get(skb)); @@ -721,6 +968,7 @@ void ping_rcv(struct sk_buff *skb) /* We're called from icmp_rcv(). kfree_skb() is done there. */ } +EXPORT_SYMBOL_GPL(ping_rcv); struct proto ping_prot = { .name = "PING", @@ -731,13 +979,13 @@ struct proto ping_prot = { .disconnect = udp_disconnect, .setsockopt = ip_setsockopt, .getsockopt = ip_getsockopt, - .sendmsg = ping_sendmsg, + .sendmsg = ping_v4_sendmsg, .recvmsg = ping_recvmsg, .bind = ping_bind, .backlog_rcv = ping_queue_rcv_skb, - .hash = ping_v4_hash, - .unhash = ping_v4_unhash, - .get_port = ping_v4_get_port, + .hash = ping_hash, + .unhash = ping_unhash, + .get_port = ping_get_port, .obj_size = sizeof(struct inet_sock), }; EXPORT_SYMBOL(ping_prot); diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 7a7724da9bf..060667a61cc 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -121,6 +121,21 @@ static int ipv4_ping_group_range(ctl_table *table, int write, return ret; } +/* Validate changes from /proc interface. */ +static int proc_tcp_default_init_rwnd(ctl_table *ctl, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) +{ + int old_value = *(int *)ctl->data; + int ret = proc_dointvec(ctl, write, buffer, lenp, ppos); + int new_value = *(int *)ctl->data; + + if (write && ret == 0 && (new_value < 3 || new_value > 100)) + *(int *)ctl->data = old_value; + + return ret; +} + static int proc_tcp_congestion_control(ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) { @@ -669,13 +684,20 @@ static struct ctl_table ipv4_table[] = { .mode = 0644, .proc_handler = proc_dointvec }, - { + { .procname = "tcp_thin_dupack", .data = &sysctl_tcp_thin_dupack, .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec }, + { + .procname = "tcp_default_init_rwnd", + .data = &sysctl_tcp_default_init_rwnd, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_tcp_default_init_rwnd + }, { .procname = "udp_mem", .data = &sysctl_udp_mem, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 257b61789ee..4210840b0dc 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -99,6 +99,7 @@ int sysctl_tcp_thin_dupack __read_mostly; int sysctl_tcp_moderate_rcvbuf __read_mostly = 1; int sysctl_tcp_abc __read_mostly; +int sysctl_tcp_default_init_rwnd __read_mostly = TCP_DEFAULT_INIT_RCVWND; #define FLAG_DATA 0x01 /* Incoming frame contained data. */ #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ @@ -348,14 +349,14 @@ static void tcp_grow_window(struct sock *sk, const struct sk_buff *skb) static void tcp_fixup_rcvbuf(struct sock *sk) { u32 mss = tcp_sk(sk)->advmss; - u32 icwnd = TCP_DEFAULT_INIT_RCVWND; + u32 icwnd = sysctl_tcp_default_init_rwnd; int rcvmem; /* Limit to 10 segments if mss <= 1460, * or 14600/mss segments, with a minimum of two segments. */ if (mss > 1460) - icwnd = max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2); + icwnd = max_t(u32, (1460 * icwnd) / mss, 2); rcvmem = SKB_TRUESIZE(mss + MAX_TCP_HEADER); while (tcp_win_from_space(rcvmem) < mss) @@ -4373,10 +4374,11 @@ static void tcp_sack_remove(struct tcp_sock *tp) return; } + BUG_ON(num_sacks > 4); for (this_sack = 0; this_sack < num_sacks;) { /* Check if the start of the sack is covered by RCV.NXT. */ if (!before(tp->rcv_nxt, sp->start_seq)) { - int i; + int i = 0; /* RCV.NXT must cover all the block! */ WARN_ON(before(tp->rcv_nxt, sp->end_seq)); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 7ac6423117a..08b49f8f628 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -229,14 +229,13 @@ void tcp_select_initial_window(int __space, __u32 mss, } /* Set initial window to a value enough for senders starting with - * initial congestion window of TCP_DEFAULT_INIT_RCVWND. Place + * initial congestion window of sysctl_tcp_default_init_rwnd. Place * a limit on the initial window when mss is larger than 1460. */ if (mss > (1 << *rcv_wscale)) { - int init_cwnd = TCP_DEFAULT_INIT_RCVWND; + int init_cwnd = sysctl_tcp_default_init_rwnd; if (mss > 1460) - init_cwnd = - max_t(u32, (1460 * TCP_DEFAULT_INIT_RCVWND) / mss, 2); + init_cwnd = max_t(u32, (1460 * init_cwnd) / mss, 2); /* when initializing use the value from init_rcv_wnd * rather than the default from above */ diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 686934acfac..753be5dd409 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile @@ -7,7 +7,7 @@ obj-$(CONFIG_IPV6) += ipv6.o ipv6-objs := af_inet6.o anycast.o ip6_output.o ip6_input.o addrconf.o \ addrlabel.o \ route.o ip6_fib.o ipv6_sockglue.o ndisc.o udp.o udplite.o \ - raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o \ + raw.o protocol.o icmp.o mcast.o reassembly.o tcp_ipv6.o ping.o \ exthdrs.o datagram.o ip6_flowlabel.o inet6_connection_sock.o ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 29625e9a51a..22ebbb97283 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -1130,6 +1131,9 @@ static int __init inet6_init(void) if (err) goto out_unregister_udplite_proto; + err = proto_register(&pingv6_prot, 1); + if (err) + goto out_unregister_ping_proto; /* We MUST register RAW sockets before we create the ICMP6, * IGMP6, or NDISC control sockets. @@ -1225,6 +1229,10 @@ static int __init inet6_init(void) if (err) goto ipv6_packet_fail; + err = pingv6_init(); + if (err) + goto pingv6_fail; + #ifdef CONFIG_SYSCTL err = ipv6_sysctl_register(); if (err) @@ -1237,6 +1245,8 @@ static int __init inet6_init(void) sysctl_fail: ipv6_packet_cleanup(); #endif +pingv6_fail: + pingv6_exit(); ipv6_packet_fail: tcpv6_exit(); tcpv6_fail: @@ -1284,6 +1294,8 @@ static int __init inet6_init(void) rtnl_unregister_all(PF_INET6); out_sock_register_fail: rawv6_exit(); +out_unregister_ping_proto: + proto_unregister(&pingv6_prot); out_unregister_raw_proto: proto_unregister(&rawv6_prot); out_unregister_udplite_proto: diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 27ac95a6342..ba0c1479ba0 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c @@ -55,6 +55,7 @@ #include #include +#include #include #include #include @@ -79,10 +80,22 @@ static inline struct sock *icmpv6_sk(struct net *net) return net->ipv6.icmp_sk[smp_processor_id()]; } +static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, + u8 type, u8 code, int offset, __be32 info) +{ + /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */ + struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset); + + if (!(type & ICMPV6_INFOMSG_MASK)) + if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST) + ping_err(skb, offset, info); +} + static int icmpv6_rcv(struct sk_buff *skb); static const struct inet6_protocol icmpv6_protocol = { .handler = icmpv6_rcv, + .err_handler = icmpv6_err, .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, }; @@ -217,7 +230,8 @@ static __inline__ int opt_unrec(struct sk_buff *skb, __u32 offset) return (*op & 0xC0) == 0x80; } -static int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, struct icmp6hdr *thdr, int len) +int icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, + struct icmp6hdr *thdr, int len) { struct sk_buff *skb; struct icmp6hdr *icmp6h; @@ -300,8 +314,8 @@ static void mip6_addr_swap(struct sk_buff *skb) static inline void mip6_addr_swap(struct sk_buff *skb) {} #endif -static struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, - struct sock *sk, struct flowi6 *fl6) +struct dst_entry *icmpv6_route_lookup(struct net *net, struct sk_buff *skb, + struct sock *sk, struct flowi6 *fl6) { struct dst_entry *dst, *dst2; struct flowi6 fl2; @@ -594,7 +608,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) icmpv6_xmit_unlock(sk); } -static void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) +void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) { const struct inet6_protocol *ipprot; int inner_offset; @@ -687,7 +701,8 @@ static int icmpv6_rcv(struct sk_buff *skb) skb->csum = ~csum_unfold(csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_ICMPV6, 0)); if (__skb_checksum_complete(skb)) { - LIMIT_NETDEBUG(KERN_DEBUG "ICMPv6 checksum failed [%pI6 > %pI6]\n", + LIMIT_NETDEBUG(KERN_DEBUG + "ICMPv6 checksum failed [%pI6c > %pI6c]\n", saddr, daddr); goto discard_it; } @@ -708,7 +723,7 @@ static int icmpv6_rcv(struct sk_buff *skb) break; case ICMPV6_ECHO_REPLY: - /* we couldn't care less */ + ping_rcv(skb); break; case ICMPV6_PKT_TOOBIG: diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c new file mode 100644 index 00000000000..cfb1b5de810 --- /dev/null +++ b/net/ipv6/ping.c @@ -0,0 +1,222 @@ +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX + * operating system. INET is implemented using the BSD Socket + * interface as the means of communication with the user level. + * + * "Ping" sockets + * + * 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. + * + * Based on ipv4/ping.c code. + * + * Authors: Lorenzo Colitti (IPv6 support) + * Vasiliy Kulikov / Openwall (IPv4 implementation, for Linux 2.6), + * Pavel Kankovsky (IPv4 implementation, for Linux 2.4.32) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct proto pingv6_prot = { + .name = "PINGv6", + .owner = THIS_MODULE, + .init = ping_init_sock, + .close = ping_close, + .connect = ip6_datagram_connect, + .disconnect = udp_disconnect, + .setsockopt = ipv6_setsockopt, + .getsockopt = ipv6_getsockopt, + .sendmsg = ping_v6_sendmsg, + .recvmsg = ping_recvmsg, + .bind = ping_bind, + .backlog_rcv = ping_queue_rcv_skb, + .hash = ping_hash, + .unhash = ping_unhash, + .get_port = ping_get_port, + .obj_size = sizeof(struct raw6_sock), +}; +EXPORT_SYMBOL_GPL(pingv6_prot); + +static struct inet_protosw pingv6_protosw = { + .type = SOCK_DGRAM, + .protocol = IPPROTO_ICMPV6, + .prot = &pingv6_prot, + .ops = &inet6_dgram_ops, + .no_check = UDP_CSUM_DEFAULT, + .flags = INET_PROTOSW_REUSE, +}; + + +/* Compatibility glue so we can support IPv6 when it's compiled as a module */ +int dummy_ipv6_recv_error(struct sock *sk, struct msghdr *msg, int len) +{ + return -EAFNOSUPPORT; +} +int dummy_datagram_recv_ctl(struct sock *sk, struct msghdr *msg, + struct sk_buff *skb) +{ + return -EAFNOSUPPORT; +} +int dummy_icmpv6_err_convert(u8 type, u8 code, int *err) +{ + return -EAFNOSUPPORT; +} +void dummy_ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, + __be16 port, u32 info, u8 *payload) {} +int dummy_ipv6_chk_addr(struct net *net, const struct in6_addr *addr, + struct net_device *dev, int strict) +{ + return 0; +} + +int __init pingv6_init(void) +{ + pingv6_ops.ipv6_recv_error = ipv6_recv_error; + pingv6_ops.datagram_recv_ctl = datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = ipv6_chk_addr; + return inet6_register_protosw(&pingv6_protosw); +} + +/* This never gets called because it's not possible to unload the ipv6 module, + * but just in case. + */ +void pingv6_exit(void) +{ + pingv6_ops.ipv6_recv_error = dummy_ipv6_recv_error; + pingv6_ops.datagram_recv_ctl = dummy_datagram_recv_ctl; + pingv6_ops.icmpv6_err_convert = dummy_icmpv6_err_convert; + pingv6_ops.ipv6_icmp_error = dummy_ipv6_icmp_error; + pingv6_ops.ipv6_chk_addr = dummy_ipv6_chk_addr; + inet6_unregister_protosw(&pingv6_protosw); +} + +int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, + size_t len) +{ + struct inet_sock *inet = inet_sk(sk); + struct ipv6_pinfo *np = inet6_sk(sk); + struct icmp6hdr user_icmph; + int addr_type; + struct in6_addr *daddr; + int iif = 0; + struct flowi6 fl6; + int err; + int hlimit; + struct dst_entry *dst; + struct rt6_info *rt; + struct pingfakehdr pfh; + + pr_debug("ping_v6_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); + + err = ping_common_sendmsg(AF_INET6, msg, len, &user_icmph, + sizeof(user_icmph)); + if (err) + return err; + + if (msg->msg_name) { + struct sockaddr_in6 *u = (struct sockaddr_in6 *) msg->msg_name; + if (msg->msg_namelen < sizeof(struct sockaddr_in6) || + u->sin6_family != AF_INET6) { + return -EINVAL; + } + if (sk->sk_bound_dev_if && + sk->sk_bound_dev_if != u->sin6_scope_id) { + return -EINVAL; + } + daddr = &(u->sin6_addr); + iif = u->sin6_scope_id; + } else { + if (sk->sk_state != TCP_ESTABLISHED) + return -EDESTADDRREQ; + daddr = &np->daddr; + } + + if (!iif) + iif = sk->sk_bound_dev_if; + + addr_type = ipv6_addr_type(daddr); + if (__ipv6_addr_needs_scope_id(addr_type) && !iif) + return -EINVAL; + if (addr_type & IPV6_ADDR_MAPPED) + return -EINVAL; + + /* TODO: use ip6_datagram_send_ctl to get options from cmsg */ + + memset(&fl6, 0, sizeof(fl6)); + + fl6.flowi6_proto = IPPROTO_ICMPV6; + fl6.saddr = np->saddr; + fl6.daddr = *daddr; + fl6.fl6_icmp_type = user_icmph.icmp6_type; + fl6.fl6_icmp_code = user_icmph.icmp6_code; + security_sk_classify_flow(sk, flowi6_to_flowi(&fl6)); + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = np->mcast_oif; + else if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->ucast_oif; + + dst = ip6_sk_dst_lookup_flow(sk, &fl6, daddr, 1); + if (IS_ERR(dst)) + return PTR_ERR(dst); + rt = (struct rt6_info *) dst; + + np = inet6_sk(sk); + if (!np) + return -EBADF; + + if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr)) + fl6.flowi6_oif = np->mcast_oif; + else if (!fl6.flowi6_oif) + fl6.flowi6_oif = np->ucast_oif; + + pfh.icmph.type = user_icmph.icmp6_type; + pfh.icmph.code = user_icmph.icmp6_code; + pfh.icmph.checksum = 0; + pfh.icmph.un.echo.id = inet->inet_sport; + pfh.icmph.un.echo.sequence = user_icmph.icmp6_sequence; + pfh.iov = msg->msg_iov; + pfh.wcheck = 0; + pfh.family = AF_INET6; + + if (ipv6_addr_is_multicast(&fl6.daddr)) + hlimit = np->mcast_hops; + else + hlimit = np->hop_limit; + if (hlimit < 0) + hlimit = ip6_dst_hoplimit(dst); + + lock_sock(sk); + err = ip6_append_data(sk, ping_getfrag, &pfh, len, + 0, hlimit, + np->tclass, NULL, &fl6, rt, + MSG_DONTWAIT, np->dontfrag); + + if (err) { + ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev, + ICMP6_MIB_OUTERRORS); + ip6_flush_pending_frames(sk); + } else { + err = icmpv6_push_pending_frames(sk, &fl6, + (struct icmp6hdr *) &pfh.icmph, + len); + } + release_sock(sk); + + if (err) + return err; + + return len; +} diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 677d6592978..685553b412b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -984,9 +984,11 @@ static int ieee80211_change_station(struct wiphy *wiphy, return -ENOENT; } - /* in station mode, supported rates are only valid with TDLS */ + /* in station mode, some updates are only valid with TDLS */ if (sdata->vif.type == NL80211_IFTYPE_STATION && - params->supported_rates && + (params->supported_rates || params->ht_capa || params->vht_capa || + params->sta_modify_mask || + (params->sta_flags_mask & BIT(NL80211_STA_FLAG_WME))) && !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { mutex_unlock(&local->sta_mtx); return -EINVAL; diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index db8fae51714..a99a71517c4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -378,6 +378,7 @@ enum ieee80211_sta_flags { IEEE80211_STA_UAPSD_ENABLED = BIT(7), IEEE80211_STA_NULLFUNC_ACKED = BIT(8), IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), + IEEE80211_STA_DISABLE_VHT = BIT(11), }; struct ieee80211_mgd_auth_data { @@ -1475,6 +1476,8 @@ u8 *ieee80211_ie_build_ht_info(u8 *pos, struct ieee80211_channel *channel, enum nl80211_channel_type channel_type); +u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, + u32 cap); /* internal work items */ void ieee80211_work_init(struct ieee80211_local *local); void ieee80211_add_work(struct ieee80211_work *wk); diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 16336480c63..018e3fbc2c2 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c @@ -673,7 +673,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) int result, i; enum ieee80211_band band; int channels, max_bitrates; - bool supp_ht; + bool supp_ht, supp_vht; static const u32 cipher_suites[] = { /* keep WEP first, it may be removed below */ WLAN_CIPHER_SUITE_WEP40, @@ -706,6 +706,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) channels = 0; max_bitrates = 0; supp_ht = false; + supp_vht = false; for (band = 0; band < IEEE80211_NUM_BANDS; band++) { struct ieee80211_supported_band *sband; @@ -723,6 +724,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (max_bitrates < sband->n_bitrates) max_bitrates = sband->n_bitrates; supp_ht = supp_ht || sband->ht_cap.ht_supported; + supp_vht = supp_vht || sband->vht_cap.vht_supported; } local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) + @@ -798,6 +800,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) if (supp_ht) local->scan_ies_len += 2 + sizeof(struct ieee80211_ht_cap); + if (supp_vht) + local->scan_ies_len += + 2 + sizeof(struct ieee80211_vht_cap); + if (!local->ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ local->hw.wiphy->max_scan_ssids = 4; diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 20c680bfc3a..a48a35c7ce6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -383,6 +383,26 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); } +static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb, + struct ieee80211_supported_band *sband) +{ + u8 *pos; + u32 cap; + struct ieee80211_sta_vht_cap vht_cap; + + BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); + + memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); + + /* determine capability flags */ + cap = vht_cap.cap; + + /* reserve and fill IE */ + pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); + ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); +} + static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) { struct ieee80211_local *local = sdata->local; @@ -428,6 +448,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) 4 + /* power capability */ 2 + 2 * sband->n_channels + /* supported channels */ 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ + 2 + sizeof(struct ieee80211_vht_cap) + /* VHT */ assoc_data->ie_len + /* extra IEs */ 9, /* WMM */ GFP_KERNEL); @@ -560,6 +581,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie, sband, local->oper_channel, ifmgd->ap_smps); + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) + ieee80211_add_vht_ie(sdata, skb, sband); + /* if present, add any custom non-vendor IEs that go after HT */ if (assoc_data->ie_len && assoc_data->ie) { noffset = ieee80211_ie_split_vendor(assoc_data->ie, @@ -3289,6 +3313,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; + ifmgd->flags &= ~IEEE80211_STA_DISABLE_VHT; ifmgd->beacon_crc_valid = false; @@ -3299,14 +3324,21 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, * We can set this to true for non-11n hardware, that'll be checked * separately along with the peer capabilities. */ - for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) + for (i = 0; i < req->crypto.n_ciphers_pairwise; i++) { if (req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP40 || req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || - req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) + req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { ifmgd->flags |= IEEE80211_STA_DISABLE_11N; + ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + netdev_info(sdata->dev, + "disabling HT/VHT due to WEP/TKIP use\n"); + } + } - if (req->flags & ASSOC_REQ_DISABLE_HT) + if (req->flags & ASSOC_REQ_DISABLE_HT) { ifmgd->flags |= IEEE80211_STA_DISABLE_11N; + ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + } /* Also disable HT if we don't support it or the AP doesn't use WMM */ sband = local->hw.wiphy->bands[req->bss->channel->band]; @@ -3314,6 +3346,14 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, local->hw.queues < 4 || !bss->wmm_used) ifmgd->flags |= IEEE80211_STA_DISABLE_11N; + /* disable VHT if we don't support it or the AP doesn't use WMM */ + if (!sband->vht_cap.vht_supported || + local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { + ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; + netdev_info(sdata->dev, + "disabling VHT as WMM/QoS is not supported\n"); + } + memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); memcpy(&ifmgd->ht_capa_mask, &req->ht_capa_mask, sizeof(ifmgd->ht_capa_mask)); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 32f7a3b3d43..1faea9dce64 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1031,6 +1031,9 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, pos += noffset - offset; } + if (sband->vht_cap.vht_supported) + pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, + sband->vht_cap.cap); return pos - buffer; } @@ -1611,6 +1614,27 @@ u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, return pos; } +u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, + u32 cap) +{ + __le32 tmp; + + *pos++ = WLAN_EID_VHT_CAPABILITY; + *pos++ = sizeof(struct ieee80211_vht_cap); + memset(pos, 0, sizeof(struct ieee80211_vht_cap)); + + /* capability flags */ + tmp = cpu_to_le32(cap); + memcpy(pos, &tmp, sizeof(u32)); + pos += sizeof(u32); + + /* VHT MCS set */ + memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs)); + pos += sizeof(vht_cap->vht_mcs); + + return pos; +} + u8 *ieee80211_ie_build_ht_info(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, struct ieee80211_channel *channel, diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 452e84de7e7..2bf14b6f3a9 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -1,3 +1,5 @@ +CFLAGS_KERNEL := -fno-unsafe-math-optimizations + netfilter-objs := core.o nf_log.o nf_queue.o nf_sockopt.o nf_conntrack-y := nf_conntrack_core.o nf_conntrack_standalone.o nf_conntrack_expect.o nf_conntrack_helper.o nf_conntrack_proto.o nf_conntrack_l3proto_generic.o nf_conntrack_proto_generic.o nf_conntrack_proto_tcp.o nf_conntrack_proto_udp.o nf_conntrack_extend.o nf_conntrack_acct.o diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 722291f8af7..70512e9a5ed 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c @@ -566,8 +566,8 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, { static MultimediaSystemControlMessage mscm; unsigned char *data = NULL; - int datalen; - int dataoff; + int datalen = 0; + int dataoff = 0; int ret; /* Until there's been traffic both ways, don't look in packets. */ @@ -1118,8 +1118,8 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff, { static Q931 q931; unsigned char *data = NULL; - int datalen; - int dataoff; + int datalen = 0; + int dataoff = 0; int ret; /* Until there's been traffic both ways, don't look in packets. */ diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c index 5bdb42bd28d..aa5f0919a1b 100644 --- a/net/netfilter/xt_qtaguid.c +++ b/net/netfilter/xt_qtaguid.c @@ -1298,6 +1298,38 @@ static void iface_stat_update(struct net_device *net_dev, bool stash_only) spin_unlock_bh(&iface_stat_list_lock); } +/* Guarantied to return a net_device that has a name */ +static void get_dev_and_dir(const struct sk_buff *skb, + struct xt_action_param *par, + enum ifs_tx_rx *direction, + const struct net_device **el_dev) +{ + BUG_ON(!direction || !el_dev); + + if (par->in) { + *el_dev = par->in; + *direction = IFS_RX; + } else if (par->out) { + *el_dev = par->out; + *direction = IFS_TX; + } else { + pr_err("qtaguid[%d]: %s(): no par->in/out?!!\n", + par->hooknum, __func__); + BUG(); + } + if (unlikely(!(*el_dev)->name)) { + pr_err("qtaguid[%d]: %s(): no dev->name?!!\n", + par->hooknum, __func__); + BUG(); + } + if (skb->dev && *el_dev != skb->dev) { + MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs par->%s=%p %s\n", + par->hooknum, skb->dev, skb->dev->name, + *direction == IFS_RX ? "in" : "out", *el_dev, + (*el_dev)->name); + } +} + /* * Update stats for the specified interface from the skb. * Do nothing if the entry @@ -1309,50 +1341,27 @@ static void iface_stat_update_from_skb(const struct sk_buff *skb, { struct iface_stat *entry; const struct net_device *el_dev; - enum ifs_tx_rx direction = par->in ? IFS_RX : IFS_TX; + enum ifs_tx_rx direction; int bytes = skb->len; int proto; - if (!skb->dev) { - MT_DEBUG("qtaguid[%d]: no skb->dev\n", par->hooknum); - el_dev = par->in ? : par->out; - } else { - const struct net_device *other_dev; - el_dev = skb->dev; - other_dev = par->in ? : par->out; - if (el_dev != other_dev) { - MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs " - "par->(in/out)=%p %s\n", - par->hooknum, el_dev, el_dev->name, other_dev, - other_dev->name); - } - } - - if (unlikely(!el_dev)) { - pr_err_ratelimited("qtaguid[%d]: %s(): no par->in/out?!!\n", - par->hooknum, __func__); - BUG(); - } else if (unlikely(!el_dev->name)) { - pr_err_ratelimited("qtaguid[%d]: %s(): no dev->name?!!\n", - par->hooknum, __func__); - BUG(); - } else { - proto = ipx_proto(skb, par); - MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n", - par->hooknum, el_dev->name, el_dev->type, - par->family, proto); - } + get_dev_and_dir(skb, par, &direction, &el_dev); + proto = ipx_proto(skb, par); + MT_DEBUG("qtaguid[%d]: iface_stat: %s(%s): " + "type=%d fam=%d proto=%d dir=%d\n", + par->hooknum, __func__, el_dev->name, el_dev->type, + par->family, proto, direction); spin_lock_bh(&iface_stat_list_lock); entry = get_iface_entry(el_dev->name); if (entry == NULL) { - IF_DEBUG("qtaguid: iface_stat: %s(%s): not tracked\n", - __func__, el_dev->name); + IF_DEBUG("qtaguid[%d]: iface_stat: %s(%s): not tracked\n", + par->hooknum, __func__, el_dev->name); spin_unlock_bh(&iface_stat_list_lock); return; } - IF_DEBUG("qtaguid: %s(%s): entry=%p\n", __func__, + IF_DEBUG("qtaguid[%d]: %s(%s): entry=%p\n", par->hooknum, __func__, el_dev->name, entry); data_counters_update(&entry->totals_via_skb, 0, direction, proto, @@ -1417,13 +1426,13 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, iface_entry = get_iface_entry(ifname); if (!iface_entry) { - pr_err_ratelimited("qtaguid: iface_stat: stat_update() " + pr_err_ratelimited("qtaguid: tag_stat: stat_update() " "%s not found\n", ifname); return; } /* It is ok to process data when an iface_entry is inactive */ - MT_DEBUG("qtaguid: iface_stat: stat_update() dev=%s entry=%p\n", + MT_DEBUG("qtaguid: tag_stat: stat_update() dev=%s entry=%p\n", ifname, iface_entry); /* @@ -1440,7 +1449,7 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, tag = combine_atag_with_uid(acct_tag, uid); uid_tag = make_tag_from_uid(uid); } - MT_DEBUG("qtaguid: iface_stat: stat_update(): " + MT_DEBUG("qtaguid: tag_stat: stat_update(): " " looking for tag=0x%llx (uid=%u) in ife=%p\n", tag, get_uid_from_tag(tag), iface_entry); /* Loop over tag list under this interface for {acct_tag,uid_tag} */ @@ -1468,6 +1477,8 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, * - No {0, uid_tag} stats and no {acc_tag, uid_tag} stats. */ new_tag_stat = create_if_tag_stat(iface_entry, uid_tag); + if (!new_tag_stat) + goto unlock; uid_tag_counters = &new_tag_stat->counters; } else { uid_tag_counters = &tag_stat_entry->counters; @@ -1476,6 +1487,8 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, if (acct_tag) { /* Create the child {acct_tag, uid_tag} and hook up parent. */ new_tag_stat = create_if_tag_stat(iface_entry, tag); + if (!new_tag_stat) + goto unlock; new_tag_stat->parent_counters = uid_tag_counters; } else { /* @@ -1489,6 +1502,7 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, BUG_ON(!new_tag_stat); } tag_stat_update(new_tag_stat, direction, proto, bytes); +unlock: spin_unlock_bh(&iface_entry->tag_stat_list_lock); } @@ -1668,8 +1682,8 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb, struct sock *sk; unsigned int hook_mask = (1 << par->hooknum); - MT_DEBUG("qtaguid: find_sk(skb=%p) hooknum=%d family=%d\n", skb, - par->hooknum, par->family); + MT_DEBUG("qtaguid[%d]: find_sk(skb=%p) family=%d\n", + par->hooknum, skb, par->family); /* * Let's not abuse the the xt_socket_get*_sk(), or else it will @@ -1695,8 +1709,8 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb, * Not fixed in 3.0-r3 :( */ if (sk) { - MT_DEBUG("qtaguid: %p->sk_proto=%u " - "->sk_state=%d\n", sk, sk->sk_protocol, sk->sk_state); + MT_DEBUG("qtaguid[%d]: %p->sk_proto=%u->sk_state=%d\n", + par->hooknum, sk, sk->sk_protocol, sk->sk_state); if (sk->sk_state == TCP_TIME_WAIT) { xt_socket_put_sk(sk); sk = NULL; @@ -1710,37 +1724,19 @@ static void account_for_uid(const struct sk_buff *skb, struct xt_action_param *par) { const struct net_device *el_dev; + enum ifs_tx_rx direction; + int proto; - if (!skb->dev) { - MT_DEBUG("qtaguid[%d]: no skb->dev\n", par->hooknum); - el_dev = par->in ? : par->out; - } else { - const struct net_device *other_dev; - el_dev = skb->dev; - other_dev = par->in ? : par->out; - if (el_dev != other_dev) { - MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs " - "par->(in/out)=%p %s\n", - par->hooknum, el_dev, el_dev->name, other_dev, - other_dev->name); - } - } - - if (unlikely(!el_dev)) { - pr_info("qtaguid[%d]: no par->in/out?!!\n", par->hooknum); - } else if (unlikely(!el_dev->name)) { - pr_info("qtaguid[%d]: no dev->name?!!\n", par->hooknum); - } else { - int proto = ipx_proto(skb, par); - MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n", - par->hooknum, el_dev->name, el_dev->type, - par->family, proto); + get_dev_and_dir(skb, par, &direction, &el_dev); + proto = ipx_proto(skb, par); + MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d dir=%d\n", + par->hooknum, el_dev->name, el_dev->type, + par->family, proto, direction); - if_tag_stat_update(el_dev->name, uid, - skb->sk ? skb->sk : alternate_sk, - par->in ? IFS_RX : IFS_TX, - proto, skb->len); - } + if_tag_stat_update(el_dev->name, uid, + skb->sk ? skb->sk : alternate_sk, + direction, + proto, skb->len); } static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) @@ -1751,6 +1747,11 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) struct sock *sk; uid_t sock_uid; bool res; + /* + * TODO: unhack how to force just accounting. + * For now we only do tag stats when the uid-owner is not requested + */ + bool do_tag_stat = !(info->match & XT_QTAGUID_UID); if (unlikely(module_passive)) return (info->match ^ info->invert) == 0; @@ -1815,12 +1816,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) * couldn't find the owner, so for now we just count them * against the system. */ - /* - * TODO: unhack how to force just accounting. - * For now we only do iface stats when the uid-owner is not - * requested. - */ - if (!(info->match & XT_QTAGUID_UID)) + if (do_tag_stat) account_for_uid(skb, sk, 0, par); MT_DEBUG("qtaguid[%d]: leaving (sk?sk->sk_socket)=%p\n", par->hooknum, @@ -1835,18 +1831,15 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) filp = sk->sk_socket->file; if (filp == NULL) { MT_DEBUG("qtaguid[%d]: leaving filp=NULL\n", par->hooknum); - account_for_uid(skb, sk, 0, par); + if (do_tag_stat) + account_for_uid(skb, sk, 0, par); res = ((info->match ^ info->invert) & (XT_QTAGUID_UID | XT_QTAGUID_GID)) == 0; atomic64_inc(&qtu_events.match_no_sk_file); goto put_sock_ret_res; } sock_uid = filp->f_cred->fsuid; - /* - * TODO: unhack how to force just accounting. - * For now we only do iface stats when the uid-owner is not requested - */ - if (!(info->match & XT_QTAGUID_UID)) + if (do_tag_stat) account_for_uid(skb, sk, sock_uid, par); /* @@ -2596,8 +2589,9 @@ static int pp_stats_line(struct proc_print_info *ppi, int cnt_set) } else { tag_t tag = ppi->ts_entry->tn.tag; uid_t stat_uid = get_uid_from_tag(tag); - - if (!can_read_other_uid_stats(stat_uid)) { + /* Detailed tags are not available to everybody */ + if (get_atag_from_tag(tag) + && !can_read_other_uid_stats(stat_uid)) { CT_DEBUG("qtaguid: stats line: " "%s 0x%llx %u: insufficient priv " "from pid=%u tgid=%u uid=%u stats.gid=%u\n", @@ -2760,7 +2754,7 @@ static int qtudev_open(struct inode *inode, struct file *file) utd_entry = get_uid_data(current_fsuid(), &utd_entry_found); if (IS_ERR_OR_NULL(utd_entry)) { res = PTR_ERR(utd_entry); - goto err; + goto err_unlock; } /* Look for existing PID based proc_data */ @@ -2802,8 +2796,8 @@ static int qtudev_open(struct inode *inode, struct file *file) rb_erase(&utd_entry->node, &uid_tag_data_tree); kfree(utd_entry); } +err_unlock: spin_unlock_bh(&uid_tag_data_tree_lock); -err: return res; } diff --git a/net/socket.c b/net/socket.c index 851edcd6b09..5e6e6218684 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1322,7 +1322,7 @@ EXPORT_SYMBOL(sock_create_kern); SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) { int retval; - struct socket *sock; + struct socket *sock = NULL; int flags; /* Check the SOCK_* constants for consistency. */ @@ -1363,7 +1363,7 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, int __user *, usockvec) { - struct socket *sock1, *sock2; + struct socket *sock1 = NULL, *sock2; int fd1, fd2, err; struct file *newfile1, *newfile2; int flags; diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index 994cfea2bad..0c20629952c 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c @@ -233,7 +233,7 @@ static int rpc_wait_bit_killable(void *word) { if (fatal_signal_pending(current)) return -ERESTARTSYS; - freezable_schedule(); + freezable_schedule_unsafe(); return 0; } diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index b97a3dd9a60..a95081721c2 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c @@ -880,6 +880,8 @@ int read_bytes_from_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, u { struct xdr_buf subbuf; int status; + subbuf.pages = 0; + subbuf.page_base = 0; status = xdr_buf_subsegment(buf, &subbuf, base, len); if (status != 0) @@ -911,6 +913,8 @@ int write_bytes_to_xdr_buf(struct xdr_buf *buf, unsigned int base, void *obj, un { struct xdr_buf subbuf; int status; + subbuf.pages = 0; + subbuf.page_base = 0; status = xdr_buf_subsegment(buf, &subbuf, base, len); if (status != 0) @@ -950,6 +954,8 @@ EXPORT_SYMBOL_GPL(xdr_encode_word); int xdr_buf_read_netobj(struct xdr_buf *buf, struct xdr_netobj *obj, unsigned int offset) { struct xdr_buf subbuf; + subbuf.pages = 0; + subbuf.page_base = 0; if (xdr_decode_word(buf, offset, &obj->len)) return -EFAULT; diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 109e30beaa6..b366cba6ae7 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -114,16 +114,26 @@ #include #include #include +#include -struct hlist_head unix_socket_table[UNIX_HASH_SIZE + 1]; +struct hlist_head unix_socket_table[2 * UNIX_HASH_SIZE]; EXPORT_SYMBOL_GPL(unix_socket_table); DEFINE_SPINLOCK(unix_table_lock); EXPORT_SYMBOL_GPL(unix_table_lock); static atomic_long_t unix_nr_socks; -#define unix_sockets_unbound (&unix_socket_table[UNIX_HASH_SIZE]) -#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash != UNIX_HASH_SIZE) +static struct hlist_head *unix_sockets_unbound(void *addr) +{ + unsigned long hash = (unsigned long)addr; + + hash ^= hash >> 16; + hash ^= hash >> 8; + hash %= UNIX_HASH_SIZE; + return &unix_socket_table[UNIX_HASH_SIZE + hash]; +} + +#define UNIX_ABSTRACT(sk) (unix_sk(sk)->addr->hash < UNIX_HASH_SIZE) #ifdef CONFIG_SECURITY_NETWORK static void unix_get_secdata(struct scm_cookie *scm, struct sk_buff *skb) @@ -644,7 +654,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock) INIT_LIST_HEAD(&u->link); mutex_init(&u->readlock); /* single task reading lock */ init_waitqueue_head(&u->peer_wait); - unix_insert_socket(unix_sockets_unbound, sk); + unix_insert_socket(unix_sockets_unbound(sk), sk); out: if (sk == NULL) atomic_long_dec(&unix_nr_socks); @@ -824,7 +834,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) struct dentry *dentry = NULL; struct path path; int err; - unsigned hash; + unsigned hash = 0; struct unix_address *addr; struct hlist_head *list; @@ -964,7 +974,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr, struct net *net = sock_net(sk); struct sockaddr_un *sunaddr = (struct sockaddr_un *)addr; struct sock *other; - unsigned hash; + unsigned hash = 0; int err; if (addr->sa_family != AF_UNSPEC) { @@ -1062,7 +1072,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr, struct sock *newsk = NULL; struct sock *other = NULL; struct sk_buff *skb = NULL; - unsigned hash; + unsigned hash = 0; int st; int err; long timeo; @@ -1437,7 +1447,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, struct sock *other = NULL; int namelen = 0; /* fake GCC */ int err; - unsigned hash; + unsigned hash = 0; struct sk_buff *skb; long timeo; struct scm_cookie tmp_scm; @@ -1874,7 +1884,7 @@ static long unix_stream_data_wait(struct sock *sk, long timeo) set_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); unix_state_unlock(sk); - timeo = schedule_timeout(timeo); + timeo = freezable_schedule_timeout(timeo); unix_state_lock(sk); clear_bit(SOCK_ASYNC_WAITDATA, &sk->sk_socket->flags); } @@ -2229,47 +2239,58 @@ static unsigned int unix_dgram_poll(struct file *file, struct socket *sock, } #ifdef CONFIG_PROC_FS -static struct sock *first_unix_socket(int *i) -{ - for (*i = 0; *i <= UNIX_HASH_SIZE; (*i)++) { - if (!hlist_empty(&unix_socket_table[*i])) - return __sk_head(&unix_socket_table[*i]); - } - return NULL; -} -static struct sock *next_unix_socket(int *i, struct sock *s) -{ - struct sock *next = sk_next(s); - /* More in this chain? */ - if (next) - return next; - /* Look for next non-empty chain. */ - for ((*i)++; *i <= UNIX_HASH_SIZE; (*i)++) { - if (!hlist_empty(&unix_socket_table[*i])) - return __sk_head(&unix_socket_table[*i]); - } - return NULL; -} +#define BUCKET_SPACE (BITS_PER_LONG - (UNIX_HASH_BITS + 1) - 1) + +#define get_bucket(x) ((x) >> BUCKET_SPACE) +#define get_offset(x) ((x) & ((1L << BUCKET_SPACE) - 1)) +#define set_bucket_offset(b, o) ((b) << BUCKET_SPACE | (o)) struct unix_iter_state { struct seq_net_private p; - int i; }; -static struct sock *unix_seq_idx(struct seq_file *seq, loff_t pos) +static struct sock *unix_from_bucket(struct seq_file *seq, loff_t *pos) { - struct unix_iter_state *iter = seq->private; - loff_t off = 0; - struct sock *s; + unsigned long offset = get_offset(*pos); + unsigned long bucket = get_bucket(*pos); + struct sock *sk; + unsigned long count = 0; - for (s = first_unix_socket(&iter->i); s; s = next_unix_socket(&iter->i, s)) { - if (sock_net(s) != seq_file_net(seq)) + for (sk = sk_head(&unix_socket_table[bucket]); sk; sk = sk_next(sk)) { + if (sock_net(sk) != seq_file_net(seq)) continue; - if (off == pos) - return s; - ++off; + if (++count == offset) + break; + } + + return sk; +} + +static struct sock *unix_next_socket(struct seq_file *seq, + struct sock *sk, + loff_t *pos) +{ + unsigned long bucket; + + while (sk > (struct sock *)SEQ_START_TOKEN) { + sk = sk_next(sk); + if (!sk) + goto next_bucket; + if (sock_net(sk) == seq_file_net(seq)) + return sk; } + + do { + sk = unix_from_bucket(seq, pos); + if (sk) + return sk; + +next_bucket: + bucket = get_bucket(*pos) + 1; + *pos = set_bucket_offset(bucket, 1); + } while (bucket < ARRAY_SIZE(unix_socket_table)); + return NULL; } @@ -2277,22 +2298,20 @@ static void *unix_seq_start(struct seq_file *seq, loff_t *pos) __acquires(unix_table_lock) { spin_lock(&unix_table_lock); - return *pos ? unix_seq_idx(seq, *pos - 1) : SEQ_START_TOKEN; + + if (!*pos) + return SEQ_START_TOKEN; + + if (get_bucket(*pos) >= ARRAY_SIZE(unix_socket_table)) + return NULL; + + return unix_next_socket(seq, NULL, pos); } static void *unix_seq_next(struct seq_file *seq, void *v, loff_t *pos) { - struct unix_iter_state *iter = seq->private; - struct sock *sk = v; ++*pos; - - if (v == SEQ_START_TOKEN) - sk = first_unix_socket(&iter->i); - else - sk = next_unix_socket(&iter->i, sk); - while (sk && (sock_net(sk) != seq_file_net(seq))) - sk = next_unix_socket(&iter->i, sk); - return sk; + return unix_next_socket(seq, v, pos); } static void unix_seq_stop(struct seq_file *seq, void *v) diff --git a/net/unix/diag.c b/net/unix/diag.c index f0486ae9ebe..f13e34ea84e 100644 --- a/net/unix/diag.c +++ b/net/unix/diag.c @@ -195,7 +195,9 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) num = s_num = cb->args[1]; spin_lock(&unix_table_lock); - for (slot = s_slot; slot <= UNIX_HASH_SIZE; s_num = 0, slot++) { + for (slot = s_slot; + slot < ARRAY_SIZE(unix_socket_table); + s_num = 0, slot++) { struct sock *sk; struct hlist_node *node; @@ -228,7 +230,7 @@ static struct sock *unix_lookup_by_ino(int ino) struct sock *sk; spin_lock(&unix_table_lock); - for (i = 0; i <= UNIX_HASH_SIZE; i++) { + for (i = 0; i < ARRAY_SIZE(unix_socket_table); i++) { struct hlist_node *node; sk_for_each(sk, node, &unix_socket_table[i]) diff --git a/net/wireless/core.c b/net/wireless/core.c index ccdfed89765..674c1fa2bd6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -505,6 +505,11 @@ int wiphy_register(struct wiphy *wiphy) ETH_ALEN))) return -EINVAL; + if (WARN_ON(wiphy->max_acl_mac_addrs && + (!(wiphy->flags & WIPHY_FLAG_HAVE_AP_SME) || + !rdev->ops->set_mac_acl))) + return -EINVAL; + if (wiphy->addresses) memcpy(wiphy->perm_addr, wiphy->addresses[0].addr, ETH_ALEN); diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4df009cd5ff..13fcc641e13 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -206,6 +206,26 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { [NL80211_ATTR_NOACK_MAP] = { .type = NLA_U16 }, [NL80211_ATTR_INACTIVITY_TIMEOUT] = { .type = NLA_U16 }, [NL80211_ATTR_BG_SCAN_PERIOD] = { .type = NLA_U16 }, + [NL80211_ATTR_WDEV] = { .type = NLA_U64 }, + [NL80211_ATTR_USER_REG_HINT_TYPE] = { .type = NLA_U32 }, + [NL80211_ATTR_SAE_DATA] = { .type = NLA_BINARY, }, + [NL80211_ATTR_VHT_CAPABILITY] = { .len = NL80211_VHT_CAPABILITY_LEN }, + [NL80211_ATTR_SCAN_FLAGS] = { .type = NLA_U32 }, + [NL80211_ATTR_P2P_CTWINDOW] = { .type = NLA_U8 }, + [NL80211_ATTR_P2P_OPPPS] = { .type = NLA_U8 }, + [NL80211_ATTR_ACL_POLICY] = {. type = NLA_U32 }, + [NL80211_ATTR_MAC_ADDRS] = { .type = NLA_NESTED }, + [NL80211_ATTR_STA_CAPABILITY] = { .type = NLA_U16 }, + [NL80211_ATTR_STA_EXT_CAPABILITY] = { .type = NLA_BINARY, }, + [NL80211_ATTR_SPLIT_WIPHY_DUMP] = { .type = NLA_FLAG, }, + [NL80211_ATTR_DISABLE_VHT] = { .type = NLA_FLAG }, + [NL80211_ATTR_VHT_CAPABILITY_MASK] = { + .len = NL80211_VHT_CAPABILITY_LEN, + }, + [NL80211_ATTR_MDID] = { .type = NLA_U16 }, + [NL80211_ATTR_IE_RIC] = { .type = NLA_BINARY, + .len = IEEE80211_MAX_DATA_LEN }, + [NL80211_ATTR_PEER_AID] = { .type = NLA_U16 }, }; /* policy for the key attributes */ @@ -811,6 +831,15 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, dev->wiphy.bands[band]->ht_cap.ampdu_density); } + /* add VHT info */ + if (dev->wiphy.bands[band]->vht_cap.vht_supported && + (nla_put(msg, NL80211_BAND_ATTR_VHT_MCS_SET, + sizeof(dev->wiphy.bands[band]->vht_cap.vht_mcs), + &dev->wiphy.bands[band]->vht_cap.vht_mcs) || + nla_put_u32(msg, NL80211_BAND_ATTR_VHT_CAPA, + dev->wiphy.bands[band]->vht_cap.cap))) + goto nla_put_failure; + /* add frequencies */ nl_freqs = nla_nest_start(msg, NL80211_BAND_ATTR_FREQS); if (!nl_freqs) @@ -1043,6 +1072,11 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, sizeof(*dev->wiphy.ht_capa_mod_mask), dev->wiphy.ht_capa_mod_mask); + if (dev->wiphy.flags & WIPHY_FLAG_HAVE_AP_SME && + dev->wiphy.max_acl_mac_addrs) + NLA_PUT_U32(msg, NL80211_ATTR_MAC_ACL_MAX, + dev->wiphy.max_acl_mac_addrs); + return genlmsg_end(msg, hdr); nla_put_failure: @@ -2082,6 +2116,97 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) return err; } +/* This function returns an error or the number of nested attributes */ +static int validate_acl_mac_addrs(struct nlattr *nl_attr) +{ + struct nlattr *attr; + int n_entries = 0, tmp; + + nla_for_each_nested(attr, nl_attr, tmp) { + if (nla_len(attr) != ETH_ALEN) + return -EINVAL; + + n_entries++; + } + + return n_entries; +} + +/* + * This function parses ACL information and allocates memory for ACL data. + * On successful return, the calling function is responsible to free the + * ACL buffer returned by this function. + */ +static struct cfg80211_acl_data *parse_acl_data(struct wiphy *wiphy, + struct genl_info *info) +{ + enum nl80211_acl_policy acl_policy; + struct nlattr *attr; + struct cfg80211_acl_data *acl; + int i = 0, n_entries, tmp; + + if (!wiphy->max_acl_mac_addrs) + return ERR_PTR(-EOPNOTSUPP); + + if (!info->attrs[NL80211_ATTR_ACL_POLICY]) + return ERR_PTR(-EINVAL); + + acl_policy = nla_get_u32(info->attrs[NL80211_ATTR_ACL_POLICY]); + if (acl_policy != NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED && + acl_policy != NL80211_ACL_POLICY_DENY_UNLESS_LISTED) + return ERR_PTR(-EINVAL); + + if (!info->attrs[NL80211_ATTR_MAC_ADDRS]) + return ERR_PTR(-EINVAL); + + n_entries = validate_acl_mac_addrs(info->attrs[NL80211_ATTR_MAC_ADDRS]); + if (n_entries < 0) + return ERR_PTR(n_entries); + + if (n_entries > wiphy->max_acl_mac_addrs) + return ERR_PTR(-ENOTSUPP); + + acl = kzalloc(sizeof(*acl) + (sizeof(struct mac_address) * n_entries), + GFP_KERNEL); + if (!acl) + return ERR_PTR(-ENOMEM); + + nla_for_each_nested(attr, info->attrs[NL80211_ATTR_MAC_ADDRS], tmp) { + memcpy(acl->mac_addrs[i].addr, nla_data(attr), ETH_ALEN); + i++; + } + + acl->n_acl_entries = n_entries; + acl->acl_policy = acl_policy; + + return acl; +} + +static int nl80211_set_mac_acl(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct net_device *dev = info->user_ptr[1]; + struct cfg80211_acl_data *acl; + int err; + + if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && + dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) + return -EOPNOTSUPP; + + if (!dev->ieee80211_ptr->beacon_interval) + return -EINVAL; + + acl = parse_acl_data(&rdev->wiphy, info); + if (IS_ERR(acl)) + return PTR_ERR(acl); + + err = rdev->ops->set_mac_acl(&rdev->wiphy, dev, acl); + + kfree(acl); + + return err; +} + static int nl80211_parse_beacon(struct genl_info *info, struct cfg80211_beacon_data *bcn) { @@ -2228,9 +2353,18 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) info->attrs[NL80211_ATTR_INACTIVITY_TIMEOUT]); } + if (info->attrs[NL80211_ATTR_ACL_POLICY]) { + params.acl = parse_acl_data(&rdev->wiphy, info); + if (IS_ERR(params.acl)) + return PTR_ERR(params.acl); + } + err = rdev->ops->start_ap(&rdev->wiphy, dev, ¶ms); if (!err) wdev->beacon_interval = params.beacon_interval; + + kfree(params.acl); + return err; } @@ -2643,6 +2777,56 @@ static struct net_device *get_vlan(struct genl_info *info, return ERR_PTR(ret); } +static struct nla_policy +nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { + [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, + [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, +}; + +static int nl80211_set_station_tdls(struct genl_info *info, + struct station_parameters *params) +{ + struct nlattr *tb[NL80211_STA_WME_MAX + 1]; + struct nlattr *nla; + int err; + + /* Dummy STA entry gets updated once the peer capabilities are known */ + if (info->attrs[NL80211_ATTR_PEER_AID]) + params->aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); + if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) + params->ht_capa = + nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); + if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + params->vht_capa = + nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); + + /* parse WME attributes if present */ + if (!info->attrs[NL80211_ATTR_STA_WME]) + return 0; + + nla = info->attrs[NL80211_ATTR_STA_WME]; + err = nla_parse_nested(tb, NL80211_STA_WME_MAX, nla, + nl80211_sta_wme_policy); + if (err) + return err; + + if (tb[NL80211_STA_WME_UAPSD_QUEUES]) + params->uapsd_queues = nla_get_u8( + tb[NL80211_STA_WME_UAPSD_QUEUES]); + if (params->uapsd_queues & ~IEEE80211_WMM_IE_STA_QOSINFO_AC_MASK) + return -EINVAL; + + if (tb[NL80211_STA_WME_MAX_SP]) + params->max_sp = nla_get_u8(tb[NL80211_STA_WME_MAX_SP]); + + if (params->max_sp & ~IEEE80211_WMM_IE_STA_QOSINFO_SP_MASK) + return -EINVAL; + + params->sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; + + return 0; +} + static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -2671,6 +2855,19 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) nla_len(info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]); } + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) { + params.capability = + nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]); + params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY; + } + + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) { + params.ext_capab = + nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); + params.ext_capab_len = + nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); + } + if (info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); @@ -2719,6 +2916,14 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) BIT(NL80211_STA_FLAG_MFP))) return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; + /* must be last in here for error handling */ params.vlan = get_vlan(info, rdev); if (IS_ERR(params.vlan)) @@ -2733,7 +2938,17 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) * to change the flag. */ params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); - /* fall through */ + /* Include parameters for TDLS peer (driver will check) */ + err = nl80211_set_station_tdls(info, ¶ms); + if (err) + return err; + /* disallow things sta doesn't support */ + if (params.plink_action) + return -EINVAL; + if (params.sta_flags_mask & ~(BIT(NL80211_STA_FLAG_AUTHORIZED) | + BIT(NL80211_STA_FLAG_WME))) + return -EINVAL; + break; case NL80211_IFTYPE_ADHOC: /* disallow things sta doesn't support */ if (params.plink_action) @@ -2742,6 +2957,9 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) return -EINVAL; if (params.listen_interval >= 0) return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; /* reject any changes other than AUTHORIZED */ if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED)) return -EINVAL; @@ -2754,6 +2972,13 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) return -EINVAL; if (params.listen_interval >= 0) return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) + return -EINVAL; + if (info->attrs[NL80211_ATTR_HT_CAPABILITY] || + info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + return -EINVAL; /* * No special handling for TDLS here -- the userspace * mesh code doesn't have this bug. @@ -2778,12 +3003,6 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) return err; } -static struct nla_policy -nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { - [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, - [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, -}; - static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) { struct cfg80211_registered_device *rdev = info->user_ptr[0]; @@ -2803,7 +3022,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) if (!info->attrs[NL80211_ATTR_STA_SUPPORTED_RATES]) return -EINVAL; - if (!info->attrs[NL80211_ATTR_STA_AID]) + if (!info->attrs[NL80211_ATTR_STA_AID] && + !info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); @@ -2814,14 +3034,34 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.listen_interval = nla_get_u16(info->attrs[NL80211_ATTR_STA_LISTEN_INTERVAL]); - params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); + if (info->attrs[NL80211_ATTR_PEER_AID]) + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_PEER_AID]); + else + params.aid = nla_get_u16(info->attrs[NL80211_ATTR_STA_AID]); if (!params.aid || params.aid > IEEE80211_MAX_AID) return -EINVAL; + if (info->attrs[NL80211_ATTR_STA_CAPABILITY]) { + params.capability = + nla_get_u16(info->attrs[NL80211_ATTR_STA_CAPABILITY]); + params.sta_modify_mask |= STATION_PARAM_APPLY_CAPABILITY; + } + + if (info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]) { + params.ext_capab = + nla_data(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); + params.ext_capab_len = + nla_len(info->attrs[NL80211_ATTR_STA_EXT_CAPABILITY]); + } + if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) params.ht_capa = nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]); + if (info->attrs[NL80211_ATTR_VHT_CAPABILITY]) + params.vht_capa = + nla_data(info->attrs[NL80211_ATTR_VHT_CAPABILITY]); + if (info->attrs[NL80211_ATTR_STA_PLINK_ACTION]) params.plink_action = nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); @@ -2867,7 +3107,8 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) params.sta_modify_mask |= STATION_PARAM_APPLY_UAPSD; } /* TDLS peers cannot be added */ - if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) + if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) || + info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; /* but don't bother the driver with it */ params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER); @@ -2879,10 +3120,12 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) break; case NL80211_IFTYPE_MESH_POINT: /* TDLS peers cannot be added */ - if (params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) + if ((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) || + info->attrs[NL80211_ATTR_PEER_AID]) return -EINVAL; break; case NL80211_IFTYPE_STATION: + case NL80211_IFTYPE_P2P_CLIENT: /* Only TDLS peers can be added */ if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) return -EINVAL; @@ -6320,6 +6563,27 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) return 0; } +static int nl80211_update_ft_ies(struct sk_buff *skb, struct genl_info *info) +{ + struct cfg80211_registered_device *rdev = info->user_ptr[0]; + struct cfg80211_update_ft_ies_params ft_params; + struct net_device *dev = info->user_ptr[1]; + + if (!rdev->ops->update_ft_ies) + return -EOPNOTSUPP; + + if (!info->attrs[NL80211_ATTR_MDID] || + !is_valid_ie_attr(info->attrs[NL80211_ATTR_IE])) + return -EINVAL; + + memset(&ft_params, 0, sizeof(ft_params)); + ft_params.md = nla_get_u16(info->attrs[NL80211_ATTR_MDID]); + ft_params.ie = nla_data(info->attrs[NL80211_ATTR_IE]); + ft_params.ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); + + return rdev->ops->update_ft_ies(&rdev->wiphy, dev, &ft_params); +} + #define NL80211_FLAG_NEED_WIPHY 0x01 #define NL80211_FLAG_NEED_NETDEV 0x02 #define NL80211_FLAG_NEED_RTNL 0x04 @@ -6908,6 +7172,22 @@ static struct genl_ops nl80211_ops[] = { .internal_flags = NL80211_FLAG_NEED_NETDEV | NL80211_FLAG_NEED_RTNL, }, + { + .cmd = NL80211_CMD_SET_MAC_ACL, + .doit = nl80211_set_mac_acl, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV | + NL80211_FLAG_NEED_RTNL, + }, + { + .cmd = NL80211_CMD_UPDATE_FT_IES, + .doit = nl80211_update_ft_ies, + .policy = nl80211_policy, + .flags = GENL_ADMIN_PERM, + .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | + NL80211_FLAG_NEED_RTNL, + }, }; @@ -8145,6 +8425,48 @@ static struct notifier_block nl80211_netlink_notifier = { .notifier_call = nl80211_netlink_notify, }; +void cfg80211_ft_event(struct net_device *netdev, + struct cfg80211_ft_event_params *ft_event) +{ + struct wiphy *wiphy = netdev->ieee80211_ptr->wiphy; + struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); + struct sk_buff *msg; + void *hdr; + int err; + + if (!ft_event->target_ap) + return; + + msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); + if (!msg) + return; + + hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_FT_EVENT); + if (!hdr) { + nlmsg_free(msg); + return; + } + + nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx); + nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex); + nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, ft_event->target_ap); + if (ft_event->ies) + nla_put(msg, NL80211_ATTR_IE, ft_event->ies_len, ft_event->ies); + if (ft_event->ric_ies) + nla_put(msg, NL80211_ATTR_IE_RIC, ft_event->ric_ies_len, + ft_event->ric_ies); + + err = genlmsg_end(msg, hdr); + if (err < 0) { + nlmsg_free(msg); + return; + } + + genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0, + nl80211_mlme_mcgrp.id, GFP_KERNEL); +} +EXPORT_SYMBOL(cfg80211_ft_event); + /* initialisation/exit functions */ int nl80211_init(void) diff --git a/net/wireless/reg.c b/net/wireless/reg.c index e9a0ac83b84..30eca9d9290 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c @@ -883,7 +883,19 @@ static void handle_channel(struct wiphy *wiphy, chan->max_antenna_gain = min(chan->orig_mag, (int) MBI_TO_DBI(power_rule->max_antenna_gain)); chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); - chan->max_power = min(chan->max_power, chan->max_reg_power); + if (chan->orig_mpwr) { + /* + * Devices that use NL80211_COUNTRY_IE_FOLLOW_POWER will always + * follow the passed country IE power settings. + */ + if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && + wiphy->country_ie_pref & NL80211_COUNTRY_IE_FOLLOW_POWER) + chan->max_power = chan->max_reg_power; + else + chan->max_power = min(chan->orig_mpwr, + chan->max_reg_power); + } else + chan->max_power = chan->max_reg_power; } static void handle_band(struct wiphy *wiphy, @@ -1295,6 +1307,8 @@ static int ignore_request(struct wiphy *wiphy, case NL80211_REGDOM_SET_BY_CORE: return 0; case NL80211_REGDOM_SET_BY_COUNTRY_IE: + if (wiphy->country_ie_pref & NL80211_COUNTRY_IE_IGNORE_CORE) + return -EALREADY; last_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); diff --git a/release/N7-2013/.gitignore b/release/N7-2013/.gitignore new file mode 100644 index 00000000000..c4c4ffc6aa4 --- /dev/null +++ b/release/N7-2013/.gitignore @@ -0,0 +1 @@ +*.zip diff --git a/release/aroma/META-INF/CERT.RSA b/release/aroma/META-INF/CERT.RSA new file mode 100755 index 00000000000..708be758cb8 Binary files /dev/null and b/release/aroma/META-INF/CERT.RSA differ diff --git a/release/aroma/META-INF/CERT.SF b/release/aroma/META-INF/CERT.SF new file mode 100755 index 00000000000..7830ffd8ac5 --- /dev/null +++ b/release/aroma/META-INF/CERT.SF @@ -0,0 +1,6232 @@ +Signature-Version: 1.0 +Created-By: 1.0 (Android SignApk) +SHA1-Digest-Manifest: DKlveLyFsaaoOXUXJIUlwTU/kjA= + +Name: system/etc/security/cacerts/87d3cf09.0 +SHA1-Digest: 8ZCcYu2OkYcLpII3VSP6d36ZQno= + +Name: system/bin/udhcpd +SHA1-Digest: krEiLY/k9Jr/+9pqA28fvsw5sSg= + +Name: system/lib/libpowermanager.so +SHA1-Digest: cil4ma+WH5c6KM7V0tQrlio2VX0= + +Name: system/lib/libchromatix_vd6869_hfr.so +SHA1-Digest: 4ucunef7qQe9Cjk/ZcBMUFfBo/s= + +Name: system/lib/libstagefright_soft_aacdec.so +SHA1-Digest: RvBjqoJ/Z9sA8Y6piUXpFR006Vk= + +Name: system/etc/permissions/android.hardware.sensor.accelerometer.xml +SHA1-Digest: 2wEa/9FPcNbDmbsyKNJp5TwVgOE= + +Name: system/customize/resource/wallpapers_b_02.jpg +SHA1-Digest: N11M//8KXkFbKny21s2y+ODgaSs= + +Name: system/fonts/DFHEIA7A.ttf +SHA1-Digest: A2mXBjXzAO7W9WVPBY6zDoYwHD4= + +Name: system/etc/dhcpcd/dhcpcd-hooks/20-dns.conf +SHA1-Digest: VPIIUnYFs4j9yMZ+a+S12pnlS/0= + +Name: system/media/audio/ringtones/Crimson.mp3 +SHA1-Digest: qiDQ7fQfCnCZkjtvySj6TcWxu/w= + +Name: system/lib/libchromatix_vd6869_hfr_60fps.so +SHA1-Digest: GETh7rYzzYF92Mnr+m6jiYbugGA= + +Name: system/lib/libaudioeffect_jni.so +SHA1-Digest: fKY0xfiGQYmEQ+MlRzuFhVPmypw= + +Name: system/app/Browser.apk +SHA1-Digest: l1I690bEkOQdaa58lG9F7cOMhaY= + +Name: system/lib/libexiv2.so +SHA1-Digest: aYxWpbqCzuI0xnnIZVXcYoNurTM= + +Name: system/lib/libdrm1_jni.so +SHA1-Digest: cjZ+o8fwIIyy+Sgi9X7EDOto3xM= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/nose_base-y0-yi45-p0-pi45-r0-ri20.lg_32/full_model.bin +SHA1-Digest: QWTMOw4GkuzG+r1zay8B6MxuB8M= + +Name: system/media/weather/weather_partly_sunny.mp4 +SHA1-Digest: c0RXFTbPdpGlQ+jNPrU7ft7V2SM= + +Name: additions/fonts/klavika/Roboto-Bold.ttf +SHA1-Digest: rxZ0Qf4S8Dabz/pZ3ofElciDAYs= + +Name: system/lib/libwfduibcinterface.so +SHA1-Digest: uXlwjZpXG9pP2moRMs+foxqJf/U= + +Name: system/etc/image_htc_earbud_2vol.bin +SHA1-Digest: H9PA04mtTHBqQmZJpDNrHC+Dl+s= + +Name: system/lib/libusbhost.so +SHA1-Digest: 6Kw1ZfWhfaW3IiZOMakfe/0TvHc= + +Name: system/fonts/AndroidClock_Solid.ttf +SHA1-Digest: PKbiQAyAy5xWcCKKDeM6mpdw3B8= + +Name: system/usr/srec/en-US/embed_phone_nn_model +SHA1-Digest: OvLDxuz3u6qqRppHXnxe+P+HgZw= + +Name: system/etc/security/cacerts/81b9768f.0 +SHA1-Digest: Abtfwk1XW6grFct1OuViAxz88dE= + +Name: system/lib/libDxDtcpClient.so +SHA1-Digest: 8I0pZM0gpJbXLMQpCuXqzWj3IeU= + +Name: system/framework/com.htc.weather.res.apk +SHA1-Digest: rk8l04TKto0PORWzPVAgFXGAyuE= + +Name: system/fonts/gcsh00d-hkscs.ttf +SHA1-Digest: 8xR0dAeqgHxrdUOV7+cDT4aW9bI= + +Name: system/lib/libyuvimage.so +SHA1-Digest: 1UKviuNJ8bBtKj/r2KisBFuinTk= + +Name: system/app/HtcScreenTimeoutWidget.apk +SHA1-Digest: KTjTiEKrFKIGo6XCliMfw9dbrZk= + +Name: system/lib/libAnalyst.so +SHA1-Digest: 4CYkNEZlL0vYcilzNAQ/DIselL8= + +Name: system/bin/sdcard +SHA1-Digest: MfwQRXNtr5/dj8X8a+ruSMG+UEI= + +Name: system/framework/ext.jar +SHA1-Digest: 9N0eqDvbEz60S83dFhgLQS01X9M= + +Name: system/media/audio/ringtones/Lavender.mp3 +SHA1-Digest: nnCdW1npkBGp80bKQTUuPUEqgcc= + +Name: system/app/MySketcher.apk +SHA1-Digest: aAu62FxQOJIdjNRE2OlCsKMMTz8= + +Name: system/etc/image_ibeats_solo.bin +SHA1-Digest: 9ZRrh74237S4JzQ0CAcwA0QNSr8= + +Name: system/media/weather/weather_l_partly_cloud_day.mp4 +SHA1-Digest: hRUsy8QabfX+kwP1ycP0D2aUEl4= + +Name: system/bin/smd +SHA1-Digest: oIwazVmMpddeThsXDlD2ZYeR6k8= + +Name: system/etc/security/cacerts/ed049835.0 +SHA1-Digest: DvbVqcuD1h/TVMgfyfSYy3n1G0Y= + +Name: data/app/com.facebook.katana-1.apk +SHA1-Digest: e2HpWUog/7ZbJvtE7L5ERy1Ut6U= + +Name: system/lib/libgnmc_id3tag.2.5.9.4.so +SHA1-Digest: XwkOVmhb07RK6Cngr7J5Qzr/7fo= + +Name: system/app/Phonesky.apk +SHA1-Digest: naHy576C4/EeBx95LOjmng71rvc= + +Name: system/media/audio/ui/Volume-6.flac +SHA1-Digest: xP8/3OLNtl9qfrTH0Cd/imGsSU8= + +Name: system/etc/security/cacerts/a3896b44.0 +SHA1-Digest: Lt7IRY6srSXDk8xe/2MpiiNof+U= + +Name: system/etc/security/cacerts/9f533518.0 +SHA1-Digest: 2P7X1cWxI3NzjMsygIUOy6dxMCw= + +Name: system/customize/CID/default.xml +SHA1-Digest: 4j+3ZIDvTmXtxbn8MI2ypW++k1Q= + +Name: META-INF/com/google/android/aroma/icons/alert.png +SHA1-Digest: vg/4Y3GcDsD3gIqqDjClKzufnak= + +Name: system/framework/com.broadcom.bt.le.jar +SHA1-Digest: QepLQ46oru48FZf7jbWyp2gKk6k= + +Name: system/lib/libstagefright_soft_mpeg4enc.so +SHA1-Digest: zzp04at2GnecxAgGdWAw1fqKN08= + +Name: system/media/audio/notifications/Claret.mp3 +SHA1-Digest: +WCc2yiPvSfrLhcnM25f6/vCkxo= + +Name: system/lib/libwpa_client.so +SHA1-Digest: U8wj3Rv6w+YiEuXztwbfEruQ1eo= + +Name: system/media/audio/ui/LowBattery.ogg +SHA1-Digest: 1UaA9zNnhg53IXetB/ze0AVzvFw= + +Name: system/bin/linker +SHA1-Digest: HGmDRNqa4RbY+7jVoBGlhRX9GgE= + +Name: system/lib/libhtcsunny2engine.so +SHA1-Digest: cTLGOMGPLC8xBWCz2Q2pLVjm1eQ= + +Name: system/lib/libmllite.so +SHA1-Digest: IwFTWaFpZvdJn/Y68y2gL1fU7ag= + +Name: system/media/weather/weather_partly_cloud_day.mp4 +SHA1-Digest: sfBGdPbvyL2kPgB7HwHo+bqz/ws= + +Name: additions/fonts/veggieburger/Roboto-Bold.ttf +SHA1-Digest: mr6dx7dKeVVF5Fjsak84Q8KbjmQ= + +Name: META-INF/com/google/android/aroma/trickdroid.png +SHA1-Digest: gwxCzpCfLKXkQ2t0oiM6wpCFn8I= + +Name: system/media/audio/ui/media_volume.ogg +SHA1-Digest: dZq6eHLUwc3Gx5LytSNtNG9f7uM= + +Name: system/app/IMEXT9Bulgaria.apk +SHA1-Digest: DcZPVHv7of2GPcVKTK+IYq09ACc= + +Name: system/media/GPU/dot_mask_3.bmp +SHA1-Digest: OCtDmOfCOhrRsMF0/Gx0FNRa6cs= + +Name: system/etc/secureproperty.xml +SHA1-Digest: rDlp8Jj01UJHiC1X2WaHTxo+AaQ= + +Name: additions/fonts/asap/Roboto-BoldItalic.ttf +SHA1-Digest: xYOqmv3m9vD4lUMuZW1neFHmvxg= + +Name: system/app/IMEXT9Russian.apk +SHA1-Digest: z6l3FVALvvya6JvpahA3UBo670s= + +Name: system/etc/permissions/android.hardware.usb.accessory.xml +SHA1-Digest: lKVhbliD+5NmYq61xsHEVEZTfsE= + +Name: system/media/zchgd/batt_40.rle +SHA1-Digest: hwcERp4tgnvb54nlWGld9plxM3c= + +Name: system/media/audio/ringtones/Persimmon.mp3 +SHA1-Digest: q4b/q7+GEUrh3UrYCtOAqZgOZKw= + +Name: system/fonts/Roboto-Regular.ttf +SHA1-Digest: jlT03ygs6K+WSYdmRK9fhzTkT+Y= + +Name: system/lib/libDivxDrm.so +SHA1-Digest: BlkVOddGp2vjZfQ8CvuZ9YI6B0o= + +Name: system/bin/mtpd +SHA1-Digest: dAQpfdMibqIXMW16f1A+uoDZfPk= + +Name: system/customize/resource/quicklaunch_21408.xml +SHA1-Digest: X+BqKjv78FVdAIZE9qezJz0k4I4= + +Name: system/customize/resource/allapplication_22288.xml +SHA1-Digest: 1+tqbej0Al5pUF3GpojUI0LjjtQ= + +Name: system/app/Nfc.apk +SHA1-Digest: R8ooyfgKex3fubW8hZCONqFuW9I= + +Name: system/usr/share/bmd/RFFspeed_501.bmd +SHA1-Digest: O4W+YPqIxPg5c57Ny/tsqS1RV8M= + +Name: system/etc/security/cacerts/635ccfd5.0 +SHA1-Digest: iOfrRlIkQ9CJR88NZ3FS2RQ+icw= + +Name: system/etc/security/cacerts/2e8714cb.0 +SHA1-Digest: pN27bgE5+KCmhIkYxNaJ83eT1rI= + +Name: system/media/GPU/CurveWarm.bmp +SHA1-Digest: bVHEn9I0GYNPacm8/kFUrIRudkA= + +Name: system/app/JETCET_PRINT_Resources.apk +SHA1-Digest: NkNfBLPE2u5RLifmCdvpbi5q8sw= + +Name: system/app/VoiceDictation.apk +SHA1-Digest: vO5zkTWMClF1/mD5UYuUR9sflNs= + +Name: META-INF/com/google/android/aroma/icons/gps.png +SHA1-Digest: IAf4Aztre45kqdZmske0USwCyzo= + +Name: system/xbin/nc +SHA1-Digest: TXl3E00ZXXlmbHJ4vcK9fNTZLgc= + +Name: data/app/com.google.android.marvin.talkback-1.apk +SHA1-Digest: KMuwXLtXQAft8LEh0rkdTzKaeR0= + +Name: system/etc/permissions/android.hardware.location.gps.xml +SHA1-Digest: 5BoPvzraABvx8iNcW0s9BCY42l4= + +Name: system/fonts/Roboto-Bold.ttf +SHA1-Digest: tohglY0iiJgDoncAZyqqWqBz6XM= + +Name: system/lib/libGLES_direct.so +SHA1-Digest: TFIx6Eoa4l9TcjXz93nyYDTqsAE= + +Name: system/app/CustomizationSetup.apk +SHA1-Digest: PWCVLOOx/9F3852eIltrcT0WhzY= + +Name: system/app/MusicChannel.apk +SHA1-Digest: wABMNHTB4Jty1b1tt+cSgrk5rxo= + +Name: system/etc/image_ibeats.bin +SHA1-Digest: 6FYxVxkES3iWcUdzMFp49xutx7k= + +Name: system/etc/image_gec_bt.bin +SHA1-Digest: IM5sFxGB3+amjCXJzJfifoE0fws= + +Name: system/lib/libcsd-client.so +SHA1-Digest: 88MoVy4odlMowHp1ESD8avNVtnk= + +Name: system/bin/RescueServer +SHA1-Digest: ze8q9UF5ZyYTjgEL9al67joHC3M= + +Name: additions/fonts/comicsans/Roboto-Italic.ttf +SHA1-Digest: xn52EsNMWUZnhTwV4ECKNWe6F/M= + +Name: system/etc/security/cacerts/5f16ce45.0 +SHA1-Digest: nRjUndhZNOejX3w/Yr7ol30Xc/I= + +Name: system/etc/security/otacerts.zip +SHA1-Digest: fWXPx5r3NdvulGzMrMs0mh9OeR8= + +Name: system/bin/stop +SHA1-Digest: Fv6hdRIUitCwfI8lPijekF1nLxA= + +Name: system/bin/htc_ebdlogd +SHA1-Digest: oqJWtA5oyYRNyEIBMQ3SN6kzwac= + +Name: system/lib/libpatts_engine_jni_api.so +SHA1-Digest: +rzAJro6Sh+VO647jFXieIgGJps= + +Name: system/lib/libglcv.so +SHA1-Digest: 5Jmozenu7ZOBTgpl9Hb7mO19xUA= + +Name: system/etc/security/cacerts/0c364b2d.0 +SHA1-Digest: m6475NwJ+vZiyjNpJVOX38j1uy4= + +Name: system/etc/firmware/fw_bcm4335_apsta_b0.bin +SHA1-Digest: y6rnSBDUHKtovU48tCk/B9Qp5C4= + +Name: system/lib/bluez-plugin/audio.so +SHA1-Digest: 6/3ijWBPxDrYLDK1CredLld6kM4= + +Name: system/lib/libsrsprocessing.so +SHA1-Digest: 4m6CftbwvbCUshSpd6BVbt7d+Ok= + +Name: system/lib/hw/audio_policy.default.so +SHA1-Digest: IDQfcMpsJa93jE8tiUfRexxvy30= + +Name: system/lib/libchromatix_ov8838_hfr.so +SHA1-Digest: CjtF8Iu6m9GetsLBU4vQRoGi9q0= + +Name: system/etc/soundimage/srs_global.cfg +SHA1-Digest: IOJLmVKbRbNn97QDBgVjMco4c1A= + +Name: system/lib/libicuuc.so +SHA1-Digest: UZlm4RhT981gfhxnzwP1fMSd3K4= + +Name: system/app/HtcMusicWidget.apk +SHA1-Digest: UY3XwZ6O3XGuCIZOzQA5inNWKvs= + +Name: system/lib/libnetsharing.so +SHA1-Digest: 4mAlZR6YGFikmR8sjGp55DFAPCc= + +Name: system/usr/keylayout/qwerty.kl +SHA1-Digest: AvLds66wuKFqzBu7lpUMr/ZIL+I= + +Name: system/etc/soundimage/srs_geq10.cfg +SHA1-Digest: WGRKxJYg1j5adpGI86zvLx3fwyY= + +Name: system/etc/security/cacerts/b5f329fa.0 +SHA1-Digest: EtCEMsveXUzOZEYvLIqXHFA+jXU= + +Name: system/bin/schedtop +SHA1-Digest: jyhC2bIsGjWN6DlyJDpiYWyoNc4= + +Name: system/lib/libstagefrighthw.so +SHA1-Digest: FLaB5R1NpT1McXHGJ8c4ssQthzc= + +Name: system/bin/chmod +SHA1-Digest: 0MqurJjzSmSy8JAeep8n0n4zrUs= + +Name: system/app/HtcMessageProvider.apk +SHA1-Digest: hF4IwimpGZWW4Nx6lXMWVwc1DZc= + +Name: additions/wipe/wipe.sh +SHA1-Digest: v6LEQ41l2RyqkxDcumy+g5gzsFc= + +Name: system/lib/libmtp.so +SHA1-Digest: k0A8S8DG+RZt6eeXydihBL7k8KQ= + +Name: system/etc/tfa/deftcoefA.speaker +SHA1-Digest: wtjbWpsy42NLfyzW3OlAUt67zh4= + +Name: system/customize/resource/wallpapers_b_05.jpg +SHA1-Digest: 4Lf7CA6uE0FVw7lDp43CH0WKJH0= + +Name: system/app/HtcDropboxGLRPlugin.apk +SHA1-Digest: cRYTEgRdLfXDENP98xBqP1aZ4iU= + +Name: system/app/IMEXT9Portuguese.apk +SHA1-Digest: 3icxnWX7MMSCgyDdTSTJORtDVi4= + +Name: system/app/HtcRingtoneWidget.apk +SHA1-Digest: 7fXTNiEIR9WbEaEtDqabCFFycMs= + +Name: system/etc/security/cacerts/e268a4c5.0 +SHA1-Digest: aUfrGa2UxFs8hGDtl0m8Koqa9GY= + +Name: system/app/HtcContactWidgets.apk +SHA1-Digest: eBf6ZjsHMCqG6KqaNomA4xN4/ow= + +Name: system/lib/libchromatix_ar0260_hdr.so +SHA1-Digest: /ySTdlA6/+XAReWKyz5lvi69Ng4= + +Name: system/lib/libmmcamera_rawchipproc.so +SHA1-Digest: +f0dSPuvtb6aCvP96j/mvDy++gg= + +Name: system/fonts/HelveticaNeueLTPro35Th.ttf +SHA1-Digest: dqm2oNB0jyOwy3o4CGg+z9VXTcg= + +Name: system/lib/libstagefright_soft_vpxdec.so +SHA1-Digest: WJTQtw0nI98y3kcYp20IN11ro8c= + +Name: system/lib/liboemcamera.so +SHA1-Digest: jr6+jSHe2BceZdCbGmd0NtJULyg= + +Name: additions/gps/europe/etc/gps.conf +SHA1-Digest: AaQog3UpIe9UXkxDD42AnjkvKcc= + +Name: system/bin/usbhub_init +SHA1-Digest: 0pFDKZvi6r8Vqhs1pHgLWQFg/Bw= + +Name: system/usr/srec/config/en.us/dictionary/enroll.ok +SHA1-Digest: RuJqPgJuq9pkqvVscU5w1p03aas= + +Name: system/media/audio/ringtones/Red.mp3 +SHA1-Digest: IQ6trD1wah1m7YEnwHCEXrzBjiQ= + +Name: system/bin/ATFWD-daemon +SHA1-Digest: DHHe9ifS9D3qz5y0sw3yIdpJb0c= + +Name: system/bin/mm-jpeg-dec-test-client +SHA1-Digest: Hq2CpSQ5709ZI8O9tLDKlnc0ghA= + +Name: system/etc/security/cacerts/56657bde.0 +SHA1-Digest: OeQPYfZ4mWVdC4vcxJy56002ySk= + +Name: system/lib/libCommandSvc.so +SHA1-Digest: 5mefyxKlpmRk9ZhNhr53Wi8Rths= + +Name: system/lib/libwt6xlsrdr.so +SHA1-Digest: plBBT6MvMz4I0oqFXiV+TE2MtGk= + +Name: system/lib/libOmxCore.so +SHA1-Digest: 5LD0wUtT8vopu1K9LGfR8PpP1lQ= + +Name: system/lib/libpixelflinger.so +SHA1-Digest: ZurFBaCQeOgajaVxpGgh5xURy+I= + +Name: system/lib/libmm-omxcore.so +SHA1-Digest: hKBNIj33yRHPXBLYCBcHEOGeYyk= + +Name: system/bin/RescueStarter +SHA1-Digest: +6gxA6+F7EaL/ohhWGv5YRkzFlI= + +Name: system/etc/ppp/ip-up-vpn +SHA1-Digest: uMw/gE4SJkSr5seC7eFIkF3hGTg= + +Name: system/lib/libandroid.so +SHA1-Digest: y4nN2TBf0XdYysnfRUK6unl+UOU= + +Name: system/lib/libcrypto.so +SHA1-Digest: AKxPsRlC+nv7lhNHk+H8J7NvXyE= + +Name: system/lib/hw/audio.primary.msm8960.so +SHA1-Digest: 6XbfYDVR0uW+PoVl/nByLlmdV9A= + +Name: system/app/Updater.apk +SHA1-Digest: VAPDuYHAitCKaw4cyk8KlQUYVAo= + +Name: system/customize/resource/allapplication_23210.xml +SHA1-Digest: G8ZkBUBPFQ8OHbNUThnSkYE9OG4= + +Name: system/lib/libext4_utils.so +SHA1-Digest: B+7RbjOZ7x2KB5X/TYxMUb7MjBA= + +Name: system/customize/resource/ConfigH.bin +SHA1-Digest: Gzg+wmcxhGxSPcTj3WytTKk7BVI= + +Name: system/lib/egl/libq3dtools_adreno200.so +SHA1-Digest: Y5ypo8dbLtaLa6v6484I20gUMt8= + +Name: system/lib/libOpenMAXAL.so +SHA1-Digest: 1Z3ZGeGdm/0QV72RYtkab88oafw= + +Name: system/etc/security/cacerts/1df5ec47.0 +SHA1-Digest: Qxp979sc7+YKhsMsGesH1DjUOJI= + +Name: system/customize/resource/wallpapers_c_04.jpg +SHA1-Digest: 3DYZGHdhyCZSwnrY0WXQvFvLSu4= + +Name: system/lib/plugins/com.adobe.flashplayer/libflashplayer.so +SHA1-Digest: zdiYvO8Y3OvJfIGTYPmrZg9sjPg= + +Name: system/framework/com.htc.resources.apk +SHA1-Digest: TsyDXA9Meyxtf42hEcDCJKx5w10= + +Name: system/etc/dhcpcd/dhcpcd-hooks/95-configured +SHA1-Digest: KWDLg1JU1szJDOSPDL6OvD3iOk4= + +Name: system/framework/input.jar +SHA1-Digest: LwNYSj4w6CpQSRq9xUQJPZib/5g= + +Name: system/etc/tfa/playbackbeats_l.config +SHA1-Digest: VQZt2bIP+QgdGt+Z7I/sBiivjqQ= + +Name: system/etc/security/cacerts/85cde254.0 +SHA1-Digest: vcr8bqyL/bCXu4bxqRiOyJ8rkls= + +Name: system/lib/libchromatix_s5k6a2ya_default_video.so +SHA1-Digest: dlYZ9gBjjy5wLmKmITRL+n5e5rY= + +Name: system/etc/tfa/recorder.preset +SHA1-Digest: tNWWfwOrlxvpWmpUZwllEnmbRFY= + +Name: system/etc/security/cacerts/0481cb65.0 +SHA1-Digest: /kQ1voFMErA39wsigwqxUluo9sg= + +Name: system/bin/printenv +SHA1-Digest: WJXRgyY6v3bypciRMFwiKCsQqbk= + +Name: system/media/audio/notifications/Viridian.mp3 +SHA1-Digest: apsyWWfgVbC5JJR4x0q/9YSUtzI= + +Name: system/bin/svc +SHA1-Digest: /1od6413nm4+hNXDHR4zepttND8= + +Name: system/framework/usbnet.jar +SHA1-Digest: LCnfPinR9anJWjStDOIqEpCbYHo= + +Name: system/framework/android.test.runner.jar +SHA1-Digest: FLAP1uf4P6zYSySOLSKapmXg/W4= + +Name: system/customize/resource/quicklaunch_23410.xml +SHA1-Digest: kgO2FR/dHmT33zD+YGRoqeSg/g8= + +Name: system/customize/resource/allapplication_65502.xml +SHA1-Digest: /PHrR7QqB2uw2LSoI2hFWuy1y/0= + +Name: system/etc/security/cacerts/2fb1850a.0 +SHA1-Digest: tpQ/ebm+s27cmkePsnMxlzdMwcc= + +Name: system/lib/libstagefright_soft_amrnbenc.so +SHA1-Digest: U/+wlZ+POoPFwe+B+zSq8iHzpG8= + +Name: system/lib/libQSEEComAPI.so +SHA1-Digest: 2CZQM6FHd/5MdKdarXqO87mye6o= + +Name: additions/fonts/roboto/Roboto-Regular.ttf +SHA1-Digest: UeXcQyRH9Fec2LT/BsgBv9kIcMw= + +Name: system/etc/tfa/fm.config +SHA1-Digest: FfNCE6iEk/5sNEdNf3VxamXpF/M= + +Name: system/etc/firmware/leia_pfp_470.fw +SHA1-Digest: MmyTkoBM53apTZk+VQC1uDHQdcE= + +Name: system/media/zchgd/batt_5.rle +SHA1-Digest: nanA9ExRNqw2oicC78rIf1LGd4k= + +Name: system/vendor/lib/libwvdrm_L1.so +SHA1-Digest: 9yEk46zaGm0YpdeuTdeUkpViS2c= + +Name: system/tts/lang_pico/es-ES_zl0_sg.bin +SHA1-Digest: dX1TIDkkkvgY3gnXGkcrIO1D/Fs= + +Name: system/app/PureC_UserDictionaryProvider.apk +SHA1-Digest: I/4ZFC4YUANxnyc1z4/c5VMEnlY= + +Name: system/lib/libqdp.so +SHA1-Digest: RalffA7l1ss5G1lAbEh9cwtxRoI= + +Name: system/lib/libcam_oem_plugin.so +SHA1-Digest: xrSqKRRZHMRyDmh9OJQ1FuJce+A= + +Name: system/etc/firmware/a225p5_pm4.fw +SHA1-Digest: K++5fIxr0AJPB7tCep7AfwsmzPs= + +Name: system/lib/libchromatix_vd6869_default_video.so +SHA1-Digest: c8XAaI/S5/DqcM78C5WSgxXgBXI= + +Name: system/etc/security/cacerts/709afd2b.0 +SHA1-Digest: 5OSTAsmLWAhmGMiYIVKh1IyxqL8= + +Name: system/bin/pnpmgr +SHA1-Digest: FGZbG/Z2f/gEaqkmUiZMAXqvAFA= + +Name: system/lib/libnmsp_speex.so +SHA1-Digest: juq0NaaYSZNmqtJNIRarusfP2QU= + +Name: system/xbin/sysrw +SHA1-Digest: 4ZhXNrRvG7piGpyJaCWV7UrRt38= + +Name: system/lib/libvideoeditorplayer.so +SHA1-Digest: aBwdJ1VA2OaHUiX3750JePoy9mo= + +Name: system/lib/libdrm1.so +SHA1-Digest: pOJ3yW9V+JZ/IYzV9D9p9B+yWK0= + +Name: system/customize/clientid/default.prop +SHA1-Digest: n2sIyqHOAstZHdIrOyYpHz3bQYM= + +Name: system/etc/permissions/com.htc.android.bluetooth.le.xml +SHA1-Digest: EfSDNpuiqM1BMYG2kxz9OBbgv1g= + +Name: system/etc/security/cacerts/1e8e7201.0 +SHA1-Digest: KqgVoWSCtWsuVVi9KeH1TTJ4rlU= + +Name: META-INF/com/google/android/aroma/icons/confirm.png +SHA1-Digest: tRQmwyaUo60uMn6QRe2DOPkRefU= + +Name: system/etc/security/cacerts/46b2fd3b.0 +SHA1-Digest: ncfFJuS33zLgLepbQtRcOp1nNTU= + +Name: system/lib/libwfduibcsrc.so +SHA1-Digest: knfV4e0LIwEyhHI12m8lVUMuCKg= + +Name: system/xbin/sysro +SHA1-Digest: mYu/dAcGZN8+y6oAWTUwxrNbuFo= + +Name: system/media/zchgd/batt_70.rle +SHA1-Digest: 7MMKIPzaeTlsIMD1ActDqLG67r4= + +Name: system/customize/resource/rp_ce_0700_i.png +SHA1-Digest: YQnLG7Ql3VXyJP2nb5fqsbgucQA= + +Name: system/lib/libstlport.so +SHA1-Digest: oWTzsPHEI7U4QfqNFa1VDwBFqSk= + +Name: system/media/weather/weather_thunderstorm_night.mp4 +SHA1-Digest: lXzummcIKe8shs3m9rU6SOfb7vw= + +Name: additions/fonts/roboto/Roboto-Bold.ttf +SHA1-Digest: 03Clm0bwbIuvbFncdpQsexZcu6Q= + +Name: system/etc/permissions/android.software.sip.voip.xml +SHA1-Digest: qPho8aR6qQ+pK8ybcLgZiHGkyEo= + +Name: system/bin/mdnsd +SHA1-Digest: Zb/sgtFDsXx5Asa6rr+yWWY0Uxc= + +Name: system/lib/libjnigraphics.so +SHA1-Digest: CsEDetPouqquavvcMs5hqGMABL4= + +Name: system/bin/ping +SHA1-Digest: 3ZuWEFmdAHWk5qoJniJ9/TTE+i0= + +Name: system/lib/libsysutils.so +SHA1-Digest: e5TgYNveAlnZ0eC1S0MLI7ofAK0= + +Name: system/lib/ssl/engines/libkeystore.so +SHA1-Digest: qjsva2pcYMqc8R2DhjG1M3gC8ZM= + +Name: system/app/GoogleBackupTransport.apk +SHA1-Digest: 0YvyntynzGSIpwVW/9I9e4U6Cwo= + +Name: META-INF/com/google/android/aroma/themes/sense/dialog_titlebar.9 + .png +SHA1-Digest: 6cZtD07kpdT+LpgfIrmN5skm7ho= + +Name: system/lib/libdmt_speex.so +SHA1-Digest: Vrq3yfNY9Yn02A+CdeeufyGcBkM= + +Name: additions/fonts/helveticaneue/Roboto-Regular.ttf +SHA1-Digest: 7f/b8q3TAEG5iZCZl4AHxmb2r4I= + +Name: system/lib/libgps.utils.so +SHA1-Digest: cq2GbReaUMClQLJ7cWRsEw65C+M= + +Name: system/customize/resource/quicklaunch_24007.xml +SHA1-Digest: dlQAOpoWZnybV/udOF2n7Jm5zuU= + +Name: system/app/RebootWarningWin.apk +SHA1-Digest: Mue9PcDdhlx2N/k16B6oV85KUsk= + +Name: system/etc/security/cacerts/a0bc6fbb.0 +SHA1-Digest: V0mHojd9hDTNmkRMn2gBBUc//E4= + +Name: system/bin/hciattach +SHA1-Digest: 9qqCR5FRNpmebVnUkvtuOft8j6o= + +Name: system/media/audio/notifications/Mantis.mp3 +SHA1-Digest: sfGTikezDwxDuQtacFdz1gLWd14= + +Name: system/etc/soundimage/srsfx_trumedia_51.cfg +SHA1-Digest: sFewTyxjx4MtCEI7WPaB3UPG3i0= + +Name: system/bin/iftop +SHA1-Digest: h4CYGQaCzALKqCTJyvRR7AGlhzM= + +Name: system/etc/security/cacerts/cf701eeb.0 +SHA1-Digest: YIKVSOwnG2XtUxSGW9n6w3exUq4= + +Name: system/etc/wifioffloadpkg.xml +SHA1-Digest: 15BrVJxxSn4gzb7IEwWUU1qXK9w= + +Name: system/framework/com.htc.browsermodule.res.apk +SHA1-Digest: 22TLk+PQyPlFkKDGcSO4n0H43yk= + +Name: system/etc/security/cacerts/67495436.0 +SHA1-Digest: ZVlG1by+ahNsQ6Uv4zmahjj+oCw= + +Name: system/lib/libaudcal.so +SHA1-Digest: 0IpgJXECWTucXaEwlDSGB4drKfw= + +Name: system/lib/libFileMux.so +SHA1-Digest: CcZsne0ww0ZuwNTJ9Cl6SVaHcLc= + +Name: system/etc/audio_policy.conf +SHA1-Digest: zj2LuVIigncZRJoBtnnxHKBAp18= + +Name: system/customize/resource/quicklaunch_228.xml +SHA1-Digest: Y8TSc9//Lny0TZHhlPHMaqJZJfo= + +Name: system/customize/resource/allapplication_65510.xml +SHA1-Digest: IdOvWMfv94KZ/II48iavCP6fOII= + +Name: system/usr/srec/config/en.us/baseline11k.par +SHA1-Digest: LAxT4ug59UO7cj2ezMGlctM/8iM= + +Name: system/lib/libext2_e2p.so +SHA1-Digest: fzrQMMsebb2x/chFgSNPP9GC8LQ= + +Name: system/app/Frisbee.apk +SHA1-Digest: rfnFt/WIv9yBYBtL5mdmVI2Q/TM= + +Name: system/lib/libchromatix_s5k3h2yx_preview.so +SHA1-Digest: EUkC+AyE8GNuZ2arl1VfLF+Xuh4= + +Name: system/lib/libqdMetaData.so +SHA1-Digest: tkm+tMrLd/LMbHqlsXo34b6pTRM= + +Name: system/etc/tfa/tfa9887.config +SHA1-Digest: UiD+6Xb8wXYeVGNh4sJe7EFZtzI= + +Name: META-INF/com/google/android/aroma/fonts/small.png +SHA1-Digest: J8lq7Wi2r7b9rEVUmrcwpBBnhZQ= + +Name: system/lib/libv8.so +SHA1-Digest: dchlIchWazth+Eda7/rNPItcZKE= + +Name: system/app/DownloadProvider.apk +SHA1-Digest: CoPnAguf2UBbo+bN27VCUJW5yYY= + +Name: system/lib/libril-qc-qmi-1.so +SHA1-Digest: r1y5lOu4gxkpR9u4e84IbX1l+cY= + +Name: system/bin/touch +SHA1-Digest: TkTufs2gEKsSWdL+eVfy1lYdCLI= + +Name: system/fonts/HelveticaNeueOTS.ttf +SHA1-Digest: x+vbU1ICaoCS6HAqlz1nlcGHUm4= + +Name: system/media/weather/weather_windy_night.mp4 +SHA1-Digest: 610NoN1UpfNlJVXT0CvFIA0Rmx8= + +Name: system/bin/mm-jpeg-enc-test-client +SHA1-Digest: ROYFElMidSYQI06AMR1tygklQrI= + +Name: system/lib/libqcci_legacy.so +SHA1-Digest: VtsemgSxQzQN4luNmp4YtNvVxvE= + +Name: system/etc/security/cacerts/bcdd5959.0 +SHA1-Digest: wUXicMukZB4UlU9/xSoCKEwh6jo= + +Name: additions/fonts/segoewp/Roboto-Regular.ttf +SHA1-Digest: A7sBtaR2beR/cqxLXAdsQyGe7is= + +Name: system/etc/security/cacerts/97fecd7d.0 +SHA1-Digest: eGd39Hr29uPL1cFzSy0LxGWJiC0= + +Name: system/bin/keystore +SHA1-Digest: w4UBTX7ePRXPlKszmAxVbVaLuiA= + +Name: system/bin/awb_camera +SHA1-Digest: Uud1Z7mzZ6ndrCS3pqWt1zEQj0A= + +Name: system/lib/modules/moc_platform_mod.ko.3.4.10 +SHA1-Digest: RkAKNk7k5eBEXDQuJ+6h56uRdic= + +Name: system/app/IMEXT9Czech.apk +SHA1-Digest: Az/c0ubMVQ4trLp+s+IH54dxBGg= + +Name: system/bin/nandread +SHA1-Digest: Ad76Zci/anGSAE0VgDCtlGZEfAc= + +Name: system/bin/bma150_usr +SHA1-Digest: 3m+lg2zZkFLDxwjM0djQwuWX4Fw= + +Name: system/media/audio/ui/Unlock.ogg +SHA1-Digest: myFHw2IIAJpwfZNEKNS0sdsTqtw= + +Name: system/etc/tfa/fm_l.preset +SHA1-Digest: HFL+I9FZAQhEl3cv2cNYEeP2OQw= + +Name: system/lib/modules/moc_crypto.ko +SHA1-Digest: Vx+NTDZ9TV5Q9CcVLn/EmeoyrPk= + +Name: system/fonts/Clockopia.ttf +SHA1-Digest: +vgYgkUemnpjfwZ99j4TWmseawE= + +Name: system/xbin/su +SHA1-Digest: ivfCc8pZ8mQCFXnQ+obbbwzbphg= + +Name: system/lib/libdmt_elvis.so +SHA1-Digest: wly8LAxia07HKq9boQVYnfZB3w8= + +Name: system/lib/libfilterfw.so +SHA1-Digest: luS6LcfcPGtil2hewuqA3MohJko= + +Name: system/media/weather/weather_cloudy_night.mp4 +SHA1-Digest: hsLw9cFbPcYdRraMQymr9AjVyro= + +Name: system/etc/image_htc_midtier_2vol.bin +SHA1-Digest: z0hxADw/FKSp8QqM8/jKcztNv0k= + +Name: system/fonts/DroidNaskh-Bold.ttf +SHA1-Digest: fwLjvQI4iM0Nvsq0mX5whsEIzhs= + +Name: system/etc/tfa/video.config +SHA1-Digest: Ew36B63+fuqSZxRunA6e9JkTywY= + +Name: system/lib/libcutils.so +SHA1-Digest: +qH7/sZKd1lRteq1SQ2kGASwAhA= + +Name: system/lib/libmmparser.so +SHA1-Digest: dVRwYS20qhyCjbTuldhBmO3+bJo= + +Name: system/media/zchgd/batt_30.rle +SHA1-Digest: FIPyXjYGxlhwxzkG2gwlnIS30Bw= + +Name: system/fonts/RobotoCondensed-Bold.ttf +SHA1-Digest: ZCg1lMs131P06MLQgm2d/Hailvs= + +Name: system/app/HtcInternalSettingsProvider.apk +SHA1-Digest: AP1l5/yjABxe6qRGvayGjTFeVsA= + +Name: META-INF/com/google/android/aroma/themes/sense/bg.9.png +SHA1-Digest: 9GI9XxGdHNyODUJIRFZEQeJihvQ= + +Name: system/lib/libchromatix_vd6869_preview.so +SHA1-Digest: 2uRV1mFZ8eKvjJVW3DzTi326Slc= + +Name: system/lib/libcameraface.so +SHA1-Digest: gm+x8fV8/AbxhSbZqdqB8BPCcYc= + +Name: system/customize/resource/allapplication_21404.xml +SHA1-Digest: huaA0lU7IEG9/WGMK9aaoiGYpzo= + +Name: system/framework/com.android.nfc_extras.jar +SHA1-Digest: qsPDx6QpUuAgaCIB3JnEcNsdMWc= + +Name: system/bin/bu +SHA1-Digest: ssJV8rKixa6InHKnBAhyFrsGwa8= + +Name: system/etc/soundimage/srs_bypass.cfg +SHA1-Digest: UwWHCemaEAeChf/A79z3iwbSfqs= + +Name: system/etc/sound_mfg_DMIC.txt +SHA1-Digest: rpTr47oShzL3OgGm4nfb5Fjjmwg= + +Name: system/lib/hw/audio.primary.default.so +SHA1-Digest: FFRQ47LpjBjRHQH2pjwRi8fe89w= + +Name: system/usr/share/partials/partials_A_gb.csv +SHA1-Digest: dSmTCHUgTwDPIQlTMjDjSfivVfk= + +Name: system/lib/libchromatix_imx175_preview.so +SHA1-Digest: P8XTc5VWSoV0EfmNuwZyJHTYlj0= + +Name: system/lib/libnetutils.so +SHA1-Digest: 3Phe9Q1FJREq0DO3gsX+vpMB8lM= + +Name: system/media/audio/ui/Volume-1.flac +SHA1-Digest: G60DY/kdy4VD5Nif9XNM550IPvE= + +Name: system/customize/resource/quicklaunch_28001.xml +SHA1-Digest: eU5HQZAVFSFyrKi/Ep7uXtvPjwE= + +Name: system/customize/resource/rp_ce_0678.png +SHA1-Digest: 7twk6OXGmp7qOa2Wgavkuawbqqg= + +Name: system/lib/libimage-omx-common.so +SHA1-Digest: Gcl42ovD3k9QzUCngA05PvQOXFg= + +Name: system/etc/firmware/fw_bcm4335_p2p.bin +SHA1-Digest: jsXbGFnpVaIkIlcopDb62XndEYU= + +Name: system/etc/security/cacerts/23f4c490.0 +SHA1-Digest: swYiy1QiVyTMlhy6V0v0qzD1Ty0= + +Name: system/lib/modules/gspca_main.ko +SHA1-Digest: VXP6dwMOnxqDQm0McXFzt0FPLP4= + +Name: system/app/HTCShoeboxShare.apk +SHA1-Digest: 45+v6rtjdlEduhOUiWQ/I69kPbs= + +Name: system/customize/MNS/default.xml +SHA1-Digest: Q8pV6m8yiw1kG5xvVbFfwfxHom0= + +Name: system/app/HTMLViewer.apk +SHA1-Digest: YJEAmGPoJwNIEf/WCqlV1rTPiX8= + +Name: system/bin/mm-qcamera-test +SHA1-Digest: EjBZN4UpyTH13TbjzlTB1u7XQXQ= + +Name: system/bin/am +SHA1-Digest: JU7gkgpcGs2BY+uIS5nNG1/nRtY= + +Name: system/etc/bluetooth/auto_pairing.conf +SHA1-Digest: SPc0OzG5Xfm2TPetGFnjUxYan9Y= + +Name: system/etc/tfa/fm.eq +SHA1-Digest: mvLm1ceGsSM6opsaJy+PFY2w3do= + +Name: system/app/SocialManager.apk +SHA1-Digest: 8L019tqzLqJppfKWth4bh2nDfKE= + +Name: system/etc/firmware/ILP0100_IPM_Code_out.bin +SHA1-Digest: bL5o56wRmZlVcVXu6wRKrvnF8MA= + +Name: system/app/Transfer.apk +SHA1-Digest: /gFzTblnPFo0K56ctlqKXuRKdHE= + +Name: system/bin/df +SHA1-Digest: jGLWgCm9QmvH6/qetbOi/GqrFOE= + +Name: system/app/WeatherSyncProvider.apk +SHA1-Digest: JbI3ptG6JggDpdwGr9M+NmPE7rs= + +Name: system/app/HtcWeatherLiveWallpaper.apk +SHA1-Digest: U6cgNh3CjwDNtOFtNXC1MlKbgkQ= + +Name: system/bin/dd +SHA1-Digest: 6lMGBoet/af17l3XySv99L/R4c8= + +Name: system/lib/hw/keystore.default.so +SHA1-Digest: cTDeTRawJqZQoxX9fhOWviKosZY= + +Name: system/bin/bluetoothd +SHA1-Digest: Ing60m+r7Musn1ZPoNnJXk5L+YQ= + +Name: system/customize/resource/quicklaunch_22288.xml +SHA1-Digest: WoRvx95L1XhotmetvpDDs/JaXps= + +Name: system/etc/security/cacerts/9d6523ce.0 +SHA1-Digest: vE5/LZQwY6jpSaq4Tnfywc0Nf6Q= + +Name: system/lib/libDxDrmCAPI.so +SHA1-Digest: Jn39E6+vzVmEZjjd9aqy3yPudnU= + +Name: system/media/audio/notifications/Glitter.mp3 +SHA1-Digest: 8xwWxRN47HFDxG84tQIypr9Lu6A= + +Name: system/etc/tfa/playbackbeats.preset +SHA1-Digest: PC0c9KHkxMg9IY8tbXq330N1H9c= + +Name: system/lib/libbluetoothd.so +SHA1-Digest: Kf1k4plLaWh4HqZA3Wl+gvPSLi8= + +Name: META-INF/com/google/android/aroma/icons/Thumbs.db +SHA1-Digest: xvG5zD3j90Z2zcoSuIrMsqPNQPY= + +Name: system/app/Prism_SocialFeedProvider.apk +SHA1-Digest: LcXWD2Dhm442dY22/IOP1DeHDJg= + +Name: system/fonts/DroidSansHebrew-Bold.ttf +SHA1-Digest: TuR/SCZHlNxWFl5ftrhCebjvNrI= + +Name: system/app/HTCShoeboxEngine.apk +SHA1-Digest: zZuZIgE6nPfVnOYpmocOW/8Xkhc= + +Name: system/app/HtcBackgroundDataWidget.apk +SHA1-Digest: wwZboWB6jFkQGeOAQkBFElxPkNQ= + +Name: system/vendor/lib/libwvm.so +SHA1-Digest: xtuBL9F/Iw9U3uCPom8N5cnKkNU= + +Name: system/media/audio/notifications/Rust.mp3 +SHA1-Digest: TVj8Av7JGO0+kxHmyF0cT4ZiSR4= + +Name: system/lib/soundfx/libbundlewrapper.so +SHA1-Digest: GAYYoXeb3xA7bbgymcuD7pRt98U= + +Name: system/bin/rmmod +SHA1-Digest: uPMvvrg7WP5WaQ6KhDaIjN8/6Jw= + +Name: system/media/weather/weather_l_fog_night.mp4 +SHA1-Digest: iVJD7mjM9MUEvJZ5fIZV5jxwrGE= + +Name: system/lib/hw/gralloc.default.so +SHA1-Digest: ofqqngjz68qeHxl7Mo/GhjwElwI= + +Name: additions/desense/Nova.apk +SHA1-Digest: Ce8iKCBW4trvTsIG5z0YLM00+7o= + +Name: additions/battery/bluep/app/SystemUI.apk +SHA1-Digest: CFdceWIbUPrhnYbl4yNuI+Dt5v4= + +Name: system/lib/libril-qcril-hook-oem.so +SHA1-Digest: tbOnWjJm9pXd1LcL0pJL2nN/fGo= + +Name: system/usr/srec/config/en.us/models/generic.swiarb +SHA1-Digest: ji4QTXKau8N4AjzzU5UsqY8aQ7c= + +Name: system/media/audio/ringtones/Sense.mp3 +SHA1-Digest: v2kVQsjzGjnHTEFpe1jwbSDXZ4s= + +Name: system/etc/bluetooth/audio.conf +SHA1-Digest: rqcq4pfB6gnsm400Ue4v9FQukus= + +Name: system/app/FacebookEngine.apk +SHA1-Digest: unEXelTyVUxzJ6Z3AVmVJyYxYXo= + +Name: system/etc/security/cacerts/a7d2cf64.0 +SHA1-Digest: ue9ZDnsNcXdGKbdrk7MpOk3dLUM= + +Name: system/lib/libbtio.so +SHA1-Digest: FTMd78TBCSNJKxVajFu2R53PRbM= + +Name: system/bin/uptime +SHA1-Digest: lXf7kRRv7nXBW6xaNv4z8SOgPgI= + +Name: system/app/KidMode-google.apk +SHA1-Digest: SyX6gr5hMONtIL/4v1Ci4VStKSg= + +Name: system/etc/security/cacerts/3c58f906.0 +SHA1-Digest: TfWYQv3pjUCWxBCz5mSQzgH9OKk= + +Name: system/lib/libvideoeditor_osal.so +SHA1-Digest: M9KN6MZEW+Wyawc6LMR5aDX/h6o= + +Name: system/customize/cid_map.xml +SHA1-Digest: LcDHJDcRwmOZUGuvulz6RW69gY4= + +Name: system/bin/wpa_cli +SHA1-Digest: P2MhsFUY1/II1yOuRq8cd/irmDc= + +Name: system/etc/security/cacerts/d16a5865.0 +SHA1-Digest: HwEya3RYnDLYdyMkC8yCmJzSKhs= + +Name: additions/fonts/klavika/Roboto-Italic.ttf +SHA1-Digest: jclIVHKvfdnQioiQk/Kgoo/fCLA= + +Name: system/lib/libdss.so +SHA1-Digest: u2DI11Sm5jl6UAQEoo4w/DOJuQ8= + +Name: system/etc/security/cacerts/882de061.0 +SHA1-Digest: C44riBaYmFJys31UFiqhZTMc7Ig= + +Name: system/customize/resource/wallpapers_a_04.jpg +SHA1-Digest: f7toV7fN4/+q1BfrF0iyhJxPw+w= + +Name: META-INF/com/google/android/aroma/themes/sense/nav.9.png +SHA1-Digest: wvj1TM+Wvf4eIYnWvMbnS5lFnrc= + +Name: system/etc/security/cacerts/8470719d.0 +SHA1-Digest: 3gm79ScbKCIpUzG6Fq+8xe+sGnw= + +Name: system/customize/resource/rp_ce_0560.png +SHA1-Digest: hFEF1g+Vj4KgFyRTsTOilss+azc= + +Name: system/etc/security/cacerts/e775ed2d.0 +SHA1-Digest: QnV/erxTCKUTQ8iuLmezodkrswc= + +Name: system/etc/firmware/vidc.b03 +SHA1-Digest: dg6KpFSRatn6L/ugYLCi30+n2Wo= + +Name: system/etc/firmware/vidc.b02 +SHA1-Digest: YSXzJYbrbxurueOJHfDHQ7N5W+Q= + +Name: system/media/GPU/stylizeContrastRamp.bmp +SHA1-Digest: byEwbeK2WiDAeJZHW1EHCG+p2qU= + +Name: system/etc/firmware/vidc.b01 +SHA1-Digest: uDqET53DNXtQ4y3Q4m6JjU32g4Y= + +Name: system/lib/libqmi_common_so.so +SHA1-Digest: gach3Ovy3fH42qnI1gHJNqzwoSw= + +Name: system/lib/libmm-audio-resampler.so +SHA1-Digest: DzlGiC+aFW5LA76fKZf55oEeNWc= + +Name: system/etc/soundimage/srsfx_trumedia_music.cfg +SHA1-Digest: B+99y1yk8dYqYyWoTfC/EIJ6l0E= + +Name: system/customize/resource/allapplication_24001.xml +SHA1-Digest: KatjPxCXN3IgNC1j2x2qWBCngwQ= + +Name: additions/battery/greenp/app/SystemUI.apk +SHA1-Digest: J3mybY6MUqvghObCiCddrTqieBc= + +Name: system/etc/security/cacerts/c9f83a1c.0 +SHA1-Digest: f3imgBTggzJSdmhd0Xk1YU+iT54= + +Name: system/lib/libgnmc_decoder.2.5.9.4.so +SHA1-Digest: BQ42wCRSi98k/GXnCWmdNqf7E7Q= + +Name: system/fonts/HelveticaNeueLTPro-Cn.otf +SHA1-Digest: jELk06Ol8P0BI7WKfng0GMhgs4c= + +Name: system/app/HtcAirplaneModeWidget.apk +SHA1-Digest: +eKr0JYjwdB+BQ6osP7x9NgQ5ys= + +Name: system/bin/bmgr +SHA1-Digest: bBpREmgN5x0uzCxgS8dQhyklSCA= + +Name: system/app/HtcWiFiWidget.apk +SHA1-Digest: mD7i8AHd7Ojsbld1N0bcsX9RyJE= + +Name: system/etc/security/cacerts/895cad1a.0 +SHA1-Digest: ZfoxSCSC3uyNPPMG27Jrd3n1Ej8= + +Name: system/usr/srec/config/en.us/dictionary/cmu6plus.ok.zip +SHA1-Digest: ACsZaiNkJjr+osByDLYlAO7jbjo= + +Name: system/app/HtcNotesPainterView.apk +SHA1-Digest: o8/hN4j5v7uViNNtGs+f3BhY/Tk= + +Name: system/media/audio/notifications/Creme.mp3 +SHA1-Digest: 5CSXz5MEIK563WBXF1CXPaJ1LW4= + +Name: system/bin/gzip +SHA1-Digest: JyvMJh12ypgvyR830X5HCttpwHQ= + +Name: system/customize/resource/quicklaunch_250.xml +SHA1-Digest: eP6cTXc2z5D6AMAIW/yNEF9nFAI= + +Name: system/etc/tfa/voiceWB_l.eq +SHA1-Digest: 72hg+IrsxZZsykZj86tVEhqcZAs= + +Name: system/media/weather/weather_l_hot.mp4 +SHA1-Digest: eQev9Zca/qWTtsthmuECQGe9C2Q= + +Name: system/bin/lsc_camera +SHA1-Digest: IGd8Lornm9e7XOzG/ynhF4MWOUs= + +Name: system/app/HtcMessageUploader.apk +SHA1-Digest: yPG1Pwt74eJaJBRU/9DVEaDVLwk= + +Name: system/etc/security/cacerts/1dac3003.0 +SHA1-Digest: xqnEkR4Urw+Mekb6eWImjmF2AMM= + +Name: system/lib/libMusicVisualizer.so +SHA1-Digest: EYF49bAZKhmwbeNh2OhOEexvUEo= + +Name: system/app/PolarisOffice.apk +SHA1-Digest: JFvYAR7qE2souad1p6oR1S+dg0w= + +Name: system/etc/firmware/vidc.b00 +SHA1-Digest: hLHwO/SVUNir7KdAQLI/7uz1M6s= + +Name: system/app/IMEXT9Ukrainian.apk +SHA1-Digest: zu1owczQHpRLW2EHdrHm+YfTjjI= + +Name: system/bin/zchgd +SHA1-Digest: Sh5o2VJM0UuH+DIV2QKidFPBLg4= + +Name: system/etc/permissions/platform.xml +SHA1-Digest: B4DaWYYzqfuysBG6ebWmi56BR74= + +Name: system/lib/libwt6pptrdr.so +SHA1-Digest: pu0gqop15ZPmahIdDqH9aq97ZM0= + +Name: system/app/HtcDataStripWidget.apk +SHA1-Digest: akpLCRldAjmSJ9pPT5BOqnpfX+w= + +Name: system/app/HtcContactsDNATransfer.apk +SHA1-Digest: Dv7cq/cvF/OWdQovTtwFiOyRpFU= + +Name: system/etc/security/cacerts/c3a6a9ad.0 +SHA1-Digest: fbdLZbwmByGAC1L8jv9+TWtc61s= + +Name: system/lib/hw/copybit.msm8960.so +SHA1-Digest: 2sX4Ht1ng5blGlYsYfnbQQfmpFE= + +Name: system/lib/libaah_rtp.so +SHA1-Digest: A7NTkR3B4hWwTrgJw4EUUwQlqIE= + +Name: system/bin/start +SHA1-Digest: /3LV6Ws6VkFzwNSJkoyN2LGdNdw= + +Name: system/lib/libchromatix_s5k6a1gx_default_video.so +SHA1-Digest: gzEvq5ZrnkjOtQ7K2rpN6B1eCec= + +Name: system/etc/NOTICE.html.gz +SHA1-Digest: twWFZX7EFH6o07wunRbXuPNFX8I= + +Name: system/bin/mm-mpo-dec-test +SHA1-Digest: VLghETRXdLUDvFRSeh914q9wGvs= + +Name: system/lib/pp_proc_plugin.so +SHA1-Digest: 8OAvdozqrci06WDu6ydsi7GaRX8= + +Name: system/bin/hd +SHA1-Digest: uXqHkK1skY7C3lHsU/j969msqwc= + +Name: system/app/HTCWeatherClockWidgetAgent.apk +SHA1-Digest: RV4UQyZlVBIXwCygsvjFsdt1HHo= + +Name: system/media/audio/notifications/Olive.mp3 +SHA1-Digest: wUE56b5AqoklljGbDlKMAlKw9Qo= + +Name: system/app/Facebook.apk +SHA1-Digest: +kqYKx6qa1piDrrlWmwrgArCdqc= + +Name: system/media/zchgd/batt_20.rle +SHA1-Digest: xP1qebJOAFu8kO4BRgVcnfHDFOg= + +Name: system/app/HtcCalendarWidgets.apk +SHA1-Digest: vZhSStJmVr7KERwe3NjPH27wr24= + +Name: system/app/VoiceSearchStub.apk +SHA1-Digest: e7bLPllwwcDBcshfeV8z2/iT3c0= + +Name: system/media/zchgd/charging_09.rle +SHA1-Digest: QEchPYa+nGV/huI0/6+hg0aBONc= + +Name: system/lib/libmorpho_edit_engine.so +SHA1-Digest: HPUdkF61w2+3FfOac7PsO3cwQ9c= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_on_sel.png +SHA1-Digest: 4OtiBiLhfOrOuJ2QT/UNRjr8bb0= + +Name: system/media/GPU/dot_mask_16x16.bmp +SHA1-Digest: ZGGV5rcruhPC7rb3du6G5Z2+dtk= + +Name: system/lib/libchromatix_ov8838_preview.so +SHA1-Digest: 4RFtACgp3+ZzHbFGNgy4ybRxgJU= + +Name: system/media/zchgd/charging_03.rle +SHA1-Digest: ekhart7hOvO1puEySttLB1i8r6Q= + +Name: system/etc/permissions/com.broadcom.bt.le.xml +SHA1-Digest: yjJIFy4CXQIFhE3de74RcEEiCjY= + +Name: system/media/GPU/ContrastCurveSet.bmp +SHA1-Digest: RIZsUiF7vgCiusq0P+jt/PoJa1s= + +Name: system/lib/libGLES_trace.so +SHA1-Digest: INzhxnQRFUQ0gN4ObhTn5Bf/hkw= + +Name: system/etc/security/cacerts/3e7271e8.0 +SHA1-Digest: RuWAcBguGdtlhixJYoOZcOECH4g= + +Name: META-INF/com/google/android/update-binary +SHA1-Digest: +Hc5mmK0diiOVs20WtZ2N6S2LqI= + +Name: system/etc/security/cacerts/89c02a45.0 +SHA1-Digest: loal9vEQNuqt054EQZ5Bc4v5bGE= + +Name: system/lib/libcameraasd.so +SHA1-Digest: DK0DoHcVsH35Cg2nnq+ZaQsglD4= + +Name: system/etc/tfa/voice_l.eq +SHA1-Digest: 11MY2YuU0QrbVYohMeReYItzFuM= + +Name: system/lib/libETC1.so +SHA1-Digest: ZVJtwNVK38JnU5JcNuvTLtb7/+Y= + +Name: system/fonts/Lohit-Bengali.ttf +SHA1-Digest: 8YyKXrXjV+v9Ocb9fWaRfBuhWdY= + +Name: system/media/zchgd/charging_05.rle +SHA1-Digest: tfGPbZxD1yMf1NNlWDad68dcCrs= + +Name: system/bin/screenshot +SHA1-Digest: QcsdkyUUq2+sheevzyAP5rX9Bak= + +Name: system/media/audio/ringtones/Vanilla.mp3 +SHA1-Digest: g1WeLc6dErQDWPotfPJLd/czOA8= + +Name: system/lib/libOpenCL.so +SHA1-Digest: JEoO/L8onFJXCywVVnDmaJh6P7g= + +Name: system/bin/cir_fw_update +SHA1-Digest: U0uQJPZHcFK5wwSZYr5aZ4MfvhU= + +Name: system/media/audio/notifications/Pear.mp3 +SHA1-Digest: w6KCOyC6V/tEv5SznvaGGwLz82o= + +Name: system/media/mms/kddi_earthquake_alert.mp3 +SHA1-Digest: /yk4s4lxpTfqF9BSM2Gb38LcEa0= + +Name: system/lib/bluez-plugin/network.so +SHA1-Digest: 6BWG8qvmf8MSHu5+4H0LKgf1bg8= + +Name: system/lib/libvideoeditor_core.so +SHA1-Digest: suOl0ljW9hEhSKvwpOO++sqlC/A= + +Name: system/lib/libexpat.so +SHA1-Digest: Rb0vWNk69RbealZadCYx0Dy8Gm0= + +Name: system/bin/thermald +SHA1-Digest: nrkMQSFV0kxCabGELaMpowyvuhU= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_on_sel.png +SHA1-Digest: Gwz5HlyhTkojSpWYOMTzcvQbSdY= + +Name: system/app/HtcModeClient.apk +SHA1-Digest: 32X3jfQp7M5vRsfQ4c79jJTzOcE= + +Name: system/customize/resource/trickdroid.jpg +SHA1-Digest: by8iSHYhr+O/5wxDPOjAXN9zgMg= + +Name: META-INF/com/google/android/aroma/fonts/big.png +SHA1-Digest: KpRWRiPGaUoFVDl0JWboNJb3kfk= + +Name: system/app/Flashlight.apk +SHA1-Digest: HcVaR9W4wD6jYOuJ2bm6bNbVCEo= + +Name: system/etc/security/cacerts/27af790d.0 +SHA1-Digest: 0cY3bpCx4tRkNSVNjHyk12XB36Q= + +Name: system/lib/libaudioutils.so +SHA1-Digest: Yvr0K/4tKgT9etrrtUL26ahlbYk= + +Name: system/customize/resource/quicklaunch_20201.xml +SHA1-Digest: rwXDAslQp8xBCcxUJnJ8CJIlUXA= + +Name: system/etc/hltof.bin +SHA1-Digest: E6HnhglLpohiT66gffeteHF1gWg= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-rn30-ri30.5-v24/full_model.bin +SHA1-Digest: MK+pzoM4WfbE9qVi0dNWTVqG4fk= + +Name: system/bin/ndc +SHA1-Digest: L2DiqqXI/gXsJc9f0p3jll6l2uY= + +Name: system/lib/libsqlite_jni.so +SHA1-Digest: /dp3RYPLyOeNkZF85oSVSQOpkZk= + +Name: system/lib/libskia.so +SHA1-Digest: eTs4bc0g0NBOUmY7YKAD7qcZUxQ= + +Name: system/usr/srec/en-US/google_hotword.config +SHA1-Digest: u15PKfBvK1oxEnD02hPRCZy5Ez4= + +Name: system/lib/libdrmframework.so +SHA1-Digest: YC5O2B3yFmjHeNUw7zq7Tyx46j4= + +Name: system/lib/libandroid_runtime.so +SHA1-Digest: mSn68M7/cC8JjKcxNBywUY6d8UI= + +Name: system/lib/modules/moc_crypto.ko.3.4.10 +SHA1-Digest: LoH2y/67VcUXbDcSyHtWaAlcxBs= + +Name: system/lib/libgabi++.so +SHA1-Digest: tvlZmxwNOKHVV9wzmrczWHrQT5E= + +Name: system/bin/ip +SHA1-Digest: sFPEmZn4s/h/tSqxXlBqFDm0ua8= + +Name: additions/fonts/segoewp/Roboto-Italic.ttf +SHA1-Digest: gYwfIM7YiamQ8LbsmJyQxwRPk8o= + +Name: system/bin/rtspserver +SHA1-Digest: 7AA9maQRx8u+aTKlS1smUsBD1tk= + +Name: system/etc/permissions/android.hardware.camera.flash-autofocus.x + ml +SHA1-Digest: aDfHvVEe0svv+HGWg3e4S1UZY1k= + +Name: system/bin/id +SHA1-Digest: Tg1r0n8FAqaLfIIMOOvPSuCINFk= + +Name: META-INF/com/google/android/aroma/icons/personalize.png +SHA1-Digest: J8xJz95qwUKrTDbgbqbfNFHoUus= + +Name: system/bin/setprop +SHA1-Digest: c7E/TK82xoZwPO8f1t1AMhXABrY= + +Name: system/lib/libstagefright_soft_rawdec.so +SHA1-Digest: 8G+s9aImm6wKxevQoDxofCNwj4w= + +Name: system/bin/kill +SHA1-Digest: ZM4BTwhKGJcdH3BjMPSJOm3AfwE= + +Name: system/etc/image_htc_earbud.bin +SHA1-Digest: CXqwEDbDsU5pxYviO6SHIIrchrY= + +Name: system/app/OneTimeInitializer.apk +SHA1-Digest: I7gBGYaAMlfc846vxsQWFHSeOfo= + +Name: system/usr/share/partials/ticklist.csv +SHA1-Digest: hf6Xd219x7zu+QnONGHZYNryBIU= + +Name: system/app/JETCET_PRINT_S50.apk +SHA1-Digest: KBNUWUeiDoFp7virDScfnmTcFDc= + +Name: system/etc/permissions/com.android.location.provider.xml +SHA1-Digest: amS9x3HUOepZjI/MyRzFmoDrRd0= + +Name: system/lib/libzeroeditor_videofilters.so +SHA1-Digest: 2ZELTdGUSReItUbmyTEV14ni9j4= + +Name: system/lib/libChange.so +SHA1-Digest: pIRy2vqW8avXhBleDg19l9OaoxM= + +Name: system/bin/ln +SHA1-Digest: p9+8eSYK/dYwxpTsBpGa807nv2k= + +Name: system/etc/capability.xml +SHA1-Digest: zMt3LK6q5/6xTWQpFwGB+bU+8H0= + +Name: system/bin/ls +SHA1-Digest: oVGslBM2u80MkNXXi9dBXNbdxMc= + +Name: META-INF/com/google/android/aroma/icons/customize.png +SHA1-Digest: envvq/UioWgJ0FmKVyuWyqaZVwk= + +Name: system/bin/mksh +SHA1-Digest: SDK79qz88hb7ajBOtAlBtWmLPrs= + +Name: system/etc/tfa/fm.preset +SHA1-Digest: r4QDvqDV9VrpQz8kSeaRsSURtmc= + +Name: system/media/audio/ringtones/Pearl.mp3 +SHA1-Digest: ivSx/6gSoIt1/v91SSXoXeN6BvI= + +Name: system/etc/permissions/com.orange.authentication.simcard.xml +SHA1-Digest: ymx4aLoY1maYXcz1PdSz0gfiJvk= + +Name: system/customize/resource/allapplication_23801.xml +SHA1-Digest: DkvCSwQpAwK65A0UuC8SRnn8EKY= + +Name: system/media/audio/notifications/Saffron.mp3 +SHA1-Digest: dUePQaaFmtO/Ul1aIXMAPzUOg4U= + +Name: META-INF/com/google/android/aroma/icons/nova.png +SHA1-Digest: kGBOFfg0gV4/+6A/YM4fkpT29P8= + +Name: system/bin/ks +SHA1-Digest: 5cz+U+l5Wh5yrx4BjelOfQc54ew= + +Name: system/lib/libm.so +SHA1-Digest: 0fY2xDEtyemq405b93Lm8/daDak= + +Name: system/lib/libdrmdecrypt.so +SHA1-Digest: wEZplOEiPdEJdS8po6oPuCtKB9c= + +Name: system/media/zchgd/charging_02.rle +SHA1-Digest: V8XXH0zjVf+UYS98Zgyf8rHERK8= + +Name: system/bin/hostapd +SHA1-Digest: hFqMKoGrtFWrGldHrAHFLxEY1m0= + +Name: system/tts/lang_pico/de-DE_ta.bin +SHA1-Digest: UxOTX6s/ImMF3+i9MWBJSPZ52Hs= + +Name: system/lib/libmm-abl-oem.so +SHA1-Digest: RON+y9Xd4UjJDmAX8xhlGfHBAi8= + +Name: system/etc/voicemail-conf.xml +SHA1-Digest: cpbegTHSEXbwpD146kWK9nSW+jI= + +Name: system/app/HtcCompressViewer.apk +SHA1-Digest: JSyR4UahTfAqOsjtocKH72voXsI= + +Name: system/usr/srec/en-US/offensive_word_normalizer +SHA1-Digest: JlWzqRWPoWw50GU8zCZrADdDH+E= + +Name: META-INF/com/google/android/aroma/changelog.txt +SHA1-Digest: DGmPbFSCsgFJDysnqWjZZzJfyDk= + +Name: system/media/audio/ringtones/Pink.mp3 +SHA1-Digest: WwK1p3HPPcW1Xzibg0BVuBlvHT0= + +Name: system/lib/libchromatix_vd6869_hdr.so +SHA1-Digest: vJmVfedV940c1tKdl8GespTlic8= + +Name: system/media/PFFprec_600.emd +SHA1-Digest: tY5XAqhHwXuMXM5dlnwKhnKvt/A= + +Name: system/usr/share/partials/partials_H_gb.csv +SHA1-Digest: fv0hDkjmNqIxK0f0Uf9tSOT9yfM= + +Name: system/app/SoundSetDownloadManager.apk +SHA1-Digest: pzx4o376t7z3MisdkNmU9+wGSus= + +Name: system/lib/libjavacore.so +SHA1-Digest: jlxoVgJ2TwLJussjhmMnzch28OA= + +Name: system/lib/libwlwpscli +SHA1-Digest: GFV2r0fGjT8wKpvyKp+n6432GEA= + +Name: system/media/audio/ringtones/Brass.mp3 +SHA1-Digest: wGEOhvW27Q2qcU664/fNa0WixVA= + +Name: additions/wipe/bash +SHA1-Digest: KPGXHEUCSWS7mah9DpGJO94czkA= + +Name: system/customize/resource/quicklaunch_65501.xml +SHA1-Digest: kGnxQlcVCBmXmK/zxW8fWCgbFIo= + +Name: system/usr/share/partials/partials_CW_rr.csv +SHA1-Digest: 2UXIVf653OLrELajiXGbfCufxnw= + +Name: system/etc/security/cacerts/7651b327.0 +SHA1-Digest: XHbRZvJn9XfMIFtTqDSXFV3AzRM= + +Name: system/bin/ioctl +SHA1-Digest: 05TebPkXcYMvqOgd8Vkse4BX6GA= + +Name: system/app/IMEXT9Italian.apk +SHA1-Digest: pQJ7t7Lch1k126ZxOBE1u5lrWLY= + +Name: system/bin/mv +SHA1-Digest: Yul+yVkdWwUkHoVRKMp0BAc1nw0= + +Name: system/lib/hw/lights.msm8960.so +SHA1-Digest: 76y6imO8vl50iq7DQ04msl5OJAk= + +Name: data/app/com.google.android.apps.plus-1.apk +SHA1-Digest: 9WU0JqJ3doLKW33WCMSwM1+IU+w= + +Name: system/media/audio/ringtones/Cerise.mp3 +SHA1-Digest: Qxuwzsd2qK4KcpXgeLi+LYN1SQ8= + +Name: system/etc/security/cacerts/219d9499.0 +SHA1-Digest: h/DoWPK51SL4obNm8yCTilqR0+8= + +Name: system/lib/libmmcamera_statsproc31.so +SHA1-Digest: e5J+f6bBB9WjQfpvnNmC2E/GFFI= + +Name: system/usr/icu/icudt48l.dat +SHA1-Digest: kanMdtwKTwlxkx1DtKWAJmwzCXw= + +Name: system/fonts/ARDJ-KK.ttf +SHA1-Digest: pGUbOB8+3o3rp9q+YY3ezzwgC4Q= + +Name: system/lib/libDxAndroidSpecific.so +SHA1-Digest: dKdWRM+D61L2sWiZoqCmOWW1F70= + +Name: system/app/VpnDialogs.apk +SHA1-Digest: pFLiB6M+S2d65MAA0PDhyujBImE= + +Name: system/app/IMEXT9Swedish.apk +SHA1-Digest: HVwZ5+ZXlX9govJieMI3tdSm9VA= + +Name: system/lib/libpphwrcore.so +SHA1-Digest: 4ZYZIsH9XB67Geym4B/ydBJHnHg= + +Name: system/media/audio/alarms/Jade.mp3 +SHA1-Digest: de1jJWm4UI253FRMXUditS8ntug= + +Name: system/etc/security/cacerts/60afe812.0 +SHA1-Digest: ttJEIPTia8N+uVOS3mUfCJzhFvI= + +Name: system/usr/srec/en-US/hotword_symbols +SHA1-Digest: dbEFacb+0FC8zwiG1opgbrzcACQ= + +Name: system/app/ZeroEditing.apk +SHA1-Digest: A1Y9H9yE78+Yx+HnmTVKzV1pe5M= + +Name: system/app/Trim_n_Slow.apk +SHA1-Digest: u+C8g7i9hdWAhd148BOn5Hcl1Lg= + +Name: system/etc/security/cacerts/f0a38a80.0 +SHA1-Digest: Hm9gf50Bu8p9qGUTsxt/fvnJteU= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-rp30-ri30.5-v24/full_model.bin +SHA1-Digest: zylgR6Y3XLkv3CWuB04/XsCJjbE= + +Name: system/lib/hw/power.default.so +SHA1-Digest: tN3SujJIGPPXk9Ca8eTqttzjCBw= + +Name: system/lib/libmmwfdsinkinterface.so +SHA1-Digest: a8CN1rDFDnvFOyeQKcmOtgG04oI= + +Name: system/lib/libdbus.so +SHA1-Digest: xMQppjZUkYcjSryk10RyTnGt2cw= + +Name: system/bin/input +SHA1-Digest: fmnGVSPBoXqAUgaTVBG6zdBwPNY= + +Name: system/lib/libalmashot-seamless.so +SHA1-Digest: OBea13pOI++tVc9Ul93/MYasfk8= + +Name: system/customize/resource/wallpapers_a_01.jpg +SHA1-Digest: oIO8YIu9JAx8B0kZ9jd8e0ZmwjY= + +Name: system/lib/libmmwfdinterface.so +SHA1-Digest: tYQ74gGUNhhOanfCrdGAv8+KJkM= + +Name: system/lib/hw/local_time.default.so +SHA1-Digest: anrPxzoXpjstXkH/+VDMpjOttS8= + +Name: system/media/zchgd/batt_60.rle +SHA1-Digest: Ci0cVjXfi3uHBdU7/R8kJ/pwaOg= + +Name: system/lib/libext2_com_err.so +SHA1-Digest: JdZ2atQG7H+wbPx6yWnf9z+nGT0= + +Name: system/bin/pm +SHA1-Digest: ZZqEROz0ggs5Pz1SZjKHP/AP6xw= + +Name: system/bin/mm-mpo-enc-test +SHA1-Digest: kCIOhg3fYX4iR1GhvYkOP2pA9Go= + +Name: system/etc/firmware/fw_bcm4335.bin +SHA1-Digest: k9ATLXVv7+F2jeHkrbjoc6whcRE= + +Name: additions/desense/Apex.apk +SHA1-Digest: 1ib2ZE7cAUCq7e2lToFqfZzblto= + +Name: system/bin/ps +SHA1-Digest: OPLUXuOPhY18Zi7PSOoRZuJPXjg= + +Name: system/etc/firmware/a300_pm4.fw +SHA1-Digest: ISjYgZpYq77YSXg2WGUDsl2xLJc= + +Name: system/lib/libchromatix_ov2722_hdr.so +SHA1-Digest: oelR4ErCfu0PnkSk92mWIZHaPxk= + +Name: system/media/audio/alarms/Amazon.mp3 +SHA1-Digest: A1hEgekWvzvyNsqEM6c+d3fub7M= + +Name: system/etc/tfa/voiceWB.eq +SHA1-Digest: EQQ5dOV9sCue4lsOOPhSihud02E= + +Name: additions/camera_4.2/lib/libjni_filtershow_filters.so +SHA1-Digest: ytVQD2l9BW3Wgvi5ekA5FF1HKlI= + +Name: system/bin/port-bridge +SHA1-Digest: Bx2n57Aq0Fly6IaIYgDdqud4eU4= + +Name: system/app/IMEXT9Norwegian.apk +SHA1-Digest: mBMOR6uLgf4NQv4IJV6Dkq2aWJY= + +Name: system/etc/sdk/sdkinfo.xml +SHA1-Digest: VVobJulw9nm+TbKcDgRcDTAu1oI= + +Name: system/lib/libImageAlignment.so +SHA1-Digest: q8yn6YsZkZgAtFUnyXMvrMl71/o= + +Name: system/bin/dalvik_coredump.sh +SHA1-Digest: o2J9r+hGyYCZMXthnRKemxKbBCs= + +Name: system/fonts/Lohit-Telugu.ttf +SHA1-Digest: abw73bBK9fbGs9tX2WASfCr7QvA= + +Name: system/etc/image_ibeats_2vol.bin +SHA1-Digest: Tnay7C4pHloO2refAYca0P/1NtA= + +Name: system/app/BackupRestoreConfirmation.apk +SHA1-Digest: YgB0NolrJqLztOZXWafuzaIT3JQ= + +Name: system/tts/lang_pico/es-ES_ta.bin +SHA1-Digest: iomlWBJnyeAmuhpPJfKYJkKDUEw= + +Name: system/lib/libstagefright_enc_common.so +SHA1-Digest: eFMlMpgGo0Bgj3a7FEBdneQBIaM= + +Name: system/lib/libsurfaceflinger.so +SHA1-Digest: C7J6nn0ong8ir2IVPlCXfzVRjCo= + +Name: system/media/audio/notifications/Capri.mp3 +SHA1-Digest: ARuq6LzlgMZ1CcNgHLtWWVmIMTY= + +Name: system/etc/updatecmds/google_generic_update.txt +SHA1-Digest: /JTgfNkrdifcko4L7i/FD70eeaA= + +Name: system/bin/tc +SHA1-Digest: EK+BjCgltQY5Sbf+vsYliPaQKXo= + +Name: system/bin/dmagent +SHA1-Digest: TA87HnbbgTpWv/nmWgqzjyFzVFM= + +Name: system/fonts/MTLmr3m.ttf +SHA1-Digest: lq6qXjY2kKKL6Rf1iBi0b5nkumA= + +Name: system/lib/libOlaEngineNew.so +SHA1-Digest: 3e/s4RP7Q8V/cwxyBIQVvF5pMlw= + +Name: system/bin/brcmapd +SHA1-Digest: h1ySdqwhLVz1KzJUIcEcXSRwJwE= + +Name: system/media/audio/ringtones/Yellow.mp3 +SHA1-Digest: gQarkiMhIuXOGwOQ7J5EQW6qlJc= + +Name: system/etc/security/cacerts/a15b3b6b.0 +SHA1-Digest: Ga8+gSid8GucSUYQ4UcWClt0eZI= + +Name: system/customize/resource/allapplication_26801.xml +SHA1-Digest: 0q41RuHWovB8oGPHk333zn6omc0= + +Name: system/etc/security/cacerts/33815e15.0 +SHA1-Digest: sxrwaxlAJHZVh6z+sNYj97iZIuA= + +Name: system/lib/libstagefright_soft_amrwbenc.so +SHA1-Digest: mi/2CUKJSkgdL0v8hMdQe9Xv8KY= + +Name: system/usr/srec/en-US/google_hotword_logistic +SHA1-Digest: sYH+W7m9I89ltQfiDWM1Pi6quVg= + +Name: system/etc/AudioBTIDnew.csv +SHA1-Digest: OqoJD98zSi+0bgQ71GlQ61s/D5I= + +Name: system/lib/libOpenSLES.so +SHA1-Digest: Kl1FYgKYPFTqSUR/wBupW0kxyS0= + +Name: system/lib/libgnmc_aactag.2.5.9.4.so +SHA1-Digest: SqiphGmt8er5d/uIqLqOX56dILE= + +Name: system/lib/libwebcore.so +SHA1-Digest: L/si2K329/yV62czlJM7jfgsY9M= + +Name: system/lib/libhwui.so +SHA1-Digest: njdGivGkB7wjEm3I5U9Lt0Vhr3Y= + +Name: system/media/audio/notifications/Lilac.mp3 +SHA1-Digest: 4v8zhTEMyL+qQze1B3o3aM7KeaI= + +Name: system/etc/tfa/voice.preset +SHA1-Digest: AHdeBzE+aWvVm1+lPSFIH9aVQ5Q= + +Name: system/media/audio/ringtones/Mustard.mp3 +SHA1-Digest: F9G9K6OBnLZjOknDhcmUN99i6e8= + +Name: system/media/weather/weather_l_thunderstorm_night.mp4 +SHA1-Digest: 933h42nOwxpmjBMtfeRffjhQY9M= + +Name: system/usr/share/partials/partials_A_rr.csv +SHA1-Digest: 7N+zrRg29j67fnbxIs/RKj+DHsY= + +Name: system/lib/libsrec_jni.so +SHA1-Digest: m6ENj91zQKcDhi1YXCFHQT2SxjU= + +Name: system/fonts/DroidSans-Bold.ttf +SHA1-Digest: WDG+d/J10mMQJ/zJyy0IqmMxQiI= + +Name: system/media/GPU/header32bpp.bmp +SHA1-Digest: PjhggTIP61boB4JqIvcpyJGbEv4= + +Name: system/etc/agps_rm +SHA1-Digest: eeIWQXwn7SfkaNiZ7b0Z+n+0oYo= + +Name: system/bin/akmd +SHA1-Digest: wwGmCKhzKRFsHioX4nUZ3EnOFY8= + +Name: system/app/MyGoogleTaskPlugin.apk +SHA1-Digest: 9DbAEYx2cca7XFpCDoR7Y15StmI= + +Name: system/lib/modules/bcmdhd.ko +SHA1-Digest: L2BqmFnLoAXmSjk7J4WjW0aZuW0= + +Name: system/lib/libmmipl.so +SHA1-Digest: AdWbW5mMg9reEHgh2AnKlqbOa5g= + +Name: system/etc/bluetooth/iop_device_list.conf +SHA1-Digest: JU1lqbNnhuHR/03bQ5Vvx86lb6k= + +Name: system/lib/libdmt_vocalizer.so +SHA1-Digest: vjVTMrqUu81Kaukl/GMrZjn/1hs= + +Name: system/etc/security/cacerts/10531352.0 +SHA1-Digest: y9ENJVY4/0yK+jqASHt1m0dczag= + +Name: additions/fonts/veggieburger/Roboto-BoldItalic.ttf +SHA1-Digest: bVb8HaPeeRPVr6cZgHkN2065hbc= + +Name: system/lib/libOmxVdec.so +SHA1-Digest: io5j7ZLtF9P0aJWzRzGqtpDujQE= + +Name: system/customize/resource/quicklaunch_21403.xml +SHA1-Digest: nc95ItwlVDnuDZ4/RD5CGYA4zPk= + +Name: system/app/HTCMediaAutoUploadSetting.apk +SHA1-Digest: kVx6Rp1glXw3Wx3lQfm3GGRqRoA= + +Name: system/bin/wpscli_test_cmd +SHA1-Digest: LuqBakNoBSNkjWwif7/6yDzhCAs= + +Name: system/lib/libchromatix_vd6869_video_hdr.so +SHA1-Digest: lMZHdaaPvE3M7ZIfXYPEJ2FXe9E= + +Name: system/lib/soundfx/libaudiopreprocessing.so +SHA1-Digest: auqvCwBX1Dh5Wo/aATaks+HxL3c= + +Name: system/customize/resource/allapplication_228.xml +SHA1-Digest: LGWAL0yrs6N5euEueAgerd//nJQ= + +Name: system/bin/dhcpcd +SHA1-Digest: ayY0ds68jiqrivUM4p4IeuPHMZU= + +Name: data/app/com.melodis.midomiMusicIdentifier.freemium-1.apk +SHA1-Digest: 03W6zO2d43p8ezJvyRQKtbA4ge8= + +Name: system/bin/l2_profile_exchange +SHA1-Digest: NWfzn7y0GDSUc+oph3TziQiG+Og= + +Name: system/lib/libloc_adapter.so +SHA1-Digest: lO9tZT9hdp8h4nOoUjP0xnPfFUU= + +Name: system/fonts/AndroidClock_Highlight.ttf +SHA1-Digest: UpUMgtFG6S4ktliTHrzjzh2Sb2E= + +Name: system/framework/com.htc.android.home.res.apk +SHA1-Digest: 2Co+tF+Irj51LK6BRN8U/hLw0/c= + +Name: system/bin/rm +SHA1-Digest: TwRPPHXmTAdrr25J0pC4RHg3n3g= + +Name: system/lib/libgoogle_endpointer_jni.so +SHA1-Digest: K1wXzd9qotSo3gwAdcKZtlthrro= + +Name: system/lib/libchromatix_imx135_zsl.so +SHA1-Digest: 7PZhONTWhBzBM8+yOUsFyTEhKDE= + +Name: system/media/audio/alarms/Turquoise.mp3 +SHA1-Digest: yXv9K97/G/Gf7dMp//Y0/uWS3nw= + +Name: system/lib/libbt-aptx-4.1.1.so +SHA1-Digest: tMjeiercoBpSJw3w5zAcwBjhIpw= + +Name: system/framework/requestsync.jar +SHA1-Digest: yd+irPspht8oiF9OAUNXr1O9ntk= + +Name: system/etc/permissions/android.hardware.nfc.xml +SHA1-Digest: HUIRpkagOLqayoGvTHbaDrcSTdc= + +Name: system/lib/hw/nfc.m7.so +SHA1-Digest: sbVxluVaDcNN29fNcAbvadMHGaI= + +Name: system/customize/resource/wallpapers_a_00.jpg +SHA1-Digest: WEx2MBpoxHDIBSN82fWjODWPCqk= + +Name: system/media/zchgd/batt_90.rle +SHA1-Digest: OJYeVZJzbDUIf2TCdBFkH78fw6A= + +Name: system/app/Tag.apk +SHA1-Digest: UoW0O0UfJ0aha9uYVsSg0qJfHXU= + +Name: system/lib/libdvm.so +SHA1-Digest: Jq9m+FnHKzJQCEPEFvFgH/KGv9U= + +Name: system/customize/resource/bootanimation.zip +SHA1-Digest: mZlVPgBP/svEc+9ESCJSb4dzcIA= + +Name: system/bin/sh +SHA1-Digest: dOr7EkmJu1IGtF1CyJwHMi1BtE0= + +Name: system/lib/libmdnssd.so +SHA1-Digest: WU8T7eLcvQBhrk9d5grr+qlsIAo= + +Name: system/etc/security/cacerts/ee7cd6fb.0 +SHA1-Digest: bkvA4zNXQeEiBJAmk+PXsF/pHKY= + +Name: system/app/FlickrEngine.apk +SHA1-Digest: yj6M/h+XANr32jSBR3QSuu2ov40= + +Name: system/media/audio/ringtones/Aqua.mp3 +SHA1-Digest: AsnPEvmilTGXNDg12+pLKP54uUc= + +Name: system/app/LocationPicker.apk +SHA1-Digest: Q9qZMpl4Ddz2Bus1eaNQjxYxU+k= + +Name: system/customize/resource/quicklaunch_23802.xml +SHA1-Digest: ZfBmyM/+qEJ/mVwYxhQrTd955IQ= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-r0-ri30.4a-v24/full_model.bin +SHA1-Digest: CzQS2Q926UpzY1pj03Kjd1YbDNs= + +Name: additions/dormancy/dormancy.sh +SHA1-Digest: LXHsFAenVTzPhKD9rU3tUI345pQ= + +Name: system/app/HtcDLNAMiddleLayer.apk +SHA1-Digest: b8faWJZH8gqscn0+P/HGlALPvtM= + +Name: system/media/audio/notifications/Lime.mp3 +SHA1-Digest: T13WnRczblO5mxJb3YWGWobNJw0= + +Name: system/lib/libconfigdb.so +SHA1-Digest: KZvUX40Je/buKLGZm4os4HSvJok= + +Name: system/fonts/DroidSansHebrew-Regular.ttf +SHA1-Digest: vCyI5L4+fY5R89LvPsNi6paN1xU= + +Name: system/etc/security/cacerts/c8763593.0 +SHA1-Digest: +gdb++qnd0mWyTgp0LJzn5wDIrE= + +Name: system/bin/route +SHA1-Digest: gHUuofyUlDMflRogtpBAPKkz6E8= + +Name: system/usr/idc/qwerty.idc +SHA1-Digest: XSU+bbgHHEbEG/bF1WUYrQ9Nj/A= + +Name: system/lib/libhtcflag_native.so +SHA1-Digest: cz6J5RIvsJsiWHCkG75OQvgF1Pk= + +Name: system/media/audio/ui/Volume-2.flac +SHA1-Digest: AhcTvmDTuDYbtfj+QgyualjZBfs= + +Name: additions/fonts/helveticaneue/Roboto-Bold.ttf +SHA1-Digest: Q6EJJWzqQ1LxrkDVTYyleESzOZ4= + +Name: system/customize/resource/quicklaunch_28010.xml +SHA1-Digest: YHb55lJk2PHJTwfpy1RpraJ0XO4= + +Name: additions/gps/oceania/etc/gps.conf +SHA1-Digest: LsvW3krIB9w0I8BIB/dO6oQJR4g= + +Name: META-INF/com/google/android/aroma/themes/sense/titlebar.9.png +SHA1-Digest: HPInA6gixR/lSTi+REkYNBsjchI= + +Name: system/customize/resource/allapplication_65507.xml +SHA1-Digest: k4HYSzTI1A5BF/zD9Vf1F1GBa1c= + +Name: system/media/audio/notifications/Fuchsia.mp3 +SHA1-Digest: OW9DCX05PaSihqhfcz2tqHPnB88= + +Name: system/lib/libSkiaWarper.so +SHA1-Digest: LgpMolEgmz8ZSf1riteZgfBtzZ4= + +Name: system/media/weather/weather_sunny.mp4 +SHA1-Digest: 0tqYOKz0w4Zs7kRU1Mvz37WFD08= + +Name: system/framework/com.htc.android.bluetooth.jar +SHA1-Digest: /RY1AjaZYJlv8Ah73M/Cl98Imgw= + +Name: system/bin/mm-jpeg-dec-test +SHA1-Digest: 88vn/NOarwauvVOpGKBkP+9NxJc= + +Name: system/lib/libxt_native.so +SHA1-Digest: owK21ES5kW8gYpXm32Liht5Vj0A= + +Name: system/etc/security/cacerts/1dcd6f4c.0 +SHA1-Digest: J/9p1bSc/vj7DXamP+uHmvUOn2c= + +Name: system/etc/security/cacerts/9772ca32.0 +SHA1-Digest: LX2TMuCYXRh8QFOPADSkAjvHbuE= + +Name: system/media/weather/weather_cloudy_day.mp4 +SHA1-Digest: R/knv9o+P3UQP6hZIPgDaCJ71Sk= + +Name: data/app/com.google.android.street-1.apk +SHA1-Digest: /hv1zxVHNeDYmqgJA2ujE0vs5YI= + +Name: system/app/PhaseBeam.apk +SHA1-Digest: tG0+E849amQzmhBrycg7Ib21dac= + +Name: system/etc/security/cacerts/5e4e69e7.0 +SHA1-Digest: OPYnMzF7mxzqxH56G6+9Io0+wns= + +Name: system/etc/firmware/hcheck.b03 +SHA1-Digest: GPRM/l2NMcKylFH8+zsgdzxLQmY= + +Name: system/lib/libqmi_encdec.so +SHA1-Digest: r8S8/jdbJAmqizRKAMD2mD+u8Ac= + +Name: system/lib/libSR_AudioIn.so +SHA1-Digest: ZvAWqejA31cQtCSogywkwFfe/eY= + +Name: system/customize/resource/allapplication_24201.xml +SHA1-Digest: gDpuLVefExqtoLsKIuY91R8sRB8= + +Name: system/fonts/DroidSerif-Regular.ttf +SHA1-Digest: rdDAMVoPkeYHrAGCh/yUOvTm5UE= + +Name: META-INF/com/google/android/aroma/themes/sense/dialog.9.png +SHA1-Digest: mnNNn3dIEnvvW/cpB6vQjin58Cg= + +Name: system/etc/firmware/hcheck.b02 +SHA1-Digest: /jCgwrCADQNqwKNzD0ySVE3GAv8= + +Name: system/etc/firmware/hcheck.b01 +SHA1-Digest: nKHb3UysKozicEsRl4v+laz5BRs= + +Name: system/etc/firmware/hcheck.b00 +SHA1-Digest: cu5aebFBYncQ4f7iTeS4RmbBEKo= + +Name: system/media/weather/weather_l_thunderstorm_day.mp4 +SHA1-Digest: dbCxlAvlJPz/K2waolaqqKzC9EU= + +Name: system/etc/vold.fstab +SHA1-Digest: Y8bxVdlq3B6hbvq12aPX8yJfteo= + +Name: system/bin/ip6tables +SHA1-Digest: wCceVLKMhMq0g+j04fd8iuIMgBg= + +Name: system/bin/system_server +SHA1-Digest: SIkU/oY+tC8xUZZvWR+kR4NE2bY= + +Name: system/media/audio/ringtones/Navy.mp3 +SHA1-Digest: F4IW4r5WScTfGcpDbM0cWkeYpF0= + +Name: system/lib/libmmcamera_wavelet_lib.so +SHA1-Digest: SMya68qET4/Cln4UBEg2MPBpTEI= + +Name: system/media/audio/alarms/Steel.mp3 +SHA1-Digest: m1RXbH+1GjBi8ZPNyxzanb3K8Fs= + +Name: system/customize/resource/quicklaunch_23420.xml +SHA1-Digest: SVCjHpVqLLLiqMWrxac5NWOnOCw= + +Name: system/usr/share/partials/partials_H.dat +SHA1-Digest: lG+VGfsDTmtHFA9oUBbtS7QbWRc= + +Name: system/etc/tfa/playback.preset +SHA1-Digest: IKLscUobhcgfw/DnpdGEmglYOJA= + +Name: system/media/weather/weather_partly_cloud_night.mp4 +SHA1-Digest: 01Rk4i3kp8kjV4SvPAY+YA4QPsM= + +Name: system/media/audio/ringtones/Laquer.mp3 +SHA1-Digest: 2QFp9EPNR/v9rnqZKk7XDbTnhJA= + +Name: system/bin/sendevent +SHA1-Digest: rYRPw4b9e4gkkTsC66H3ztOJdNE= + +Name: system/etc/security/cacerts/08aef7bb.0 +SHA1-Digest: XVcxHM5N/xsTnkuy9vaaWCBrlTw= + +Name: system/bin/wl +SHA1-Digest: OQdlUrtmkgnphJ15J/s15hok3Go= + +Name: system/app/Settings.apk +SHA1-Digest: 4By+MceBBK7URTHYe79jqQ0TB6w= + +Name: system/lib/libstagefright_soft_mp3dec.so +SHA1-Digest: UH6hjIceVIFxd/6MoEPQwo1uKx0= + +Name: system/etc/firmware/fw_bcm4335_p2p_b0.bin +SHA1-Digest: l5lP68M201qLReKuCKPa246GGo8= + +Name: system/lib/libttspico.so +SHA1-Digest: 1yH0Ide+mM9FHhNxKzPXFgJZ9l4= + +Name: system/lib/libBeautyChat.so +SHA1-Digest: IoFMDKIokKPmrpwaUK+72+vpIn0= + +Name: system/customize/resource/allapplication_24801.xml +SHA1-Digest: fVhSVQFv4WcinppHBPKMTbSeiWs= + +Name: system/lib/libnfc.so +SHA1-Digest: xrLIk5FrAqy11mA7QYZF1j+UedE= + +Name: system/etc/security/cacerts/87753b0d.0 +SHA1-Digest: pDoFkt0ow4oMrnwoJ8V53XXw608= + +Name: system/etc/security/cacerts/1d657651.0 +SHA1-Digest: Nnt+JruWEZcGnA8niaYbmGxn1f0= + +Name: system/app/HtcPowerStripWidget.apk +SHA1-Digest: hGjQX9QGid+AZ78zfKtri9tAZqA= + +Name: system/usr/keylayout/Vendor_046d_Product_c532.kl +SHA1-Digest: uLc7pyyR3HK7SZbqxNhxTnBjvQU= + +Name: system/bin/climax +SHA1-Digest: M+KYGET+N+PWthN8exobPmK5StY= + +Name: system/lib/libc2d2_z180.so +SHA1-Digest: d7o/IDYyC0q+FpGrYqkNCiXeLzM= + +Name: system/media/audio/notifications/Magenta.mp3 +SHA1-Digest: WN6F04usQrI7mkff/OLOW8URHMs= + +Name: system/app/WorldClock.apk +SHA1-Digest: wy0fN+853RdFGRz9wxEJ1aR/vt4= + +Name: system/lib/libqmi_client_qmux.so +SHA1-Digest: Ft3VeuRXsfWmrqBVyCCl/xirwT0= + +Name: system/fonts/AndroidClock.ttf +SHA1-Digest: SwKcMGDzVbbA3ny3+tJbieABH4s= + +Name: system/lib/libchromatix_s5k3h2yx_hfr.so +SHA1-Digest: 6OLyZ8USV8Ka9y1FXYwA1sZdVao= + +Name: system/etc/security/cacerts/76579174.0 +SHA1-Digest: pzzaX91VWO/hKUAL6vLTr/M9//8= + +Name: system/etc/security/cacerts/48478734.0 +SHA1-Digest: DD+Jf/xyWUb9vB7awEI1t/6+AM0= + +Name: system/lib/libvorbisidec.so +SHA1-Digest: HpuJ4g4HT01NWdMVqzVxB/BG7o8= + +Name: system/app/HtcNotesProvider.apk +SHA1-Digest: uNo+ac+iwWnnguLi4x/CU1DTZzI= + +Name: system/customize/resource/allapplication_23407.xml +SHA1-Digest: WJtJykoC0urdDyYlaPffojNy6+w= + +Name: system/media/audio/ringtones/Cyan.mp3 +SHA1-Digest: jTlup3iRS7gYouSkQRgqkAUArKY= + +Name: system/bin/ionice +SHA1-Digest: 3CEFbc3lIVHpriR9iowFnWHIbqg= + +Name: system/media/weather/weather_l_windy_day.mp4 +SHA1-Digest: py1l/yQtfoP6yxIc/tloV1whcaw= + +Name: system/lib/soundfx/libdownmix.so +SHA1-Digest: V3bmPjOo3C1gl+jh6aAtRM2CewM= + +Name: system/etc/image_ibeats_v2.bin +SHA1-Digest: yrtDyORccn24flPqVUDEy+rsvYY= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x_Fusion3_DMIC +SHA1-Digest: jgdmdCfgWk5QKWHJblRSS9raHf0= + +Name: system/bin/pand +SHA1-Digest: HVUXS6xM4bfif1v0xYhQW9fyO50= + +Name: system/usr/keychars/Virtual.kcm +SHA1-Digest: 9uQOx02FYajtTIKVRSyjp4oMPWM= + +Name: system/lib/libbcc.so +SHA1-Digest: GDX6MwnQkH0z0LOmNI+d+NraXfc= + +Name: system/lib/libchromatix_ov8838_hdr.so +SHA1-Digest: 1jDyx7S1a+7DSbRjlHpSei7RJdI= + +Name: system/lib/hw/alsa.msm8960.so +SHA1-Digest: ATyiDD+FadGgmF4Vv+ZCUUllaW8= + +Name: system/customize/resource/allapplication_24008.xml +SHA1-Digest: dXKTNsL1lKpvIevUWul7dSkEVwg= + +Name: system/lib/libstdc++.so +SHA1-Digest: MRzKLx3PiQUa3JWLShNO/ktKHO0= + +Name: system/lib/libtcpfinaggr.so +SHA1-Digest: fDqEE9zfOvk2PGff2lLTnfZL0Fk= + +Name: system/lib/hw/camera.msm8960.so +SHA1-Digest: kWPMYJS6eRFndidzp9ibeEzbYwQ= + +Name: system/bin/aplay +SHA1-Digest: BYJh5AgvFptF0WaN42BM1uFmask= + +Name: system/lib/libcameraservice.so +SHA1-Digest: iMFOT/cAbYyIcoan7uvFgFQngTY= + +Name: additions/fonts/segoewp/Roboto-BoldItalic.ttf +SHA1-Digest: V4A/5csAB03WjIUXgAvi0hHrIX8= + +Name: system/media/audio/notifications/Azure.mp3 +SHA1-Digest: LtqOknf1tpoKi7Xa1eG6lfM5xJI= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_sel.png +SHA1-Digest: seBUwREyFfHhc3t9FaUpWRc8v1M= + +Name: system/lib/libchromatix_ar0260_default_video.so +SHA1-Digest: Y2gtGxt6C8R2QWj2FtJr+Pi5EpU= + +Name: system/app/HtcSpeakNGF.apk +SHA1-Digest: hdlb3jzWb/V134gl6u8faP1HAXQ= + +Name: system/usr/share/zoneinfo/zoneinfo.dat +SHA1-Digest: 3bNLXP6MzuugMmpyUxw5kRipvbc= + +Name: system/media/audio/notifications/Vermillion.mp3 +SHA1-Digest: qCAiIzq5nY66wEKjE8pbVv5y8FI= + +Name: system/app/MyTask.apk +SHA1-Digest: IbgsXO31oGCEnV1cFg7NOMcr/G0= + +Name: META-INF/com/google/android/aroma/themes/sense/cb.png +SHA1-Digest: otH0B2KK+X+pBC/lOuajvnTDWwM= + +Name: system/framework/uiautomator.jar +SHA1-Digest: Sp1TQcUsfvSaDwUZU5VALZINlfA= + +Name: system/lib/libhardware.so +SHA1-Digest: 6+JECohsz82ljXyp2pcaOFfx0vw= + +Name: additions/fonts/helveticaneue/Roboto-Italic.ttf +SHA1-Digest: GHaEjf4U2l+YTb2u0BtcTx/G6a4= + +Name: system/lib/libpphwr.so +SHA1-Digest: s3W0b4A2yBXiVeXQcCh803s2HhU= + +Name: system/customize/resource/downanimation.zip +SHA1-Digest: iC4e8Xngli3tCBYzP20GwIFiMIE= + +Name: system/lib/libc.so +SHA1-Digest: 5/ugqLeBLFWR2G3vk4s//RjDcDU= + +Name: system/etc/security/cacerts/60f083f8.0 +SHA1-Digest: aj1D0xqgrp24x4HTQIeDYqwRDDI= + +Name: system/etc/permissions/com.htc.software.market.xml +SHA1-Digest: AaDdllNGEOMXv8mIV7BCFuJYTGA= + +Name: system/lib/libext2_profile.so +SHA1-Digest: cy63T6xVxSx/WV4qP2BznWzZaxk= + +Name: system/lib/libgui.so +SHA1-Digest: rf7ylid2migXIESNiOTbwLHJ7hQ= + +Name: system/bin/qseecomd +SHA1-Digest: C0cJn/J6WfISwCkBSqZy/zNNuV4= + +Name: system/media/zchgd/charging_08.rle +SHA1-Digest: gX0zh+1tUH+r3U17Zqjqtn3SgnM= + +Name: system/usr/idc/projector_input.idc +SHA1-Digest: PRYvjiPekMTt2IIrX0QRUkERcd0= + +Name: system/app/WeatherProvider.apk +SHA1-Digest: 92S7vGK/u5jGWsJyDgdJfF3LhFI= + +Name: system/bin/fusermount +SHA1-Digest: iCiRvrTRlDUM0mZmmSPpakL9IaI= + +Name: system/media/audio/notifications/Purple.mp3 +SHA1-Digest: jul63XvZnAFXJqnH36crUYmyVYk= + +Name: system/lib/libinput.so +SHA1-Digest: zNa5EYdFR00GSK70DLglDtUJmUk= + +Name: system/lib/libgoogle_recognizer_jni.so +SHA1-Digest: 7ri4BbwNSD99TrYEyU/7PrsKklE= + +Name: system/bin/dmesg +SHA1-Digest: gsZHB8KXidrgYtH/MQ/0YNhbeKw= + +Name: system/customize/resource/allapplication.xml +SHA1-Digest: 5MLlgce+wTFngYWMm5cfSE58vc8= + +Name: META-INF/com/google/android/aroma/icons/welcome.png +SHA1-Digest: fYixHffIAobmHhXPb9KlqbdyR40= + +Name: system/media/audio/notifications/Ruby.mp3 +SHA1-Digest: T5LEoKwV4e4XdYh0LdIUh5yib3w= + +Name: system/etc/security/cacerts/418595b9.0 +SHA1-Digest: EurtZmuo2p5AcFiyeJVA1GXOrHs= + +Name: system/app/HtcCupd.apk +SHA1-Digest: 7qhwHEVM8jVHkJBILBquXhM/8nI= + +Name: system/fonts/DroidKufi-Bold.ttf +SHA1-Digest: rGF1p7Z7NPJVWgYz8gl5g94DTj4= + +Name: system/app/HTC_CIR.apk +SHA1-Digest: bpmMVuRAf2Sfv/W9fM6oW6lDEF8= + +Name: system/etc/bluetooth/blacklist.conf +SHA1-Digest: /NVpapHNK5NICIClWd0zLSqpX2Y= + +Name: system/usr/srec/en-US/symbols +SHA1-Digest: X3eWxk+MQsrhAd6FOn03af84C5I= + +Name: system/media/GPU/CurveCold.bmp +SHA1-Digest: sOGl7dhD5vnH9hZn1Iu2kJCavOI= + +Name: system/etc/soundimage/srsfx_trumedia_voice.cfg +SHA1-Digest: RndG81JIozmd3D7uioPQ1PeU48g= + +Name: system/etc/firmware/vidc.mdt +SHA1-Digest: OGFwf5U2qAHXKLNEGCiRkvCCIIw= + +Name: system/lib/libmedia_jni.so +SHA1-Digest: tui0VO7QMqC/nlHOcyHynhmPscs= + +Name: system/bin/applypatch +SHA1-Digest: Rmm3Q5BMoWXdCjbzKx8AXjI98rw= + +Name: system/app/IMEXT9BahasaMalaysia.apk +SHA1-Digest: bBud4bit6ebA3w+gNYQHTNgHv6s= + +Name: system/etc/mkshrc +SHA1-Digest: AXWBhFfy48EBsMirawoVQJ6RzHI= + +Name: system/lib/libpower.so +SHA1-Digest: 1Z0pFdkihuPI4sCZ+IEIZJuilZI= + +Name: system/etc/security/cacerts/d8274e24.0 +SHA1-Digest: ggueFUwteH2USaNRFI+bu48RY2w= + +Name: system/lib/libimu.so +SHA1-Digest: UXOupjyuBnXgO0YNUdQWQ/Q8/1k= + +Name: system/etc/permissions/com.google.android.maps.xml +SHA1-Digest: QaPNB5FUfwkZ5T3fG1bXJpF8pNY= + +Name: system/app/HtcWeatherClockWidget.apk +SHA1-Digest: RQcrUieRNrK31JbElWsYLwEOxEI= + +Name: system/lib/libsonivox.so +SHA1-Digest: vR1wuMiAvyK7BfiuMjTQC15hwV4= + +Name: system/lib/libstagefright.so +SHA1-Digest: fYSus60fQ+jDy9cHZlPsDoeXths= + +Name: system/etc/permissions/android.hardware.sensor.gyroscope.xml +SHA1-Digest: DhtVHxHAeMpMhNawakMGfQRTkR0= + +Name: system/app/IMEXT9Dutch.apk +SHA1-Digest: 5y4cahExfFBYX/NWbxbNT9kyhA4= + +Name: system/usr/srec/en-US/dict +SHA1-Digest: AXBx0Bz53vO1Keed7lCO425AmBc= + +Name: system/customize/resource/quicklaunch_21406.xml +SHA1-Digest: AWjqtVcxi/ZNuY8yZJGc1vx6dtc= + +Name: system/media/audio/alarms/Citrine.mp3 +SHA1-Digest: 8jtsUdGmvNKkldvykvSN/Bk61gI= + +Name: system/media/audio/notifications/Smoke.mp3 +SHA1-Digest: Ot8pg8/oUoLUr+TS9UfYyTEOLgs= + +Name: system/etc/security/cacerts/d777342d.0 +SHA1-Digest: KqcaEKbpbxK/ZskNhdSlNwqFbY4= + +Name: system/media/audio/ringtones/Orange.mp3 +SHA1-Digest: /Y+mbPEthQ3IE17N0oU/mcHIrYE= + +Name: system/lib/libchromatix_s5k6a1gx_zsl.so +SHA1-Digest: 8iNeuMu9oxBFxXYmBXDrcTFihDY= + +Name: system/bin/venc-widi +SHA1-Digest: uTYNS02YLDr9njD97va6rihcWT0= + +Name: system/media/weather/weather_l_sunny.mp4 +SHA1-Digest: pmi42pNKvDy+mDpFZfhUIuHNEog= + +Name: system/etc/security/cacerts/84cba82f.0 +SHA1-Digest: RbfVG4qh9BQlLNlkl+9eQ/iwr90= + +Name: system/lib/libchromatix_ar0260_preview.so +SHA1-Digest: T1Qi4QJHsjgavJNKTVP/XWmcTnc= + +Name: system/lib/libwfdcommonutils.so +SHA1-Digest: vwl5C20x61qpS14Lh6Rkb1y4MT8= + +Name: system/etc/security/cacerts/399e7759.0 +SHA1-Digest: C7nniIwXMNqhQza0pF0/S/7ALuk= + +Name: system/framework/am.jar +SHA1-Digest: byLKmUjp4MtYwoAR2h6mAPI8OJ8= + +Name: system/media/audio/notifications/Rose.mp3 +SHA1-Digest: z3QuX0C2fxcjT25K8X1GKv8RkGg= + +Name: system/lib/libmedia_native.so +SHA1-Digest: jx/9VAk+0ec9OQjl4AFvAr6Cdtw= + +Name: system/app/KeyChain.apk +SHA1-Digest: 3vA6JhjDV6r9I7mhrIpjj2zHD7c= + +Name: system/etc/security/cacerts/c33a80d4.0 +SHA1-Digest: j+oS/ELhscXEs8jsZgH1YZdo0Yk= + +Name: system/lib/librs_jni.so +SHA1-Digest: yCROPfwCRQhLlVbWpXquW4g+Mrw= + +Name: system/media/audio/ringtones/Blue.mp3 +SHA1-Digest: Ba1ddb3TO+29FawDxv5NpCSvqEM= + +Name: system/media/audio/notifications/Cobalt.mp3 +SHA1-Digest: v0oCG6zJcTTYmjrddpJzJlTQGdo= + +Name: system/etc/security/cacerts/bc3f2570.0 +SHA1-Digest: Djn1z26jqNrHK/cY3pNLU/I9bN8= + +Name: system/bin/mm-qcamera-app +SHA1-Digest: Gj0TXVvCGzCDhzvk0FooEopa7bQ= + +Name: system/bin/asound +SHA1-Digest: zOADLfJdjHHyBtVTSKf+vAheGxc= + +Name: system/lib/libwt6docxrdr.so +SHA1-Digest: WcgoibecQbe8Luu5d+4xamDqBE4= + +Name: system/lib/libdsutils.so +SHA1-Digest: MPpPbpY6S4WtL8zUlz9iOa+dIYI= + +Name: system/lib/libgetzip.so +SHA1-Digest: g9lq/P9WQh0gDlTdNpuLRy0T6vQ= + +Name: system/app/IMEXT9Lithuanian.apk +SHA1-Digest: POole4XX0AfwFzvmarPql0s2Aw4= + +Name: system/lib/libmode10.so +SHA1-Digest: Pn2nLBJpq+o2Qf6TEYRGrZYJBhU= + +Name: system/media/weather/weather_l_fog_day.mp4 +SHA1-Digest: yOAPNP78Vlio7k7Ib/PybPuIZqU= + +Name: system/lib/libsuspend.so +SHA1-Digest: JEobXXx2+4iLklfHPGt82EnSOs0= + +Name: system/lib/libzeroeditorplayer.so +SHA1-Digest: 9lDAbFLanipmj0Mu/mwVPhRyucQ= + +Name: system/bin/run-as +SHA1-Digest: vv0XB9PuCuGrYGXPDZzrSTR0XcY= + +Name: system/app/NewsPlugin.apk +SHA1-Digest: N4kXYQ2wOOnYXGMivnQuWww78qA= + +Name: system/etc/security/cacerts/73da149b.0 +SHA1-Digest: 7cmlEdkiJbcZT7yljZ32CLuOb+w= + +Name: system/customize/resource/rp_pct.png +SHA1-Digest: Be1I75CUYHlN5Ls2n607uIxRVig= + +Name: system/customize/resource/rp_ce_0678_i.png +SHA1-Digest: XipoQXhxul8pBJuXY9trmd6VPV0= + +Name: system/usr/srec/config/en.us/models/generic8_m.swimdl +SHA1-Digest: XJZq9k/wtjPuUrP1MbJNulTtfGM= + +Name: system/framework/svc.jar +SHA1-Digest: YrodjHp0I5+Fifs6LgPSwZZ8Ng0= + +Name: system/fonts/DroidSerif-Italic.ttf +SHA1-Digest: aCx+e4yyj8kOYcR5otukddlLoMo= + +Name: system/framework/HTCDev.jar +SHA1-Digest: j1L3wgS1mh6iHbKNu3EP36rouD8= + +Name: system/etc/calibration_EMEA +SHA1-Digest: uRTWUBer/lqKeJ2gFIzBtOrNdmk= + +Name: system/etc/bluetooth/a2dp_avrcp.conf +SHA1-Digest: NlkTOsv3ZiP4svSRZAIvwRpWqw8= + +Name: system/customize/resource/rp_ce_0682.png +SHA1-Digest: uIRmYCqvz2wPoE28lQegeDXvcP8= + +Name: system/lib/libbluetooth.so +SHA1-Digest: mai1lv4Zn46PnVLqidoAu/uw2E8= + +Name: additions/fonts/sonysketchef/Roboto-Regular.ttf +SHA1-Digest: lDROUZu6Oz9zcaSfVrBtY95SpJY= + +Name: system/etc/snd_soc_msm/snd_soc_msm +SHA1-Digest: bBeGPT2by8zbsjZI+It3dAOCpas= + +Name: system/customize/resource/quicklaunch_27205.xml +SHA1-Digest: VBKE0GatLtLCs1qmDsYCJdJnWwE= + +Name: system/etc/security/cacerts/d59297b8.0 +SHA1-Digest: TqrmlyeuzKiljmAPGWKtMKLCpAA= + +Name: system/lib/libqmi_csi.so +SHA1-Digest: bwq87eoeJxBEkLccueg99mXRkqM= + +Name: system/etc/permissions/android.hardware.wifi.direct.xml +SHA1-Digest: iPmbEsXxaKyWbEdVZcAxkacBUr0= + +Name: system/media/audio/ringtones/Khaki.mp3 +SHA1-Digest: irpirz//OwRY39BxoC444KAs4SQ= + +Name: system/app/HTC_IME.apk +SHA1-Digest: yRnGh/ab3PMpQm6R2aUZ5/k1Mc8= + +Name: META-INF/com/google/android/aroma/icons/agreement.png +SHA1-Digest: ibAcfqhbZ3H32/KMQIip/od/qkA= + +Name: system/etc/security/cacerts/0e82f83a.0 +SHA1-Digest: xEq3keiHRd9SnhRy+UqNOh/kDrs= + +Name: system/customize/resource/allapplication_26803.xml +SHA1-Digest: 4p4vJdqyBDLtVB8AXL+U0+mgHw4= + +Name: system/customize/resource/quicklaunch_65507.xml +SHA1-Digest: +bkSDL4ocUaADLb4Y74kNP3xafk= + +Name: system/app/SettingsProvider.apk +SHA1-Digest: Ldf/gSc1L0e8QIlUGUoTQWxpx1U= + +Name: system/bin/wipe +SHA1-Digest: Mz+bmG1S9V6Hgz8Pq5XzXwZh7hA= + +Name: system/etc/tfa/fm_l.eq +SHA1-Digest: JHHxqTumKfmNAWK7jGQNakAWYK8= + +Name: system/media/audio/alarms/Cinnabar.mp3 +SHA1-Digest: h4qo4N2u1M2jSktZfSr3rku2aXQ= + +Name: system/lib/libdmt_sse.so +SHA1-Digest: jmoMFkLJX9bKZarT2DIVh0XEdTg= + +Name: system/etc/security/cacerts/d537fba6.0 +SHA1-Digest: 4R+LXj2wGe4iRwjgn1A1cvhf/n8= + +Name: system/app/HtcImageWallpaper.apk +SHA1-Digest: UDJFr5Wz/efm0oL83cxZnDOA+CE= + +Name: system/usr/share/partials/partials_H_rr.csv +SHA1-Digest: SdVrP6Qyuj5Dy8HsjZiLNVbebsA= + +Name: system/lib/libmpl_jni.so +SHA1-Digest: j8OjRonuiSFuGBu7F387ZaHqooA= + +Name: system/lib/libnativehelper.so +SHA1-Digest: hT8AQKpX6iiypkm+vpad+bkeGTg= + +Name: system/customize/resource/allapplication_21401.xml +SHA1-Digest: YNkcLskRkz8fXkJ7AhCvFVlB5lE= + +Name: system/bin/netcfg +SHA1-Digest: QgnxLUFalIH7f6liBF7mX0S9piE= + +Name: system/bin/hcheck +SHA1-Digest: sUF0yNcHBoACcQOXnbHvusvHTdM= + +Name: system/etc/security/cacerts/0d188d89.0 +SHA1-Digest: FzoOvFUf3dNV/AEJ20wcfK1JUGk= + +Name: system/app/IMEXT9Spanish.apk +SHA1-Digest: PGkzNTDFl+iww658ib3ik8aRdzA= + +Name: system/etc/firmware/vidc_1080p.fw +SHA1-Digest: Z6gbTAYS4ObPGq6kO0CXW8AWNPM= + +Name: system/lib/libwt6xlsxrdr.so +SHA1-Digest: jsrRzt7/6lWMOotgA3BGO+ZW+O8= + +Name: system/etc/init.d/98permissions +SHA1-Digest: w2PPeuPCimdnbmp45rvkfvox2L8= + +Name: system/app/Picasa_GLRplugin.apk +SHA1-Digest: ICWBGz+hPhklXB+JEyAgOLXRtyc= + +Name: system/usr/idc/qwerty2.idc +SHA1-Digest: CxeFAjbR656/zttheEGexLMYZio= + +Name: system/bin/efsks +SHA1-Digest: gOktRfLkIJlrVKqwmseQ90MkpJY= + +Name: system/etc/res_ctrl.conf +SHA1-Digest: YgH4bLCC4AyfYf8e6z7u4dse85U= + +Name: system/bin/tune2fs +SHA1-Digest: NVUF8wExJBsGi7oaTsCuiumbJRY= + +Name: system/etc/libdvhwrc.so +SHA1-Digest: /tfgt+zY6FvGBl/HqCTnm+F4+FI= + +Name: system/lib/libaddrsdetection.so +SHA1-Digest: 9nn+AmEARA9Eu8vEZX/J7SXYJh8= + +Name: system/media/audio/ringtones/Coral.mp3 +SHA1-Digest: LIo7TXUlYvYoT+nwasC2AnuCT+0= + +Name: system/etc/tfa/voip_l.eq +SHA1-Digest: M7bmyz3Ii2FYKS1hAaiNtS6n/bs= + +Name: system/lib/libchromatix_s5k6a2ya_hfr.so +SHA1-Digest: Qi4mbSlFGxKnLE1rDIoYaM7M0y8= + +Name: system/lib/libwsp.so +SHA1-Digest: nGPk65m0G4LxjDZLVTGuGSyDUQc= + +Name: system/fonts/RobotoCondensed-Italic.ttf +SHA1-Digest: HjOk01XwQ2PScIy0Q1HS5ekk5+E= + +Name: system/bin/renice +SHA1-Digest: bg47hJEc+ukaAoM4k+cF5DH5ALw= + +Name: system/app/idlescreen_shortcut.apk +SHA1-Digest: 0lRa3WO6SjIMeS6EfU9lUHdbpmY= + +Name: system/lib/soundfx/libsrsfx.so +SHA1-Digest: XLqFNtEFIQKGKWIN2iwz313MZRI= + +Name: system/usr/srec/en-US/normalizer +SHA1-Digest: 4iCTB9icELI1BJdqCXr2ZLXF120= + +Name: system/app/IMEXT9Hungarian.apk +SHA1-Digest: yBiR0qpWEhXzeMz0EABf3q0HH6U= + +Name: system/app/SystemUI.apk +SHA1-Digest: mfZJIjPzt7T7pT3K+vLBZxANuIQ= + +Name: META-INF/com/google/android/aroma/themes/sense/theme.prop +SHA1-Digest: uzGkY17JqmPF0PoHloc5zTYL0QE= + +Name: system/media/audio/notifications/Licorice.mp3 +SHA1-Digest: r4wi6TAIdsjIK2FCsd+99gujT6s= + +Name: system/customize/resource/allapplication_20404.xml +SHA1-Digest: IyQuoTej816CiJ0liXtRhn+j7V0= + +Name: system/lib/libchromatix_imx135_hfr.so +SHA1-Digest: 8CtXXsOn/M82JZXnmze8PYG4umM= + +Name: additions/fonts/veggieburger/Roboto-Italic.ttf +SHA1-Digest: 95gI0tiQ4JO/vec8ZA3GT+z7rmQ= + +Name: system/media/audio/ringtones/Sapphire.mp3 +SHA1-Digest: lJDiFVTinX0KYFEgVXw0l8vf0+c= + +Name: system/bin/cat +SHA1-Digest: KUyhy0ZoKz1cXTDbUegpNJLva7g= + +Name: system/framework/content.jar +SHA1-Digest: Bso+OnPUeV1AyeJJEtjD2asbm9Y= + +Name: system/etc/priorityd.sh +SHA1-Digest: 17dY6yKME3SLQaOsOwaEtVfLYQQ= + +Name: system/framework/com.google.android.media.effects.jar +SHA1-Digest: PD7Al1WUenLQfEEGairnxJHGACE= + +Name: system/customize/resource/quicklaunch_22201.xml +SHA1-Digest: ZJL7LaozR6FK6YpLu+7VmR3glvo= + +Name: META-INF/com/google/android/aroma/themes/sense/select_push.9.png +SHA1-Digest: 5S4mWeE8z3nPBdjxWfl0viqHtJI= + +Name: system/lib/libacc.so +SHA1-Digest: 7VLlxLV3zqDXV5lRW2F7Z3O88Eg= + +Name: system/lib/libmorpho_image_stitcher3.so +SHA1-Digest: RmpA5hxwOyGEMNM6h4CFt8knHSA= + +Name: system/framework/framework.jar +SHA1-Digest: wSwXw+JFG6qDx2WvmlSyELwa0OQ= + +Name: system/etc/security/FotaSign_PubKey.der +SHA1-Digest: N/aZKtIVna/mcnhl99ssySqMBFE= + +Name: system/bin/mount +SHA1-Digest: fKvsg1cW9ujWQMdkW0Q22qRJSzY= + +Name: system/lib/libaricentomxplugin.so +SHA1-Digest: xhXHHfYJHW9g2dsUQ/EKQw7mS8M= + +Name: system/media/audio/ringtones/Neon.mp3 +SHA1-Digest: VepX2fFmM/l3JxoOtzsFGqHhbQg= + +Name: system/etc/security/cacerts/1dbdda5b.0 +SHA1-Digest: Z8P5gTMftWn5WsxGoaWi5Ewsbjc= + +Name: system/lib/libexif_jni.so +SHA1-Digest: IROWgTVDHzja2IkF/V4Q9osCdxo= + +Name: system/customize/resource/wallpapers_c_02.jpg +SHA1-Digest: zOXPka/BgqekYZ0MX2Sa/KHCmsI= + +Name: system/etc/firmware/a225_pfp.fw +SHA1-Digest: JXnk+hLjb41rBPpvRTxNe6dba2Q= + +Name: system/app/IdleScreen_Music.apk +SHA1-Digest: PMGAk0lRV2hm4JjL6N+FsmyGrsQ= + +Name: system/lib/libqdi.so +SHA1-Digest: bxzEhxTMmtZj9MV9bmT/N4+l140= + +Name: system/bin/sync +SHA1-Digest: jVmFV1ds4PqXMCix5z3OId8dJpY= + +Name: system/etc/gps.conf +SHA1-Digest: RHhyPtQaWA3yAooxUs1CdQZe/6c= + +Name: system/customize/resource/allapplication_21419.xml +SHA1-Digest: 2of0589sAC1LJ5V3toTuB301Ksk= + +Name: system/bin/dalvikvm +SHA1-Digest: 6M2CFaMsKqhuLaCcVd/AJxxcQcI= + +Name: system/app/HtcRingtoneTrimmer.apk +SHA1-Digest: b4HD+gW4D9aAGQmiDKqPBQ1taTM= + +Name: system/etc/security/cacerts/75680d2e.0 +SHA1-Digest: zmqh8h2o8Hm6tDQfcCh8iNtUuUc= + +Name: system/lib/libxml.so +SHA1-Digest: HQv7lVu8DuelrRb84vNnioEj0EI= + +Name: system/lib/libdivxdrmdecrypt.so +SHA1-Digest: GHc4stKNP7L0nhxr4wdmMwcmiwQ= + +Name: system/lib/libvideoeditor_videofilters.so +SHA1-Digest: GZHqM7U5znS9v5TpC1UWwKikTCw= + +Name: system/media/weather/weather_rain_night.mp4 +SHA1-Digest: bqegZe3VgA1xXQRZtBSbaWCpLmM= + +Name: system/customize/resource/quicklaunch_20210.xml +SHA1-Digest: tVje1ibdXVTB6aTS4zKEIb0joaA= + +Name: system/lib/libsnfc.so +SHA1-Digest: CC9aUhMiwuQyPsQ8yAsUJAf7Dv0= + +Name: system/lib/libmemalloc.so +SHA1-Digest: mn2ZEle3ujP7WH6J8tcVZiYbZXA= + +Name: system/media/audio/notifications/Slate.mp3 +SHA1-Digest: u8uvKRqmxN/UDFzj35oqdPvbcAI= + +Name: system/app/InputDevices.apk +SHA1-Digest: NEOxB65++3xfKWgZ8ngLoSMwn5U= + +Name: system/app/HtcSyncWidget.apk +SHA1-Digest: 7bNxWqaGgG/6Ig+YwXlPpNtk8XI= + +Name: system/fonts/DroidSerif-Bold.ttf +SHA1-Digest: MlOUKslixMSZJEtMW5rgRjkfMq4= + +Name: additions/openvpn/xbin/openvpn +SHA1-Digest: rCpMAOJ1M64vjMl+LyCTHlv1KfY= + +Name: system/usr/keylayout/keypad_8960.kl +SHA1-Digest: ddkS1H1fJkiTLkCpbwTO7LC3EdA= + +Name: system/bin/mm-jps-enc-test +SHA1-Digest: DsBNQhUTyacmHKd41cteMDdN0iM= + +Name: system/framework/bmgr.jar +SHA1-Digest: Bdlc18itOeXFgVUJeGoaFmygzSw= + +Name: system/lib/libchromatix_imx175_hfr.so +SHA1-Digest: 4RkjsVnPLFVG/+9TwdgruNcJI/k= + +Name: system/customize/resource/quicklaunch_23407.xml +SHA1-Digest: 7kH4nPdwTWCnWKlCFKXF3idZkfs= + +Name: system/etc/security/cacerts/7672ac4b.0 +SHA1-Digest: ZvDdi25zaHa3+F+HBUDiaEjzgrA= + +Name: system/etc/security/cacerts/00673b5b.0 +SHA1-Digest: bC6baGqpg7WySAQXIdpwsoA9xLA= + +Name: system/etc/tfa/ring.eq +SHA1-Digest: 4luSW/fn+3qnGJ9ELxyvDqQ/AX8= + +Name: system/lib/libexif.so +SHA1-Digest: MEQwRnyJgtjyko3cIU3WTlzAnP0= + +Name: system/bin/umount +SHA1-Digest: PJo4zqzS5BfU6A3O+bq3dBjayJk= + +Name: system/lib/libwfdhdcpcp.so +SHA1-Digest: InL+k8uz3h7KEATn0Jx+oNeF7ow= + +Name: system/etc/security/cacerts/6e8bf996.0 +SHA1-Digest: VlozgKv+QbW1H/99/nImmPiyEOI= + +Name: system/lib/egl/libGLESv1_CM_adreno200.so +SHA1-Digest: gwprO3sKhU7nrPUHCoeT/+pZigA= + +Name: system/etc/tfa/video_l.eq +SHA1-Digest: 39AAkesJZDW1hCnZ6qFfGBa+B3E= + +Name: system/lib/libsoundpool.so +SHA1-Digest: l5Tdhg5V53Gd193liRb/CNH36LI= + +Name: system/media/audio/ui/Volume-4.flac +SHA1-Digest: UwmGIIUqyxsXRyWXu0cngmm0958= + +Name: additions/fonts/roboto/Roboto-BoldItalic.ttf +SHA1-Digest: BLLUGzekHTI7qddxiB3d8Y0juxE= + +Name: system/etc/security/cacerts/5021a0a2.0 +SHA1-Digest: OsZKswcn/xRvpTKd7JaZpcHdR+o= + +Name: system/bin/netmgrd +SHA1-Digest: M6NHUjMQjlR2KRaH6Yje5+W+Ty8= + +Name: system/etc/fallback_fonts.xml +SHA1-Digest: T+aQo4vmIpSseZd0vz0O/WM52VY= + +Name: system/app/GoogleTTS.apk +SHA1-Digest: AflpmS9CoJhaMzOdpHgK1pGTlJQ= + +Name: system/lib/libtilerenderer.so +SHA1-Digest: aNLD1NMDL+56S8JpngtdZ5oZfEw= + +Name: system/app/FDHttpd.apk +SHA1-Digest: kVJQ5poEcWVtXg2OLx2EBidEPM0= + +Name: system/lib/qnet-plugin.so +SHA1-Digest: dpAXlO7iYxN56kb/orXnzqly+G8= + +Name: META-INF/com/google/android/aroma/icons/license.png +SHA1-Digest: p42J8rgNtbZL30syGVJdpF13Y9s= + +Name: system/etc/security/cacerts/9fae0770.0 +SHA1-Digest: GAPh+uzlba5nB+JrHSVpIU7wbyQ= + +Name: system/bin/make_ext4fs +SHA1-Digest: 4y7Ar7Ogb1z483nzMHk+U0ChmVM= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/right_eye-y0-yi45-p0-pi45-r0-ri20.lg_32-2/full_model.bin +SHA1-Digest: Pvsuib7v1Y1CLewHRtiIm/N9W54= + +Name: system/bin/rmdir +SHA1-Digest: CtBkDwE3MSJ4Wgd1yuuaq/N6JH4= + +Name: system/customize/resource/allapplication_21416.xml +SHA1-Digest: plYc1a/i+cY7NstoAmT2htpgXIs= + +Name: system/app/HtcSpeak_HFM.apk +SHA1-Digest: eXydZhugZZJ4VjG1FFf9mULC6RA= + +Name: system/etc/security/cacerts/bda4cc84.0 +SHA1-Digest: /ZztxwPHRyN202+l2rSGg6udDJE= + +Name: system/usr/srec/en-US/dictation.config +SHA1-Digest: dAG0jruo14Cvr/u888Yg9c8UGMo= + +Name: system/lib/libharfbuzz.so +SHA1-Digest: xAKdmpe2G1VE+m64KjY6WBq7Zbw= + +Name: system/tts/lang_pico/fr-FR_ta.bin +SHA1-Digest: xsa/hqJTXz8Rc7l3UTQXz1ikriw= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_sel.png +SHA1-Digest: FH8/F/Sm+KTbT80qWTj5dksties= + +Name: data/app/com.google.android.apps.translate-1.apk +SHA1-Digest: FUaRH0BaaKsy0htFVWVOEG8CrtY= + +Name: system/etc/tfa/ring_l.eq +SHA1-Digest: b0PCFbsirfmVnMKjATkmIGb3s0o= + +Name: system/customize/resource/ConfigP.bin +SHA1-Digest: tyfXGVlq3TP6dUKiUenkfsL3yHI= + +Name: system/customize/resource/quicklaunch_24001.xml +SHA1-Digest: mldsHEAyR5CU90F02FX62Sms3TQ= + +Name: system/etc/security/cacerts/6adf0799.0 +SHA1-Digest: yOpUlfl7ZFCprMcTVr1bX0nCx28= + +Name: system/bin/mpdecision +SHA1-Digest: pXJ8xS/Nch0re1FdR5pd3P5cbsE= + +Name: system/framework/bouncycastle.jar +SHA1-Digest: s3oKrD3ywnHrCUBRlZDbQ/xQ5oc= + +Name: system/lib/libctest.so +SHA1-Digest: i5yNDyqNnOIGUEgEDmguoFzcLtU= + +Name: system/lib/libwebrtc_audio_preprocessing.so +SHA1-Digest: Aa33rMJv8VYRgUdQf3UDfHnqiTE= + +Name: system/customize/resource/quicklaunch_24008.xml +SHA1-Digest: i7xR6xqRyXfLVbUgT+YtlyTl0DY= + +Name: system/app/GoogleContactsSyncAdapter.apk +SHA1-Digest: 0wX05Cuyht3zhwAwBvGe28IMwGM= + +Name: system/usr/srec/config/en.us/models/generic11_f.swimdl +SHA1-Digest: 5eK+Uqn7V9+/aGXZDDzZ5MstkII= + +Name: system/etc/security/cacerts/4fbd6bfa.0 +SHA1-Digest: S6TGnIWLIWVHbHri7sRkvgXJHPo= + +Name: system/lib/libhtccamera_yushaniiproc.so +SHA1-Digest: vAED5EE+GLdECI3wEpr6kVSqowo= + +Name: META-INF/com/google/android/updater-script +SHA1-Digest: +S+ufnwCLW/gW0K9/3HYkNg/fZE= + +Name: system/etc/sound_mfg.txt +SHA1-Digest: AN7WINwvsjlVvjf+SPKTX6w0MXs= + +Name: system/lib/libchromatix_imx175_hdr.so +SHA1-Digest: Yj0wkZZeFebIqU1PkkbOeHXAJs4= + +Name: system/customize/resource/allapplication_20201.xml +SHA1-Digest: YDbdj4SQyRljcF5pspNE3yXddVU= + +Name: system/lib/libsnfc_ndef.so +SHA1-Digest: jKOUv7tU4dinM+XJtI9OyFfMEaU= + +Name: system/etc/tfa/playback.config +SHA1-Digest: P5zxhyDI7JZdLvRnRz4J2uoCyl8= + +Name: system/fonts/DroidSans.ttf +SHA1-Digest: AuiJIJMNRa/jDLEZK4Jns75Z2u4= + +Name: system/customize/resource/allapplication_28010.xml +SHA1-Digest: 0Kh8mMJcaEXDIqd8nntcuTDjYDU= + +Name: additions/gps/australia/etc/gps.conf +SHA1-Digest: kULxyLDy8GH4Gv/6bF7PBSY0YPY= + +Name: system/lib/libjUPnPCP.so +SHA1-Digest: Yu+U/yPgUSFjX8HeRoEfwEBu+EQ= + +Name: system/etc/image_beats_speaker.bin +SHA1-Digest: eMeu7tLJ4kKJt7erNC95CGLsVXs= + +Name: system/etc/security/KeyServer_PubKey.der +SHA1-Digest: lDlSctHdJLEuf53ZM2YZaXCKfkg= + +Name: system/lib/libmmcamera_aec.so +SHA1-Digest: whW7N4LJG2C8kNI9x6+yzTT8cZE= + +Name: system/lib/libchromatix_s5k3h2yx_hdr.so +SHA1-Digest: ZjVqacHeCdFtHwmSuy4kOu/3wTQ= + +Name: system/etc/security/cacerts/fde84897.0 +SHA1-Digest: 1Q5mh0RLzUt7mJgES/HlLi2LFqE= + +Name: system/etc/firmware/leia_pm4_470.fw +SHA1-Digest: BFO3gNEnY1H82fEQBZ1FOXmSBYQ= + +Name: system/customize/resource/quicklaunch_23801.xml +SHA1-Digest: cqxyXV8MvuyN0hV/7f78SiKt1Rk= + +Name: system/media/zchgd/charging_00.rle +SHA1-Digest: d8bbQ4r9gOqYEJwhsceUOPG8ZXI= + +Name: system/framework/bu.jar +SHA1-Digest: BTF3lS1JL/z1s7e06Fo11RE+j5M= + +Name: system/app/HTCAlbum.apk +SHA1-Digest: 5Cn+DE641P2qXaTf6Lm8naurIjk= + +Name: system/app/Calendar.apk +SHA1-Digest: zOxveMD+euIOwVXlWuMO1FkPEmg= + +Name: system/bin/fsck_msdos +SHA1-Digest: lPU/oX5W6C5uGs5TMnsALC5xzhs= + +Name: system/etc/firmware/BCM4335A0_001.001.038.0015.0020.hcd +SHA1-Digest: 8TRbLQgUTbM3/8ofAc+t40SEoB0= + +Name: system/app/HtcFMRadioWidget.apk +SHA1-Digest: x6JAVoZsvEfiVvSSddI5FN1sBYo= + +Name: system/app/HtcContacts.apk +SHA1-Digest: wa6h/Q3KebwI6SVBUAkBw9FB39s= + +Name: system/bin/drmserver +SHA1-Digest: biOAgsaThR4eNo34iE/WH9tGMoQ= + +Name: system/lib/liboverlay.so +SHA1-Digest: lpHazt3lNorVWy1r9mMh3PtgN7w= + +Name: system/etc/permissions/com.htc.fusion.fx.xml +SHA1-Digest: MT0zMcwC2cm9yU+MpnSbZgI3zag= + +Name: system/etc/security/cacerts/052e396b.0 +SHA1-Digest: DZ81ptcnRpSHtb9evRwrx5aFhFg= + +Name: system/customize/resource/rp_ac_with_nfc.png +SHA1-Digest: /xZnw8GFpomK5WRrcBaS4qcqFfU= + +Name: system/lib/modules/moc_crypto.ko.sig.3.4.10 +SHA1-Digest: TKfYEscEI9/CJEY2yi+tRuQnJNY= + +Name: system/bin/e2fsck +SHA1-Digest: QHpJtJPLjLSdUsBh8v4IOkN99WE= + +Name: system/customize/resource/wallpapers_a_05.jpg +SHA1-Digest: wYOYxPXBRtvATVdfYdyLHVDMtls= + +Name: system/media/audio/ringtones/QuietlyBrilliant.mp3 +SHA1-Digest: +0cjCoXJdOdFaap3B9zPkP0jc+Y= + +Name: system/lib/libvideochat_jni.so +SHA1-Digest: AGchaBSlU7cDNw7bPMCKj7ytmUA= + +Name: system/usr/keychars/qwerty2.kcm +SHA1-Digest: daI1+jRsBLH0AaORU4xCM1Bp4/M= + +Name: system/framework/apache-xml.jar +SHA1-Digest: yp7qBABAWpRkC9MQafc+MUVdZTU= + +Name: system/media/GPU/CurveCross.bmp +SHA1-Digest: MX2+KHC75avjfNxEsu4W/Yykpd0= + +Name: system/lib/libGLESv2.so +SHA1-Digest: HawW980PAsROnP4Ur75q0bXOxFg= + +Name: system/usr/srec/en-US/lintrans_model +SHA1-Digest: kpgCxKz87KHw265e+HcUMuVMhlQ= + +Name: system/media/audio/notifications/Jasper.mp3 +SHA1-Digest: n1jpnkw4MA+Qc6VYiaAKNiVAcb4= + +Name: additions/fonts/klavika/Roboto-BoldItalic.ttf +SHA1-Digest: TX5YPBSL/cZfEmoGflOO9Tjv6AU= + +Name: system/build.prop +SHA1-Digest: kn2BGI5dEK9w/25tVZiMKqDjCP4= + +Name: system/lib/modules/moc_platform_mod.ko +SHA1-Digest: 44WtQK1NWpYnFvtZP+xWmzZ3eKg= + +Name: system/app/TelephonyProvider.apk +SHA1-Digest: QUduWYjugD+Kw/PJGQ6+1Wb/XqA= + +Name: system/bin/qmuxd +SHA1-Digest: FItwYHuH9P8pvqY7GWJZM1Prv1Y= + +Name: system/lib/egl/libEGL_adreno200.so +SHA1-Digest: jUuNJH/HsXhv/8E5M4ghsyghLwQ= + +Name: system/bin/debuggerd +SHA1-Digest: QYqUUNNOYd+X9zdmujvszKZZRWc= + +Name: system/lib/libpng.so +SHA1-Digest: EV2ljSKqDjAerLnFxwsgq2hcxw0= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_on.png +SHA1-Digest: /mnI1Z1pwbSalzzsCUDJClEpneM= + +Name: system/lib/libcorkscrew.so +SHA1-Digest: rD/hGF3WIGW0FciF3Ac8LG25bQk= + +Name: system/customize/AAInfo.txt +SHA1-Digest: RV6F1rEu6yXkMmMKnaHVeZ3GvQc= + +Name: system/media/audio/ui/Volume-7.flac +SHA1-Digest: c79ptpPXIA8z5D5mMMHVRpFYyjg= + +Name: system/app/FMRadioService.apk +SHA1-Digest: 7nSK9gbcLhcbabY8Lm6q34fZe/U= + +Name: system/etc/security/cacerts/524d9b43.0 +SHA1-Digest: k2297HCYvN3BAhcl4kjnmOImy4g= + +Name: system/etc/security/cacerts/1eb37bdf.0 +SHA1-Digest: iEZtf6Bn7/kWs6HdB0tR9qNkl1I= + +Name: system/bin/logwrapper +SHA1-Digest: ef6A3igwr39uKD2uToHHxFP2MLY= + +Name: system/media/GPU/dot_mask_128x128.bmp +SHA1-Digest: RCj4FOMQHtkNTPmiMIeHvQXMT5k= + +Name: data/app/com.koushikdutta.superuser-1.apk +SHA1-Digest: K3UCnEsr2PWr1OmTIGIeRYhWTQI= + +Name: system/etc/snd_soc_msm/snd_soc_msm_Sitar +SHA1-Digest: vjgnZ+/DF0C+V/tn13tRkvx8/zQ= + +Name: system/lib/libRS.so +SHA1-Digest: aKxszPbesoHFdLRMcG1OD7m+/yo= + +Name: system/customize/resource/wallpapers_c_01.jpg +SHA1-Digest: ugxIiFpJKMaagm/Z46WJv4DfwXw= + +Name: system/etc/security/cacerts/455f1b52.0 +SHA1-Digest: kAWSB8ILogPZzBtuKBpjQvO6wGU= + +Name: system/etc/permissions/android.hardware.touchscreen.multitouch.j + azzhand.xml +SHA1-Digest: +jpP1GhT6HwDfDHhPbF4fqQTwB8= + +Name: system/etc/security/cacerts/03e16f6c.0 +SHA1-Digest: NU+kXb+8/njmA2M/T0gBfUiAMw4= + +Name: system/media/audio/notifications/Maize.mp3 +SHA1-Digest: JOPJ2B0wUdJ1YpbTis6Ls/hvfTA= + +Name: system/usr/srec/en-US/compile_grammar.config +SHA1-Digest: mdpUNdm82426woOidVS5ExtlbTQ= + +Name: system/usr/keylayout/Generic.kl +SHA1-Digest: fIrDip0pbaTuslI8pbUBHoBPS58= + +Name: system/lib/libaudioflinger.so +SHA1-Digest: cO/Bk3PzEHZpk+3+wn8qAyfojsY= + +Name: system/media/GPU/mask_vignette_legacy.bmp +SHA1-Digest: UkD7py3wdeRqiXYsYjTsldM2eeI= + +Name: system/customize/resource/quicklaunch_28020.xml +SHA1-Digest: D0ImwjegPrVsFHm2Lvv6p+fPMcs= + +Name: system/usr/keylayout/dummy_keypad.kl +SHA1-Digest: U2k1GE0KNq0lGhB6bgkZJhSPFmw= + +Name: system/bin/dbus-daemon +SHA1-Digest: GyEIqtCdnCCA+moMXYsZx0U/eHc= + +Name: system/media/audio/ui/camera_click.ogg +SHA1-Digest: V7fhbEaJIXo2h/p1lguCCaLW6qk= + +Name: system/lib/libstagefright_soft_aacenc.so +SHA1-Digest: GURrnkB4thJiQvAfQBWhCq+yMP0= + +Name: system/lib/libext2fs.so +SHA1-Digest: MLQUNKXqnD23KWj/fT5NEg/hmHw= + +Name: system/lib/libllvm-a3xx.so +SHA1-Digest: 2GnN8GHqNjI+UEIDdDC+69KgaFU= + +Name: system/etc/tfa/tfa9887_l.patch +SHA1-Digest: 0VJpWQFPVRYdJ4EGAzL9eBZDvbg= + +Name: system/app/SetupWizard.apk +SHA1-Digest: V2FqvWxQCjwBKpT1mMTXEZnagoY= + +Name: system/app/HtcNotes.apk +SHA1-Digest: Ckraw+UO1QBBioD3tVP/3gnKKF8= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x_Fusion3 +SHA1-Digest: yXQfZsxZRUlI0Fsz574lYKuy3Ic= + +Name: system/media/weather/weather_l_cloudy_day.mp4 +SHA1-Digest: 2ad2jPTcN08/Fz9IqaabG8bJUrI= + +Name: system/customize/resource/wallpapers_b_01.jpg +SHA1-Digest: Qhc0ajCPGXYjPvMohZlWmkgBnLg= + +Name: system/app/Mail+nonprime.apk +SHA1-Digest: MR5lrEaF9CeAZDA1nSY+ArONTvk= + +Name: system/etc/security/cacerts/cdaebb72.0 +SHA1-Digest: boCUiF4OQ/Bc6b9xuzVVDs8BBkk= + +Name: system/usr/keylayout/Vendor_045e_Product_028e.kl +SHA1-Digest: 5vqCZTOVkoSpc0kmFfaNUhf5FbE= + +Name: system/lib/libwt6docrdr.so +SHA1-Digest: WrDRasG7xvTHPlWnb/2rl/Mvzb8= + +Name: system/customize/resource/quicklaunch_63102.xml +SHA1-Digest: 29yXw3o1lTltww2+7gpOib6e9yI= + +Name: system/lib/modules/lcd.ko +SHA1-Digest: rndArHiiK4U1POSkjpq2f2QuMWM= + +Name: system/etc/fallback_fonts-ja.xml +SHA1-Digest: z2fFfpqzlK/fJYgl0/ISK1xxNjU= + +Name: system/app/Automotive_Traffic.apk +SHA1-Digest: GA294MlsVBSfxrAjLfezKM1pjxI= + +Name: system/etc/security/cacerts/dbc54cab.0 +SHA1-Digest: mLY39lqUQs7ml8zsoOpALdtZjMk= + +Name: system/lib/libdefcontainer_jni.so +SHA1-Digest: K7GvikoWnY+JCh3UhB+Zbo8eRhI= + +Name: system/bin/btld +SHA1-Digest: MKJsyx/COSXQ7w3pS4lPgyrFBsM= + +Name: system/etc/permissions/handheld_core_hardware.xml +SHA1-Digest: F4hDcGHqWxsTh4I+siOHqZJtIlQ= + +Name: system/etc/image_htc_midtier.bin +SHA1-Digest: K3AuJkRycsl4u41aCaVv65rWJ08= + +Name: system/etc/tfa/ring.config +SHA1-Digest: vp0Z5j8P3tSbQfhd3TX1QzkHElY= + +Name: system/app/MyHTC.apk +SHA1-Digest: 4+JRmBCm8lhSlVAWvANxLwOhXpE= + +Name: system/app/CheckinProvider.apk +SHA1-Digest: QPZgI8MJdc1Ow4hlP50v0Kou25Q= + +Name: system/customize/resource/quicklaunch_24801.xml +SHA1-Digest: Xa2aGR1lr575hocOep84Upntxxg= + +Name: system/framework/monkey.jar +SHA1-Digest: MkmzaOT9qYqS59wQLx22K+NioIU= + +Name: system/lib/libhtcflash.so +SHA1-Digest: TQSPk3eosSohCQWXpA5MwTIXcUI= + +Name: system/fonts/DroidSerif-BoldItalic.ttf +SHA1-Digest: 9yrTa21bS7lrxMqVUy9FELRQ5WM= + +Name: system/lib/libwsp_jni.so +SHA1-Digest: +zcdvT6LGB0OOCbkzowaeBKN8Lk= + +Name: system/etc/security/cacerts/5046c355.0 +SHA1-Digest: OQH1BPU6CROY/RgHEc+aJJM9Lcs= + +Name: system/lib/libwivu.so +SHA1-Digest: R3hrlu+eMZTjvKiMB0wdCp1PtzE= + +Name: system/bin/surfaceflinger +SHA1-Digest: 2qmr2aL5TAPukvq667gIVGkyQtk= + +Name: system/lib/libcpt9core.so +SHA1-Digest: NP7L6hhyTVBsOCbGHWeu4pFY8IA= + +Name: system/etc/security/cacerts/ce1adacf.0 +SHA1-Digest: Ou6tsrEpMUV7CScsC6XMlmto+9I= + +Name: system/app/IdleScreen_No_lock_screen.apk +SHA1-Digest: p25buBhqy++M+WCuxDda/Lbmm0U= + +Name: system/bin/memlock +SHA1-Digest: RcWgny934lOB35Ht6tKSldgK3Xw= + +Name: system/etc/security/cacerts/11f154d6.0 +SHA1-Digest: N3mD6hj2jNRv/GRshgLKaXmOtaY= + +Name: system/etc/security/cacerts/5a5372fc.0 +SHA1-Digest: Fb0tYUiGRziyUpyHHetf0/rTWWU= + +Name: system/etc/security/cacerts/9685a493.0 +SHA1-Digest: uQOYnTRtD38Rh9THdcalO+4cPsI= + +Name: system/media/GPU/dot_mask_2.bmp +SHA1-Digest: ePCPruIAtEN9jvd++wLUw0EuuR0= + +Name: system/etc/tfa/recorder_l.config +SHA1-Digest: aAViz/nsb9kNIE42WjaKFSRjsfM= + +Name: additions/fonts/comicsans/Roboto-Bold.ttf +SHA1-Digest: j/PZDPmw1f3ho31euZFpwEKP5ss= + +Name: system/media/zchgd/batt_95.rle +SHA1-Digest: DHOlOsXEwzaYFltcNOM04oZQV78= + +Name: system/app/IMEXT9English.apk +SHA1-Digest: SHE0TI7r65ez9ylXakrL99f48oQ= + +Name: system/lib/libwt6epprndrv.so +SHA1-Digest: exGfwLsLL1PdbbtmzqVFcpzV/Wo= + +Name: system/etc/tfa/ring_l.config +SHA1-Digest: T5byfbh4wTg+1ji6PtDoT/9Bnd8= + +Name: system/lib/libdsprofile.so +SHA1-Digest: vWmvGf0Du1yz0Sv1Wj5Gjapshn4= + +Name: system/etc/tfa/recorder_l.eq +SHA1-Digest: bBkshORbpfxCjRB7MT/pTcpqb/4= + +Name: system/lib/libDxDrmJava.so +SHA1-Digest: jDD58xXLtRzU5DHI26xKFaVtMfM= + +Name: system/media/audio/ringtones/Emerald.mp3 +SHA1-Digest: 5p7C+6BZXNwMG7EWCPT66emmFAk= + +Name: system/customize/resource/allapplication_28001.xml +SHA1-Digest: u5gd0TLGYUUhV0S8kqQTjxsjJ2s= + +Name: system/lib/chiaddict.dat +SHA1-Digest: jKkE8OjVEpdNSRYvaAp2pZYRJYQ= + +Name: system/bin/netd +SHA1-Digest: g55N861xb+nbqhC7R0xNX6WGeOo= + +Name: system/etc/image_gec_2vol.bin +SHA1-Digest: 8E2vv/LialvvztFPjhcdKUzJx20= + +Name: system/etc/htcfs.conf +SHA1-Digest: 7U9m+U7G1dY6oJecxU/nDpsMh4Q= + +Name: system/media/weather/weather_rain_day.mp4 +SHA1-Digest: GKKdtxUFHsJoMLFHrGfup5R8BQ4= + +Name: system/etc/security/cacerts/d64f06f3.0 +SHA1-Digest: rJ+XZX/zYV6CfIibccm6aeg3E8Y= + +Name: system/bin/schedtest +SHA1-Digest: 79TTHeYMFVcsu212JsTCwVPL4qM= + +Name: system/app/CertInstaller.apk +SHA1-Digest: hPAU3/4e16V9g7k1K6RBefJbygg= + +Name: system/usr/srec/en-US/grammar.config +SHA1-Digest: i0kpjrtpyO9CYP1yXMnKNwVLv6U= + +Name: system/media/weather/weather_l_cloudy_night.mp4 +SHA1-Digest: u41T0CONl/OZDiUWXPtxZyadZRU= + +Name: system/app/Liveretouch.apk +SHA1-Digest: r8r/ZaXfywZCvgW5TcEYMdMOFwk= + +Name: system/media/audio/ringtones/Grey.mp3 +SHA1-Digest: nNLSGLck6f1bwD7p1m8gtQXz33A= + +Name: system/etc/security/cacerts/d2adc77d.0 +SHA1-Digest: soKD09dcMHFX0hjD+rJQypQWLqM= + +Name: system/app/CustomizationSettingsProvider.apk +SHA1-Digest: LNLWqQFVpTCLVEdKmzQsqC5FOVg= + +Name: system/lib/libstagefright_soft_flacenc.so +SHA1-Digest: TcOCo+hR6OU/OTXDXpqAgYG4FOA= + +Name: system/lib/libfilterpack_facedetect.so +SHA1-Digest: G4gdGHlFL/RryALdFEJAQ3aWuYs= + +Name: system/media/audio/ringtones/Ultramarine.mp3 +SHA1-Digest: SOCNlHgKrXXOys4whSWMrhzAiJo= + +Name: system/lib/libmmstillomx.so +SHA1-Digest: Y43b2rqJ41jdMttwug3vkSiDu+U= + +Name: system/app/NetworkLocation.apk +SHA1-Digest: PY9WUQXh7LHQZMO/kszERBxA9zQ= + +Name: system/lib/libgsl.so +SHA1-Digest: Clb42VzvPf62A/B2GNLx43l2VOs= + +Name: system/etc/tfa/voip.preset +SHA1-Digest: nzd/u9J610RTa1J06s56MpAarB0= + +Name: system/etc/image_gec.bin +SHA1-Digest: no0rxo2odQyCl671MdeRXbNZ5Sw= + +Name: system/app/FM_Radio.apk +SHA1-Digest: cI55Z5UFdXu2hu0Udh8CSwULPYk= + +Name: system/lib/libmmwfdsrcinterface.so +SHA1-Digest: qxpirYYwJARgfi4EGhpKgTVP7Ws= + +Name: system/usr/srec/en-US/acoustic_model +SHA1-Digest: Bzsv1FQKC7SoKYlOYai42KLLvAc= + +Name: system/lib/libusbnetjni.so +SHA1-Digest: FjIEsbp9Kc+/SEOBMwZ+q9Xrhss= + +Name: system/bin/v4l2-qcamera-app +SHA1-Digest: wop8IV+2HfdgeJUDvmZ0k0KnUOw= + +Name: system/lib/libswapheap.so +SHA1-Digest: X+K6qJwQOO6zZOsbjM+kMRp4fgw= + +Name: system/lib/libwfdrtsp.so +SHA1-Digest: XeMSeCQ1CcxBwC8kfbdaLvic8Ng= + +Name: system/bin/atrace +SHA1-Digest: DK0xp5iRZ5DQJdqRYpH1qWVT33c= + +Name: system/bin/mm-qcamera-daemon +SHA1-Digest: 5Mz9mWphrBpQLPAPhYmf+XJT8y4= + +Name: system/etc/permissions/android.software.live_wallpaper.xml +SHA1-Digest: AyPpQw5IN0UBn608llm8t77fiPY= + +Name: system/fonts/DroidSansArmenian.ttf +SHA1-Digest: ZqNiJp/UISxsUJB+Xj4nlWWRPT8= + +Name: system/bin/mediaserver +SHA1-Digest: 2RSiZw/H8Q0MGq/RMV0imHSq6PM= + +Name: system/media/zchgd/batt_0.rle +SHA1-Digest: A4vbAFbLotgT+iEZiSbbNo/mcNU= + +Name: system/etc/security/cacerts/57692373.0 +SHA1-Digest: EskvxfpDUOk0oqxCTSEsSQR+P6g= + +Name: system/app/HtcProfilesWidget.apk +SHA1-Digest: zlSCeGitNNxnRbKUP8EGD08/1i8= + +Name: system/lib/libandroidfw.so +SHA1-Digest: IRG30e+cRwhUIRTS29ec+7Ol9nA= + +Name: system/lib/libjpeg.so +SHA1-Digest: cUjm6sHRhr1jv9V0G4tvoXD0Hd0= + +Name: system/media/audio/ringtones/Tangerine.mp3 +SHA1-Digest: Ze6NMjnGzJeJMRV8CoBfjLQdIcM= + +Name: system/lib/modules/msm-buspm-dev.ko +SHA1-Digest: 2np61brl2AOEmviP1bYXad0EuQc= + +Name: additions/fonts/comfortaa/Roboto-Regular.ttf +SHA1-Digest: XOc3d+Q6ZPzZSunfqxnFMKyzGWU= + +Name: system/lib/libdumppcm.so +SHA1-Digest: pAs7NlFsLOM6usGY2rqLvxA5+Yg= + +Name: system/etc/tfa/voice.config +SHA1-Digest: cvb/y9BZioN2wM9PRoIRQePdSow= + +Name: system/etc/tfa/recorder.eq +SHA1-Digest: b7YaGmv7Xu4rODdez3eRlk00JZw= + +Name: system/media/audio/alarms/Taupe.mp3 +SHA1-Digest: pIoWko3vsMo5A4TiuBNtDwWxlrA= + +Name: system/lib/libwt6bjprndrv.so +SHA1-Digest: GFqFQUt15r6p9Bit27sAkLyM1RQ= + +Name: system/etc/security/cacerts/7a819ef2.0 +SHA1-Digest: Ig0Zi/k4BqWAYNZWWgJjpKVsDHs= + +Name: system/framework/com.dropboxpartner.jar +SHA1-Digest: axVoQ38TBr/xquuVBRBtdT2yGjU= + +Name: system/lib/libchromatix_imx175_default_video.so +SHA1-Digest: NLBeF6M37nFeZK1JwN60asbEG3E= + +Name: data/app/com.google.android.apps.maps-1.apk +SHA1-Digest: +tTZZYAOoDSxEJTjbxWuNwBxnGQ= + +Name: system/etc/init.qcom.bt.sh +SHA1-Digest: GoEymPhK8EdX962l/M7nOIM6W2E= + +Name: system/lib/libext2_uuid.so +SHA1-Digest: i7g7GxfXcgQWlRLyigJnSt5ouDs= + +Name: system/fonts/AndroidEmoji.ttf +SHA1-Digest: irAmQlWMaVfKS2WbXf6WPUKnkfI= + +Name: system/fonts/ucsh00d_c.ttf +SHA1-Digest: FF+ClHJNof/U9r2Ooj7HLPA7SjM= + +Name: system/etc/thermald_boot.conf +SHA1-Digest: kpjCZLxFp1Wn1m6oJ9The1KIj9k= + +Name: META-INF/com/google/android/aroma/themes/sense/radio.png +SHA1-Digest: S42xKueiiE6TUmu9NwkfcrekzlA= + +Name: system/etc/security/cacerts/8ccb5f6d.0 +SHA1-Digest: E7FbxirzVSqvpXtf38OurNlrqfw= + +Name: system/framework/com.htc.android.bluetooth.le.jar +SHA1-Digest: rty+oj59TGDphdvtjzr5qV7Y+WE= + +Name: system/app/IMEXT9Hebrew.apk +SHA1-Digest: AgT9S9Rn79ZhmBHDi7LUyhQ/CCY= + +Name: system/vendor/tmo_cm/demoutil +SHA1-Digest: v/1/QNUfZZnXtB44k9fBKxm9dMk= + +Name: system/lib/libtzsrv.so +SHA1-Digest: 8I5T86LmWpPbjqRXN+4qEnAS7Aw= + +Name: system/media/weather/weather_l_partly_sunny.mp4 +SHA1-Digest: Wvw/WrrZd/Rf1fHM3am4SVnEihY= + +Name: system/usr/share/partials/partials_CW.dat +SHA1-Digest: /rzyHT6AMAejio0aC1tthzjKqT8= + +Name: system/customize/resource/allapplication_26003.xml +SHA1-Digest: OXCYG9LTxP6bOuChsDhcOKOb80U= + +Name: system/etc/tfa/deftcoefA_l.speaker +SHA1-Digest: qxlPE8Oa6KZuMFIfLkrkhbOBBNU= + +Name: system/vendor/lib/libWVStreamControlAPI_L1.so +SHA1-Digest: +RyYf1fJpQCZ9gjd4DK/hTAotWs= + +Name: system/usr/srec/config/en.us/models/generic11.lda +SHA1-Digest: gCp5FAUl5aR0GnFC/tkkamX7ic8= + +Name: system/etc/firmware/hcheck.mdt +SHA1-Digest: l3jA3PcSX/yUUGCpzA2WEDv4uXM= + +Name: system/app/Camera.apk +SHA1-Digest: 2RpMwYyt8WzAUJGRMTn+Qt7Q5bY= + +Name: META-INF/com/google/android/aroma/scripts/restore.sh +SHA1-Digest: +IFiQ87RD/mBgFk3nO1EVpUZoEA= + +Name: system/app/HtcResetNotify.apk +SHA1-Digest: 5fU00pE+ZkRWBi9sXi9iy6Xj+LA= + +Name: system/lib/liboma-drm1-fs.so +SHA1-Digest: tXHTRquBOPSLL4i5ovm/kayrx10= + +Name: system/etc/tfa/playbackbeats_l.eq +SHA1-Digest: +M8Q2RJodUbgkVcTi0aPa96zoaM= + +Name: system/media/GPU/dot_mask_1.bmp +SHA1-Digest: 0FS1Rq1IuGptrsIASMoZJuajNz0= + +Name: system/etc/permissions/com.android.nfc_extras.xml +SHA1-Digest: Qi+tQ+6ZJcMQyV/l49XjYlVTiHk= + +Name: system/etc/permissions/com.google.widevine.software.drm.xml +SHA1-Digest: MvejKuFQO4VpexrZo29KXJ+HiE0= + +Name: system/lib/liblog.so +SHA1-Digest: ri8qM9tyEfeIIFgH98xHZoYp71s= + +Name: system/vendor/lib/drm/libdrmwvmplugin.so +SHA1-Digest: POSlWZHYhwsHJBQxLVZkpxlRhZ8= + +Name: system/etc/tfa/video.eq +SHA1-Digest: Dp4yAwQQcqyl+1dS1Sn2d2+myjk= + +Name: system/media/audio/alarms/Metal.mp3 +SHA1-Digest: YZ+I0awmNJthQhv7r1j8nu8MmmM= + +Name: system/etc/firmware/BCM4335B0_002.001.006.0042.0044.hcd +SHA1-Digest: X+iOdsNt8Ynh1ROzUwLtyki0twk= + +Name: system/etc/tfa/tfa9887_l.speaker +SHA1-Digest: kemyp/nV0lUfI5SIOo2l7Bxf3LE= + +Name: system/etc/tfa/voip_l.preset +SHA1-Digest: AiUIPnv0eAPZ85xkvzoR3KpCSG0= + +Name: system/customize/resource/quicklaunch_21910.xml +SHA1-Digest: yDmSwysEv+KAwqnAxESa+45UC2c= + +Name: system/app/DeviceManagement.apk +SHA1-Digest: r2udjBSMgIEeHT+4YrS7JGGdkYA= + +Name: system/framework/framework2.jar +SHA1-Digest: HFENq4WIXLBzcDq5LnJkbzylFac= + +Name: system/lib/modules/qcrypto.ko +SHA1-Digest: TtehboObBgutlAWk39hipZSGLFA= + +Name: system/bin/iptables +SHA1-Digest: vP0hwB0wB2UrqUTHNooWbBpTq5Y= + +Name: system/lib/libchromatix_ov5693_default_video.so +SHA1-Digest: q7n/2KqLaeprA6aGO+9jNpvbQtk= + +Name: system/lib/libchromatix_imx135_hdr.so +SHA1-Digest: RtM5wWJ0Gxrq3iPLwVt/yhjwyHs= + +Name: system/lib/libmmcamera_frameproc.so +SHA1-Digest: R7ncBjN27ct15KyLm6MFbF5ja5Y= + +Name: system/etc/security/cacerts/bdacca6f.0 +SHA1-Digest: GIoKYjYZDMCLnDmLcIXSPHiDtmc= + +Name: system/lib/libdrmtime.so +SHA1-Digest: poYQE6pFCKw8CMGUHptcn/cUCR0= + +Name: system/lib/libmorpho_frame_overlay.so +SHA1-Digest: gbVlf47RojfdfDgYHfPDP7bLgFk= + +Name: system/media/audio/notifications/Ivory.mp3 +SHA1-Digest: hmK8RlxgveGD5SyMrkE+GVhT6C0= + +Name: system/app/HtcSettingsProvider.apk +SHA1-Digest: bxjX1Lj4cRoG0YaZXhisEoO2BBY= + +Name: system/lib/libwt6pdfrdr.so +SHA1-Digest: B+GCLLFrgHg/D7OuDZlf/hFg1QA= + +Name: system/etc/tfa/ring.preset +SHA1-Digest: vzK8FP9UHfN6O7t7OG7XpmMDv7g= + +Name: system/lib/libchromatix_s5k6a1gx_hdr.so +SHA1-Digest: PWtqDeWbLuzRWMjewirD5PAmbMw= + +Name: system/lib/libgccdemangle.so +SHA1-Digest: zuXmNt8TPZ20EzljdjbSNWM/qqo= + +Name: system/app/IMEXT9Croatian.apk +SHA1-Digest: Qeiaq8+F3t8Zgzb0n2DDsG6UtSg= + +Name: system/etc/pnp.xml +SHA1-Digest: H4VoWJ7UKQwr4fx5mhoicuZ2518= + +Name: system/app/HtcAlbumMapView.apk +SHA1-Digest: wZrL5/adG2UdiThOhqxaCN1N0GU= + +Name: system/app/IMEXT9Kazakh.apk +SHA1-Digest: XA4b+bIaRwMZ8waGbca+lHCzmts= + +Name: system/app/COTAClient.apk +SHA1-Digest: MYENtyP3sM2QkGpUZgVTi6ZlXRQ= + +Name: system/etc/firmware/a225_pm4.fw +SHA1-Digest: XA4uOpkFkKHZLr/AR3MBZiTP258= + +Name: system/app/DownloadProviderUi.apk +SHA1-Digest: Ts3kpdy7RB0TTudBPb25fNMhCSI= + +Name: system/etc/security/cacerts/d78a75c7.0 +SHA1-Digest: KjqNAg7rqiKjiInNH3f2Iw3g6lo= + +Name: system/media/audio/ui/Effect_Tick.ogg +SHA1-Digest: zjEY3W+2jVwKElh2zJYZzLLjRE4= + +Name: system/media/weather/weather_l_snow_day.mp4 +SHA1-Digest: GomNkwvZBLxYwgMsJl+0Xg2l47Q= + +Name: system/lib/libdrmfs.so +SHA1-Digest: bwpPYLzuTtPgtjXn2e6kHEeQeEY= + +Name: system/etc/security/cacerts/86212b19.0 +SHA1-Digest: qWrS3UkHFWMxfILKNINl2lbaHMU= + +Name: system/lib/libstagefright_soft_aacdec1.so +SHA1-Digest: oB07pxZuRY4qhAugsnLiSdesh5E= + +Name: system/customize/resource/wallpapers_c_03.jpg +SHA1-Digest: Xu2V6yZkQTiej/8ML+mi29OK8i0= + +Name: system/lib/libmorpho_image_transform.so +SHA1-Digest: FJ8iZgeyA1uR2kq448yOvbdqYMI= + +Name: additions/openvpn/xbin/bb/placeholder +SHA1-Digest: VsY8qMTJY2AtLHJaNPXQY6YhoHU= + +Name: system/lib/libfuse.so +SHA1-Digest: dxpdoTqPZTJE3ZZQ420P68neBMA= + +Name: system/etc/tfa/voice.eq +SHA1-Digest: bcJn0BeKcW3qiAk5Kk12Cwn34ys= + +Name: system/etc/wfdconfig.xml +SHA1-Digest: Xn544gPZ7XZBcrchver+OSt6Uk4= + +Name: system/bin/getevent +SHA1-Digest: jyJF2/MqB/fdA8FZls4TTnLwsbE= + +Name: system/tts/lang_pico/it-IT_cm0_sg.bin +SHA1-Digest: rnh7Xn11wgxlksoos2j4/cAF2+I= + +Name: system/lib/modules/ansi_cprng.ko +SHA1-Digest: Bjedkn80a+dDlXOQuNs+wOVQ62U= + +Name: system/bin/diag_uart_log +SHA1-Digest: yih7EjhghzPsZ0KUizJ9s3MuRp8= + +Name: system/bin/pppd +SHA1-Digest: Vt2JveeRqPfLTr/9HeL/fALyWz4= + +Name: system/lib/libbeatscorehtc.so +SHA1-Digest: zX/7I0xHeFfzyd9j9RfF2wHmdw0= + +Name: system/lib/libchromatix_s5k6a2ya_hdr.so +SHA1-Digest: GQzK5zYLu4tKlMcOAneZ+Mb7TVA= + +Name: system/lib/modules/qce40.ko +SHA1-Digest: om3IJToQ5gEtM7NAPjyvN4ttM90= + +Name: system/lib/soundfx/libvisualizer.so +SHA1-Digest: VOFEmt/JQoqbVTQ5ht7iiGEeU1w= + +Name: system/lib/libqdcbutils.so +SHA1-Digest: bY8sDp6onZxGzsBVz0yMK/Jqh80= + +Name: system/framework/com.android.future.usb.accessory.jar +SHA1-Digest: MnGPJU6giBw4K6/TQDp9KwvEVkA= + +Name: system/app/Message+Nonprime.apk +SHA1-Digest: iTIvO/nEwLIBmyh8n34c9gU0sGE= + +Name: system/customize/resource/allapplication_21407.xml +SHA1-Digest: dMyxtMyLSm3khse/Km+6SQI+BYA= + +Name: system/lib/libiculx.so +SHA1-Digest: +2ROc4e+MLsQvysJqxJ9h8dgP+Y= + +Name: system/lib/libmode10fx.so +SHA1-Digest: dyAg+HL4o61jqScUuTg53ntIQUU= + +Name: system/lib/modules/evbug.ko +SHA1-Digest: +m/bbNDyk2J3io9zgMMyBoRDhEs= + +Name: system/app/HtcMediaCacheService.apk +SHA1-Digest: WXKyX+ycK7scpeW9J5YIrBtlw2I= + +Name: system/bin/installd +SHA1-Digest: pG2UoqfqrDFdH8FeIr4+iCU1sMY= + +Name: system/usr/keychars/qwerty.kcm +SHA1-Digest: Z/WKxPvIkR28R++ZAs/Acj5tvbw= + +Name: system/etc/permissions/android.software.sip.xml +SHA1-Digest: 9UTSCo9zY5j/DOZVZMjh7ozBOFE= + +Name: system/etc/security/cwcerts.zip +SHA1-Digest: sPG4eRyxb5c4TTGX2JPy7KEOZcs= + +Name: system/media/mms/atis_tia_cmas_alert.mp3 +SHA1-Digest: L7S6WJtNyvSN7YriPwX04gDCF+M= + +Name: system/framework/com.htc.lockscreen.fusion.jar +SHA1-Digest: m6qzyXS8H/CZgqZAfcS4JQmqWYI= + +Name: system/lib/plugins/com.adobe.flashplayer/libstagefright_honeycom + b.so +SHA1-Digest: q0h3Rv9yyal3c19kb6O2YgGkvqc= + +Name: system/customize/resource/rp_ce_0700.png +SHA1-Digest: v7F0xMXe45bPSig6vrS7gIQ2wqg= + +Name: system/lib/libjDTCPServer.so +SHA1-Digest: FUl5wM+qEWAKkeGtzwWHqk5SqJ8= + +Name: system/customize/resource/quicklaunch_20601.xml +SHA1-Digest: h2yzFJ7GC3jbUTuQo/iYYY/gYsQ= + +Name: system/bin/cmp +SHA1-Digest: Y5T4jDFDZs6zEzwr9ZsR01gIj7Q= + +Name: system/lib/libNEONImage.so +SHA1-Digest: u5p5I6j6LxSjLPFuCJgWmFvoPB0= + +Name: system/bin/insmod +SHA1-Digest: CF4EingoEEicimLEYbnXuhI3JGs= + +Name: system/lib/libchromatix_s5k6a1gx_hfr.so +SHA1-Digest: /hrnV0MFd2LVHfc0h/doxN5MxFo= + +Name: system/usr/srec/en-US/endpointer_voicesearch.config +SHA1-Digest: MgyAh0x/DUBKQE/gm2rmLwyDODg= + +Name: system/lib/libjni_fe.so +SHA1-Digest: 9fBJ9HCfjWTibyp/vFlkJXe+f3E= + +Name: system/lib/libopencv_java.so +SHA1-Digest: +QWBOPiG++GYLv5DygI81qsU0Jg= + +Name: system/app/HomePersonalize.apk +SHA1-Digest: GPmUURLwP3EpuM9YHoJEwKOTriY= + +Name: system/lib/hw/gps.default.so +SHA1-Digest: ny3DaVrJVxAIUAlV23a2g76VgZ4= + +Name: system/etc/security/cacerts/b0f3e76e.0 +SHA1-Digest: 0wOZM5sOi9oFQTTpvoJC+0fuSmc= + +Name: system/usr/share/partials/partials_A.dat +SHA1-Digest: MsZfd3Sh8KJLEmKi51AQMuyifno= + +Name: system/lib/modules/dm-crypt.ko +SHA1-Digest: haD7H9tZbXTPnHUjp0CBcW7UWJs= + +Name: additions/screenshot/screenshot.sh +SHA1-Digest: sQz1dLmN24swbFfivxOjllH5L4s= + +Name: system/lib/libmlplatform.so +SHA1-Digest: YUmP4T7bnyyAqM01vKoSRXUTiqc= + +Name: system/media/zchgd/batt_10.rle +SHA1-Digest: uSiHDjZDP1MnhBIzPP3BCqu6dHc= + +Name: system/customize/resource/allapplication_20205.xml +SHA1-Digest: 4kr1GLIAEf5ixO+HqGYC1UVnHOc= + +Name: system/usr/keylayout/Vendor_054c_Product_0268.kl +SHA1-Digest: iwHzEwj5WX7NvOdertR+r9nuRsk= + +Name: system/lib/libgnmc_fpx.2.5.9.4.so +SHA1-Digest: /Ip5KP/CWmjMcPV8E0JRNNGlMo0= + +Name: system/lib/libgenlock.so +SHA1-Digest: fuUHtDVQW8Tj4Pemc+d6dol4Zic= + +Name: system/app/HtcMobileNetworkWidget.apk +SHA1-Digest: Wups6DNdXr28hWXwXJSNI9+D8XY= + +Name: system/etc/init.d/99complete +SHA1-Digest: R38JsJrPdpB2Ne7I1Fp/iBELBhw= + +Name: system/fonts/DroidSansFallback-htc.ttf +SHA1-Digest: 0R5Cccj9M9oQI22nYm9KEIOrSk8= + +Name: system/bin/rild +SHA1-Digest: Dg+6j0dDUBtvnMCBzOXvsRNqieQ= + +Name: system/bin/logcat2 +SHA1-Digest: 7Xc63MXm7/d6p749M0tZsp/7wuU= + +Name: system/lib/libhtc_rilhook.so +SHA1-Digest: byBYA8+ysxTSaRcmrch63a/cKm0= + +Name: system/etc/wifi/wpa_supplicant.conf +SHA1-Digest: FtmOFmIrZRtpuTgL9V/rpfsYYDk= + +Name: system/customize/resource/allapplication_26806.xml +SHA1-Digest: waWxu+bWyHBdN0HJdc12vNjU3I0= + +Name: system/xbin/bttest +SHA1-Digest: p7uc529Tjh3Ihn10STfG6IC6KsY= + +Name: system/lib/libiprouteutil.so +SHA1-Digest: naTz9lLr1u5eCUbUQujR9FlT0tI= + +Name: system/customize/resource/allapplication_22201.xml +SHA1-Digest: 4mH10Pu0YPh2I9QN1bcs+1RPCNU= + +Name: system/app/PureC_PackageInstaller.apk +SHA1-Digest: z/VA10vym5uqxV4Nwz8ewJZ8ZEM= + +Name: additions/camera_4.2/app/GmsCore.apk +SHA1-Digest: zMX3n0qREjPgwLY6ZvH3pqfYvSk= + +Name: system/fonts/DroidSansTamil-Regular.ttf +SHA1-Digest: d/a5ySWr4uOYlmRQ/GVVxmtcfDk= + +Name: system/usr/srec/config/en.us/grammars/boolean.g2g +SHA1-Digest: IaXNuE4WOK1Xeb/yfielIx9Z4P8= + +Name: system/lib/libzeroeditor_osal.so +SHA1-Digest: 72fzz0iXk4ZNZ1b4/HGF6Agz1E4= + +Name: system/media/weather/weather_fog_day.mp4 +SHA1-Digest: 2BJJjHgJJmChAf3ANGkXtPFYefU= + +Name: system/lib/libmorpho_image_converter.so +SHA1-Digest: 7VmgYJpv0DFnfpt//joPmNYwFeo= + +Name: system/fonts/DroidKufi-Regular.ttf +SHA1-Digest: yYCvuiwVrMbyw5ISV3ba2OZ1zoU= + +Name: system/etc/fallback_fonts-HTC__J15.xml +SHA1-Digest: 5d+S8w87iCgH3YnHOxUnKmc1BQg= + +Name: system/lib/libhtcdrm1.so +SHA1-Digest: mcBukB0FRIHFjz4bB27skHSai3M= + +Name: system/usr/keylayout/Vendor_046d_Product_c299.kl +SHA1-Digest: N64rO5ir6UJhDLlL6vtA277M/n0= + +Name: system/customize/resource/allapplication_28020.xml +SHA1-Digest: nhiXU7xgEIe7zyW5d85uyVOV6Gk= + +Name: system/customize/resource/wallpapers_a_07.jpg +SHA1-Digest: rD6ZUfJ/tRCBTXLEiKLphZi1J0Y= + +Name: system/lib/libimage-jpeg-enc-omx-comp.so +SHA1-Digest: HRe1pdqqHyucUC/8eD2akmlqWPs= + +Name: system/lib/libmediaplayerservice.so +SHA1-Digest: pQueBISOcUpex8fia7K2vPnJDBE= + +Name: system/etc/security/cacerts/6b3f8240.0 +SHA1-Digest: 3I0ujeIwJOwFszifeBp0o8qMJQQ= + +Name: system/bin/log +SHA1-Digest: AZEUVqKb3UoIq1X3sE4OOqq/2Wo= + +Name: system/lib/libsensorservice.so +SHA1-Digest: KK/cGeoiyXIIayLEEsIqmNDn+ag= + +Name: system/lib/libEGL.so +SHA1-Digest: qq/qzn2H2sq5GI7F677ZFMhio/g= + +Name: system/bin/hdmid +SHA1-Digest: x3HXee0Z570O4FcxyAcruOF6zrk= + +Name: system/app/HtcHotspotWidget.apk +SHA1-Digest: XHMPERNPAHrfSW49gVxTVUvbRFk= + +Name: system/lib/libt9.so +SHA1-Digest: x5CleNw5JpAasMkmBcM9USOO/cQ= + +Name: system/bin/dexopt +SHA1-Digest: jfxGZp5Hday8mZSHbdMFZ6olCIY= + +Name: additions/fonts/helveticaneue/Roboto-BoldItalic.ttf +SHA1-Digest: nfsnY6gTEe6cMYaSuQ65Nb5cjJg= + +Name: system/media/zchgd/charging_06.rle +SHA1-Digest: LsydjjfZHDQcEBK7Gf4/f0a59+c= + +Name: system/app/PrivInit.apk +SHA1-Digest: EV007z7aT/E+q5auPFbz69+rlEY= + +Name: system/etc/firmware/vidcfw.elf +SHA1-Digest: rhXGC85w0om5FgIC+8//PD+2/7I= + +Name: system/etc/init.post_boot.sh +SHA1-Digest: yzW3xsjDjJyn+Ynrv6G+Sato6MA= + +Name: data/app/com.adobe.reader-1.apk +SHA1-Digest: L2QjUb1uv46hatREfZMoq70Aykg= + +Name: system/customize/resource/rp_ce_0560_i.png +SHA1-Digest: PnWwLXbc2v3oa/GkzxQNP2/aYgY= + +Name: system/customize/resource/allapplication_20601.xml +SHA1-Digest: +KZplE3XGBCEpyYowniKJYKTrb4= + +Name: system/etc/tfa/tfa9887.speaker +SHA1-Digest: LLSy88cA2gRdbFTAorLNVXTFBt4= + +Name: system/app/CustomAppInstaller.apk +SHA1-Digest: 85lIe5L2/tWRW8UN/a0O+3JTwBM= + +Name: system/app/IMEXT9Romanian.apk +SHA1-Digest: LKjLlwBZu4LrPrKwcdR7Ss/JWdA= + +Name: system/app/SelectPlayer.apk +SHA1-Digest: 3CgyH0fSvUaMRu18Ewc9Q9DbSj0= + +Name: system/etc/permissions/com.nxp.mifare.xml +SHA1-Digest: EbIle6B9w6yccdVJMcnCw23QJfc= + +Name: system/lib/libmorpho_memory_allocator.so +SHA1-Digest: d08BuL1nVzqGB0lr9bndr+07BqM= + +Name: system/etc/security/cacerts/7d453d8f.0 +SHA1-Digest: cA140QKiXig4ceJ7hyHJpuo224E= + +Name: additions/fonts/sonysketchef/Roboto-Italic.ttf +SHA1-Digest: aRM1HZHitSCbFit+cthH1govBD8= + +Name: system/customize/resource/quicklaunch_21419.xml +SHA1-Digest: Xl+dEFLy7PfwhJ+1W66GLrQFTec= + +Name: system/customize/resource/allapplication_23802.xml +SHA1-Digest: Bah8MgCCo4y6o6+AfmvsPqoYXh4= + +Name: system/etc/hosts +SHA1-Digest: +OtKCCSMljlpySKxhuN+zzZS88s= + +Name: system/media/audio/notifications/Lily.mp3 +SHA1-Digest: b30Y4nAPegXSdB5NvIZhJ2nMri0= + +Name: system/bin/qcks +SHA1-Digest: cMSmAHbLew3NESH89SZuhCPchHQ= + +Name: system/lib/libstagefright_foundation.so +SHA1-Digest: w/KOEfRfVs3qxmGp6I5GTdl/u/c= + +Name: system/media/audio/ringtones/Auburn.mp3 +SHA1-Digest: r39/U4ixvtZDtDVZAnW5wS9x1Zc= + +Name: system/lib/libstagefright_omx.so +SHA1-Digest: oC6HYs4zGcRSlUL6DX79Sm3oFjk= + +Name: system/etc/security/cacerts/add67345.0 +SHA1-Digest: BBZuvZg7SZem+qk/+qhuNIjw13A= + +Name: system/customize/resource/wallpapers_a_02.jpg +SHA1-Digest: TpyORqyeegJk9sPat+c2YjtO2kY= + +Name: system/lib/bluez-plugin/bluetooth-health.so +SHA1-Digest: sqs+99Zp4zb1z0XrT3xVHaEIhi4= + +Name: system/lib/libstagefright_soft_amrdec.so +SHA1-Digest: kWQVlyIqWb9PoC5ZPku2JyzQwYw= + +Name: system/usr/srec/config/en.us/grammars/VoiceDialer.g2g +SHA1-Digest: 6wv+uJnGUhIlJyoUJeIPbB+anro= + +Name: system/lib/modules/ks8851.ko +SHA1-Digest: kAgNUhRUYWyaKQW3EtTRj3Ztklk= + +Name: system/customize/resource/allapplication_24002.xml +SHA1-Digest: p+ENmY2oCc0RZ7dea9xU8U9Vns0= + +Name: system/lib/libmmrtpdecoder.so +SHA1-Digest: hXSa/tUQWRHSVNBJfD14hTV+aqY= + +Name: system/customize/resource/allapplication_23410.xml +SHA1-Digest: l5FhPtV99qzxOgsgcvYXbT4bzpw= + +Name: system/app/HtcLavaLiveWallpaper.apk +SHA1-Digest: JjNJL0+r+1VmPC6ZEzQgZ1bjDlA= + +Name: system/xbin/tcpdump +SHA1-Digest: GcI1cmfqUvkkEJLdkO5h+EHjLvY= + +Name: system/media/weather/weather_l_rain_night.mp4 +SHA1-Digest: 1qwxO1jxgSQ5Zupnr+9kVOuzzkI= + +Name: system/usr/share/bmd/RFFstd_501.bmd +SHA1-Digest: C0S/D/gyoOXBfe27iJkWBkJGc28= + +Name: system/bin/arec +SHA1-Digest: 3ZEvJ8K3c87q9KLSDkbqkaRdUaY= + +Name: system/media/weather/weather_fog_night.mp4 +SHA1-Digest: F1b1sHQ91NVfzgPSFKaIvjcvOyw= + +Name: system/framework/com.google.android.maps.jar +SHA1-Digest: fRt08xUFyTFpkn4QFMNXJAqzOnk= + +Name: system/media/audio/notifications/Pistachio.mp3 +SHA1-Digest: 8DSmU9sbyE1dBnUOqpU79DEmpBA= + +Name: system/bin/monkey +SHA1-Digest: WfWmGLdcQp2C3BlQ/nd56hRSN4M= + +Name: system/etc/firmware/tzapps.b03 +SHA1-Digest: RocT85k/WvAoPW1dD68npZqqe80= + +Name: system/etc/security/cacerts/17b51fe6.0 +SHA1-Digest: TF8DP16R0P3dLAbPoykKOGfTFrE= + +Name: system/bin/mm-vdec-omx-test +SHA1-Digest: IzB0v5b/nnoozAvTplkVv5mAOIM= + +Name: system/app/HtcMediaUploader.apk +SHA1-Digest: /B3ta4ot60KtLMXDGAWMMWmX0G0= + +Name: system/app/IMEXT9Slovenian.apk +SHA1-Digest: kJF7FN2xwqp/mUuTpA107TWzXG8= + +Name: system/lib/libchromatix_s5k6a1gx_preview.so +SHA1-Digest: 7rtlj9XIQMhiBPh5ZcC0PEjIVUI= + +Name: system/etc/firmware/tzapps.b01 +SHA1-Digest: GYR6PZVehWLZ+4iDuaHbZQ2jIDo= + +Name: system/fonts/DroidSansThai.ttf +SHA1-Digest: qrdCj47VL3j4/yEIwxqV+BM3IM0= + +Name: system/vendor/pittpatt/models/recognition/face.face.y0-y0-22-b-N + /full_model.bin +SHA1-Digest: zGut66M6P1Qi+iZT+iL2rTSfOWE= + +Name: system/etc/firmware/tzapps.b02 +SHA1-Digest: xGu+uRbMscGqBbCQylkLh2EKjqQ= + +Name: system/lib/libcommon_time_client.so +SHA1-Digest: RaK5F5IjhhZjYVeZz8yRxxARHLc= + +Name: system/etc/firmware/tzapps.b00 +SHA1-Digest: PYh07Ihkyaie2IP3Y68Y2YG8viU= + +Name: system/etc/security/cacerts/119afc2e.0 +SHA1-Digest: juMSLklsnjDd89OdzOhmdhh86b0= + +Name: system/bin/watchprops +SHA1-Digest: rVi0KO/rXSV+B0Zqs+CZzy4+gX0= + +Name: system/framework/browsermanagement.jar +SHA1-Digest: GQz97jDQIh0G3Fbl2VcLru54vFg= + +Name: system/app/GoogleServicesFramework.apk +SHA1-Digest: emeC9LDY+3EZFUJGf1j+jFZ6OuE= + +Name: META-INF/com/google/android/aroma/themes/sense/button.9.png +SHA1-Digest: 7KaJc9RyFKyk5aBmABch6EwwqBc= + +Name: system/media/audio/ui/Volume-5.flac +SHA1-Digest: VYzWS/U/znmHOaY1j+Yj4XbLhD8= + +Name: system/app/HTC_IR_Remote.apk +SHA1-Digest: iOYu+dC5zyYT4OL2F5+WN0R3+oQ= + +Name: system/lib/libstagefright_amrnb_common.so +SHA1-Digest: vho9Ypch07RLrJ9pTHklac/W88I= + +Name: system/app/HtcBtWidget.apk +SHA1-Digest: xYhdQWCQNrXsCWFqVJa321zLkzE= + +Name: system/customize/resource/wallpapers_b_06.jpg +SHA1-Digest: ewtQbQYZP2Cg3cZq4ECPW8d2xKQ= + +Name: system/customize/resource/rp_ac_no_nfc.png +SHA1-Digest: PJnfpIEfY9GB8l7IrPvDgxb+QM0= + +Name: system/framework/com.htc.fusion.fx.jar +SHA1-Digest: 1S/fpjL7E25RvXjS+8fMurMZMEE= + +Name: system/etc/dhcpcd/dhcpcd-run-hooks +SHA1-Digest: wlZAlg8sJGqNf67T6lXIETPzJxk= + +Name: system/lib/libmorpho_jpeg_io.so +SHA1-Digest: psc//o3vRza+y2DOzt4J6y1GIk4= + +Name: system/etc/security/cacerts/e7b8d656.0 +SHA1-Digest: bCEbhSbq/GjuAX/qoGBoN21YJuo= + +Name: system/etc/firmware/fw_bcm4335_apsta.bin +SHA1-Digest: x2+rDmFMd3c8WyCaJKg6ujcTrAg= + +Name: system/media/LMprec_508.emd +SHA1-Digest: P3ntvXeluWhTgyVlRyER0VRvzT4= + +Name: system/lib/libwlwpscli.so +SHA1-Digest: DUPG6tJdOqvwukRr9PTEFs8QQ9M= + +Name: system/lib/libspeex_sh.so +SHA1-Digest: tAuSG6ZD6iJ4UAa9PUwV2ponC1Y= + +Name: system/customize/resource/quicklaunch_234.xml +SHA1-Digest: 9BZOvNqHqO8g/LrYXOKjwuy3uJE= + +Name: system/etc/tfa/playbackbeats.config +SHA1-Digest: zFWqhuoYKHwrHgZELWBBXhpxnFw= + +Name: system/lib/libbcc.so.sha1 +SHA1-Digest: J/AeVx28TseGg1d4D2l3X25H9Yg= + +Name: system/bin/wpa_supplicant +SHA1-Digest: tY9Pj+FU/G/CNYVGu4z2uVzODZU= + +Name: system/app/ChromeBookmarksSyncAdapter.apk +SHA1-Digest: 4RQQmTFT4s2GAwxmPKzD6sHIPhE= + +Name: system/usr/srec/en-US/norm_fst +SHA1-Digest: yPCdX0EcppUA9o9xNvA5KBY7mUo= + +Name: system/media/weather/weather_l_partly_cloud_night.mp4 +SHA1-Digest: KGVl87qq7XxBvEf4nVirASRcN8o= + +Name: system/media/audio/alarms/Sea_Green.mp3 +SHA1-Digest: 6uwaXp8aCiPA0s66r/jVRRAr2EA= + +Name: system/lib/libril.so +SHA1-Digest: RVoivmiZdo52E1SWEUHvhVFoUug= + +Name: system/lib/libwt6docintr.so +SHA1-Digest: k/C2wZsheT7Jlzm7tmPIhkhHmjQ= + +Name: system/etc/permissions/com.htc.lockscreen.fusion.xml +SHA1-Digest: xDwHovhQsZ91x2Uok5Fkdp41qwo= + +Name: system/media/audio/ringtones/Violet.mp3 +SHA1-Digest: hCoDBZIIRTEmME686s9uGkQ4jn8= + +Name: system/etc/dbus.conf +SHA1-Digest: d6cc2Bt6sxy6Yzv4CTZl1X6sweY= + +Name: system/app/SmartDim.apk +SHA1-Digest: WwN7s9XcJbb0m7CUZLUIpJJgHvk= + +Name: system/etc/tfa/playbackbeats.eq +SHA1-Digest: 4B5p+K4WF2OwN1e2UO2b8VmZdFs= + +Name: system/lib/libdnshostprio.so +SHA1-Digest: ptLm4pujwPN5fBvXo4cB44F93jU= + +Name: system/lib/libttscompat.so +SHA1-Digest: 3YPguQTFjzvsxm7fxPzRGsFR4Kw= + +Name: system/app/HtcScreenBrightnessWidget.apk +SHA1-Digest: rijfDWQB2uPiSXkMzPrjgNHz/vM= + +Name: system/lib/libmmcamera_faceproc.so +SHA1-Digest: LyCqbfWUlPrumRmhY3ixT4u2luY= + +Name: system/bin/sdptool +SHA1-Digest: pNrMIU/dKkhf9JkkzORTuKctg0c= + +Name: system/media/audio/ui/KeypressReturn.ogg +SHA1-Digest: iYH8DQ0v9kvYnxCWM4nm70dYz7I= + +Name: system/usr/srec/config/en.us/baseline.par +SHA1-Digest: M4pck9N5JkEe9alJyTrxUpaKRd8= + +Name: system/bin/test_gemini +SHA1-Digest: QUT56NOIVSG03ywzQ54uc05IMkU= + +Name: META-INF/com/google/android/aroma/icons/update.png +SHA1-Digest: lkr8LjGc0VQptQ7ubRduxZr8zT0= + +Name: META-INF/com/google/android/update-binary-installer +SHA1-Digest: 80ouIw7SwSi1O7aqJJonSgZYfNY= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_on.png +SHA1-Digest: bs1vf9xjcGOwDrYbOQNH+pKlPs4= + +Name: system/lib/bluez-plugin/input.so +SHA1-Digest: fYOyLs9+Aurt1iwfF70oIdizAUs= + +Name: data/app/com.google.android.gms-1.apk +SHA1-Digest: dQ887zLtKJRIYH978Rlor18qK0E= + +Name: system/app/AndroidHtcSync.apk +SHA1-Digest: A8CPczjYJla7YfquRVTOyTkHkEQ= + +Name: system/etc/permissions/android.hardware.touchscreen.multitouch.d + istinct.xml +SHA1-Digest: +ecLNHyCJcTgt86gz93pkIwcJ+c= + +Name: system/customize/resource/allapplication_21406.xml +SHA1-Digest: aJB1oVeQabIXk7Y3CRsaTfTdBx8= + +Name: system/bin/sleep +SHA1-Digest: 9libFqVtNipfKd041p5ESQDBFG8= + +Name: system/app/CalculatorWidget.apk +SHA1-Digest: x/ub7xVYqs1jMOb0LEhx8607BNE= + +Name: system/fonts/AnjaliNewLipi-light.ttf +SHA1-Digest: TXtkBSsmdd04OAXePzPNnSx+Vdc= + +Name: system/etc/security/cacerts/4e18c148.0 +SHA1-Digest: AC2kb6vDxMM9PpuxWWSvwbGQ+fo= + +Name: system/app/Basic.apk +SHA1-Digest: s/q6lm+7Mas5AWRYH3UeF4p2G+w= + +Name: system/app/IMEXT9Turkish.apk +SHA1-Digest: yaNbDmiq5rarikNgk50f2owunG8= + +Name: system/etc/security/cacerts/ff783690.0 +SHA1-Digest: uwa7DANnTSVTBT+3cPJVrv4kphk= + +Name: system/lib/libwt6imgrdr.so +SHA1-Digest: qAz9KRSQZ4ARkADJgg+7d9lFOJc= + +Name: system/bin/app_process +SHA1-Digest: SbWVq4U5vPF+9w2KjoyzNs+f7tA= + +Name: system/lib/plugins/com.adobe.flashplayer/libstagefright_froyo.so +SHA1-Digest: ivPwyUrCdxDSFUy0G64Wg/GeeMY= + +Name: system/media/zchgd/batt_100.rle +SHA1-Digest: m5MSMDD1fADP9RFjYCJm6ZePUWU= + +Name: system/lib/libstagefright_soft_h264dec.so +SHA1-Digest: 5CxbjmGEBI+E3HV5y7IBS9V3yrQ= + +Name: system/lib/libhtcpainting.so +SHA1-Digest: BQZRmBf8uSofJQJIIz2cDHWbn3k= + +Name: system/lib/libssl.so +SHA1-Digest: ueOfAvZYcpT0MWWyQcFXxAhUul0= + +Name: system/app/HtcPowerManager.apk +SHA1-Digest: NSK9+iXszubPvzwIaux0dLKQxoM= + +Name: system/bin/radish +SHA1-Digest: vp5Tq2dMAydZc7s7toiy5uD+9c0= + +Name: additions/smson/app/Message.apk +SHA1-Digest: rnXZn//zi9kTkgyWdb1JrUYX5Hc= + +Name: system/lib/libicule.so +SHA1-Digest: ahqhxS2GoYeVil4hDe74ZUYIyq8= + +Name: system/lib/libsc-a2xx.so +SHA1-Digest: RbTsmTu0Hvn33r1Wsvz118iDuFc= + +Name: system/media/zchgd/batt_80.rle +SHA1-Digest: ehGvAsA5GM+eE+bBhCv+TuF9BEg= + +Name: system/lib/tcp-connections.so +SHA1-Digest: EAGdxWVXzqk8cAvf4BzcbAzcQsE= + +Name: system/lib/libwfdmmsrc.so +SHA1-Digest: Batr2a9f11vKqfI5wrhGVds6Lqk= + +Name: system/lib/libchromatix_ov5693_hdr.so +SHA1-Digest: sJXZQNj3m4GcGvb7zl/1Ry7dKCY= + +Name: system/media/audio/ringtones/Indigo.mp3 +SHA1-Digest: E2bt/jqisKGMUm+gaosWWZA0dbU= + +Name: system/app/IMEXT9Arabic.apk +SHA1-Digest: QXvKHafsRjZRgdBIUxXJ3TIsnBM= + +Name: system/usr/srec/en-US/hmmsyms +SHA1-Digest: Fln/PQLUYTKhhm652kNflbC8Bv8= + +Name: system/usr/keychars/Generic.kcm +SHA1-Digest: ydpzvFLPpnkO8f4mH6S/QxmVMkg= + +Name: system/lib/libawDTCP.so +SHA1-Digest: VbYMSaaCWvPo2icuBUGTE15woVE= + +Name: system/framework/framework-res.apk +SHA1-Digest: a5BEOfUTEwYHlewNixviAkByLwY= + +Name: system/etc/tfa/voip.eq +SHA1-Digest: qhH+GMu5vwrIEMn9ouJWtWCH9IY= + +Name: system/fonts/HTCHand.ttf +SHA1-Digest: F8IpJV/YMT1MEi/m47xfoNy/lR0= + +Name: system/media/audio/ringtones/Chrome.mp3 +SHA1-Digest: 9lO8Sem8vny1CNKUQWNbluuaVl4= + +Name: system/framework/javax.obex.jar +SHA1-Digest: VhRlDoSmpM2CksGp/86sLrZySNA= + +Name: system/lib/libicui18n.so +SHA1-Digest: VzBzwvx0JyY495rafK6iTs/Tx6M= + +Name: system/lib/libmmcamera_interface2.so +SHA1-Digest: EDV25daRYtU/uUlJWdIK6uZwErg= + +Name: system/etc/security/cacerts/e8651083.0 +SHA1-Digest: pTCqliEJ3Q0TNsBDd6B+1e0I5nU= + +Name: system/etc/ar0260_1 +SHA1-Digest: QKnM/RS5ae8QNcxDNUVma4emeqI= + +Name: system/customize/resource/allapplication_234.xml +SHA1-Digest: 8bJFZyeyXGbTHMqG6HEZ+20XZwA= + +Name: system/bin/dnsmasq +SHA1-Digest: AYRKrUNjSDGj9U9KYA6vt5b4vlY= + +Name: system/lib/libglib.so +SHA1-Digest: 5jCi0rSwNKHlCUm2nwVM19Gr4kg= + +Name: system/etc/firmware/ILP0100_IPM_Data_out.bin +SHA1-Digest: KfvuhMuBeWLwiIkDhxChUNVP+ac= + +Name: system/etc/security/cacerts/aaa45464.0 +SHA1-Digest: xpHvANASM4utyFC+6Q3F3wh1Ys0= + +Name: system/etc/security/cacerts/613f892a.0 +SHA1-Digest: u4UojKzGDVs3PoKEWKv6snsYrIE= + +Name: additions/fonts/roboto/Roboto-Italic.ttf +SHA1-Digest: 6rQE9q8RGQRSFqC5wj8x3cFu9kI= + +Name: system/bin/mm-venc-omx-test720p +SHA1-Digest: bhlK0w71+8orkuJV3R4wcwdhmuo= + +Name: system/bin/content +SHA1-Digest: PyF7E/iuWk4+agaPGfAomR/pre4= + +Name: system/lib/libFFTEm.so +SHA1-Digest: XP8nHO95883H6AqL5yYOLWRETFc= + +Name: system/bin/date +SHA1-Digest: PPXSdz4sEw5eZGPAdLJAqjoYN2A= + +Name: system/lib/hw/sensors.m7.so +SHA1-Digest: NtZAVC8zlOYhHlLLJ90WsRC55X4= + +Name: system/usr/keylayout/Vendor_05ac_Product_0239.kl +SHA1-Digest: aBBF8yCxbsyLsypxLAxv1OlR2pk= + +Name: system/bin/mm-video-driver-test +SHA1-Digest: IRToKXmHGv2upaAZxYVumUDUJtU= + +Name: system/app/Usage.apk +SHA1-Digest: UKtHxQn0YchgOYNUmNKAzwpTiV8= + +Name: system/lib/libsc-a3xx.so +SHA1-Digest: BIWGF+g3PxChWpt8QIB5qugtpGg= + +Name: META-INF/com/google/android/aroma/scripts/save.sh +SHA1-Digest: vrYK/AoRaZBx+okEOHmUzh0B74Q= + +Name: additions/fonts/klavika/Roboto-Regular.ttf +SHA1-Digest: ciaRq3tsOK/Ke/dK8uZAvJxJE3E= + +Name: system/bin/mm-pp-daemon +SHA1-Digest: tHi1QrgbtQr2H/mW5xEHNIzq8ps= + +Name: system/fonts/DroidSansEthiopic-Regular.ttf +SHA1-Digest: U8h+g8V+6bpPaxzFPXVV+bsYq74= + +Name: system/framework/core-junit.jar +SHA1-Digest: +AAsrrXAwIGmFNCFk5vEusCNIqU= + +Name: additions/fonts/segoewp/Roboto-Bold.ttf +SHA1-Digest: 3h0w/uUFFJnc1ex3BXWL82A8q4A= + +Name: system/lib/libhtccamera.so +SHA1-Digest: ZRFfdutSxi9pqtXtXJ9Yz+Uwn78= + +Name: system/usr/srec/en-US/endpointer_dictation.config +SHA1-Digest: j/ixWk0Vzc1Re76RugKSBPSkHbw= + +Name: system/media/weather/weather_thunderstorm_day.mp4 +SHA1-Digest: yh5iPUYR6jSsntfCorxoFyNs4Mw= + +Name: system/lib/libvideochat_stabilize.so +SHA1-Digest: txEUDS8EnRRlhU8NCE9ldcIfoOo= + +Name: additions/gps/south_america/etc/gps.conf +SHA1-Digest: 5GwTcGELf4z+xgYvn8fwD8bHP28= + +Name: system/lib/libmode10GLES20.so +SHA1-Digest: 5qSsIGqZhUNnNVJsgSXl6bXH5pQ= + +Name: system/media/audio/alarms/Celedon.mp3 +SHA1-Digest: pvg9awAINiFozX4Zov4xCO6VAIs= + +Name: system/app/HtcDialer.apk +SHA1-Digest: gZOejpO+sizM2ZkWaEaCeqfok5k= + +Name: system/lib/libchromatix_ar0260_zsl.so +SHA1-Digest: 9yno7wqwASdnJJNIG+JXnzwLaJg= + +Name: system/tts/lang_pico/it-IT_ta.bin +SHA1-Digest: t4tHCovvvrsnb4fc09cpVofPZOk= + +Name: system/bin/newfs_msdos +SHA1-Digest: KGdqAutaCs2PvkI4hG1nBQztpc8= + +Name: additions/fonts/sonysketchef/Roboto-Bold.ttf +SHA1-Digest: sta2G6y77yNSNg0upEmuXR4etKc= + +Name: data/app/com.google.android.gm-1.apk +SHA1-Digest: 4VBgzK9eIDMwgPYR4rbTRxJBIBU= + +Name: system/media/GPU/twoToneMaskH.bmp +SHA1-Digest: xWeWCFQ1Rp/R0fFb01M4TfLoY4Q= + +Name: system/app/Prism_AppUpdate_DummpPackage.apk +SHA1-Digest: AbCLTuM3f+iqnTX7E5lyDeaYpi0= + +Name: system/lib/libWVphoneAPI.so +SHA1-Digest: NeRHbPbXB5A6ls7y00dXUSefc7A= + +Name: system/etc/security/cacerts/aeb67534.0 +SHA1-Digest: ud63QfbrYmZs4yriaRbj9lIsun8= + +Name: system/etc/permissions/android.hardware.sensor.light.xml +SHA1-Digest: Pn0I13jrVn51nOyc4S/jiw/Xw6U= + +Name: system/lib/libchromatix_ov5693_preview.so +SHA1-Digest: 4gO38ZvRB8WqQ529SAwNcR1skl4= + +Name: system/app/HtcMusicEnhancer.apk +SHA1-Digest: kOcVPJp2lU3zbl2m21pJxL3r2T4= + +Name: system/lib/libmmmpo.so +SHA1-Digest: lpU59utd0Fadlo6fAtcN8c5oiJY= + +Name: system/media/audio/ringtones/Silver.mp3 +SHA1-Digest: cGHQTgTlkDHF4UwqLsZeuwyGB7U= + +Name: system/lib/libqmiservices.so +SHA1-Digest: EBsoJ0M6eLF3bAtpFzsLsR/1vPw= + +Name: system/etc/tfa/playbackbeats_l.preset +SHA1-Digest: Q0TZIziqcpclRmObniL1er8Got4= + +Name: system/lib/drm/libhtcomaplugin.so +SHA1-Digest: nMHqmgZFRAdNMAyEUgnuqpMWt1M= + +Name: system/lib/libimage-jpeg-dec-omx-comp.so +SHA1-Digest: 4DYGsXK/zOcrrlcdIAAsytw8vOE= + +Name: system/media/audio/notifications/Pine.mp3 +SHA1-Digest: 2THq5LMbYiDNI3m/yKRU9AB3RZU= + +Name: system/lib/libdmt_native_utils.so +SHA1-Digest: FX1lbng++9Gs8DDpIPaD3MLwUyE= + +Name: system/app/IMEXT9German.apk +SHA1-Digest: l11AQTg8B1cbRf1hG0kwe1AuR3o= + +Name: system/etc/security/cacerts/ed62f4e3.0 +SHA1-Digest: KW0dSbYbK/i9Crtcd9f/fVpSbDE= + +Name: system/bin/uiautomator +SHA1-Digest: EiHYAGH42TXmzxcRoUP3lkgEJMg= + +Name: system/bin/mm-video-encdrv-test +SHA1-Digest: f+KGvutmd/M+bw3AXIFQHb5zJdA= + +Name: system/media/audio/ringtones/Plum.mp3 +SHA1-Digest: RsGgQnEXfp+mFtCBZv9euT6b2dg= + +Name: system/bin/chown +SHA1-Digest: TrfLtV+viHMlpIimA1jIFQk3rCo= + +Name: system/app/MusicVisualization.apk +SHA1-Digest: llgR8WcTKjQ8knsmvNnraI/Iw9c= + +Name: system/etc/tfa/tfa9887.patch +SHA1-Digest: suMmSifogGempOYsW+xvvM+nBdE= + +Name: system/etc/security/cacerts/f61bff45.0 +SHA1-Digest: T+qB4/2WaUuV16PYtu7WwP3b0gE= + +Name: system/app/HtcLocationService.apk +SHA1-Digest: ul5Mizp1t3enKMj1cWeIRMoN/cQ= + +Name: system/fonts/RobotoCondensed-BoldItalic.ttf +SHA1-Digest: V7BP9MVj0P5pYIh0SmIaP/EMkQo= + +Name: system/etc/image_ibeats_v2_2vol.bin +SHA1-Digest: DnSL6Klxjoag7verZXjNCDqzDj4= + +Name: system/lib/libC2D2.so +SHA1-Digest: ZCQi1vZcYcKqfr+D5Uy17McH0v8= + +Name: system/lib/libhtcirinterface_jni.so +SHA1-Digest: p8EX57AmrP/L05qron9CBCOQ9iY= + +Name: system/customize/resource/quicklaunch_23210.xml +SHA1-Digest: Xu2aZuMkhrIRc7N0FElEaawAhBk= + +Name: system/media/audio/alarms/Beige.mp3 +SHA1-Digest: txglnjYcfUj6COkbCo2mlNMPxHI= + +Name: system/app/HtcCarGps.apk +SHA1-Digest: tEPFkAklXgA1Ka7VkDX+k/yFSiU= + +Name: system/etc/image_ibeats_solo_v2.bin +SHA1-Digest: v9Db4C6c+YeDp85uSvMWuN9hB6k= + +Name: system/lib/libOmxMux.so +SHA1-Digest: 7Yx11FnrxVUdIKiE92B/Jw4tG7Q= + +Name: system/bin/sensorservice +SHA1-Digest: 6iATkATjNRNF3YHr2F3U819IXzY= + +Name: system/fonts/DFHEIA5A.ttf +SHA1-Digest: 84Z3W6Q+eumM70rJDS/uGptCPHs= + +Name: system/usr/share/partials/partials.dat +SHA1-Digest: UTJxbMVvrG6dkhTB7qqPAN/2Cig= + +Name: system/usr/keylayout/Vendor_046d_Product_c294.kl +SHA1-Digest: FEu4tbv/pfG+jZWhYQQVPaclr8Y= + +Name: system/media/audio/ringtones/Snow.mp3 +SHA1-Digest: LZFG5uLY6WL/LSg29j69+5m2/g8= + +Name: system/lib/libstagefright_soft_h264enc.so +SHA1-Digest: AqeRtQnbC7K82K+2DfxdLslutso= + +Name: system/etc/init.goldfish.sh +SHA1-Digest: D3Ehu4SxtQQqVaZr1ifP/Prf93E= + +Name: additions/gps/north_america/etc/gps.conf +SHA1-Digest: DCebaPJa7hDrT9/6c1vxQyBkLFg= + +Name: system/app/Weather.apk +SHA1-Digest: L9Ok6edL+yV02GdlwcoZ5753Wc4= + +Name: system/lib/libchromatix_imx135_default_video.so +SHA1-Digest: /gfdOKFRcBuhF0K4aCFndg3O/HY= + +Name: system/lib/libthread_db.so +SHA1-Digest: vPJCBwzilN8TWjh4QlIOZZGMM+M= + +Name: META-INF/com/google/android/aroma/themes/sense/button_press.9.pn + g +SHA1-Digest: nL1yytK4nOHkeUrWs1fCO28OGzg= + +Name: system/bin/vdc +SHA1-Digest: oWcoYQLY9XoiTX2nLFqCZi6pkTc= + +Name: system/lib/libpagecurl.so +SHA1-Digest: z50tWJsW7DesATjOuO24BsPrm2o= + +Name: system/bin/qmiproxy +SHA1-Digest: DfDijwSciHTPbuAF2CZo7p8XPvI= + +Name: system/bin/getprop +SHA1-Digest: z4G855jswNjE/BhwYD7VGBBU2NE= + +Name: system/fonts/Roboto-BoldItalic.ttf +SHA1-Digest: b18bhiBhpPwzpvMDiEeVWLwx6Uc= + +Name: system/etc/security/cacerts/f4996e82.0 +SHA1-Digest: NFib+Gt/85AoEla6GdaHBKkqcA0= + +Name: system/usr/srec/config/en.us/grammars/phone_type_choice.g2g +SHA1-Digest: KPYJAVJTCr7vOBWM2qlErKU+otg= + +Name: system/fonts/Roboto-Light.ttf +SHA1-Digest: bpJiUAPuXulTMdeRsm1UuaCcnMo= + +Name: system/media/audio/alarms/Twilight.mp3 +SHA1-Digest: WY84OgsIc96QeCRipngQiDcvKIw= + +Name: system/app/Calculator.apk +SHA1-Digest: Y2oHvYw12kY2c60gWdc0ITN0SoY= + +Name: additions/gps/south_africa/etc/gps.conf +SHA1-Digest: NcoJGKFFd14LXP+sW0Syurx5VGY= + +Name: system/lib/libchromatix_s5k3h2yx_zsl.so +SHA1-Digest: JZkJ++64ERD5Z3lor9fiZMY2VXQ= + +Name: system/media/audio/notifications/Jasmine.mp3 +SHA1-Digest: 3VQZdT2cVc4F9VbbE6UGWrNgDcU= + +Name: system/usr/keylayout/Vendor_046d_Product_c216.kl +SHA1-Digest: 334eygJ7+pqLeyMJvz5L56ffVVY= + +Name: system/lib/libloc_eng.so +SHA1-Digest: IApohNePX8MPvlm/gKwaJOPR0Tk= + +Name: system/lib/libzeroeditor_jni.so +SHA1-Digest: omMS7BKsEHBPyt56nwP23MCMTWg= + +Name: system/lib/libmmjps.so +SHA1-Digest: FlJ5Yp/HRCr11TFCE/RUV94PM4k= + +Name: system/etc/tfa/video_l.config +SHA1-Digest: jWakpYCv2zkvgmSaBkeSMTiqNdM= + +Name: system/media/audio/ringtones/Ao.mp3 +SHA1-Digest: PQK7ZTe7oPTgTmPnk2JuYVHGXeY= + +Name: system/etc/tfa/playback_l.eq +SHA1-Digest: 5LAtUXn6Eyj3WC3JlRhpzZ/35Ng= + +Name: system/fonts/Roboto-Italic.ttf +SHA1-Digest: 5ipbgj463XjLbp5Mgkaxo9XZCDs= + +Name: system/media/audio/ringtones/Icterine.mp3 +SHA1-Digest: /wptp4Gq4I6FcOVl6kqAtJLvhWs= + +Name: system/lib/libbcinfo.so +SHA1-Digest: chlT4uOARA9QrhGj43rzh3jo6R4= + +Name: system/lib/libnfc_ndef.so +SHA1-Digest: 0c3Dddj4fbYCs30w0IFCcJNctBQ= + +Name: system/bin/notify +SHA1-Digest: rTWUwJn9oHB892gzXMc16hvae6U= + +Name: system/customize/resource/quicklaunch_420.xml +SHA1-Digest: JlAaOAkZTmVWQAl0p9WK6Y59IKc= + +Name: system/customize/resource/quicklaunch_21404.xml +SHA1-Digest: 1gtunsQsyygzOMyBCBKj/RVaKog= + +Name: system/etc/tfa/ring_l.preset +SHA1-Digest: +F37yHZP90FckmptjVvkAEKcJiE= + +Name: system/lib/libmmosal.so +SHA1-Digest: MuJA+Qi6+d26prR5vNGsT85ZPbU= + +Name: system/etc/tfa/playback_l.preset +SHA1-Digest: GULLLq6MoArA2166ns11ra2LXp4= + +Name: system/framework/com.orange.authentication.simcard.jar +SHA1-Digest: KYr204+jv13+8h2lS3qJVXf+3/o= + +Name: system/media/GPU/dot_mask_0.bmp +SHA1-Digest: ag0Fq3nt+YKQ74CbgAGPRZpR4J0= + +Name: system/app/IMEXT9Serbian.apk +SHA1-Digest: xbyby2PkrqtB3HAGCJBPS8EZSd8= + +Name: system/etc/security/cacerts/74c26bd0.0 +SHA1-Digest: JPSZvZ3Tx+8fME4kV3U1NQInDwk= + +Name: system/lib/libalsa-intf.so +SHA1-Digest: URj08O9p2YfgSgq5WSOY665/d8g= + +Name: system/customize/resource/icon_launcher_mail.png +SHA1-Digest: ktCYh5h+5iWLP1r1Z6Z8alABXaw= + +Name: system/lib/libOmxVenc.so +SHA1-Digest: cXe/TqyWZDyptEuz9wL+m8OCT3c= + +Name: system/bin/rtspclient +SHA1-Digest: 2YHz3OJkGrzvule+bJnu11xwNN0= + +Name: system/framework/com.playstation.playstationcertified.jar +SHA1-Digest: FrfFys+jI//GV1lOK2lpJiUYcv0= + +Name: system/fonts/Lohit-Kannada.ttf +SHA1-Digest: qHTrL92TrDbIdXwjer7+zqQUZf8= + +Name: system/usr/keylayout/synaptics-rmi-touchscreen.kl +SHA1-Digest: m5ofoFqImJCHzLiS6dJEgE6OlRg= + +Name: system/lib/libutils.so +SHA1-Digest: HjaAyeXA2S0jyVVbuMBQJlqqYs4= + +Name: system/lib/libc2d2_a3xx.so +SHA1-Digest: GaBWy1TM2uDZMwHJwIs0C7oAZQ0= + +Name: system/etc/tfa/video_l.preset +SHA1-Digest: XZ+MlvUOVl9GLYT8SwnELn0W+z8= + +Name: system/xbin/dexdump +SHA1-Digest: DjHijikQSM1xS5/1fnUy6DNUN8Y= + +Name: META-INF/com/google/android/aroma/icons/apps.png +SHA1-Digest: Zk3Qpx7ckFAxEptOqb7dNE8H5Eo= + +Name: system/app/MediaUploader.apk +SHA1-Digest: GcIaJ12HGP/78kaXOiG3tLUvftg= + +Name: system/etc/security/cacerts/a2df7ad7.0 +SHA1-Digest: RjuHalVKlyJZTzlSUI6VbkP70KU= + +Name: system/app/IMEXT9BahasaIndonesia.apk +SHA1-Digest: AlIJ8Iayp3+++2u3NTW5RIq2vIU= + +Name: system/media/weather/weather_hot.mp4 +SHA1-Digest: 1/Bzu8Of0SzR+HJB21HfMOVataw= + +Name: additions/camera_4.2/lib/libjni_mosaic.so +SHA1-Digest: Zv0SR3lCdDUVMNHKxmE9n8oGiPI= + +Name: system/app/GenieWidget.apk +SHA1-Digest: z+W0UnPRAxfnRwcVSgyKl6byn6I= + +Name: system/etc/security/cacerts/a7605362.0 +SHA1-Digest: Z0AbnajZ3GPkGwTegW8+BCjdbFI= + +Name: system/usr/share/partials/partials_A_bb.csv +SHA1-Digest: tvd7LYflGgVMWsB919FkEVJrPzs= + +Name: system/etc/security/cacerts/56b8a0b6.0 +SHA1-Digest: BbeXAaF1+TrUH67tzOrpG2PoDbM= + +Name: META-INF/com/google/android/aroma/icons/install.png +SHA1-Digest: wumpyMrgwC25f10MrBJ2W1MnF2s= + +Name: system/customize/resource/icon_launcher_hotmail.png +SHA1-Digest: lMcd7sRaou47W+UVAGdK/RDoy8M= + +Name: data/app/com.google.android.youtube-1.apk +SHA1-Digest: Ctg53ZZS/YBx1d7B7eu66psmuwo= + +Name: system/lib/addict.dat +SHA1-Digest: D7FAhoXfMRz2YXQ4GYk2ELF0MHo= + +Name: system/lib/libnativedocviewer.so +SHA1-Digest: l9Z8+bRQs9H6rSIrpapUgoyPq6c= + +Name: system/media/GPU/CurveSepia.bmp +SHA1-Digest: ZejsYRyq+WQjBq0RzqkGT0nxA4Y= + +Name: system/bin/netsharing +SHA1-Digest: gcFLn/w8oetZXVCoQNuc+hQBOGw= + +Name: system/app/Phone.apk +SHA1-Digest: FaakWN7ffUTcgaBopUNX3yiT4dA= + +Name: system/media/zchgd/charging_04.rle +SHA1-Digest: dOSxjb6Cm7yRboOF3ohM3RySLsw= + +Name: system/lib/libchromatix_ov8838_zsl.so +SHA1-Digest: j252XxBe46QzAO0A504mkDM/Le8= + +Name: system/app/PureC_ApplicationsProvider.apk +SHA1-Digest: oZWU6jAUb7b/wK9Mp+1R407wYUQ= + +Name: additions/fonts/ubuntu/Roboto-Regular.ttf +SHA1-Digest: wuI0G6Y816DgS7XtXxCYzEWQDyM= + +Name: system/lib/libbluedroid.so +SHA1-Digest: jdOd3wszmJPIirQPqfavNqA8FmE= + +Name: META-INF/com/google/android/aroma/requirements.txt +SHA1-Digest: Rohd883z51SfKNiUGz8Yu/xk/sc= + +Name: system/customize/resource/allapplication_21408.xml +SHA1-Digest: 4F2ptWc2oWGSU1g8OiVmZhU1s+E= + +Name: system/fonts/DroidSansMono.ttf +SHA1-Digest: c95nnXS8f3Ki6JMBrBxt2DG/pB4= + +Name: system/framework/android.policy.jar +SHA1-Digest: Ufq+iNGNjOZzYUnKDu7S4cIW5q0= + +Name: system/lib/libHTC_DIS.so +SHA1-Digest: 8EvgK+H8mHa+tx8131mKhZpwInE= + +Name: system/customize/resource/quicklaunch_21407.xml +SHA1-Digest: 5LrDADj2+VcxMPEOMe83X0srzek= + +Name: system/lib/libdsi_netctrl.so +SHA1-Digest: E2t1cPdZBHDFbRSyjWq+uQgrzoo= + +Name: system/etc/security/cacerts/7a481e66.0 +SHA1-Digest: Qrug23rc7GLUystiW+B7d4bzaJw= + +Name: META-INF/com/google/android/aroma/themes/sense/button_focus.9.pn + g +SHA1-Digest: StAvalhPxNmH70D4vXRIHmO6ASU= + +Name: system/lib/libnotesprovider_jni.so +SHA1-Digest: V3IY2du9sl/h7ESQH9spJ8Z93vI= + +Name: system/media/GPU/dot_mask.bmp +SHA1-Digest: 3O94/Rp7XSC2nwJfLxNRRuPcZ08= + +Name: system/app/IMEXT9Danish.apk +SHA1-Digest: iaQ08LYCLXAi4Lbn2UDfKrXu1Vc= + +Name: system/etc/security/cacerts/5a3f0ff8.0 +SHA1-Digest: ZHheT+DD2seVYhDReWK8HQa1FoY= + +Name: system/app/WifiRouter.apk +SHA1-Digest: 3bRUJFeCNFy33tKT8zRQB65qL00= + +Name: system/media/audio/ui/KeypressStandard.ogg +SHA1-Digest: WSD7VCgtBBhkGoFGei4G/W0G3Kw= + +Name: additions/fonts/ubuntu/Roboto-Bold.ttf +SHA1-Digest: g30zOU7f6Pdfabgd91hK6ajDgVA= + +Name: system/lib/libGLESv1_CM.so +SHA1-Digest: 0kcTNT8GRMG9AKHtn9nDyE0FZbk= + +Name: system/lib/libeffects.so +SHA1-Digest: LvAbIGjxHSCSV3rnyBDTdLQfztg= + +Name: system/app/IMEXT9Slovak.apk +SHA1-Digest: RIsbdqmAgNZZ2lKqjceaAdpEYYw= + +Name: system/lib/libmmcamera_image_stab.so +SHA1-Digest: BUX1fzicFOtz4r+pOF7nnWZVNaY= + +Name: system/etc/security/cacerts/e48193cf.0 +SHA1-Digest: UXw27ZZFF2Dc7iZjui9EOHuDgpQ= + +Name: system/etc/security/cacerts/4d654d1d.0 +SHA1-Digest: RiffZAyYlk3Z5RE5r3Eimp4hoCQ= + +Name: system/lib/libchromium_net.so +SHA1-Digest: dKicHajqfxlnMy5+E3lkV392glQ= + +Name: system/lib/libdrmframework_jni.so +SHA1-Digest: mxmw4qMThZTp1ISQA7/Zv4dhOlw= + +Name: system/lib/egl/libGLESv2S3D_adreno200.so +SHA1-Digest: yKrF37f31+7nk6dPn6o1tmOOKt8= + +Name: system/customize/resource/allapplication_27205.xml +SHA1-Digest: dHEgc+kr2e2cfpg63/GdSSMLFks= + +Name: system/media/zchgd/error.rle +SHA1-Digest: 4QY+gkSiSwxpDnYvfNqpERxsSc8= + +Name: system/lib/libchromatix_ov2722_zsl.so +SHA1-Digest: x8VXF9/c4j6iDwEERrseVcV3TGs= + +Name: system/fonts/Roboto-LightItalic.ttf +SHA1-Digest: /WLukeHzJHHKYaWWlSfU7iLz6Ug= + +Name: system/lib/modules/qcedev.ko +SHA1-Digest: xXBoXivuETB8J7IGCAWdcjPqU6U= + +Name: system/app/Automotive_InternetRadio.apk +SHA1-Digest: WPeYPFDAcVZM9QV+sR0XpevabFI= + +Name: system/app/FlexNet.apk +SHA1-Digest: UnPV413Umm3CpBCiHkhvutPo8Ng= + +Name: additions/fonts/sonysketchef/Roboto-BoldItalic.ttf +SHA1-Digest: dXgXv+z3vAUFYteuuYcX71L5ETo= + +Name: system/etc/permissions/android.hardware.telephony.gsm.xml +SHA1-Digest: VedgY17d+3Q4Wvr4BUBh8n6kIt4= + +Name: system/usr/share/partials/partials_A_gr.csv +SHA1-Digest: /n9Urmy7jVo/AGrw22Fh4RAv0gc= + +Name: system/customize/resource/wallpapers_b_03.jpg +SHA1-Digest: dFczPlC3dQas2UTFBN2X5h1G2Qg= + +Name: META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf +SHA1-Digest: 44m+VfT30MwizlyBK13EzrelmyY= + +Name: system/etc/firmware/lscbuffer_rev2.bin +SHA1-Digest: oee0bMCVNFyjMOeZqtb5Go6U0ho= + +Name: system/framework/HTCCommonctrl.jar +SHA1-Digest: QAWIw4tIgHuSFb5YVTfWkhTPwgM= + +Name: system/media/audio/alarms/Chartreuse.mp3 +SHA1-Digest: MBQlhEXTTaIX9ASLApP3V3juhxo= + +Name: system/etc/searchabledb.conf +SHA1-Digest: S5y/v4ny4JTeqbtLO0+RgkxoacA= + +Name: system/app/LinkedIn_Fsplugin.apk +SHA1-Digest: LqIqPYolDj505Mw8JCbo9NBakyI= + +Name: system/media/weather/weather_snow_night.mp4 +SHA1-Digest: eALDZ5DDW0sZpO09jQoEKI33GIA= + +Name: META-INF/com/google/android/aroma/icons/default.png +SHA1-Digest: Yhs0q06XbKp0vJUs91GNf1iJJjM= + +Name: system/media/audio/ui/Volume-3.flac +SHA1-Digest: oesbXHtU6zkl91dasm+wDrAqk98= + +Name: system/media/weather/weather_l_snow_night.mp4 +SHA1-Digest: sTLivo4tZrqfKJQ687oiIvGMzIU= + +Name: system/etc/security/cacerts/ab5346f4.0 +SHA1-Digest: JR31iZjUtae696itSOA/gRp+YY0= + +Name: system/customize/resource/quicklaunch_26003.xml +SHA1-Digest: eCqFT9mQwBYwsexrenDL+hgEq9c= + +Name: system/etc/security/cacerts/c215bc69.0 +SHA1-Digest: n3bzg8K5bD8w4yGFJSki+vVIDiw= + +Name: system/etc/security/cacerts/6fcc125d.0 +SHA1-Digest: dxoW8n5icyMm+Np/IAxgMBCnnt8= + +Name: system/lib/libcamera_client.so +SHA1-Digest: nZNA0I4cbZVXDUGO7/lGs7YDGbQ= + +Name: system/app/IMEHWRPenPower.apk +SHA1-Digest: EOVTOqTPWCK/B+RbLU20PS7UTpA= + +Name: system/lib/libNewTimeBreakin.so +SHA1-Digest: jLtJv7uQXFMse2QEiR50MxYQaS8= + +Name: system/etc/bluetooth/network.conf +SHA1-Digest: crKuOFEm+RBwaID7QozPTtbB6YY= + +Name: system/media/audio/notifications/Peach.mp3 +SHA1-Digest: 7XPoBTFTNcWHlmUFXG88WTBEzdc= + +Name: system/etc/security/cacerts/7d3cd826.0 +SHA1-Digest: 9A93UolYEp2zLqOTDQS6H+32euM= + +Name: system/bin/bootanimation +SHA1-Digest: WIf2qfyvaymeBbRa/QfqcDShmGU= + +Name: system/app/HTCSetupWizard.apk +SHA1-Digest: RBoywLBY4YNJLdr7+bh0N1u51lM= + +Name: system/lib/modules/reset_modem.ko +SHA1-Digest: KoazTbClyBu4PoR4uYCTCBIXRRI= + +Name: system/customize/resource/wallpapers_a_06.jpg +SHA1-Digest: U/n8WL22D0JlovZwc2nadcaf0yI= + +Name: system/lib/libnetlink.so +SHA1-Digest: jWveqHbWqI3y2/+uYDfmK7p3R1w= + +Name: system/media/audio/ringtones/Aero.mp3 +SHA1-Digest: c6wbkxr7eg01qydYj/FDWzetiZQ= + +Name: system/lib/libwfdsm.so +SHA1-Digest: oiar2HEK1wgfvtfU/LGzFxeAkcQ= + +Name: system/framework/com.android.location.provider.jar +SHA1-Digest: t8pRLzCXgm0n9b5u5NCaqOLH/P8= + +Name: system/bin/flash_camera +SHA1-Digest: h7mzWBfoTG96QT7sKefJ3Gnxtrc= + +Name: system/etc/firmware/tzapps.mdt +SHA1-Digest: pO2z0RNhw36QckT77RaDpqfO1AY= + +Name: system/media/audio/ui/VideoRecord.ogg +SHA1-Digest: op0jkXcHGjUiRs4Ps9209mGlsNE= + +Name: system/usr/srec/config/en.us/dictionary/basic.ok +SHA1-Digest: jtEEAE60jUZP6V7Rz23Hu8XXsMo= + +Name: system/bin/screencap +SHA1-Digest: sp32egnkI9v6643+kB/clgBXnpc= + +Name: system/customize/resource/allapplication_24007.xml +SHA1-Digest: LXs6oMVyHiFgB+3JJh5c3mTmehA= + +Name: system/lib/libalmashot-clr.so +SHA1-Digest: qTetNE+Fv/XMNLWx/V8J+q9WXfM= + +Name: system/bin/radvd +SHA1-Digest: nS+OsUl5EglEotSm4cHPFQq6OWA= + +Name: system/etc/security/cacerts/594f1775.0 +SHA1-Digest: b8fylO1vYs50OMpD7EuUt+mZmQs= + +Name: system/app/HTCSyncManager.apk +SHA1-Digest: TtUnTimsyXFl0rWogBrqpq/0z/8= + +Name: additions/fonts/asap/Roboto-Bold.ttf +SHA1-Digest: V4dKj2LU73Tfslr8kvC160T9pdo= + +Name: system/bin/bridgemgrd +SHA1-Digest: Dph+C9/+nJbwip5I9h0YioIGSy4= + +Name: system/usr/srec/en-US/clg +SHA1-Digest: M1NeTS6D64i9L1/b+048/LDqKe8= + +Name: system/etc/security/cacerts/2fa87019.0 +SHA1-Digest: RI7spWByA4m8BiATKQhVCZPh1kg= + +Name: system/app/Idlescreen_Base.apk +SHA1-Digest: mrnftpKmMyeemqLyLRvlNc3Bgok= + +Name: system/etc/thermald.conf +SHA1-Digest: ShcUv8dFRGpmiR3HPmLIuaYVsis= + +Name: system/etc/event-log-tags +SHA1-Digest: W0Oja3PYmai+SyVOi9tXyi3WYYE= + +Name: system/bin/mm-qcamera-testsuite-client +SHA1-Digest: 9BA2kenPlvvGn5+nafrWhkb7uMI= + +Name: system/etc/calibration +SHA1-Digest: XN6cTQaTuXiZubymE7rO1sZuLos= + +Name: system/fonts/DroidNaskh-Regular-SystemUI.ttf +SHA1-Digest: bwVSgcJ3NdZfsnHmCZ2QrM7zjB8= + +Name: system/app/IMEXT9Greek.apk +SHA1-Digest: 6cL7jr3h3HFGe0CN2GVxLBuLtLI= + +Name: system/usr/keylayout/Vendor_22b8_Product_093d.kl +SHA1-Digest: 94UqYM02uQuqPT7U58C9UD8Plaw= + +Name: system/xbin/busybox +SHA1-Digest: 8E/3tj8N2azeeWgsnWOtitpoXR8= + +Name: system/lib/libchromatix_ov2722_preview.so +SHA1-Digest: ZsHx9LcvmZgp6rVa4LAeHB0Ver0= + +Name: system/app/Twitter.apk +SHA1-Digest: wve6Tcoo2Jcf+orWhjRDoeE6sBA= + +Name: system/etc/permissions/android.hardware.sensor.compass.xml +SHA1-Digest: PruFWW+ufsGh/T3LCec2MGlHPeA= + +Name: system/bin/mm-jpeg-enc-test +SHA1-Digest: e/wL022CV/Q6itXE78UvZbKx5ps= + +Name: system/etc/security/cacerts/fac084d7.0 +SHA1-Digest: kVbZi1tMnjKCdaDIG1+QC0uymEk= + +Name: system/lib/libqmi_cci.so +SHA1-Digest: ourvnfDszP3F5L9EkgF7EocjTLw= + +Name: system/usr/srec/config/en.us/models/generic8_f.swimdl +SHA1-Digest: OUQtGxyzBG46RkofSQn8ez34OlE= + +Name: system/customize/resource/icon_launcher_gmail.png +SHA1-Digest: lUDKBTZUS81T4wP9tWC9ap5ch5U= + +Name: system/bin/usbhub +SHA1-Digest: vNgBg+PGdm7KUSyxNl0KmHFfYMA= + +Name: system/bin/vold +SHA1-Digest: hNTtIgGtMZGRnow9UmwvEHZQE0A= + +Name: system/app/Watch.apk +SHA1-Digest: iXG5DzpfZX3OCdQlRfnWUW5TNHw= + +Name: system/usr/keylayout/projector-Keypad.kl +SHA1-Digest: 3Ti3XtXwuJ1ydUUHapHUPYRLQZo= + +Name: system/app/FaceLock.apk +SHA1-Digest: NuhH6Nrj9YmtE/+I9tcS1qZx6cs= + +Name: system/fonts/RobotoCondensed-Regular.ttf +SHA1-Digest: mB9hDORpS3N2Odl07kEleF5SRy8= + +Name: system/media/audio/notifications/Almond.mp3 +SHA1-Digest: K0J803ByerQfJSjZHZXKlxv9lkw= + +Name: system/usr/srec/en-US/google_hotword_clg +SHA1-Digest: LMFoDJ5AhwQs1sYdBn6Cw/fH1cE= + +Name: system/bin/ime +SHA1-Digest: RpNbbWSd+bvmP5Bk8IPErzl4iN4= + +Name: system/etc/timezones.db +SHA1-Digest: qlHmvXKew9L7FiRRraI6IR23kUE= + +Name: system/media/audio/notifications/Teal.mp3 +SHA1-Digest: vjuO4xWewe4g9SLni1O49s3+UiM= + +Name: system/media/weather/weather_l_clear.mp4 +SHA1-Digest: WLcDczYS8xCr70fWqZ1rSLVxv7Q= + +Name: system/usr/srec/en-US/embed_phone_nn_state_sym +SHA1-Digest: WdfxealU/CvP2D0CmAfrqDt16J0= + +Name: system/lib/libacdbloader.so +SHA1-Digest: /Ar64yl/+gVpOX6DJNrWflhnmj4= + +Name: system/usr/srec/config/en.us/models/generic8.lda +SHA1-Digest: OYQ/W3VpcPHMWi23NHXjTYvQcIM= + +Name: system/app/Prism_AppUpdate_UpdatingScreen.apk +SHA1-Digest: h/aOTRHM0gJyWSV6oznA8PPCmoI= + +Name: system/etc/security/cacerts/ed524cf5.0 +SHA1-Digest: YUUDaE+eI4AQpO1M9Eel4WIxTGI= + +Name: system/etc/security/cacerts/9ec3a561.0 +SHA1-Digest: qRdHoQ5ZrOBV71toEWCbreo7vPM= + +Name: system/customize/resource/quicklaunch_65510.xml +SHA1-Digest: rqyrBJ+PS7IAJaHdd061sYDvkfo= + +Name: system/etc/security/cacerts/7999be0d.0 +SHA1-Digest: Y1fSp79Il7ssJJxn6Hi1lfyqI5Y= + +Name: system/lib/libchromatix_vd6869_night.so +SHA1-Digest: 60qhiT7TfN1d4gt12zxo4GZR6nw= + +Name: system/app/MyPen.apk +SHA1-Digest: ScWpivpwpsel+monzq4g/qaCr+Q= + +Name: system/bin/DxDrmServerIpc +SHA1-Digest: 8dD5qK0EfR3Cv+0yPtp5+KCigRo= + +Name: system/lib/libkeystore_client.so +SHA1-Digest: bl/SgJ77PeH9wMUPo4Esfl64TjY= + +Name: system/lib/libgemini.so +SHA1-Digest: mdFZ/KR9JJ0m2AkPKPeHnpqlFYY= + +Name: system/lib/libz.so +SHA1-Digest: Fs3dZaHzM87UPD3iacqO/uwNoqc= + +Name: system/bin/requestsync +SHA1-Digest: XkE8EJuMNX9lldXnHHdHoskUaeE= + +Name: system/etc/security/cacerts/111e6273.0 +SHA1-Digest: Ws4Pq966Jvp4ZXfGW5/zAefw3Es= + +Name: system/lib/libcneapiclient.so +SHA1-Digest: gA7oWvyOtuGAmYHt2f+GWyhyUPI= + +Name: system/etc/cir.img +SHA1-Digest: jnGPsNcYFTpehrTBOhSUsHTkM9w= + +Name: system/etc/security/cacerts/e60bf0c0.0 +SHA1-Digest: qso/01ui1WfhOpSAedhVrLUBpW0= + +Name: system/customize/resource/allapplication_20210.xml +SHA1-Digest: bg6ngqGb+g4Lb2WVz3eNFX40VKM= + +Name: system/etc/tfa/recorder.config +SHA1-Digest: ykYYK/c2dcBU73ncRP03GbucjOI= + +Name: system/etc/firmware/a300_pfp.fw +SHA1-Digest: pH7SOSDvT0+QoaQLwmjMzdNEEpE= + +Name: system/media/GPU/twoToneMaskV.bmp +SHA1-Digest: 2zakIRZyyu3xXJ1BjXYCfW0Bkhw= + +Name: system/etc/security/cacerts/3ad48a91.0 +SHA1-Digest: HZXjr9IxEdl/bLsWXl0vBzOswmE= + +Name: system/bin/amix +SHA1-Digest: GJXunroM9gUTI/S0TY4o7UUBEO4= + +Name: system/media/weather/weather_l_rain_day.mp4 +SHA1-Digest: st5DdhjDvFtSNyAjdLtQss95hkM= + +Name: system/lib/libmpl.so +SHA1-Digest: 0vf4hGZ+KUPyvaUTJp2YNOVN6R4= + +Name: system/lib/libposteffect.so +SHA1-Digest: lMi3p+1Pqqfkfh2r/N7xD4utEhk= + +Name: system/etc/init.qcom.post_boot.sh +SHA1-Digest: hx6jFq2OrLUDHDL7/ZNJNuKkhmY= + +Name: additions/camera_4.2/app/GalleryGoogle.apk +SHA1-Digest: eXI+kl1iz9x08xyjtcAlh274qo0= + +Name: system/etc/bluetooth/main.conf +SHA1-Digest: 5RkqoQQaXaFMJREY82g5hwcE1PM= + +Name: system/tts/lang_pico/fr-FR_nk0_sg.bin +SHA1-Digest: uJPDIkoo44Xdhg1IvPQ7n+AiG7M= + +Name: system/etc/security/cacerts/3c860d51.0 +SHA1-Digest: 3MirMMMxVPDIjrUJzJT9kQaASwQ= + +Name: system/app/IMEXT9Polish.apk +SHA1-Digest: ViD31OrtgfWeczVelW6U9hVD9Ks= + +Name: system/bin/vmstat +SHA1-Digest: qPoTHrfziBT1aLF78BsObMPg8u0= + +Name: system/lib/libemoji.so +SHA1-Digest: gRBMqCTHrajikXG3qvHtKWdAOWg= + +Name: system/lib/libstagefright_soft_mpeg4dec.so +SHA1-Digest: JwckNPKVzwn+D9RKgnj6/7k3eaA= + +Name: system/framework/framework-htc-res.apk +SHA1-Digest: dL/kBADS3oeD2aweqViA1xq2bKs= + +Name: system/app/SenseTV_Home.apk +SHA1-Digest: OtlHr1JtTra5rIXT0gsERklHiIE= + +Name: system/media/weather/weather_windy_day.mp4 +SHA1-Digest: RD30Nd1OvTGema47qPZKWCcCDrI= + +Name: system/app/HtcAutoRotateWidget.apk +SHA1-Digest: aSqKAV7cKN6cA8SjEE1R0yOrqT0= + +Name: system/lib/libwt6hpprndrv.so +SHA1-Digest: PqILQalRMzCIyJILAUNHxzVHuzw= + +Name: system/media/audio/alarms/Rajah.mp3 +SHA1-Digest: wdkZ5eh29OaTLbvZiektybOsjCo= + +Name: system/etc/PCTOOL.ISO +SHA1-Digest: /hLdJwScogPQLq12OmEg/cXu3y0= + +Name: additions/fonts/ubuntu/Roboto-Italic.ttf +SHA1-Digest: NUvpq8QWMFIJpZk9jrI/Us11tNc= + +Name: system/app/Stock.apk +SHA1-Digest: GrO7UBMjFChYld+DMqFZK8SBNUU= + +Name: system/lib/libsystem_server.so +SHA1-Digest: UnCvIb6pqZLLjjmulWXOyudUbmU= + +Name: system/etc/security/cacerts/9339512a.0 +SHA1-Digest: mQ4WSgNEy6kTq/gCEHGaZMW5sY0= + +Name: system/app/LMW.apk +SHA1-Digest: MFRK/FnyyI5aKLP6wE8/tgQ3Mlw= + +Name: system/bin/charging +SHA1-Digest: a2UWJwJdGPmimWYLnc4sTN5aGY4= + +Name: system/app/IdleScreen_Photo.apk +SHA1-Digest: bfZTpKNfXv/ffNxO5UEvvfCIvRs= + +Name: system/etc/permissions/android.hardware.wifi.xml +SHA1-Digest: oHkBECWfFLtDqANIBIPZoPQ2mkU= + +Name: system/bin/racoon +SHA1-Digest: llJyjXiPfXEnwCmt94BpGyGA3lI= + +Name: system/bin/netstat +SHA1-Digest: KUzhcfJlDVdkejY7AYglLJLTtbE= + +Name: system/etc/security/cacerts/f80cc7f6.0 +SHA1-Digest: W8bDrAuHeemBUG1E6My97G/SuFg= + +Name: system/usr/srec/en-US/g2p_fst +SHA1-Digest: l8/XYD+Shc9RuLVFVZjR/GYc/Us= + +Name: system/customize/resource/allapplication_20810.xml +SHA1-Digest: 41S0C1M7DZXYQ4mmP5w7aSg87No= + +Name: system/app/GoogleCalendarSyncAdapter.apk +SHA1-Digest: PzwMbvQgDD2z0/5nlE/GYFiuGkE= + +Name: system/etc/security/cacerts/69105f4f.0 +SHA1-Digest: jltP5Tn1V+xLjDQLZwAgoHqzxc0= + +Name: system/etc/bluetooth/input.conf +SHA1-Digest: Y/By99uRCUpOsQ7WtQZrnrEoLaI= + +Name: system/etc/image_ibeats_solo_v2_2vol.bin +SHA1-Digest: VgoVxk9+8ojZmlWclTuFKD9a0cQ= + +Name: system/lib/libwfduibcsrcinterface.so +SHA1-Digest: +wLbg7IUzVCW2OEbukzp2uOf70w= + +Name: system/bin/lsmod +SHA1-Digest: AZ+2VohmiVR9xQaVrDBXqxEmonY= + +Name: system/customize/resource/allapplication_23420.xml +SHA1-Digest: CZHdqJr20PAgttOkUmxWoR1Lv2s= + +Name: system/etc/security/cacerts/5cf9d536.0 +SHA1-Digest: EX93MpxobY/BeHpdRW+gBO+pVKE= + +Name: system/app/HoloSpiral.apk +SHA1-Digest: 2SlfN9VMTyZPR93kweAM1I7VxXo= + +Name: system/bin/reboot +SHA1-Digest: /dXywgBL1YWDV3o+cEpCwrLmB8U= + +Name: system/lib/hw/audio.a2dp.default.so +SHA1-Digest: LGyb83q2jGUyuLDLLZP9b346xqk= + +Name: system/etc/firmware/fw_bcm4335_b0.bin +SHA1-Digest: /lJcLfK8cwy7GE8BGUCGA34wQr0= + +Name: system/media/GPU/header8bpp.bmp +SHA1-Digest: ssnGfYivLrVgcmXAPAgseLpV7Bs= + +Name: system/lib/libchromatix_s5k3h2yx_default_video.so +SHA1-Digest: 6ewCy57u4uyD+rnf0t1cbl7ITEA= + +Name: system/etc/tfa/voip_l.config +SHA1-Digest: M1+NT3W/Jlju4Qu5UbGbWRBMoRA= + +Name: system/lib/libstagefright_soft_vorbisdec.so +SHA1-Digest: VPmV56HIERjGd55K7m2T2wagS7g= + +Name: system/lib/libchromatix_vd6869_zsl.so +SHA1-Digest: 4LvUDP0T/e9IiadvtZqAEX5YcuA= + +Name: system/bin/htcfs +SHA1-Digest: 1LWOQTHfhcKFvit2sKy9pXzrq7o= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/left_eye-y0-yi45-p0-pi45-r0-ri20.lg_32/full_model.bin +SHA1-Digest: dwEn0myGUfjd7vy7JX7yh6urTJU= + +Name: system/etc/security/cacerts/fb126c6d.0 +SHA1-Digest: 7lobtNCl//Q03nIbGlcwTyJqJGc= + +Name: system/usr/srec/en-US/rescoring_lm +SHA1-Digest: 3WHFz2o3uGTMAlgIyQ+ZXBCk66w= + +Name: system/customize/resource/allapplication_21403.xml +SHA1-Digest: mPk9sa5nDdZR08spwn/ba9ppttg= + +Name: system/customize/resource/allapplication_23806.xml +SHA1-Digest: 6EyS0LK6bFutLEiv7ArNexEofVU= + +Name: system/etc/security/cacerts/ccb919f9.0 +SHA1-Digest: 7VWT/WcAU6T9mjvE7onES7hpMbc= + +Name: system/etc/init.d/96Tweaks +SHA1-Digest: sf8jHA3f3isYP7kibOFa0E3BuXQ= + +Name: system/usr/srec/en-US/ep_acoustic_model +SHA1-Digest: TRJvr6ElzKlRSjdRODtxGDwejN4= + +Name: system/app/HtcGpsWidget.apk +SHA1-Digest: ab4AVHlWP+1UW/R4oFu/6wCvGPI= + +Name: system/etc/media_codecs.xml +SHA1-Digest: 0SVknIR5QUYdXLP236lVtGwwdSY= + +Name: system/lib/libwfdmmsink.so +SHA1-Digest: PHoy+HDlRdMfDNILGRvVaffhGj0= + +Name: system/etc/tfa/voip.config +SHA1-Digest: DFdN8cNIlzLvqILuqsVDvHJ2+9k= + +Name: system/lib/libui.so +SHA1-Digest: u0aNwBPXeB7lT4wl6k7TFobCy0U= + +Name: system/etc/security/cacerts/19899da5.0 +SHA1-Digest: Wzo6JYKWmTiD3ttZm0h2QNK9HrA= + +Name: system/lib/libfrsdk.so +SHA1-Digest: alZ3crgL13yR0dD68lcHixDzRd8= + +Name: system/usr/share/partials/partials_CW_gb.csv +SHA1-Digest: lsgq0ojgoiKAq3w+Ga7cZFz6JjA= + +Name: system/etc/security/cacerts/bf64f35b.0 +SHA1-Digest: PatpGMTkqlaTNx343GS4IRRAciA= + +Name: system/lib/libchromatix_ov2722_default_video.so +SHA1-Digest: 3zZBMr2Qn9yg3YUmki02ldSHhJs= + +Name: system/lib/libOpenVG.so +SHA1-Digest: 7lwwhQd/M3cqsw1Zx2oWeGvYMTA= + +Name: system/media/audio/alarms/Topaz.mp3 +SHA1-Digest: tj13XPSUlh9+tOQiMkP08fSbeGQ= + +Name: system/lib/libmm-color-convertor.so +SHA1-Digest: tr0uHzgcPD5sPb7wYfH1jcRZQf4= + +Name: system/etc/security/cacerts/ddc328ff.0 +SHA1-Digest: UgwJP9g4O1D5SSYH0ozmn6x/BKg= + +Name: META-INF/com/google/android/aroma/themes/sense/select.9.png +SHA1-Digest: wlV86JXTAm/MyV8VgyAjgNkhNWo= + +Name: system/etc/hsml.key +SHA1-Digest: myTg62oTw70c+xnz2HxdGE5Lsfk= + +Name: system/lib/librtp_jni.so +SHA1-Digest: zTJHUs2o1lxFyT1/xgAdQE9AWlI= + +Name: system/lib/egl/eglsubAndroid.so +SHA1-Digest: RX9770n7xnFXmz1G2ZvdFyGz5Kc= + +Name: system/media/weather/weather_l_windy_night.mp4 +SHA1-Digest: 657X3MoEv7xeFgTDzw+MB3nfQZs= + +Name: system/lib/modules/eeprom_93cx6.ko +SHA1-Digest: kZQU7Hl+wSRN8RNHeHtdrHvjtP4= + +Name: system/usr/srec/config/en.us/models/generic11_m.swimdl +SHA1-Digest: REX20baAUwoqpKFT+1FzKuave5I= + +Name: additions/fonts/comicsans/Roboto-Regular.ttf +SHA1-Digest: tgy9oyM7AJDWdj+Ysl+Gjt3G/8g= + +Name: system/etc/wifi/p2p_supplicant.conf +SHA1-Digest: 7ZLmeR14YO1bqd4WO09fcCYgvN4= + +Name: additions/fonts/asap/Roboto-Regular.ttf +SHA1-Digest: tP27/68ADAWzU6PT53N427dqLz8= + +Name: system/etc/ov2722_1 +SHA1-Digest: BWSHMIN8MNqOqER+L/PzaJZAlQ8= + +Name: data/app/com.adobe.flashplayer-1.apk +SHA1-Digest: Il/alwTzNLQ/ry6hCye+ozoQAdg= + +Name: system/bin/top +SHA1-Digest: UJ+vWLLalE+ev7TFnSCtqOozK7c= + +Name: system/lib/libqdutils.so +SHA1-Digest: AhsH8PCm+47FmKWzqr+HFmQVh+0= + +Name: system/etc/media_profiles.xml +SHA1-Digest: M9W+1pFsmP1X9v/NWljjso3hZ3Y= + +Name: system/app/HtcBackupReset.apk +SHA1-Digest: cultZx34wjobQybrk9QcIuSoWF8= + +Name: system/etc/tfa/recorder_l.preset +SHA1-Digest: cDZJyUVni8/H4BL4PsorzvWhb4Y= + +Name: system/customize/resource/icon_launcher_active_sync.png +SHA1-Digest: 6dZT1LxR08dTeAKPmatUy7gZqqo= + +Name: system/etc/security/cacerts/72f369af.0 +SHA1-Digest: B0FekN7giev0q4MtHFobsMO8JOw= + +Name: additions/gps/asia/etc/gps.conf +SHA1-Digest: 0DgcjLbRiR1zPk6YC3D7Zb3Amqw= + +Name: system/lib/libchromatix_s5k6a2ya_preview.so +SHA1-Digest: F9VqF8QAE8Bsf+GGJRnFox+sgS4= + +Name: system/customize/resource/icon_launcher_yahoo.png +SHA1-Digest: 7PHbmnYtD4Ry1swbRqbqEqbplC8= + +Name: system/media/weather/weather_clear.mp4 +SHA1-Digest: C8aLG84uaZPpRVJkJAebCRu0pKU= + +Name: system/media/audio/notifications/Magnolia.mp3 +SHA1-Digest: X3s4iU4hmGvHAL2OCn0Sk3aADFI= + +Name: system/framework/core.jar +SHA1-Digest: 2pKHl6EISazUBxjavJIurbURdWc= + +Name: system/media/audio/ui/Lock.ogg +SHA1-Digest: Z8fphp0j4uyfkRUuFIB6KHwHc3c= + +Name: system/media/zchgd/batt_50.rle +SHA1-Digest: t2qt0NS6ZF62IfkC+tnuMLV8EVc= + +Name: system/customize/resource/allapplication_232.xml +SHA1-Digest: VXUin3Fw3nyZc16fWYhbeJJaZZY= + +Name: system/lib/libwfdnative.so +SHA1-Digest: FOlqsylhOJt56FzFdKaPz0bxPaM= + +Name: system/framework/ime.jar +SHA1-Digest: KpPJDm4y3Mi0hYsFSRu+GM+1fx0= + +Name: system/customize/resource/quicklaunch_26806.xml +SHA1-Digest: BRXfQf1tcd1rP6BttdWC59jiJwo= + +Name: META-INF/com/google/android/aroma/icons/apex.png +SHA1-Digest: S5fbqhLG8GgJK4i9Zc5iVsYb3JI= + +Name: system/etc/security/cacerts/b7db1890.0 +SHA1-Digest: PnsdiNOuklg1r+/IRDgFBHM0gW8= + +Name: system/lib/libloc_api_v02.so +SHA1-Digest: szbY9rCuP4bXQLWEczs8aZ2f0QM= + +Name: system/etc/security/cacerts/412bea73.0 +SHA1-Digest: 1lSpCLZh5dp3WIcNHNj0NwNm6bE= + +Name: system/lib/libwt6pptxrdr.so +SHA1-Digest: cEFhVkOVzusj/ye5mjuKE5z7Yz0= + +Name: system/app/SharedStorageBackup.apk +SHA1-Digest: fHIKNB27H+tHhpM15YHgjPQlMSc= + +Name: system/lib/libstagefright_yuv.so +SHA1-Digest: grYHAQs0Rr4DIKbeb+YdtLaO078= + +Name: system/framework/modemwarmup.jar +SHA1-Digest: kqOtzrkIcSK7cXO1MMJhbeH3khw= + +Name: system/app/HTCBackup.apk +SHA1-Digest: 4CoJgW0Kdtqt90ZU2Wb5IJQmz/8= + +Name: system/usr/idc/synaptics-rmi-touchscreen.idc +SHA1-Digest: lab85HH2Cs9C40C3y2aLJU4Hpmc= + +Name: system/usr/srec/en-US/c_fst +SHA1-Digest: WbnZvDieUD1i8/vibs9Xx1Wx4sk= + +Name: system/etc/tfa/playback_l.config +SHA1-Digest: gphLjEG4rx+ZzxEvlj/dHj8UHdw= + +Name: system/app/Prism_LocalFeedProvider.apk +SHA1-Digest: 1sIyjmYm24ek/Tj4FPEyx0Ydqs8= + +Name: system/bin/logcat +SHA1-Digest: VRSKwMY83oB/I0FCcjGwxf4x/K0= + +Name: system/bin/mke2fs +SHA1-Digest: zbUy2F9srEcyQS3QrvuA1vWlVkM= + +Name: system/lib/libnotes_jni.so +SHA1-Digest: wpVs1BtCBVFF9lZ0js9no0xdka4= + +Name: system/etc/hltrd.bin +SHA1-Digest: 3sYn8UrJq3ExmZnnBfYJ3vzyUSg= + +Name: system/lib/libspeexwrapper.so +SHA1-Digest: goX7MyYJrrJ5gSf56ChkN/Ecqgc= + +Name: system/bin/dumpstate +SHA1-Digest: gy8GdVjEQLJ+82gNGHOd/pZ5WZM= + +Name: system/usr/share/partials/partials_H_gr.csv +SHA1-Digest: ZNj3aJy8pxjCk1K+8k9xLjgqtNM= + +Name: system/customize/resource/quicklaunch_26803.xml +SHA1-Digest: wanDss5dSktZ68VjA39ekLFTgEI= + +Name: system/etc/AlarmGroupQueueList.xml +SHA1-Digest: YgTUbvgOQwN7obaZlSZ2cCmbNbI= + +Name: system/bin/mkdir +SHA1-Digest: 1EmuA6Ym95jLVFY1N32uhoWkmiM= + +Name: system/app/HtcLockScreen.apk +SHA1-Digest: vJPk3dQCtR/i00t+Sk2Iuuh4rSc= + +Name: additions/fonts/comicsans/Roboto-BoldItalic.ttf +SHA1-Digest: a6Yzf5INecHzMJaCV51iLx2OfNc= + +Name: system/fonts/DroidSansFallback.ttf +SHA1-Digest: AVoIMOYxESTcwCXbQXfPqT6ROIA= + +Name: additions/fonts/comfortaa/Roboto-BoldItalic.ttf +SHA1-Digest: uXQkzJFpt44Ayw/bevVAkl7BLv8= + +Name: system/etc/security/cacerts/1920cacb.0 +SHA1-Digest: jnyFPukRwUWlDtLf5/32Yj9FaSY= + +Name: system/media/GPU/stylizeColorRamp.bmp +SHA1-Digest: qdmxYxbHuskGeAETArT/mtJ6yRQ= + +Name: system/app/DefaultContainerService.apk +SHA1-Digest: LAXeKYGyDZM1vgPxEiZL9Lj3zEo= + +Name: system/app/FilePicker.apk +SHA1-Digest: cpGKX7VtGXH61HkBDH/cjPgOzWM= + +Name: system/lib/libbinder.so +SHA1-Digest: yWzsT645IQXOHeR/IoVs/okpqOo= + +Name: system/app/MyDropbox.apk +SHA1-Digest: JIv1FUdW7r44+WWcUEnfy9nhHJ0= + +Name: system/app/HtcDataRoamingWidget.apk +SHA1-Digest: ugpem+ZpGJT8bGjV5QZ6SbT0OQs= + +Name: system/lib/libmmjpeg.so +SHA1-Digest: 9LGuPJDniFb07i8NyiqMyocx79E= + +Name: system/lib/libchromatix_s5k6a2ya_zsl.so +SHA1-Digest: iSDxGxtJPcgx66KTRKwAEYxY4RE= + +Name: system/etc/security/cacerts/9dbefe7b.0 +SHA1-Digest: yGiY2vyvGY8f13llDmyVgk0uikM= + +Name: system/lib/libalbum_util2e.so +SHA1-Digest: 3tlxqGM8fzYrhYHGeu7RITnkVZE= + +Name: system/etc/init.qcom.fm.sh +SHA1-Digest: vCm0EohH9ulqvdFWI7FYYC++5Ic= + +Name: system/customize/resource/allapplication_65501.xml +SHA1-Digest: FFTUxstTRxw9XRsTlBEhReTzjTs= + +Name: system/etc/security/cacerts/2afc57aa.0 +SHA1-Digest: nPKWafPr4jvpuNF1YPzwOiNGfjw= + +Name: system/customize/resource/quicklaunch_20810.xml +SHA1-Digest: vxVKX7hC4CLQRBkqrFM7Gl05K6U= + +Name: system/etc/security/cacerts/343eb6cb.0 +SHA1-Digest: rYcngakSpBQiNzp/GrZRITUXhlE= + +Name: system/app/HtcAccessoryService.apk +SHA1-Digest: kGpL+dG7PUWa1u5aan36Qbi1c5s= + +Name: system/customize/resource/quicklaunch_23806.xml +SHA1-Digest: 7jPh89tioFJ8eDAwC3lnFhzijmc= + +Name: system/app/CalendarProvider.apk +SHA1-Digest: wb8b9TRUkzs3DxsKppdM90f65fg= + +Name: system/etc/permissions/com.playstation.playstationcertified.xml +SHA1-Digest: PFvZQJi9dc7GlvjjKwSE3aeOs8c= + +Name: system/etc/security/cacerts/3e3744fd.0 +SHA1-Digest: IwRhl/a5N/2khuBeFSvzFoAtwcY= + +Name: system/bin/service +SHA1-Digest: 0R56vXBvoTExxFjripbzoIrjG+A= + +Name: system/bin/ois_camera +SHA1-Digest: 7uPyecBaJLotk93u1xg+FjpYyyw= + +Name: system/media/audio/alarms/Scarlet.mp3 +SHA1-Digest: KH51i/rPPBswEYsBhyAQav7/9+8= + +Name: system/app/HtcPhotoEnhancer.apk +SHA1-Digest: z4fMJ28xdRkC5pi9EZ+kftupN2A= + +Name: system/lib/libI420colorconvert.so +SHA1-Digest: HmVHNdrW7p3KsEbMxb6V2gUwgtI= + +Name: system/etc/security/cacerts/2edf7016.0 +SHA1-Digest: xyC9NTzY91oxJhxlL/1jiDTgB5g= + +Name: system/media/audio/notifications/Regalia.mp3 +SHA1-Digest: P4eaZ4Az8NkQmOffm7TanIQweCY= + +Name: system/etc/soundimage/srsfx_trumedia_movie.cfg +SHA1-Digest: NEa0d9QtPHE6IdLs9LAn9N6KCAU= + +Name: system/app/Automotive_Home.apk +SHA1-Digest: 07Gh1XQED2Rzk4UawmjAnzDaTc0= + +Name: system/lib/libhtcflag-jni.so +SHA1-Digest: 7i7wK/8Mg4/9aLHojbX25v9Be2Y= + +Name: system/bin/servicemanager +SHA1-Digest: 5gMBLDIDuhgiF6IZ0SbP82NeZNI= + +Name: system/etc/security/cacerts/0dbd0096.0 +SHA1-Digest: DYnXLEQ1aXDBnX4A+RfapiTz4nI= + +Name: system/media/audio/ui/KeypressSpacebar.ogg +SHA1-Digest: vJK46s6r2X/zJslrzS0KftDoq2E= + +Name: system/usr/share/zoneinfo/zoneinfo.idx +SHA1-Digest: 7SC0/Qh30fU10nBi4b/Fz+ROgsY= + +Name: additions/camera_4.2/lib/liblightcycle.so +SHA1-Digest: jzz5HoxsxdXYpCF0DL53HaJvmcg= + +Name: system/customize/mns_map.xml +SHA1-Digest: r52y39sn5wathoGFI2MFDf7Ok6M= + +Name: system/lib/libqmi.so +SHA1-Digest: kFnY12RsdkkPQ1IBhOfNfo6wK68= + +Name: system/customize/resource/rp_ce_0682_i.png +SHA1-Digest: WKHDKtKzRMxIzllQrKn7QHFiPrQ= + +Name: system/lib/libvideoeditor_jni.so +SHA1-Digest: DdbChcjps5WaEVLA7+r9eojxZvQ= + +Name: system/media/audio/alarms/Flame.mp3 +SHA1-Digest: gOLjmeuJKqafUwM0Y4j77UifN7U= + +Name: system/etc/RT5501 +SHA1-Digest: yv5GxwCaHTB3Iuzw+w08O+Zymlg= + +Name: system/app/Tube2_Configuration.apk +SHA1-Digest: CdXayply5QHfmKHtXnzRK1GihBc= + +Name: system/lib/modules/scsi_wait_scan.ko +SHA1-Digest: lB6dUM+7kgWnwWkMpgAnMz8T/mY= + +Name: system/framework/services.jar +SHA1-Digest: UGZjsSBuvC5tnK0lyaoemQAxFqI= + +Name: system/usr/srec/en-US/phonelist +SHA1-Digest: S2L0nVL6UG1/1SM58nULzylbpFY= + +Name: system/lib/libchromatix_vd6869_zoe.so +SHA1-Digest: 3/bbKYDuEk4EARUb6HtY2BpHfjA= + +Name: system/customize/resource/allapplication_420.xml +SHA1-Digest: kZtDN2GddbEfYmTQ7MlfPstAQtI= + +Name: system/bin/hostapd_cli +SHA1-Digest: CD1v5Nq4fJ/KE9A7fpUhB+2pk+4= + +Name: system/etc/init.qcom.coex.sh +SHA1-Digest: FR3i7XbfPq4T4S6W4FDXPWHNZ7E= + +Name: system/lib/hw/gralloc.msm8960.so +SHA1-Digest: mSjvOQ3P+ys9zpLuai4ZYJ9u5b8= + +Name: system/lib/libAudioTrimmer.so +SHA1-Digest: 0MjKqcBx3qrGvjWzsFrpRLnCZcA= + +Name: system/media/zchgd/charging_01.rle +SHA1-Digest: JcEiL3zNIXAmvN++fw9RS54Mrv8= + +Name: system/vendor/firmware/libpn544_fw.so +SHA1-Digest: SPf3hp3lircgbMnhTIJJGJYosN4= + +Name: system/lib/libdl.so +SHA1-Digest: VHNK7fGKavNrBoCdYwXERNwPF9o= + +Name: system/etc/tfa/voice_l.preset +SHA1-Digest: kDZMLMLsUEgpp51qMwbQT7teqd0= + +Name: additions/seeder/app/Seeder-2.0.0.apk +SHA1-Digest: NiHREDWwRHkWWFlSu2VkTOAkffQ= + +Name: system/bin/adaptive +SHA1-Digest: pO7YMDfo9BW3zl0PvRFQG54NdeU= + +Name: additions/fonts/ubuntu/Roboto-BoldItalic.ttf +SHA1-Digest: UyQMQ1PxkXqpAlGUP5TtL6qOPZ4= + +Name: system/etc/security/cacerts/b413391d.0 +SHA1-Digest: OlTPiY0ZtV+Jeqnl2ANvTa3BMeU= + +Name: system/etc/tfa/playback.eq +SHA1-Digest: pizpUtQoy5M7h5msVhr8m7aa/cg= + +Name: system/app/Talk.apk +SHA1-Digest: rJA1/6WChLlvHJ9rMKdU4mQirmw= + +Name: system/usr/srec/en-US/metadata +SHA1-Digest: KGPX1W+FZfaR/73RY0nIPfxsrcQ= + +Name: system/etc/libpmhwrl.so +SHA1-Digest: yvWh33yNnurSbPOntunZgVd/icM= + +Name: system/usr/srec/en-US/contacts.abnf +SHA1-Digest: iQQ63Xbl9ApZU2QzQYi80ayVbZA= + +Name: system/customize/resource/quicklaunch_232.xml +SHA1-Digest: C0Wbf6mcqyiDjafHNWbVOG4y96A= + +Name: system/tts/lang_pico/de-DE_gl0_sg.bin +SHA1-Digest: ScYyzXaktqrP2gdGvGwnttbNyVw= + +Name: system/lib/libandroid_simlock.so +SHA1-Digest: RrUW88EdrC4QfM9vyDkH4AypSyw= + +Name: META-INF/com/google/android/aroma/icons/info.png +SHA1-Digest: 7f5jW9mAVWrLoUspbijsj4gAkS0= + +Name: system/usr/share/zoneinfo/zoneinfo.version +SHA1-Digest: 2fI97bQ2ZyWLXtpTWG7caV9Ozzg= + +Name: system/lib/libmmmpod.so +SHA1-Digest: aUBK5VuuHUkVYF7HHt7dVS6Iwmc= + +Name: system/app/HtcVideoPlayer.apk +SHA1-Digest: Y4lFLyW4GQxamswaG3dJdOe7sOE= + +Name: system/media/audio/ringtones/Ocean.mp3 +SHA1-Digest: 6NKT94oqUUipEfUTvM8T6LfN+WQ= + +Name: boot.img +SHA1-Digest: g7fYb8Pd6hOm4ibygeL9DUIXbBM= + +Name: system/lib/libsqlite.so +SHA1-Digest: nEtH1P3X9/MLO9OIw/0WnGZgmBw= + +Name: system/etc/AudioBTID.csv +SHA1-Digest: CInBgnfhK5c1Vy69h8+uTFFhffA= + +Name: system/etc/permissions/android.hardware.camera.front.xml +SHA1-Digest: brba3Lj1cD+5FUB6sCkGYr27DvU= + +Name: system/customize/resource/quicklaunch_24201.xml +SHA1-Digest: ku/al2B9OfkVUz4bPU297LDCiag= + +Name: system/lib/libzeroeditor_core.so +SHA1-Digest: JDlqOefX1qz1+q5THpm6MolCcL8= + +Name: system/etc/security/cacerts/58a44af1.0 +SHA1-Digest: 4NuW5gozKsdwb1kgkbS9CS2AMzU= + +Name: system/etc/permissions/com.cisco.anyconnect.permissions.patch.ht + c.xml +SHA1-Digest: MXR25A+j2qIehrS6brcUqa2Marc= + +Name: system/etc/security/cacerts/1155c94b.0 +SHA1-Digest: Itv/d3FpM7SIr1DMDQhBhUgrq+c= + +Name: system/etc/security/cacerts/12d55845.0 +SHA1-Digest: oaj59fzV/q9qjIGZjotc01lpf9A= + +Name: system/lib/libwilhelm.so +SHA1-Digest: IbWFAO3GkotSFIMURK6uFZL+xag= + +Name: system/etc/permissions/com.google.android.media.effects.xml +SHA1-Digest: j/P++0UEThlMLHb5ewoUXe96pQ4= + +Name: system/fonts/DroidSansDevanagari-Regular.ttf +SHA1-Digest: YAhglQpSW2PkVPPeXBILe0Nx7BA= + +Name: system/customize/resource/quicklaunch.xml +SHA1-Digest: vzq+YJI/lr6aIfQzg+Ej4mqsqKw= + +Name: system/media/zchgd/charging_07.rle +SHA1-Digest: 4dams2U6rz8fcWcxjTBGDR1FL9Y= + +Name: system/app/GooglePartnerSetup.apk +SHA1-Digest: tEU24VZiJ4TLagvbXv/qpXq/9FM= + +Name: system/lib/libclcore_neon.bc +SHA1-Digest: IgUoLVtkK8FeBYy6FgG/wABo8aU= + +Name: system/lib/libclcore.bc +SHA1-Digest: kx7/I5zjVQRa2TbkUZnNjWS5WcQ= + +Name: system/customize/resource/wallpapers_b_04.jpg +SHA1-Digest: 3S4MmJqXQMsLhxttz7cpLNTQVVw= + +Name: system/bin/cand +SHA1-Digest: MCSVuKfLSuwuVc8CbWW88lEqZt0= + +Name: system/bin/lsof +SHA1-Digest: VcpBaMqEtljvrLbnQcKUYtb5AQ4= + +Name: system/lib/libpdfviewer.so +SHA1-Digest: SIhkGxLgJcZb/52Njtz6zHN+cnU= + +Name: system/lib/libmedia.so +SHA1-Digest: a+tYL/WwNQfnUPBMSiYAUDHZym8= + +Name: system/lib/libfacelock_jni.so +SHA1-Digest: iqvINeQDiCl1jyNwRsPVsitKnsw= + +Name: system/lib/libfilterpack_imageproc.so +SHA1-Digest: lkGtHR8jiy7H2H1mhPWCJcb6COo= + +Name: system/lib/modules/bluetooth-power.ko +SHA1-Digest: F6f43/WPUKsM7IZ4r0iSWZxSwHU= + +Name: system/usr/share/partials/partials_H_bb.csv +SHA1-Digest: z2A1DJTbdzcx0lWzn5WWnQU5PnY= + +Name: system/lib/libmm-abl.so +SHA1-Digest: YmVIr6Q4JLSXcblF5d3moILU0/c= + +Name: system/usr/share/partials/partials_CW_bb.csv +SHA1-Digest: H/oAhiLegM5EVK1IX1Y1UQxFpO8= + +Name: additions/fonts/asap/Roboto-Italic.ttf +SHA1-Digest: xHDqZ+fRWcdOtgL4QuuNri7GYN4= + +Name: system/app/Prism.apk +SHA1-Digest: FBR3GVo4P1T0ZVnk05+z9Cj3kos= + +Name: system/app/PluginManager.apk +SHA1-Digest: i7DozftSyy2Yro1Cy0Dtm3mMKtE= + +Name: system/vendor/firmware/mfg.bin +SHA1-Digest: ZcQMPSS4UC0C8EvWkbdOUBqw27A= + +Name: system/etc/system_fonts.xml +SHA1-Digest: jLNfZULcuazUesCv/tfD7W17xXA= + +Name: system/customize/resource/quicklaunch_262.xml +SHA1-Digest: r0UngEa1VzAAQcnmUbuNWC2lihc= + +Name: system/app/IMEXT9Latvian.apk +SHA1-Digest: GczboxIDj8YH+E/etPJ3AFkkrrM= + +Name: system/lib/soundfx/libreverbwrapper.so +SHA1-Digest: j4G7RiEvoDuiZVN26wTcHuGtKt4= + +Name: system/fonts/DroidNaskh-Regular.ttf +SHA1-Digest: UNiU8/FeO2boS+hjDrvun3Oq3tc= + +Name: system/etc/permissions/android.hardware.usb.host.xml +SHA1-Digest: 4e0iQFffHEDh5vP8Oa9PBa1PxGo= + +Name: system/lib/libmmcamera_hdr_lib.so +SHA1-Digest: i+JN1igz8EN3ywqkOFaVlhwPWwc= + +Name: system/app/Flickr.apk +SHA1-Digest: GuabfffINyjiy1Q7kHuanImerOA= + +Name: system/customize/resource/quicklaunch_26801.xml +SHA1-Digest: GIwp1ydu2jvqw9i5rgrWujUtJww= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x +SHA1-Digest: pJvz1tbUV8UL/mUYvaQTc/DVvyM= + +Name: additions/fonts/comfortaa/Roboto-Bold.ttf +SHA1-Digest: C0O41MVvXmK9r/SCd0osf0IPzTo= + +Name: system/app/CIMEXT9.apk +SHA1-Digest: 4px82M/N/QT7JCVgEZOHwS5pGIs= + +Name: system/app/HtcSoundRecorder.apk +SHA1-Digest: 1sE6H7Dg5NFVJb4hMVjmnipZCY0= + +Name: system/media/audio/alarms/Gold.mp3 +SHA1-Digest: nY30eAs7BHFgHFMcg8p5ApCzFvU= + +Name: system/etc/audio_effects.conf +SHA1-Digest: UXHpWqlGmFvLcW3+h2XH3LZa8V8= + +Name: system/customize/resource/quicklaunch_21401.xml +SHA1-Digest: GSgB6IK1YTP1jKL1ZyUJ3E9OVGA= + +Name: system/framework/pm.jar +SHA1-Digest: aeivCuZKxuop0ukIwK0eBDTVtN0= + +Name: system/etc/image_ibeats_solo_2vol.bin +SHA1-Digest: X7DEwM7Qh7Umqotba3D+Wfd29TQ= + +Name: system/app/NoiseField.apk +SHA1-Digest: GDkB+0b25OzjS4kDK6sMGEUx/BE= + +Name: system/lib/libdiag.so +SHA1-Digest: HJI3iIIPlNN+OOp62M2fcPhHexo= + +Name: data/app/com.google.android.googlequicksearchbox-1.apk +SHA1-Digest: o7zALTlG+CI2sNYLWGiSM+QA/mI= + +Name: data/app/com.twitter.android-1.apk +SHA1-Digest: Njvi+Iy6uJqhg2YtviAZGQGXY1U= + +Name: system/bin/toolbox +SHA1-Digest: 0CS+bNClQb17GONHN9G1PXB2XtM= + +Name: system/customize/resource/allapplication_63102.xml +SHA1-Digest: DvImVnO8XdPerR6nGGAe4yTcGSE= + +Name: system/etc/security/cacerts/eb375c3e.0 +SHA1-Digest: 9jrnwjglpn8uhR8xCTFy4wec+Ww= + +Name: system/lib/libwfdmmutils.so +SHA1-Digest: /h2YECLdRiySQSqAoAlD0Z1P1Yg= + +Name: system/lib/plugins/com.adobe.flashplayer/libysshared.so +SHA1-Digest: MJvCNwSlNiLR1Mth8d18l7bGUng= + +Name: system/etc/nfcee_access.xml +SHA1-Digest: 2z89gPlqpgchFCWC6+PmyhnaNYU= + +Name: META-INF/com/google/android/aroma-config +SHA1-Digest: 97W+p/aWegmVbzItS8rkupLV4Ig= + +Name: system/app/IMEXT9French.apk +SHA1-Digest: yn9MSajjgKMm6CpvTCG3Lz1tj8A= + +Name: system/framework/com.google.widevine.software.drm.jar +SHA1-Digest: Xh2UVVj5kEVRLGQuhBDPaGcB/P8= + +Name: system/framework/com.htc.videowidget.res.apk +SHA1-Digest: 3kpUSj48wcdHlfSfXWj4U9kHkV0= + +Name: system/bin/ipv6tether +SHA1-Digest: FWgQgBm1f/IZk8wlEkTQ67PwP7A= + +Name: system/etc/tfa/video.preset +SHA1-Digest: LchSL4ppfSBn9M0BoSatykA2iP8= + +Name: system/media/weather/weather_snow_day.mp4 +SHA1-Digest: ZWBFDLr0cVh0v2c8k8S9nI8xcwA= + +Name: system/customize/resource/allapplication_262.xml +SHA1-Digest: rv4iV7Gp1gx65XtWFZeTNUDfSiY= + +Name: system/etc/security/cacerts/4f19d2b4.0 +SHA1-Digest: mq4atZ6EcT4H7DaCR/BaKTlCKDQ= + +Name: system/etc/security/cacerts/ea169617.0 +SHA1-Digest: YCD1HGf7ZhS7lIrL78/hxupCFtA= + +Name: system/lib/hw/hwcomposer.msm8960.so +SHA1-Digest: SHy0GejAtEtlEBn3P8JojEXXnIs= + +Name: system/etc/security/cacerts/72fa7371.0 +SHA1-Digest: sw/ScEhE17ZGzZHg7RJLvGMTN2I= + +Name: system/etc/security/cacerts/3d441de8.0 +SHA1-Digest: kgXAr2tpkHl35rHXGMamr1Cpxd4= + +Name: system/lib/libcpt9.so +SHA1-Digest: qmQHE7VcmotG7j5l7eRrTNMRXjU= + +Name: additions/exchange/app/Mail.apk +SHA1-Digest: xHrLOuI2ijR8xwH7uYT8EEkP6Gg= + +Name: system/etc/security/cacerts/facacbc6.0 +SHA1-Digest: bZhsIsflntPIp9DFlV2R0Pc4eqc= + +Name: system/app/HtcGetStarted.apk +SHA1-Digest: hgpu6uuIPsOxcQ3umVIt/6kNmww= + +Name: system/lib/libprojector.so +SHA1-Digest: k6cncE9/WbjtErkot8hGtom9WZM= + +Name: system/lib/libidl.so +SHA1-Digest: 4D7DzabihSKcYIZENxBjHRVTnKQ= + +Name: system/framework/HTCExtension.jar +SHA1-Digest: BBwXW9q2Lfsc2cOP9lomy9AyPUQ= + +Name: system/lib/libcpt9provider.so +SHA1-Digest: cploiCWCBN0Apb0z7hE2Fht5Vhg= + +Name: system/lib/libhardware_legacy.so +SHA1-Digest: KtKT9chPgoKL0i73CM/uwmvc7Dk= + +Name: system/usr/srec/config/en.us/baseline8k.par +SHA1-Digest: xxkwHYqQ6wMwPFVXTMJScnVstGM= + +Name: system/lib/libwt6prnddi.so +SHA1-Digest: 5OuFUDg9iHLRNj78Eovlt3S0HLM= + +Name: system/app/TwitterEngine.apk +SHA1-Digest: A6hjoBuMQh8ji3W3uVhRVg0esZs= + +Name: system/etc/permissions/android.hardware.sensor.proximity.xml +SHA1-Digest: XnS+P6QtWXi//4uZhn9zCGLFAOk= + +Name: system/lib/libstagefright_soft_g711dec.so +SHA1-Digest: Dd2A2VHq4kXywd1MEzVvUtXztH8= + +Name: system/bin/shutdown +SHA1-Digest: b9n30BLB6DJIcBOyl/xip0Kj3D4= + +Name: system/usr/srec/config/en.us/g2p/en-US-ttp.data +SHA1-Digest: TMoAJlQxGPS0YwmkBuVSOTH3Ewg= + +Name: system/lib/libchromatix_ov5693_hfr.so +SHA1-Digest: ss4blvbqv9MF6FYc6w87kQGSYhM= + +Name: system/lib/libvariablespeed.so +SHA1-Digest: hl7xKWD79EUfcNioEbjM8OV8DL8= + +Name: system/lib/modules/spidev.ko +SHA1-Digest: VwEW3LuG/yOXrWEa4bEsHdkUv7o= + +Name: system/bin/nl_listener +SHA1-Digest: KGhJO/ADNGsl9oR6ivgkd1xgq6I= + +Name: system/app/Stk.apk +SHA1-Digest: H8VfrLbAzKIc1yPyO5IFoW5W1rU= + +Name: system/lib/libnfc_jni.so +SHA1-Digest: TwfOC6SAWUwNTxbFraWCrFoH/tc= + +Name: system/etc/security/cacerts/ccc52f49.0 +SHA1-Digest: O0+cfSTNAOmAaDWYHOWEHop+Czc= + +Name: data/app/tunein.player-1.apk +SHA1-Digest: SCsoHJcVX7VbN9ENTyU6TV6HziE= + +Name: system/lib/libchromatix_imx175_zsl.so +SHA1-Digest: JHQvQ2v7PtwDmR9qyhi4+U6ztJA= + +Name: system/framework/com.htc.socialnetwork.res.apk +SHA1-Digest: Ufsmj13nsAUtZvH4Yd8+6DG7oU4= + +Name: additions/fonts/comfortaa/Roboto-Italic.ttf +SHA1-Digest: YtmXnSrAAlQHs9TCx4mJ+lG7Nv4= + +Name: system/customize/resource/quicklaunch_20205.xml +SHA1-Digest: APl8Ptm3nYwlKMlmOALIiaI+A/8= + +Name: system/app/IMEXT9Estonian.apk +SHA1-Digest: m3W0j9DmidKIcP+gK2VR3ndGR9c= + +Name: system/etc/security/cacerts/d0081655.0 +SHA1-Digest: lNTj+/VAIpCdtuWWvc9Z7xY8iX0= + +Name: system/etc/security/cacerts/34d760b2.0 +SHA1-Digest: 50/DzWfq0F6oVJRfiP4yiQcLsv8= + +Name: system/lib/libspeexresampler.so +SHA1-Digest: 7WWvp0/D/bmygY4yvMJUKIJ6Qb4= + +Name: system/bin/ds_fmc_appd +SHA1-Digest: It7lTm9VOXijmC4C0Q2AWk6809Q= + +Name: system/etc/spn-conf.xml +SHA1-Digest: 27/5n0weOKYT3PcMPQra8hjR4Us= + +Name: system/etc/hldm.bin +SHA1-Digest: nnT7IdiQ7VXIbAHj/kH1Z6YX9DA= + +Name: system/lib/libcamerapp.so +SHA1-Digest: /j9xnMlsC8Z2wMilaUhnYUIK3ec= + +Name: system/fonts/DroidSansGeorgian.ttf +SHA1-Digest: TcKNYOeiNvn93qI0a4VO4OsezbA= + +Name: system/etc/tfa/fm_l.config +SHA1-Digest: b6pLXWHOdArgyXDP6MvVHbO6GCg= + +Name: system/customize/resource/allapplication_250.xml +SHA1-Digest: SeZXqBbu5HGhV/BA/4PG26RgL9Y= + +Name: system/etc/security/cacerts/c7e2a638.0 +SHA1-Digest: FNY7YX9aUI4JunnbSM/rvcUd32A= + +Name: system/app/IMEXT9Finnish.apk +SHA1-Digest: 4YM/rYyWEeHom4NXuyKM4bps2Vk= + +Name: system/bin/dumpsys +SHA1-Digest: uc5ewjzvLT6VoP3mDb8HMXCsfZg= + +Name: system/app/GoogleLoginService.apk +SHA1-Digest: mN8ICUC4kJHQr4Ps6d/jitNC/yM= + +Name: system/lib/libandroid_servers.so +SHA1-Digest: 8vCO8MYjqKY6bnyjtzRVnzhx0lk= + +Name: system/media/audio/notifications/Verdigris.mp3 +SHA1-Digest: 84lpXgkNBXm+hYZsvGK/hz+V0Hc= + +Name: system/bin/hci_qcomm_init +SHA1-Digest: TXizsKByQ3vfo0s0FGwmtAeBH0Q= + +Name: system/lib/libmmrtpencoder.so +SHA1-Digest: T9mPiI9BZBAphi1tUtqwlzCDlGw= + +Name: system/etc/image_beats_wireless_bt.bin +SHA1-Digest: hjN5rdNOd8tepCcZ+FrBVg2FvZo= + +Name: system/media/audio/ui/KeypressDelete.ogg +SHA1-Digest: VPKqb3uV7dbibtW5woFWXBcSN+M= + +Name: system/usr/share/partials/partials_CW_gr.csv +SHA1-Digest: gAUUYLqzAgSiY3uwRo+jh/CkOV0= + +Name: data/app/com.estrongs.android.pop-1.apk +SHA1-Digest: PnRrvNbBPSBRZ0wpH9dXAbHU1ik= + +Name: system/app/Idlescreen_productivity.apk +SHA1-Digest: Pqrlxc6rJF+NnvEhFy+qPsAQ3f8= + +Name: system/customize/resource/quicklaunch_65502.xml +SHA1-Digest: DQnk65pNRL2GX6+WM/D1tVS+eEw= + +Name: system/app/MediaProvider.apk +SHA1-Digest: OokEgx3q2b2QoLey38da1DupvkI= + +Name: system/bin/wmdsi +SHA1-Digest: UyzhqibByeIs7xJ0iRziF2jg+Ig= + +Name: system/lib/egl/egl.cfg +SHA1-Digest: y/87VoK0H7VIrFPbmtXvdY1n6gA= + +Name: system/etc/security/cacerts/11a09b38.0 +SHA1-Digest: R669axPhbXAdwOxMeYoDQernEpI= + +Name: system/app/HtcMusic.apk +SHA1-Digest: Bty+q8AzXVj+c+XmNRpLI5na1Ac= + +Name: system/etc/security/cacerts/c527e4ab.0 +SHA1-Digest: zRMmakm1sS3WLz+jAxVfL05XL0k= + +Name: system/customize/resource/allapplication_21910.xml +SHA1-Digest: i79JVoogPm3jv4tbMIP04FnsGSM= + +Name: system/bin/adb +SHA1-Digest: AyqWlH1Q5xCOwe0CWVB7C1N4NXo= + +Name: system/app/ContactsProvider.apk +SHA1-Digest: f8O4TLMZEg6BnmUIokx6p8kNkic= + +Name: additions/fonts/veggieburger/Roboto-Regular.ttf +SHA1-Digest: ZT/jve8vcRhC0XxvTMtwUP1Zdd0= + +Name: system/lib/libnetmgr.so +SHA1-Digest: +k4F516tG1p0hPa6MVm3AFWVqX8= + +Name: system/etc/security/cacerts/95aff9e3.0 +SHA1-Digest: 1GRiRyM4dxD3loVZew6tSzCwVBY= + +Name: system/bin/ifconfig +SHA1-Digest: npeumq00l0cYaxlYSKU4rl6+uvM= + +Name: system/lib/libqc-opt.so +SHA1-Digest: XTtoY/nOHGgA6bC2VXg9F15THNA= + +Name: system/lib/libalbum_imagelib.so +SHA1-Digest: e1Xe0ZnV9m0GFX8K/vm/l/qvX8E= + +Name: system/xbin/dexus +SHA1-Digest: dM8PUVtaDdjf1BX/Fvr8CZR81LQ= + +Name: system/lib/libext2_blkid.so +SHA1-Digest: tytcsJZGOovAw1286BzpxHDFrrk= + +Name: system/lib/egl/libGLESv2_adreno200.so +SHA1-Digest: iMRWj21EscIFc39EfHjiu3MrWr8= + +Name: system/etc/security/cacerts/8f7b96c4.0 +SHA1-Digest: lDZRYJyvALtGjuqSKR0e/O5iFq0= + +Name: system/customize/resource/quicklaunch_20404.xml +SHA1-Digest: +a2CJ41n8YYkTqetRZQUUlJNGbI= + +Name: system/lib/libmmcamera_rubik.so +SHA1-Digest: jPPts5yGKFs16Qh0Xorp6dXCFD4= + +Name: system/etc/security/cacerts/58546a39.0 +SHA1-Digest: 473pDMwaRrwq+3jG4bQw3k+3HUI= + +Name: system/bin/bugreport +SHA1-Digest: iCWefAb7f32Ty/OvmgrQYgAfaXc= + +Name: system/lib/egl/libGLES_android.so +SHA1-Digest: bBpJY9bMeRoAZAdGSyOzN0lhOZc= + +Name: system/lib/libstagefright_avc_common.so +SHA1-Digest: BtTF+4ahI0FVaDiTYk3l3AIXrVY= + +Name: system/lib/libchromatix_imx135_preview.so +SHA1-Digest: HGZ1+94/Y6Nr0WGHXMDpYO0Ljkg= + +Name: system/app/BrcmBluetoothServices.apk +SHA1-Digest: qrRZSFfgbrb+fS2i5qQC9iKFKIw= + +Name: system/customize/resource/wallpapers_a_03.jpg +SHA1-Digest: 8RY+MUBbvnQUFJSv91arbPdsF+c= + +Name: system/lib/libchromatix_ov8838_default_video.so +SHA1-Digest: zHj7ebwXAI+xiP5M3ynx5WZS1H0= + +Name: system/lib/libVDRecognitionAPI-jni.so +SHA1-Digest: aQvzk+4K7no0QMgKTJIVGXzEnKo= + +Name: system/lib/libdiskconfig.so +SHA1-Digest: VSnvy5BbXzdVXjm08Ca9nv5KbgA= + +Name: system/bin/md5 +SHA1-Digest: jWvu7/NiF0a4jTMpNYkwHUSLqXA= + +Name: system/app/Bluetooth.apk +SHA1-Digest: LUyi4uDvG0o2UDsSBRU8oQa54SA= + +Name: system/lib/libmode10AutoTest.so +SHA1-Digest: 68tyKlCv0oWwvKur6SQzIc9AZMI= + +Name: system/customize/resource/CCInfo.txt +SHA1-Digest: /jZfBXY0Al6Gv6wOibTEkwcPiLY= + +Name: system/lib/liblz.so +SHA1-Digest: ke71LqCfi2XM36qzzJ+IdIWRNHY= + +Name: system/etc/security/cacerts/f58a60fe.0 +SHA1-Digest: 68/j3gHkt1C4pcp35lL5Y5cLsM8= + +Name: system/usr/keylayout/AVRCP.kl +SHA1-Digest: QuW9bT29OeTZExCprXrP8pA3gzE= + +Name: system/framework/wimax.jar +SHA1-Digest: sTo97xjCatVK8Ke7h0NijLsgrfo= + +Name: system/fonts/DroidSansTamil-Bold.ttf +SHA1-Digest: oSDuoNatRJoV24tZWDAT4L26Fw0= + +Name: system/app/GSD.apk +SHA1-Digest: 12zGK8D6momXGf56oG9knpp1wRc= + +Name: system/lib/libpolarisoffice_Clipboard.so +SHA1-Digest: TBSyhXyuB6IOFjsCfBujx9CMZA0= + +Name: system/etc/security/cacerts/c19d42c7.0 +SHA1-Digest: nXSR1rdjKTm3ugwRQ/JqDMBzLC4= + +Name: system/media/GPU/mask_vignette_wide.bmp +SHA1-Digest: 1SqKi5VvUhucAdwuEhrUQHa5010= + +Name: system/etc/security/cacerts/3a3b02ce.0 +SHA1-Digest: SQgeiwC1dSnuF8xaVn3NAriZV0M= + +Name: system/etc/image_beatbox_bt.bin +SHA1-Digest: XrcM4+m48vUeHVNR9smiOCVliiQ= + +Name: system/lib/libchromatix_ov5693_zsl.so +SHA1-Digest: s9OpRyEn6XDnFaqS1L3DKIrjvjc= + +Name: system/etc/tfa/voice_l.config +SHA1-Digest: iVbhOpsi7AOVilnNgxAQtIDWKxo= + +Name: system/bin/setconsole +SHA1-Digest: 1XRP1FO1G4TTlIQrL/0pueb6040= + +Name: system/media/audio/ringtones/Eggshell.mp3 +SHA1-Digest: YbzKnciuNFXuS1FCvIL6mBP0d68= + +Name: system/customize/resource/quicklaunch_21416.xml +SHA1-Digest: YblfW35M5Jqg/LFEQy9CKY/uTjA= + +Name: data/app/com.dropbox.android-1.apk +SHA1-Digest: oyvr7H44My9F9tJY9OCAN0ync5E= + +Name: system/customize/resource/quicklaunch_24002.xml +SHA1-Digest: W3fsa9bWB6bPhZoKBBdm/Qhor20= + diff --git a/release/aroma/META-INF/MANIFEST.MF b/release/aroma/META-INF/MANIFEST.MF new file mode 100755 index 00000000000..11fe6a70e8a --- /dev/null +++ b/release/aroma/META-INF/MANIFEST.MF @@ -0,0 +1,6231 @@ +Manifest-Version: 1.0 +Created-By: 1.0 (Android SignApk) + +Name: system/etc/security/cacerts/87d3cf09.0 +SHA1-Digest: SEvFz4ELxIbs56LRzjo3NgdBMaI= + +Name: system/bin/udhcpd +SHA1-Digest: ICYQQiAY904jCH1dYyaysa/YVa4= + +Name: system/lib/libpowermanager.so +SHA1-Digest: MORUwsrDzN0bPdXQKk0uLd+WJkA= + +Name: system/lib/libstagefright_soft_aacdec.so +SHA1-Digest: Ck4zlKZQmvqLQQDwKG/U2clXZ2o= + +Name: system/lib/libchromatix_vd6869_hfr.so +SHA1-Digest: B0zvKcnvgiDByjPiXnBriK6WjMs= + +Name: system/customize/resource/wallpapers_b_02.jpg +SHA1-Digest: xK8TsbrmohwCiuAa/Mec/rXcgvQ= + +Name: system/etc/permissions/android.hardware.sensor.accelerometer.xml +SHA1-Digest: H/ej10L8o81LMOjg3YIBw6GjoiI= + +Name: system/fonts/DFHEIA7A.ttf +SHA1-Digest: jraRllXz4lXhFQAQJwh6Z4739mA= + +Name: system/etc/dhcpcd/dhcpcd-hooks/20-dns.conf +SHA1-Digest: d1dqXCfxg0GO1o8tbtrKcixcoP0= + +Name: system/media/audio/ringtones/Crimson.mp3 +SHA1-Digest: o7xwLMcPANL9tgyHDqHHZ6xXeag= + +Name: system/lib/libchromatix_vd6869_hfr_60fps.so +SHA1-Digest: v2ozOKaVIzWBbTUx+6bvbXBaIic= + +Name: system/lib/libaudioeffect_jni.so +SHA1-Digest: N+/49eJpANno573xc57sTje/gnk= + +Name: system/app/Browser.apk +SHA1-Digest: MZeezBbeW5M2CspoOWK5sy0VOOA= + +Name: system/lib/libexiv2.so +SHA1-Digest: xMhoaY0xJle1MtDnsctRcGMpAPQ= + +Name: system/lib/libdrm1_jni.so +SHA1-Digest: YzNBS82OnBXvIVGMJYq++/FGF2s= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/nose_base-y0-yi45-p0-pi45-r0-ri20.lg_32/full_model.bin +SHA1-Digest: eI6ovSLIm3HCCBrDqsxX2Q/Ei2s= + +Name: system/media/weather/weather_partly_sunny.mp4 +SHA1-Digest: Z+gWdLxgUcy8xv7twDfUe4ExolU= + +Name: additions/fonts/klavika/Roboto-Bold.ttf +SHA1-Digest: ktvGBDYTMDFPLQ14CSjsitANs70= + +Name: system/lib/libwfduibcinterface.so +SHA1-Digest: ugrz1oyVZVPOe3nZDDpuk+IQS8o= + +Name: system/etc/image_htc_earbud_2vol.bin +SHA1-Digest: WIs7nGT5LJbKwcpAuPojnAl6OKo= + +Name: system/lib/libusbhost.so +SHA1-Digest: V7bdb7BIejsifZ8dQa56f1vTBXQ= + +Name: system/fonts/AndroidClock_Solid.ttf +SHA1-Digest: 0vRHOkM++Y5hREyvokR3HBnI2ig= + +Name: system/usr/srec/en-US/embed_phone_nn_model +SHA1-Digest: MVunhgmY/DSaOzfB2Xc+O/LHNcs= + +Name: system/etc/security/cacerts/81b9768f.0 +SHA1-Digest: 4erTsgDtkF3RUrNOypxOujy6Zeo= + +Name: system/lib/libDxDtcpClient.so +SHA1-Digest: lK4TzZSutj4fykOPkjBkwUr5kH8= + +Name: system/framework/com.htc.weather.res.apk +SHA1-Digest: 61qMtJi4XR0xZHXTKFGw6dCgops= + +Name: system/fonts/gcsh00d-hkscs.ttf +SHA1-Digest: 1M0itSuFKi2mVAJ+izWFbLvsI/s= + +Name: system/lib/libyuvimage.so +SHA1-Digest: Q/mE0gt20kUypL9y51rTrPDZdsI= + +Name: system/app/HtcScreenTimeoutWidget.apk +SHA1-Digest: 08yopP2PL3m9T1fuBEhpTeAjtJ4= + +Name: system/lib/libAnalyst.so +SHA1-Digest: 4rEUfTdKOOhjxD+ExvSZacoufhw= + +Name: system/bin/sdcard +SHA1-Digest: JkjhVSwvvxYamYbcNjJFMqd6utY= + +Name: system/framework/ext.jar +SHA1-Digest: rnZ/HdpD8ExGmwo4+Q7C+ksBlbw= + +Name: system/media/audio/ringtones/Lavender.mp3 +SHA1-Digest: 402J4OoPp4eh7vFA4M/BzVFIMBw= + +Name: system/app/MySketcher.apk +SHA1-Digest: nTh5DoVVR0PclhrxhhyhHEe44J0= + +Name: system/etc/image_ibeats_solo.bin +SHA1-Digest: rW+4jB7c23PSDBTWJVHs98rZ2cM= + +Name: system/media/weather/weather_l_partly_cloud_day.mp4 +SHA1-Digest: fVXtKss1zrCNz07DzyDH7B1GrIM= + +Name: system/bin/smd +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/ed049835.0 +SHA1-Digest: qfwv5fm9WuVJSoOfaW0MTXSQraU= + +Name: data/app/com.facebook.katana-1.apk +SHA1-Digest: DcQH7kiI1zeEIuAQZpTsxmzueSY= + +Name: system/app/Phonesky.apk +SHA1-Digest: nIJ143RgNUPCdsajQAZIJSxDDXE= + +Name: system/lib/libgnmc_id3tag.2.5.9.4.so +SHA1-Digest: PS9cMyZXauQF63C0EMibFH1XRAk= + +Name: system/media/audio/ui/Volume-6.flac +SHA1-Digest: JjjeOlpdXTjl8uR9mFQN1qmfZ6I= + +Name: system/etc/security/cacerts/9f533518.0 +SHA1-Digest: AZtPDtYCuXAjFbgZptviWf6or4o= + +Name: system/etc/security/cacerts/a3896b44.0 +SHA1-Digest: ZLbceCx+C2qAgw+u1XPHRG5oKOw= + +Name: system/customize/CID/default.xml +SHA1-Digest: 8KAO8QboF3gb37TigGvB3JX2+BY= + +Name: META-INF/com/google/android/aroma/icons/alert.png +SHA1-Digest: 4vVPQ4oeO+xcr1ttQ56VRZ+7nRU= + +Name: system/framework/com.broadcom.bt.le.jar +SHA1-Digest: hZWbjQDYlKpdy0b4PySH7jocpBo= + +Name: system/lib/libstagefright_soft_mpeg4enc.so +SHA1-Digest: Njo56YAyfa+nIu3Gqc6hBtuXQ3s= + +Name: system/media/audio/notifications/Claret.mp3 +SHA1-Digest: rjxEbzJGIB1VQy0Bc1iqqVPrIWA= + +Name: system/lib/libwpa_client.so +SHA1-Digest: 34BVv0QT4i8PAQv+b17SV4WFgUI= + +Name: system/media/audio/ui/LowBattery.ogg +SHA1-Digest: uuIldXjG+4uO9pGKN3pjkar13pA= + +Name: system/bin/linker +SHA1-Digest: 02EtQtgXZ9Hk0UYHNOWcoe5Fmuk= + +Name: system/lib/libhtcsunny2engine.so +SHA1-Digest: AMcVQjyAMAtQ7pN7zoqVfF1OXa8= + +Name: system/lib/libmllite.so +SHA1-Digest: nFnhkw56G2Yi5eK+rO8j6dYdzU0= + +Name: system/media/weather/weather_partly_cloud_day.mp4 +SHA1-Digest: L70Lt52toKCCLeE4aj3UJ8hE7PE= + +Name: additions/fonts/veggieburger/Roboto-Bold.ttf +SHA1-Digest: vqC6OfKIK+uned2YmV09YK3dTLE= + +Name: META-INF/com/google/android/aroma/trickdroid.png +SHA1-Digest: menCFRnjUaVA2x9WyPcw5tVAjPs= + +Name: system/media/audio/ui/media_volume.ogg +SHA1-Digest: 3My0Ro04VTBOMDcfDucgkfcYkkQ= + +Name: system/app/IMEXT9Bulgaria.apk +SHA1-Digest: E5go9fvJ+lCivI1omVK1TWROeHA= + +Name: system/media/GPU/dot_mask_3.bmp +SHA1-Digest: B6JIoYVFR1iw8UeYx476FnEI+OI= + +Name: system/etc/secureproperty.xml +SHA1-Digest: 67uk8SBU7aXMrgV0KC9FUb5f7IU= + +Name: additions/fonts/asap/Roboto-BoldItalic.ttf +SHA1-Digest: Tc7CBKbNIpVRaAgaAaerhcw1uyY= + +Name: system/app/IMEXT9Russian.apk +SHA1-Digest: Cb/QzF2AwqOI4W+VfKI0QcOadgU= + +Name: system/etc/permissions/android.hardware.usb.accessory.xml +SHA1-Digest: FqpJrpvkKQ0UpylOSdp44H4smXo= + +Name: system/media/zchgd/batt_40.rle +SHA1-Digest: iYWRM++q9nAhIzkLnTWYwWW4z6w= + +Name: system/media/audio/ringtones/Persimmon.mp3 +SHA1-Digest: HwUsaVwP56xvkJwsyZyIsoDg5vQ= + +Name: system/fonts/Roboto-Regular.ttf +SHA1-Digest: Z9cynTXQb4TYTpzUSFMVfKk/tTc= + +Name: system/lib/libDivxDrm.so +SHA1-Digest: QGCKZ6H+psPbNnbfQRPRwNFDIfk= + +Name: system/bin/mtpd +SHA1-Digest: HHKag5D5o4pCnd/Bp6F/Eh9VJdY= + +Name: system/customize/resource/quicklaunch_21408.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/allapplication_22288.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/Nfc.apk +SHA1-Digest: Ukj8nEJVKrd7dzX4ZRerTSGNGfY= + +Name: system/usr/share/bmd/RFFspeed_501.bmd +SHA1-Digest: U8VAt4ToJM9cf23UWSW02bJYN+M= + +Name: system/etc/security/cacerts/635ccfd5.0 +SHA1-Digest: fEdbGydFBhoJjXNJXzEVa18unJ0= + +Name: system/etc/security/cacerts/2e8714cb.0 +SHA1-Digest: B52F0B9cohH697PhOwRGCzELdTw= + +Name: system/media/GPU/CurveWarm.bmp +SHA1-Digest: 1zAKIDQrpBz6UoXmWFbWP7kvi1s= + +Name: system/app/JETCET_PRINT_Resources.apk +SHA1-Digest: Unz/6TBE7Szc/keNt1hOThLniCU= + +Name: system/app/VoiceDictation.apk +SHA1-Digest: Lw46+mQ5gNkvEqqKperlyjQWpqw= + +Name: META-INF/com/google/android/aroma/icons/gps.png +SHA1-Digest: /fuHyjV7VcRMGsrWh41SyLvvKkY= + +Name: system/xbin/nc +SHA1-Digest: JJE+yImZJSlJ3rCNFl4j7ZSRB7A= + +Name: data/app/com.google.android.marvin.talkback-1.apk +SHA1-Digest: LVvWQ1CfxMa1GET5I/xZShrj3ZA= + +Name: system/etc/permissions/android.hardware.location.gps.xml +SHA1-Digest: ydG3KogqmSduNEKpFzBYmpQFX1c= + +Name: system/fonts/Roboto-Bold.ttf +SHA1-Digest: Ykc18CQi8T5QzPRm8NKe3aBa2zY= + +Name: system/lib/libGLES_direct.so +SHA1-Digest: Q89nbZ2bx3MJcWNr5W7tVNttqjk= + +Name: system/app/CustomizationSetup.apk +SHA1-Digest: gTS4PSKwUvB3cOu2SKALBJLVbos= + +Name: system/app/MusicChannel.apk +SHA1-Digest: ciWFeCFIer+Ct/TyozFIQB0QQ6U= + +Name: system/etc/image_ibeats.bin +SHA1-Digest: X08lPbW7p7cgywYQokNcIXrjg9k= + +Name: system/etc/image_gec_bt.bin +SHA1-Digest: W873c0G9gw4/bBA3L4yMLUX4FjU= + +Name: system/lib/libcsd-client.so +SHA1-Digest: HI8vFJ5sh9uN57pHJ5bhH/AOu0U= + +Name: system/bin/RescueServer +SHA1-Digest: qWDoVCW2cB48MJcB5PpTQUa7pyk= + +Name: additions/fonts/comicsans/Roboto-Italic.ttf +SHA1-Digest: yfjgrSTLZI+MEqcsxa/l2nhsMIA= + +Name: system/etc/security/cacerts/5f16ce45.0 +SHA1-Digest: CR5ngcPg+GhEF4lVh4M7sbRV3Hc= + +Name: system/etc/security/otacerts.zip +SHA1-Digest: E4kiOM61KkKokn2eIpqJkkW66qA= + +Name: system/bin/stop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/htc_ebdlogd +SHA1-Digest: qlUPTF1QEqz3j8XS7ee1+on2BPM= + +Name: system/lib/libpatts_engine_jni_api.so +SHA1-Digest: YrCR4O7XonOvv9ISeoe9WTjZPoY= + +Name: system/lib/libglcv.so +SHA1-Digest: cIKwdQHtKSxo7YWm4HqwRnBmW+E= + +Name: system/etc/firmware/fw_bcm4335_apsta_b0.bin +SHA1-Digest: uJMxJ3MkPLcTV1cMI2rm37qvk5k= + +Name: system/etc/security/cacerts/0c364b2d.0 +SHA1-Digest: W8eUtQrdCtbH5zZbkCDjlJgwhWM= + +Name: system/lib/libsrsprocessing.so +SHA1-Digest: VBBOu2dxNLOxOG1sGNAvpu22Gy8= + +Name: system/lib/bluez-plugin/audio.so +SHA1-Digest: D4mFDntmcVZy7tQ6c9lCUcieDpk= + +Name: system/lib/hw/audio_policy.default.so +SHA1-Digest: qThVt3mzx1I4ru994vnRjrlzv6M= + +Name: system/lib/libchromatix_ov8838_hfr.so +SHA1-Digest: eAUTj1TEZBU/EHpBVBvDlNrwRT4= + +Name: system/etc/soundimage/srs_global.cfg +SHA1-Digest: tczDSklQzgifcr56AGYV5l4snkM= + +Name: system/lib/libicuuc.so +SHA1-Digest: DnBGOiWQWhYzSW8y5r1QeAHvHSs= + +Name: system/app/HtcMusicWidget.apk +SHA1-Digest: m89XS5KwhzYZz2X9ojto7EtS3Ls= + +Name: system/lib/libnetsharing.so +SHA1-Digest: SnS12zE4I94jofnoeroNXfeEPxw= + +Name: system/usr/keylayout/qwerty.kl +SHA1-Digest: 8/B84i3bQPu2tSLenvsrd+0YolI= + +Name: system/etc/security/cacerts/b5f329fa.0 +SHA1-Digest: StMAnoljP1hXqiJcZYbmEssAnJk= + +Name: system/etc/soundimage/srs_geq10.cfg +SHA1-Digest: tIQaXxMaShowHXYfAAagY2+QX5c= + +Name: system/lib/libstagefrighthw.so +SHA1-Digest: Cpj4bysXshhtZjkBGTHWvhIS084= + +Name: system/bin/schedtop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/chmod +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/HtcMessageProvider.apk +SHA1-Digest: VJZKx4YD7YH4YlKPOx8saV6uZIU= + +Name: system/lib/libmtp.so +SHA1-Digest: 05jOPlWXrErIJCCnLckmxdGfU3c= + +Name: additions/wipe/wipe.sh +SHA1-Digest: cx54+cFy0h15QJ1DmLm9cMmr5yA= + +Name: system/customize/resource/wallpapers_b_05.jpg +SHA1-Digest: Qrj4Qp1GHo1sQOhMgNvA1BshBIk= + +Name: system/etc/tfa/deftcoefA.speaker +SHA1-Digest: gsLxDUQ+FIJVMB2pqmIkWDyioPM= + +Name: system/app/HtcDropboxGLRPlugin.apk +SHA1-Digest: b+PuostABgQK7yAo00+lUHGjFr0= + +Name: system/app/HtcRingtoneWidget.apk +SHA1-Digest: Vu50iaCVxDrvTzA4CrTAzjLQwV0= + +Name: system/app/IMEXT9Portuguese.apk +SHA1-Digest: a+nfSrEWJlKv9QCfMQ8i1aloIyY= + +Name: system/etc/security/cacerts/e268a4c5.0 +SHA1-Digest: m5F+mEcMoF+8u8DBD6e9pEogIk8= + +Name: system/app/HtcContactWidgets.apk +SHA1-Digest: atqXG9dZ1ls22nZ5C4+sALdEHo0= + +Name: system/lib/libchromatix_ar0260_hdr.so +SHA1-Digest: fgb3Ftj2LsX7L0leGVf3jfuSE1E= + +Name: system/lib/libmmcamera_rawchipproc.so +SHA1-Digest: DzDEfnc/dJVCu6iKaaIA0R5nUPE= + +Name: system/fonts/HelveticaNeueLTPro35Th.ttf +SHA1-Digest: cSJmjVS5DnDDAXRSSKSL/w/9DRo= + +Name: system/lib/libstagefright_soft_vpxdec.so +SHA1-Digest: zR6gdZ24MxkGHS0XrspUQpDlJJc= + +Name: system/lib/liboemcamera.so +SHA1-Digest: 5lRAXG7bZR7hAj2TdMJAa3XNYQY= + +Name: additions/gps/europe/etc/gps.conf +SHA1-Digest: +XeSYP/cwNlriWknNc/ynSlEPi4= + +Name: system/bin/usbhub_init +SHA1-Digest: /rGFX6XmI14zpeW2U1uxk/acqTo= + +Name: system/usr/srec/config/en.us/dictionary/enroll.ok +SHA1-Digest: rcl7CO9ZOIxVX+yaPLoqJv8ZtwY= + +Name: system/media/audio/ringtones/Red.mp3 +SHA1-Digest: T+48wiN95iILjhoQLezHDIvXPvg= + +Name: system/bin/mm-jpeg-dec-test-client +SHA1-Digest: Jp1ZGNBLYmopygN9kLw9Sigf6BI= + +Name: system/bin/ATFWD-daemon +SHA1-Digest: eXxEZcgXeLpbtKUWMHSnuwwBxOY= + +Name: system/etc/security/cacerts/56657bde.0 +SHA1-Digest: OXPix8Y5jubMndNxaBClQGy9Bac= + +Name: system/lib/libCommandSvc.so +SHA1-Digest: 492in0O89MvYOGzeN2kDqlNJglg= + +Name: system/lib/libwt6xlsrdr.so +SHA1-Digest: w0J5AFyw4QGRL3v/7vCu4r2zyls= + +Name: system/lib/libOmxCore.so +SHA1-Digest: EHDNGS7zjUs3qEgR7Qoy5BHF8Wg= + +Name: system/lib/libpixelflinger.so +SHA1-Digest: RR7d6/BwUIPBy9M+P870M6YweTs= + +Name: system/bin/RescueStarter +SHA1-Digest: c/jazM0uc+RxFBAJJnMv/81MLaA= + +Name: system/lib/libmm-omxcore.so +SHA1-Digest: pqmwQZ0q5qxsoOeHlV65gX2g2/Q= + +Name: system/etc/ppp/ip-up-vpn +SHA1-Digest: CXnecb4k4Mn5g3hdEHTquN7PUcY= + +Name: system/lib/libandroid.so +SHA1-Digest: gEX7YAOBEY++LGBMF5w0CmPeDkg= + +Name: system/lib/libcrypto.so +SHA1-Digest: eDbAsV89FAEkvXuRxuDfUPj/eNY= + +Name: system/app/Updater.apk +SHA1-Digest: ICmDyKhy+HM7fkmgGa4WKfN3Hc4= + +Name: system/lib/hw/audio.primary.msm8960.so +SHA1-Digest: tspOLjpGQfry6lyr9+czVfc8vnk= + +Name: system/customize/resource/allapplication_23210.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libext4_utils.so +SHA1-Digest: 1CnzR/0HZDNdZVimKHeo9RvCf9c= + +Name: system/customize/resource/ConfigH.bin +SHA1-Digest: m0Qoky+wTVeedsMjdE5kLy2/5Jc= + +Name: system/lib/libOpenMAXAL.so +SHA1-Digest: MYgmWEVFSGwXoDXDabC91pANHzQ= + +Name: system/lib/egl/libq3dtools_adreno200.so +SHA1-Digest: PRNVFjAWP2dZ9LY7CywY+WfC3bY= + +Name: system/etc/security/cacerts/1df5ec47.0 +SHA1-Digest: UujKW9YI89cjOO6uCaBGaKKEdIQ= + +Name: system/lib/plugins/com.adobe.flashplayer/libflashplayer.so +SHA1-Digest: VdarjMW0yjKajHGXemvkCmYy27g= + +Name: system/customize/resource/wallpapers_c_04.jpg +SHA1-Digest: BYj83VTJTKiETaKJT7cHGMjhudg= + +Name: system/framework/com.htc.resources.apk +SHA1-Digest: DmH2Nut+hrC/yLTw1FZHZQjntS0= + +Name: system/etc/dhcpcd/dhcpcd-hooks/95-configured +SHA1-Digest: n21FxtoLF/bqDP+kxPLFVdyzXE8= + +Name: system/etc/tfa/playbackbeats_l.config +SHA1-Digest: j6S5V89FwvUw8PmIK737fBvqmO4= + +Name: system/framework/input.jar +SHA1-Digest: akcCB8GSs9P/7zfOavMR8ZWFWSQ= + +Name: system/etc/security/cacerts/85cde254.0 +SHA1-Digest: R9VocfbkwOamdyjLfP1NDBc/kug= + +Name: system/lib/libchromatix_s5k6a2ya_default_video.so +SHA1-Digest: gz6UUSlC1pq6pP25Sp92v195htc= + +Name: system/bin/printenv +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/0481cb65.0 +SHA1-Digest: eUDnOJWQG+0Mq73qo4bkRPu78z0= + +Name: system/etc/tfa/recorder.preset +SHA1-Digest: ZIWhTsSVk2FQh+JqEczz/+vRDeQ= + +Name: system/media/audio/notifications/Viridian.mp3 +SHA1-Digest: OIMHInxfNZZ7TXa3aUlXVIisGa8= + +Name: system/bin/svc +SHA1-Digest: laWKf0PV0fXkGCVIDLsyLTOEAMc= + +Name: system/framework/android.test.runner.jar +SHA1-Digest: CznXOzRKZf6f4KrS0zzYhytFHbs= + +Name: system/framework/usbnet.jar +SHA1-Digest: Y00mvgIlw27s/vNByWclrNj217c= + +Name: system/customize/resource/quicklaunch_23410.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/allapplication_65502.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/2fb1850a.0 +SHA1-Digest: 5FY7vEW9oM3Pyb/ez0M7eSlco+Y= + +Name: system/lib/libstagefright_soft_amrnbenc.so +SHA1-Digest: u/sofmApIfrfaibn7guEnXET+qI= + +Name: system/lib/libQSEEComAPI.so +SHA1-Digest: VhqE0Dnd7pRC+q4Vn7coCpKfIPc= + +Name: additions/fonts/roboto/Roboto-Regular.ttf +SHA1-Digest: Z9cynTXQb4TYTpzUSFMVfKk/tTc= + +Name: system/etc/tfa/fm.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/etc/firmware/leia_pfp_470.fw +SHA1-Digest: RqjOgh0hg1n/foRttdzBWzG91co= + +Name: system/media/zchgd/batt_5.rle +SHA1-Digest: mTf5wlQitI2OSGQ5ZVH3otlcoD0= + +Name: system/vendor/lib/libwvdrm_L1.so +SHA1-Digest: iSMDSbyVS1cczOIzcSrBNvjDsEk= + +Name: system/tts/lang_pico/es-ES_zl0_sg.bin +SHA1-Digest: /gTDSWCUKfTXAlH/biqyNzYk1Yg= + +Name: system/app/PureC_UserDictionaryProvider.apk +SHA1-Digest: eKflp8acbknSlFvQ0+jMM6DNJXs= + +Name: system/lib/libqdp.so +SHA1-Digest: 93/hEy/0LFl5cETrCw7THy2IG6U= + +Name: system/etc/firmware/a225p5_pm4.fw +SHA1-Digest: AuX7JsEh04gQS8ag8xgR36kfGCg= + +Name: system/lib/libcam_oem_plugin.so +SHA1-Digest: rHaYCWxFAn5s4Vuivjl4aR980eM= + +Name: system/lib/libchromatix_vd6869_default_video.so +SHA1-Digest: uSHznNV44UrOBccfwGYO0tyv5t0= + +Name: system/bin/pnpmgr +SHA1-Digest: Vy4Vbu4eXCFxPaH+yGfXP246XUs= + +Name: system/etc/security/cacerts/709afd2b.0 +SHA1-Digest: KGT1Ull1qgWICgtxU3/55nw/4uM= + +Name: system/lib/libnmsp_speex.so +SHA1-Digest: rgmO+eaj75rcbY2C2VDDekOnhWo= + +Name: system/xbin/sysrw +SHA1-Digest: rRps8RoUnWtGRd9F9IAQfTH9XTU= + +Name: system/lib/libvideoeditorplayer.so +SHA1-Digest: cmQOiIlvBC/LzknfMZSFNwAv3f4= + +Name: system/customize/clientid/default.prop +SHA1-Digest: AscF550NfHVQFC+Z7pvfsgv7wVw= + +Name: system/lib/libdrm1.so +SHA1-Digest: C31dRgDxPMm+ODh0Wn4sFJ7TGrY= + +Name: system/etc/permissions/com.htc.android.bluetooth.le.xml +SHA1-Digest: Jofz0dJK3Vk0K9IXRh4dyoggaDc= + +Name: META-INF/com/google/android/aroma/icons/confirm.png +SHA1-Digest: YeJPRW3VKUhuHZf6Y0a5iznavIA= + +Name: system/etc/security/cacerts/1e8e7201.0 +SHA1-Digest: AjTvkNYA86SfWxtzL6wQkemMoBs= + +Name: system/etc/security/cacerts/46b2fd3b.0 +SHA1-Digest: qcEpnsYeagaaeB94Fmlp1prYt3g= + +Name: system/lib/libwfduibcsrc.so +SHA1-Digest: 3YSVDi/Du/huYnAtdoAoFKKlF+Q= + +Name: system/xbin/sysro +SHA1-Digest: ff02R0/YaPW3I5ywDdoFZ5IZ7gQ= + +Name: system/media/zchgd/batt_70.rle +SHA1-Digest: VB2HqgtLseMqkl4Ik/NLl5/dXlY= + +Name: system/customize/resource/rp_ce_0700_i.png +SHA1-Digest: UGI5KGSeTQPMYqmL7qnAJfWw3Qg= + +Name: system/lib/libstlport.so +SHA1-Digest: hnVy+XlrBQXBM+bEbPjCHfdUX30= + +Name: system/media/weather/weather_thunderstorm_night.mp4 +SHA1-Digest: VjkbK4QDyi9uc6dvG6SYTpSFDtQ= + +Name: additions/fonts/roboto/Roboto-Bold.ttf +SHA1-Digest: Ykc18CQi8T5QzPRm8NKe3aBa2zY= + +Name: system/etc/permissions/android.software.sip.voip.xml +SHA1-Digest: qrhF2jqAj3LTjMn5u0PyAXph4X8= + +Name: system/bin/mdnsd +SHA1-Digest: 2OrmXCnG/YnFlNtScWNoyW+D0xo= + +Name: system/lib/libjnigraphics.so +SHA1-Digest: wTiZqoyzkioNm03yN6nJQjTS2Mg= + +Name: system/bin/ping +SHA1-Digest: ZbyK03myR5eRM9L0qnc5GmZ14W4= + +Name: system/lib/libsysutils.so +SHA1-Digest: n61harAISM3aIRP7eu+cmqK84+0= + +Name: system/lib/ssl/engines/libkeystore.so +SHA1-Digest: i3di5pdD3Km7Yz+gL50XiTGP3iA= + +Name: system/app/GoogleBackupTransport.apk +SHA1-Digest: 5DQ1KS2UzPp86rTeATEyPUkVbeQ= + +Name: META-INF/com/google/android/aroma/themes/sense/dialog_titlebar.9 + .png +SHA1-Digest: ZuhQ+jwdSiXNUSLIhMaANsclNnY= + +Name: system/lib/libdmt_speex.so +SHA1-Digest: Ln81AgCDfS2yTdCGRlMK+KLZcQc= + +Name: additions/fonts/helveticaneue/Roboto-Regular.ttf +SHA1-Digest: Ag4WCAlIdfsROGQIFQls/Byifrs= + +Name: system/lib/libgps.utils.so +SHA1-Digest: P4H+Yt98m2auKJaWAOebN+eCq6Y= + +Name: system/customize/resource/quicklaunch_24007.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/RebootWarningWin.apk +SHA1-Digest: rWJiLEASvgKcD47/DRAbuFKQtG8= + +Name: system/etc/security/cacerts/a0bc6fbb.0 +SHA1-Digest: NWKfQevFapMePZRehJiiL3l2b/A= + +Name: system/bin/hciattach +SHA1-Digest: sbOHlsLTY6saOGKu5+914Kp3UkM= + +Name: system/media/audio/notifications/Mantis.mp3 +SHA1-Digest: xX+XvtTHFrGcMoonpy48TRCUAn0= + +Name: system/etc/soundimage/srsfx_trumedia_51.cfg +SHA1-Digest: wlYxA19kBnDd8l7lWPyidjrvBmo= + +Name: system/bin/iftop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/cf701eeb.0 +SHA1-Digest: EJ+vugw2T3Rx/5SHC912B2Lc1AA= + +Name: system/etc/wifioffloadpkg.xml +SHA1-Digest: V4kLYM5/b/JRAaxS0lQRHbFH5TY= + +Name: system/framework/com.htc.browsermodule.res.apk +SHA1-Digest: cjGxhGqq9Hg47ctm6EEMRGUbP1E= + +Name: system/etc/security/cacerts/67495436.0 +SHA1-Digest: YTT/bqjqefQaDmHNLvdFEV4CLqE= + +Name: system/lib/libaudcal.so +SHA1-Digest: nbolEaLO5TtS88tZeRNVkiQhqaw= + +Name: system/lib/libFileMux.so +SHA1-Digest: lf9wC4Yk/cJ74WJ2Oz6ZFPOsaRg= + +Name: system/etc/audio_policy.conf +SHA1-Digest: q9qbm60+wECXJFaM8Gp6QMJqsv8= + +Name: system/customize/resource/quicklaunch_228.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/allapplication_65510.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/usr/srec/config/en.us/baseline11k.par +SHA1-Digest: Mq1IVDJlLzTaUQHLe+XE3eS3jPQ= + +Name: system/lib/libext2_e2p.so +SHA1-Digest: 33VPKMi7fie8LNOiYpWZB2ZbQ4g= + +Name: system/app/Frisbee.apk +SHA1-Digest: NlDalMEIq2fxk58storhUdg/A58= + +Name: system/lib/libchromatix_s5k3h2yx_preview.so +SHA1-Digest: jg3fWy6T4HdqIcWwdSPZT81OrRQ= + +Name: system/lib/libqdMetaData.so +SHA1-Digest: SzGHNOVk8qlyoTTKAhuG9cN3kxk= + +Name: system/etc/tfa/tfa9887.config +SHA1-Digest: gyvcECYDl8FeI8LlmyOTfQPiJNg= + +Name: META-INF/com/google/android/aroma/fonts/small.png +SHA1-Digest: oHYrbDXlnhjFwHqNQePor+/Vf/A= + +Name: system/lib/libv8.so +SHA1-Digest: zabtPZyGyUa63l+QXI7gJkpHD9o= + +Name: system/app/DownloadProvider.apk +SHA1-Digest: 7TJ+skb/OfzDBCO7uHS7IScbw2g= + +Name: system/lib/libril-qc-qmi-1.so +SHA1-Digest: t6hRA6Prqzsp0pMQNzdUlBLU1xQ= + +Name: system/bin/touch +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/fonts/HelveticaNeueOTS.ttf +SHA1-Digest: cZ0Da8Hkqx8UuwK/LHEMD8H1L9s= + +Name: system/media/weather/weather_windy_night.mp4 +SHA1-Digest: zRYAoh5YklqbHBaLKJCwMcpYyrE= + +Name: system/bin/mm-jpeg-enc-test-client +SHA1-Digest: /qwcTMDPXNrI+VamDqQ3FUHx/YE= + +Name: system/lib/libqcci_legacy.so +SHA1-Digest: WFV68Oec4O2xur7WYvexqWnkbhk= + +Name: system/etc/security/cacerts/bcdd5959.0 +SHA1-Digest: mqSe0pzB0HImT/8Q9HI7sCP7FyQ= + +Name: additions/fonts/segoewp/Roboto-Regular.ttf +SHA1-Digest: QtOqY32WXX7LiT5Iur74jDKa5gA= + +Name: system/etc/security/cacerts/97fecd7d.0 +SHA1-Digest: 3spPf/i94EWIhdbNLwN/QDT8d4k= + +Name: system/bin/keystore +SHA1-Digest: AKSAfcwIR89pjBzIN3PpCQVLIF4= + +Name: system/bin/awb_camera +SHA1-Digest: gGaXimGKHzC/W9RfebCTzPVw+w0= + +Name: system/lib/modules/moc_platform_mod.ko.3.4.10 +SHA1-Digest: /a3egfHcdDg/9sn2cqzNTBmpgc8= + +Name: system/app/IMEXT9Czech.apk +SHA1-Digest: GexOcXPl9sd8oLgaq5tRhXop+yk= + +Name: system/bin/nandread +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/bma150_usr +SHA1-Digest: 3VYydgZq2PF92YX557JxNX3gL+I= + +Name: system/media/audio/ui/Unlock.ogg +SHA1-Digest: F9KA4TW+Gp7zDkIj6GjLT7I1KCE= + +Name: system/etc/tfa/fm_l.preset +SHA1-Digest: 5sbhFGjzewa4Pfs10aaWH7c80Ew= + +Name: system/lib/modules/moc_crypto.ko +SHA1-Digest: P2mbWXOwwNsOMU2yzf/+aFkZkSo= + +Name: system/fonts/Clockopia.ttf +SHA1-Digest: iw96Cm9uf/w/SbVQekBynrfv48I= + +Name: system/xbin/su +SHA1-Digest: zHxPpqr9D5YGHzZMFfX6VrZ8dj4= + +Name: system/lib/libdmt_elvis.so +SHA1-Digest: 9KmiXSvBv5ZXnLnSJIchdWhcsvQ= + +Name: system/lib/libfilterfw.so +SHA1-Digest: AQjn8SbVPeWOfwFtZHLH8cwdkRs= + +Name: system/media/weather/weather_cloudy_night.mp4 +SHA1-Digest: 9/QjibnIK9fIVBGjPPgfOqNlv7Y= + +Name: system/etc/image_htc_midtier_2vol.bin +SHA1-Digest: R37IgU56A2CD+WeOI2wbE1qSzbM= + +Name: system/fonts/DroidNaskh-Bold.ttf +SHA1-Digest: VeIrLgRpCvr8H4wYbwzQb48k8eI= + +Name: system/etc/tfa/video.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/lib/libcutils.so +SHA1-Digest: eLqgXW8SrY4XHkDgJz6S84vl8zc= + +Name: system/lib/libmmparser.so +SHA1-Digest: j+AlCpNgyGbpCCxuLKjEPVeD7fA= + +Name: system/media/zchgd/batt_30.rle +SHA1-Digest: Upz3AuGR4pHfuaOhzVzOjIZjm14= + +Name: system/fonts/RobotoCondensed-Bold.ttf +SHA1-Digest: IIA82t9wxAtGgB9tHwt16IBinrQ= + +Name: system/app/HtcInternalSettingsProvider.apk +SHA1-Digest: l+woGnwnp4fVV9FgYAIaVu77wL0= + +Name: META-INF/com/google/android/aroma/themes/sense/bg.9.png +SHA1-Digest: InlGz7Cq45PigWMA4uPLHlms3+0= + +Name: system/lib/libchromatix_vd6869_preview.so +SHA1-Digest: yx+5Mx4GRFNKAuJwpVIY+nC2gJA= + +Name: system/lib/libcameraface.so +SHA1-Digest: km4j+8o+0kWqM800zNKtc3d+r5o= + +Name: system/customize/resource/allapplication_21404.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/framework/com.android.nfc_extras.jar +SHA1-Digest: QlWKCE8PrdciN0PB7IJ1amq81JU= + +Name: system/bin/bu +SHA1-Digest: qZ1ifCg2IqfafLkirzAP4dMjOro= + +Name: system/etc/soundimage/srs_bypass.cfg +SHA1-Digest: X37NMhOuhn1HdWL2ngW7auz8uGo= + +Name: system/etc/sound_mfg_DMIC.txt +SHA1-Digest: j/gKOE8iUqvcIuoNQ8JSpnSnGjE= + +Name: system/lib/hw/audio.primary.default.so +SHA1-Digest: SRxklM1aIq33mo3YTMc8o8/mGnw= + +Name: system/usr/share/partials/partials_A_gb.csv +SHA1-Digest: VIxIrgVGX2kG8+c51NduCfOVR3o= + +Name: system/lib/libchromatix_imx175_preview.so +SHA1-Digest: 0qhmyIQCFmlvr5qy046WISvIRUw= + +Name: system/lib/libnetutils.so +SHA1-Digest: LmQoMK52xp4fub06favUVZU5eEA= + +Name: system/media/audio/ui/Volume-1.flac +SHA1-Digest: C6ClE+7lNVzPOVG5CZeVHFFTpGw= + +Name: system/customize/resource/quicklaunch_28001.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/rp_ce_0678.png +SHA1-Digest: 4dGbvvlcMK9bEePatdS4fbLpm28= + +Name: system/lib/libimage-omx-common.so +SHA1-Digest: MNmhyWWpm+Bw0UIHhNTYkvqYwN4= + +Name: system/etc/firmware/fw_bcm4335_p2p.bin +SHA1-Digest: xmuNdIdduLdBGDKSfXL3O6FpdSw= + +Name: system/etc/security/cacerts/23f4c490.0 +SHA1-Digest: V/L3KgnCcIYZZFFbYbX2T0h9s5o= + +Name: system/lib/modules/gspca_main.ko +SHA1-Digest: KlLsTlXLahSqyPXUuGIAXnGEIms= + +Name: system/app/HTCShoeboxShare.apk +SHA1-Digest: QEbVt+qQFY0i1Tf134T/LAe63pk= + +Name: system/customize/MNS/default.xml +SHA1-Digest: z47LYgzlDKCwBwl9mBHusnPwjhs= + +Name: system/app/HTMLViewer.apk +SHA1-Digest: yMCsh1IO4sUwHp6N2/sEJFPt81U= + +Name: system/bin/mm-qcamera-test +SHA1-Digest: EF5+wtDx1q7KbKodN8Ws+scymd8= + +Name: system/bin/am +SHA1-Digest: tGduMx5JPECn+7U+fdIzcrCdrlk= + +Name: system/etc/bluetooth/auto_pairing.conf +SHA1-Digest: fb/w7V4UP/xpqHx8XMBbGn+pv/s= + +Name: system/etc/tfa/fm.eq +SHA1-Digest: PM6hx2pEVi+SuZ9Ef8C0eIPB808= + +Name: system/app/SocialManager.apk +SHA1-Digest: NqZf4AjkcCd8ydn5vq7CclydhSU= + +Name: system/etc/firmware/ILP0100_IPM_Code_out.bin +SHA1-Digest: DOSeFIkMt3Ikrg28LBJGaDPnZow= + +Name: system/app/Transfer.apk +SHA1-Digest: QO4BegU2QMSi0hMOfUGPBXH7eps= + +Name: system/bin/df +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/WeatherSyncProvider.apk +SHA1-Digest: 6CP9l+MN1VbZItebFFGjK/iQnC0= + +Name: system/app/HtcWeatherLiveWallpaper.apk +SHA1-Digest: w7imRD489Vqfwku6TobrDI9S6qg= + +Name: system/bin/dd +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/hw/keystore.default.so +SHA1-Digest: Kw7S4QLStJVpdNG1TJuzfdcMmLk= + +Name: system/bin/bluetoothd +SHA1-Digest: 7sBnRXVMe/GmjkepS7xhIlybtVg= + +Name: system/customize/resource/quicklaunch_22288.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/9d6523ce.0 +SHA1-Digest: w//rjddcx+4ATCiAMsrJludK9w8= + +Name: system/lib/libDxDrmCAPI.so +SHA1-Digest: tEwmNKb4KtpDbSNoakPymxx/wb4= + +Name: system/media/audio/notifications/Glitter.mp3 +SHA1-Digest: rty15s/42rnP0lnT3zGX+BZBjio= + +Name: system/etc/tfa/playbackbeats.preset +SHA1-Digest: JYWGCVyXl3c9Rz9ndzK8oEuGmqk= + +Name: system/lib/libbluetoothd.so +SHA1-Digest: Hz17q18yvMR0kBFDMexqNR1fW+A= + +Name: META-INF/com/google/android/aroma/icons/Thumbs.db +SHA1-Digest: X9OsSoU/rnK/nV4e0VHprniiwgQ= + +Name: system/app/Prism_SocialFeedProvider.apk +SHA1-Digest: dHKG+JN2x8hojKS4aNeoa6mZ5AU= + +Name: system/fonts/DroidSansHebrew-Bold.ttf +SHA1-Digest: bnHHY3zVhU5icp9deYBYiLskRlM= + +Name: system/app/HTCShoeboxEngine.apk +SHA1-Digest: TYvp8xpwpBqYWg2PImZZVptlJFU= + +Name: system/app/HtcBackgroundDataWidget.apk +SHA1-Digest: jraLC1cknYx79fg5ieq8ZQWWt6M= + +Name: system/vendor/lib/libwvm.so +SHA1-Digest: ptdoe8vhKa6go0xhB4I9MbcX61s= + +Name: system/media/audio/notifications/Rust.mp3 +SHA1-Digest: c1Pf722FGAbxAM4raX1DyRrQPOM= + +Name: system/lib/soundfx/libbundlewrapper.so +SHA1-Digest: 1MghHxF0Qz8bCdp3kD2QUhozEAk= + +Name: system/bin/rmmod +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/media/weather/weather_l_fog_night.mp4 +SHA1-Digest: XN6Fgljv4Va/sNrw62edXwG4ums= + +Name: system/lib/hw/gralloc.default.so +SHA1-Digest: rGGOcIAZ/M4QSHm9RkRSHP83sbQ= + +Name: additions/desense/Nova.apk +SHA1-Digest: 1eVsnCKW6UinaJRJl9EMs/1Dut0= + +Name: additions/battery/bluep/app/SystemUI.apk +SHA1-Digest: qVbHJasTVDOW+xOfpkZM/bJoXEk= + +Name: system/lib/libril-qcril-hook-oem.so +SHA1-Digest: be3wqhWFo50pXZbU+r1RFH/ZPqQ= + +Name: system/usr/srec/config/en.us/models/generic.swiarb +SHA1-Digest: QGzUh5WkfKQRmuaI+sJtXBZrEFg= + +Name: system/media/audio/ringtones/Sense.mp3 +SHA1-Digest: gWLpBEu/EWnftqMy0ujTAwRipu0= + +Name: system/etc/bluetooth/audio.conf +SHA1-Digest: Mn9R6t7GUhTTFiY8C0BnVlE9ZPk= + +Name: system/app/FacebookEngine.apk +SHA1-Digest: eXpk9TbK5e9j9TTNFsEfnZyuFls= + +Name: system/etc/security/cacerts/a7d2cf64.0 +SHA1-Digest: ovUCtI0EY0f9I+ptWEk2GL/6+2Y= + +Name: system/lib/libbtio.so +SHA1-Digest: bxJog3JGeHJlfJ/4kFjDQOLgcrc= + +Name: system/bin/uptime +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/KidMode-google.apk +SHA1-Digest: uMAqf+vxSkG3rq3D00TAfrWKfCE= + +Name: system/etc/security/cacerts/3c58f906.0 +SHA1-Digest: /+9N6BT7ZtaVjBA7JzJT/bxXV7w= + +Name: system/lib/libvideoeditor_osal.so +SHA1-Digest: LiCj95XIBHPbxtkhtaNEgl8iBmo= + +Name: system/customize/cid_map.xml +SHA1-Digest: xWmNWm5qkKwdkxxKDxT1cj8LD/I= + +Name: system/bin/wpa_cli +SHA1-Digest: 3RfyiqfOHQQMUfI40GSxh+UC3PM= + +Name: system/etc/security/cacerts/d16a5865.0 +SHA1-Digest: uhdS7HZmT6TkFszu7r9Y2xzhX2w= + +Name: additions/fonts/klavika/Roboto-Italic.ttf +SHA1-Digest: IiFl+/BBcNqYP0q2dECLEoDLGoE= + +Name: system/lib/libdss.so +SHA1-Digest: wTFNKSD3d724zSu+hq4O61HW+FM= + +Name: system/etc/security/cacerts/882de061.0 +SHA1-Digest: fCt4s0+592o+QOkmDeYrj+o9kCI= + +Name: system/customize/resource/wallpapers_a_04.jpg +SHA1-Digest: T4D18RMWNdkL4kgL13z94ow46fY= + +Name: META-INF/com/google/android/aroma/themes/sense/nav.9.png +SHA1-Digest: aM5gHxPbCzYbkn/idDhNbfU01Q8= + +Name: system/etc/security/cacerts/8470719d.0 +SHA1-Digest: f5QED3DbZCbDT1sNmR7e40z3aao= + +Name: system/customize/resource/rp_ce_0560.png +SHA1-Digest: wST8AmAajkDNdy69DLoM7ITiFXo= + +Name: system/etc/security/cacerts/e775ed2d.0 +SHA1-Digest: 0GkuHmAcEDLQf+8r8yG75doHYQ4= + +Name: system/etc/firmware/vidc.b03 +SHA1-Digest: zvMTXDOkNwpbPkEqqr+douzUurA= + +Name: system/etc/firmware/vidc.b02 +SHA1-Digest: xRSzjS+YH2eHexFe51xH6Zs/JYo= + +Name: system/media/GPU/stylizeContrastRamp.bmp +SHA1-Digest: f/sWG+Rz0zuBnFAYWEidLb8Ov6Y= + +Name: system/etc/firmware/vidc.b01 +SHA1-Digest: ljBiUzT6+KKzOK4Z6xGaDGENZvY= + +Name: system/lib/libqmi_common_so.so +SHA1-Digest: jBuoamOOXTMVFujkXnO30Zg6JvU= + +Name: system/lib/libmm-audio-resampler.so +SHA1-Digest: 0FCirfvUw/aoxvgAFuZ8ikoVIpM= + +Name: system/etc/soundimage/srsfx_trumedia_music.cfg +SHA1-Digest: 1hPAjcb1kqGpWbhoSoRVZUc4qfA= + +Name: system/customize/resource/allapplication_24001.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: additions/battery/greenp/app/SystemUI.apk +SHA1-Digest: teUcNPNEiRebW8MyEKO2xDhP/rQ= + +Name: system/etc/security/cacerts/c9f83a1c.0 +SHA1-Digest: 9i3z/3hCXgOYpEWeFkt7O27uy4g= + +Name: system/lib/libgnmc_decoder.2.5.9.4.so +SHA1-Digest: cZh1S1h4FqhhMxcvmF7S0NXnlz0= + +Name: system/fonts/HelveticaNeueLTPro-Cn.otf +SHA1-Digest: G7YRo/dTEkda3YYdfuhU0P8S7Ck= + +Name: system/app/HtcAirplaneModeWidget.apk +SHA1-Digest: hl4DIIfXiW+w/pt6NwEt7u7S8eI= + +Name: system/bin/bmgr +SHA1-Digest: txVKgTGjXkxUtbIhsor6EUCfLsM= + +Name: system/app/HtcWiFiWidget.apk +SHA1-Digest: 9nTVBC3bg9oNjZ3TYL4omvNGcRQ= + +Name: system/etc/security/cacerts/895cad1a.0 +SHA1-Digest: I6mXiEZNYMrute2XDIugRzsK/f8= + +Name: system/usr/srec/config/en.us/dictionary/cmu6plus.ok.zip +SHA1-Digest: gix9zeNXUv3/qb72caDqmlPws9U= + +Name: system/app/HtcNotesPainterView.apk +SHA1-Digest: UFVGp3UU3lsaqTQxO2fDEHajD7Q= + +Name: system/media/audio/notifications/Creme.mp3 +SHA1-Digest: eY+Bw9iDZ5jM0tVE6B8Fydg9iwE= + +Name: system/bin/gzip +SHA1-Digest: 1vab/ZEiI2NqAujm3NoLAy9fQKk= + +Name: system/customize/resource/quicklaunch_250.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/tfa/voiceWB_l.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/media/weather/weather_l_hot.mp4 +SHA1-Digest: spPYbhPUE7F72TdHD8OPch8w+sg= + +Name: system/bin/lsc_camera +SHA1-Digest: rkt4qcEY9dLXtQRPN37TL6QCCAU= + +Name: system/app/HtcMessageUploader.apk +SHA1-Digest: 6WRmDCSjTWKKCJCQTab4u2rtaOM= + +Name: system/etc/security/cacerts/1dac3003.0 +SHA1-Digest: mgJ5j9kIbAF3wxCvrgctrBj5mEI= + +Name: system/lib/libMusicVisualizer.so +SHA1-Digest: wFucyEWcD14CXKxeOcRZrD08C8E= + +Name: system/app/PolarisOffice.apk +SHA1-Digest: SLH9RO+IH8658ftoMGT3oxn75RY= + +Name: system/etc/firmware/vidc.b00 +SHA1-Digest: yfS8/3kMSaL0+ItjAbIMptehGm0= + +Name: system/app/IMEXT9Ukrainian.apk +SHA1-Digest: hfj3GUHC/rFymobDyS+cOfoVPRo= + +Name: system/bin/zchgd +SHA1-Digest: FoQo5zaAUntpEpKxCY4Ij8K6nDo= + +Name: system/etc/permissions/platform.xml +SHA1-Digest: S36kP7qxXw/1k5VR0iZNNzfRycg= + +Name: system/lib/libwt6pptrdr.so +SHA1-Digest: yV9ut9izv9pC3uHuwGusX73po50= + +Name: system/app/HtcDataStripWidget.apk +SHA1-Digest: ilW8Kf+5P8fEGWDCiLP9QsUOahw= + +Name: system/app/HtcContactsDNATransfer.apk +SHA1-Digest: Y/LKOoUnzguc5LBzs5uAVCsNoz4= + +Name: system/etc/security/cacerts/c3a6a9ad.0 +SHA1-Digest: fLZHDOpbrGZWvLkuE3qgKE8NxuU= + +Name: system/lib/hw/copybit.msm8960.so +SHA1-Digest: xHGReRk1BCM7kcZ8rI5X9e3HEpU= + +Name: system/lib/libaah_rtp.so +SHA1-Digest: qd8eMrRU+Jw8l1H/vjttFqhJSiE= + +Name: system/bin/start +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libchromatix_s5k6a1gx_default_video.so +SHA1-Digest: oXZchM6Km012QC4pyTlRjpp3nKY= + +Name: system/etc/NOTICE.html.gz +SHA1-Digest: biuUwzhCgq5GjrKgeiwO+uJ0xWA= + +Name: system/lib/pp_proc_plugin.so +SHA1-Digest: uPqlxh4p3dtUEbNWzJMSHdphVrY= + +Name: system/bin/mm-mpo-dec-test +SHA1-Digest: VvJ1QwHTRyof+f6nnBPwnJOKfs4= + +Name: system/bin/hd +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/HTCWeatherClockWidgetAgent.apk +SHA1-Digest: 77fowdXm0shCLvQ6PgCVrDF4D3Q= + +Name: system/media/audio/notifications/Olive.mp3 +SHA1-Digest: 4Qt31whgN0ERMv9hrYejogl7S4g= + +Name: system/media/zchgd/batt_20.rle +SHA1-Digest: H94fJLAo1VJ12d4VgM7RqrxEJQI= + +Name: system/app/Facebook.apk +SHA1-Digest: Prwx/foKi7WktdFJHENqiugdIWQ= + +Name: system/app/HtcCalendarWidgets.apk +SHA1-Digest: 9dbVmm1DnXDtieCR2CBIM1HSODA= + +Name: system/app/VoiceSearchStub.apk +SHA1-Digest: mB+R5R/hWaSuwUaxF8zQ1VYbtLU= + +Name: system/media/zchgd/charging_09.rle +SHA1-Digest: S48C90ViaLLTNuLvRQ95MBU8/DM= + +Name: system/lib/libmorpho_edit_engine.so +SHA1-Digest: sn2u9olIS//pqmIFPXbT04JYjd8= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_on_sel.png +SHA1-Digest: GFe5LzZlbXSly+JDxME4ogZqEZw= + +Name: system/media/GPU/dot_mask_16x16.bmp +SHA1-Digest: qrLAwxXlluYbqatU06+Rg6TiKS8= + +Name: system/lib/libchromatix_ov8838_preview.so +SHA1-Digest: y2tKKWPQry3P/TEIQ+0hJ3Xfv54= + +Name: system/media/zchgd/charging_03.rle +SHA1-Digest: nTXp2Ml9w2TPiqd8Vi6NR1wpmYc= + +Name: system/media/GPU/ContrastCurveSet.bmp +SHA1-Digest: roYDdcsfTVFwpM/ZIzVQrBie/7A= + +Name: system/etc/permissions/com.broadcom.bt.le.xml +SHA1-Digest: QPYcOsj6a6cagjBQZJDy23evcYM= + +Name: system/lib/libGLES_trace.so +SHA1-Digest: /7AU8F7zLukLhk/p+EVAhJI2ZCk= + +Name: META-INF/com/google/android/update-binary +SHA1-Digest: VtCr1jnXgXMfBohepsvLkllYIg0= + +Name: system/etc/security/cacerts/3e7271e8.0 +SHA1-Digest: exnkaZiA8uIb4yIVkEyv4B8Mo40= + +Name: system/etc/security/cacerts/89c02a45.0 +SHA1-Digest: 6k/+zqCB5f/qyWJjkf/PvVoNG64= + +Name: system/etc/tfa/voice_l.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/lib/libcameraasd.so +SHA1-Digest: iMQBAZr0WL+9RaP4uevXuWrxIPI= + +Name: system/lib/libETC1.so +SHA1-Digest: DisCtmBA8J/88Xn3Y+OY7EZXTvg= + +Name: system/fonts/Lohit-Bengali.ttf +SHA1-Digest: L8kDnfbVNjOJMtDSZTd/OjkndS8= + +Name: system/media/zchgd/charging_05.rle +SHA1-Digest: RxWagAYJ9pk2xnZppBnwdNUpdxo= + +Name: system/media/audio/ringtones/Vanilla.mp3 +SHA1-Digest: 1SxbgXxMdYvn4EXMSHMPh8GVdQA= + +Name: system/bin/screenshot +SHA1-Digest: /E332dYacBltFf8H8F/zw3oBZjM= + +Name: system/lib/libOpenCL.so +SHA1-Digest: 2U/EshFRq11j4eO+XBr3mWkYM4M= + +Name: system/bin/cir_fw_update +SHA1-Digest: navUdcWtB/ORyzaZ3XN6SiFG+fk= + +Name: system/media/audio/notifications/Pear.mp3 +SHA1-Digest: /sAdGHGjmvas8wjGpd1QNAbgiRo= + +Name: system/media/mms/kddi_earthquake_alert.mp3 +SHA1-Digest: pabH2nWTXdOSLBAI+pJya7MR/r4= + +Name: system/lib/libvideoeditor_core.so +SHA1-Digest: QJ7mokQcRuTYZts+UF0nZ3YP+Z8= + +Name: system/lib/bluez-plugin/network.so +SHA1-Digest: Qr1Y0OxuVpgErhfyQesfBDIo/l4= + +Name: system/bin/thermald +SHA1-Digest: Wr+mMKa/8d+VBbBWkhmGqA+2qLI= + +Name: system/lib/libexpat.so +SHA1-Digest: CIai+dbiAT4X2hD/OBIyBmnPXQY= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_on_sel.png +SHA1-Digest: ResWXZhJLGsmdQXzieaC7zI84/8= + +Name: system/app/HtcModeClient.apk +SHA1-Digest: i5kc3hPIp+8VF3FzqdGNbxX45hg= + +Name: system/customize/resource/trickdroid.jpg +SHA1-Digest: 3NwsI8FC0rXGxfcHxfn1x/bJkUE= + +Name: system/app/Flashlight.apk +SHA1-Digest: k9X07SW1eOeHcDCztT8gNsJEzPg= + +Name: META-INF/com/google/android/aroma/fonts/big.png +SHA1-Digest: oHYrbDXlnhjFwHqNQePor+/Vf/A= + +Name: system/etc/security/cacerts/27af790d.0 +SHA1-Digest: tWr5feX55f+zArlEQVaA+3FTUZk= + +Name: system/customize/resource/quicklaunch_20201.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/libaudioutils.so +SHA1-Digest: mDBmNK8faRMvHrJXReTkud2pMvI= + +Name: system/etc/hltof.bin +SHA1-Digest: axmU3A62c/M9Vx5bhZJfCFNPaXo= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-rn30-ri30.5-v24/full_model.bin +SHA1-Digest: zd4aqRFsrWVCg9MMHAQMpm8tWyY= + +Name: system/lib/libsqlite_jni.so +SHA1-Digest: 7wxca+iSFexD8BXG8ula5zZ5P3Y= + +Name: system/bin/ndc +SHA1-Digest: eNgJroW7M3Klt/t/m75BdCRGHHU= + +Name: system/lib/libskia.so +SHA1-Digest: EZG3k40O/U9SOJ8W6+7Dgaoi5EI= + +Name: system/usr/srec/en-US/google_hotword.config +SHA1-Digest: Q8EXKoSue5BQvI8aQIC5FgDXr7M= + +Name: system/lib/libdrmframework.so +SHA1-Digest: HJX1qqHjuw4Hnr4l4GqoU5q2Wls= + +Name: system/lib/modules/moc_crypto.ko.3.4.10 +SHA1-Digest: wGyXq6GEMzMsKIdOwWD7NVhuMP8= + +Name: system/lib/libandroid_runtime.so +SHA1-Digest: 0i75no3JWAtjL8L1ZNMqcx2B8eI= + +Name: system/lib/libgabi++.so +SHA1-Digest: 5XuI+2FjNoarhaQBX0/mDHFI2gk= + +Name: system/bin/ip +SHA1-Digest: S1K6wQEVcIhGji4ZNVRl6NaCQw4= + +Name: system/bin/rtspserver +SHA1-Digest: HV6HaJdUpLldUaQDM8RePzn/NXI= + +Name: additions/fonts/segoewp/Roboto-Italic.ttf +SHA1-Digest: GJbcewXmkyB3YcV4qvzeo4E7k0c= + +Name: system/etc/permissions/android.hardware.camera.flash-autofocus.x + ml +SHA1-Digest: B9lECmkbQ6pSctxuPBeUiDPmthA= + +Name: system/bin/id +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: META-INF/com/google/android/aroma/icons/personalize.png +SHA1-Digest: mnAYF0GaMh88zuP56SKiEcxq2pk= + +Name: system/lib/libstagefright_soft_rawdec.so +SHA1-Digest: Ga+toLhkzPGD2fRM3Fh6XkM1VYM= + +Name: system/bin/setprop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/kill +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/image_htc_earbud.bin +SHA1-Digest: BQvgRVzmndETmB2zqTO7nDfu05c= + +Name: system/app/OneTimeInitializer.apk +SHA1-Digest: vNp5PcD4OMPv/kdCktZh+Ym1GLs= + +Name: system/usr/share/partials/ticklist.csv +SHA1-Digest: /KbguW9SBGbKSzULShtwb5UkaLE= + +Name: system/app/JETCET_PRINT_S50.apk +SHA1-Digest: 9VXwMt6DgEL63siq5knL0+AtlrQ= + +Name: system/etc/permissions/com.android.location.provider.xml +SHA1-Digest: LTdinhy89ODvYRYxUm8yTOSA5VM= + +Name: system/lib/libzeroeditor_videofilters.so +SHA1-Digest: MhKTiBo1+CFolLw++j0TlgYnVDI= + +Name: system/bin/ln +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libChange.so +SHA1-Digest: 72HvBVw5Fgj9jvfl47G2qLaoSY0= + +Name: system/etc/capability.xml +SHA1-Digest: k+jsHQZ+/yBYeXC+p3She4CvEZ4= + +Name: system/bin/ls +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: META-INF/com/google/android/aroma/icons/customize.png +SHA1-Digest: BaZ7Q5/xMfjVC22hsYmQ3lfKfBw= + +Name: system/bin/mksh +SHA1-Digest: AtbTC0Y345Q8WUktAbZDG2IfbpY= + +Name: system/etc/tfa/fm.preset +SHA1-Digest: 5sbhFGjzewa4Pfs10aaWH7c80Ew= + +Name: system/media/audio/ringtones/Pearl.mp3 +SHA1-Digest: Y7Bq9HYiesPOPZ4zZIOF5V7zx/s= + +Name: system/etc/permissions/com.orange.authentication.simcard.xml +SHA1-Digest: epCNDZ7eEVaCAtm40i+f5+XFoXs= + +Name: system/customize/resource/allapplication_23801.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/media/audio/notifications/Saffron.mp3 +SHA1-Digest: +FdZMPoLejhfa9CPC/QYkFdEQYo= + +Name: META-INF/com/google/android/aroma/icons/nova.png +SHA1-Digest: Gx/1cvONcm447ffX5qizF3IxASg= + +Name: system/bin/ks +SHA1-Digest: x+AEts2KwouOQ9L/279//gmTFh0= + +Name: system/lib/libm.so +SHA1-Digest: OmrEBW5pnXLTquKcOd7mAcs2wvg= + +Name: system/lib/libdrmdecrypt.so +SHA1-Digest: es0IN1VgjrwJUAcwNb52T9sr0hY= + +Name: system/media/zchgd/charging_02.rle +SHA1-Digest: EXqLHmDATH06bTfx8yaOikW1qOE= + +Name: system/tts/lang_pico/de-DE_ta.bin +SHA1-Digest: 4+D9z4UNIRauW5tuRA/6Z8gjRZo= + +Name: system/bin/hostapd +SHA1-Digest: fMu31XZwo01HY5cOlnmiIQunxYw= + +Name: system/etc/voicemail-conf.xml +SHA1-Digest: gEhglUYhKRFe/gLhE94bPPBBkis= + +Name: system/lib/libmm-abl-oem.so +SHA1-Digest: uBp7lWNkxS4wmsAwAcp5lxotpjo= + +Name: system/usr/srec/en-US/offensive_word_normalizer +SHA1-Digest: RIsPYtNeY/zpfXhd80jm+FtPTEk= + +Name: system/app/HtcCompressViewer.apk +SHA1-Digest: vxZUe/m8Xzsp7qS1GjCt+/smPrw= + +Name: META-INF/com/google/android/aroma/changelog.txt +SHA1-Digest: o2QwUA/8EDFcz6GBRndT/PwBKi8= + +Name: system/media/audio/ringtones/Pink.mp3 +SHA1-Digest: gR43IxTs1H5pyreV9nasXQs3eIY= + +Name: system/lib/libchromatix_vd6869_hdr.so +SHA1-Digest: pFxSeF/efHQATVq4GV9S51GAFBM= + +Name: system/media/PFFprec_600.emd +SHA1-Digest: Lp6CpxDd7/os6xa7v/mAzUATs9g= + +Name: system/usr/share/partials/partials_H_gb.csv +SHA1-Digest: 6Wde5jH/xw/Icvl+fVnJJg04/6A= + +Name: system/app/SoundSetDownloadManager.apk +SHA1-Digest: B/pLMa5+yu2iq08J9EsA2yfGptQ= + +Name: system/lib/libwlwpscli +SHA1-Digest: NUaizgnrnzhRVL2RlE14srPeXJE= + +Name: system/lib/libjavacore.so +SHA1-Digest: yEafnvlNdxnzH66U6FtN4xpfauA= + +Name: system/media/audio/ringtones/Brass.mp3 +SHA1-Digest: rtkyk28W/Vwn5xyqRHJsvdlqFBw= + +Name: system/customize/resource/quicklaunch_65501.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: additions/wipe/bash +SHA1-Digest: F69Mawxw1zmAOQLGd0uxGGKimhA= + +Name: system/usr/share/partials/partials_CW_rr.csv +SHA1-Digest: QGpuL87jnCrX6qj+w6CvO+Yr7+M= + +Name: system/etc/security/cacerts/7651b327.0 +SHA1-Digest: j/CjK50zYtj/xzaZFhptUghXaPk= + +Name: system/bin/ioctl +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/mv +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/IMEXT9Italian.apk +SHA1-Digest: tPMuKDobkkYFEZRFnFTfMeQSUE4= + +Name: data/app/com.google.android.apps.plus-1.apk +SHA1-Digest: QAB8+ZNxBkl+9l3N05269ljXCoA= + +Name: system/lib/hw/lights.msm8960.so +SHA1-Digest: gqFab0FjUHHiVj7166kfG6QtQnI= + +Name: system/media/audio/ringtones/Cerise.mp3 +SHA1-Digest: I8CAHjfUuAgTIWNkTtL9cZ2M/Vk= + +Name: system/etc/security/cacerts/219d9499.0 +SHA1-Digest: kAbEu38ad02aTzdrF222x0w0M0o= + +Name: system/lib/libmmcamera_statsproc31.so +SHA1-Digest: DX1NdQQqpsUGQErdcbQ//jfSlA0= + +Name: system/usr/icu/icudt48l.dat +SHA1-Digest: bqcC8epqeTv8IrZ8PKMsVCHLIOk= + +Name: system/fonts/ARDJ-KK.ttf +SHA1-Digest: L0wleYpEe9myxwgMOqVm/8e0HsU= + +Name: system/app/VpnDialogs.apk +SHA1-Digest: c8TzYq9l7TookjWKdLjIghkZCBQ= + +Name: system/lib/libDxAndroidSpecific.so +SHA1-Digest: rQT3QlVF1jXaIEsBqnDZnxkaya4= + +Name: system/media/audio/alarms/Jade.mp3 +SHA1-Digest: st/f7XW9r0PEAVsJ0jMO5w8rGdA= + +Name: system/lib/libpphwrcore.so +SHA1-Digest: f1uhaPpKnaj+Kmjv5fCPZErdjL8= + +Name: system/app/IMEXT9Swedish.apk +SHA1-Digest: LhKkqC1KDlIvxYWMsjmF1OHiu9U= + +Name: system/etc/security/cacerts/60afe812.0 +SHA1-Digest: q2HXyTTJrYXtlcX9A4n+Smodlco= + +Name: system/usr/srec/en-US/hotword_symbols +SHA1-Digest: 7qeVa2EIhFOtRUo55/SFRc4EIzE= + +Name: system/app/ZeroEditing.apk +SHA1-Digest: mOLSwSm9bsuD3nPPvvhX9T4DMlc= + +Name: system/app/Trim_n_Slow.apk +SHA1-Digest: AZEfKG/xEPUAIwVE+jGNBaZYdxQ= + +Name: system/etc/security/cacerts/f0a38a80.0 +SHA1-Digest: 477jilsDvssMgn9iF5DSp2L1dBg= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-rp30-ri30.5-v24/full_model.bin +SHA1-Digest: 759/0Df6xJs4gqdB7a/kA81yX44= + +Name: system/lib/hw/power.default.so +SHA1-Digest: KocExwwT9Wlsko41O/XG5hcJC1M= + +Name: system/lib/libmmwfdsinkinterface.so +SHA1-Digest: bKq2GUyzGBAvw4B0nt+N50JkLEM= + +Name: system/lib/libdbus.so +SHA1-Digest: p1ww3oTzHuLjdDpP+Bm8WOTiaso= + +Name: system/bin/input +SHA1-Digest: QALzgk6btxyAeKYglJuc20newks= + +Name: system/customize/resource/wallpapers_a_01.jpg +SHA1-Digest: 0HAE1p7QQHJZkqh+wgOHMYLXSxI= + +Name: system/lib/libalmashot-seamless.so +SHA1-Digest: odBXwbyZHasOa2yazKJXHW7XRaQ= + +Name: system/media/zchgd/batt_60.rle +SHA1-Digest: HITkPml3u3zwomD5uAVs2cNcEoU= + +Name: system/lib/hw/local_time.default.so +SHA1-Digest: wVJsmcRTLw0INlGLg5xosWzeM5k= + +Name: system/lib/libmmwfdinterface.so +SHA1-Digest: e1K+IdYrlEgxRKnBxK3zQMt0ZQ8= + +Name: system/bin/pm +SHA1-Digest: XY3kUD4TG6bh8EMZiFFrRWiG7Ec= + +Name: system/lib/libext2_com_err.so +SHA1-Digest: BSLIAt5ebdmwN9ekWwGR3O13rm4= + +Name: system/etc/firmware/fw_bcm4335.bin +SHA1-Digest: xmuNdIdduLdBGDKSfXL3O6FpdSw= + +Name: system/bin/mm-mpo-enc-test +SHA1-Digest: FlKv0JpU9BEcqz2fVsd0y41FbVA= + +Name: system/bin/ps +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: additions/desense/Apex.apk +SHA1-Digest: yU8lUBgl5xbhGwJfgVRaJAEXbBA= + +Name: system/etc/firmware/a300_pm4.fw +SHA1-Digest: QrPhH4bO2hPUjoQPVsQsXEBBB+w= + +Name: system/lib/libchromatix_ov2722_hdr.so +SHA1-Digest: /J4dEZtuQF+qjuesj/K23RCHXHQ= + +Name: system/media/audio/alarms/Amazon.mp3 +SHA1-Digest: XFh/W7gZE4T3l7gSJ7jIzJrd1xk= + +Name: system/etc/tfa/voiceWB.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/bin/port-bridge +SHA1-Digest: G3WlcqGqIhZPLjXxq1+4mmAAC5I= + +Name: additions/camera_4.2/lib/libjni_filtershow_filters.so +SHA1-Digest: vvad3jmOu8bieJWshtJkzVGu23s= + +Name: system/app/IMEXT9Norwegian.apk +SHA1-Digest: tX/b7yQ9VRT2TaAcbNs2KFSqM+o= + +Name: system/etc/sdk/sdkinfo.xml +SHA1-Digest: strBQ803H7m7Mmxlc4JuWgJPzPs= + +Name: system/lib/libImageAlignment.so +SHA1-Digest: LPIBnUI34KZg/FtVJAxC+90hmlY= + +Name: system/bin/dalvik_coredump.sh +SHA1-Digest: 7YfCyuA6+7KtXknKMOXdB4sgz/w= + +Name: system/fonts/Lohit-Telugu.ttf +SHA1-Digest: W03fOM/KRs6NXuT+IWU6wXXW2QY= + +Name: system/etc/image_ibeats_2vol.bin +SHA1-Digest: vjvhr7ejqmQ60pXuUxqB9veV0pk= + +Name: system/tts/lang_pico/es-ES_ta.bin +SHA1-Digest: NqpVUDr2Zot71OE2b9H9alSFvmU= + +Name: system/app/BackupRestoreConfirmation.apk +SHA1-Digest: qDntanWX+MnYNhoO2RrVJD87mf8= + +Name: system/lib/libstagefright_enc_common.so +SHA1-Digest: +uGp308y3njBj1+q+Ez+d+qGcBI= + +Name: system/media/audio/notifications/Capri.mp3 +SHA1-Digest: fb0f2+DEm9/IZf59qQnNlT7qUOE= + +Name: system/lib/libsurfaceflinger.so +SHA1-Digest: hEkIGnHbCwac26zeYAvxLwnbC7s= + +Name: system/bin/tc +SHA1-Digest: 8ZXftveIrr6x1KKzb8a3wovrgqY= + +Name: system/etc/updatecmds/google_generic_update.txt +SHA1-Digest: 1Vp4IR8a20SbLBsHcaOPbkUf+NE= + +Name: system/bin/dmagent +SHA1-Digest: s2W0Pg6erv4oQ26QEd78D3jSdEw= + +Name: system/fonts/MTLmr3m.ttf +SHA1-Digest: Btnmblk0kwRaZjo2AkofmEVA7Os= + +Name: system/lib/libOlaEngineNew.so +SHA1-Digest: FwCZ9bC1z9o3XNY48HgLrHVmTJ4= + +Name: system/bin/brcmapd +SHA1-Digest: +shHcui55nH5pIxgOMjZvdfheMg= + +Name: system/media/audio/ringtones/Yellow.mp3 +SHA1-Digest: 5Rs/XQrj0a56+wwQ8FyPzWpIh4Q= + +Name: system/etc/security/cacerts/a15b3b6b.0 +SHA1-Digest: 8ZOob41YQP9QUVzJd/7ktNxnMRw= + +Name: system/customize/resource/allapplication_26801.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/33815e15.0 +SHA1-Digest: Tg2OusUL9dKQej4AiGYCRSEgVyY= + +Name: system/usr/srec/en-US/google_hotword_logistic +SHA1-Digest: ockBZc2VMYxuaYq6KET9/bVJbtA= + +Name: system/lib/libstagefright_soft_amrwbenc.so +SHA1-Digest: Zm+NDMWcQI/sUAKSa6efaHHQQDk= + +Name: system/etc/AudioBTIDnew.csv +SHA1-Digest: Gqh/UYdUamQ0hhKaMR4rftiJS6M= + +Name: system/lib/libOpenSLES.so +SHA1-Digest: Nlrm0ZmW33UuQ232fA7tPULKFGU= + +Name: system/lib/libgnmc_aactag.2.5.9.4.so +SHA1-Digest: az7H58js2u60b15IB/ckj2nAzSo= + +Name: system/lib/libwebcore.so +SHA1-Digest: iKlwYnQeokdWgKAQrWeI7sl6NMc= + +Name: system/media/audio/notifications/Lilac.mp3 +SHA1-Digest: w+lAsOjMjvDGROYnkhUVYaGLEys= + +Name: system/lib/libhwui.so +SHA1-Digest: UoAbW8Q/oPhsOseLlhCU5IOWHKc= + +Name: system/media/audio/ringtones/Mustard.mp3 +SHA1-Digest: frTfMvAlgAaaFiuqQ8uhoNrfNG8= + +Name: system/etc/tfa/voice.preset +SHA1-Digest: OVBiITpEEwnpRzjGcCTdTkgmGA4= + +Name: system/media/weather/weather_l_thunderstorm_night.mp4 +SHA1-Digest: xeaglmdE6nR7llDH3GPZj+kCNOU= + +Name: system/usr/share/partials/partials_A_rr.csv +SHA1-Digest: sTqwPLgB5lu1fU2zG83kvGOpDBk= + +Name: system/lib/libsrec_jni.so +SHA1-Digest: suu6aNn6SkQtawHo52QvreQvxZM= + +Name: system/media/GPU/header32bpp.bmp +SHA1-Digest: cVd7vUZ5xiCRD3XhuTFpPUjxC0w= + +Name: system/fonts/DroidSans-Bold.ttf +SHA1-Digest: Ykc18CQi8T5QzPRm8NKe3aBa2zY= + +Name: system/etc/agps_rm +SHA1-Digest: 2jmj7l5rSw0yVb/vlWAYkK/YBwk= + +Name: system/lib/modules/bcmdhd.ko +SHA1-Digest: 7433DTw/6R0GuMYjNT3f6hK28Qo= + +Name: system/app/MyGoogleTaskPlugin.apk +SHA1-Digest: 4gBWeaGazltpjDNH9aeY/1aZbjs= + +Name: system/bin/akmd +SHA1-Digest: 1rnxMQDAvhxkKBbWTLgO2Rf8vm4= + +Name: system/etc/bluetooth/iop_device_list.conf +SHA1-Digest: TdKSuRkPZjKgvTvEC8jyGaCSdr8= + +Name: system/lib/libmmipl.so +SHA1-Digest: rLSAhTG3L0rwxBzqS2zxb1uktEs= + +Name: system/lib/libdmt_vocalizer.so +SHA1-Digest: sLaTmgeTwSz5MXjCdZLgzJ7uNmA= + +Name: system/lib/libOmxVdec.so +SHA1-Digest: Xx794TUu1yBalixHbvb4FEzZI/k= + +Name: additions/fonts/veggieburger/Roboto-BoldItalic.ttf +SHA1-Digest: 5v6ke/vpr2ZsccH1w33Ogr5YAbA= + +Name: system/etc/security/cacerts/10531352.0 +SHA1-Digest: x031sSTTrg99nYnqERvbmDu8aP8= + +Name: system/customize/resource/quicklaunch_21403.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/HTCMediaAutoUploadSetting.apk +SHA1-Digest: Nu7rneZwk3Y5VE40//G8RPBs0bY= + +Name: system/bin/wpscli_test_cmd +SHA1-Digest: 8mEoufwud+K7DoqomZo5ysFUZjg= + +Name: system/lib/soundfx/libaudiopreprocessing.so +SHA1-Digest: OGmb+76DPWV8aUIrhOaNNMOqPig= + +Name: system/lib/libchromatix_vd6869_video_hdr.so +SHA1-Digest: CXe+Qq3saE7qCRPDWJccNQRAokc= + +Name: system/customize/resource/allapplication_228.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/dhcpcd +SHA1-Digest: GCXsC3peq3eZxlBG1gWdGIJa99k= + +Name: data/app/com.melodis.midomiMusicIdentifier.freemium-1.apk +SHA1-Digest: 8kqn6tJQS00oUx0SCWI1IlHJnZE= + +Name: system/bin/l2_profile_exchange +SHA1-Digest: a8m3prEi4PBFVD9X8YMRw5X+3YM= + +Name: system/fonts/AndroidClock_Highlight.ttf +SHA1-Digest: 0vRHOkM++Y5hREyvokR3HBnI2ig= + +Name: system/lib/libloc_adapter.so +SHA1-Digest: miK40rr48n7kDIZBXx3vn/lGLHA= + +Name: system/bin/rm +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/framework/com.htc.android.home.res.apk +SHA1-Digest: re117fgRZeW2tVx2p1JKtMChGUk= + +Name: system/media/audio/alarms/Turquoise.mp3 +SHA1-Digest: UibvlSTXFjMIdQ/y/DXqDSmVSl0= + +Name: system/lib/libchromatix_imx135_zsl.so +SHA1-Digest: YZFAn1ti4/djMLUMAqZ2hXvBhUc= + +Name: system/lib/libgoogle_endpointer_jni.so +SHA1-Digest: kX/O1CZ4pT6phlKrbw58QLLbxfA= + +Name: system/lib/libbt-aptx-4.1.1.so +SHA1-Digest: rZNVP7xWHQX1KdgkGtpAjtS7XKE= + +Name: system/framework/requestsync.jar +SHA1-Digest: MZzwRoXa1GjyxtsTIBl/BhMh3U0= + +Name: system/etc/permissions/android.hardware.nfc.xml +SHA1-Digest: GIaOjWIx6Re8D6cSufWoe3tSkw4= + +Name: system/lib/hw/nfc.m7.so +SHA1-Digest: PtlsI0eQwDu+rjiepUf2NuXeX3s= + +Name: system/media/zchgd/batt_90.rle +SHA1-Digest: 3rIXvJMnp/LK3LWpJB3ohkz9TNo= + +Name: system/customize/resource/wallpapers_a_00.jpg +SHA1-Digest: dg46UFdE7l2FDYlgdi13jn8AhfM= + +Name: system/app/Tag.apk +SHA1-Digest: XsuowlwMALDbq3jjMOqucg0RoiY= + +Name: system/customize/resource/bootanimation.zip +SHA1-Digest: Tw1xSnBQ+Cx0EMGuYNLpGyakSqU= + +Name: system/lib/libdvm.so +SHA1-Digest: vkchp8WS5UIbIhUfiAEvnWOI+5o= + +Name: system/bin/sh +SHA1-Digest: PHOOpAG9IpARYrBB1CtNeBbyugQ= + +Name: system/lib/libmdnssd.so +SHA1-Digest: U4Qb9R8jnuAOfrQgekqZqb0Tayw= + +Name: system/app/FlickrEngine.apk +SHA1-Digest: uEJLrtNP5Ytz3uiqoS+p+7zeSLk= + +Name: system/etc/security/cacerts/ee7cd6fb.0 +SHA1-Digest: UwvGu9gadYis3G+kKIIPVzHgGRk= + +Name: system/media/audio/ringtones/Aqua.mp3 +SHA1-Digest: pXW9Xsy3UIIzS/d/jxdybBCwJjQ= + +Name: system/app/LocationPicker.apk +SHA1-Digest: RKkwziKH/3I7fFaXh1t5zXtt3Ro= + +Name: system/vendor/pittpatt/models/detection/yaw_roll_face_detectors. + 6/head-y0-yi45-p0-pi45-r0-ri30.4a-v24/full_model.bin +SHA1-Digest: qC6ZM1KBN5XExmxhUXM5McociJ8= + +Name: system/customize/resource/quicklaunch_23802.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: additions/dormancy/dormancy.sh +SHA1-Digest: Pmig1OJ+4mh3pKKV03INFu3K6FM= + +Name: system/media/audio/notifications/Lime.mp3 +SHA1-Digest: 1K5E3SRxUBEPb+u7vMicCwIn+/Y= + +Name: system/app/HtcDLNAMiddleLayer.apk +SHA1-Digest: /QT/WWOxQN7s66EpGbZPW7TZemQ= + +Name: system/lib/libconfigdb.so +SHA1-Digest: viC/s/cNiFQUKUjeyjUK0vS7EKs= + +Name: system/fonts/DroidSansHebrew-Regular.ttf +SHA1-Digest: x+RcN58KCjuoXGnq7mti4m/7gag= + +Name: system/bin/route +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/c8763593.0 +SHA1-Digest: kZMwI4zPBDpymR428YsYQNm4Etw= + +Name: system/usr/idc/qwerty.idc +SHA1-Digest: 5oeOyx5R5vdh3tPnK4A+NyN9jzg= + +Name: system/media/audio/ui/Volume-2.flac +SHA1-Digest: WIvWiqi1f2nRqevMotkyhRR9WUM= + +Name: system/lib/libhtcflag_native.so +SHA1-Digest: MJgp6r54goA8xL1gEN3b+NVwRRw= + +Name: system/customize/resource/quicklaunch_28010.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: additions/fonts/helveticaneue/Roboto-Bold.ttf +SHA1-Digest: ejK3MxV4VpZhZJKLZFuKgfpgBo8= + +Name: additions/gps/oceania/etc/gps.conf +SHA1-Digest: oHvd+/TVsst/c5x3sZWI5vxhciQ= + +Name: META-INF/com/google/android/aroma/themes/sense/titlebar.9.png +SHA1-Digest: V36x7nmB4rgSAEDMj2KmQX+CqsE= + +Name: system/media/audio/notifications/Fuchsia.mp3 +SHA1-Digest: rKZ05GIDryb35jFmHHhJwuuNsf0= + +Name: system/customize/resource/allapplication_65507.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libSkiaWarper.so +SHA1-Digest: sXKNz4gEz5r6ZrwQoVVLgRLEcls= + +Name: system/media/weather/weather_sunny.mp4 +SHA1-Digest: TsJqq606vjdFWXRKx4xv7VUfQjQ= + +Name: system/framework/com.htc.android.bluetooth.jar +SHA1-Digest: lEYxDi8EkalOFQiEftYNwm4myeE= + +Name: system/bin/mm-jpeg-dec-test +SHA1-Digest: NMuLZXB3pQ/c3MJXfOpGnZWtzFc= + +Name: system/lib/libxt_native.so +SHA1-Digest: unlur90tEoRiJSwiErDS42a2uNQ= + +Name: system/etc/security/cacerts/1dcd6f4c.0 +SHA1-Digest: ZD4839PLxZdYujgVOpN7nvdxfvs= + +Name: system/etc/security/cacerts/9772ca32.0 +SHA1-Digest: gLmISuqfwLlRD8jocBuF5N3MkTM= + +Name: system/media/weather/weather_cloudy_day.mp4 +SHA1-Digest: wh2Nv12FGXhv/ZzjMi4oNsd0tvM= + +Name: data/app/com.google.android.street-1.apk +SHA1-Digest: gy7wRgDM+/QJWcqujoRdJcZFtgM= + +Name: system/app/PhaseBeam.apk +SHA1-Digest: ielPdSX3mNLQgYX+tTV7iLby5wo= + +Name: system/etc/security/cacerts/5e4e69e7.0 +SHA1-Digest: RU4Glj5/5C9MVwUct4nnQREaDf4= + +Name: system/etc/firmware/hcheck.b03 +SHA1-Digest: 2JeO5ns1SDnurjw+EjmLaxMgqng= + +Name: system/lib/libSR_AudioIn.so +SHA1-Digest: s8dQygjzJPQjSmX9GaT90IjK/bA= + +Name: system/lib/libqmi_encdec.so +SHA1-Digest: 26CSKQvdSdrV9UwnkfMowP1Rlq4= + +Name: system/customize/resource/allapplication_24201.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/fonts/DroidSerif-Regular.ttf +SHA1-Digest: gFxfl14C9Ij6HdHdDUTtT5Ow+rQ= + +Name: system/etc/firmware/hcheck.b02 +SHA1-Digest: WlNOjg0efF87NE9MRwsYKmsc544= + +Name: META-INF/com/google/android/aroma/themes/sense/dialog.9.png +SHA1-Digest: az4c50d0N5ecMDHxjZQp6nyXdvw= + +Name: system/etc/firmware/hcheck.b01 +SHA1-Digest: gd2tz4h9OJJrN+J3gUqi9XC/gnA= + +Name: system/etc/firmware/hcheck.b00 +SHA1-Digest: C4BmB/sEgIUA00GQ6FJLLDh3saw= + +Name: system/media/weather/weather_l_thunderstorm_day.mp4 +SHA1-Digest: TeZiLThX0Unuvd4ZEtfLxLLATw8= + +Name: system/etc/vold.fstab +SHA1-Digest: ucuLszvO3SHZOfQiNA0CMp/tV1I= + +Name: system/media/audio/ringtones/Navy.mp3 +SHA1-Digest: bAEA1Q4xbJcsoFm6sGFVI/pkDH0= + +Name: system/bin/system_server +SHA1-Digest: TaJbGo4Y4VsP7Go/qIbooGmPWsw= + +Name: system/bin/ip6tables +SHA1-Digest: 2qpoMVnCR1qe7GENPgGD/+FpOZs= + +Name: system/lib/libmmcamera_wavelet_lib.so +SHA1-Digest: yLp7X2iU9TWT7qLurgNzRAG0w28= + +Name: system/media/audio/alarms/Steel.mp3 +SHA1-Digest: K66Y4hc1crmgbP0ndNq5A2R1jR4= + +Name: system/usr/share/partials/partials_H.dat +SHA1-Digest: 6dQX7CVJ1gVAwOKdtEiWhm3hYnE= + +Name: system/customize/resource/quicklaunch_23420.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/weather/weather_partly_cloud_night.mp4 +SHA1-Digest: i37+qFiRsf1xCZRncomlEb9Q1vw= + +Name: system/etc/tfa/playback.preset +SHA1-Digest: 580uOSSwzkh9I7l9PyiZgNlsUg8= + +Name: system/media/audio/ringtones/Laquer.mp3 +SHA1-Digest: sFtlaRFuRdUS6BltC2r5nN+XOsQ= + +Name: system/bin/sendevent +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/08aef7bb.0 +SHA1-Digest: UDr/oMgTCEDGW8P/MLGetyQV6u8= + +Name: system/bin/wl +SHA1-Digest: X2QXpEp8OVHPEeaU4NwGySlLmi8= + +Name: system/app/Settings.apk +SHA1-Digest: gHKYSqeqFXvkmHvzntdHJRCJ+Us= + +Name: system/lib/libstagefright_soft_mp3dec.so +SHA1-Digest: xpKEFKirOyhSFUksQ0ygWkb0K1I= + +Name: system/etc/firmware/fw_bcm4335_p2p_b0.bin +SHA1-Digest: s8ujoESTcrSfW/Q17UP/DzlEQo8= + +Name: system/lib/libttspico.so +SHA1-Digest: i05v1BTdOkIdh1jLD0T5fe5cctY= + +Name: system/customize/resource/allapplication_24801.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libBeautyChat.so +SHA1-Digest: fRzA/rj3ymM5xj72Ktq+00t1UGc= + +Name: system/lib/libnfc.so +SHA1-Digest: L583ggGB4ltbSstF71w4/xvkfwM= + +Name: system/etc/security/cacerts/1d657651.0 +SHA1-Digest: AJPWrMhCJR8Rc5W2NOtk7GsZq8w= + +Name: system/etc/security/cacerts/87753b0d.0 +SHA1-Digest: tDVMAZ7hAGg3lwrrlN+4kvp3Jkc= + +Name: system/app/HtcPowerStripWidget.apk +SHA1-Digest: WkcXkk/gTUwshGBXCJxg0urJuhA= + +Name: system/usr/keylayout/Vendor_046d_Product_c532.kl +SHA1-Digest: iT7ZHxI43pKBUzjQc541oOM22hc= + +Name: system/bin/climax +SHA1-Digest: GP7jOba2djn5PYv/ZlFb9+Su0Fs= + +Name: system/lib/libc2d2_z180.so +SHA1-Digest: 08rTYYnzPDddF5ahoGgHGzZu3LI= + +Name: system/media/audio/notifications/Magenta.mp3 +SHA1-Digest: ifqL1FH3yjmLzMzROxEZSo3ESxE= + +Name: system/lib/libqmi_client_qmux.so +SHA1-Digest: RWDhR0WS4cwUkLDDl996WKB20qQ= + +Name: system/app/WorldClock.apk +SHA1-Digest: HSV8bYlyRtTb7cBo3ZYIYzt+qdw= + +Name: system/fonts/AndroidClock.ttf +SHA1-Digest: 0vRHOkM++Y5hREyvokR3HBnI2ig= + +Name: system/lib/libchromatix_s5k3h2yx_hfr.so +SHA1-Digest: zYQg3LtJHryGbO2EGqKcHcQm4rI= + +Name: system/lib/libvorbisidec.so +SHA1-Digest: M0x1pISGdE2H9QtBqcfJyv71pBg= + +Name: system/etc/security/cacerts/48478734.0 +SHA1-Digest: CCkvYaE7BOlkHFDTReqBRiiR8II= + +Name: system/etc/security/cacerts/76579174.0 +SHA1-Digest: Uw9KFPBW37XtteEhKlq5eRnOm1w= + +Name: system/app/HtcNotesProvider.apk +SHA1-Digest: 2yYt03vBV2Cyr4umli/XmLlLgbU= + +Name: system/customize/resource/allapplication_23407.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/media/audio/ringtones/Cyan.mp3 +SHA1-Digest: /nDN/N7hPG1jMDFA0uwMrzGDFBY= + +Name: system/bin/ionice +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/media/weather/weather_l_windy_day.mp4 +SHA1-Digest: FCHMbwmJrbjeQH4KoQMQgctIWfw= + +Name: system/lib/soundfx/libdownmix.so +SHA1-Digest: WVOGcq7JOqrf6VNF+AOGd/IpxGw= + +Name: system/etc/image_ibeats_v2.bin +SHA1-Digest: sk5OXKhrlVALM7wlPCRxNjlrmRk= + +Name: system/usr/keychars/Virtual.kcm +SHA1-Digest: xYiPhd++Jpvl6ARXJyusriz4pqE= + +Name: system/bin/pand +SHA1-Digest: ZMXBK9eGlsTKQBacuifpjgwTvzQ= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x_Fusion3_DMIC +SHA1-Digest: GMpUgtLfs21E9UG4/9Y4pW6q/3w= + +Name: system/lib/libbcc.so +SHA1-Digest: dsB9BNyeUFQ3bQH725qzLGprOYc= + +Name: system/lib/libchromatix_ov8838_hdr.so +SHA1-Digest: 4rpYmxobRs4QoOkCEh6Ua5v6O2w= + +Name: system/lib/libstdc++.so +SHA1-Digest: 3YTMdOtqO+yHg0KoU/wW0upylbs= + +Name: system/customize/resource/allapplication_24008.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/hw/alsa.msm8960.so +SHA1-Digest: mY5ojcsvM/1g6t77GzOG7OuPd/M= + +Name: system/lib/libtcpfinaggr.so +SHA1-Digest: KJMIASBMHzCQxpnp+O5Kki22O7M= + +Name: system/lib/hw/camera.msm8960.so +SHA1-Digest: Qu/8X2nmNJs3vCys+brzVipz85E= + +Name: system/bin/aplay +SHA1-Digest: 6NYQVPkLIRJBjKCw1oTuCpXWSDw= + +Name: system/lib/libcameraservice.so +SHA1-Digest: 4ZRayTkbaYSiHJyEsUJt8YcnZao= + +Name: additions/fonts/segoewp/Roboto-BoldItalic.ttf +SHA1-Digest: giRk6fDZ0SHi824wIO5nYW7UXtk= + +Name: system/media/audio/notifications/Azure.mp3 +SHA1-Digest: G3ucPWq/kTonTGmvgdrYFyfp7kA= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_sel.png +SHA1-Digest: 7pjS+lUbSC+PIKz/ZFlYi1Q0qbo= + +Name: system/app/HtcSpeakNGF.apk +SHA1-Digest: uOPzoHwciI5o4KsYaiAfkoqOsXA= + +Name: system/lib/libchromatix_ar0260_default_video.so +SHA1-Digest: Py3Pc5Mo89hSl3XuoYYzgUKGFLU= + +Name: system/usr/share/zoneinfo/zoneinfo.dat +SHA1-Digest: bShcRYsKQq5TEPhpXvhJMaks+Ns= + +Name: system/media/audio/notifications/Vermillion.mp3 +SHA1-Digest: vJiXbzdF8poe/UUrL2FsrNVMN2A= + +Name: system/app/MyTask.apk +SHA1-Digest: wm6Eonrqhvf/486tyPlAh8ccqFo= + +Name: META-INF/com/google/android/aroma/themes/sense/cb.png +SHA1-Digest: RcJookrxsxmN98b0pdHWj1BOhsY= + +Name: system/framework/uiautomator.jar +SHA1-Digest: MOp4VoDD9cckeAqOBVeEfXhPXGY= + +Name: system/lib/libhardware.so +SHA1-Digest: gE+aDB6Znb8dWVDvy6HDTvXJzpg= + +Name: additions/fonts/helveticaneue/Roboto-Italic.ttf +SHA1-Digest: U1PDOx+d2cxdKKeXmmkyO5N+dUo= + +Name: system/lib/libpphwr.so +SHA1-Digest: NDzimzJdwblwsFBMzfcgJZ/XGgk= + +Name: system/customize/resource/downanimation.zip +SHA1-Digest: W10ZlwFkdSe/NfDkFLTUKU9usCA= + +Name: system/etc/permissions/com.htc.software.market.xml +SHA1-Digest: E/BqBu8ugtHZ1OGY+h4Bgqs48G0= + +Name: system/etc/security/cacerts/60f083f8.0 +SHA1-Digest: 6bEJK4/D+kSqeKMInAqbqBJVuro= + +Name: system/lib/libc.so +SHA1-Digest: koteUSFbvpNCyJSQMiLudw/IdgA= + +Name: system/lib/libext2_profile.so +SHA1-Digest: HdOoe5pQH/R0TV4X7RZ04h4ncGM= + +Name: system/bin/qseecomd +SHA1-Digest: hslOr2KtEHWqqtuNWPVpvILccdU= + +Name: system/lib/libgui.so +SHA1-Digest: G0hOOuwMyGS12XQuFmaQxsbqjwg= + +Name: system/media/zchgd/charging_08.rle +SHA1-Digest: nTXp2Ml9w2TPiqd8Vi6NR1wpmYc= + +Name: system/usr/idc/projector_input.idc +SHA1-Digest: jdmpS6Rrbyb9aEDdfIKHDIcMGdw= + +Name: system/app/WeatherProvider.apk +SHA1-Digest: gIZTrmv1RhXgxM/u7lduTpiLSKU= + +Name: system/bin/fusermount +SHA1-Digest: Pq3IHhSy+8CgIoF3ioQv/8J9GTQ= + +Name: system/media/audio/notifications/Purple.mp3 +SHA1-Digest: BdDCNlOVajs46E0wuyW3owciqnY= + +Name: system/lib/libinput.so +SHA1-Digest: RoebUdb5YHN+OGZyXVIv76iU+5Q= + +Name: system/bin/dmesg +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libgoogle_recognizer_jni.so +SHA1-Digest: XSsNFriGTcQNVMjgEsK/X5CE0/k= + +Name: system/customize/resource/allapplication.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: META-INF/com/google/android/aroma/icons/welcome.png +SHA1-Digest: ZjyGs/r4la7VrriRQUXPk33edrw= + +Name: system/media/audio/notifications/Ruby.mp3 +SHA1-Digest: YwrWSqwmAuZq0aDEO+VueJVWh3I= + +Name: system/etc/security/cacerts/418595b9.0 +SHA1-Digest: B6oXTUKiu1cnRTfY8Ck3pr4h5Jc= + +Name: system/app/HtcCupd.apk +SHA1-Digest: SsRCrkVUUtnQbZE8gQg+GW/IEso= + +Name: system/fonts/DroidKufi-Bold.ttf +SHA1-Digest: WQhlrdI9jAsNoe1Su0Uyd9gk4ZU= + +Name: system/app/HTC_CIR.apk +SHA1-Digest: h7YZ2pj8YegPphoN0vYnjFn3eLU= + +Name: system/etc/bluetooth/blacklist.conf +SHA1-Digest: tzfL29uwKo39KMrIZp8Cd3Wa36Y= + +Name: system/usr/srec/en-US/symbols +SHA1-Digest: VssslP42+1LcOram2NHS9Gxlu94= + +Name: system/media/GPU/CurveCold.bmp +SHA1-Digest: 8nF+MLzdnJFSMudXwC/q7WrO6LI= + +Name: system/etc/soundimage/srsfx_trumedia_voice.cfg +SHA1-Digest: xPIju7qeidETr0QJ6TkJ20bur9Y= + +Name: system/etc/firmware/vidc.mdt +SHA1-Digest: Kwo/hMLh12h5rFoRbcGuU0ukJSs= + +Name: system/bin/applypatch +SHA1-Digest: QK+KvNKbomEv4kSe4F79oinnE1E= + +Name: system/lib/libmedia_jni.so +SHA1-Digest: yhPDMpzu3osPBcw7BNL/WSEHZAE= + +Name: system/app/IMEXT9BahasaMalaysia.apk +SHA1-Digest: h7bQyCebLsqtfnp06EAmaSTsqWM= + +Name: system/lib/libpower.so +SHA1-Digest: 81LO2NWhRbM6yRximbHfdTxxf4E= + +Name: system/etc/mkshrc +SHA1-Digest: ymRp0Mh4Si4DSGQjbO2HFBivOTU= + +Name: system/etc/security/cacerts/d8274e24.0 +SHA1-Digest: z2/j38mQezRg/RCv/RJ9aCSpKZ4= + +Name: system/lib/libimu.so +SHA1-Digest: aDR3Dn3nxW5ubqLTmqEhm4wYZJc= + +Name: system/app/HtcWeatherClockWidget.apk +SHA1-Digest: GekMrORXYACTIRO5VW6pwhRcghY= + +Name: system/etc/permissions/com.google.android.maps.xml +SHA1-Digest: BbK4aFOA+G3wd2qESxbxITfwZYM= + +Name: system/lib/libsonivox.so +SHA1-Digest: vZUIvkMfkZ+iZpv7ZJH4zHZmtkQ= + +Name: system/lib/libstagefright.so +SHA1-Digest: V0F5MTH2nbjmuHeltDoDSGsCVR8= + +Name: system/etc/permissions/android.hardware.sensor.gyroscope.xml +SHA1-Digest: brL84JgL2wCWqFvQAQDPM5lm+4o= + +Name: system/app/IMEXT9Dutch.apk +SHA1-Digest: PlpfZOm8ZFF1Q4Styd4/aphbpzs= + +Name: system/usr/srec/en-US/dict +SHA1-Digest: h7Q/ArygyOrwdPMa0NL4+48riLc= + +Name: system/media/audio/alarms/Citrine.mp3 +SHA1-Digest: nndkVIHcYaWnNiMLcRxaPHMNOU4= + +Name: system/customize/resource/quicklaunch_21406.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/audio/notifications/Smoke.mp3 +SHA1-Digest: 2YbI9Krioe6M2m9m3aATGR1OCEw= + +Name: system/etc/security/cacerts/d777342d.0 +SHA1-Digest: WdQWfF7rZDzaXOGfoJMJS1qOuYU= + +Name: system/media/audio/ringtones/Orange.mp3 +SHA1-Digest: CxKx+6Q5OXffZALJLNGjyXlaRDI= + +Name: system/lib/libchromatix_s5k6a1gx_zsl.so +SHA1-Digest: rcP3nNaS9qv1nASjVvMaaJQXtI4= + +Name: system/bin/venc-widi +SHA1-Digest: cowCUbQjqb2zX2FKdpB3h/8vyas= + +Name: system/media/weather/weather_l_sunny.mp4 +SHA1-Digest: uyLd5pchxzv4zA/i3LZQkG5SsgY= + +Name: system/etc/security/cacerts/84cba82f.0 +SHA1-Digest: m8/Q3u0mnTMsbDO41AfCzDSrMvg= + +Name: system/lib/libwfdcommonutils.so +SHA1-Digest: jAMFWx5jyCYi4Rbhe04RqrJo7a0= + +Name: system/lib/libchromatix_ar0260_preview.so +SHA1-Digest: DUTrZyPpZlLIvuUM24s5UQ/6sNQ= + +Name: system/etc/security/cacerts/399e7759.0 +SHA1-Digest: UAbvBS8lvF2AOEsEs98fRQGKiwo= + +Name: system/media/audio/notifications/Rose.mp3 +SHA1-Digest: l9jmqMhdJymmIWlz0Cxv+UzLgAk= + +Name: system/framework/am.jar +SHA1-Digest: RuFCYnMyrosieGVuBpKjrbyf/LM= + +Name: system/lib/libmedia_native.so +SHA1-Digest: p09lfRLy/qM3aXb3KXsK2lus15g= + +Name: system/app/KeyChain.apk +SHA1-Digest: frVpXHZFKxla0aiCbXodnWTVcb8= + +Name: system/etc/security/cacerts/c33a80d4.0 +SHA1-Digest: rNpc82k59uWEFW5aGR7MLPbTGbI= + +Name: system/lib/librs_jni.so +SHA1-Digest: 1RR4mqRUuiRyRJpYsql9vEcsGko= + +Name: system/media/audio/ringtones/Blue.mp3 +SHA1-Digest: 3dd4USTc2lpmh9CmLN99R4/+ZcY= + +Name: system/media/audio/notifications/Cobalt.mp3 +SHA1-Digest: HdFILyI++GWExpNfvHJ4dP996rw= + +Name: system/etc/security/cacerts/bc3f2570.0 +SHA1-Digest: T0YolQvu92p5y+/IKRYPyfG1tQs= + +Name: system/bin/mm-qcamera-app +SHA1-Digest: R5uBJXvMGLtoboVGmHJAWng7gnw= + +Name: system/bin/asound +SHA1-Digest: tr1Lz3UjyOXEGicp6Ld0ePsKrK8= + +Name: system/lib/libwt6docxrdr.so +SHA1-Digest: FvkjkrqIWmngv7ca5nyaFw4ho+I= + +Name: system/lib/libdsutils.so +SHA1-Digest: JkQlzdBDWOlw4fE0kcOx3vGo3+c= + +Name: system/lib/libgetzip.so +SHA1-Digest: OYhw+CnZlkkMLB2QEhRCuvS9in0= + +Name: system/app/IMEXT9Lithuanian.apk +SHA1-Digest: M1kGJx6WWkybgPjjxKsBDyFVa3A= + +Name: system/lib/libmode10.so +SHA1-Digest: tgb/0mYrJsbmsM/DhdcdKyCYG8o= + +Name: system/media/weather/weather_l_fog_day.mp4 +SHA1-Digest: HQdXquqVt46a900WjDhjY4/cDmM= + +Name: system/lib/libsuspend.so +SHA1-Digest: /DJdOpz4VCTs+vgjoL4pmTk1J1A= + +Name: system/lib/libzeroeditorplayer.so +SHA1-Digest: axpPpMFqm0m3jb0mNUWi1ehEzUE= + +Name: system/bin/run-as +SHA1-Digest: hx9/aOVvMgtxG66iNmjlU1OfEWY= + +Name: system/app/NewsPlugin.apk +SHA1-Digest: taupwIVbRhPO7kZmquFpUKU93Gk= + +Name: system/etc/security/cacerts/73da149b.0 +SHA1-Digest: ZMH3aJsy2YBcWh1dq/Pq0xRGuAw= + +Name: system/customize/resource/rp_pct.png +SHA1-Digest: r1eCZ3sgAL2DZIG+nOjj9IVMwPQ= + +Name: system/customize/resource/rp_ce_0678_i.png +SHA1-Digest: QcdYwynqePRy5S+yjCqmjCBU+gA= + +Name: system/usr/srec/config/en.us/models/generic8_m.swimdl +SHA1-Digest: bFt0FGX1o+r+WlmE2dUzuoGlyao= + +Name: system/framework/svc.jar +SHA1-Digest: dzmluNqjY6rka7DAMjxykM//OQk= + +Name: system/fonts/DroidSerif-Italic.ttf +SHA1-Digest: vdiq1easVG0R5zeL36vqx8y9rfw= + +Name: system/framework/HTCDev.jar +SHA1-Digest: YJnljdIZS5DHAZczapMLR2kYgLg= + +Name: system/etc/calibration_EMEA +SHA1-Digest: 7baJRpUcgPwijs9O87vUJihnsO8= + +Name: system/etc/bluetooth/a2dp_avrcp.conf +SHA1-Digest: wJ3llWKQ+xtnKrQGf8GPwJRNJsI= + +Name: system/customize/resource/rp_ce_0682.png +SHA1-Digest: SR9O4zypMKzAhv4TE0rg1PRbtwI= + +Name: system/lib/libbluetooth.so +SHA1-Digest: C3923f3taBldsRGTlaWnwPMYUU0= + +Name: additions/fonts/sonysketchef/Roboto-Regular.ttf +SHA1-Digest: EMDAO+K2QAZphYvpq41fCdaYVzk= + +Name: system/etc/snd_soc_msm/snd_soc_msm +SHA1-Digest: o3bFCVwsteawrBQVy5QXfsAegWk= + +Name: system/customize/resource/quicklaunch_27205.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/d59297b8.0 +SHA1-Digest: EzYjzIwGO6iEh1Tk+7MTNXd/AaE= + +Name: system/lib/libqmi_csi.so +SHA1-Digest: rUUEJwiHfTrsjeqqKpyD4GCKFpI= + +Name: system/etc/permissions/android.hardware.wifi.direct.xml +SHA1-Digest: 26Zih/5IpKCLJgM/cg+lI9zxZ4Q= + +Name: system/media/audio/ringtones/Khaki.mp3 +SHA1-Digest: AjDFyx9+vDgzVdoFoD5fTBRM+lA= + +Name: system/app/HTC_IME.apk +SHA1-Digest: w47UWIC6ZXGBE3Qp2jZKaF3Gcdk= + +Name: META-INF/com/google/android/aroma/icons/agreement.png +SHA1-Digest: BLCgQbcevGAuuV0SxkEF+2IKpMM= + +Name: system/etc/security/cacerts/0e82f83a.0 +SHA1-Digest: 0ntDMr2qchEGTju9oHhfb1h53sw= + +Name: system/customize/resource/allapplication_26803.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/customize/resource/quicklaunch_65507.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/SettingsProvider.apk +SHA1-Digest: zScbEEsECUcpAtlTWlRBfogNVIY= + +Name: system/bin/wipe +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/tfa/fm_l.eq +SHA1-Digest: PM6hx2pEVi+SuZ9Ef8C0eIPB808= + +Name: system/media/audio/alarms/Cinnabar.mp3 +SHA1-Digest: HBt23TwCVLI6WqiPf92TxBK4DJs= + +Name: system/lib/libdmt_sse.so +SHA1-Digest: fqywsXgma0tT7ggXDocV+ETl+lo= + +Name: system/etc/security/cacerts/d537fba6.0 +SHA1-Digest: fpmK/UpGvaATZvclHSu6ryqfKbU= + +Name: system/app/HtcImageWallpaper.apk +SHA1-Digest: jSvsayHcmLqO7oYv/5wBofD0uhI= + +Name: system/usr/share/partials/partials_H_rr.csv +SHA1-Digest: Z9/32RI5ujeuYS0CQCyM3eJ0uKw= + +Name: system/lib/libmpl_jni.so +SHA1-Digest: TsofTQBH2CnLU3StUSwRKISUbMQ= + +Name: system/lib/libnativehelper.so +SHA1-Digest: 8ZvHOAFdkmzXXWPAQIxHBPCcMrQ= + +Name: system/customize/resource/allapplication_21401.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/netcfg +SHA1-Digest: /XE2tGorWihZb9UPh2t/r6dzMAk= + +Name: system/bin/hcheck +SHA1-Digest: 2QwrwUi0fys2KMUzXLDgMnCh5sk= + +Name: system/etc/security/cacerts/0d188d89.0 +SHA1-Digest: u89PgYhymechdBRRkE2kQEwXY/E= + +Name: system/app/IMEXT9Spanish.apk +SHA1-Digest: bsNk6NfNQsZNbwX+IXB5I1RFAvE= + +Name: system/etc/firmware/vidc_1080p.fw +SHA1-Digest: gqKcZYBg08EkYPnkeK+Enjp+HBY= + +Name: system/lib/libwt6xlsxrdr.so +SHA1-Digest: Lp6CqOuO1ZW/ZUu/re+oIZSSTWs= + +Name: system/etc/init.d/98permissions +SHA1-Digest: grvdXwEXHuuJS340Pl63cdMSWn0= + +Name: system/app/Picasa_GLRplugin.apk +SHA1-Digest: ltQ+brxccIr2E1RKharJ24WhG/o= + +Name: system/usr/idc/qwerty2.idc +SHA1-Digest: /k6dNiHz49smZosdSvGtSb0EYtA= + +Name: system/bin/efsks +SHA1-Digest: gBxjIEyjA/lbTF624YUo/kSJ6ZE= + +Name: system/etc/res_ctrl.conf +SHA1-Digest: KmRlUl4bp1NIL2Fhbmrv8paVah8= + +Name: system/bin/tune2fs +SHA1-Digest: 4/CV20c7VmLx3Z5JLuM4WsXanCU= + +Name: system/etc/libdvhwrc.so +SHA1-Digest: +EWukgBrL0RRdllVFHX2rBMwb2g= + +Name: system/lib/libaddrsdetection.so +SHA1-Digest: +0QElNcLXtVKeu7hOkgHMTktnxc= + +Name: system/media/audio/ringtones/Coral.mp3 +SHA1-Digest: RImr/WaHlGMCHMBMWRVGPXU8UQs= + +Name: system/etc/tfa/voip_l.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/lib/libchromatix_s5k6a2ya_hfr.so +SHA1-Digest: eNuiaeikRv9je/KlLoxga77mqnw= + +Name: system/lib/libwsp.so +SHA1-Digest: FdbsSRYW39nqDa0CoBWRfM8bVL0= + +Name: system/fonts/RobotoCondensed-Italic.ttf +SHA1-Digest: NKhBTHMcBPw7pwPS/BseTh6QXIY= + +Name: system/bin/renice +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/idlescreen_shortcut.apk +SHA1-Digest: pBFu9y0DZPUj/5sX8cc48KouQmI= + +Name: system/lib/soundfx/libsrsfx.so +SHA1-Digest: 2JKU/k68txIbvOJXUubdithIRnQ= + +Name: system/usr/srec/en-US/normalizer +SHA1-Digest: a+2nBo6Uy8cIhMZ4fRNuUxTriU4= + +Name: system/app/IMEXT9Hungarian.apk +SHA1-Digest: oZnZ0/IVAxZ+X8/SejxfEs7Q5hc= + +Name: system/app/SystemUI.apk +SHA1-Digest: IEwtDhlSXEkcAA8cKLYUOpF7hiU= + +Name: META-INF/com/google/android/aroma/themes/sense/theme.prop +SHA1-Digest: Yz5tb5g0tT9fChUum1jvE913gyE= + +Name: system/media/audio/notifications/Licorice.mp3 +SHA1-Digest: 5wA/j7AK7pDTYzBVIVmfAA5CUdY= + +Name: system/customize/resource/allapplication_20404.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libchromatix_imx135_hfr.so +SHA1-Digest: I1dk3hMidqp1cfg55Lfwk155bFg= + +Name: additions/fonts/veggieburger/Roboto-Italic.ttf +SHA1-Digest: Vhq5Pc0f7QDwQAeDuWWtQ4Jv6AQ= + +Name: system/media/audio/ringtones/Sapphire.mp3 +SHA1-Digest: JCkPpw/iOZTI/FppUwM3zmVuvxo= + +Name: system/bin/cat +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/framework/content.jar +SHA1-Digest: duOd+EdAcZpoGhB7w5AyARDLeu8= + +Name: system/etc/priorityd.sh +SHA1-Digest: C7jajOmGRwQmdPqt6X+JsE+0d7Y= + +Name: system/framework/com.google.android.media.effects.jar +SHA1-Digest: AUO08uWhTl7NmmwZGD07Ggg2bpU= + +Name: system/customize/resource/quicklaunch_22201.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: META-INF/com/google/android/aroma/themes/sense/select_push.9.png +SHA1-Digest: wvmedWe4h/6eEbWYDRhLYEuk70A= + +Name: system/lib/libacc.so +SHA1-Digest: rc420sUj7Jtzw5Rc8xhVHYLx3pw= + +Name: system/lib/libmorpho_image_stitcher3.so +SHA1-Digest: gHT+Fzrh6Jc9K36VCDEwSpILkiU= + +Name: system/framework/framework.jar +SHA1-Digest: UPiN80ttZtF3e4R9yUS8pOCXUNM= + +Name: system/etc/security/FotaSign_PubKey.der +SHA1-Digest: hpRUdVe1bjjhrmKbqvFBUk49wFk= + +Name: system/bin/mount +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libaricentomxplugin.so +SHA1-Digest: Zk3azoDxsqanCAb95Jf7ssxHgg8= + +Name: system/media/audio/ringtones/Neon.mp3 +SHA1-Digest: kuALt75+0iqM+0jOFia7gG8uKeI= + +Name: system/etc/security/cacerts/1dbdda5b.0 +SHA1-Digest: Pvfb+Mx0s9ZkvrdvSJCmchuTHpM= + +Name: system/lib/libexif_jni.so +SHA1-Digest: DTsfUp1mSPWTXKEx+zi9hJC3D3w= + +Name: system/customize/resource/wallpapers_c_02.jpg +SHA1-Digest: /UaU6oCe0Ragnxzcmf9hCsOyRxE= + +Name: system/etc/firmware/a225_pfp.fw +SHA1-Digest: e6QAN5YoXTbBJfq+RTtF1eIYUMw= + +Name: system/app/IdleScreen_Music.apk +SHA1-Digest: XvbDzjop40JdxREo3KGFwj1aZCc= + +Name: system/lib/libqdi.so +SHA1-Digest: yYHAQlouk6ZP0GWfUQkWmm6Ux7o= + +Name: system/bin/sync +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/gps.conf +SHA1-Digest: OgKe2mCQxfu/GvkoVtCoNjaJijA= + +Name: system/customize/resource/allapplication_21419.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/dalvikvm +SHA1-Digest: JrCBcdjQPnUVB33opNhr70q2iiE= + +Name: system/app/HtcRingtoneTrimmer.apk +SHA1-Digest: dZ5qYRdJCHDoPbPTW1A35UfHvyU= + +Name: system/etc/security/cacerts/75680d2e.0 +SHA1-Digest: xKfC4N5pEuEgXN2tZ44LcEXXY5s= + +Name: system/lib/libxml.so +SHA1-Digest: fot1OMClyO4qokS/HfMfLLc+sP4= + +Name: system/lib/libdivxdrmdecrypt.so +SHA1-Digest: oDqyznowMx/6Vyo7SGKN0DJ+7x0= + +Name: system/lib/libvideoeditor_videofilters.so +SHA1-Digest: IHrnJdoac+oL5tNTVC5fz2+81r8= + +Name: system/media/weather/weather_rain_night.mp4 +SHA1-Digest: I5L+abZ4jGUUDEd+KEjg7OXY67g= + +Name: system/customize/resource/quicklaunch_20210.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/libsnfc.so +SHA1-Digest: mwzgx2UqRssL863ZYTPm0oYdV3o= + +Name: system/lib/libmemalloc.so +SHA1-Digest: jpFojqzx4rSQFLr2tE4HqW9CH0I= + +Name: system/media/audio/notifications/Slate.mp3 +SHA1-Digest: xb+HoEobEEz3qfBegsUVJSxtsXI= + +Name: system/app/InputDevices.apk +SHA1-Digest: FUnvm84KB01PAOr1QEYxmnPyKCg= + +Name: system/app/HtcSyncWidget.apk +SHA1-Digest: 3gY8BrIZDuLh/PTtal0p78J0FAk= + +Name: system/fonts/DroidSerif-Bold.ttf +SHA1-Digest: KU+pnOr2B3q2M7Wnx9t2Hi92z4w= + +Name: additions/openvpn/xbin/openvpn +SHA1-Digest: 5v+Yuy7ZjRYGHtcqcmC/6ujs1zc= + +Name: system/usr/keylayout/keypad_8960.kl +SHA1-Digest: IIOk+zhgi7afHkxlyl82NdD77rY= + +Name: system/bin/mm-jps-enc-test +SHA1-Digest: mUaccGUCFe6x+/p9/ZOWKi3qaTA= + +Name: system/framework/bmgr.jar +SHA1-Digest: e/dXKGKrmgoAIPsRdm8QR2ZukX8= + +Name: system/lib/libchromatix_imx175_hfr.so +SHA1-Digest: D8LSrZQwnG6bEiMygZU6nS1mFB0= + +Name: system/customize/resource/quicklaunch_23407.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/7672ac4b.0 +SHA1-Digest: rVlRiFPQlGlMwhz5m6Ak2XDc2KM= + +Name: system/etc/security/cacerts/00673b5b.0 +SHA1-Digest: G5keTPZotrFLEINobTM5FTRYmLA= + +Name: system/etc/tfa/ring.eq +SHA1-Digest: PM6hx2pEVi+SuZ9Ef8C0eIPB808= + +Name: system/lib/libexif.so +SHA1-Digest: TouCCtku0jQ9vNm9HV4EbtCGtrQ= + +Name: system/bin/umount +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libwfdhdcpcp.so +SHA1-Digest: dGEtDG+yLuu1OMX71ZyPfn5Sqxg= + +Name: system/etc/security/cacerts/6e8bf996.0 +SHA1-Digest: p7GnxdBahRQFK6WFiKO8zA1I1FA= + +Name: system/lib/egl/libGLESv1_CM_adreno200.so +SHA1-Digest: cAZCFpvmAHYoao83wKupn26Mi+A= + +Name: system/etc/tfa/video_l.eq +SHA1-Digest: yVnitUPrXicZNKfZWIRmiKsUotA= + +Name: system/lib/libsoundpool.so +SHA1-Digest: 3C7cAST77VP8GhUWSvnIYpqu+4M= + +Name: system/media/audio/ui/Volume-4.flac +SHA1-Digest: P9cUKKRKCbyS9vHXNcNuuo2zpOY= + +Name: additions/fonts/roboto/Roboto-BoldItalic.ttf +SHA1-Digest: VYDbVJTNb2eL1eOY4SYWXg+P4PE= + +Name: system/etc/security/cacerts/5021a0a2.0 +SHA1-Digest: CI19Ue/cTwI484BmRLdR5TbCY7I= + +Name: system/bin/netmgrd +SHA1-Digest: o3T/3Uod1c4qw/kklD5+sbrEqg4= + +Name: system/etc/fallback_fonts.xml +SHA1-Digest: S5MUd49ldVxJTSz3bE/3gh3fGfo= + +Name: system/app/GoogleTTS.apk +SHA1-Digest: JsJQulafhOvc0/9D4kibYPkj7d8= + +Name: system/lib/libtilerenderer.so +SHA1-Digest: jPzbjr7YnyThaAbe2UY/snAABbM= + +Name: system/app/FDHttpd.apk +SHA1-Digest: inJe8LTXx1IBSnk+riZTJjjhxxU= + +Name: system/lib/qnet-plugin.so +SHA1-Digest: nvZKgsSuVO+Uth0Yy4KPSkIs2y0= + +Name: META-INF/com/google/android/aroma/icons/license.png +SHA1-Digest: Ne75iY0xgnD40gRcUCzOQh3q4/M= + +Name: system/etc/security/cacerts/9fae0770.0 +SHA1-Digest: LgctgBWI+ELcn1TUtd6wcus2h3I= + +Name: system/bin/make_ext4fs +SHA1-Digest: PePb8zRPRvKq4mEuBqiQJFqar0w= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/right_eye-y0-yi45-p0-pi45-r0-ri20.lg_32-2/full_model.bin +SHA1-Digest: AVjVyo3+d6RuT9gQEL1j2A4yQCA= + +Name: system/bin/rmdir +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/customize/resource/allapplication_21416.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/HtcSpeak_HFM.apk +SHA1-Digest: e9YgIqKlnN/ScgaEGZWqSQOT7nU= + +Name: system/etc/security/cacerts/bda4cc84.0 +SHA1-Digest: cfrYr6hqVNGZ0HN4nhlR9hRwrPg= + +Name: system/usr/srec/en-US/dictation.config +SHA1-Digest: zSaq9OS/+DTEJgF7GYk4324GoCo= + +Name: system/lib/libharfbuzz.so +SHA1-Digest: k9uxPG303FkzDi89qyK0/zUV6c8= + +Name: system/tts/lang_pico/fr-FR_ta.bin +SHA1-Digest: k5eoGN7uJD6gPoD62ErDAhLNV3k= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_sel.png +SHA1-Digest: n31tGc578dhSV8i3jfhdnSmQ0oM= + +Name: data/app/com.google.android.apps.translate-1.apk +SHA1-Digest: jkzaquApYqUHbOA58P/qWJHhu2Q= + +Name: system/etc/tfa/ring_l.eq +SHA1-Digest: PM6hx2pEVi+SuZ9Ef8C0eIPB808= + +Name: system/customize/resource/ConfigP.bin +SHA1-Digest: 7D+XC/yPY7DmScf5vTLbnji/ziY= + +Name: system/customize/resource/quicklaunch_24001.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/6adf0799.0 +SHA1-Digest: AdlddUEzDH/iR/px2uzU8RQlpxg= + +Name: system/bin/mpdecision +SHA1-Digest: 5dNSjaqjtC5fC59ELh3MAzqsW94= + +Name: system/framework/bouncycastle.jar +SHA1-Digest: DPnnUKOkEQzsMnB33VA9Wnzl1Sg= + +Name: system/lib/libctest.so +SHA1-Digest: 35NN9yTJRrBoPL09IBLd4iMpjfg= + +Name: system/lib/libwebrtc_audio_preprocessing.so +SHA1-Digest: ITe++q770lDJs4f5PekopdABhHc= + +Name: system/customize/resource/quicklaunch_24008.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/GoogleContactsSyncAdapter.apk +SHA1-Digest: Zwl6Wwpm6094Y/zeJm8wi+f5UQ4= + +Name: system/usr/srec/config/en.us/models/generic11_f.swimdl +SHA1-Digest: 5e8IIA7SPCk0zXso+yzwYfaIl4Q= + +Name: system/etc/security/cacerts/4fbd6bfa.0 +SHA1-Digest: n3+dvWbE0UcGOz9eUcbG8BT7IdU= + +Name: system/lib/libhtccamera_yushaniiproc.so +SHA1-Digest: vIPQ6qRoKl9A+owmk62YWdEdKvU= + +Name: META-INF/com/google/android/updater-script +SHA1-Digest: ixinSyWKgr33ZST6nH8NAfvTCdk= + +Name: system/etc/sound_mfg.txt +SHA1-Digest: q/uKM6MZpJZWI+bIpLWChCRtLU4= + +Name: system/lib/libchromatix_imx175_hdr.so +SHA1-Digest: 0XZLbtCR/18OS0lJ8r1PC+iftXg= + +Name: system/customize/resource/allapplication_20201.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libsnfc_ndef.so +SHA1-Digest: DYM7j3ais+je1juF6K95iIWClRI= + +Name: system/etc/tfa/playback.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/fonts/DroidSans.ttf +SHA1-Digest: Z9cynTXQb4TYTpzUSFMVfKk/tTc= + +Name: system/customize/resource/allapplication_28010.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: additions/gps/australia/etc/gps.conf +SHA1-Digest: nroBXNimUD4NF6JWtHpYHV0r8xE= + +Name: system/lib/libjUPnPCP.so +SHA1-Digest: vaopdM61+7qPkeer03WliwwX42o= + +Name: system/etc/image_beats_speaker.bin +SHA1-Digest: zlnEYty/dzXh9ohcIvRrpNP0s8I= + +Name: system/etc/security/KeyServer_PubKey.der +SHA1-Digest: U3W3nVoWgllu1mADcOUDQtRQa9s= + +Name: system/lib/libmmcamera_aec.so +SHA1-Digest: lmjrXRBXP1s+Fa5+CSMYF8SvEMs= + +Name: system/lib/libchromatix_s5k3h2yx_hdr.so +SHA1-Digest: bifkrneLL8rL+oDTjpzrhhhoNz0= + +Name: system/etc/security/cacerts/fde84897.0 +SHA1-Digest: iUIGZoxaUSmKyq84n5poAuNYHgg= + +Name: system/etc/firmware/leia_pm4_470.fw +SHA1-Digest: mTZLCv2U5JbMyDPKBCTdaFO5cdU= + +Name: system/customize/resource/quicklaunch_23801.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/zchgd/charging_00.rle +SHA1-Digest: RxWagAYJ9pk2xnZppBnwdNUpdxo= + +Name: system/framework/bu.jar +SHA1-Digest: z19B50fkFSf5eaptvZQw2tgzVfg= + +Name: system/app/HTCAlbum.apk +SHA1-Digest: 9h0TWDSkgk7l+ngKXTCKrBt1Fug= + +Name: system/app/Calendar.apk +SHA1-Digest: pQxSDQczKKgxq1PaF2Ywn3nDPec= + +Name: system/bin/fsck_msdos +SHA1-Digest: y5dF/aFpyChS/0urza6lpom2soQ= + +Name: system/etc/firmware/BCM4335A0_001.001.038.0015.0020.hcd +SHA1-Digest: vO8yCkln/F/B37QPZ5CiPu/unaA= + +Name: system/app/HtcFMRadioWidget.apk +SHA1-Digest: 4G0Poj5Y9Mi8silmomPPKvAIVCI= + +Name: system/app/HtcContacts.apk +SHA1-Digest: Gq0/+UJy38JrPgNKkHuSd9/rySI= + +Name: system/bin/drmserver +SHA1-Digest: U0x34YMoJTQjYSdqJB83v5wky7A= + +Name: system/lib/liboverlay.so +SHA1-Digest: 008Znk8mIA++m3pBL2bew+OrSWg= + +Name: system/etc/permissions/com.htc.fusion.fx.xml +SHA1-Digest: JPnWpxVThb8VsMttUQzLG2Qt+MY= + +Name: system/etc/security/cacerts/052e396b.0 +SHA1-Digest: 200jVgTclSNIhG4o7lvN+mFHZ6E= + +Name: system/customize/resource/rp_ac_with_nfc.png +SHA1-Digest: Stl55tSmRUa9B6xR4UGRf5Hcq/s= + +Name: system/lib/modules/moc_crypto.ko.sig.3.4.10 +SHA1-Digest: nYTXrUdepbvacQ7ESSHMPwBq4ng= + +Name: system/bin/e2fsck +SHA1-Digest: MQskU5DlqAgQJzuQLoc2x9tjSbg= + +Name: system/customize/resource/wallpapers_a_05.jpg +SHA1-Digest: S6qUDEgmc2ACGO3o9i8W9lIH3ls= + +Name: system/media/audio/ringtones/QuietlyBrilliant.mp3 +SHA1-Digest: CqKwkDHXpzqnDOReQ8mjHvjI3Ww= + +Name: system/lib/libvideochat_jni.so +SHA1-Digest: x9HVQGQWyTQJe9KKBgTqbBSjqwc= + +Name: system/usr/keychars/qwerty2.kcm +SHA1-Digest: qPZSGYC9afTwkRU3aCThctqnOdQ= + +Name: system/framework/apache-xml.jar +SHA1-Digest: 726UBIoXvriXHLpmGKCFUR+2ma0= + +Name: system/media/GPU/CurveCross.bmp +SHA1-Digest: 0jlE4XxN3GFh/6bgUnOXQFhqqCg= + +Name: system/lib/libGLESv2.so +SHA1-Digest: mcWW9B4AUh56ak8w1ok1fQ2uwMo= + +Name: system/usr/srec/en-US/lintrans_model +SHA1-Digest: ZES3OS6OKnK1lLKetEkUi+PgL4I= + +Name: system/media/audio/notifications/Jasper.mp3 +SHA1-Digest: DVCjzvDToL+qUcpgxJVQn8IZHK0= + +Name: additions/fonts/klavika/Roboto-BoldItalic.ttf +SHA1-Digest: Es6W1ntnwfUennlakydhCrk9COY= + +Name: system/build.prop +SHA1-Digest: w75xfXXoLMim+TsW7R8Wdr7AOIE= + +Name: system/lib/modules/moc_platform_mod.ko +SHA1-Digest: p5dbkTb7Q3GnrtCdFcmHjcyywjE= + +Name: system/app/TelephonyProvider.apk +SHA1-Digest: PZRVe81IyY08YDaBjaaHrhCvm8I= + +Name: system/bin/qmuxd +SHA1-Digest: EwS3kqJqQZIeV4fglBuKgeaH4x4= + +Name: system/lib/egl/libEGL_adreno200.so +SHA1-Digest: 5RIlj+9d9BZD3Pi1PiQ6+9eKRQk= + +Name: system/bin/debuggerd +SHA1-Digest: 4n0TUd4xCFZwldJ2rVrjEJR9ZLQ= + +Name: system/lib/libpng.so +SHA1-Digest: zUA1jH4ZH9rbImKG3M4f73EGatE= + +Name: META-INF/com/google/android/aroma/themes/sense/radio_on.png +SHA1-Digest: y06yW42n0e7ueDV5DVRx7odUtrw= + +Name: system/lib/libcorkscrew.so +SHA1-Digest: jega2j1r1/SvfkZgW1rjLV46Tik= + +Name: system/customize/AAInfo.txt +SHA1-Digest: pdhBxRntxO/v05VEMJHgJBOP5OY= + +Name: system/media/audio/ui/Volume-7.flac +SHA1-Digest: KyE0g7KRVX5Uf4680FmU7pqUA3E= + +Name: system/app/FMRadioService.apk +SHA1-Digest: tDhEJHl+yVKD6VGQDquYdlWRKco= + +Name: system/etc/security/cacerts/524d9b43.0 +SHA1-Digest: rOw80KrUjM6OhWVNkxN1dgNU2W4= + +Name: system/etc/security/cacerts/1eb37bdf.0 +SHA1-Digest: vHz58A2QzT7wd83T0nvUMdAkBps= + +Name: system/bin/logwrapper +SHA1-Digest: P81qhmlKrcTz4FE4vYncuFxFw+Y= + +Name: system/media/GPU/dot_mask_128x128.bmp +SHA1-Digest: GB5y4r0gtHy5zl9McUq/0s6I+pc= + +Name: data/app/com.koushikdutta.superuser-1.apk +SHA1-Digest: jwXPCa2WmEeom8wzvKuYb50H+wg= + +Name: system/etc/snd_soc_msm/snd_soc_msm_Sitar +SHA1-Digest: dI1aRl8EWe4XieDJ6ixXJaqLMHs= + +Name: system/lib/libRS.so +SHA1-Digest: CTTR86seXl6r8n4DexZ1BcGTNvo= + +Name: system/customize/resource/wallpapers_c_01.jpg +SHA1-Digest: PBukbupwv6CWRLPdpDTL+45P4cA= + +Name: system/etc/security/cacerts/455f1b52.0 +SHA1-Digest: IK/26zCMyRWnrIwW2qASL3px2sU= + +Name: system/etc/permissions/android.hardware.touchscreen.multitouch.j + azzhand.xml +SHA1-Digest: +3w9s8y7aS1ccCYaDZP65k5lMVM= + +Name: system/etc/security/cacerts/03e16f6c.0 +SHA1-Digest: joMfuOODTdwYLn+o/FBfOobAp90= + +Name: system/media/audio/notifications/Maize.mp3 +SHA1-Digest: 7Y3rDIFovmU3ISyo1L2syRQEmq0= + +Name: system/usr/srec/en-US/compile_grammar.config +SHA1-Digest: M9bLVAEUN3cV/AB6Ng0mW2ljUGg= + +Name: system/usr/keylayout/Generic.kl +SHA1-Digest: 2Bn3gvxfnE10qV2h0uMsTJ6IRwo= + +Name: system/lib/libaudioflinger.so +SHA1-Digest: WidozZNbCHHWr3TIMCqOdMVIe68= + +Name: system/media/GPU/mask_vignette_legacy.bmp +SHA1-Digest: sptkLNnJq1p64FZslLh7sDENx1Q= + +Name: system/customize/resource/quicklaunch_28020.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/usr/keylayout/dummy_keypad.kl +SHA1-Digest: PDYRL0v0BqshAyIbN0KSP7Ei4Qk= + +Name: system/bin/dbus-daemon +SHA1-Digest: vLCWtNQClOzRPIQsve+0gHAZAuk= + +Name: system/media/audio/ui/camera_click.ogg +SHA1-Digest: jet4ZWI3QDsJT8T3YoNr9gH1NUc= + +Name: system/lib/libstagefright_soft_aacenc.so +SHA1-Digest: IWMCawTf/vpkOobJ8/VH9wjR6og= + +Name: system/lib/libext2fs.so +SHA1-Digest: jZqcTyc3ejb5VSIIVB1iW8UtOS0= + +Name: system/lib/libllvm-a3xx.so +SHA1-Digest: WO6rJvPjmmha7yiXjCvH5e9clz0= + +Name: system/etc/tfa/tfa9887_l.patch +SHA1-Digest: Kd02luAPrgU9ys9kn6jt3QLZdqk= + +Name: system/app/SetupWizard.apk +SHA1-Digest: yYpqA4bYT0xyW35QSy71HL5X9rE= + +Name: system/app/HtcNotes.apk +SHA1-Digest: Of5RW11wB63HtuBSoMDFMgClW3E= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x_Fusion3 +SHA1-Digest: pMkCwM+W9M9vdC2O3Ac3sTzOwuc= + +Name: system/media/weather/weather_l_cloudy_day.mp4 +SHA1-Digest: bqSdABAAbdbnLYoj2nuYG9TSeoY= + +Name: system/customize/resource/wallpapers_b_01.jpg +SHA1-Digest: CYURrn521O+KKiLOTihLWcW608o= + +Name: system/app/Mail+nonprime.apk +SHA1-Digest: YsL/O92Lp+PIXnRDV4RPMOZJo/o= + +Name: system/etc/security/cacerts/cdaebb72.0 +SHA1-Digest: 9xXJaJxcsRt52ZKmLTb10lCP8fM= + +Name: system/usr/keylayout/Vendor_045e_Product_028e.kl +SHA1-Digest: BsTBZddUa0mpDkeAEr4ZC/V3iX8= + +Name: system/lib/libwt6docrdr.so +SHA1-Digest: 7coR/U9TJL1PcJ1aA494cKidvQQ= + +Name: system/customize/resource/quicklaunch_63102.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/modules/lcd.ko +SHA1-Digest: p2KD0JE9mSm14TUJMnLUyWm28TY= + +Name: system/etc/fallback_fonts-ja.xml +SHA1-Digest: hFw+wrKp3DC0jQjjI1j35jo7Lmc= + +Name: system/app/Automotive_Traffic.apk +SHA1-Digest: nM6tLvlAY8+lQQny3RLypLoz1yY= + +Name: system/etc/security/cacerts/dbc54cab.0 +SHA1-Digest: G7ilNysmUiKqjP0b0/CgdRCDdpE= + +Name: system/lib/libdefcontainer_jni.so +SHA1-Digest: UTtx60yLAvONe2tc2OMA79WMYyk= + +Name: system/bin/btld +SHA1-Digest: OffE5oP8VHmc1/0nC9HjaoRY+Ms= + +Name: system/etc/permissions/handheld_core_hardware.xml +SHA1-Digest: whHNJSrlPVXT63+1hEtHspIBsV0= + +Name: system/etc/image_htc_midtier.bin +SHA1-Digest: BQvgRVzmndETmB2zqTO7nDfu05c= + +Name: system/etc/tfa/ring.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/app/MyHTC.apk +SHA1-Digest: UOTbH+RhAvxYfUOH/n8R0Iim9eY= + +Name: system/app/CheckinProvider.apk +SHA1-Digest: OFAA6QUQgH5JM/DQXnSSpMPAeZ0= + +Name: system/customize/resource/quicklaunch_24801.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/framework/monkey.jar +SHA1-Digest: Kfe4Z7HMOx36ROXlGQaB8kQLAjU= + +Name: system/lib/libhtcflash.so +SHA1-Digest: icfl/z8ks/YUfItg1Xb9NTwHcJY= + +Name: system/fonts/DroidSerif-BoldItalic.ttf +SHA1-Digest: t/LTfDoGK+Zxd0/1L0/ZXL74E84= + +Name: system/lib/libwsp_jni.so +SHA1-Digest: 35uE8D9wGKJSjhnp3hDXjuryhJU= + +Name: system/etc/security/cacerts/5046c355.0 +SHA1-Digest: yq910Cd0R0uzSNpNm6fYzr5Q5Ho= + +Name: system/lib/libwivu.so +SHA1-Digest: JPKZ5bsWYjO31qs3MSIgIZkBngg= + +Name: system/bin/surfaceflinger +SHA1-Digest: Nzd11E5dNzy+pj8QMti9NjEYpnk= + +Name: system/lib/libcpt9core.so +SHA1-Digest: yQuLEK5jcxzCXisprspXorgsQw4= + +Name: system/etc/security/cacerts/ce1adacf.0 +SHA1-Digest: cIi2wLDmlyHctdMiDeeu/VF3g1c= + +Name: system/app/IdleScreen_No_lock_screen.apk +SHA1-Digest: 2Eg4YSmM0hGFdqXVReUt2SNCpSk= + +Name: system/bin/memlock +SHA1-Digest: gQy7+jwKorad5h5KhsY8HB8Sk0s= + +Name: system/etc/security/cacerts/11f154d6.0 +SHA1-Digest: zkNyiWna542K/kWuC7wUAMTPM0Y= + +Name: system/etc/security/cacerts/5a5372fc.0 +SHA1-Digest: lRZnSCW+h2OrdLdhSE/61v9FF5g= + +Name: system/etc/security/cacerts/9685a493.0 +SHA1-Digest: kaSX6pI0rQB+TDbRWSlOP44RXUE= + +Name: system/media/GPU/dot_mask_2.bmp +SHA1-Digest: sjcQcSVjA2XM1TxpkSbHjsxbDF8= + +Name: system/etc/tfa/recorder_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: additions/fonts/comicsans/Roboto-Bold.ttf +SHA1-Digest: 1vu6g8g0wpPV9wtnDqmeZv/44CA= + +Name: system/media/zchgd/batt_95.rle +SHA1-Digest: 4MVAx4a7RzDHup8UZBR1bxcMMwo= + +Name: system/app/IMEXT9English.apk +SHA1-Digest: Lt9vqMB+TDpKWAfTKsT7tsk/3Nk= + +Name: system/lib/libwt6epprndrv.so +SHA1-Digest: DivO8hstWF82Qz59KZqcfPbdIKc= + +Name: system/etc/tfa/ring_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/lib/libdsprofile.so +SHA1-Digest: sA2FesTFJAf4f67bqF9IhYSXKFw= + +Name: system/etc/tfa/recorder_l.eq +SHA1-Digest: yVnitUPrXicZNKfZWIRmiKsUotA= + +Name: system/lib/libDxDrmJava.so +SHA1-Digest: QyPndMGblkKvHV4OZ5E6s/7JBto= + +Name: system/media/audio/ringtones/Emerald.mp3 +SHA1-Digest: Gh51VoohEE1bdGYLkq7bbQhGQh8= + +Name: system/customize/resource/allapplication_28001.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/chiaddict.dat +SHA1-Digest: 85pAZ/jBIMhVFp3HKNeiyVE5WqQ= + +Name: system/bin/netd +SHA1-Digest: KxsVClbuTlqxb6fe7d517VQiVQI= + +Name: system/etc/image_gec_2vol.bin +SHA1-Digest: c3h5EiPq0vgBG4R2HBL/c17QSxs= + +Name: system/etc/htcfs.conf +SHA1-Digest: HeXpVVeMwj4YPEiLlsiwMzjYJ40= + +Name: system/media/weather/weather_rain_day.mp4 +SHA1-Digest: KEfSq7YK0eJH3C9m+mAstKK0HXE= + +Name: system/etc/security/cacerts/d64f06f3.0 +SHA1-Digest: 0RWeUYy8yvPc5W09WdfTXhlSn7A= + +Name: system/bin/schedtest +SHA1-Digest: 60DcaKewo7d7KqtxIJppcZ12FEU= + +Name: system/app/CertInstaller.apk +SHA1-Digest: VjxzxabP+8M0I+Eqany0AIcshF8= + +Name: system/usr/srec/en-US/grammar.config +SHA1-Digest: +twRBfiA7IzTU1sLmK3tG316qUM= + +Name: system/media/weather/weather_l_cloudy_night.mp4 +SHA1-Digest: yJ+y0IAMkSi2f8BCptEigyJbsJI= + +Name: system/app/Liveretouch.apk +SHA1-Digest: llzVpH+/tc22GSBAcP5t/Qi9otI= + +Name: system/media/audio/ringtones/Grey.mp3 +SHA1-Digest: 1DWo0fvo6VSyRSgFr+xWeQbyboY= + +Name: system/etc/security/cacerts/d2adc77d.0 +SHA1-Digest: ubLdIu8HnKW70iqEOAjEVa0wb7E= + +Name: system/app/CustomizationSettingsProvider.apk +SHA1-Digest: LJTL72fe4gTO2NWhVoVTbRKkAWQ= + +Name: system/lib/libstagefright_soft_flacenc.so +SHA1-Digest: RmB9eqtlD3N94l4pvj7iU5j/JJc= + +Name: system/lib/libfilterpack_facedetect.so +SHA1-Digest: kduWGk1cz2zwFnv/PqJejadfrKw= + +Name: system/media/audio/ringtones/Ultramarine.mp3 +SHA1-Digest: z+I1piLy0ys8STWPjHa+DmneuQ0= + +Name: system/lib/libmmstillomx.so +SHA1-Digest: NIqu8AWrgVpUz/RQ9MYaZmRGPgQ= + +Name: system/app/NetworkLocation.apk +SHA1-Digest: OEv5L2BDvqj0WX/OwQ8SC6YM21Q= + +Name: system/lib/libgsl.so +SHA1-Digest: A5oLBdLBAeOvTswhqi1BzCjXsm4= + +Name: system/etc/tfa/voip.preset +SHA1-Digest: OVBiITpEEwnpRzjGcCTdTkgmGA4= + +Name: system/etc/image_gec.bin +SHA1-Digest: f997e72Hw94tjKgYBxm0sr48UZI= + +Name: system/app/FM_Radio.apk +SHA1-Digest: 8NASxviuaV2bb6E+yG2h34toPL4= + +Name: system/lib/libmmwfdsrcinterface.so +SHA1-Digest: oLubjM57VO/TbHmXey26hXnZbfI= + +Name: system/usr/srec/en-US/acoustic_model +SHA1-Digest: cfkvAc/HaQ1I8nrAw+GLdvrr2oc= + +Name: system/lib/libusbnetjni.so +SHA1-Digest: OWohQT0SsuwTVMciPvGBLwcVADM= + +Name: system/bin/v4l2-qcamera-app +SHA1-Digest: 7gvTDFVnEd/QJRifDhFg3kw2opY= + +Name: system/lib/libswapheap.so +SHA1-Digest: uSBGNOr/JuRG9ZOuwn3fKXiLT20= + +Name: system/lib/libwfdrtsp.so +SHA1-Digest: IwSZFYZlRJswU0oz0TlEGAmbVyw= + +Name: system/bin/atrace +SHA1-Digest: oAIPhNcMnmoHb03JNVsbPuc9Wr0= + +Name: system/bin/mm-qcamera-daemon +SHA1-Digest: Evh8sDNPO2l51znGMPbwgiiWZpY= + +Name: system/etc/permissions/android.software.live_wallpaper.xml +SHA1-Digest: XSE9c962K3wJVmHaaJ4PglJg9iQ= + +Name: system/fonts/DroidSansArmenian.ttf +SHA1-Digest: lC+raRjA3Jv1n2KrFeP9OHNrvo0= + +Name: system/bin/mediaserver +SHA1-Digest: 9F9xOzk836QYl9R4E2VPO3o/5C8= + +Name: system/media/zchgd/batt_0.rle +SHA1-Digest: pxzRkTs4X+F5+2a0W+ThQYarA0Q= + +Name: system/etc/security/cacerts/57692373.0 +SHA1-Digest: cxktqBsx3bsf1do5QynEaxTvX64= + +Name: system/app/HtcProfilesWidget.apk +SHA1-Digest: yVBE3tM3KlvzBjwcm9mxyHCHaFE= + +Name: system/lib/libandroidfw.so +SHA1-Digest: jd2DLIwwIjNnzdrHwlbPbJoWZl0= + +Name: system/lib/libjpeg.so +SHA1-Digest: T3UJ41FfePmAwYh1MWsUEUZuTbU= + +Name: system/media/audio/ringtones/Tangerine.mp3 +SHA1-Digest: tVkPUTi2D7rUXdNF8LpviMe3Nwc= + +Name: system/lib/modules/msm-buspm-dev.ko +SHA1-Digest: Cw7O74pnvnOM2O+NgSdhQN+tbYY= + +Name: additions/fonts/comfortaa/Roboto-Regular.ttf +SHA1-Digest: 2p1tyuEu2DmaDtDgX8hfYUUU6iI= + +Name: system/lib/libdumppcm.so +SHA1-Digest: Bpe+qsMbPkq04Xq53iNUXiGWSq4= + +Name: system/etc/tfa/voice.config +SHA1-Digest: HKUbwkwyeWNkWCWTnAgcEbOJbpQ= + +Name: system/etc/tfa/recorder.eq +SHA1-Digest: yVnitUPrXicZNKfZWIRmiKsUotA= + +Name: system/media/audio/alarms/Taupe.mp3 +SHA1-Digest: x7HaNTdM9IGZhZMXtELhkknxjBI= + +Name: system/lib/libwt6bjprndrv.so +SHA1-Digest: tKKavt5fW8gzEf3YeVyrfH5DY6A= + +Name: system/etc/security/cacerts/7a819ef2.0 +SHA1-Digest: sPFvH0vDqnbyji1Ydpg3E5Jsph8= + +Name: system/framework/com.dropboxpartner.jar +SHA1-Digest: 49iathKtlRnATkLFBV+ykocqG3I= + +Name: system/lib/libchromatix_imx175_default_video.so +SHA1-Digest: ApWU1yreGwFXecrytZ06LkIYqCQ= + +Name: data/app/com.google.android.apps.maps-1.apk +SHA1-Digest: 2BwczxCxJPaUJQ+QJa1xqCcFva8= + +Name: system/etc/init.qcom.bt.sh +SHA1-Digest: kVjq1GcV+qMGYnbUSp9GrvhraA4= + +Name: system/lib/libext2_uuid.so +SHA1-Digest: 4CnYPTuKmsCDazcosPEwBoTlhvA= + +Name: system/fonts/AndroidEmoji.ttf +SHA1-Digest: ZBbXr5sxLSyugwpq55Z15ajrX84= + +Name: system/fonts/ucsh00d_c.ttf +SHA1-Digest: HVQrSni9pygKOOT38dwxiXhQP8Q= + +Name: system/etc/thermald_boot.conf +SHA1-Digest: 78zY9hqxtRpnnI/IRdSh5LNog3I= + +Name: META-INF/com/google/android/aroma/themes/sense/radio.png +SHA1-Digest: 1wbvEt+0D4I0q/rFu1t19w4Gqow= + +Name: system/etc/security/cacerts/8ccb5f6d.0 +SHA1-Digest: RiH8pECN67dnw5z0r+NP3XM5Lw0= + +Name: system/framework/com.htc.android.bluetooth.le.jar +SHA1-Digest: 0rpN6wUBYRo25q0EzGGKwaqEV/Q= + +Name: system/app/IMEXT9Hebrew.apk +SHA1-Digest: KYshzfQSG8csCAFqTJ6e3P9yjfg= + +Name: system/vendor/tmo_cm/demoutil +SHA1-Digest: FGie6hvQPvklcsleJVa1/DCcdyQ= + +Name: system/lib/libtzsrv.so +SHA1-Digest: va4N5zf2EKkqtxmNDmxc4tE9v7k= + +Name: system/media/weather/weather_l_partly_sunny.mp4 +SHA1-Digest: HRDmwgjrIkn08jW1GVmcK3YZ5og= + +Name: system/usr/share/partials/partials_CW.dat +SHA1-Digest: QM66QXBaDtvPMgoYA6Us3ARHjfQ= + +Name: system/customize/resource/allapplication_26003.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/tfa/deftcoefA_l.speaker +SHA1-Digest: SKR62eVqVHRTCir6cWJ9OE2ezUo= + +Name: system/vendor/lib/libWVStreamControlAPI_L1.so +SHA1-Digest: BB1gSObJzUFhIrVZMBes4e/V+2o= + +Name: system/usr/srec/config/en.us/models/generic11.lda +SHA1-Digest: /y/sXjBSqRQkFc848OCkAh9PhTE= + +Name: system/etc/firmware/hcheck.mdt +SHA1-Digest: kpgwhIcZ5cfbiZZ3c/LDaCiDvLA= + +Name: system/app/Camera.apk +SHA1-Digest: vJzwJD/1BPe390OxazKGU+N60DI= + +Name: META-INF/com/google/android/aroma/scripts/restore.sh +SHA1-Digest: vRdoYWSdDNGNVXs2dq0E2HZOuDk= + +Name: system/app/HtcResetNotify.apk +SHA1-Digest: mQeLikCqCW9ZBXpoIo0QazwoTK8= + +Name: system/lib/liboma-drm1-fs.so +SHA1-Digest: 4ov3R6J9WJz6w+vybFX93XoCa78= + +Name: system/etc/tfa/playbackbeats_l.eq +SHA1-Digest: GRbTA4TG5srGNohUHz6/IXX9Ffo= + +Name: system/media/GPU/dot_mask_1.bmp +SHA1-Digest: Wax3umuK2HuUtQBi6arUPTP2WPc= + +Name: system/etc/permissions/com.android.nfc_extras.xml +SHA1-Digest: ZvocFvtXygXFd7nw2Ja+V7G7PR4= + +Name: system/etc/permissions/com.google.widevine.software.drm.xml +SHA1-Digest: Gggf4BO2xlvJgH9ml/1pz/WZTAE= + +Name: system/lib/liblog.so +SHA1-Digest: +gHvJkV1p5Y18EfkwxHDSWDrKhk= + +Name: system/vendor/lib/drm/libdrmwvmplugin.so +SHA1-Digest: Ebyulhu+DJrZwZGv4+uC182OV4I= + +Name: system/etc/tfa/video.eq +SHA1-Digest: yVnitUPrXicZNKfZWIRmiKsUotA= + +Name: system/media/audio/alarms/Metal.mp3 +SHA1-Digest: fpZhnFeMMo3VpXTZUSpYDd3zFcc= + +Name: system/etc/firmware/BCM4335B0_002.001.006.0042.0044.hcd +SHA1-Digest: spwgfp+HFxE7G1LAMC/wM90T+FY= + +Name: system/etc/tfa/tfa9887_l.speaker +SHA1-Digest: sw/pJtd7xyhONVoxqf9knMu5s/c= + +Name: system/etc/tfa/voip_l.preset +SHA1-Digest: OVBiITpEEwnpRzjGcCTdTkgmGA4= + +Name: system/customize/resource/quicklaunch_21910.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/DeviceManagement.apk +SHA1-Digest: I4VtjQHhZJTxdTNj8rAFMlNm/1g= + +Name: system/framework/framework2.jar +SHA1-Digest: 66IZBoOGdnGAkiijrTM3SMV1Nlg= + +Name: system/lib/modules/qcrypto.ko +SHA1-Digest: Ni5oyZEvvjgQFlTJYfyGArIs8Ic= + +Name: system/bin/iptables +SHA1-Digest: 2Yp8m4EFPry2awwZt5aBBjaFd1c= + +Name: system/lib/libchromatix_ov5693_default_video.so +SHA1-Digest: rm/zEvmmaXZu39ipCPXvZOuBneM= + +Name: system/lib/libchromatix_imx135_hdr.so +SHA1-Digest: CuXA/vJ+5WBphZamfxsAXvNUYDk= + +Name: system/lib/libmmcamera_frameproc.so +SHA1-Digest: 3fbV7O/u6K1FwBRF0UElF/qJ0ZM= + +Name: system/etc/security/cacerts/bdacca6f.0 +SHA1-Digest: 6zbSCMgMZa9LslRYITBh6DFKQSY= + +Name: system/lib/libdrmtime.so +SHA1-Digest: R+VHrLTTgQOITEhkOAlveQlq4R4= + +Name: system/lib/libmorpho_frame_overlay.so +SHA1-Digest: mwItnbN3XLYfV0ttYAM1S9BNbSg= + +Name: system/media/audio/notifications/Ivory.mp3 +SHA1-Digest: dGvQgq+o4pPceW5wXEkw3ASWqBY= + +Name: system/app/HtcSettingsProvider.apk +SHA1-Digest: LgFmDJVDNdAx7R0wUvgJ1hFKk7Y= + +Name: system/lib/libwt6pdfrdr.so +SHA1-Digest: zD6aYZT9jbZHjUT6yLKAh42np7Q= + +Name: system/etc/tfa/ring.preset +SHA1-Digest: gFz2Zw5riOxrVU5rGDqqz6MwXYI= + +Name: system/lib/libchromatix_s5k6a1gx_hdr.so +SHA1-Digest: PNAC3Y4r+OTMVGl1NQK3qKv1tAA= + +Name: system/lib/libgccdemangle.so +SHA1-Digest: w5+dUn8Aeb8vEnHRG0w7Vircp0o= + +Name: system/app/IMEXT9Croatian.apk +SHA1-Digest: SBiV8dxn1oonNaGzuXbSaDY4SvY= + +Name: system/etc/pnp.xml +SHA1-Digest: VAdO916JdGgtDk88gLxBHlcy1fw= + +Name: system/app/HtcAlbumMapView.apk +SHA1-Digest: jRomM3zEV34PkSib+onlOG2G6Ug= + +Name: system/app/IMEXT9Kazakh.apk +SHA1-Digest: HbrImUPCYO6yr5HldiscOCbMEV4= + +Name: system/app/COTAClient.apk +SHA1-Digest: x9ha/w3v1RWfFe/Y/MGDE8UdhnM= + +Name: system/etc/firmware/a225_pm4.fw +SHA1-Digest: h9byfKCLUhzDNh9j8GMaH+8kA6w= + +Name: system/app/DownloadProviderUi.apk +SHA1-Digest: 0B0Kr6sXMMvReo+nWVJ83Zo45xQ= + +Name: system/etc/security/cacerts/d78a75c7.0 +SHA1-Digest: jRLGGp/ersc4b9xR3gfIJpalIK0= + +Name: system/media/audio/ui/Effect_Tick.ogg +SHA1-Digest: jdIBk/wZcXKAuBBFS0XV0YpPWNw= + +Name: system/media/weather/weather_l_snow_day.mp4 +SHA1-Digest: UEAete7q4zTgaOmLqJZIF/ThM6E= + +Name: system/lib/libdrmfs.so +SHA1-Digest: UijPliPLfknHZbBFsiOcWgzBuV8= + +Name: system/etc/security/cacerts/86212b19.0 +SHA1-Digest: z5oVrRiZngoDfKl6smrTYg59YWM= + +Name: system/lib/libstagefright_soft_aacdec1.so +SHA1-Digest: d6trVJMYtBd71+BqS1tzytrmBwc= + +Name: system/customize/resource/wallpapers_c_03.jpg +SHA1-Digest: aYZVl15XqVYu7uGhLnCtaznrYck= + +Name: system/lib/libmorpho_image_transform.so +SHA1-Digest: b98BD4Y8WRNobNTHfFX2+vMvhPw= + +Name: additions/openvpn/xbin/bb/placeholder +SHA1-Digest: 2jmj7l5rSw0yVb/vlWAYkK/YBwk= + +Name: system/lib/libfuse.so +SHA1-Digest: 1bnxYpVPN31kddW9VwMkK10tdjk= + +Name: system/etc/tfa/voice.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/etc/wfdconfig.xml +SHA1-Digest: WtcnhaAVQR0lKxzsfzuX1x51g+Y= + +Name: system/bin/getevent +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/tts/lang_pico/it-IT_cm0_sg.bin +SHA1-Digest: z7Ft7pwEG46mPScafCDOoqZt8HE= + +Name: system/lib/modules/ansi_cprng.ko +SHA1-Digest: rXVXGV2Ia4PsLRJYyQLOQ9iDyNo= + +Name: system/bin/diag_uart_log +SHA1-Digest: 19q3MUyJ8TtQ65AOR35CNDfsW2M= + +Name: system/bin/pppd +SHA1-Digest: 5VzcXeD3kOye440tK3zSIcmwV5E= + +Name: system/lib/libbeatscorehtc.so +SHA1-Digest: 0Fas1vcZaoWEEQK4fD1wKkG3DF4= + +Name: system/lib/libchromatix_s5k6a2ya_hdr.so +SHA1-Digest: dMjTlkTv8rJxhfuDffKTerLqXrM= + +Name: system/lib/modules/qce40.ko +SHA1-Digest: F2VksRKR7IGkaYYQGepHRA9zQFQ= + +Name: system/lib/soundfx/libvisualizer.so +SHA1-Digest: yLn/2BuFnHJdK5j5MBnl//hvqYU= + +Name: system/lib/libqdcbutils.so +SHA1-Digest: X0qjs+57Xnw9Xt3gB52F2Ij4tDE= + +Name: system/framework/com.android.future.usb.accessory.jar +SHA1-Digest: +cUBlanPKJOyUNPWTeuauMgH9lI= + +Name: system/app/Message+Nonprime.apk +SHA1-Digest: INL8ZGLvnTsZDnGT3oOHliFs7rc= + +Name: system/customize/resource/allapplication_21407.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libiculx.so +SHA1-Digest: TFeAc/ZJL9fyAHMgutH6ZsaPhDo= + +Name: system/lib/libmode10fx.so +SHA1-Digest: l4GwEMvWuivktE6foJU1va6p7mE= + +Name: system/lib/modules/evbug.ko +SHA1-Digest: +XH+Oxrhtq97b0wjwVLvYV5ynus= + +Name: system/app/HtcMediaCacheService.apk +SHA1-Digest: avJjdnSTlCyiY4CKak1ToOUJCmg= + +Name: system/bin/installd +SHA1-Digest: acEr58yRetZ7tN0f3ZDjQdmLQoU= + +Name: system/usr/keychars/qwerty.kcm +SHA1-Digest: TsWF0/tutWtAi0whFMCQCDu+uZg= + +Name: system/etc/permissions/android.software.sip.xml +SHA1-Digest: 1GKUjmqd+/qTc9Ke8c+RbW3a1jk= + +Name: system/etc/security/cwcerts.zip +SHA1-Digest: xNqzvX4C4xGsQrVMWIVxm4z/8yA= + +Name: system/media/mms/atis_tia_cmas_alert.mp3 +SHA1-Digest: LssUZvBfcn9LUQMvsj+RnvVGa/8= + +Name: system/framework/com.htc.lockscreen.fusion.jar +SHA1-Digest: 8GnpugUMNUA8XYBFMI+DVbiULEI= + +Name: system/lib/plugins/com.adobe.flashplayer/libstagefright_honeycom + b.so +SHA1-Digest: uWjsCs50ibuut/XTIp3J94p4HSo= + +Name: system/customize/resource/rp_ce_0700.png +SHA1-Digest: Nlz8m5UiVPcOs8ynWRYzBgWMqx8= + +Name: system/lib/libjDTCPServer.so +SHA1-Digest: YsvrOx6D/ipBSmuknx2QcEIoiNQ= + +Name: system/customize/resource/quicklaunch_20601.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/bin/cmp +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libNEONImage.so +SHA1-Digest: 3IKqQsrcobW6FSodXVwVffdAins= + +Name: system/bin/insmod +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libchromatix_s5k6a1gx_hfr.so +SHA1-Digest: bZqm1iwAYfwvIuNDjcAQJw3zzJo= + +Name: system/usr/srec/en-US/endpointer_voicesearch.config +SHA1-Digest: nhkSWehXFaaI7ycDX+V9HMkl0m0= + +Name: system/lib/libjni_fe.so +SHA1-Digest: hlQUpmjshanl1eBgH1uQPO34jrs= + +Name: system/lib/libopencv_java.so +SHA1-Digest: nenUMgD0CwQmI5BNr6SMneu/gu4= + +Name: system/app/HomePersonalize.apk +SHA1-Digest: rdBD2DqXz7VziiG12H0ZHlUBELA= + +Name: system/lib/hw/gps.default.so +SHA1-Digest: Z0OioAf19Krb6KN/U+YjH4mPNmc= + +Name: system/etc/security/cacerts/b0f3e76e.0 +SHA1-Digest: Xyiw528S3pbKQvg1OVh6hyfYS8k= + +Name: system/usr/share/partials/partials_A.dat +SHA1-Digest: xZzfW8IVOK8KFwWXGOEUbHuh69M= + +Name: system/lib/modules/dm-crypt.ko +SHA1-Digest: Df4JmM94KLbR7HrMKtyEi4+J4PE= + +Name: additions/screenshot/screenshot.sh +SHA1-Digest: +ZWG4bOr+IAoYljI+NgPyrB1M08= + +Name: system/lib/libmlplatform.so +SHA1-Digest: Ft84I4vZerg+XlJxK0jExyWz9Yw= + +Name: system/media/zchgd/batt_10.rle +SHA1-Digest: hH7rhOpOgTqVZLwooLGMDXkoYWc= + +Name: system/customize/resource/allapplication_20205.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/usr/keylayout/Vendor_054c_Product_0268.kl +SHA1-Digest: AHzPYrfjA0QHSpO6s67YfBjJQZU= + +Name: system/lib/libgnmc_fpx.2.5.9.4.so +SHA1-Digest: 8ez4St4BoPHoMjScZ4SQBuFis1w= + +Name: system/lib/libgenlock.so +SHA1-Digest: J0pjn4zMVKj+ocwUtRBeqyH3Bmw= + +Name: system/app/HtcMobileNetworkWidget.apk +SHA1-Digest: +Ztrbac+ub6/EeN9qIerLQxeDdU= + +Name: system/etc/init.d/99complete +SHA1-Digest: CnRVb2+/yVfPYZCj8AG5fWjPmNk= + +Name: system/fonts/DroidSansFallback-htc.ttf +SHA1-Digest: DWwjun5t3d3PeHfrFs8/TYTdXRE= + +Name: system/bin/rild +SHA1-Digest: HB9YpIJkGb9cj1PP0AcGwtmzJW4= + +Name: system/bin/logcat2 +SHA1-Digest: 6TafioEigwWHrC6otd7YlLJCRNo= + +Name: system/lib/libhtc_rilhook.so +SHA1-Digest: l7WnlLGKg7vN2zTtW7VkdVGThEY= + +Name: system/etc/wifi/wpa_supplicant.conf +SHA1-Digest: gnijNFdlV/VI2tMxz7KcnFewPuA= + +Name: system/customize/resource/allapplication_26806.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/xbin/bttest +SHA1-Digest: 6+BO9zoiX5X2O4tniaMMIBh9MsM= + +Name: system/lib/libiprouteutil.so +SHA1-Digest: ZRcT8RXBzbFs5MPoU77lxybGXvo= + +Name: system/customize/resource/allapplication_22201.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/PureC_PackageInstaller.apk +SHA1-Digest: 1lN/ofD+V/G3//ApYVGO3YWWXSk= + +Name: additions/camera_4.2/app/GmsCore.apk +SHA1-Digest: q6CT0jzv1Ror8dZprbIhyBRvQFg= + +Name: system/fonts/DroidSansTamil-Regular.ttf +SHA1-Digest: /e/ks+E8syMC6xadn01QJRV6mwg= + +Name: system/usr/srec/config/en.us/grammars/boolean.g2g +SHA1-Digest: Y6aiso1+39wx/fFSodB1MOdR7GQ= + +Name: system/lib/libzeroeditor_osal.so +SHA1-Digest: S5KHswnBrw9QL2q+NK6qxf2whbQ= + +Name: system/media/weather/weather_fog_day.mp4 +SHA1-Digest: zvAggeABRU3wx0RdwiJam2W9gSY= + +Name: system/lib/libmorpho_image_converter.so +SHA1-Digest: sDD/ahc6gG/2mzwp0mh34BW2opk= + +Name: system/fonts/DroidKufi-Regular.ttf +SHA1-Digest: 8qblYJhDwV7V6UscEs+VrSPgqjY= + +Name: system/etc/fallback_fonts-HTC__J15.xml +SHA1-Digest: wwDIFQFgqxmpCQXnggRhsY7lwRI= + +Name: system/lib/libhtcdrm1.so +SHA1-Digest: IxQj0Pm3qbjElIIwy2HELUNDN0c= + +Name: system/usr/keylayout/Vendor_046d_Product_c299.kl +SHA1-Digest: wIcNdtms/WYTXXig4lG68oFo/4A= + +Name: system/customize/resource/allapplication_28020.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/customize/resource/wallpapers_a_07.jpg +SHA1-Digest: QISjVTiPyhffZCfj0ZfoxpcWO/4= + +Name: system/lib/libimage-jpeg-enc-omx-comp.so +SHA1-Digest: 7LhOjPtOchiJsoHRIAehb2NU3bw= + +Name: system/lib/libmediaplayerservice.so +SHA1-Digest: BqAjujCtAEHP9YFdwxGBqkUyPQQ= + +Name: system/etc/security/cacerts/6b3f8240.0 +SHA1-Digest: 8bN1lqw6g87ShwSbO699nOS1KMM= + +Name: system/bin/log +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libsensorservice.so +SHA1-Digest: WGlSJx+uffDfyAll4kyILRYxfwc= + +Name: system/lib/libEGL.so +SHA1-Digest: HHq4wVnpdEk86yEoCARLjxZgjHM= + +Name: system/bin/hdmid +SHA1-Digest: +OwNWh2+4yyDvwYUlO1Elc6Q56U= + +Name: system/app/HtcHotspotWidget.apk +SHA1-Digest: hEkQk8aUV1jsrMzVPwDOTzPRe4Y= + +Name: system/lib/libt9.so +SHA1-Digest: ritqzaUaR88WsC/Aug2jeMsAoEE= + +Name: system/bin/dexopt +SHA1-Digest: bBBbMZ16oQHZiTqgH9q/1k1gW5w= + +Name: additions/fonts/helveticaneue/Roboto-BoldItalic.ttf +SHA1-Digest: hrfo9+REAhOTrclAM/0Q2aDTPtw= + +Name: system/media/zchgd/charging_06.rle +SHA1-Digest: 5sXmisNHh+5iyc5fMW1QUefvkHw= + +Name: system/app/PrivInit.apk +SHA1-Digest: tmlPsM+O/Th5a5pEuM1m7UsJy1I= + +Name: system/etc/firmware/vidcfw.elf +SHA1-Digest: Mx4rvApSUBdci9CXVoQAtIaY1jQ= + +Name: system/etc/init.post_boot.sh +SHA1-Digest: PETLFfEv+49NzIYR4JpnwJMJJZc= + +Name: data/app/com.adobe.reader-1.apk +SHA1-Digest: BqQn/+RpyR3gfjEouL+FSrIbvUw= + +Name: system/customize/resource/rp_ce_0560_i.png +SHA1-Digest: ficP8So1xl78fsNO60wU7+CobCM= + +Name: system/customize/resource/allapplication_20601.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/tfa/tfa9887.speaker +SHA1-Digest: dDOaM5M/giSViXya0furAKBJ2nk= + +Name: system/app/CustomAppInstaller.apk +SHA1-Digest: UBxJOh3N5RObX6pTLFsT5lGtX5Q= + +Name: system/app/IMEXT9Romanian.apk +SHA1-Digest: MSxxDWuVCefhexCkAzYiY88VABA= + +Name: system/app/SelectPlayer.apk +SHA1-Digest: 2XsY4OwW6Emn0/h+nB7TEm2egE4= + +Name: system/etc/permissions/com.nxp.mifare.xml +SHA1-Digest: NHX3y1UpJ+hZmxuIG3M5wc2meZQ= + +Name: system/lib/libmorpho_memory_allocator.so +SHA1-Digest: XoN/HJrKoupLdpJcq/4wZiVIsSs= + +Name: system/etc/security/cacerts/7d453d8f.0 +SHA1-Digest: KA7EPB8eqmgYlxbOQtVKnWf+GDk= + +Name: additions/fonts/sonysketchef/Roboto-Italic.ttf +SHA1-Digest: 1zCsX+RdRK2+Hip1fVXHo514Rlo= + +Name: system/customize/resource/quicklaunch_21419.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/allapplication_23802.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/hosts +SHA1-Digest: 0jQXewud5TCfeP9Tnl6v6gDgad8= + +Name: system/media/audio/notifications/Lily.mp3 +SHA1-Digest: TRyYEW/06CgGWJFGoGZlqRqCgCo= + +Name: system/bin/qcks +SHA1-Digest: iLfliqcx1yJSz2S38lwlBtrCb9k= + +Name: system/lib/libstagefright_foundation.so +SHA1-Digest: vdi/Jm4HpfEcyNXAT3gjTvEALzk= + +Name: system/media/audio/ringtones/Auburn.mp3 +SHA1-Digest: 5QqIIrEs2e0RXsYC3GzzAVcVzH4= + +Name: system/lib/libstagefright_omx.so +SHA1-Digest: LdLnKzmaFvd7AUbkWO2R0ei8hu8= + +Name: system/etc/security/cacerts/add67345.0 +SHA1-Digest: 7q4BGtgTYUE358iZPLoaZft9+1U= + +Name: system/customize/resource/wallpapers_a_02.jpg +SHA1-Digest: 4l2b/97vCQGSPlx2CwNx3RlBX2k= + +Name: system/lib/bluez-plugin/bluetooth-health.so +SHA1-Digest: RV6FTb4q2okmKaxxQqfpbdZYEqw= + +Name: system/lib/libstagefright_soft_amrdec.so +SHA1-Digest: fDo5foBZ2lQxXrgMpAjwXrfUCZs= + +Name: system/usr/srec/config/en.us/grammars/VoiceDialer.g2g +SHA1-Digest: XmIZbaPyRCbQlbRk8avvfTN0VF4= + +Name: system/lib/modules/ks8851.ko +SHA1-Digest: d2rbxTyVPBSXPEXBcwRIxHFMR3g= + +Name: system/customize/resource/allapplication_24002.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libmmrtpdecoder.so +SHA1-Digest: TDVHa4JTGgFCOeXocES9R7OdDe0= + +Name: system/customize/resource/allapplication_23410.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/HtcLavaLiveWallpaper.apk +SHA1-Digest: HHcCSXypyN6pvStwQm3hty4+fFU= + +Name: system/xbin/tcpdump +SHA1-Digest: B9jgs60m1dMUmthmb5W2Qvq5N2A= + +Name: system/media/weather/weather_l_rain_night.mp4 +SHA1-Digest: BP6xNBn+l7AzUx8hINepsIkfmLk= + +Name: system/usr/share/bmd/RFFstd_501.bmd +SHA1-Digest: 0k98ukIhHL0h2zs4tRS2FMidCtE= + +Name: system/bin/arec +SHA1-Digest: +Ida7XXk/3YOIEVSbTpWDPaDMqM= + +Name: system/media/weather/weather_fog_night.mp4 +SHA1-Digest: 1tlC0yLo9lrT817DAHeVu3LP6EE= + +Name: system/framework/com.google.android.maps.jar +SHA1-Digest: bVajguL94nh7v1GkrPjARHw08zE= + +Name: system/media/audio/notifications/Pistachio.mp3 +SHA1-Digest: OayW/hU0w8NZEQZe1LmbDO6ITH0= + +Name: system/bin/monkey +SHA1-Digest: n6hOeaWcDYXtOM/S/BuElL10hfQ= + +Name: system/etc/firmware/tzapps.b03 +SHA1-Digest: /XR+GskqqT8KrDwQ7sDCPdVUzOA= + +Name: system/etc/security/cacerts/17b51fe6.0 +SHA1-Digest: hKFYfH2Zix7tBH5I1wFZbo/Uu1M= + +Name: system/bin/mm-vdec-omx-test +SHA1-Digest: /ynpAtMDzrHEUpKJycxasmg0BpU= + +Name: system/app/HtcMediaUploader.apk +SHA1-Digest: DuBN0D14qUEFKFmROCDQSEMdALI= + +Name: system/app/IMEXT9Slovenian.apk +SHA1-Digest: W9yQa+2WZGEFoZBBj4h8yg8VR3w= + +Name: system/lib/libchromatix_s5k6a1gx_preview.so +SHA1-Digest: M9+FuF7eLy76ADXb5myjVHN+qKc= + +Name: system/etc/firmware/tzapps.b01 +SHA1-Digest: 6EhkhARvMZD8gj0qjMuPWWvHi2s= + +Name: system/fonts/DroidSansThai.ttf +SHA1-Digest: 90bP0Gb6wvJfiap86bLKmXUIXpg= + +Name: system/vendor/pittpatt/models/recognition/face.face.y0-y0-22-b-N + /full_model.bin +SHA1-Digest: KblDOYF2yaers6P16X1U78FNHmo= + +Name: system/etc/firmware/tzapps.b02 +SHA1-Digest: nl4uvPbTSuKaUXBRxTCwv99kQTY= + +Name: system/lib/libcommon_time_client.so +SHA1-Digest: Wv9+6a+IJILSDBARvk6419S3PM0= + +Name: system/etc/firmware/tzapps.b00 +SHA1-Digest: ajmdiAw4ldokY5nVSdc6jH+1Fv0= + +Name: system/etc/security/cacerts/119afc2e.0 +SHA1-Digest: EWDvjIKz5iXOM8ywruinfBcudRs= + +Name: system/bin/watchprops +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/framework/browsermanagement.jar +SHA1-Digest: N81zoXfQjR572GywvaGR/NYRgjU= + +Name: system/app/GoogleServicesFramework.apk +SHA1-Digest: VHzT2lsiVAN675/KJK2CPUWRf2I= + +Name: META-INF/com/google/android/aroma/themes/sense/button.9.png +SHA1-Digest: InlGz7Cq45PigWMA4uPLHlms3+0= + +Name: system/media/audio/ui/Volume-5.flac +SHA1-Digest: ewkQuipEljWSztx0GZkDjC/T9Fo= + +Name: system/app/HTC_IR_Remote.apk +SHA1-Digest: HV7gFcxr6RAdjZw+0NsbJXkjbus= + +Name: system/lib/libstagefright_amrnb_common.so +SHA1-Digest: dxPR/svY1yVFA83S1UiUkyD228g= + +Name: system/app/HtcBtWidget.apk +SHA1-Digest: Yr1HhSH9x1RXUfcHvyw6FqF9fBo= + +Name: system/customize/resource/wallpapers_b_06.jpg +SHA1-Digest: jFHHhCqbnq8FrglsJOLbl2pL6Lc= + +Name: system/customize/resource/rp_ac_no_nfc.png +SHA1-Digest: 350zjLKXC0/TIruGqGLQOswctQM= + +Name: system/framework/com.htc.fusion.fx.jar +SHA1-Digest: eje7d/ifUw8hN1MSlnXEQH7p1xM= + +Name: system/etc/dhcpcd/dhcpcd-run-hooks +SHA1-Digest: 45jhBTsJr35CEQZApn9fjYeWTYA= + +Name: system/lib/libmorpho_jpeg_io.so +SHA1-Digest: nxbUbQNumyF4BO6VN42ruXXB3pU= + +Name: system/etc/security/cacerts/e7b8d656.0 +SHA1-Digest: H+gcIZ25xZ2zXtjkS4UDXDJdo7o= + +Name: system/etc/firmware/fw_bcm4335_apsta.bin +SHA1-Digest: tOGU7t2PAjHx4SyMN0ODOq33Q5Y= + +Name: system/media/LMprec_508.emd +SHA1-Digest: 6FhFfYVqFx0dhdkGKfVq/4ek+GY= + +Name: system/lib/libwlwpscli.so +SHA1-Digest: NUaizgnrnzhRVL2RlE14srPeXJE= + +Name: system/lib/libspeex_sh.so +SHA1-Digest: kvsBu1cUoOw4tCvXnDfeF2TYKQA= + +Name: system/customize/resource/quicklaunch_234.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/tfa/playbackbeats.config +SHA1-Digest: j6S5V89FwvUw8PmIK737fBvqmO4= + +Name: system/lib/libbcc.so.sha1 +SHA1-Digest: Iz1kPz6CHH55kQCrIwbkuoRYlfk= + +Name: system/bin/wpa_supplicant +SHA1-Digest: 9O/IOgmSBhu2MBcb1GL4Mi2FHCo= + +Name: system/app/ChromeBookmarksSyncAdapter.apk +SHA1-Digest: 7+Ainsjkh0eQzisgg61adorIbYI= + +Name: system/usr/srec/en-US/norm_fst +SHA1-Digest: 32Va9kDkSjxVzWPqPAuaFcGR824= + +Name: system/media/weather/weather_l_partly_cloud_night.mp4 +SHA1-Digest: eXPCSlmRkUbObdGF0BDSKlvQF8w= + +Name: system/media/audio/alarms/Sea_Green.mp3 +SHA1-Digest: AW72uwxPQnW6LD6EOfJlbep9qcw= + +Name: system/lib/libril.so +SHA1-Digest: xtM5qbO0otiQb4Lf3MA5j1liBiE= + +Name: system/lib/libwt6docintr.so +SHA1-Digest: cMuuHbQ4YRR12qq3fsh4VRg6xNk= + +Name: system/etc/permissions/com.htc.lockscreen.fusion.xml +SHA1-Digest: fMICRSZIHAqkIugRoyji09kbU7w= + +Name: system/media/audio/ringtones/Violet.mp3 +SHA1-Digest: xckKz52mp++IoqDt0RoAKg2zwxs= + +Name: system/etc/dbus.conf +SHA1-Digest: tFSSxBd60rDOWFVGzFY7lMyaFcs= + +Name: system/app/SmartDim.apk +SHA1-Digest: DpDJNBJseuD9ZYPOlHtxwgTcdFg= + +Name: system/etc/tfa/playbackbeats.eq +SHA1-Digest: GRbTA4TG5srGNohUHz6/IXX9Ffo= + +Name: system/lib/libdnshostprio.so +SHA1-Digest: mZQPXUw71EJxOzmdz91kN9P+wdQ= + +Name: system/lib/libttscompat.so +SHA1-Digest: CmBjDj/n2wSRL4NDdtW5QK4fGpk= + +Name: system/app/HtcScreenBrightnessWidget.apk +SHA1-Digest: NrOGeNLycZ5xV/dYnopxwI6vSCA= + +Name: system/lib/libmmcamera_faceproc.so +SHA1-Digest: 8D8rJPbt+VvBtZ0blTOWgWfb18A= + +Name: system/bin/sdptool +SHA1-Digest: 9ZTFNlZ95GcqWWaZbY/GPfJLFi4= + +Name: system/media/audio/ui/KeypressReturn.ogg +SHA1-Digest: AhKAuhFRUYILt2u43zNK389U9hE= + +Name: system/usr/srec/config/en.us/baseline.par +SHA1-Digest: mOE8GQoDRu/VLgUGSPxYHPuTfIc= + +Name: system/bin/test_gemini +SHA1-Digest: QCxZBkfqAnnFUJh854ow4yU7hms= + +Name: META-INF/com/google/android/aroma/icons/update.png +SHA1-Digest: /TMHtx0Qm4TkPEEeYHxdW6dBApY= + +Name: META-INF/com/google/android/update-binary-installer +SHA1-Digest: GZ+9X0ra+kM28qh/Dsrgb0KaIQA= + +Name: META-INF/com/google/android/aroma/themes/sense/cb_on.png +SHA1-Digest: 9VS4RbjDR4WXSrUKhpx828IJREI= + +Name: system/lib/bluez-plugin/input.so +SHA1-Digest: Xky071GSJofAmhM29sIfvhFiRiM= + +Name: data/app/com.google.android.gms-1.apk +SHA1-Digest: wN5vHNB3EYgxbAIfFV0AJGWaK1Q= + +Name: system/app/AndroidHtcSync.apk +SHA1-Digest: o8JzqbMaE6/zYAh1iY4L6HDWqe0= + +Name: system/etc/permissions/android.hardware.touchscreen.multitouch.d + istinct.xml +SHA1-Digest: 6bH+JNF8K7loeVqBinWWVhatvEU= + +Name: system/customize/resource/allapplication_21406.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/sleep +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/CalculatorWidget.apk +SHA1-Digest: MAx/MqvXBSSpbgCFul3jyWlETAM= + +Name: system/fonts/AnjaliNewLipi-light.ttf +SHA1-Digest: rU+cXSq1srM57xAO9aHbB+WV8No= + +Name: system/etc/security/cacerts/4e18c148.0 +SHA1-Digest: 1Cu+Q2UOC9j8wfjVMl1AK6h2IPo= + +Name: system/app/Basic.apk +SHA1-Digest: 6FgOxuXOQd0pkcwWQuGb+ogXIoU= + +Name: system/app/IMEXT9Turkish.apk +SHA1-Digest: v0hfNh9uEDFedhE45xQxDR9Vyo4= + +Name: system/etc/security/cacerts/ff783690.0 +SHA1-Digest: 7sOkn8zxphGUXHNkddKmw5n9Lrw= + +Name: system/lib/libwt6imgrdr.so +SHA1-Digest: gvVKNg9lMEbn2bL8cRllFaLVumw= + +Name: system/bin/app_process +SHA1-Digest: WvPCmzYJRLX9uaJEpBabdCns+NE= + +Name: system/lib/plugins/com.adobe.flashplayer/libstagefright_froyo.so +SHA1-Digest: vQEUytAuigLJJbJWsXDNaf/YSuU= + +Name: system/media/zchgd/batt_100.rle +SHA1-Digest: DqypThdyPWCZQTQ1TTbGt94te2o= + +Name: system/lib/libstagefright_soft_h264dec.so +SHA1-Digest: XdBsOuVDvbb4QfOxCPpVslufVF8= + +Name: system/lib/libhtcpainting.so +SHA1-Digest: i1tLwPyuVEgPk1M4oc8rNUbhC94= + +Name: system/lib/libssl.so +SHA1-Digest: SFV4A69frH0oevUOL/iCMpSGF70= + +Name: system/app/HtcPowerManager.apk +SHA1-Digest: nQpau0Ci9Dd0/D2qoZRMkUm9e1o= + +Name: system/bin/radish +SHA1-Digest: ZuH0aX+bOVnBm6LqLW3Ao5L+NHU= + +Name: additions/smson/app/Message.apk +SHA1-Digest: sAzIlEutDRa6NvwrAg6J/XEQmJw= + +Name: system/lib/libicule.so +SHA1-Digest: RFWGAf562CzfoH/hsfGhibTJDOI= + +Name: system/lib/libsc-a2xx.so +SHA1-Digest: h+Rqx/lpDSgBfVDo9bZ5KIRlegA= + +Name: system/media/zchgd/batt_80.rle +SHA1-Digest: c7okre4LVo5tBcQ9oP/g35t2NB0= + +Name: system/lib/tcp-connections.so +SHA1-Digest: HfuhcZxgF/H4/GE7BeLVpAe6/1Y= + +Name: system/lib/libwfdmmsrc.so +SHA1-Digest: jWdRj7Di+hhrY6tO3frTWz+rIxU= + +Name: system/lib/libchromatix_ov5693_hdr.so +SHA1-Digest: XC9+clcrEQoWK3oNCwk5H4RoXXc= + +Name: system/media/audio/ringtones/Indigo.mp3 +SHA1-Digest: uYAaWSSkaf3LEjeRLl9D3Ywj2SA= + +Name: system/app/IMEXT9Arabic.apk +SHA1-Digest: w5a6xDXfLyFiXZSmQWDfsLf2tlM= + +Name: system/usr/srec/en-US/hmmsyms +SHA1-Digest: 91T/MhByCAfKs+vOQQiZsYXNWsM= + +Name: system/usr/keychars/Generic.kcm +SHA1-Digest: OIjK3iqPcTGY5f9GOefCLwVUTSo= + +Name: system/lib/libawDTCP.so +SHA1-Digest: ePlt7ugg+bAyp32M3X/eqRcJAew= + +Name: system/framework/framework-res.apk +SHA1-Digest: 0kleShctAfGcGP8cB/iakD3qqZE= + +Name: system/etc/tfa/voip.eq +SHA1-Digest: akzJZd8ilz4aAsWHG6uC3H5L+tk= + +Name: system/fonts/HTCHand.ttf +SHA1-Digest: 7n7FxCJtne87cdOvZgS11BHxFoA= + +Name: system/media/audio/ringtones/Chrome.mp3 +SHA1-Digest: PpJnx3JqMdGsUpnePXxYnSZRKSU= + +Name: system/framework/javax.obex.jar +SHA1-Digest: s8baZXkZ8fbuhdIDTM1k0tkVHXk= + +Name: system/lib/libicui18n.so +SHA1-Digest: N13+lhhqDCxc/yXtBQdxCHoIFaw= + +Name: system/lib/libmmcamera_interface2.so +SHA1-Digest: Hx5y2BMF1NoySn3BWaBW17WpCic= + +Name: system/etc/security/cacerts/e8651083.0 +SHA1-Digest: WgJxTbOn+kJyfUYGkHMdssJ14+4= + +Name: system/etc/ar0260_1 +SHA1-Digest: P8BRHTNEk4ZkOWaSvNi1nLT3aiM= + +Name: system/customize/resource/allapplication_234.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/dnsmasq +SHA1-Digest: tAuBH1Pthk5Qsjn28X1kaR8o+b8= + +Name: system/lib/libglib.so +SHA1-Digest: Z6jH5i1N9Wfk6pT5FkXjwiqvsnY= + +Name: system/etc/firmware/ILP0100_IPM_Data_out.bin +SHA1-Digest: Lv1yzkNB68uxzCvj1audhYdjB7c= + +Name: system/etc/security/cacerts/aaa45464.0 +SHA1-Digest: hPmjRDs4R8Z0AstXNTrfuQx92jQ= + +Name: system/etc/security/cacerts/613f892a.0 +SHA1-Digest: Vtbly9XYW23L/7ACZufcLj3bvFw= + +Name: additions/fonts/roboto/Roboto-Italic.ttf +SHA1-Digest: UoLSclAdePMifNNIYtx6LAHL9Us= + +Name: system/bin/mm-venc-omx-test720p +SHA1-Digest: F3Hy/4M466IKOAO0m5nIKfBmaqU= + +Name: system/bin/content +SHA1-Digest: 6POL0bmUWZQ4ZznC7yaw+OKUcs0= + +Name: system/lib/libFFTEm.so +SHA1-Digest: OFM8rnycbA1w5W8A/YzpMRAeuw4= + +Name: system/bin/date +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/hw/sensors.m7.so +SHA1-Digest: IA+bUAEzAIIlwjxwZeZHfdXSwNs= + +Name: system/usr/keylayout/Vendor_05ac_Product_0239.kl +SHA1-Digest: 0R+he6vcnn7eY/jqIcFaCiCK7rE= + +Name: system/bin/mm-video-driver-test +SHA1-Digest: fQ1YbIvgPHX2WMWh1LV9fmmXn5Q= + +Name: system/app/Usage.apk +SHA1-Digest: Diw8nDozHr6CSfXUiZV2vvvIZ/I= + +Name: system/lib/libsc-a3xx.so +SHA1-Digest: zKqvJBWcrnsgX+70n9v4zje73go= + +Name: META-INF/com/google/android/aroma/scripts/save.sh +SHA1-Digest: GTL6976QW8zlzkaNNd/ezvASMz0= + +Name: additions/fonts/klavika/Roboto-Regular.ttf +SHA1-Digest: WHIxRNJuAltbRkdU7rHB9nQ2AfQ= + +Name: system/bin/mm-pp-daemon +SHA1-Digest: 7AG+TpFZseIuZbHPBlr6uagrgNU= + +Name: system/fonts/DroidSansEthiopic-Regular.ttf +SHA1-Digest: iFu88W2tFX67p/lLUPlONycOIdU= + +Name: system/framework/core-junit.jar +SHA1-Digest: DFWeZOPPVB3iHxLEVZTR4i70w2c= + +Name: additions/fonts/segoewp/Roboto-Bold.ttf +SHA1-Digest: pwKJLD+hi6FeGBMj1lkCD/AU7lU= + +Name: system/lib/libhtccamera.so +SHA1-Digest: sSvxUY+aqECkCvbl2tkwHOI/iQc= + +Name: system/usr/srec/en-US/endpointer_dictation.config +SHA1-Digest: +WnICju2l/yud03mhNLtzPFtppY= + +Name: system/media/weather/weather_thunderstorm_day.mp4 +SHA1-Digest: nDyReD5EeGwIMVHxh9IqlA5Y/5o= + +Name: system/lib/libvideochat_stabilize.so +SHA1-Digest: 51zUOY6tjmgc4biG/R8+WTwQvgc= + +Name: additions/gps/south_america/etc/gps.conf +SHA1-Digest: lWgC/Z1PboORJ+qeZ1NYXFWATnQ= + +Name: system/lib/libmode10GLES20.so +SHA1-Digest: CCSwoltPLHCrYA1t4YeLPu6uG+o= + +Name: system/media/audio/alarms/Celedon.mp3 +SHA1-Digest: 0VKOTOh45ctwqNCVTdcXpRpbZTA= + +Name: system/app/HtcDialer.apk +SHA1-Digest: 1s5oTJBj3XEtcnE+33YPBNXJxDs= + +Name: system/lib/libchromatix_ar0260_zsl.so +SHA1-Digest: Kj0VI+A2GccEu7Ot+KlnmVG4jzI= + +Name: system/tts/lang_pico/it-IT_ta.bin +SHA1-Digest: HKQqkLPKlZzLKMjUtrSHc56oLsw= + +Name: system/bin/newfs_msdos +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: additions/fonts/sonysketchef/Roboto-Bold.ttf +SHA1-Digest: V2q2Mh+gmO4mB5vcclK6VQjb8H4= + +Name: data/app/com.google.android.gm-1.apk +SHA1-Digest: 81MvNoL8PoyiE4PPRKmC+DI1MHE= + +Name: system/media/GPU/twoToneMaskH.bmp +SHA1-Digest: xju58t119afsTQgOLGLjXJZylb0= + +Name: system/app/Prism_AppUpdate_DummpPackage.apk +SHA1-Digest: Rxu4Y3ItKiJyWNrnK60Scz9C1Fo= + +Name: system/lib/libWVphoneAPI.so +SHA1-Digest: tfhAPiVo+Fp/al91zrUzmbiij8k= + +Name: system/etc/security/cacerts/aeb67534.0 +SHA1-Digest: 3niKiQPKP7O/zD2IkVJZqxha7s4= + +Name: system/etc/permissions/android.hardware.sensor.light.xml +SHA1-Digest: o5fC0OmTC1XhEfP9A5C41jbAt2w= + +Name: system/lib/libchromatix_ov5693_preview.so +SHA1-Digest: +8YZGzQVSveOyAbb5SQhsJ2o9kM= + +Name: system/app/HtcMusicEnhancer.apk +SHA1-Digest: xdbz9gXDS+ZCJmlQSv86O2+Erl8= + +Name: system/lib/libmmmpo.so +SHA1-Digest: TKcwQmWeuJc3Kc87mXLSOgT5MNc= + +Name: system/media/audio/ringtones/Silver.mp3 +SHA1-Digest: rsdVdsQredwmS1AzA+da++X+GEo= + +Name: system/lib/libqmiservices.so +SHA1-Digest: gwZhzMTCWF31takbrlaBx5OVVo0= + +Name: system/etc/tfa/playbackbeats_l.preset +SHA1-Digest: JYWGCVyXl3c9Rz9ndzK8oEuGmqk= + +Name: system/lib/drm/libhtcomaplugin.so +SHA1-Digest: m3mZnETp7k9G66LiTlx15cDwcf8= + +Name: system/lib/libimage-jpeg-dec-omx-comp.so +SHA1-Digest: ICZzQfoGovmXQVvoU+6CJhPXqvc= + +Name: system/media/audio/notifications/Pine.mp3 +SHA1-Digest: lB/YaqhyHoimiswvkhxOIyI7ZXo= + +Name: system/lib/libdmt_native_utils.so +SHA1-Digest: 6P8SpdE1r3CXHT90RYbtDgjW3pg= + +Name: system/app/IMEXT9German.apk +SHA1-Digest: vlK9sDi4HA/dC8RhAySMFLAMyiE= + +Name: system/etc/security/cacerts/ed62f4e3.0 +SHA1-Digest: /rUe4P3d/iSrFrAVuxlri5RIGWo= + +Name: system/bin/uiautomator +SHA1-Digest: 4tR5BSwIaFPIGk76lJrXZYZ2P28= + +Name: system/bin/mm-video-encdrv-test +SHA1-Digest: TaZdZhFUK7SI3fzuaA2wiBiRyyU= + +Name: system/media/audio/ringtones/Plum.mp3 +SHA1-Digest: X23ZUi3Pg5VrHwwCJUsKDfw9wtE= + +Name: system/bin/chown +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/MusicVisualization.apk +SHA1-Digest: b3jB/4niU3X544HwSfdSRvChu0Y= + +Name: system/etc/tfa/tfa9887.patch +SHA1-Digest: Kd02luAPrgU9ys9kn6jt3QLZdqk= + +Name: system/etc/security/cacerts/f61bff45.0 +SHA1-Digest: d3A25cK0u8CKtQwP0QHb01XjqXU= + +Name: system/app/HtcLocationService.apk +SHA1-Digest: fDETx6ISrFcOIYGCy7TIIzavPVs= + +Name: system/fonts/RobotoCondensed-BoldItalic.ttf +SHA1-Digest: urWUX1xs52/IukAulDtzt91OkPo= + +Name: system/etc/image_ibeats_v2_2vol.bin +SHA1-Digest: pTIJmH3i3zx9ELCVq8H8g/upAv0= + +Name: system/lib/libC2D2.so +SHA1-Digest: KHveEZGGzHmMzvupGBxt0a8KKB4= + +Name: system/lib/libhtcirinterface_jni.so +SHA1-Digest: wXD+k1OlJW7ac1k9gT6zhpFv1zU= + +Name: system/customize/resource/quicklaunch_23210.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/audio/alarms/Beige.mp3 +SHA1-Digest: 2lQr/z0TwvIPi0RBW1XzRjokBhU= + +Name: system/app/HtcCarGps.apk +SHA1-Digest: gpbW3q1Q9ml6qpc9ZgFGkXLD3jM= + +Name: system/etc/image_ibeats_solo_v2.bin +SHA1-Digest: UotezM2rsyllTt3c8Yc/R1IIcW8= + +Name: system/lib/libOmxMux.so +SHA1-Digest: Shn5kMCnrsikB4N8xL83jZ6M4y4= + +Name: system/bin/sensorservice +SHA1-Digest: LP7Ov/1BSwY9eXtP43YERlNwX18= + +Name: system/fonts/DFHEIA5A.ttf +SHA1-Digest: nKbBSUH3LiqZ+hEfHZywHJJA1Rk= + +Name: system/usr/share/partials/partials.dat +SHA1-Digest: yMWni8PMW+loCQCK8J9i1xN7MMM= + +Name: system/usr/keylayout/Vendor_046d_Product_c294.kl +SHA1-Digest: n8G5GZJh3RRh04UYBCiVlEHimDU= + +Name: system/media/audio/ringtones/Snow.mp3 +SHA1-Digest: HGW+EDMikVmz2AhN/XfEtOztsCo= + +Name: system/lib/libstagefright_soft_h264enc.so +SHA1-Digest: fIDI8QtWGgP+oYuhz8/X54hfb7Y= + +Name: system/etc/init.goldfish.sh +SHA1-Digest: oVAMzXnCy588jqkgurss/oczzDA= + +Name: additions/gps/north_america/etc/gps.conf +SHA1-Digest: 68asJMwdPHiBQYzs8QMvJ+ac+90= + +Name: system/app/Weather.apk +SHA1-Digest: 7Ug5iu81KE4Im8imK4PwJSJOLCQ= + +Name: system/lib/libchromatix_imx135_default_video.so +SHA1-Digest: oitRbpklaND3p9QI7y2cNVG2Ge8= + +Name: system/lib/libthread_db.so +SHA1-Digest: HrDOWUiApB5sexO54NCcCVdixOI= + +Name: META-INF/com/google/android/aroma/themes/sense/button_press.9.pn + g +SHA1-Digest: kcHcD4rK2BxI7gl+rIx8czWi+QA= + +Name: system/bin/vdc +SHA1-Digest: mQih+J8qbeXVAKrOOeDQqnfVBJg= + +Name: system/lib/libpagecurl.so +SHA1-Digest: De2IEUdsaixmdJLjRRx+o+N1Y6Y= + +Name: system/bin/qmiproxy +SHA1-Digest: 76GuJCvplRx3y01VsNeOpBgCtlo= + +Name: system/bin/getprop +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/fonts/Roboto-BoldItalic.ttf +SHA1-Digest: VYDbVJTNb2eL1eOY4SYWXg+P4PE= + +Name: system/etc/security/cacerts/f4996e82.0 +SHA1-Digest: e7OjBFQ1iru2cH13tni5XjfcfHw= + +Name: system/usr/srec/config/en.us/grammars/phone_type_choice.g2g +SHA1-Digest: Z3YKR+VbcDEuAiO5Qd2G4wsvIVg= + +Name: system/fonts/Roboto-Light.ttf +SHA1-Digest: +RPUxNPpLsZ8LSXfUkfgctYerrA= + +Name: system/media/audio/alarms/Twilight.mp3 +SHA1-Digest: 3Aeiy0/h9X4juVjXW5vYwa2wecU= + +Name: system/app/Calculator.apk +SHA1-Digest: KlsSdXKxTRL+vUtpG/oJffhOpOk= + +Name: additions/gps/south_africa/etc/gps.conf +SHA1-Digest: shrruXhq5DGjgROrCyv1OYb3J98= + +Name: system/lib/libchromatix_s5k3h2yx_zsl.so +SHA1-Digest: +SQpws0S6M6dmSUNR9hgZ5vXkuI= + +Name: system/media/audio/notifications/Jasmine.mp3 +SHA1-Digest: iB1oqrWQYHW9fXRULid+igsnZ40= + +Name: system/usr/keylayout/Vendor_046d_Product_c216.kl +SHA1-Digest: l5FztcNn+7EF/aXwMPgibvC1XXE= + +Name: system/lib/libloc_eng.so +SHA1-Digest: jtWTjPyeN8EoIQdTk0N/1apnxiI= + +Name: system/lib/libzeroeditor_jni.so +SHA1-Digest: xZCpggShFY5Xsf+hLAtYEWkl8zI= + +Name: system/lib/libmmjps.so +SHA1-Digest: CEvRYbjxzkD6BlngVUpiHgpAADk= + +Name: system/etc/tfa/video_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/media/audio/ringtones/Ao.mp3 +SHA1-Digest: 1u/NxiCTgu2gfUzpZie3XUiJnqE= + +Name: system/etc/tfa/playback_l.eq +SHA1-Digest: vq86JS6uyWcHNWiP3yEKg+8JCXQ= + +Name: system/fonts/Roboto-Italic.ttf +SHA1-Digest: UoLSclAdePMifNNIYtx6LAHL9Us= + +Name: system/media/audio/ringtones/Icterine.mp3 +SHA1-Digest: aP5LEa6FdDKVoC+5LBv8boAg6Nw= + +Name: system/lib/libbcinfo.so +SHA1-Digest: rw3LNo82QqZaegTX3uukZXyWUXc= + +Name: system/lib/libnfc_ndef.so +SHA1-Digest: fmd7R7lF53tuY5rxJb4gFJk0+Jo= + +Name: system/bin/notify +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/customize/resource/quicklaunch_420.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/quicklaunch_21404.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/tfa/ring_l.preset +SHA1-Digest: NDpQDq6Ee/6Q/YEhmqXfFGXPVP0= + +Name: system/lib/libmmosal.so +SHA1-Digest: 4YD6JeWoVqE8VllWp9scJhfo+a4= + +Name: system/etc/tfa/playback_l.preset +SHA1-Digest: 95X1TUPDgbbUrIKwgfEXGc069HQ= + +Name: system/framework/com.orange.authentication.simcard.jar +SHA1-Digest: ypu7QN97yd7a3xcfDRjHAkSoZVE= + +Name: system/media/GPU/dot_mask_0.bmp +SHA1-Digest: sAn8AkmRls6yJuJQujf9oJ3xCDg= + +Name: system/app/IMEXT9Serbian.apk +SHA1-Digest: jje8OmPaSXek4FjZ2mDeO2n3G1M= + +Name: system/etc/security/cacerts/74c26bd0.0 +SHA1-Digest: OaKWMuPk9pCf4isRHaBDfJj//V4= + +Name: system/lib/libalsa-intf.so +SHA1-Digest: gb16Mfb5qAMe5btW+LIWxONUELM= + +Name: system/customize/resource/icon_launcher_mail.png +SHA1-Digest: FRf1YnrwgMhqMxSGrzcr4JUAs/U= + +Name: system/lib/libOmxVenc.so +SHA1-Digest: WXYRSL/LBhCv4BNRybuxIfjGgnE= + +Name: system/bin/rtspclient +SHA1-Digest: qG0rGkomB0b7fN6ku2nwLLKrLlQ= + +Name: system/framework/com.playstation.playstationcertified.jar +SHA1-Digest: xMAftjL+VhmkF4bAF++wCGmeUMY= + +Name: system/fonts/Lohit-Kannada.ttf +SHA1-Digest: e+cag/VBf8+7uop4vUTQbpk22qE= + +Name: system/usr/keylayout/synaptics-rmi-touchscreen.kl +SHA1-Digest: IQcIzYOfqpGYPTRy0AtLk1vMfz8= + +Name: system/lib/libutils.so +SHA1-Digest: Gqf+CCM9+BIY9C/tolknwYxI/3g= + +Name: system/lib/libc2d2_a3xx.so +SHA1-Digest: s4rpme3VwG5ISEgOxxYVlwdwya4= + +Name: system/etc/tfa/video_l.preset +SHA1-Digest: gLyUQwAim17CsSVazvxBjmG77tQ= + +Name: system/xbin/dexdump +SHA1-Digest: J1YamenP4hAHBZs/PqaU1OclGho= + +Name: META-INF/com/google/android/aroma/icons/apps.png +SHA1-Digest: PfvyF/zQeOBuTVbIBl7Wb+TonE0= + +Name: system/app/MediaUploader.apk +SHA1-Digest: Jb8yqCvQBeX5XIO3PgSW6xJtywQ= + +Name: system/etc/security/cacerts/a2df7ad7.0 +SHA1-Digest: +xwpSUIGj8RMEb/Xl28K69HmZLc= + +Name: system/app/IMEXT9BahasaIndonesia.apk +SHA1-Digest: 7XjJ2jR+pov9G8l1M5eAD3GAvp4= + +Name: system/media/weather/weather_hot.mp4 +SHA1-Digest: TY/GwOH3Gw3gZUDIctB7BYTZyGA= + +Name: additions/camera_4.2/lib/libjni_mosaic.so +SHA1-Digest: M1/kJbLfeKPWydQnYPUkw5cwJ1M= + +Name: system/app/GenieWidget.apk +SHA1-Digest: XiTzeRUija4ISyy5l0cWYgRkpZ4= + +Name: system/usr/share/partials/partials_A_bb.csv +SHA1-Digest: Eh6+/JGzpbNSY9dIETqiXqU7MnA= + +Name: system/etc/security/cacerts/a7605362.0 +SHA1-Digest: ydDNX6E+RFIn8R4w9i4iJXOLoOE= + +Name: META-INF/com/google/android/aroma/icons/install.png +SHA1-Digest: 4jQwvaI7rzIWej0OwJJDRtr9hF4= + +Name: system/etc/security/cacerts/56b8a0b6.0 +SHA1-Digest: LSyf6A501o2tD7CKNauSUSoXSJU= + +Name: system/customize/resource/icon_launcher_hotmail.png +SHA1-Digest: +lvjvcq+1MsKzD688ACzHYGgdVw= + +Name: data/app/com.google.android.youtube-1.apk +SHA1-Digest: Y3H/kZRzccAkgJz+iXvnGcHGopE= + +Name: system/lib/addict.dat +SHA1-Digest: 4H0zWmhejpZ0NeoBB8Yz2wU3l+s= + +Name: system/lib/libnativedocviewer.so +SHA1-Digest: 6C2cEHlgQLTxsRCy6v0D0hb1sHk= + +Name: system/media/GPU/CurveSepia.bmp +SHA1-Digest: 30cjruI5GORG96DTq3dcz4kz5N0= + +Name: system/bin/netsharing +SHA1-Digest: +gT5huWi3HJicH/vmF66HGqsjkI= + +Name: system/app/Phone.apk +SHA1-Digest: G3DpCJnghYXgbvQDE8fGXmvit5c= + +Name: system/media/zchgd/charging_04.rle +SHA1-Digest: S48C90ViaLLTNuLvRQ95MBU8/DM= + +Name: system/lib/libchromatix_ov8838_zsl.so +SHA1-Digest: nHmo57hQE6HG9CzAH3E143TnoRo= + +Name: system/app/PureC_ApplicationsProvider.apk +SHA1-Digest: SJR7EfyX8nt+XAR1YQh2uIZzuKY= + +Name: additions/fonts/ubuntu/Roboto-Regular.ttf +SHA1-Digest: Do4jwIp9qHyjkFfqU311iWT/7AA= + +Name: META-INF/com/google/android/aroma/requirements.txt +SHA1-Digest: k8MUSCbWtXAMQbYGt3LxYu0bQjU= + +Name: system/lib/libbluedroid.so +SHA1-Digest: 3xcNyw7TezSyQj117g75VhAswMo= + +Name: system/customize/resource/allapplication_21408.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/fonts/DroidSansMono.ttf +SHA1-Digest: Ez+2zybqBztFb7VXuUzoxGFDsRc= + +Name: system/framework/android.policy.jar +SHA1-Digest: 7SA6H6NljMdWNExBiEz0hZQPqPk= + +Name: system/lib/libHTC_DIS.so +SHA1-Digest: lnTwhSl3Y9yhbZ4qSk0UftW5MIU= + +Name: system/customize/resource/quicklaunch_21407.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: META-INF/com/google/android/aroma/themes/sense/button_focus.9.pn + g +SHA1-Digest: qedWodmyPtpvTVBa5oh+kEhfRbs= + +Name: system/etc/security/cacerts/7a481e66.0 +SHA1-Digest: SA1ZMXDrMT0bFLrkIXeyPdSCldI= + +Name: system/lib/libdsi_netctrl.so +SHA1-Digest: t05ojITUQ+wNBDOx3i0rOE+SRUY= + +Name: system/media/GPU/dot_mask.bmp +SHA1-Digest: oSDtm4iAj/b5A9SIk+P0x2UfXtg= + +Name: system/lib/libnotesprovider_jni.so +SHA1-Digest: Wdh/Z80JsK4h9sL2kJMYChtA5KY= + +Name: system/app/IMEXT9Danish.apk +SHA1-Digest: oJkcExcRgVQNm2Ms+voRd0HKhIQ= + +Name: system/etc/security/cacerts/5a3f0ff8.0 +SHA1-Digest: D5NgyenT/uE9GAWVJqapSAwCRC4= + +Name: system/app/WifiRouter.apk +SHA1-Digest: vdqnawB107cfDoetLpwu7HvXzr4= + +Name: system/media/audio/ui/KeypressStandard.ogg +SHA1-Digest: WFdYi785ujyp6JwqtdsHziO5hjU= + +Name: additions/fonts/ubuntu/Roboto-Bold.ttf +SHA1-Digest: rq3ZO1oCm8CTnanH/Zf3LyO18RU= + +Name: system/app/IMEXT9Slovak.apk +SHA1-Digest: z7H/60ekio9IWMtchLXF8NidDUY= + +Name: system/lib/libeffects.so +SHA1-Digest: IiD7VBTNo5oQcby43dxSM/GIsvU= + +Name: system/lib/libGLESv1_CM.so +SHA1-Digest: 7Ux4NBloMYNsc9A3RSmgJ4wvqRw= + +Name: system/etc/security/cacerts/4d654d1d.0 +SHA1-Digest: toWvfEMJLsSRpeuXhuMMajO/iiQ= + +Name: system/etc/security/cacerts/e48193cf.0 +SHA1-Digest: 4QUQZs0nSjATJqFpt84dfehXF/4= + +Name: system/lib/libmmcamera_image_stab.so +SHA1-Digest: ua0+bnV6OjIk35IDohjjR4qi004= + +Name: system/lib/libchromium_net.so +SHA1-Digest: zpFCCxPptH74gTVfpK3EiSp1ciQ= + +Name: system/lib/libdrmframework_jni.so +SHA1-Digest: IB4FoyJzXHpn2s6YPwBG2NZWbgA= + +Name: system/customize/resource/allapplication_27205.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/egl/libGLESv2S3D_adreno200.so +SHA1-Digest: me8zPb/3KzQIbERPMpeCaBWU2Q8= + +Name: system/media/zchgd/error.rle +SHA1-Digest: BWaADBe8pcLSYBl4fA+034BcA4I= + +Name: system/lib/libchromatix_ov2722_zsl.so +SHA1-Digest: OmYn5YzcMGrQxXVwIY88uqwrR20= + +Name: system/fonts/Roboto-LightItalic.ttf +SHA1-Digest: Q0C/Q8zT4VcjEgGFGwTtWOhdW3k= + +Name: system/lib/modules/qcedev.ko +SHA1-Digest: ckYKOnlf1lFgPaNCn0eT6PzIO0k= + +Name: system/app/Automotive_InternetRadio.apk +SHA1-Digest: b8D1sIoaSgitqbfJ3pTKpbIT5FA= + +Name: system/app/FlexNet.apk +SHA1-Digest: U0ffGHuHwClWke+w5pnNOwZF9FY= + +Name: additions/fonts/sonysketchef/Roboto-BoldItalic.ttf +SHA1-Digest: uFf98lNK2CuS0rghoIYKfwBCTD4= + +Name: system/usr/share/partials/partials_A_gr.csv +SHA1-Digest: AKIkzhOqfcSzrb1K1jTWWZCy/rQ= + +Name: system/etc/permissions/android.hardware.telephony.gsm.xml +SHA1-Digest: nvdtSduykpjyEj1aCRzJQBwuh+c= + +Name: system/customize/resource/wallpapers_b_03.jpg +SHA1-Digest: LKBoWw7+/vMvJI/uGxBb7A6SpjA= + +Name: META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf +SHA1-Digest: aXrRiEJkMD14GvrKNCxOpkbt7nc= + +Name: system/etc/firmware/lscbuffer_rev2.bin +SHA1-Digest: L9bFwDw2ScJ5H98TwtvdmmBQqCw= + +Name: system/media/audio/alarms/Chartreuse.mp3 +SHA1-Digest: I9UvkhacKlrDRk+aUbXtXQ3TgfI= + +Name: system/framework/HTCCommonctrl.jar +SHA1-Digest: krx6jdVzi95nVakzqrEBSRmjjmU= + +Name: system/etc/searchabledb.conf +SHA1-Digest: ZCh6WPvzRQaMaft6m7p6ixkNXlM= + +Name: system/app/LinkedIn_Fsplugin.apk +SHA1-Digest: BTPYpsGjdi7CuybVYZ+AJf9lzNg= + +Name: system/media/weather/weather_snow_night.mp4 +SHA1-Digest: Np6FCe3cWe2ybFjMfl2G5C6EasM= + +Name: META-INF/com/google/android/aroma/icons/default.png +SHA1-Digest: 75xqsrZegulFIjheicul/9p3vDI= + +Name: system/media/weather/weather_l_snow_night.mp4 +SHA1-Digest: +SAY1uuWIU2aGoJEi2rrrmDl6e8= + +Name: system/media/audio/ui/Volume-3.flac +SHA1-Digest: J4P4GrN6UbJeBFR0ob5ZRc/IZvs= + +Name: system/etc/security/cacerts/ab5346f4.0 +SHA1-Digest: sSqWJJT/XZpH/LXyVH22pHuXL3I= + +Name: system/customize/resource/quicklaunch_26003.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/c215bc69.0 +SHA1-Digest: quX/iNXdfSEwfOpAJ7UjjBlmlo8= + +Name: system/etc/security/cacerts/6fcc125d.0 +SHA1-Digest: gD/RtuZNrRkHd/Kf7B4e3urcpfs= + +Name: system/lib/libNewTimeBreakin.so +SHA1-Digest: ZEFVmAyvprl9LwNlSoZTe5gtdjo= + +Name: system/app/IMEHWRPenPower.apk +SHA1-Digest: h92ywSRdXWZoWbFiP/1aiYUxoec= + +Name: system/lib/libcamera_client.so +SHA1-Digest: xSnZAJZUGGG6iAJiCzvnDwE3EiI= + +Name: system/media/audio/notifications/Peach.mp3 +SHA1-Digest: ymL1P1ksEjti5eQuiwCumhNXcYI= + +Name: system/etc/bluetooth/network.conf +SHA1-Digest: nu2dYktiZ0gI1G/0bmJQ0vG9GTw= + +Name: system/bin/bootanimation +SHA1-Digest: 24Yb1yQTf6X2uc//DRN5zwN1L7A= + +Name: system/etc/security/cacerts/7d3cd826.0 +SHA1-Digest: L/MwBTuZjUtda8j0poy4nGz3j+I= + +Name: system/app/HTCSetupWizard.apk +SHA1-Digest: BqzbMxAKUhfljqRnxx9j3ECZLmc= + +Name: system/lib/modules/reset_modem.ko +SHA1-Digest: N/sGiNea7wgZSkyBy9v8LTlA4MY= + +Name: system/customize/resource/wallpapers_a_06.jpg +SHA1-Digest: 5LdlMFoT9UnuzvwhAcOYbMhhcZY= + +Name: system/lib/libnetlink.so +SHA1-Digest: J3yzDrTFSoJhM5U3UPLsnjQsQeo= + +Name: system/media/audio/ringtones/Aero.mp3 +SHA1-Digest: h9R+AZZXjJ55zkS/xD/hbPiNhW4= + +Name: system/lib/libwfdsm.so +SHA1-Digest: 2LBzWvL/z1Xk71ZXtDD9Az2LW1w= + +Name: system/framework/com.android.location.provider.jar +SHA1-Digest: kgxRjEPXNXaB02KQnU9/gwpSrr0= + +Name: system/bin/flash_camera +SHA1-Digest: /YWptCbuJQYnQsnaCrMLgA8rYLA= + +Name: system/usr/srec/config/en.us/dictionary/basic.ok +SHA1-Digest: /nwZFjqTU6CKLzpmEnxPxb7aqks= + +Name: system/media/audio/ui/VideoRecord.ogg +SHA1-Digest: lNxenUZXTJQfFT2OxJHkWx8URbg= + +Name: system/etc/firmware/tzapps.mdt +SHA1-Digest: Iwf+i6zrBITqZaRImyM0+Aig/U4= + +Name: system/bin/screencap +SHA1-Digest: QwcRhuq+uie8NIklTk18DcTWF+U= + +Name: system/customize/resource/allapplication_24007.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libalmashot-clr.so +SHA1-Digest: 7P4/bNoos1tk+eAaug6AJ9tDFys= + +Name: system/bin/radvd +SHA1-Digest: M9C8/hBXLoy5zlkjDZqLwEVmDKA= + +Name: additions/fonts/asap/Roboto-Bold.ttf +SHA1-Digest: 3Rm+5MW1h8ODs0v/Lf1r+/eOzqg= + +Name: system/app/HTCSyncManager.apk +SHA1-Digest: JL1ux00jOd3R21gBAn2ZSFecc7w= + +Name: system/etc/security/cacerts/594f1775.0 +SHA1-Digest: rB1X3r8ms6gP9FsYn8TKeNfNeFg= + +Name: system/usr/srec/en-US/clg +SHA1-Digest: i9WVIl/L+yb/jaO4rLxhQP7k/wg= + +Name: system/bin/bridgemgrd +SHA1-Digest: RPDKnxjmMu/EVkw6CUM/z//Lbwk= + +Name: system/app/Idlescreen_Base.apk +SHA1-Digest: TyrclWrz82Koe5QloTyYL0A8bqo= + +Name: system/etc/security/cacerts/2fa87019.0 +SHA1-Digest: PB53+gvlezFU7Jj+8YJ0mh+UzAM= + +Name: system/etc/event-log-tags +SHA1-Digest: xA1plne+LBYz1eFKlWoxMYS0HfA= + +Name: system/etc/thermald.conf +SHA1-Digest: x+qoOykK3A9D753DjqDTgaJ5N3o= + +Name: system/etc/calibration +SHA1-Digest: lTV0aszMLrptXcobTj5m3kE6Jzk= + +Name: system/bin/mm-qcamera-testsuite-client +SHA1-Digest: zwlAtEkAs2epwVMh4jH3xV+OIg0= + +Name: system/app/IMEXT9Greek.apk +SHA1-Digest: 49ATrOz6yUAEu8KwMYPkEFlKD18= + +Name: system/fonts/DroidNaskh-Regular-SystemUI.ttf +SHA1-Digest: /YLqFkhUkwWAbuSlqkVAGnVHze0= + +Name: system/xbin/busybox +SHA1-Digest: /xCDxHWWoisUg/jBaID9qpaxuf4= + +Name: system/usr/keylayout/Vendor_22b8_Product_093d.kl +SHA1-Digest: SNU5mBeA6Kxhy0czF4BOLpoOan8= + +Name: system/lib/libchromatix_ov2722_preview.so +SHA1-Digest: B9JZ/szR02JnV1moLRx6RzD4uVs= + +Name: system/app/Twitter.apk +SHA1-Digest: 5ymRIXvO2rcAi7re+9AVzVOHKWg= + +Name: system/etc/permissions/android.hardware.sensor.compass.xml +SHA1-Digest: 5lFtWpy4NCGP+VUxJOxCJ6wvNcs= + +Name: system/bin/mm-jpeg-enc-test +SHA1-Digest: xeDii/rfIiQ5Aqzdd/MlgeNwaTA= + +Name: system/usr/srec/config/en.us/models/generic8_f.swimdl +SHA1-Digest: GgnYWcIdaKmXR6fAvPMIhiEu1Wo= + +Name: system/lib/libqmi_cci.so +SHA1-Digest: GDQLrVqk6JlyFKeQEvZdaAPDOhs= + +Name: system/etc/security/cacerts/fac084d7.0 +SHA1-Digest: JrK7FVoKOO/8bvPLla8wo5xTToE= + +Name: system/customize/resource/icon_launcher_gmail.png +SHA1-Digest: 5kiKKBaBFTSP1WJqOWpUxaW5btk= + +Name: system/bin/usbhub +SHA1-Digest: vE6JfRSIlqRRaEE+ezhzdWfzOV0= + +Name: system/bin/vold +SHA1-Digest: CsOzGuP6l38w+9hFA3EnBm8g4A8= + +Name: system/usr/keylayout/projector-Keypad.kl +SHA1-Digest: gx7IMdEqFXd9j8P4kPbXmTfw/EA= + +Name: system/app/Watch.apk +SHA1-Digest: Tke36FZGf5fkqEsWMWJEVV/5YFE= + +Name: system/app/FaceLock.apk +SHA1-Digest: uUKqZkThdouzBu87kJMhWVvxfCs= + +Name: system/fonts/RobotoCondensed-Regular.ttf +SHA1-Digest: qY1rjMjPiMivTe+AYG+lleCOGYc= + +Name: system/usr/srec/en-US/google_hotword_clg +SHA1-Digest: k3aCqpXWQM5DIn7znzZjsU9SJ24= + +Name: system/media/audio/notifications/Almond.mp3 +SHA1-Digest: u5D+XxQySwPKM7pmnshOd2FK14s= + +Name: system/bin/ime +SHA1-Digest: tRT4xXnmwLMmpCiARGf1xmn/8K0= + +Name: system/media/weather/weather_l_clear.mp4 +SHA1-Digest: nEd35PcerVC7tCPhsERSgUGTceo= + +Name: system/media/audio/notifications/Teal.mp3 +SHA1-Digest: B1O5UU4hnW/9/d8yh9eJk0FFEHc= + +Name: system/etc/timezones.db +SHA1-Digest: 2f/R5IXEykAILEmJiuOJUUR1pnI= + +Name: system/usr/srec/en-US/embed_phone_nn_state_sym +SHA1-Digest: T8+zEXNoKbioXdyuELp0PzOMY3c= + +Name: system/usr/srec/config/en.us/models/generic8.lda +SHA1-Digest: /y/sXjBSqRQkFc848OCkAh9PhTE= + +Name: system/lib/libacdbloader.so +SHA1-Digest: gcDVxBVY8xWNQMUZ4BZs6EoJT9M= + +Name: system/app/Prism_AppUpdate_UpdatingScreen.apk +SHA1-Digest: Wxt0dFOS/VLVOpJL9mTUugO5UAc= + +Name: system/etc/security/cacerts/ed524cf5.0 +SHA1-Digest: yTN26RsNrb/CudFl/v0+xfETrU8= + +Name: system/customize/resource/quicklaunch_65510.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/security/cacerts/9ec3a561.0 +SHA1-Digest: Ks4msL8rX99I9sph+SVRWp56LLw= + +Name: system/etc/security/cacerts/7999be0d.0 +SHA1-Digest: IsAGvSZ42ierGS9JE3DG/92df74= + +Name: system/lib/libchromatix_vd6869_night.so +SHA1-Digest: ju32fIoVrHY6g06KqcRBo4PKzO4= + +Name: system/app/MyPen.apk +SHA1-Digest: hQMmOqZJR1YphJVnYSdX56b08lM= + +Name: system/bin/DxDrmServerIpc +SHA1-Digest: B/khYap8U+IsHXo4eOeQUVSanOM= + +Name: system/lib/libkeystore_client.so +SHA1-Digest: gHZPh7PIN4pfyTol4+H0f8RkMIc= + +Name: system/lib/libgemini.so +SHA1-Digest: gOcIcvsHIy1bJWm5yhohGdlDbpc= + +Name: system/lib/libz.so +SHA1-Digest: RalaGOwZWuxB6e0enf5eK61HlGY= + +Name: system/bin/requestsync +SHA1-Digest: rYhU5wsWgx+19p9hyVYoPtrvMhQ= + +Name: system/etc/security/cacerts/111e6273.0 +SHA1-Digest: p+zFXiO2e0tv0nws8olvT8Aek/M= + +Name: system/lib/libcneapiclient.so +SHA1-Digest: QNV1EkKHUFtXhshGKIaG1KdV2Aw= + +Name: system/etc/cir.img +SHA1-Digest: Pv8H10C1z+OkuPHHrvyhWoDXHa4= + +Name: system/etc/security/cacerts/e60bf0c0.0 +SHA1-Digest: J9pHPWumPXu348/ay/6TIhWXEQE= + +Name: system/customize/resource/allapplication_20210.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/tfa/recorder.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/etc/firmware/a300_pfp.fw +SHA1-Digest: iZ2/rUgSCElxz8H/MPBqS0XC00w= + +Name: system/media/GPU/twoToneMaskV.bmp +SHA1-Digest: qwqnegSS7y93ykkmEFdP7tHZtyM= + +Name: system/etc/security/cacerts/3ad48a91.0 +SHA1-Digest: fiM/NEifCut6APMA4lYBH+/tUUA= + +Name: system/bin/amix +SHA1-Digest: Lg4AgytLAT1XL4Quw5iGXn6xMzA= + +Name: system/media/weather/weather_l_rain_day.mp4 +SHA1-Digest: cSHTqHnmLVRhBBag4G8h4DbdqLM= + +Name: system/lib/libposteffect.so +SHA1-Digest: 5vfal77EdZb0zL1jlPLNvFnLXiU= + +Name: system/lib/libmpl.so +SHA1-Digest: +KnVDngG0CrNz9dw+RzM6ESoK5I= + +Name: system/etc/init.qcom.post_boot.sh +SHA1-Digest: Vxokp11pfAjDvLmIyoM2zDinMak= + +Name: additions/camera_4.2/app/GalleryGoogle.apk +SHA1-Digest: gt/HaSMaax3cwQru6AIYZeKqO0U= + +Name: system/etc/bluetooth/main.conf +SHA1-Digest: oKXWcTolFUhYL4eb8XNIXgyN6U0= + +Name: system/tts/lang_pico/fr-FR_nk0_sg.bin +SHA1-Digest: FJvhnnxrIuE3NSTkPFjQuepe1yM= + +Name: system/etc/security/cacerts/3c860d51.0 +SHA1-Digest: NEjSItc3RYcgBxmnDxIXD4Eqy28= + +Name: system/app/IMEXT9Polish.apk +SHA1-Digest: D0HDPAVrREjfPVIvMetnGFwDkM8= + +Name: system/bin/vmstat +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libemoji.so +SHA1-Digest: ro9Wy2cWrVaEF7WL/VsSImLw+eQ= + +Name: system/lib/libstagefright_soft_mpeg4dec.so +SHA1-Digest: 6m3nwfqE2lzAHywZd399wMqUqdE= + +Name: system/framework/framework-htc-res.apk +SHA1-Digest: cHhXGxL1Bit3kEGMReLkRKv9mZY= + +Name: system/app/SenseTV_Home.apk +SHA1-Digest: ZwkB+dw2a8USrWwDZrZinBq9mZI= + +Name: system/media/weather/weather_windy_day.mp4 +SHA1-Digest: ZLybKR1cVR2AjjduU4w8W03JdI4= + +Name: system/app/HtcAutoRotateWidget.apk +SHA1-Digest: nRZ6dYR58M1KJW7iIOlAs7Vh+wk= + +Name: system/lib/libwt6hpprndrv.so +SHA1-Digest: gs9ftbIQwJEvPSmL9OiGnAPfYWs= + +Name: system/media/audio/alarms/Rajah.mp3 +SHA1-Digest: q8fZq/jLjgh9NUgdj0p2EcI19Wg= + +Name: system/etc/PCTOOL.ISO +SHA1-Digest: 1WrLSM00uaSV+bli/JaER4GiHxk= + +Name: additions/fonts/ubuntu/Roboto-Italic.ttf +SHA1-Digest: 60VoOZG3a5twaesOqklAVrUI+0M= + +Name: system/app/Stock.apk +SHA1-Digest: rx/aMR9X65no6sz6Wo7oE8XACLs= + +Name: system/lib/libsystem_server.so +SHA1-Digest: /Im4WYgHrNYlzJYiUlvv7dALZHs= + +Name: system/etc/security/cacerts/9339512a.0 +SHA1-Digest: hsOnlnqeX401dhi0nNmDk65W+/4= + +Name: system/bin/charging +SHA1-Digest: 7Q3Uinh9xZxprO9bV24Y9CQfEpQ= + +Name: system/app/LMW.apk +SHA1-Digest: pOpNe/0BO1uawsc1QyxikRzZp50= + +Name: system/app/IdleScreen_Photo.apk +SHA1-Digest: Ede9u3EENvWWeoT+VZpUWOym1oE= + +Name: system/bin/racoon +SHA1-Digest: wVXHHRCSsQ869NYoXil5UeO9NLE= + +Name: system/etc/permissions/android.hardware.wifi.xml +SHA1-Digest: 2QUUSx+bDnRPeI0RKInztkPY0L8= + +Name: system/bin/netstat +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/usr/srec/en-US/g2p_fst +SHA1-Digest: 56BTKRSLceP1JQBIw26sU7rnRg8= + +Name: system/etc/security/cacerts/f80cc7f6.0 +SHA1-Digest: KIRiP3e2KnZuw1n5MOiP4r/DfXo= + +Name: system/customize/resource/allapplication_20810.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/app/GoogleCalendarSyncAdapter.apk +SHA1-Digest: LxmcE/37BL8GjgTkGPTeqtgK8j8= + +Name: system/etc/security/cacerts/69105f4f.0 +SHA1-Digest: +kWiVJ8jvMUCSABOD1q0wrmOwls= + +Name: system/etc/bluetooth/input.conf +SHA1-Digest: Tgwt4ltLhyMYLAEDfZMe0/GHQ8c= + +Name: system/etc/image_ibeats_solo_v2_2vol.bin +SHA1-Digest: Eoz94iefZEs4CIG3BXZhUHJe8WI= + +Name: system/lib/libwfduibcsrcinterface.so +SHA1-Digest: Tog4xhqnS/g2J9quFS8OzjcNjOI= + +Name: system/customize/resource/allapplication_23420.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/lsmod +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/security/cacerts/5cf9d536.0 +SHA1-Digest: TwWGlhUS/XyYTVbiXyDEu4yCHOk= + +Name: system/app/HoloSpiral.apk +SHA1-Digest: IUpd9tg3DlDsFiYOf7PajFQwl0s= + +Name: system/bin/reboot +SHA1-Digest: I8x9/T8IJUHst+9mTffQBrfKN7M= + +Name: system/lib/hw/audio.a2dp.default.so +SHA1-Digest: FDO/HUlaoEEXyLWt63JcGJ5udNM= + +Name: system/media/GPU/header8bpp.bmp +SHA1-Digest: VlMyBckc5chNrS2FChiEEZgZQ6Y= + +Name: system/etc/firmware/fw_bcm4335_b0.bin +SHA1-Digest: s8ujoESTcrSfW/Q17UP/DzlEQo8= + +Name: system/lib/libchromatix_s5k3h2yx_default_video.so +SHA1-Digest: xptMw90p6xZ2RzEtQAPHLcTN8mM= + +Name: system/lib/libstagefright_soft_vorbisdec.so +SHA1-Digest: W51bwn8wsBJwbuDL6joCynE7wdQ= + +Name: system/etc/tfa/voip_l.config +SHA1-Digest: HKUbwkwyeWNkWCWTnAgcEbOJbpQ= + +Name: system/lib/libchromatix_vd6869_zsl.so +SHA1-Digest: qWd+XgpNdHAFrnvMALbUN8XeK3I= + +Name: system/bin/htcfs +SHA1-Digest: VGSiL+tb6f3B8/ivAw5HYmejx3g= + +Name: system/vendor/pittpatt/models/detection/multi_pose_face_landmark + _detectors.7/left_eye-y0-yi45-p0-pi45-r0-ri20.lg_32/full_model.bin +SHA1-Digest: 2RO6gFG2Qc2bgM8YcmcjeX1ieuI= + +Name: system/etc/security/cacerts/fb126c6d.0 +SHA1-Digest: IWQN7rJtQQHN57H5dd6OTOg45Bw= + +Name: system/usr/srec/en-US/rescoring_lm +SHA1-Digest: 6GyGVA+P2g8W+DkDc/dPWTIDcmc= + +Name: system/customize/resource/allapplication_21403.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/customize/resource/allapplication_23806.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/init.d/96Tweaks +SHA1-Digest: TG6FqP4J/ntSWhsMi7UbHvNu4TU= + +Name: system/etc/security/cacerts/ccb919f9.0 +SHA1-Digest: GrKodXYQ6yyhwcC2Aeon0asWWHI= + +Name: system/usr/srec/en-US/ep_acoustic_model +SHA1-Digest: 8PLUJrKu4KdJRfExvDQgyCW3w0I= + +Name: system/app/HtcGpsWidget.apk +SHA1-Digest: AnCbMYFFCqRFRbNXemf4va+/Et4= + +Name: system/etc/media_codecs.xml +SHA1-Digest: agzpZ6xk+1LUBBa36hVb4jmDDyY= + +Name: system/lib/libwfdmmsink.so +SHA1-Digest: CGU26anRhWWwYn0WjI9S7dfaNM0= + +Name: system/etc/tfa/voip.config +SHA1-Digest: HKUbwkwyeWNkWCWTnAgcEbOJbpQ= + +Name: system/lib/libui.so +SHA1-Digest: 5U4hil0vCG9HBfXWgCu221wqw0s= + +Name: system/etc/security/cacerts/19899da5.0 +SHA1-Digest: +UmV9YdO6tXmnuyAqdwmaQRUjag= + +Name: system/lib/libfrsdk.so +SHA1-Digest: zCAgqawgYyfceORBN6OdlzJInBI= + +Name: system/usr/share/partials/partials_CW_gb.csv +SHA1-Digest: 46+b7bjNw9xCRwVfWEiE8Mqc9DY= + +Name: system/etc/security/cacerts/bf64f35b.0 +SHA1-Digest: C9BPEBWg6QPfoVIADHUCxuXpPo0= + +Name: system/lib/libchromatix_ov2722_default_video.so +SHA1-Digest: 4Mi4hBE3vUoS6H+bRiuKwI8eWew= + +Name: system/lib/libOpenVG.so +SHA1-Digest: +Uwi23fBjZ/WXyYXHGpf6XbA6DA= + +Name: system/media/audio/alarms/Topaz.mp3 +SHA1-Digest: zCYU22lanMN0X9Q8U2lXEDHfej4= + +Name: system/lib/libmm-color-convertor.so +SHA1-Digest: EOBxEHhZUDgBEwwNoMughtDuXs4= + +Name: META-INF/com/google/android/aroma/themes/sense/select.9.png +SHA1-Digest: /S9wdSsjM2HOisLSogibe57BvD4= + +Name: system/etc/security/cacerts/ddc328ff.0 +SHA1-Digest: rQJV0QS5EjB+JDM0B2vSegD4f8c= + +Name: system/etc/hsml.key +SHA1-Digest: czCkPuRCXsueGicln2eH5xyAw3E= + +Name: system/lib/librtp_jni.so +SHA1-Digest: wOIppFTkyE7GJCxQKC/o+YQrf8I= + +Name: system/lib/egl/eglsubAndroid.so +SHA1-Digest: QNMdorgIk98JO9ln6ZZxeQVzhzg= + +Name: system/media/weather/weather_l_windy_night.mp4 +SHA1-Digest: Jdv//CAJ/HvFl6WXAUHqFRVcXL4= + +Name: system/usr/srec/config/en.us/models/generic11_m.swimdl +SHA1-Digest: N2jOonTixJLNBvuNMlZ1cmcMhzU= + +Name: system/lib/modules/eeprom_93cx6.ko +SHA1-Digest: l0W+6AxuGi+ZwQrSJbIoVEdXqCc= + +Name: additions/fonts/comicsans/Roboto-Regular.ttf +SHA1-Digest: 3H/7DHILeP5YaFf1M5+OGT5BQhM= + +Name: additions/fonts/asap/Roboto-Regular.ttf +SHA1-Digest: 2i3Y+rL5W0C8NRJuxSuGDpjzkGU= + +Name: system/etc/wifi/p2p_supplicant.conf +SHA1-Digest: gnijNFdlV/VI2tMxz7KcnFewPuA= + +Name: data/app/com.adobe.flashplayer-1.apk +SHA1-Digest: bHgFjf3MX8sSwyfwmcrGnWABh/o= + +Name: system/etc/ov2722_1 +SHA1-Digest: P8BRHTNEk4ZkOWaSvNi1nLT3aiM= + +Name: system/lib/libqdutils.so +SHA1-Digest: /7sCeTTYgSLJputfkQ6QspGJjT0= + +Name: system/bin/top +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/etc/media_profiles.xml +SHA1-Digest: x7T2Lt4eYUFpufhh9uFg3lIx+zo= + +Name: system/app/HtcBackupReset.apk +SHA1-Digest: Oj7hzUS+QtPFaQgTK+VY7slW7EQ= + +Name: system/etc/tfa/recorder_l.preset +SHA1-Digest: ZIWhTsSVk2FQh+JqEczz/+vRDeQ= + +Name: system/customize/resource/icon_launcher_active_sync.png +SHA1-Digest: J9ZTXgbThiTNedL+9nw3jv24TCY= + +Name: system/etc/security/cacerts/72f369af.0 +SHA1-Digest: kDG+4qnGpf1LhqDTY1b++EDoMAI= + +Name: additions/gps/asia/etc/gps.conf +SHA1-Digest: bV8Qal0r4TZ65mrlH4e8lb9rNnA= + +Name: system/lib/libchromatix_s5k6a2ya_preview.so +SHA1-Digest: cWtBl0zWUbjPDYhGEZ2oPX3siWY= + +Name: system/media/weather/weather_clear.mp4 +SHA1-Digest: xMbQ70LkzOLa0YMCMdg7A+CT+1w= + +Name: system/customize/resource/icon_launcher_yahoo.png +SHA1-Digest: 4zrDzP2De2eCAV3wpPQm4zvfDy0= + +Name: system/media/audio/notifications/Magnolia.mp3 +SHA1-Digest: GpiUgNJ/bR6utCxj4xjpN9R+Lf4= + +Name: system/media/audio/ui/Lock.ogg +SHA1-Digest: m1O0ZlYq8HMVfUAz7JuG28NXwxQ= + +Name: system/framework/core.jar +SHA1-Digest: YDmBWCkWD+seFvQPPfqB2Lvd9SA= + +Name: system/media/zchgd/batt_50.rle +SHA1-Digest: bW741QkPmOXetEgJpp4vweToIek= + +Name: system/lib/libwfdnative.so +SHA1-Digest: wENU8g3NkgFpB5FuSptJyyZA3PE= + +Name: system/customize/resource/allapplication_232.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/framework/ime.jar +SHA1-Digest: GSJ7k17MSlHYXqvj3qzwNsGsCic= + +Name: system/customize/resource/quicklaunch_26806.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: META-INF/com/google/android/aroma/icons/apex.png +SHA1-Digest: akhGWuuQ3xUBorLR4mvPN1cXAvk= + +Name: system/etc/security/cacerts/b7db1890.0 +SHA1-Digest: 2szR4UBPkIHU3s5s690BvX+1zuk= + +Name: system/lib/libloc_api_v02.so +SHA1-Digest: 0xAwh+xAT+JiDuK10Bbn6ZWrKkM= + +Name: system/etc/security/cacerts/412bea73.0 +SHA1-Digest: IzFpXikosbCidRWhJIDcs/X7LNA= + +Name: system/lib/libwt6pptxrdr.so +SHA1-Digest: RoDj8twq/34sEZHJle4yIs6rtNw= + +Name: system/app/SharedStorageBackup.apk +SHA1-Digest: c7xODp2TjlAprh8YxZTtzPLHGUs= + +Name: system/lib/libstagefright_yuv.so +SHA1-Digest: 0HToHiT/n1mTKB1vCZbwVEWOEAQ= + +Name: system/framework/modemwarmup.jar +SHA1-Digest: QQd4sRTzCLMS2dENDFw6qm6THr4= + +Name: system/app/HTCBackup.apk +SHA1-Digest: aR4ER4pzg7XGMPZ5pMMpXK8uzts= + +Name: system/usr/idc/synaptics-rmi-touchscreen.idc +SHA1-Digest: 6JEfMdlyDan77GFkNoKg2WEZEZk= + +Name: system/usr/srec/en-US/c_fst +SHA1-Digest: V2x/Tax3DLB7jG4K359SkvtizQ0= + +Name: system/app/Prism_LocalFeedProvider.apk +SHA1-Digest: 2rPadGHal7rS0Cp2c/Ti5U0yGwY= + +Name: system/etc/tfa/playback_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/bin/logcat +SHA1-Digest: z4Byfm16+LdHBseQivHnr82RK0I= + +Name: system/bin/mke2fs +SHA1-Digest: kNU14h7raZkOtasdoo/GnbEf3Qk= + +Name: system/lib/libnotes_jni.so +SHA1-Digest: OIOZFKTyfXCPkI8VvcPECpknkZA= + +Name: system/etc/hltrd.bin +SHA1-Digest: Ym1kH+mpPRnjJ7Xz9MTNHjTf1kU= + +Name: system/lib/libspeexwrapper.so +SHA1-Digest: M3sx2CRBxoNO4l9n0UKt3WuTXXc= + +Name: system/bin/dumpstate +SHA1-Digest: SLgxmRplJdnOoTf84QRtuQN6u/M= + +Name: system/usr/share/partials/partials_H_gr.csv +SHA1-Digest: x3H1K0s8nIfhStMBJ1ml3INv6g4= + +Name: system/customize/resource/quicklaunch_26803.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/AlarmGroupQueueList.xml +SHA1-Digest: vrBNOXzkLD/tVWD6+YeqblgEr+c= + +Name: system/bin/mkdir +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/HtcLockScreen.apk +SHA1-Digest: kS35HRJ7v13teUc1lNZ4nBQ4xBg= + +Name: additions/fonts/comicsans/Roboto-BoldItalic.ttf +SHA1-Digest: JGZVL5b7jSLrk3LMJK7phFPyg8s= + +Name: system/fonts/DroidSansFallback.ttf +SHA1-Digest: PsxABdyJmBV/NOdZluIGqPPzIT4= + +Name: additions/fonts/comfortaa/Roboto-BoldItalic.ttf +SHA1-Digest: /35z/1Nkw4zfuX4GbhNRmxDFhkc= + +Name: system/etc/security/cacerts/1920cacb.0 +SHA1-Digest: R7QRICoLwPUp6AhMzbXPpFGE8ho= + +Name: system/media/GPU/stylizeColorRamp.bmp +SHA1-Digest: ssv57ZtVn6dDDbUW1MzY1avYzuE= + +Name: system/app/FilePicker.apk +SHA1-Digest: rjMNoC24q2QK/alv/idtkd6Q8qY= + +Name: system/app/DefaultContainerService.apk +SHA1-Digest: OBlxwCyVH7+0FXG1WyZ2Ze2SjV0= + +Name: system/lib/libbinder.so +SHA1-Digest: kQLYdUwx2/oYFVuL33d9z+ngSyg= + +Name: system/app/MyDropbox.apk +SHA1-Digest: al9MGR+POmf9Jx5Gtt+IyhhZYGE= + +Name: system/app/HtcDataRoamingWidget.apk +SHA1-Digest: vB96sxPiIF7MuG+CmWmMrCCiC70= + +Name: system/lib/libmmjpeg.so +SHA1-Digest: EDqj9jj2hfC342UyVdAM+WINqeM= + +Name: system/lib/libchromatix_s5k6a2ya_zsl.so +SHA1-Digest: 9nKEs/Z8eTiBlkha6y7H0gE1tIs= + +Name: system/etc/security/cacerts/9dbefe7b.0 +SHA1-Digest: EPhp4B4/b2pUwm0D3ZjC5np6RpI= + +Name: system/lib/libalbum_util2e.so +SHA1-Digest: oVM2Wt1z5ZolHFY/F0CsUUTmYu4= + +Name: system/etc/init.qcom.fm.sh +SHA1-Digest: C08X0QRMGyiedbHR/ucZ1NMa2cA= + +Name: system/customize/resource/allapplication_65501.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/2afc57aa.0 +SHA1-Digest: EkhgecDeewZKqIaZMoXgIPqbsQM= + +Name: system/customize/resource/quicklaunch_20810.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/HtcAccessoryService.apk +SHA1-Digest: 3B1ejiyaEa0j85AFUAkdDuKOkRA= + +Name: system/etc/security/cacerts/343eb6cb.0 +SHA1-Digest: O+vAjCl4L2DEpmcXgqljeBNzRgw= + +Name: system/customize/resource/quicklaunch_23806.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/CalendarProvider.apk +SHA1-Digest: AOHTj3KmClCZGyGUhqotz/fJxWM= + +Name: system/etc/permissions/com.playstation.playstationcertified.xml +SHA1-Digest: nVjSmkPikQF9xTTZo1SgdBSvYGI= + +Name: system/bin/service +SHA1-Digest: 6nGxxM9K+Xtwnat7jFsVFcLulG4= + +Name: system/etc/security/cacerts/3e3744fd.0 +SHA1-Digest: vASvqfaKbXK7xfFL5JUfZnMLtWM= + +Name: system/media/audio/alarms/Scarlet.mp3 +SHA1-Digest: YHmfzFkL4rPX2or9InI5c4mFqsE= + +Name: system/bin/ois_camera +SHA1-Digest: iTIUECc95oRWv2lEYh9jBBr+YfE= + +Name: system/app/HtcPhotoEnhancer.apk +SHA1-Digest: qjz+FJdwOC/eMXKo0nlWYTHExH0= + +Name: system/etc/security/cacerts/2edf7016.0 +SHA1-Digest: qaI/Jledqev96e95cWVbRtxDzdA= + +Name: system/lib/libI420colorconvert.so +SHA1-Digest: 54LKYxmGJX3Ns5+wbfRGSv7rjr0= + +Name: system/media/audio/notifications/Regalia.mp3 +SHA1-Digest: dOguRyeA7e/c4z49OKdm5EJfAlw= + +Name: system/etc/soundimage/srsfx_trumedia_movie.cfg +SHA1-Digest: L9EmttwiCIxAPEQCWKJ2RZCQgS0= + +Name: system/app/Automotive_Home.apk +SHA1-Digest: WLXPdpZG4OolaFoakS6bQBprnk8= + +Name: system/bin/servicemanager +SHA1-Digest: mzGF2ORzj7Zt7Jexmxtoti+JXoQ= + +Name: system/lib/libhtcflag-jni.so +SHA1-Digest: CXC2Uvdw0yuip74h8yZJPy0LIQg= + +Name: system/etc/security/cacerts/0dbd0096.0 +SHA1-Digest: wOf/ufGVHjhFv2iS9c0YutoTNhQ= + +Name: system/media/audio/ui/KeypressSpacebar.ogg +SHA1-Digest: W5H8TwiuPBEoXIq85+hJWUrkOVU= + +Name: system/usr/share/zoneinfo/zoneinfo.idx +SHA1-Digest: m5//InzwugFOH2ZQxTdoK+x2MMk= + +Name: system/lib/libqmi.so +SHA1-Digest: GaIMAMkZUnA77cUvBF9PdtrkREA= + +Name: system/customize/mns_map.xml +SHA1-Digest: xWmNWm5qkKwdkxxKDxT1cj8LD/I= + +Name: additions/camera_4.2/lib/liblightcycle.so +SHA1-Digest: kXD0YGYtnvaYnWMUVS/i+J6w3uU= + +Name: system/lib/libvideoeditor_jni.so +SHA1-Digest: xdDGtjaE4KpmVRrmed8Z3VRsW9I= + +Name: system/customize/resource/rp_ce_0682_i.png +SHA1-Digest: MPFDvWPN/dtjToDg0dFEd+j3ql8= + +Name: system/media/audio/alarms/Flame.mp3 +SHA1-Digest: xxKH8avP+cwPx+keF0OhlAmDu4A= + +Name: system/etc/RT5501 +SHA1-Digest: AMGLnOuJ9+oyGb/krqH7tDbrnQk= + +Name: system/app/Tube2_Configuration.apk +SHA1-Digest: L0mn/dA8Pll++KWx87hmLnJEWWs= + +Name: system/lib/modules/scsi_wait_scan.ko +SHA1-Digest: m/QV2ZO8XJ6InW3js0Y2qPre0z4= + +Name: system/framework/services.jar +SHA1-Digest: E/WZFm9MDDcX6VEwKFofwew1Qzk= + +Name: system/usr/srec/en-US/phonelist +SHA1-Digest: UXoRA4i+4slLvj7BwxfVXzFgK0Q= + +Name: system/customize/resource/allapplication_420.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/lib/libchromatix_vd6869_zoe.so +SHA1-Digest: +Tf9eE+qWHPG9r++iQhaaOAEX8Q= + +Name: system/bin/hostapd_cli +SHA1-Digest: PUbMwiu76TGMgof3OlFG8idyEOU= + +Name: system/etc/init.qcom.coex.sh +SHA1-Digest: Qn0udCSEPgfUvHcL8pWOad4QERI= + +Name: system/lib/hw/gralloc.msm8960.so +SHA1-Digest: Z2T9uIST+h4d20R9ihin3+Yx0zE= + +Name: system/lib/libAudioTrimmer.so +SHA1-Digest: 2ol/zGXeF7RhaSxT161h5a2i+fc= + +Name: system/media/zchgd/charging_01.rle +SHA1-Digest: 5sXmisNHh+5iyc5fMW1QUefvkHw= + +Name: system/vendor/firmware/libpn544_fw.so +SHA1-Digest: 2TS1uqpe82e/P2sHI7H75nr0m4Q= + +Name: additions/seeder/app/Seeder-2.0.0.apk +SHA1-Digest: AmhI8h/aTClfVVdvzRH4qkpikog= + +Name: system/etc/tfa/voice_l.preset +SHA1-Digest: OVBiITpEEwnpRzjGcCTdTkgmGA4= + +Name: system/lib/libdl.so +SHA1-Digest: 3txFCvD04/L1VxTwEe7XrVqYLIE= + +Name: additions/fonts/ubuntu/Roboto-BoldItalic.ttf +SHA1-Digest: XTo42R6xZv0bq2wDzQz0PvlqM6s= + +Name: system/bin/adaptive +SHA1-Digest: E8tsEwE7cmroacvJPUvSP/NEf94= + +Name: system/etc/security/cacerts/b413391d.0 +SHA1-Digest: lehk0//w6Yyx1L2BnNMZoRZKluc= + +Name: system/usr/srec/en-US/metadata +SHA1-Digest: YPYK5NG59a30DaQyjp8lHVJfo48= + +Name: system/app/Talk.apk +SHA1-Digest: HPyifh93uiJhKS4VINUBUsY9WEE= + +Name: system/etc/tfa/playback.eq +SHA1-Digest: ioyR7ioJoO6yab62er4b74v4YhQ= + +Name: system/usr/srec/en-US/contacts.abnf +SHA1-Digest: 7OXPIU1ePgerziVbKoBu2RcikeA= + +Name: system/etc/libpmhwrl.so +SHA1-Digest: Jnedoe4Se6fF59bMDc4y2eybuk4= + +Name: system/tts/lang_pico/de-DE_gl0_sg.bin +SHA1-Digest: AqYOydFO+UHIftz1QE8h+6cjU+s= + +Name: system/customize/resource/quicklaunch_232.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/libandroid_simlock.so +SHA1-Digest: LLT7TC7NOhRDAM+LC2OLdzQPXw8= + +Name: system/usr/share/zoneinfo/zoneinfo.version +SHA1-Digest: C3jhoc/P5UgYjouhc4bZw3TcmeA= + +Name: META-INF/com/google/android/aroma/icons/info.png +SHA1-Digest: cUFToRrZ3Xv7BsscGsCW8a+wXXQ= + +Name: system/media/audio/ringtones/Ocean.mp3 +SHA1-Digest: n+GLdCDo7g9/CpQgj1iTVDHShHo= + +Name: system/app/HtcVideoPlayer.apk +SHA1-Digest: teXCH7b33Grv7XPWz/bkfA3M8hM= + +Name: system/lib/libmmmpod.so +SHA1-Digest: 84nlFZD8ykNNOWejAY303ZpNPhM= + +Name: boot.img +SHA1-Digest: P3rDJfT3UeB6sdl8RKM4VFyDiGk= + +Name: system/lib/libsqlite.so +SHA1-Digest: /fiK6C43s8RwQjvRV9QuKdZly3A= + +Name: system/etc/AudioBTID.csv +SHA1-Digest: Gqh/UYdUamQ0hhKaMR4rftiJS6M= + +Name: system/etc/permissions/android.hardware.camera.front.xml +SHA1-Digest: UHlHrvWjU+j2mP35N5eTTCJsGKo= + +Name: system/customize/resource/quicklaunch_24201.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/lib/libzeroeditor_core.so +SHA1-Digest: S2HmhIBOoZbCFQnsOCoCCb1uDSg= + +Name: system/etc/permissions/com.cisco.anyconnect.permissions.patch.ht + c.xml +SHA1-Digest: +2+iPfdnszYMIo0aZVtE47s5XHU= + +Name: system/etc/security/cacerts/58a44af1.0 +SHA1-Digest: t3CGdgkkwdvHlDpdrK1fU2hm7VM= + +Name: system/etc/security/cacerts/1155c94b.0 +SHA1-Digest: s4MqqrFEF/72+iq+wIGqr5PcZAs= + +Name: system/etc/security/cacerts/12d55845.0 +SHA1-Digest: Dl66XTBMvMhwxbJmyV6GBJ6brpk= + +Name: system/lib/libwilhelm.so +SHA1-Digest: e6ZCFDPcd9H6HnF8UgX8MNZ+QPg= + +Name: system/etc/permissions/com.google.android.media.effects.xml +SHA1-Digest: 1ymq8QA4Aky6u6O7KNmEtnQRsho= + +Name: system/fonts/DroidSansDevanagari-Regular.ttf +SHA1-Digest: rcDk7w2X12yWFtec3dheokLZP7Y= + +Name: system/customize/resource/quicklaunch.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/media/zchgd/charging_07.rle +SHA1-Digest: EXqLHmDATH06bTfx8yaOikW1qOE= + +Name: system/app/GooglePartnerSetup.apk +SHA1-Digest: ztiFVIJXpgHa+MR5KZopt6qvb88= + +Name: system/lib/libclcore.bc +SHA1-Digest: B1+4TwzZ4lL0Qb/Ord20AIlruwk= + +Name: system/lib/libclcore_neon.bc +SHA1-Digest: OR0PB7cN5Otkgd4lrNXFsT8DheM= + +Name: system/customize/resource/wallpapers_b_04.jpg +SHA1-Digest: KAgiQy4/IH7XzoWjWCoFsbh6XIk= + +Name: system/bin/lsof +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/bin/cand +SHA1-Digest: 7Ggz8CRViN4vqDOtYfvbnI29HB0= + +Name: system/lib/libpdfviewer.so +SHA1-Digest: uFCKw2Nb8ECjcEWdQkAJFGqvw00= + +Name: system/lib/libfacelock_jni.so +SHA1-Digest: ZWJMjaHj8gmUvAfIPm5jmo1xn68= + +Name: system/lib/libmedia.so +SHA1-Digest: WPtRnRat1cE5UF+1GqobEPo38uE= + +Name: system/lib/libfilterpack_imageproc.so +SHA1-Digest: roc4s57JfSFjG5jjNCmzOw9Vhg0= + +Name: system/lib/modules/bluetooth-power.ko +SHA1-Digest: H/+LuShLo0Q+gqT686s1uhoNqI8= + +Name: system/usr/share/partials/partials_H_bb.csv +SHA1-Digest: 3Q3qT2QP7+oby0sCeg2DVnX33jI= + +Name: system/usr/share/partials/partials_CW_bb.csv +SHA1-Digest: N+ejER4kXRjOwMUkDjEY+gWIdGk= + +Name: system/lib/libmm-abl.so +SHA1-Digest: TpzopUDSJmY3Pl7IuMQOUta+ioA= + +Name: additions/fonts/asap/Roboto-Italic.ttf +SHA1-Digest: sVPgPJUSOxnZgqIoFaGvCU/vRNw= + +Name: system/app/PluginManager.apk +SHA1-Digest: I/RRszMgfSJurTtjA2QmtunTz70= + +Name: system/app/Prism.apk +SHA1-Digest: Ud6S/8tldGhCLUt/aqidkCzD5Zo= + +Name: system/vendor/firmware/mfg.bin +SHA1-Digest: h+7kLgkbGybwIyGt6Vpej2Nj3Lk= + +Name: system/etc/system_fonts.xml +SHA1-Digest: +AFAJEzDoN8rlf6Jboc5EHuDwFg= + +Name: system/customize/resource/quicklaunch_262.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/IMEXT9Latvian.apk +SHA1-Digest: VQ6ZPnIux+tkpe9+02XXXDOjbVM= + +Name: system/lib/soundfx/libreverbwrapper.so +SHA1-Digest: jPJNweOjdXsN6nEnRUilEtgbca0= + +Name: system/fonts/DroidNaskh-Regular.ttf +SHA1-Digest: UlmKZJTwpi0qnPC8KApnbHJiosQ= + +Name: system/etc/permissions/android.hardware.usb.host.xml +SHA1-Digest: Na0AbBFcnB2Br8zB+hMI2Y53zys= + +Name: system/app/Flickr.apk +SHA1-Digest: xCptiwsZYo3Pw09cDQISxZiL/Q0= + +Name: system/lib/libmmcamera_hdr_lib.so +SHA1-Digest: 3aF4x20mC2yzZmdSW/vWhEBkgHA= + +Name: system/customize/resource/quicklaunch_26801.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/snd_soc_msm/snd_soc_msm_2x +SHA1-Digest: a1cCYKU154XoMVmsXqQz9Fl2vYg= + +Name: system/app/CIMEXT9.apk +SHA1-Digest: Lnkp0+G9zpJKidHwb0tWwlKkXJg= + +Name: additions/fonts/comfortaa/Roboto-Bold.ttf +SHA1-Digest: G2bLol7a6Kcue8P7a+sLda6U/Bk= + +Name: system/app/HtcSoundRecorder.apk +SHA1-Digest: uVWOQYl9J11LcW74S3J6y5nR1UU= + +Name: system/media/audio/alarms/Gold.mp3 +SHA1-Digest: EyYq1nhqZ6Qr8HGJZFNbC9RcUmE= + +Name: system/etc/audio_effects.conf +SHA1-Digest: UIu/6M+4Z9jE0VBhYxYIt5hQoJY= + +Name: system/customize/resource/quicklaunch_21401.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/etc/image_ibeats_solo_2vol.bin +SHA1-Digest: nvzAjLdyidqP8V4UNUiSmf5Kn24= + +Name: system/framework/pm.jar +SHA1-Digest: e++O044GpPSgchnVlOlDHQNlCM0= + +Name: system/app/NoiseField.apk +SHA1-Digest: uXjJo3Y4nTwxe4lxfomzOq+T1H4= + +Name: system/lib/libdiag.so +SHA1-Digest: f6EADf0JxGJE7eXW/Kew6jGMv8k= + +Name: data/app/com.twitter.android-1.apk +SHA1-Digest: xiDcu9vlE4kYb93vu33DeaK4Sv4= + +Name: data/app/com.google.android.googlequicksearchbox-1.apk +SHA1-Digest: 5jVjrlDZyL8HLRl3zoedJ4f97Ag= + +Name: system/bin/toolbox +SHA1-Digest: j3eLJl1JFEoS/ACfsVGQlX/uAIo= + +Name: system/customize/resource/allapplication_63102.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/eb375c3e.0 +SHA1-Digest: tmCwIHz56faNDn0roOj08Yyrv0E= + +Name: system/lib/plugins/com.adobe.flashplayer/libysshared.so +SHA1-Digest: TB891nh0tUUz+nsrHzpoSik8nMA= + +Name: system/lib/libwfdmmutils.so +SHA1-Digest: uqKruruA4V3poQY7ppuWmLo/te4= + +Name: META-INF/com/google/android/aroma-config +SHA1-Digest: 5tmXTnBNRM+FTnbgvU4Zvw7eBIs= + +Name: system/etc/nfcee_access.xml +SHA1-Digest: TgL7tDwvgXVKDC/jEltr/83iPPQ= + +Name: system/app/IMEXT9French.apk +SHA1-Digest: SFH+luypioo+vXtpj43SuSlCz+I= + +Name: system/framework/com.google.widevine.software.drm.jar +SHA1-Digest: +qbuOxdtyIu/AQZLR8qCxopyN90= + +Name: system/bin/ipv6tether +SHA1-Digest: 0RaTsspOHB3JLyn0o7zSLyfa9zM= + +Name: system/framework/com.htc.videowidget.res.apk +SHA1-Digest: MZEzmMO/yyYm/Hd0NPs4EnT33B0= + +Name: system/media/weather/weather_snow_day.mp4 +SHA1-Digest: Gpb/DamZOkmv7mv1p+FmsWDPM2E= + +Name: system/etc/tfa/video.preset +SHA1-Digest: gLyUQwAim17CsSVazvxBjmG77tQ= + +Name: system/customize/resource/allapplication_262.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/4f19d2b4.0 +SHA1-Digest: hr7OO548ug4ki+JB3UhR3NJvru0= + +Name: system/etc/security/cacerts/ea169617.0 +SHA1-Digest: smRXb6WPNBJ4NICRtncXV/vuQiY= + +Name: system/etc/security/cacerts/3d441de8.0 +SHA1-Digest: bswrWmxovthgf13lTWpmpt5/X/Y= + +Name: system/etc/security/cacerts/72fa7371.0 +SHA1-Digest: O84yTu+CcVyjxjgoAYqQZpR9xI8= + +Name: system/lib/hw/hwcomposer.msm8960.so +SHA1-Digest: qJPRtnt8wrlWZhBvP26iUbJRgEk= + +Name: system/lib/libcpt9.so +SHA1-Digest: CFtKbAxU+7cVGYLd7OUKqcvS2A4= + +Name: additions/exchange/app/Mail.apk +SHA1-Digest: 0/qoQPnDF6YXDnrq2lz+epbScbs= + +Name: system/etc/security/cacerts/facacbc6.0 +SHA1-Digest: /tkMzD2t5DcEEHz19euP7w+unGY= + +Name: system/app/HtcGetStarted.apk +SHA1-Digest: qldS5QI2yvvqGtn8+cd/kc+CgfQ= + +Name: system/lib/libprojector.so +SHA1-Digest: jRqmE7on2zuK8MDiMMm+IyxWcSU= + +Name: system/lib/libidl.so +SHA1-Digest: 52s99Y2Ue3P4p/awhXBDLP1kBmI= + +Name: system/framework/HTCExtension.jar +SHA1-Digest: hRs/1ZRv7AYJ5nsA8XY0Q0RhIJY= + +Name: system/lib/libcpt9provider.so +SHA1-Digest: 41+2Jxxgntz7iz5drfCm9n4aaoI= + +Name: system/lib/libhardware_legacy.so +SHA1-Digest: m/lX5JVU18gON9I58uopDEjWMwQ= + +Name: system/usr/srec/config/en.us/baseline8k.par +SHA1-Digest: cR3ErVVeWITO4QendRZRkkfChHc= + +Name: system/lib/libwt6prnddi.so +SHA1-Digest: lZ7gRr5kLfU2sV56wvXaht6T1GQ= + +Name: system/app/TwitterEngine.apk +SHA1-Digest: flZBqEpA4U9zeJR8sleiIunqrls= + +Name: system/etc/permissions/android.hardware.sensor.proximity.xml +SHA1-Digest: Ir4TfyGxk4QiuORZa9Esndgmxfk= + +Name: system/lib/libstagefright_soft_g711dec.so +SHA1-Digest: EuZ1FOfGI4lFfHFyj1P+higw4XQ= + +Name: system/usr/srec/config/en.us/g2p/en-US-ttp.data +SHA1-Digest: EeTucxvP4KvwmGxmWn6mzatobhQ= + +Name: system/bin/shutdown +SHA1-Digest: XsHDC1ougaip0TcxuKl4P0+2huU= + +Name: system/lib/libchromatix_ov5693_hfr.so +SHA1-Digest: W4iXehh+/IlJJ4UnIgvYGGOmPXs= + +Name: system/lib/libvariablespeed.so +SHA1-Digest: rPE11kp8EQzuXL+LD4kqpgM3ZDQ= + +Name: system/lib/modules/spidev.ko +SHA1-Digest: dTPqk0ahf3jMtL4rspKQ5btIQ+c= + +Name: system/bin/nl_listener +SHA1-Digest: 7rZrAjymyIKZLbaOCC3FnftsceA= + +Name: system/app/Stk.apk +SHA1-Digest: YM4/rYqam4Byd2uN3F78VbGxGoE= + +Name: system/lib/libnfc_jni.so +SHA1-Digest: lpxse3k8wgRK2PcZHFSlVKjDShE= + +Name: system/etc/security/cacerts/ccc52f49.0 +SHA1-Digest: 8vnIJSGmWI5J6d7i+2tVGHvD5i0= + +Name: data/app/tunein.player-1.apk +SHA1-Digest: 3ib4NtvpqV0edCJUZ8B3n5Ur8+g= + +Name: system/lib/libchromatix_imx175_zsl.so +SHA1-Digest: 2DtYs/3o06QSvTE1yRBoliZ08nY= + +Name: additions/fonts/comfortaa/Roboto-Italic.ttf +SHA1-Digest: FD5Rg9PAMNslUz8+KIO69W/UC4M= + +Name: system/framework/com.htc.socialnetwork.res.apk +SHA1-Digest: CzzNxbO0yf4O8kqfwyFwPra8eEE= + +Name: system/customize/resource/quicklaunch_20205.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/IMEXT9Estonian.apk +SHA1-Digest: eSzu36cr2HN9YAAPh6nWBDVTPx4= + +Name: system/etc/security/cacerts/d0081655.0 +SHA1-Digest: Ez6pwhMlUxmpGLkfoVyymK1LdBA= + +Name: system/etc/security/cacerts/34d760b2.0 +SHA1-Digest: 6JmKjb1sxRq4tbDi9K8OatWlBis= + +Name: system/lib/libspeexresampler.so +SHA1-Digest: QCU1ObIPcsMakYiBncBZCmaIxQ0= + +Name: system/bin/ds_fmc_appd +SHA1-Digest: tGFQUY5RWrDe8kvIIdzYY++b/mA= + +Name: system/etc/spn-conf.xml +SHA1-Digest: e4aOGIw34uYo5aZxeys5bXSTuLU= + +Name: system/etc/hldm.bin +SHA1-Digest: 9OvfF+g5Z1T11E7xlK6Lssdw9/c= + +Name: system/lib/libcamerapp.so +SHA1-Digest: xkMJP0WQbYup90m3RnuEmW16CGs= + +Name: system/fonts/DroidSansGeorgian.ttf +SHA1-Digest: qGy+CDCNRhdxla4YsZpnovwHGGM= + +Name: system/etc/tfa/fm_l.config +SHA1-Digest: mcDPznDmbQbzvQ1yOzfS3mAX2n0= + +Name: system/customize/resource/allapplication_250.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/etc/security/cacerts/c7e2a638.0 +SHA1-Digest: 9ya3Pspxo12STfIyX8NIsr5A/7c= + +Name: system/app/IMEXT9Finnish.apk +SHA1-Digest: wpW93NqfbJxg+9M8+eLcsQAUwH8= + +Name: system/bin/dumpsys +SHA1-Digest: AhelssiTpzulZJISDs3bQ1ZUv4w= + +Name: system/app/GoogleLoginService.apk +SHA1-Digest: PD9V04uBXIrFaZNr8YjfcBFKD78= + +Name: system/media/audio/notifications/Verdigris.mp3 +SHA1-Digest: mHsVS/jKDzfKdflpv7ThAWZlgno= + +Name: system/lib/libandroid_servers.so +SHA1-Digest: RFhR+vMZltpT5kluPQF4QyriPzE= + +Name: system/bin/hci_qcomm_init +SHA1-Digest: S0Xcr75dW5UGi6EBVe3gWlc2vd8= + +Name: system/lib/libmmrtpencoder.so +SHA1-Digest: aqv8kwkl8hT5s+RxW1KiqSGYETg= + +Name: system/etc/image_beats_wireless_bt.bin +SHA1-Digest: XFROhQCo3zqAvzn90oj42boldH8= + +Name: system/usr/share/partials/partials_CW_gr.csv +SHA1-Digest: +n5gUnrxus6DupV6WP7jVOZ2+6Q= + +Name: system/media/audio/ui/KeypressDelete.ogg +SHA1-Digest: bZEM7p2jzlwy0AICXAOSF3LdqGw= + +Name: data/app/com.estrongs.android.pop-1.apk +SHA1-Digest: i4qJTljs0jlro13CKAShhunMPbg= + +Name: system/app/Idlescreen_productivity.apk +SHA1-Digest: S3PZauHq6OnGehGz59PX4+oLFhQ= + +Name: system/customize/resource/quicklaunch_65502.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/app/MediaProvider.apk +SHA1-Digest: eaqUACetsBXAb751OaaMfTdRIg0= + +Name: system/bin/wmdsi +SHA1-Digest: j3eLJl1JFEoS/ACfsVGQlX/uAIo= + +Name: system/lib/egl/egl.cfg +SHA1-Digest: gSZVwUFEbiJSML4A429+nW64kQY= + +Name: system/app/HtcMusic.apk +SHA1-Digest: qbT7LnFTjplTIbmglp6mxnGq5kE= + +Name: system/etc/security/cacerts/11a09b38.0 +SHA1-Digest: WAuD+V8HYjv2J8L6RjLCvz0/eXI= + +Name: system/etc/security/cacerts/c527e4ab.0 +SHA1-Digest: Htxt63bTyJOKdCrkatkDPmVvkhs= + +Name: system/customize/resource/allapplication_21910.xml +SHA1-Digest: L0xGTJy9cj6vz50e6iHcjF8NhP0= + +Name: system/bin/adb +SHA1-Digest: FcAl3iUM+RfrW3qZNvY+B984JN8= + +Name: system/app/ContactsProvider.apk +SHA1-Digest: 5yOp0Wo/mGVibiWrI+150x4sv84= + +Name: additions/fonts/veggieburger/Roboto-Regular.ttf +SHA1-Digest: Wmfs/7ddF/Fbm10Rfh9eri+OtXo= + +Name: system/lib/libnetmgr.so +SHA1-Digest: OR7o3//BGAQOFrF01AtGo4xnRys= + +Name: system/etc/security/cacerts/95aff9e3.0 +SHA1-Digest: 1FyDHWZk97rejAOqX84plYw2Dik= + +Name: system/lib/libqc-opt.so +SHA1-Digest: 8mXjFG05pBbeyGHzO4DIPnpKDq0= + +Name: system/bin/ifconfig +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/lib/libalbum_imagelib.so +SHA1-Digest: EJJQtnePbvDVz1T4BuYk0x9U0yM= + +Name: system/xbin/dexus +SHA1-Digest: ZLa/57bXQry9uH3eqmezYVytmQs= + +Name: system/etc/security/cacerts/8f7b96c4.0 +SHA1-Digest: QfxKn6PfoE0C352mOtyffWA172I= + +Name: system/lib/egl/libGLESv2_adreno200.so +SHA1-Digest: AMIj/L6GRcJMr+gKGdO/hFwlM/g= + +Name: system/lib/libext2_blkid.so +SHA1-Digest: tMHS6rxl5aKI0GTBzy/jm6pwQ0A= + +Name: system/customize/resource/quicklaunch_20404.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/bin/bugreport +SHA1-Digest: 3+6f66+v91o3OCeBaHh4FwT8jQo= + +Name: system/etc/security/cacerts/58546a39.0 +SHA1-Digest: QKH0gKtdbsPsdzQ2/mfmfqKzaHM= + +Name: system/lib/libmmcamera_rubik.so +SHA1-Digest: FSD6HoU01NRtBXreaBBWRPKSKGc= + +Name: system/lib/egl/libGLES_android.so +SHA1-Digest: FHBVLd1WKuQEDAo+IOKaaJBCJJQ= + +Name: system/lib/libstagefright_avc_common.so +SHA1-Digest: 0sfq1IbkelkviReLiD8xJBwGbAQ= + +Name: system/lib/libchromatix_imx135_preview.so +SHA1-Digest: cQjiJ+LKCP7beE/dOhaVeenpXX0= + +Name: system/app/BrcmBluetoothServices.apk +SHA1-Digest: fVownm6g4lj70cO/9FbXZlgMIp8= + +Name: system/customize/resource/wallpapers_a_03.jpg +SHA1-Digest: A+IzIxm/nJelEphlXWCTj+wIaj8= + +Name: system/lib/libchromatix_ov8838_default_video.so +SHA1-Digest: w3BpqXKEPOooHvvZzefCfUgneYc= + +Name: system/lib/libVDRecognitionAPI-jni.so +SHA1-Digest: HRpasglAV3sgRYSiIHfsitDeIhc= + +Name: system/lib/libdiskconfig.so +SHA1-Digest: SHkL2KT2vlcd3JNpJtRBJT7Zt0s= + +Name: system/bin/md5 +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/app/Bluetooth.apk +SHA1-Digest: 2DYPNTgMoCdFyhAa/UfMZiwNqTc= + +Name: system/customize/resource/CCInfo.txt +SHA1-Digest: VmIGhE4OKzAsCZuOpz4o0riUTww= + +Name: system/lib/libmode10AutoTest.so +SHA1-Digest: ejW5BuSYaS+bt8Qnw0kJmDb7jkg= + +Name: system/lib/liblz.so +SHA1-Digest: Ub18k/qSmpblpCjeCzISinIxOGA= + +Name: system/etc/security/cacerts/f58a60fe.0 +SHA1-Digest: A9xf8h5F7uhACk3LuvV2KFpjaR8= + +Name: system/usr/keylayout/AVRCP.kl +SHA1-Digest: XnlMR1We/Ygio+9C2HOkzyIpbjQ= + +Name: system/framework/wimax.jar +SHA1-Digest: x9Te2YB5qgIxw8tEXQWZumcRE6o= + +Name: system/lib/libpolarisoffice_Clipboard.so +SHA1-Digest: 78uPvk3STomxiLln549Pu2U06hg= + +Name: system/app/GSD.apk +SHA1-Digest: +MuFIFeXNd2mYmcltiMADDy+fRo= + +Name: system/fonts/DroidSansTamil-Bold.ttf +SHA1-Digest: mKyxCfCv+wTh1xiep9O2FLktnPQ= + +Name: system/etc/security/cacerts/c19d42c7.0 +SHA1-Digest: xIy8/UfYWjSn64KCqIwcfN3P5J0= + +Name: system/media/GPU/mask_vignette_wide.bmp +SHA1-Digest: JYMBuLpGEVRVp4jEkZ8pQxrxunU= + +Name: system/etc/security/cacerts/3a3b02ce.0 +SHA1-Digest: I8WzZpsm5HGEorbt5jlzpTt3jQ8= + +Name: system/etc/image_beatbox_bt.bin +SHA1-Digest: W873c0G9gw4/bBA3L4yMLUX4FjU= + +Name: system/lib/libchromatix_ov5693_zsl.so +SHA1-Digest: K/dRA4kBAjUzZwWEu/Fxf844gmE= + +Name: system/etc/tfa/voice_l.config +SHA1-Digest: HKUbwkwyeWNkWCWTnAgcEbOJbpQ= + +Name: system/bin/setconsole +SHA1-Digest: 11upI/qC8hcBZzGoNKUNuTk10Q0= + +Name: system/media/audio/ringtones/Eggshell.mp3 +SHA1-Digest: 1c50J3YQkiGr8FRkZ28W5ZpkzqY= + +Name: system/customize/resource/quicklaunch_21416.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: system/customize/resource/quicklaunch_24002.xml +SHA1-Digest: cBaRY8TE6AGQCzp+fX1K22fLVLM= + +Name: data/app/com.dropbox.android-1.apk +SHA1-Digest: A37YG/+dSeI4A0OnIfUfdBGIv78= + diff --git a/release/aroma/META-INF/com/google/android/aroma-config b/release/aroma/META-INF/com/google/android/aroma-config new file mode 100644 index 00000000000..131f050fb5e --- /dev/null +++ b/release/aroma/META-INF/com/google/android/aroma-config @@ -0,0 +1,432 @@ +### LICENSE: +# +# Copyright (C) 2011 Ahmad Amarullah ( http://amarullz.com/ ) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +### FILE INFO: +# +# AROMA Installer 2.70 - AROMA Installer Test Script Configuration +# (c) 2011-2012 by Ahmad Amarullah +# amarullz - xda-developers +# http://www.amarullz.com/ +# +# Binary Version : 2.70B +# Binary Codename : Flamboyan +# +### INFO: +# +# * AROMA Resource Dir = META-INF/com/google/android/aroma +# +# * AROMA Temporary Dir = /tmp/aroma/ + +ini_set("rom_name", "Glitch kernel"); +ini_set("rom_version", "N7-AOSP"); +ini_set("rom_author", "Tk-Glitch"); +ini_set("rom_device", "Nexus 7 (2013)"); +ini_set("rom_date", "September 17 2014"); + +ini_set("force_colorspace","rgba"); +#ini_set("dp","6"); + +fontresload( "0", "ttf/Roboto-Regular.ttf", "12" ); +fontresload( "1", "ttf/Roboto-Regular.ttf", "18" ); +theme("miui4"); + +splash(2000, "glitch"); + + +viewbox( + "Welcome", + "You are about to flash "+ + ini_get("rom_name")+ + "\nfor "+ini_get("rom_device")+".\n\n"+ + + + " VERSION\t: <#selectbg_g>"+ini_get("rom_version")+"\n"+ + " AUTHOR \t: <#selectbg_g>"+ini_get("rom_author")+"\n"+ + " RELEASED\t: <#selectbg_g>"+ini_get("rom_date")+"\n\n\n"+ + + "Press Next to Continue...", + "@welcome" +); + +agreebox("Terms Of Use","Please read the Glitch kernel Terms of Use...","themes/miui4/icon.agreement", + "" + readfile_aroma("agreement.txt"), + "I Agree with these Terms Of Use...", + "Please check the box..." +); + +selectbox( + "Keep your Glitch settings ?","New user? Coming back? Already using this kernel?\n","@personalize","glitched.prop", + "I want to make a fresh installation, please.","(wipes previous Glitch settings if any)",1, + "I'm already Glitch'd, just try to keep my settings, thx.","",0 +); + +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" +then + +selectbox( + "CPU Settings","","","cpu.prop", + + "Set each CPU core frequency separately","",2, + "No","(recommended)",1, + "Yes","Gives the option to set the max freq for each core individually",0, + + "CPU optimization level","",2, + "stock","(1.13GHz-4.26GBps)",0, + "improved","(1.19GHz-4.26GBps)",1, + "balanced","(1.22GHz-4.66GBps)",0, + "fast","(1.35GHz-4.66GBps)",0, + "extreme","(1.43GHz-4.80GBps)",0, + "glitchy","(1.49GHz-4.80GBps)",0, + + "Hotplug driver","",2, + "Qualcomm mpdecision","(stock)",0, + "Fluxi's MSM Hotplug","",1, + "Faux123 Intelli-plug","",0, + + "CPU governor","",2, + "ondemand","(stock)",1, + "interactive","",0, + "intellidemand","",0, + "smartmax","",0, + "smartmax_eps","",0, + "intelliactive","",0, + "conservative","",0, + + "Minimum CPU Frequency","",2, + "81MHz","",0, + "162MHz","",0, + "270MHz","",0, + "384MHz","(stock)",1, + "594MHz","",0, + "810MHz","",0 +); + +if file_getprop("/tmp/aroma/cpu.prop","selected.1") == "1" +then +selectbox( + "Maximum CPU Frequency","Select maximum CPU frequency\n","@info","freq0.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); +endif; + +if file_getprop("/tmp/aroma/cpu.prop","selected.1") == "2" +then +selectbox( + "Maximum CPU Frequency","Select maximum frequency for first CPU core\n","@menu","freq0.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); + +selectbox( + "Maximum CPU Frequency","Select maximum frequency for second CPU core\n","@menu","freq1.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); + +selectbox( + "Maximum CPU Frequency","Select maximum frequency for third CPU core\n","@menu","freq2.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); + +selectbox( + "Maximum CPU Frequency","Select maximum frequency for fourth CPU core\n","@menu","freq3.prop", + "1512MHz","(stock)",0, + "1620MHz","",0, + "1728MHz","(balanced)",1, + "1836MHz","",0, + "1890MHz","(performance)",0, + "1944MHz","",0, + "1998MHz","(high)",0, + "2052MHz","",0, + "2106MHz","(very high)",0, + "2160MHz","",0, + "2214MHz","(extreme)",0, + "2268MHz","",0, + "2322MHz","(glitchy)",0 +); +endif; + +selectbox( + "Thermal & battery related Settings","","","nrg.prop", + + "Thermal settings","",2, + "run cool","more thermal throttling",0, + "default","default thermal throttling",1, + "run hot","less thermal throttling",0, + + "Battery life eXtender settings","",2, + "4.3V","(100% - stock)",1, + "4.2V","(93% - balanced)",0, + "4.1V","(83% - conservative)",0, + "4.0V","(73% - very conservative)",0, + + "CPU minfreq undervolting","",2, + "No undervolting","(Stock)",0, + "Undervolt -50 mV","",1, + "Undervolt -75 mV","",0, + "Undervolt -100 mV","",0, + "Undervolt -125 mV","",0, + "Undervolt -150 mV","",0, + "Undervolt -175 mV","",0, + + "GPU undervolting","",2, + "No undervolting","(stock)",0, + "Undervolt -25mV","",1, + "Undervolt -50mV","",0, + "Undervolt -75mV","",0, + "Undervolt -100mV","",0, + "Undervolt -125mV","",0, + "Undervolt -150mV","",0 +); + +selectbox( + "GPU Settings","","","gpu.prop", + + "Select maximum GPU frequency","",2, + "320MHz","(powersaving)",0, + "400MHz","(stock)",0, + "450MHz","(improved)",1, + "504MHz","(balanced)",0, + "545MHz","(fast)",0, + "600MHz","(extreme)",0, + "627MHz","(glitchy)",0, + + "GPU governor","",2, + "Ondemand","(stock)",1, + "Interactive","",0 +); + +selectbox( + "Storage Settings","","","disk.prop", + + "I/O scheduler","",2, + "cfq","(stock)",0, + "row","",1, + "deadline","",0, + "fiops","",0, + "sio","",0, + "noop","",0, + + "Read-ahead buffer size","",2, + "128 KB","(stock)",0, + "256 KB","",1, + "512 KB","",0, + "1024 KB","",0, + "2048 KB","",0 +); + +selectbox( + "Sweep2Wake and DoubleTap2Wake","","","wg.prop", + + "Wake Gestures support","Perform actions or launch apps on gesture (requires Wake Gestures Xposed module or nothing will happen)",0, + "Traditional S2W/DT2W","S2W/DT2W wake screen only",1, + "Disable S2W/DT2W","",0 +); + +if file_getprop("/tmp/aroma/wg.prop","selected.0") == "1" || file_getprop("/tmp/aroma/wg.prop","selected.0") == "2" +then + +checkbox( + "Gesture Options","Customize Sweep2Wake and DoubleTap2Wake","","gest.prop", + + "Available Gestures:","",2, + "Sweep right","",1, + "Sweep left","",1, + "Sweep up","",1, + "Sweep down","",1, + "Double tap","",1, + + "Other Options","",2, + "Short sweep","Enable shorter sweep distance for S2W",1, + "Power button toggles S2W/DT2W","Turn screen off with power button to temporarily disable S2W/DT2W. S2W/DT2W are re-enabled next time the screen comes on",0, + "Magnetic cover toggles S2W/DT2W","S2W/DT2W is disabled when magnetic cover is closed",1, + "Wake Timeout","Disable S2W/DT2W after a specified period of time",0 +); + +if file_getprop("/tmp/aroma/gest.prop","item.1.1") == "0" + && file_getprop("/tmp/aroma/gest.prop","item.1.2") == "0" + && file_getprop("/tmp/aroma/gest.prop","item.1.3") == "0" + && file_getprop("/tmp/aroma/gest.prop","item.1.4") == "0" + && file_getprop("/tmp/aroma/gest.prop","item.1.5") == "0" +then +alert( + "PLEASE NOTE:", + "You didn't enable any gestures", + "@alert", + "OK" +); +back("1"); +endif; + +if file_getprop("/tmp/aroma/gest.prop","item.2.4") == "1" +then +selectbox( + "S2W/DT2W timeout","Select timeout length\nS2W and DT2W will be disabled after this length of time to save battery.","@info","timeout.prop", + "15 minutes","",0, + "30 minutes","",0, + "60 minutes","(default)",1, + "90 minutes","",0, + "120 minutes","",0 +); +endif; +endif; + +checkbox( + "Sweep2Sleep","Sweep left across navbar area to put phone to sleep\nThis feature does NOT drain battery","","s2s.prop", + + "Available Gestures:","",2, + "Enable Sweep2Sleep","",1, + + "Sweep2Sleep Options:","",2, + "Disable sweep2sleep in landscape mode","",1, + "Disable sweep2sleep in portrait mode","",0 +); + +if file_getprop("/tmp/aroma/s2s.prop","item.2.1") == "1" + && file_getprop("/tmp/aroma/s2s.prop","item.2.2") == "1" +then +alert( + "PLEASE NOTE:", + "You might as well disable sweep2sleep. Choose disable in landscape OR disable in portrait, not both.", + "@alert", + "OK" +); +back("1"); +endif; + +checkbox( + "Other settings","Select the mods you want to install","@personalize","misc.prop", + "Enable USB fastcharge","",0, + "Disable magnetic cover on/off","",0, + "Enable USB OTG+Charge mode","Allows charging in USB host mode (disables self-powered OTG)",0, + "Backlight dimmer","Lower screen brightness",0, + "Enable max screen off frequency","",0, + "Enable max MC power savings","",0, + "Override default wlan firmware","Fixes wifi on some roms",0 +); + +if file_getprop("/tmp/aroma/misc.prop","item.0.5") == "1" +then + +selectbox( + "Max screen off CPU Frequency","Select max CPU frequency when the screen is off\n","@personalize","maxscroff.prop", + "594MHz","",0, + "702MHz","",0, + "810MHz","",0, + "1026MHz","",1, + "1242MHz","",0 +); +endif; +endif; + +if file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" +then +alert( + "WARNING:", + "You MUST already have either Glitch kernel installed and running on this device or a backup of your settings on your SDcard root. Else, stock settings will be enforced.", + "@alert", + "OK" +); + +checkbox( + "Glitched already ?","You may want to restore your settings.\n","@personalize","galready.prop", + "Restore your settings from SDcard","If you have a glitch-settings.conf backup from a previous installation (on SDcard root).",0, + "Override default wlan firmware","Replaces your rom's wlan firmware to fix wifi. Unneeded if wifi works as is.",0 +); +endif; + +menubox( + "Glitch Kernel Installer", + "Ready to install", + "@info", + "menu.prop", + "I want to Glitch my device, install it now !","","@install", + "Abort installation","","@default" +); + +if prop("menu.prop","selected")=="2" +then + exit(""); +endif; + +setvar("retstatus", +install( + "Installing", + "Installing Glitch Kernel...\nPlease wait...", + "@install") +); + +ini_set("text_next", "Finish"); + +if getvar("retstatus")=="0" then + viewbox( + "Installation Completed", + "<#080>Congratulations !\n\n"+ + "Glitch kernel has been installed successfully!\n\n"+ + "Please let your device boot completely to let Cthulhu do his work...\n\n"+ + "Enjoy!", + "@info" +); +else + viewbox("Installation Failed","\n\nInstaller Status: "+ getvar("retstatus"),"@alert"); +endif; + diff --git a/release/aroma/META-INF/com/google/android/aroma/agreement.txt b/release/aroma/META-INF/com/google/android/aroma/agreement.txt new file mode 100755 index 00000000000..303bbbee85a --- /dev/null +++ b/release/aroma/META-INF/com/google/android/aroma/agreement.txt @@ -0,0 +1,15 @@ + + +Agreement: + +<*>This kernel is provided as-is without warranty. You are installing this at your own risks + +<*>I'm not responsible for any problem you may encounter with your phone or if your cat suddenly dies. + +<*>By using this kernel, you agree with the above terms! + +<*>PLEASE NOTE: + +This kernel will allow you to choose hardware settings that may not work with your device. + +If you install this and have problems such as instability or random reboots, please reinstall with a lower CPU frequency or higher voltage. diff --git a/release/aroma/META-INF/com/google/android/aroma/fonts/big.png b/release/aroma/META-INF/com/google/android/aroma/fonts/big.png new file mode 100755 index 00000000000..458f00c8938 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/fonts/big.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/fonts/small.png b/release/aroma/META-INF/com/google/android/aroma/fonts/small.png new file mode 100755 index 00000000000..adbdef4afce Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/fonts/small.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/glitch.png b/release/aroma/META-INF/com/google/android/aroma/glitch.png new file mode 100644 index 00000000000..c2c0640574d Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/glitch.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/bg.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/bg.png new file mode 100644 index 00000000000..496cb8558f6 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/bg.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button.9.png new file mode 100644 index 00000000000..420ebc3bb6e Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button.9.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_focus.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_focus.9.png new file mode 100644 index 00000000000..e89c6bf7a2f Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_focus.9.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_press.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_press.9.png new file mode 100644 index 00000000000..13c6ebf1853 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/button_press.9.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb.png new file mode 100644 index 00000000000..62640b09f41 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_focus.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_focus.png new file mode 100644 index 00000000000..eb65efa41e1 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_focus.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on.png new file mode 100644 index 00000000000..e6225732825 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_focus.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_focus.png new file mode 100644 index 00000000000..f6cccccae7d Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_focus.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_press.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_press.png new file mode 100644 index 00000000000..8487d93b14e Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_on_press.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_press.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_press.png new file mode 100644 index 00000000000..e271779be20 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/cb_press.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog.9.png new file mode 100644 index 00000000000..9473701c481 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog.9.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog_titlebar.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog_titlebar.9.png new file mode 100644 index 00000000000..2f70c227cd2 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/dialog_titlebar.9.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.big.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.big.png new file mode 100644 index 00000000000..3a66db5d109 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.big.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.small.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.small.png new file mode 100644 index 00000000000..cb302f2c04c Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/font.roboto.small.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.agreement.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.agreement.png new file mode 100644 index 00000000000..f85b0159a44 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.agreement.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.alert.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.alert.png new file mode 100644 index 00000000000..5b2e08a5b80 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.alert.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.apps.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.apps.png new file mode 100644 index 00000000000..483c4db29e3 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.apps.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.back.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.back.png new file mode 100644 index 00000000000..d88e36fb7c4 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.back.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.confirm.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.confirm.png new file mode 100644 index 00000000000..304c14a8754 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.confirm.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.customize.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.customize.png new file mode 100644 index 00000000000..64d2633ccc8 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.customize.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.default.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.default.png new file mode 100644 index 00000000000..084528c1c9b Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.default.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.info.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.info.png new file mode 100644 index 00000000000..491030aaf63 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.info.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.install.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.install.png new file mode 100644 index 00000000000..7f9484ff176 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.install.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.license.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.license.png new file mode 100644 index 00000000000..0ea1fc0e047 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.license.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.menu.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.menu.png new file mode 100644 index 00000000000..ce48992bf49 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.menu.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.next.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.next.png new file mode 100644 index 00000000000..8c9656f6753 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.next.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.personalize.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.personalize.png new file mode 100644 index 00000000000..f1a411d9b4f Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.personalize.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.update.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.update.png new file mode 100644 index 00000000000..30088c43af2 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.update.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.welcome.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.welcome.png new file mode 100644 index 00000000000..78388c9f852 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/icon.welcome.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/list.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/list.9.png new file mode 100644 index 00000000000..e24409c0606 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/list.9.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/navbar.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/navbar.png new file mode 100644 index 00000000000..8943b806a98 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/navbar.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio.png new file mode 100644 index 00000000000..ff1db4c5d24 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_focus.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_focus.png new file mode 100644 index 00000000000..35399b5a585 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_focus.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on.png new file mode 100644 index 00000000000..fb7310469cd Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_focus.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_focus.png new file mode 100644 index 00000000000..35399b5a585 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_focus.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_press.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_press.png new file mode 100644 index 00000000000..fb7310469cd Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_on_press.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_press.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_press.png new file mode 100644 index 00000000000..fb7310469cd Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/radio_press.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/theme.prop b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/theme.prop new file mode 100644 index 00000000000..f3e9d54f57b --- /dev/null +++ b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/theme.prop @@ -0,0 +1,67 @@ +img.background=bg +img.titlebar=titlebar +img.navbar=navbar +img.dialog=dialog.9 +img.dialog.titlebar=dialog_titlebar.9 +img.progress=button.9 +img.prograss.fill=button_press.9 +img.selection=list.9 +img.selection.push=list.9 +img.button=button.9 +img.button.focus=button_focus.9 +img.button.push=button_press.9 +img.checkbox=cb +img.checkbox.focus=cb_focus +img.checkbox.push=cb_press +img.checkbox.on=cb_on +img.checkbox.on.focus=cb_on_focus +img.checkbox.on.push=cb_on_press +img.radio=radio +img.radio.focus=radio_focus +img.radio.push=radio_press +img.radio.on=radio_on +img.radio.on.focus=radio_on_focus +img.radio.on.push=radio_on_press + + +color.winbg = #ffffff +color.winbg_g = #eeeeee +color.winfg = #000000 +color.winfg_gray = #666666 +color.dialogbg = #ffffff +color.dialogbg_g = #eeeeee +color.dialogfg = #000000 +color.textbg = #ffffff +color.textfg = #000000 +color.textfg_gray = #666666 +color.controlbg = #dddddd +color.controlbg_g = #cccccc +color.controlfg = #000000 +color.selectbg = #ff7e00 +color.selectbg_g = #ff7e00 +color.selectfg = #ffffff +color.titlebg = #ff7e00 +color.titlebg_g = #ff7e00 +color.titlefg = #ffffff +color.dlgtitlebg = #ffffff +color.dlgtitlebg_g = #ffffff +color.dlgtitlefg = #444444 +color.scrollbar = #ff7e00 +color.navbg = #ffffff +color.navbg_g = #eeeeee +color.border = #666666 +color.border_g = #666666 +color.progressglow = #ff7e00 + +config.roundsize = 1 +config.button_roundsize = 1 +config.window_roundsize = 1 +config.transition_frame = 5 + +font.small = font.roboto.small +font.big = font.roboto.big + + +info.themename = MIUI v4 ICS +info.description = MIUI v4 ICS Theme for AROMA Installer +info.author = DemonWav & amarullz & Lennox \ No newline at end of file diff --git a/release/aroma/META-INF/com/google/android/aroma/themes/miui4/titlebar.9.png b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/titlebar.9.png new file mode 100644 index 00000000000..b7b1a62ae25 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/themes/miui4/titlebar.9.png differ diff --git a/release/aroma/META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf b/release/aroma/META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf new file mode 100755 index 00000000000..43b3c4fa133 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/aroma/ttf/Roboto-Regular.ttf differ diff --git a/release/aroma/META-INF/com/google/android/update-binary b/release/aroma/META-INF/com/google/android/update-binary new file mode 100755 index 00000000000..177f535597e Binary files /dev/null and b/release/aroma/META-INF/com/google/android/update-binary differ diff --git a/release/aroma/META-INF/com/google/android/update-binary-installer b/release/aroma/META-INF/com/google/android/update-binary-installer new file mode 100755 index 00000000000..43a2d461d55 Binary files /dev/null and b/release/aroma/META-INF/com/google/android/update-binary-installer differ diff --git a/release/aroma/META-INF/com/google/android/updater-script b/release/aroma/META-INF/com/google/android/updater-script new file mode 100755 index 00000000000..3ddd38fdbf0 --- /dev/null +++ b/release/aroma/META-INF/com/google/android/updater-script @@ -0,0 +1,167 @@ +set_progress(0.0); +ui_print(""); +ui_print("Installing Glitch kernel..."); + +set_progress(0.1); + +if + file_getprop("/tmp/aroma/glitched.prop","selected.0") == "1" + then + +set_progress(0.3); + +package_extract_dir("config", "/tmp"); +set_perm(0, 0, 0777, "/tmp/busybox"); +set_perm(0, 0, 0777, "/tmp/compatibility.sh"); +set_perm(0, 0, 0777, "/tmp/compatibility2.sh"); +run_program("/tmp/busybox", "mount", "/system"); + +ui_print("Cleaning up"); +delete("/system/etc/init.d/99glitchsetup"); +delete("/system/etc/init.d/99glitchsetup~"); +delete("/system/etc/init.d/99elementalx"); +delete("/system/etc/init.d/99elementalx~"); +delete("/system/etc/init.d/01glitch-settings"); +delete("/system/etc/init.d/01glitch-settings~"); +delete("/system/etc/init.d/99glitch"); +delete("/system/etc/init.d/99glitch~"); +delete("/system/etc/elementalx.conf"); +delete("/system/etc/glitch.conf"); +delete("/system/etc/settings.conf"); +delete("/system/etc/glitch-settings.conf"); +delete("/system/etc/init.d/99zram.sh"); +delete("/system/lib/modules/cpufreq_limit.ko"); +delete("/system/lib/modules/scsi_wait_scan.ko"); +delete("/system/lib/modules/frandom.ko"); +delete("/system/lib/modules/exfat.ko"); + +set_perm(0, 0, 0777, "/tmp/systemcheck.sh"); +run_program("/tmp/systemcheck.sh"); + +ui_print("Installing system files for real."); +package_extract_dir("system", "/system"); +set_perm_recursive(0, 2000, 0777, 0777, "/system/etc/init.d/99glitchsetup"); +set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); +set_perm_recursive(0, 2000, 0755, 0755, "/system/bin/fstrim"); + +set_perm(0, 0, 0777, "/tmp/buildconfig.sh"); +run_program("/tmp/buildconfig.sh"); +run_program("/tmp/busybox", "cp", "/tmp/glitch-settings.conf", "/system/etc/glitch-settings.conf"); +set_perm(0, 0, 0666, "/system/etc/glitch-settings.conf"); + +if + file_getprop("/tmp/aroma/cpu.prop","selected.3") == "2" + then + ui_print("Fluxi's MSM Hotplug enabled"); +ui_print("Renaming binaries..."); +ui_print(" /system/bin/mpdecision -> mpdecision_bck"); +ui_print(" /system/bin/thermald -> thermald_bck"); +run_program("/tmp/compatibility.sh"); +else +if + file_getprop("/tmp/aroma/cpu.prop","selected.3") == "3" + then + ui_print("Faux123 Intelli-plug enabled"); +ui_print("Renaming binaries..."); +ui_print(" /system/bin/mpdecision -> mpdecision_bck"); +ui_print(" /system/bin/thermald -> thermald_bck"); +run_program("/tmp/compatibility.sh"); +else + ui_print("Qualcomm mpdecision enabled"); +ui_print("Renaming binaries..."); +ui_print(" /system/bin/mpdecision_bck -> mpdecision"); +ui_print(" /system/bin/thermald -> thermald_bck"); +run_program("/tmp/compatibility2.sh"); +endif; +endif; + +if + file_getprop("/tmp/aroma/misc.prop","item.0.7") == "1" + then + ui_print("Replacing wlan firmware"); +package_extract_dir("wifi_mod", "/system"); +set_perm_recursive(0, 0, 0644, 0644, "/system/etc/wifi/WCNSS_qcom_cfg.ini"); +set_perm_recursive(0, 0, 0644, 0644, "/system/vendor/firmware/wlan/prima/WCNSS_cfg.dat"); +endif; + +package_extract_dir("boot", "/tmp"); +set_perm(0, 0, 0777, "/tmp/max_oc.sh"); +set_perm(0, 0, 0777, "/tmp/edit_ramdisk.sh"); +set_perm(0, 0, 0777, "/tmp/abootimg"); + +ui_print("Applying init settings"); +run_program("/tmp/busybox", "dd", "if=/dev/block/mmcblk0p14", "of=/tmp/boot.img"); +run_program("/tmp/abootimg", "-x", "/tmp/boot.img", "/tmp/bootimg.cfg", "/tmp/zImage", "/tmp/initrd.img"); +run_program("/tmp/max_oc.sh"); +endif; + +if + file_getprop("/tmp/aroma/glitched.prop","selected.0") == "2" + then + +set_progress(0.3); + +package_extract_dir("config", "/tmp"); +set_perm(0, 0, 0777, "/tmp/busybox"); +run_program("/tmp/busybox", "mount", "/system"); + +ui_print("Installing system files to be a good boy."); +package_extract_dir("system", "/system"); +set_perm_recursive(0, 2000, 0777, 0777, "/system/etc/init.d/99glitchsetup"); +set_perm_recursive(0, 0, 0644, 0644, "/system/lib/modules"); +set_perm_recursive(0, 2000, 0755, 0755, "/system/bin/fstrim"); + +if + file_getprop("/tmp/aroma/galready.prop","item.0.1") == "1" + then + ui_print("Pray Cthulhu to get your settings backup in place.."); +run_program("/tmp/busybox", "cp", "/sdcard/glitch-settings.conf", "/system/etc/glitch-settings.conf"); +set_perm(0, 0, 0666, "/system/etc/glitch-settings.conf"); +endif; + +if + file_getprop("/tmp/aroma/galready.prop","item.0.2") == "1" + then + ui_print("Replacing wlan firmware"); +package_extract_dir("wifi_mod", "/system"); +set_perm_recursive(0, 0, 0644, 0644, "/system/etc/wifi/WCNSS_qcom_cfg.ini"); +set_perm_recursive(0, 0, 0644, 0644, "/system/vendor/firmware/wlan/prima/WCNSS_cfg.dat"); +endif; + +ui_print("Do some useless cleaning in case something didn't went wrong..."); +delete("/system/etc/init.d/99glitch"); +delete("/system/lib/modules/cpufreq_limit.ko"); +delete("/system/lib/modules/scsi_wait_scan.ko"); + +set_perm(0, 0, 0777, "/tmp/systemcheck.sh"); +run_program("/tmp/systemcheck.sh"); + +ui_print("Try not to destroy your other settings.. too much."); + +package_extract_dir("boot", "/tmp"); +set_perm(0, 0, 0777, "/tmp/restore.sh"); +set_perm(0, 0, 0777, "/tmp/edit_ramdisk.sh"); +set_perm(0, 0, 0777, "/tmp/abootimg"); + +run_program("/tmp/busybox", "dd", "if=/dev/block/mmcblk0p14", "of=/tmp/boot.img"); +run_program("/tmp/abootimg", "-x", "/tmp/boot.img", "/tmp/bootimg.cfg", "/tmp/zImage", "/tmp/initrd.img"); +run_program("/tmp/restore.sh"); + +endif; + +set_progress(0.6); + +run_program("/tmp/edit_ramdisk.sh"); +run_program("/tmp/abootimg", "-u", "/tmp/boot.img", "-f", "/tmp/cmdline.cfg", "-k", "/tmp/glitch.zImage", "-r", "/tmp/initrd.img"); + +ui_print("@Glitching your device..."); +run_program("/tmp/busybox", "dd", "if=/tmp/boot.img", "of=/dev/block/mmcblk0p14"); + +ui_print(""); +set_progress(0.9); + +ui_print(""); + +ui_print(""); +set_progress(1.0); +ui_print("Finished!"); diff --git a/release/aroma/boot/abootimg b/release/aroma/boot/abootimg new file mode 100755 index 00000000000..fa4bbf8dfb4 Binary files /dev/null and b/release/aroma/boot/abootimg differ diff --git a/release/aroma/boot/cmdline.cfg b/release/aroma/boot/cmdline.cfg new file mode 100755 index 00000000000..1530be1767f --- /dev/null +++ b/release/aroma/boot/cmdline.cfg @@ -0,0 +1,6 @@ +pagesize = 0x800 +kerneladdr = 0x80208000 +ramdiskaddr = 0x82200000 +secondaddr = 0x81100000 +tagsaddr = 0x80200100 +name = diff --git a/release/aroma/boot/edit_ramdisk.sh b/release/aroma/boot/edit_ramdisk.sh new file mode 100755 index 00000000000..2685cd68aab --- /dev/null +++ b/release/aroma/boot/edit_ramdisk.sh @@ -0,0 +1,84 @@ +#!/sbin/sh + +mkdir /tmp/ramdisk +cp /tmp/initrd.img /tmp/ramdisk/initrd.gz +cd /tmp/ramdisk/ +gunzip -c /tmp/ramdisk/initrd.gz | cpio -i +rm /tmp/ramdisk/initrd.gz +rm /tmp/initrd.img + +if [ $(grep -c "mount tmpfs tmpfs /storage mode=0050,uid=0,gid=1028" /tmp/ramdisk/init.rc) == 0 ]; then + sed -i "/mkdir \/mnt\/asec/i\ \ \ \ mount tmpfs tmpfs /storage mode=0050,uid=0,gid=1028" /tmp/ramdisk/init.rc +fi + +if [ $(grep -c "init.d" /tmp/ramdisk/init.rc) == 0 ]; then + echo "" >> /tmp/ramdisk/init.rc + echo "service userinit /system/xbin/busybox run-parts /system/etc/init.d" >> /tmp/ramdisk/init.rc + echo " oneshot" >> /tmp/ramdisk/init.rc + echo " class late_start" >> /tmp/ramdisk/init.rc + echo " user root" >> /tmp/ramdisk/init.rc + echo " group root" >> /tmp/ramdisk/init.rc +fi + +#remove governor overrides, use kernel default +sed -i '/\/sys\/devices\/system\/cpu\/cpu0\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu1\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu2\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc +sed -i '/\/sys\/devices\/system\/cpu\/cpu3\/cpufreq\/scaling_governor/d' /tmp/ramdisk/init.flo.rc + +#add line for CIFs +tmpfs=$(find /tmp/ramdisk/init.rc -type f | xargs grep -oh "mount tmpfs /storage mode=050,uid=0,gid=1028"); +if [ "$tmpfs" != 'mount tmpfs /storage mode=050,uid=0,gid=1028' ]; then + echo "CIF hack found!"; +else +sed '/mkdir /storage 0050 root sdcard_r/a \ +> mount tmpfs /storage mode=0050,uid=0,gid=1028' /tmp/ramdisk/init.flo.rc; + echo "CIF hack added"; +fi + +#Check for F2FS and change fstab accordingly in ramdisk +mount /cache 2> /dev/null +mount /data 2> /dev/null +mount /system 2> /dev/null + +mount | grep -q 'cache type f2fs' +CACHE_F2FS=$? +mount | grep -q 'data type f2fs' +DATA_F2FS=$? +mount | grep -q 'system type f2fs' +SYSTEM_F2FS=$? + +if [ $CACHE_F2FS -eq 0 ] || [ $DATA_F2FS -eq 0 ] || [ $SYSTEM_F2FS -eq 0 ]; then + +if [ $CACHE_F2FS -eq 0 ]; then + sed -i 's,#CACHE_ISF2FS,,' /tmp/fstab.tmp; +else + sed -i 's,#CACHE_ISEXT4,,' /tmp/fstab.tmp; +fi; +if [ $DATA_F2FS -eq 0 ]; then + sed -i 's,#DATA_ISF2FS,,' /tmp/fstab.tmp; +else + sed -i 's,#DATA_ISEXT4,,' /tmp/fstab.tmp; +fi; +if [ $SYSTEM_F2FS -eq 0 ]; then + sed -i 's,#SYS_ISF2FS,,' /tmp/fstab.tmp; +else + sed -i 's,#SYS_ISEXT4,,' /tmp/fstab.tmp; +fi; + +if [ ! -f "/tmp/ramdisk/fstab.orig" ]; then +mv /tmp/ramdisk/fstab.flo /tmp/ramdisk/fstab.orig; +fi; + +mv /tmp/fstab.tmp /tmp/ramdisk/fstab.flo; + +else + +if [ -f "/tmp/ramdisk/fstab.orig" ]; then +mv /tmp/ramdisk/fstab.orig /tmp/ramdisk/fstab.flo; +fi; + +fi; + +#repack +find . | cpio -o -H newc | gzip > /tmp/initrd.img diff --git a/release/aroma/boot/fstab.tmp b/release/aroma/boot/fstab.tmp new file mode 100644 index 00000000000..196bf6a998c --- /dev/null +++ b/release/aroma/boot/fstab.tmp @@ -0,0 +1,29 @@ +# Android fstab file. +# +# The filesystem that contains the filesystem checker binary (typically /system) cannot +# specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK + +#SYS_ISEXT4/dev/block/platform/msm_sdcc.1/by-name/system /system ext4 ro,barrier=1 wait +#SYS_ISF2FS/dev/block/platform/msm_sdcc.1/by-name/system /system f2fs ro,noatime,flush_merge,nosuid,nodev,discard,nodiratime,inline_xattr,errors=recover wait + +#CACHE_ISEXT4/dev/block/platform/msm_sdcc.1/by-name/cache /cache ext4 noatime,nosuid,nodev,barrier=1,data=ordered,nomblk_io_submit,errors=panic wait,check +#CACHE_ISF2FS/dev/block/platform/msm_sdcc.1/by-name/cache /cache f2fs noatime,flush_merge,nosuid,nodev,nodiratime,inline_xattr,errors=recover wait,nonremovable + +#DATA_ISEXT4/dev/block/platform/msm_sdcc.1/by-name/userdata /data ext4 noatime,nosuid,nodev,barrier=1,data=ordered,nomblk_io_submit,errors=panic wait,check,encryptable=/dev/block/platform/msm_sdcc.1/by-name/metadata +#DATA_ISF2FS/dev/block/platform/msm_sdcc.1/by-name/userdata /data f2fs noatime,flush_merge,nosuid,nodev,nodiratime,inline_xattr,errors=recover wait,nonremovable,encryptable=/dev/block/platform/msm_sdcc.1/by-name/metadata + +/dev/block/platform/msm_sdcc.1/by-name/persist /persist ext4 nosuid,nodev,barrier=1,data=ordered,nodelalloc wait +/dev/block/platform/msm_sdcc.1/by-name/boot /boot emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/recovery /recovery emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/misc /misc emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/sbl1 /sbl1 emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/sbl2 /sbl2 emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/sbl3 /sbl3 emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/tz /tz emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/rpm /rpm emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/aboot /aboot emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/sbl2b /sbl2b emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/sbl3b /sbl3b emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/tzb /tzb emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/rpmb /rpmb emmc defaults defaults +/dev/block/platform/msm_sdcc.1/by-name/abootb /abootb emmc defaults defaults diff --git a/release/aroma/boot/max_oc.sh b/release/aroma/boot/max_oc.sh new file mode 100755 index 00000000000..d51a449c818 --- /dev/null +++ b/release/aroma/boot/max_oc.sh @@ -0,0 +1,264 @@ +#!/sbin/sh + +#set max_oc +val0=$(cat /tmp/aroma-data/freq0.prop | cut -d '=' -f2) + +case $val0 in + + 1) + max_oc0="max_oc0=1512000" + ;; + 2) + max_oc0="max_oc0=1620000" + ;; + 3) + max_oc0="max_oc0=1728000" + ;; + 4) + max_oc0="max_oc0=1836000" + ;; + 5) + max_oc0="max_oc0=1890000" + ;; + 6) + max_oc0="max_oc0=1944000" + ;; + 7) + max_oc0="max_oc0=1998000" + ;; + 8) + max_oc0="max_oc0=2052000" + ;; + 9) + max_oc0="max_oc0=2106000" + ;; + 10) + max_oc0="max_oc0=2160000" + ;; + 11) + max_oc0="max_oc0=2214000" + ;; + 12) + max_oc0="max_oc0=2268000" + ;; + 13) + max_oc0="max_oc0=2322000" + ;; +esac + +if [ ! -e /tmp/aroma-data/freq1.prop ]; then + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq1.prop; + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq2.prop; + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq3.prop; +fi + +val1=$(cat /tmp/aroma-data/freq1.prop | cut -d '=' -f2) +case $val1 in + + 1) + max_oc1="max_oc1=1512000" + ;; + 2) + max_oc1="max_oc1=1620000" + ;; + 3) + max_oc1="max_oc1=1728000" + ;; + 4) + max_oc1="max_oc1=1836000" + ;; + 5) + max_oc1="max_oc1=1890000" + ;; + 6) + max_oc1="max_oc1=1944000" + ;; + 7) + max_oc1="max_oc1=1998000" + ;; + 8) + max_oc1="max_oc1=2052000" + ;; + 9) + max_oc1="max_oc1=2106000" + ;; + 10) + max_oc1="max_oc1=2160000" + ;; + 11) + max_oc1="max_oc1=2214000" + ;; + 12) + max_oc1="max_oc1=2268000" + ;; + 13) + max_oc1="max_oc1=2322000" + ;; +esac + +val2=$(cat /tmp/aroma-data/freq2.prop | cut -d '=' -f2) +case $val2 in + + 1) + max_oc2="max_oc2=1512000" + ;; + 2) + max_oc2="max_oc2=1620000" + ;; + 3) + max_oc2="max_oc2=1728000" + ;; + 4) + max_oc2="max_oc2=1836000" + ;; + 5) + max_oc2="max_oc2=1890000" + ;; + 6) + max_oc2="max_oc2=1944000" + ;; + 7) + max_oc2="max_oc2=1998000" + ;; + 8) + max_oc2="max_oc2=2052000" + ;; + 9) + max_oc2="max_oc2=2106000" + ;; + 10) + max_oc2="max_oc2=2160000" + ;; + 11) + max_oc2="max_oc2=2214000" + ;; + 12) + max_oc2="max_oc2=2268000" + ;; + 13) + max_oc2="max_oc2=2322000" + ;; +esac + +val3=$(cat /tmp/aroma-data/freq3.prop | cut -d '=' -f2) +case $val3 in + + 1) + max_oc3="max_oc3=1512000" + ;; + 2) + max_oc3="max_oc3=1620000" + ;; + 3) + max_oc3="max_oc3=1728000" + ;; + 4) + max_oc3="max_oc3=1836000" + ;; + 5) + max_oc3="max_oc3=1890000" + ;; + 6) + max_oc3="max_oc3=1944000" + ;; + 7) + max_oc3="max_oc3=1998000" + ;; + 8) + max_oc3="max_oc3=2052000" + ;; + 9) + max_oc3="max_oc3=2106000" + ;; + 10) + max_oc3="max_oc3=2160000" + ;; + 11) + max_oc3="max_oc3=2214000" + ;; + 12) + max_oc3="max_oc3=2268000" + ;; + 13) + max_oc3="max_oc3=2322000" + ;; +esac + +#set min_clock +val4=$(grep selected.5 /tmp/aroma-data/cpu.prop | cut -d '=' -f2) + +case $val4 in + 1) + min_clock="min_clock=81000" + ;; + 2) + min_clock="min_clock=162000" + ;; + 3) + min_clock="min_clock=270000" + ;; + 4) + min_clock="min_clock=384000" + ;; + 5) + min_clock="min_clock=594000" + ;; + 6) + min_clock="min_clock=810000" + ;; +esac + +#set optimization level +val5=$(grep selected.2 /tmp/aroma-data/cpu.prop | cut -d '=' -f2) + +case $val5 in + 1) + l2_opt="l2_opt=0" + ;; + 2) + l2_opt="l2_opt=1" + ;; + 3) + l2_opt="l2_opt=2" + ;; + 4) + l2_opt="l2_opt=3" + ;; + 5) + l2_opt="l2_opt=4" + ;; + 6) + l2_opt="l2_opt=5" + ;; +esac + +#set undervolting +val6=$(grep selected.3 /tmp/aroma-data/nrg.prop | cut -d '=' -f2) + +case $val6 in + 1) + vdd_uv="vdd_uv=0" + ;; + 2) + vdd_uv="vdd_uv=1" + ;; + 3) + vdd_uv="vdd_uv=2" + ;; + 4) + vdd_uv="vdd_uv=3" + ;; + 5) + vdd_uv="vdd_uv=4" + ;; + 6) + vdd_uv="vdd_uv=5" + ;; + 7) + vdd_uv="vdd_uv=6" + ;; +esac + +null="abc" + +echo "cmdline = console=ttyHSL0,115200,n8 androidboot.hardware=flo user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3" $l2_opt $vdd_uv $max_oc0 $max_oc1 $max_oc2 $max_oc3 $min_clock $null >> /tmp/cmdline.cfg diff --git a/release/aroma/boot/restore.sh b/release/aroma/boot/restore.sh new file mode 100644 index 00000000000..2cc2cb068a8 --- /dev/null +++ b/release/aroma/boot/restore.sh @@ -0,0 +1,47 @@ +#!/sbin/sh + +# Read the settings file +if [ -f "/system/etc/glitch-settings.conf" ]; +then + +. /system/etc/glitch-settings.conf + +if [ "$HOTPLUGDRV" == "0" ] ; then +if [ -e /system/bin/mpdecision_bck ] ; then +busybox mv /system/bin/mpdecision_bck /system/bin/mpdecision +fi +fi + +if [ "$HOTPLUGDRV" == "1" ] ; then +if [ -e /system/bin/mpdecision ] ; then +busybox mv /system/bin/mpdecision /system/bin/mpdecision_bck +fi +fi + +if [ "$HOTPLUGDRV" == "2" ] ; then +if [ -e /system/bin/mpdecision ] ; then +busybox mv /system/bin/mpdecision /system/bin/mpdecision_bck +fi +fi + +if [ -e /system/bin/thermald ] ; then +busybox mv /system/bin/thermald /system/bin/thermald_bck +fi + +l2_opt="l2_opt="$L2_OC; +vdd_uv="vdd_uv="$UV_LEVEL; +min_clock="min_clock="$MINF"000"; +max_oc0="max_oc0="$MAXF_CPU0"000"; +max_oc1="max_oc1="$MAXF_CPU1"000"; +max_oc2="max_oc2="$MAXF_CPU2"000"; +max_oc3="max_oc3="$MAXF_CPU3"000"; + +null="abc" + +echo "cmdline = console=ttyHSL0,115200,n8 androidboot.hardware=flo user_debug=31 msm_rtb.filter=0x3F ehci-hcd.park=3" $l2_opt $vdd_uv $max_oc0 $max_oc1 $max_oc2 $max_oc3 $min_clock $null >> /tmp/cmdline.cfg + +else + +echo "glitch-settings.conf file not found. If you have one, please restore your backup from SDcard or make a complete installation."; + +fi diff --git a/release/aroma/config/buildconfig.sh b/release/aroma/config/buildconfig.sh new file mode 100755 index 00000000000..839d60f3e6d --- /dev/null +++ b/release/aroma/config/buildconfig.sh @@ -0,0 +1,568 @@ +#!/sbin/sh + +#Build config file +CONFIGFILE="/tmp/glitch-settings.conf" + +#Wake Gestures +WG=`grep "selected.0" /tmp/aroma/wg.prop | cut -d '=' -f2` +echo -e "\n\n##### Wake Gestures Settings #####\n# 0 to disable wake gestures" >> $CONFIGFILE +echo -e "# 1 to enable wake gestures\n" >> $CONFIGFILE +if [ "$WG" = 1 ]; then + echo "WG=1" >> $CONFIGFILE; +else + echo "WG=0" >> $CONFIGFILE; +fi + +if [ ! -e /tmp/aroma/gest.prop ]; then + touch /tmp/aroma/gest.prop; +fi + +#S2W +SR=`grep "item.1.1" /tmp/aroma/gest.prop | cut -d '=' -f2` +SL=`grep "item.1.2" /tmp/aroma/gest.prop | cut -d '=' -f2` +SU=`grep "item.1.3" /tmp/aroma/gest.prop | cut -d '=' -f2` +SD=`grep "item.1.4" /tmp/aroma/gest.prop | cut -d '=' -f2` +echo -e "\n\n##### Sweep2wake Settings #####\n# 0 to disable sweep2wake" >> $CONFIGFILE +echo -e "# 1 to enable sweep right" >> $CONFIGFILE +echo -e "# 2 to enable sweep left" >> $CONFIGFILE +echo -e "# 4 to enable sweep up" >> $CONFIGFILE +echo -e "# 8 to enable sweep down\n" >> $CONFIGFILE +echo -e "# For combinations, add values together (e.g. all gestures enabled = 15)\n" >> $CONFIGFILE +if [ "$SL" = 1 ]; then + SL=2 +fi +if [ "$SU" = 1 ]; then + SU=4 +fi +if [ "$SD" = 1 ]; then + SD=8 +fi + +S2W=$(( SL + SR + SU + SD )) +echo S2W=$S2W >> $CONFIGFILE; + +#DT2W +DT2W=`grep "item.1.5" /tmp/aroma/gest.prop | cut -d '=' -f2` +echo -e "\n\n##### DoubleTap2Wake Settings #####\n# 0 to disable DoubleTap2Wake" >> $CONFIGFILE +echo -e "# 1 to enable DoubleTap2Wake\n" >> $CONFIGFILE +if [ "$DT2W" = 1 ]; then + echo "DT2W=1" >> $CONFIGFILE; +else + echo "DT2W=0" >> $CONFIGFILE; +fi + +#Shortsweep +SHORTSWEEP=`grep "item.2.1" /tmp/aroma/gest.prop | cut -d '=' -f2` +echo -e "\n\n##### Shortsweep Settings #####\n# 0 to disable Shortsweep" >> $CONFIGFILE +echo -e "# 1 to enable Shortsweep\n" >> $CONFIGFILE +if [ "$SHORTSWEEP" = 1 ]; then + echo "SHORTSWEEP=1" >> $CONFIGFILE; +else + echo "SHORTSWEEP=0" >> $CONFIGFILE; +fi + +#S2W Power key toggle +PWR_KEY=`grep "item.2.2" /tmp/aroma/gest.prop | cut -d '=' -f2` +echo -e "\n\n##### Power Key Toggles S2W/DT2W #####\n# 0 to disable" >> $CONFIGFILE +echo -e "# 1 to enable\n" >> $CONFIGFILE +if [ "$PWR_KEY" = 1 ]; then + echo "PWR_KEY=1" >> $CONFIGFILE; +else + echo "PWR_KEY=0" >> $CONFIGFILE; +fi + +#S2W Magnetic cover toggle +LID_SUS=`grep "item.2.3" /tmp/aroma/gest.prop | cut -d '=' -f2` +echo -e "\n\n##### Magnetic Cover Toggles S2W/DT2W #####\n# 0 to disable" >> $CONFIGFILE +echo -e "# 1 to enable\n" >> $CONFIGFILE +if [ "$LID_SUS" = 1 ]; then + echo "LID_SUS=1" >> $CONFIGFILE; +else + echo "LID_SUS=0" >> $CONFIGFILE; +fi + +#S2W/DT2W Timeout +if [ ! -e /tmp/aroma/timeout.prop ]; then + touch /tmp/aroma/timeout.prop; +fi + +TIMEOUT=`cat /tmp/aroma/timeout.prop | cut -d '=' -f2` +echo -e "\n\n##### S2W/DT2W Timeout #####\n# 0 = disabled" >> $CONFIGFILE +echo -e "# Otherwise, specify number of minutes (default is 60)\n" >> $CONFIGFILE +if [ "$TIMEOUT" = 1 ]; then + echo "TIMEOUT=15" >> $CONFIGFILE; +elif [ "$TIMEOUT" = 2 ]; then + echo "TIMEOUT=30" >> $CONFIGFILE; +elif [ "$TIMEOUT" = 3 ]; then + echo "TIMEOUT=60" >> $CONFIGFILE; +elif [ "$TIMEOUT" = 4 ]; then + echo "TIMEOUT=90" >> $CONFIGFILE; +elif [ "$TIMEOUT" = 5 ]; then + echo "TIMEOUT=120" >> $CONFIGFILE; +else + echo "TIMEOUT=0" >> $CONFIGFILE; +fi + +#S2S +S2S=`grep "item.1.1" /tmp/aroma/s2s.prop | cut -d '=' -f2` +echo -e "\n\n##### Sweep2Sleep Settings #####\n# 0 to disable Sweep2Sleepe" >> $CONFIGFILE +echo -e "# 1 to enable Sweep2Sleep\n" >> $CONFIGFILE +if [ "$S2S" = 1 ]; then + echo "S2S=1" >> $CONFIGFILE; +else + echo "S2S=0" >> $CONFIGFILE; +fi + +#S2S Options +PORTRAIT=`grep "item.2.1" /tmp/aroma/s2s.prop | cut -d '=' -f2` +LANDSCAPE=`grep "item.2.2" /tmp/aroma/s2s.prop | cut -d '=' -f2` +echo -e "\n\n##### Sweep2sleep Orientation Settings #####\n# 0 to enable portrait and landscape" >> $CONFIGFILE +echo -e "# 1 to disable sweep2sleep landscape mode\n" >> $CONFIGFILE +echo -e "# 2 to disable sweep2sleep in portrait mode\n" >> $CONFIGFILE +if [ "$PORTRAIT" = 1 ]; then + echo "ORIENTATION=1" >> $CONFIGFILE; +elif [ "$LANDSCAPE" = 1 ]; then + echo "ORIENTATION=2" >> $CONFIGFILE; +else + echo "ORIENTATION=0" >> $CONFIGFILE; +fi + +#Fast Charge +FAST_CHARGE=`grep "item.0.1" /tmp/aroma/misc.prop | cut -d '=' -f2` +echo -e "\n\n##### Force fast-charge Settings #####\n# 0 to disable fast-charge" >> $CONFIGFILE +echo -e "# 1 to enable fast-charge\n" >> $CONFIGFILE +if [ "$FAST_CHARGE" = 1 ]; then + echo "FAST_CHARGE=1" >> $CONFIGFILE; +else + echo "FAST_CHARGE=0" >> $CONFIGFILE; +fi + +#Magnetic on/off +LID=`grep "item.0.2" /tmp/aroma/misc.prop | cut -d '=' -f2` +echo -e "\n\n##### Magnetic on/off Settings #####\n# 0 to disable Magnetic on/off" >> $CONFIGFILE +echo -e "# 1 to enable Magnetic on/off\n" >> $CONFIGFILE +if [ "$LID" = 1 ]; then + echo "LID=0" >> $CONFIGFILE; +else + echo "LID=1" >> $CONFIGFILE; +fi + +#USB Host mode charging +OTGCM=`grep "item.0.3" /tmp/aroma/misc.prop | cut -d '=' -f2` +echo -e "\n\n##### USB OTG+Charge Settings ######\n# 1 to enable USB host mode charging\n# 0 to disable USB host mode charging\n" >> $CONFIGFILE +if [ "$OTGCM" = 1 ]; then + echo "OTGCM=1" >> $CONFIGFILE; +else + echo "OTGCM=0" >> $CONFIGFILE; +fi + +#Backlight dimmer +BLD=`grep "item.0.4" /tmp/aroma/misc.prop | cut -d '=' -f2` +echo -e "\n\n##### Backlight Dimmer Settings ######\n# Adjust screen brightness. A value of 4 is default, higher values decrease brightness.\n" >> $CONFIGFILE +if [ $BLD = 1 ]; then + echo "BLD=4" >> $CONFIGFILE; +else + echo "BLD=0" >> $CONFIGFILE; +fi + +#MC Power Savings +MC_POWERSAVE=`grep "item.0.6" /tmp/aroma/misc.prop | cut -d '=' -f2` +echo -e "\n\n##### MC Power savings Settings #####\n# 0 to disable MC power savings" >> $CONFIGFILE +echo -e "# 1 to enable maximum MC power savings\n" >> $CONFIGFILE +if [ "$MC_POWERSAVE" = 1 ]; then + echo "MC_POWERSAVE=1" >> $CONFIGFILE; +else + echo "MC_POWERSAVE=0" >> $CONFIGFILE; +fi + +#THERMAL +THERM=`grep selected.1 /tmp/aroma/nrg.prop | cut -d '=' -f2` +echo -e "\n\n##### Thermal Settings #####\n# 0 for default thermal throttling" >> $CONFIGFILE +echo -e "# 1 to run cool\n# 2 to run hot\n" >> $CONFIGFILE +if [ "$THERM" = 1 ]; then + echo "THERM=1" >> $CONFIGFILE; +elif [ "$THERM" = 3 ]; then + echo "THERM=2" >> $CONFIGFILE; +else + echo "THERM=0" >> $CONFIGFILE; +fi + +#Battery life extender +BLE=`grep selected.2 /tmp/aroma/nrg.prop | cut -d '=' -f2` +echo -e "\n\n##### Battery life eXtender #####\n# 1 4.3V (stock - 100%)" >> $CONFIGFILE +echo -e "# 2 4.2V (balanced - 93%)\n# 3 4.1V (conservative - 83%)\n# 4 4.0V (very conservative - 73%)\n" >> $CONFIGFILE +if [ "$BLE" = 2 ]; then + echo "BLE=2" >> $CONFIGFILE; +elif [ "$BLE" = 3 ]; then + echo "BLE=3" >> $CONFIGFILE; +elif [ "$BLE" = 4 ]; then + echo "BLE=4" >> $CONFIGFILE; +else + echo "BLE=1" >> $CONFIGFILE; +fi + +#GPU UV +GPU_UV=`grep selected.4 /tmp/aroma/nrg.prop | cut -d '=' -f2` +echo -e "\n\n##### GPU Undervolting #####\n# 1 Stock\n# 2 -25mV" >> $CONFIGFILE +echo -e "# 3 -50mV\n# 4 -75mV\n# 5 -100mV\n# 6 -125mV\n# 7 -150mV\n" >> $CONFIGFILE +if [ "$GPU_UV" = 2 ]; then + echo "GPU_UV=2" >> $CONFIGFILE; +elif [ "$GPU_UV" = 3 ]; then + echo "GPU_UV=3" >> $CONFIGFILE; +elif [ "$GPU_UV" = 4 ]; then + echo "GPU_UV=4" >> $CONFIGFILE; +elif [ "$GPU_UV" = 5 ]; then + echo "GPU_UV=5" >> $CONFIGFILE; +elif [ "$GPU_UV" = 6 ]; then + echo "GPU_UV=6" >> $CONFIGFILE; +elif [ "$GPU_UV" = 7 ]; then + echo "GPU_UV=7" >> $CONFIGFILE; +else + echo "GPU_UV=1" >> $CONFIGFILE; +fi + +#GPU Clock +GPU_OC=`grep selected.1 /tmp/aroma/gpu.prop | cut -d '=' -f2` +echo -e "\n\n##### Max GPU Clock #####\n# 1 320 MHz" >> $CONFIGFILE +echo -e "# 2 400 MHz\n# 3 450 MHz\n# 4 504 MHz\n# 5 545 MHz\n# 6 600 MHz\n# 7 627 MHz\n" >> $CONFIGFILE +if [ "$GPU_OC" = 1 ]; then + echo "GPU_OC=1" >> $CONFIGFILE; +elif [ "$GPU_OC" = 3 ]; then + echo "GPU_OC=3" >> $CONFIGFILE; +elif [ "$GPU_OC" = 4 ]; then + echo "GPU_OC=4" >> $CONFIGFILE; +elif [ "$GPU_OC" = 5 ]; then + echo "GPU_OC=5" >> $CONFIGFILE; +elif [ "$GPU_OC" = 6 ]; then + echo "GPU_OC=6" >> $CONFIGFILE; +elif [ "$GPU_OC" = 7 ]; then + echo "GPU_OC=7" >> $CONFIGFILE; +else + echo "GPU_OC=2" >> $CONFIGFILE; +fi + +#GPU Governor +GPU_GOV=`grep selected.2 /tmp/aroma/gpu.prop | cut -d '=' -f2` +echo -e "\n\n##### GPU Governor #####\n# 1 Ondemand (default)" >> $CONFIGFILE +echo -e "# 2 Interactive\n# 3 Performance\n" >> $CONFIGFILE +if [ "$GPU_GOV" = 2 ]; then + echo "GPU_GOV=2" >> $CONFIGFILE; +else + echo "GPU_GOV=1" >> $CONFIGFILE; +fi + +#I/O scheduler +IOSCHED=`grep selected.1 /tmp/aroma/disk.prop | cut -d '=' -f2` +echo -e "\n\n##### I/O scheduler #####\n# 1 cfq (stock)\n# 2 row" >> $CONFIGFILE +echo -e "# 3 deadline\n# 4 fiops\n# 5 sio# 6 noop\n" >> $CONFIGFILE +if [ "$IOSCHED" = 2 ]; then + echo "IOSCHED=2" >> $CONFIGFILE; +elif [ "$IOSCHED" = 3 ]; then + echo "IOSCHED=3" >> $CONFIGFILE; +elif [ "$IOSCHED" = 4 ]; then + echo "IOSCHED=4" >> $CONFIGFILE; +elif [ "$IOSCHED" = 5 ]; then + echo "IOSCHED=5" >> $CONFIGFILE; +elif [ "$IOSCHED" = 6 ]; then + echo "IOSCHED=6" >> $CONFIGFILE; +else + echo "IOSCHED=1" >> $CONFIGFILE; +fi + +#read-ahead +READAHEAD=`grep selected.2 /tmp/aroma/disk.prop | cut -d '=' -f2` +echo -e "\n\n##### Read-ahead buffer size (KB) #####\n# 1 128 (stock)\n# 2 256" >> $CONFIGFILE +echo -e "# 3 512\n# 4 1024\n# 5 2048\n" >> $CONFIGFILE +if [ "$READAHEAD" = 2 ]; then + echo "READAHEAD=2" >> $CONFIGFILE; +elif [ "$READAHEAD" = 3 ]; then + echo "READAHEAD=3" >> $CONFIGFILE; +elif [ "$READAHEAD" = 4 ]; then + echo "READAHEAD=4" >> $CONFIGFILE; +elif [ "$READAHEAD" = 5 ]; then + echo "READAHEAD=5" >> $CONFIGFILE; +elif [ "$READAHEAD" = 6 ]; then + echo "READAHEAD=6" >> $CONFIGFILE; +else + echo "READAHEAD=1" >> $CONFIGFILE; +fi + +#CPU governor +CPU_GOV=`grep selected.4 /tmp/aroma/cpu.prop | cut -d '=' -f2` +echo -e "\n\n##### CPU governor #####\n# 1 ondemand (stock)" >> $CONFIGFILE +echo -e "# 2 interactive\n# 3 intellidemand\n# 4 smartmax" >> $CONFIGFILE +echo -e "# 5 smartmax_eps\n# 6 intelliactive\n# 7 conservative\n" >> $CONFIGFILE +if [ "$CPU_GOV" = 2 ]; then + echo "CPU_GOV=2" >> $CONFIGFILE; +elif [ "$CPU_GOV" = 3 ]; then + echo "CPU_GOV=3" >> $CONFIGFILE; +elif [ "$CPU_GOV" = 4 ]; then + echo "CPU_GOV=4" >> $CONFIGFILE; +elif [ "$CPU_GOV" = 5 ]; then + echo "CPU_GOV=5" >> $CONFIGFILE; +elif [ "$CPU_GOV" = 6 ]; then + echo "CPU_GOV=6" >> $CONFIGFILE; +elif [ "$CPU_GOV" = 7 ]; then + echo "CPU_GOV=7" >> $CONFIGFILE; +else + echo "CPU_GOV=1" >> $CONFIGFILE; +fi + +#Max screen off frequency +if [ -f "/tmp/aroma/maxscroff.prop" ]; +then +SCROFF=`cat /tmp/aroma/maxscroff.prop | cut -d '=' -f2` +echo -e "\n\n##### Max screen off frequency ######\n# 0 disabled\n# 1 594MHz\n# 2 702MHz" >> $CONFIGFILE +echo -e "# 3 810MHz\n# 4 1026MHz\n# 5 1242MHz\n" >> $CONFIGFILE +if [ "$SCROFF" = 1 ]; then + echo "SCROFF=1" >> $CONFIGFILE; +elif [ "$SCROFF" = 2 ]; then + echo "SCROFF=2" >> $CONFIGFILE; +elif [ "$SCROFF" = 3 ]; then + echo "SCROFF=3" >> $CONFIGFILE; +elif [ "$SCROFF" = 4 ]; then + echo "SCROFF=4" >> $CONFIGFILE; +elif [ "$SCROFF" = 5 ]; then + echo "SCROFF=5" >> $CONFIGFILE; +else + echo "SCROFF=0" >> $CONFIGFILE; +fi +else +echo "selected.0=99" > /tmp/aroma/maxscroff.prop +echo -e "\n\n##### Max screen off frequency ######\n# 0 disabled\n# 1 594MHz\n# 2 702MHz" >> $CONFIGFILE +echo -e "# 3 810MHz\n# 4 1026MHz\n# 5 1242MHz\n" >> $CONFIGFILE +echo "SCROFF=0" >> $CONFIGFILE; +fi + +echo -e "\n\n####################################################################" >> $CONFIGFILE +echo -e "# Anything past this is a backup of your initialization settings #" >> $CONFIGFILE +echo -e "# for Aroma Installer to restore them if asked. #" >> $CONFIGFILE +echo -e "# Edit these lines only if you're planning to reinstall the kernel #" >> $CONFIGFILE +echo -e "# and restore settings, as they won't be applied outside of Aroma. #" >> $CONFIGFILE +echo -e "####################################################################\n\n" >> $CONFIGFILE + +if [ ! -e /tmp/aroma-data/freq1.prop ]; then + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq1.prop; + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq2.prop; + cp /tmp/aroma-data/freq0.prop /tmp/aroma-data/freq3.prop; +fi + +#MAXFREQ +if [ -f "/tmp/aroma/freq0.prop" ]; +then +MAXF_CPU0=`cat /tmp/aroma/freq0.prop | cut -d '=' -f2` +echo -e "\n\n##### Maximum CPU0 frequency (MHz) #####\n# 1512, 1620, 1728, 1836, 1890, 1944, 1998\n# 2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE +if [ "$MAXF_CPU0" = 2 ]; then + echo "MAXF_CPU0=1620" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 3 ]; then + echo "MAXF_CPU0=1728" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 4 ]; then + echo "MAXF_CPU0=1836" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 5 ]; then + echo "MAXF_CPU0=1890" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 6 ]; then + echo "MAXF_CPU0=1944" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 7 ]; then + echo "MAXF_CPU0=1998" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 8 ]; then + echo "MAXF_CPU0=2052" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 9 ]; then + echo "MAXF_CPU0=2106" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 10 ]; then + echo "MAXF_CPU0=2160" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 11 ]; then + echo "MAXF_CPU0=2214" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 12 ]; then + echo "MAXF_CPU0=2268" >> $CONFIGFILE; +elif [ "$MAXF_CPU0" = 13 ]; then + echo "MAXF_CPU0=2322" >> $CONFIGFILE; +else + echo "MAXF_CPU0=1512" >> $CONFIGFILE; +fi +else +echo "selected.0=99" > /tmp/aroma/freq0.prop +echo -e "\n\n##### Maximum CPU0 frequency (MHz) #####\n# 1512, 1620, 1728, 1836, 1890, 1944, 1998\n# 2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE +echo "MAXF_CPU0=1512" >> $CONFIGFILE; +fi + +if [ -f "/tmp/aroma/freq1.prop" ]; +then +MAXF_CPU1=`cat /tmp/aroma/freq1.prop | cut -d '=' -f2` +echo -e "\n\n##### Maximum CPU1 frequency (MHz) #####\n# 1512, 1620, 1728, 1836, 1890, 1944, 1998\n# 2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE +if [ "$MAXF_CPU1" = 2 ]; then + echo "MAXF_CPU1=1620" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 3 ]; then + echo "MAXF_CPU1=1728" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 4 ]; then + echo "MAXF_CPU1=1836" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 5 ]; then + echo "MAXF_CPU1=1890" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 6 ]; then + echo "MAXF_CPU1=1944" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 7 ]; then + echo "MAXF_CPU1=1998" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 8 ]; then + echo "MAXF_CPU1=2052" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 9 ]; then + echo "MAXF_CPU1=2106" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 10 ]; then + echo "MAXF_CPU1=2160" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 11 ]; then + echo "MAXF_CPU1=2214" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 12 ]; then + echo "MAXF_CPU1=2268" >> $CONFIGFILE; +elif [ "$MAXF_CPU1" = 13 ]; then + echo "MAXF_CPU1=2322" >> $CONFIGFILE; +else + echo "MAXF_CPU1=1512" >> $CONFIGFILE; +fi +else +echo "selected.0=99" > /tmp/aroma/freq1.prop +echo -e "\n\n##### Maximum CPU1 frequency (MHz) #####\n# 1512, 1620, 1728, 1836, 1890, 1944, 1998\n# 2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE +echo "MAXF_CPU1=1512" >> $CONFIGFILE; +fi + +if [ -f "/tmp/aroma/freq2.prop" ]; +then +MAXF_CPU2=`cat /tmp/aroma/freq2.prop | cut -d '=' -f2` +echo -e "\n\n##### Maximum CPU2 frequency (MHz) #####\n# 1512, 1620, 1728, 1836, 1890, 1944, 1998\n# 2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE +if [ "$MAXF_CPU2" = 2 ]; then + echo "MAXF_CPU2=1620" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 3 ]; then + echo "MAXF_CPU2=1728" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 4 ]; then + echo "MAXF_CPU2=1836" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 5 ]; then + echo "MAXF_CPU2=1890" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 6 ]; then + echo "MAXF_CPU2=1944" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 7 ]; then + echo "MAXF_CPU2=1998" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 8 ]; then + echo "MAXF_CPU2=2052" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 9 ]; then + echo "MAXF_CPU2=2106" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 10 ]; then + echo "MAXF_CPU2=2160'" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 11 ]; then + echo "MAXF_CPU2=2214" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 12 ]; then + echo "MAXF_CPU2=2268" >> $CONFIGFILE; +elif [ "$MAXF_CPU2" = 13 ]; then + echo "MAXF_CPU2=2322" >> $CONFIGFILE; +else + echo "MAXF_CPU2=1512" >> $CONFIGFILE; +fi +else +echo "selected.0=99" > /tmp/aroma/freq2.prop +echo -e "\n\n##### Maximum CPU2 frequency (MHz) #####\n# 1512, 1620, 1728, 1836, 1890, 1944, 1998\n# 2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE +echo "MAXF_CPU2=1512" >> $CONFIGFILE; +fi + +if [ -f "/tmp/aroma/freq3.prop" ]; +then +MAXF_CPU3=`cat /tmp/aroma/freq3.prop | cut -d '=' -f2` +echo -e "\n\n##### Maximum CPU3 frequency (MHz) #####\n# 1512, 1620, 1728, 1836, 1890, 1944, 1998\n# 2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE +if [ "$MAXF_CPU3" = 2 ]; then + echo "MAXF_CPU3=1620" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 3 ]; then + echo "MAXF_CPU3=1728" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 4 ]; then + echo "MAXF_CPU3=1836" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 5 ]; then + echo "MAXF_CPU3=1890" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 6 ]; then + echo "MAXF_CPU3=1944" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 7 ]; then + echo "MAXF_CPU3=1998" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 8 ]; then + echo "MAXF_CPU3=2052" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 9 ]; then + echo "MAXF_CPU3=2106" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 10 ]; then + echo "MAXF_CPU3=2160" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 11 ]; then + echo "MAXF_CPU3=2214" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 12 ]; then + echo "MAXF_CPU3=2268" >> $CONFIGFILE; +elif [ "$MAXF_CPU3" = 13 ]; then + echo "MAXF_CPU3=2322" >> $CONFIGFILE; +else + echo "MAXF_CPU3=1512" >> $CONFIGFILE; +fi +else +echo "selected.0=99" > /tmp/aroma/freq3.prop +echo -e "\n\n##### Maximum CPU3 frequency (MHz) #####\n# 1512, 1620, 1728, 1836, 1890, 1944, 1998\n# 2052, 2106, 2160, 2214, 2268, 2322\n" >> $CONFIGFILE +echo "MAXF_CPU3=1512" >> $CONFIGFILE; +fi + +#MINFREQ +MINF=`grep selected.5 /tmp/aroma/cpu.prop | cut -d '=' -f2` +echo -e "\n\n##### Minimum CPU frequency (MHz) #####\n# 81, 162, 270, 384, 595 or 810 are valid frequencies.\n" >> $CONFIGFILE +if [ "$MINF" = 1 ]; then + echo "MINF=81" >> $CONFIGFILE; +elif [ "$MINF" = 2 ]; then + echo "MINF=162" >> $CONFIGFILE; +elif [ "$MINF" = 3 ]; then + echo "MINF=270" >> $CONFIGFILE; +elif [ "$MINF" = 5 ]; then + echo "MINF=595" >> $CONFIGFILE; +elif [ "$MINF" = 6 ]; then + echo "MINF=810" >> $CONFIGFILE; +else + echo "MINF=384" >> $CONFIGFILE; +fi + +#UV +UV_LEVEL=`grep selected.3 /tmp/aroma/nrg.prop | cut -d '=' -f2` +echo -e "\n\n##### Level of uV to apply to min frequency #####\n# 0 stock(no uV)\n# 1 -50 mV" >> $CONFIGFILE +echo -e "# 2 -75 mV\n# 3 -100 mV\n# 4 -125 mV\n# 5 -150 mV\n# 6 -175 mV\n" >> $CONFIGFILE +if [ "$UV_LEVEL" = 2 ]; then + echo "UV_LEVEL=1" >> $CONFIGFILE; +elif [ "$UV_LEVEL" = 3 ]; then + echo "UV_LEVEL=2" >> $CONFIGFILE; +elif [ "$UV_LEVEL" = 4 ]; then + echo "UV_LEVEL=3" >> $CONFIGFILE; +elif [ "$UV_LEVEL" = 5 ]; then + echo "UV_LEVEL=4" >> $CONFIGFILE; +elif [ "$UV_LEVEL" = 6 ]; then + echo "UV_LEVEL=5" >> $CONFIGFILE; +elif [ "$UV_LEVEL" = 7 ]; then + echo "UV_LEVEL=6" >> $CONFIGFILE; +else + echo "UV_LEVEL=0" >> $CONFIGFILE; +fi + +#L2/CACHE OC +L2_OC=`grep selected.2 /tmp/aroma/cpu.prop | cut -d '=' -f2` +echo -e "\n\n##### L2/cache OC settings #####\n# 0 stock(1.13GHz-4.26GBps)\n# 1 improved(1.19GHz-4.26GBps)" >> $CONFIGFILE +echo -e "# 2 balanced(1.22GHz-4.66GBps)\n# 3 fast(1.35GHz-4.66GBps)\n# 4 extreme(1.43GHz-4.80GBps)" >> $CONFIGFILE +echo -e "# 5 glitchy(1.49GHz-4.96GBps)\n" >> $CONFIGFILE +if [ "$L2_OC" = 2 ]; then + echo "L2_OC=1" >> $CONFIGFILE; +elif [ "$L2_OC" = 3 ]; then + echo "L2_OC=2" >> $CONFIGFILE; +elif [ "$L2_OC" = 4 ]; then + echo "L2_OC=3" >> $CONFIGFILE; +elif [ "$L2_OC" = 5 ]; then + echo "L2_OC=4" >> $CONFIGFILE; +elif [ "$L2_OC" = 6 ]; then + echo "L2_OC=5" >> $CONFIGFILE; +else + echo "L2_OC=0" >> $CONFIGFILE; +fi + +#HOTPLUGDRV +HOTPLUGDRV=`grep selected.3 /tmp/aroma/cpu.prop | cut -d '=' -f2` +echo -e "\n\n##### Hotplug driver Settings #####\n# 0 to enable qualcomm mpdecision (stock)" >> $CONFIGFILE +echo -e "# 1 to enable MSM Hotplug (recommended)\n# 2 to enable intelli-plug\n" >> $CONFIGFILE +if [ "$HOTPLUGDRV" = 1 ]; then + echo "HOTPLUGDRV=0" >> $CONFIGFILE; +elif [ "$HOTPLUGDRV" = 3 ]; then + echo "HOTPLUGDRV=2" >> $CONFIGFILE; +else + echo "HOTPLUGDRV=1" >> $CONFIGFILE; +fi + +echo -e "\n\n##############################" >> $CONFIGFILE +#END diff --git a/release/aroma/config/busybox b/release/aroma/config/busybox new file mode 100755 index 00000000000..e7acacfb624 Binary files /dev/null and b/release/aroma/config/busybox differ diff --git a/release/aroma/config/compatibility.sh b/release/aroma/config/compatibility.sh new file mode 100644 index 00000000000..09039f25c57 --- /dev/null +++ b/release/aroma/config/compatibility.sh @@ -0,0 +1,13 @@ +#!/sbin/sh +# + +#remove the binaries as they are no longer needed. (kernel handled) +if [ -e /system/bin/mpdecision ] ; then + busybox mv /system/bin/mpdecision /system/bin/mpdecision_bck +fi +if [ -e /system/bin/thermald ] ; then + busybox mv /system/bin/thermald /system/bin/thermald_bck +fi + +return $? + diff --git a/release/aroma/config/compatibility2.sh b/release/aroma/config/compatibility2.sh new file mode 100644 index 00000000000..872100f16b7 --- /dev/null +++ b/release/aroma/config/compatibility2.sh @@ -0,0 +1,13 @@ +#!/sbin/sh +# + +#remove the binaries as they are no longer needed. (kernel handled) +if [ -e /system/bin/mpdecision_bck ] ; then + busybox mv /system/bin/mpdecision_bck /system/bin/mpdecision +fi +if [ -e /system/bin/thermald ] ; then + busybox mv /system/bin/thermald /system/bin/thermald_bck +fi + +return $? + diff --git a/release/aroma/config/glitch-settings.conf b/release/aroma/config/glitch-settings.conf new file mode 100755 index 00000000000..12e5646e6f5 --- /dev/null +++ b/release/aroma/config/glitch-settings.conf @@ -0,0 +1,6 @@ +############################# + +#Glitch kernel Configuration + + +#For settings to take effect, you must execute /etc/init.d/01glitch-settings as root. If you don't know how to do that, just reboot. diff --git a/release/aroma/config/systemcheck.sh b/release/aroma/config/systemcheck.sh new file mode 100755 index 00000000000..3972c2d486f --- /dev/null +++ b/release/aroma/config/systemcheck.sh @@ -0,0 +1,15 @@ +#!/sbin/sh + +if [ ! -f /system/xbin/busybox ]; then + + cp /tmp/busybox /system/xbin/busybox; + chmod 777 /system/xbin/busybox; +fi + + +if [ ! -d /system/etc/init.d ]; then + if [ -f /system/etc/init.d ]; then + mv /system/etc/init.d /system/etc/init.d.bak; + fi + mkdir /system/etc/init.d; +fi diff --git a/release/aroma/system/bin/fstrim b/release/aroma/system/bin/fstrim new file mode 100755 index 00000000000..4b0819ea239 Binary files /dev/null and b/release/aroma/system/bin/fstrim differ diff --git a/release/aroma/system/etc/init.d/99glitchsetup b/release/aroma/system/etc/init.d/99glitchsetup new file mode 100755 index 00000000000..12ac4fc1c21 --- /dev/null +++ b/release/aroma/system/etc/init.d/99glitchsetup @@ -0,0 +1,343 @@ +#!/system/bin/sh + +KERNEL_CONF="/system/etc/glitch-settings.conf"; +KERNEL_LOGFILE="/data/local/tmp/glitch-kernel.log"; + +if [ -f $KERNEL_LOGFILE ]; then + mv $KERNEL_LOGFILE $KERNEL_LOGFILE.2; +fi + +echo $(date) >> $KERNEL_LOGFILE; + +#Touch Firmware +TFW="`cat /sys/devices/i2c-3/3-0010/vendor`" +echo TouchFW: $TFW >> $KERNEL_LOGFILE; + +#Max CPU_FREQ +MAXF="`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq`" +echo $MAXF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq; +echo $MAXF > /sys/devices/system/cpu/cpu1/cpufreq/scaling_max_freq; +echo $MAXF > /sys/devices/system/cpu/cpu2/cpufreq/scaling_max_freq; +echo $MAXF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_max_freq; +echo Max CPU Frequency: $MAXF >> $KERNEL_LOGFILE; + +#Min CPU_FREQ +MINF="`cat /sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_min_freq`" +echo $MINF > /sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq; +echo $MINF > /sys/devices/system/cpu/cpu1/cpufreq/scaling_min_freq; +echo $MINF > /sys/devices/system/cpu/cpu2/cpufreq/scaling_min_freq; +echo $MINF > /sys/devices/system/cpu/cpu3/cpufreq/scaling_min_freq; +echo Min CPU Frequency: $MINF >> $KERNEL_LOGFILE; + +#I/O scheduler +if [ "`grep IOSCHED=1 $KERNEL_CONF`" ]; then +echo "cfq" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: cfq >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=2 $KERNEL_CONF`" ]; then +echo "row" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: row >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=3 $KERNEL_CONF`" ]; then +echo "deadline" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: deadline >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=4 $KERNEL_CONF`" ]; then +echo "fiops" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: fiops >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=5 $KERNEL_CONF`" ]; then +echo "sio" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: sio >> $KERNEL_LOGFILE; +elif [ "`grep IOSCHED=6 $KERNEL_CONF`" ]; then +echo "noop" > /sys/block/mmcblk0/queue/scheduler; +echo io scheduler: noop >> $KERNEL_LOGFILE; +fi + +#Read-ahead +if [ "`grep READAHEAD=1 $KERNEL_CONF`" ]; then +echo 128 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 128 >> $KERNEL_LOGFILE; +elif [ "`grep READAHEAD=2 $KERNEL_CONF`" ]; then +echo 256 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 256 >> $KERNEL_LOGFILE; +elif [ "`grep READAHEAD=3 $KERNEL_CONF`" ]; then +echo 512 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 512 >> $KERNEL_LOGFILE; +elif [ "`grep READAHEAD=4 $KERNEL_CONF`" ]; then +echo 1024 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 1024 >> $KERNEL_LOGFILE; +elif [ "`grep READAHEAD=5 $KERNEL_CONF`" ]; then +echo 2048 > /sys/block/mmcblk0/queue/read_ahead_kb; +echo Read-ahead: 2048 >> $KERNEL_LOGFILE; +fi + +#Backlight dimmer option +BLD=`grep "BLD" $KERNEL_CONF | cut -d '=' -f2` +echo $BLD > /sys/module/msm_fb/parameters/backlight_dimmer; +echo Backlight dimmer enabled\: $BLD >> $KERNEL_LOGFILE; + +#FAST CHARGE +if [ "`grep FAST_CHARGE=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/kernel/fast_charge/force_fast_charge; + echo fast charge enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/kernel/fast_charge/force_fast_charge; + echo fast charge disabled >> $KERNEL_LOGFILE; +fi + +#Set HOTPLUGDRV +if [ "`grep HOTPLUGDRV=1 $KERNEL_CONF`" ]; then + echo 0 > /sys/module/msm_mpdecision/parameters/enabled; + echo 1 > /sys/module/msm_hotplug/msm_enabled; + echo 0 > /sys/module/intelli_plug/parameters/intelli_plug_active; + echo 0 > /sys/module/intelli_plug/parameters/touch_boost_active; + echo MSM-hotplug enabled >> $KERNEL_LOGFILE; +elif [ "`grep HOTPLUGDRV=2 $KERNEL_CONF`" ]; then + echo 0 > /sys/module/msm_mpdecision/parameters/enabled; + echo 0 > /sys/module/msm_hotplug/msm_enabled; + echo 1 > /sys/module/intelli_plug/parameters/intelli_plug_active; + echo 1 > /sys/module/intelli_plug/parameters/touch_boost_active; + echo Intelli-Plug enabled >> $KERNEL_LOGFILE; +else + echo 1 > /sys/module/msm_mpdecision/parameters/enabled; + echo 0 > /sys/module/msm_hotplug/msm_enabled; + echo 0 > /sys/module/intelli_plug/parameters/intelli_plug_active; + echo 0 > /sys/module/intelli_plug/parameters/touch_boost_active; + echo Qualcomm MPdecision enabled >> $KERNEL_LOGFILE; +fi + +#Set Wake Gestures +if [ "`grep WG=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/wake_gestures + echo Wake gestures enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/wake_gestures + echo Wake gestures disabled >> $KERNEL_LOGFILE; +fi + +#Set S2W +S2W="`grep S2W $KERNEL_CONF | cut -d '=' -f2`" + echo $S2W > /sys/android_touch/sweep2wake + echo Sweep2wake $S2W >> $KERNEL_LOGFILE; + +#Set S2W SHORTSWEEP +if [ "`grep SHORTSWEEP=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/shortsweep; + echo Sweep2wake shortsweep enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/shortsweep; + echo Sweep2wake shortsweep disabled >> $KERNEL_LOGFILE; +fi + +#Set DOUBLETAP2WAKE +if [ "`grep DT2W=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/doubletap2wake; + echo DoubleTap2Wake enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/doubletap2wake; + echo DoubleTap2Wake disabled >> $KERNEL_LOGFILE; +fi + +#Set S2W/DT2W Power key toggle +if [ "`grep PWR_KEY=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/pwrkey_suspend; + echo "Power key toggle for S2W/DT2W enabled" >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/pwrkey_suspend; + echo "Power key toggle for S2W/DT2W disabled" >> $KERNEL_LOGFILE; +fi + +#Set S2W/DT2W Magnetic cover toggle +if [ "`grep LID_SUS=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/lid_suspend; + echo "Magnetic cover toggle for S2W/DT2W enabled" >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/lid_suspend; + echo "Magnetic cover toggle for S2W/DT2W disabled" >> $KERNEL_LOGFILE; +fi + +#Set S2W/DT2W Timeout +TIMEOUT=`grep "TIMEOUT" $KERNEL_CONF | cut -d '=' -f2` +echo $TIMEOUT > /sys/android_touch/wake_timeout +echo S2W/DT2W Timeout\: $TIMEOUT >> $KERNEL_LOGFILE; + +#Set S2S +if [ "`grep S2S=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/sweep2sleep + echo Sweep2sleep enabled >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/sweep2sleep + echo Sweep2sleep disabled >> $KERNEL_LOGFILE; +fi + +#Set S2S ORIENTATION +if [ "`grep ORIENTATION=1 $KERNEL_CONF`" ]; then + echo 1 > /sys/android_touch/orientation; + echo Disabled sweep2sleep in landscape mode >> $KERNEL_LOGFILE; +elif [ "`grep ORIENTATION=2 $KERNEL_CONF`" ]; then + echo 2 > /sys/android_touch/orientation; + echo Disabled sweep2sleep in portrait mode >> $KERNEL_LOGFILE; +else + echo 0 > /sys/android_touch/orientation; +fi + +#Set Magnetic on/off +if [ "`grep LID=0 $KERNEL_CONF`" ]; then + echo 0 > /sys/module/lid/parameters/enable_lid; + echo Magnetic on/off disabled >> $KERNEL_LOGFILE; +else + echo 1 > /sys/module/lid/parameters/enable_lid; + echo Magnetic on/off enabled >> $KERNEL_LOGFILE; +fi + +#USB Host mode charging +if [ "`grep OTGCM=1 $KERNEL_CONF`" ]; then + echo Y > /sys/module/msm_otg/parameters/usbhost_charge_mode; + echo USB OTG+Charge mode enabled >> $KERNEL_LOGFILE; +fi + +#MC Power savings +if [ "`grep MC_POWERSAVE=1 $KERNEL_CONF`" ]; then + echo 2 > /sys/devices/system/cpu/sched_mc_power_savings; + echo Maximum MC power savings >> $KERNEL_LOGFILE; +else + echo MC power savings disabled >> $KERNEL_LOGFILE; +fi + +#fstrim +fstrim -v /cache | tee -a $KERNEL_LOGFILE; +fstrim -v /data | tee -a $KERNEL_LOGFILE; + +#thermal settings +if [ "`grep THERM=1 $KERNEL_CONF`" ]; then + echo 80,82,90,100 > /sys/module/msm_thermal/parameters/limit_temp_degC; + echo run cool >> $KERNEL_LOGFILE; +elif [ "`grep THERM=2 $KERNEL_CONF`" ]; then + echo 85,90,97,105 > /sys/module/msm_thermal/parameters/limit_temp_degC; + echo run hot >> $KERNEL_LOGFILE; +fi + +#GPU Clock settings +if [ "`grep GPU_OC=1 $KERNEL_CONF`" ]; then + echo 320000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 320MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=3 $KERNEL_CONF`" ]; then + echo 450000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 450MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=4 $KERNEL_CONF`" ]; then + echo 504000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 504MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=5 $KERNEL_CONF`" ]; then + echo 545000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 545MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=6 $KERNEL_CONF`" ]; then + echo 600000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 600MHz GPU >> $KERNEL_LOGFILE; +elif [ "`grep GPU_OC=7 $KERNEL_CONF`" ]; then + echo 627000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 627MHz GPU >> $KERNEL_LOGFILE; +else + echo 400000000 > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/max_gpuclk; + echo 400MHz GPU >> $KERNEL_LOGFILE; +fi + +#GPU Governor settings +if [ "`grep GPU_GOV=2 $KERNEL_CONF`" ]; then + echo interactive > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; + echo Interactive GPU Governor >> $KERNEL_LOGFILE; +elif [ "`grep GPU_GOV=3 $KERNEL_CONF`" ]; then + echo performance > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; + echo Performance GPU Governor >> $KERNEL_LOGFILE; +else + echo ondemand > /sys/devices/platform/kgsl-3d0.0/kgsl/kgsl-3d0/pwrscale/trustzone/governor; + echo Ondemand GPU Governor >> $KERNEL_LOGFILE; +fi + +#GPU uV settings +if [ "`grep GPU_UV=2 $KERNEL_CONF`" ]; then + printf "920000\n1025000\n1125000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -25mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=3 $KERNEL_CONF`" ]; then + printf "895000\n1000000\n1100000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -50mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=4 $KERNEL_CONF`" ]; then + printf "870000\n975000\n1075000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -75mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=5 $KERNEL_CONF`" ]; then + printf "845000\n950000\n1050000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -100mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=6 $KERNEL_CONF`" ]; then + printf "820000\n925000\n1025000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -125mV GPU uV >> $KERNEL_LOGFILE; +elif [ "`grep GPU_UV=7 $KERNEL_CONF`" ]; then + printf "795000\n900000\n1000000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo -150mV GPU uV >> $KERNEL_LOGFILE; +else + printf "945000\n1050000\n1150000\n" > /sys/devices/system/cpu/cpufreq/vdd_table/vdd_levels_GPU; + echo Stock GPU voltage >> $KERNEL_LOGFILE; +fi + +#max scroff +if [ "`grep SCROFF=1 $KERNEL_CONF`" ]; then + echo 594000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 594MHz max screen off >> $KERNEL_LOGFILE; +elif [ "`grep SCROFF=2 $KERNEL_CONF`" ]; then + echo 702000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 702MHz max screen off >> $KERNEL_LOGFILE; +elif [ "`grep SCROFF=3 $KERNEL_CONF`" ]; then + echo 810000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 810MHz max screen off >> $KERNEL_LOGFILE; +elif [ "`grep SCROFF=4 $KERNEL_CONF`" ]; then + echo 1026000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 1026MHz max screen off >> $KERNEL_LOGFILE; +elif [ "`grep SCROFF=5 $KERNEL_CONF`" ]; then + echo 1242000 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max_freq; + echo 1242MHz max screen off >> $KERNEL_LOGFILE; +else + echo 0 > /sys/devices/system/cpu/cpu0/cpufreq/screen_off_max; + echo max screen off freq disabled >> $KERNEL_LOGFILE; +fi + +#Battery life extender +if [ "`grep BLE=2 $KERNEL_CONF`" ]; then + echo 4200 > /sys/devices/i2c-0/0-006a/float_voltage; + echo 4.2V charge voltage >> $KERNEL_LOGFILE; +elif [ "`grep BLE=3 $KERNEL_CONF`" ]; then + echo 4100 > /sys/devices/i2c-0/0-006a/float_voltage; + echo 4.1V charge voltage >> $KERNEL_LOGFILE; +elif [ "`grep BLE=4 $KERNEL_CONF`" ]; then + echo 4000 > /sys/devices/i2c-0/0-006a/float_voltage; + echo 4.0V charge voltage >> $KERNEL_LOGFILE; +else + echo 4300 > /sys/devices/i2c-0/0-006a/float_voltage; + echo Stock charge voltage >> $KERNEL_LOGFILE; +fi + +#exFAT support + insmod /system/lib/modules/exfat.ko; + echo exFAT module loaded >> $KERNEL_LOGFILE; + +#Backup settings to sdcard + cp /system/etc/glitch-settings.conf /sdcard/glitch-settings.conf; + echo "Settings backup created on sdcard root" >> $KERNEL_LOGFILE; + +#Wait a bit before applying governor changes +sleep 20 + +#CPU governor +if [ "`grep CPU_GOV=2 $KERNEL_CONF`" ]; then + governor=interactive +elif [ "`grep CPU_GOV=3 $KERNEL_CONF`" ]; then + governor=intellidemand +elif [ "`grep CPU_GOV=4 $KERNEL_CONF`" ]; then + governor=smartmax +elif [ "`grep CPU_GOV=5 $KERNEL_CONF`" ]; then + governor=smartmax_eps +elif [ "`grep CPU_GOV=6 $KERNEL_CONF`" ]; then + governor=intelliactive +elif [ "`grep CPU_GOV=7 $KERNEL_CONF`" ]; then + governor=conservative +else + governor=ondemand +fi + echo $governor > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor; + echo CPU Governor: $governor >> $KERNEL_LOGFILE; + +exit 0 diff --git a/release/aroma/wifi_mod/etc/wifi/WCNSS_qcom_cfg.ini b/release/aroma/wifi_mod/etc/wifi/WCNSS_qcom_cfg.ini new file mode 100755 index 00000000000..aa7e6164dc5 --- /dev/null +++ b/release/aroma/wifi_mod/etc/wifi/WCNSS_qcom_cfg.ini @@ -0,0 +1,254 @@ +# This file allows user to override the factory +# defaults for the WLAN Driver + +# Enable IMPS or not +gEnableImps=1 + +# Enable/Disable Idle Scan +gEnableIdleScan=0 + +# Increase sleep duration (seconds) during IMPS +# 0 implies no periodic wake up from IMPS. Periodic wakeup is +# unnecessary if Idle Scan is disabled. +gImpsModSleepTime=0 + +# Enable BMPS or not +gEnableBmps=1 + +# Enable Close Loop or not +gEnableCloseLoop=1 + +# Enable suspend or not +# 1: Enable standby, 2: Enable Deep sleep, 3: Enable Mcast/Bcast Filter +gEnableSuspend=3 + +# Phy Mode (auto, b, g, n, etc) +gDot11Mode=0 + +# Handoff Enable(1) Disable(0) +gEnableHandoff=0 + +# CSR Roaming Enable(1) Disable(0) +gRoamingTime=0 + +# Assigned MAC Addresses - This will be used until NV items are in place +# Each byte of MAC address is represented in Hex format as XX +Intf0MacAddress=000AF58989FF +Intf1MacAddress=000AF58989FE +Intf2MacAddress=000AF58989FD +Intf3MacAddress=000AF58989FC + +# UAPSD service interval for VO,VI, BE, BK traffic +InfraUapsdVoSrvIntv=0 +InfraUapsdViSrvIntv=0 +InfraUapsdBeSrvIntv=0 +InfraUapsdBkSrvIntv=0 + +# Enable Firmware RSSI monitoring for roaming +gEnableFWRssiMonitoring=1 + +# Make 1x1 the default antenna configuration +gNumRxAnt=1 + +# Beacon filtering frequency (unit in beacon intervals) +gNthBeaconFilter=50 + +# Enable WAPI or not +# WAPIIsEnabled=0 + +# Flags to filter Mcast and Bcast RX packets. +# Value 0: No filtering, 1: Filter all Multicast. +# 2: Filter all Broadcast. 3: Filter all Mcast and Bcast +McastBcastFilter=3 + +# Flag to enable Active mode offload +gEnableActiveModeOffload=1 + +# Flag to enable HostARPOffload feature or not +hostArpOffload=1 + +# Flag to enable Host IPv6 NS Offload feature or not +hostNSOffload=1 + +#SoftAP Related Parameters +# AP MAc addr (obsolete) +gAPMacAddr=000AF58989EF + +# Enable Random BSSID +gEnableApRandomBssid=1 + +# 802.11n Protection flag +gEnableApProt=1 + +# Enable OBSS protection +gEnableApOBSSProt=0 + +# Enable/Disable UAPSD for SoftAP +gEnableApUapsd=1 + +# Fixed Rate +gFixedRate=0 + +# Maximum Tx power +# gTxPowerCap=30 + +# Fragmentation Threshold +# gFragmentationThreshold=2346 + +# RTS threshold +RTSThreshold=2347 + +# Intra-BSS forward +gDisableIntraBssFwd=0 + +# WMM Enable/Disable +WmmIsEnabled=0 + +# 802.11d support +g11dSupportEnabled=1 + +# CCX Support and fast transition +CcxEnabled=0 +FastTransitionEnabled=1 +ImplicitQosIsEnabled=1 +gNeighborScanTimerPeriod=200 + +gNeighborLookupThreshold=76 +gNeighborReassocThreshold=81 + +gNeighborScanChannelMinTime=20 +gNeighborScanChannelMaxTime=30 +gMaxNeighborReqTries=3 + +# Legacy (non-CCX, non-802.11r) Fast Roaming Support +# To enable, set FastRoamEnabled=1, gEnableFWRssiMonitoring=1, FastTransitionEnabled=1 +# To disable, set FastRoamEnabled=0, gEnableFWRssiMonitoring=0, FastTransitionEnabled=0 +FastRoamEnabled=1 + +#Check if the AP to which we are roaming is better than current AP in terms of RSSI. +#Checking is disabled if set to Zero.Otherwise it will use this value as to how better +#the RSSI of the new/roamable AP should be for roaming +RoamRssiDiff=3 + +#Configure the RSSI gap that will be used to partition/categorize width of +#each individual category (aka bucket). +gRssiCatGap=5 + +# SAP Country code +# Default Country Code is 2 bytes, 3rd byte is optional indoor or out door. +# Example +# US Indoor, USI +# Korea Outdoor, KRO +# Japan without optional byte, JP +# France without optional byte, FR +#gAPCntryCode=USI + +#Short Guard Interval Enable/disable +gShortGI20Mhz=1 +gShortGI40Mhz=1 + +#Auto Shutdown Value in seconds. A value of 0 means Auto shutoff is disabled +gAPAutoShutOff=0 + +# SAP auto channel selection configuration +# 0 = disable auto channel selection +# 1 = enable auto channel selection, channel provided by supplicant will be ignored +gApAutoChannelSelection=0 + +# Listen Energy Detect Mode Configuration +# Valid values 0-128 +# 128 means disable Energy Detect feature +# 0-9 are threshold code and 7 is recommended value from system if feature is to be enabled. +# 10-128 are reserved. +# The EDET threshold mapping is as follows in 3dB step: +# 0 = -60 dBm +# 1 = -63 dBm +# 2 = -66 dBm +# ... +# 7 = -81 dBm +# 8 = -84 dBm +# 9 = -87 dBm +# Note: Any of these settings are valid. Setting 0 would yield the highest power saving (in a noisy environment) at the cost of more range. The range impact is approximately #calculated as: +# +# Range Loss (dB) = EDET threshold level (dBm) + 97 dBm. +# +gEnablePhyAgcListenMode=128 + +#Preferred band (both or 2.4 only or 5 only) +BandCapability=0 + +#Forced Device Listen Interval in multiples of DTIM Period aligned to DTIM +gEnableModulatedDTIM=3 + +#Beacon Early Termination (1 = enable the BET feature, 0 = disable) +enableBeaconEarlyTermination=1 +beaconEarlyTerminationWakeInterval=11 + +#Bluetooth Alternate Mac Phy (1 = enable the BT AMP feature, 0 = disable) +gEnableBtAmp=0 + +#Preferred channel to start BT AMP AP mode (0 means, any channel) +BtAmpPreferredChannel=0 + +#SOFTAP Channel Range selection +gAPChannelSelectStartChannel=1 +gAPChannelSelectEndChannel=11 + +#SOFTAP Channel Range selection Operating band +# 0:2.4GHZ 1: LOW-5GHZ 2:MID-5GHZ 3:HIGH-5GHZ 4: 4.9HZ BAND +gAPChannelSelectOperatingBand=0 + +#Enable Keep alive with non-zero period value +gStaKeepAlivePeriod = 25 + +#If set will start with active scan after driver load, otherwise will start with +#passive scan to find out the domain +gEnableBypass11d=1 + +#If set to 0, will not scan DFS channels +gEnableDFSChnlScan=1 + +# Enable logp/SSR +gEnableLogp=1 + +# Enable HT40 +gChannelBondingMode5GHz=1 + +# Enable Automatic Tx Power control +gEnableAutomaticTxPowerControl=1 + +# Derive P2P MAC address from primary MAC address +isP2pDeviceAddrAdministrated=1 + +# Disable channel 165 for Indonesia +gIgnore_Chan165=1 + +btcStaticLenLeBt=120000 +btcStaticLenLeWlan=30000 + +#Data Inactivity Timeout when in powersave (in ms) +gDataInactivityTimeout=200 + +gCountryCodePriority=1 + +gNumChanCombinedConc=255 + +# TDLS configuration +gEnableTDLSSupport=1 +gEnableTDLSImplicitTrigger=1 +gTDLSExternalControl=1 +gTDLSTxStatsPeriod=500 +gTDLSTxPacketThreshold=10 +gTDLSDiscoveryPeriod=20000 +gTDLSMaxDiscoveryAttempt=5 +gTDLSIdleTimeout=40000 +gTDLSRssiHysteresis=100 +gTDLSRSSITriggerThreshold=-60 +gTDLSIdlePacketThreshold=5 +gTDLSRSSITeardownThreshold=-70 + +# Enable IPv6 RA filtering +gMCAddrListEnable=1 + +END +# Note: Configuration parser would not read anything past the END marker diff --git a/release/aroma/wifi_mod/vendor/firmware/wlan/prima/WCNSS_cfg.dat b/release/aroma/wifi_mod/vendor/firmware/wlan/prima/WCNSS_cfg.dat new file mode 100755 index 00000000000..16ba06f087a Binary files /dev/null and b/release/aroma/wifi_mod/vendor/firmware/wlan/prima/WCNSS_cfg.dat differ diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 0be6f110cce..8e40f0699f4 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -304,6 +304,11 @@ cmd_lzo = (cat $(filter-out FORCE,$^) | \ lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ (rm -f $@ ; false) +quiet_cmd_lz4 = LZ4 $@ +cmd_lz4 = (cat $(filter-out FORCE,$^) | \ + lz4c -l -c1 stdin stdout && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) + # U-Boot mkimage # --------------------------------------------------------------------------- diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 857ea4fccb8..94a482234fb 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -55,7 +55,7 @@ scm_version() # If only the short version is requested, # don't bother running further git commands if $short; then - echo "+" + echo "" return fi printf '%s%s' -g "`git show-ref -s --abbrev --tags $atag 2>/dev/null`" @@ -65,7 +65,7 @@ scm_version() # If only the short version is requested, don't bother # running further git commands if $short; then - echo "+" + echo "" return fi # If we are past a tagged commit (like diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index b28b7eb3ca4..2b356575526 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -217,6 +217,14 @@ static int inode_alloc_security(struct inode *inode) return 0; } +static void inode_free_rcu(struct rcu_head *head) +{ + struct inode_security_struct *isec; + + isec = container_of(head, struct inode_security_struct, rcu); + kmem_cache_free(sel_inode_cache, isec); +} + static void inode_free_security(struct inode *inode) { struct inode_security_struct *isec = inode->i_security; @@ -227,8 +235,16 @@ static void inode_free_security(struct inode *inode) list_del_init(&isec->list); spin_unlock(&sbsec->isec_lock); - inode->i_security = NULL; - kmem_cache_free(sel_inode_cache, isec); + /* + * The inode may still be referenced in a path walk and + * a call to selinux_inode_permission() can be made + * after inode_free_security() is called. Ideally, the VFS + * wouldn't do this, but fixing that is a much harder + * job. For now, simply free the i_security via RCU, and + * leave the current inode->i_security pointer intact. + * The inode will be freed after the RCU grace period too. + */ + call_rcu(&isec->rcu, inode_free_rcu); } static int file_alloc_security(struct file *file) diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h index 4a4a9aebca9..20b00fc37cc 100644 --- a/security/selinux/include/classmap.h +++ b/security/selinux/include/classmap.h @@ -145,7 +145,9 @@ struct security_class_mapping secclass_map[] = { "node_bind", "name_connect", NULL } }, { "memprotect", { "mmap_zero", NULL } }, { "peer", { "recv", NULL } }, - { "capability2", { "mac_override", "mac_admin", "syslog", NULL } }, + { "capability2", + { "mac_override", "mac_admin", "syslog", "wake_alarm", "block_suspend", + NULL } }, { "kernel_service", { "use_as_override", "create_files_as", NULL } }, { "tun_socket", { COMMON_SOCK_PERMS, NULL } }, diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 26c7eee1c30..7b1830bde1c 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h @@ -38,7 +38,10 @@ struct task_security_struct { struct inode_security_struct { struct inode *inode; /* back pointer to inode object */ - struct list_head list; /* list of inode_security_struct */ + union { + struct list_head list; /* list of inode_security_struct */ + struct rcu_head rcu; /* for freeing the inode_security_struct */ + }; u32 task_sid; /* SID of creating task */ u32 sid; /* SID of this object */ u16 sclass; /* security class of this object */ diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 185f849a26f..72b20b1089d 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1229,6 +1229,10 @@ static int security_context_to_sid_core(const char *scontext, u32 scontext_len, struct context context; int rc = 0; + /* An empty security context is never valid. */ + if (!scontext_len) + return -EINVAL; + if (!ss_initialized) { int i; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0e99137db86..aec054a739f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -454,3 +454,16 @@ config SND_SOC_TPA2028D default n help Texas Instruments 3W Mono Class-D Audio Amplifier + +config SOUND_CONTROL_HAX_GPL + tristate "wcd93xx sound control hax" + default y + help + FauxSound WCD93xx chipset sound control hacks + +config SOUND_CONTROL_HAX_3_GPL + tristate "new wcd93xx sound control hax" + default y + help + FauxSound WCD93xx chipset sound control hacks 3.0 for deeper hax + diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index ec05d3c644d..7e105b53d47 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -213,3 +213,8 @@ obj-$(CONFIG_SND_SOC_MSM_STUB) += snd-soc-msm-stub.o obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o obj-$(CONFIG_SND_SOC_TPA2028D) += tpa2028d.o + +# Hack +obj-$(CONFIG_SOUND_CONTROL_HAX_GPL) += sound_control_gpl.o +obj-$(CONFIG_SOUND_CONTROL_HAX_3_GPL) += sound_control_3_gpl.o + diff --git a/sound/soc/codecs/sound_control_3_gpl.c b/sound/soc/codecs/sound_control_3_gpl.c new file mode 100644 index 00000000000..e53823ed40b --- /dev/null +++ b/sound/soc/codecs/sound_control_3_gpl.c @@ -0,0 +1,545 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * WCD93xx sound control module + * Copyright 2013 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 + +#define SOUND_CONTROL_MAJOR_VERSION 3 +#define SOUND_CONTROL_MINOR_VERSION 6 + +extern struct snd_soc_codec *fauxsound_codec_ptr; +extern int wcd9xxx_hw_revision; + +static int snd_ctrl_locked = 0; +static int snd_rec_ctrl_locked = 0; + +unsigned int tabla_read(struct snd_soc_codec *codec, unsigned int reg); +int tabla_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value); + + +#define REG_SZ 25 +static unsigned int cached_regs[] = {6, 6, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 }; + +static unsigned int *cache_select(unsigned int reg) +{ + unsigned int *out = NULL; + + switch (reg) { + case TABLA_A_RX_HPH_L_GAIN: + out = &cached_regs[0]; + break; + case TABLA_A_RX_HPH_R_GAIN: + out = &cached_regs[1]; + break; + case TABLA_A_CDC_RX1_VOL_CTL_B2_CTL: + out = &cached_regs[4]; + break; + case TABLA_A_CDC_RX2_VOL_CTL_B2_CTL: + out = &cached_regs[5]; + break; + case TABLA_A_CDC_RX3_VOL_CTL_B2_CTL: + out = &cached_regs[6]; + break; + case TABLA_A_CDC_RX4_VOL_CTL_B2_CTL: + out = &cached_regs[7]; + break; + case TABLA_A_CDC_RX5_VOL_CTL_B2_CTL: + out = &cached_regs[8]; + break; + case TABLA_A_CDC_RX6_VOL_CTL_B2_CTL: + out = &cached_regs[9]; + break; + case TABLA_A_CDC_RX7_VOL_CTL_B2_CTL: + out = &cached_regs[10]; + break; + case TABLA_A_CDC_TX1_VOL_CTL_GAIN: + out = &cached_regs[11]; + break; + case TABLA_A_CDC_TX2_VOL_CTL_GAIN: + out = &cached_regs[12]; + break; + case TABLA_A_CDC_TX3_VOL_CTL_GAIN: + out = &cached_regs[13]; + break; + case TABLA_A_CDC_TX4_VOL_CTL_GAIN: + out = &cached_regs[14]; + break; + case TABLA_A_CDC_TX5_VOL_CTL_GAIN: + out = &cached_regs[15]; + break; + case TABLA_A_CDC_TX6_VOL_CTL_GAIN: + out = &cached_regs[16]; + break; + case TABLA_A_CDC_TX7_VOL_CTL_GAIN: + out = &cached_regs[17]; + break; + case TABLA_A_CDC_TX8_VOL_CTL_GAIN: + out = &cached_regs[18]; + break; + case TABLA_A_CDC_TX9_VOL_CTL_GAIN: + out = &cached_regs[19]; + break; + case TABLA_A_CDC_TX10_VOL_CTL_GAIN: + out = &cached_regs[20]; + break; + case TABLA_A_RX_LINE_1_GAIN: + out = &cached_regs[21]; + break; + case TABLA_A_RX_LINE_2_GAIN: + out = &cached_regs[22]; + break; + case TABLA_A_RX_LINE_3_GAIN: + out = &cached_regs[23]; + break; + case TABLA_A_RX_LINE_4_GAIN: + out = &cached_regs[24]; + break; + } + return out; +} + +void snd_hax_cache_write(unsigned int reg, unsigned int value) +{ + unsigned int *tmp = cache_select(reg); + + if (tmp != NULL) + *tmp = value; +} +EXPORT_SYMBOL(snd_hax_cache_write); + +unsigned int snd_hax_cache_read(unsigned int reg) +{ + if (cache_select(reg) != NULL) + return *cache_select(reg); + else + return -1; +} +EXPORT_SYMBOL(snd_hax_cache_read); + +int snd_hax_reg_access(unsigned int reg) +{ + int ret = 1; + + switch (reg) { + case TABLA_A_RX_HPH_L_GAIN: + case TABLA_A_RX_HPH_R_GAIN: + case TABLA_A_RX_HPH_L_STATUS: + case TABLA_A_RX_HPH_R_STATUS: + if (snd_ctrl_locked > 1) + ret = 0; + break; + case TABLA_A_CDC_RX1_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX2_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX3_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX4_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX5_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX6_VOL_CTL_B2_CTL: + case TABLA_A_CDC_RX7_VOL_CTL_B2_CTL: + case TABLA_A_RX_LINE_1_GAIN: + case TABLA_A_RX_LINE_2_GAIN: + case TABLA_A_RX_LINE_3_GAIN: + case TABLA_A_RX_LINE_4_GAIN: + if (snd_ctrl_locked > 0) + ret = 0; + break; + case TABLA_A_CDC_TX1_VOL_CTL_GAIN: + case TABLA_A_CDC_TX2_VOL_CTL_GAIN: + case TABLA_A_CDC_TX3_VOL_CTL_GAIN: + case TABLA_A_CDC_TX4_VOL_CTL_GAIN: + case TABLA_A_CDC_TX5_VOL_CTL_GAIN: + case TABLA_A_CDC_TX6_VOL_CTL_GAIN: + case TABLA_A_CDC_TX7_VOL_CTL_GAIN: + case TABLA_A_CDC_TX8_VOL_CTL_GAIN: + case TABLA_A_CDC_TX9_VOL_CTL_GAIN: + case TABLA_A_CDC_TX10_VOL_CTL_GAIN: + if (snd_rec_ctrl_locked > 0) + ret = 0; + break; + default: + break; + } + return ret; +} +EXPORT_SYMBOL(snd_hax_reg_access); + +static bool calc_checksum(unsigned int a, unsigned int b, unsigned int c) +{ + unsigned char chksum = 0; + + chksum = ~((a & 0xff) + (b & 0xff)); + + if (chksum == (c & 0xff)) { + return true; + } else { + return false; + } +} + +static ssize_t cam_mic_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_TX6_VOL_CTL_GAIN)); + +} + +static ssize_t cam_mic_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, chksum; + + sscanf(buf, "%u %u", &lval, &chksum); + + if (calc_checksum(lval, 0, chksum)) { + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_TX6_VOL_CTL_GAIN, lval); + } + return count; +} + +static ssize_t mic_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u\n", + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_TX7_VOL_CTL_GAIN)); +} + +static ssize_t mic_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, chksum; + + sscanf(buf, "%u %u", &lval, &chksum); + + if (calc_checksum(lval, 0, chksum)) { + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_TX7_VOL_CTL_GAIN, lval); + } + return count; + +} + +static ssize_t speaker_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u %u\n", + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_RX3_VOL_CTL_B2_CTL), + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_RX4_VOL_CTL_B2_CTL)); + +} + +static ssize_t speaker_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, rval, chksum; + + sscanf(buf, "%u %u %u", &lval, &rval, &chksum); + + if (calc_checksum(lval, rval, chksum)) { + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_RX3_VOL_CTL_B2_CTL, lval); + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_RX4_VOL_CTL_B2_CTL, rval); + } + return count; +} + +static ssize_t headphone_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u %u\n", + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_RX1_VOL_CTL_B2_CTL), + tabla_read(fauxsound_codec_ptr, + TABLA_A_CDC_RX2_VOL_CTL_B2_CTL)); +} + +static ssize_t headphone_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, rval, chksum; + + sscanf(buf, "%u %u %u", &lval, &rval, &chksum); + + if (calc_checksum(lval, rval, chksum)) { + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_RX1_VOL_CTL_B2_CTL, lval); + tabla_write(fauxsound_codec_ptr, + TABLA_A_CDC_RX2_VOL_CTL_B2_CTL, rval); + } + return count; +} + +static ssize_t headphone_pa_gain_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%u %u\n", + tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_GAIN), + tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_GAIN)); +} + +static ssize_t headphone_pa_gain_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int lval, rval, chksum; + unsigned int gain, status; + unsigned int out; + + sscanf(buf, "%u %u %u", &lval, &rval, &chksum); + + if (calc_checksum(lval, rval, chksum)) { + gain = tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_GAIN); + out = (gain & 0xf0) | lval; + tabla_write(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_GAIN, out); + + status = tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_STATUS); + out = (status & 0x0f) | (lval << 4); + tabla_write(fauxsound_codec_ptr, TABLA_A_RX_HPH_L_STATUS, out); + + gain = tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_GAIN); + out = (gain & 0xf0) | rval; + tabla_write(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_GAIN, out); + + status = tabla_read(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_STATUS); + out = (status & 0x0f) | (rval << 4); + tabla_write(fauxsound_codec_ptr, TABLA_A_RX_HPH_R_STATUS, out); + } + return count; +} + +static unsigned int selected_reg = 0xdeadbeef; + +static ssize_t sound_reg_select_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + sscanf(buf, "%u", &selected_reg); + + return count; +} + +static ssize_t sound_reg_read_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + if (selected_reg == 0xdeadbeef) + return -1; + else + return sprintf(buf, "%u\n", + tabla_read(fauxsound_codec_ptr, selected_reg)); +} + +static ssize_t sound_reg_write_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + unsigned int out, chksum; + + sscanf(buf, "%u %u", &out, &chksum); + if (calc_checksum(out, 0, chksum)) { + if (selected_reg != 0xdeadbeef) + tabla_write(fauxsound_codec_ptr, selected_reg, out); + } + return count; +} + +static ssize_t sound_control_hw_revision_show (struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "hw_revision: %i\n", wcd9xxx_hw_revision); +} + +static ssize_t sound_control_version_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "version: %u.%u\n", + SOUND_CONTROL_MAJOR_VERSION, + SOUND_CONTROL_MINOR_VERSION); +} + +static ssize_t sound_control_locked_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int inp; + + sscanf(buf, "%d", &inp); + + snd_ctrl_locked = inp; + + return count; +} + +static ssize_t sound_control_locked_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", snd_ctrl_locked); +} + +static ssize_t sound_control_rec_locked_store(struct kobject *kobj, + struct kobj_attribute *attr, const char *buf, size_t count) +{ + int inp; + + sscanf(buf, "%d", &inp); + + snd_rec_ctrl_locked = inp; + + return count; +} + +static ssize_t sound_control_rec_locked_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n", snd_ctrl_locked); +} + +static struct kobj_attribute sound_reg_sel_attribute = + __ATTR(sound_reg_sel, + 0222, + NULL, + sound_reg_select_store); + +static struct kobj_attribute sound_reg_read_attribute = + __ATTR(sound_reg_read, + 0444, + sound_reg_read_show, + NULL); + +static struct kobj_attribute sound_reg_write_attribute = + __ATTR(sound_reg_write, + 0222, + NULL, + sound_reg_write_store); + +static struct kobj_attribute cam_mic_gain_attribute = + __ATTR(gpl_cam_mic_gain, + 0666, + cam_mic_gain_show, + cam_mic_gain_store); + +static struct kobj_attribute mic_gain_attribute = + __ATTR(gpl_mic_gain, + 0666, + mic_gain_show, + mic_gain_store); + +static struct kobj_attribute speaker_gain_attribute = + __ATTR(gpl_speaker_gain, + 0666, + speaker_gain_show, + speaker_gain_store); + +static struct kobj_attribute headphone_gain_attribute = + __ATTR(gpl_headphone_gain, + 0666, + headphone_gain_show, + headphone_gain_store); + +static struct kobj_attribute headphone_pa_gain_attribute = + __ATTR(gpl_headphone_pa_gain, + 0666, + headphone_pa_gain_show, + headphone_pa_gain_store); + +static struct kobj_attribute sound_control_locked_attribute = + __ATTR(gpl_sound_control_locked, + 0666, + sound_control_locked_show, + sound_control_locked_store); + +static struct kobj_attribute sound_control_rec_locked_attribute = + __ATTR(gpl_sound_control_rec_locked, + 0666, + sound_control_rec_locked_show, + sound_control_rec_locked_store); + +static struct kobj_attribute sound_control_version_attribute = + __ATTR(gpl_sound_control_version, + 0444, + sound_control_version_show, NULL); + +static struct kobj_attribute sound_hw_revision_attribute = + __ATTR(gpl_sound_control_hw_revision, + 0444, + sound_control_hw_revision_show, NULL); + +static struct attribute *sound_control_attrs[] = + { + &cam_mic_gain_attribute.attr, + &mic_gain_attribute.attr, + &speaker_gain_attribute.attr, + &headphone_gain_attribute.attr, + &headphone_pa_gain_attribute.attr, + &sound_control_locked_attribute.attr, + &sound_control_rec_locked_attribute.attr, + &sound_reg_sel_attribute.attr, + &sound_reg_read_attribute.attr, + &sound_reg_write_attribute.attr, + &sound_hw_revision_attribute.attr, + &sound_control_version_attribute.attr, + NULL, + }; + +static struct attribute_group sound_control_attr_group = + { + .attrs = sound_control_attrs, + }; + +static struct kobject *sound_control_kobj; + +static int sound_control_init(void) +{ + int sysfs_result; + + sound_control_kobj = + kobject_create_and_add("sound_control_3", kernel_kobj); + + if (!sound_control_kobj) { + pr_err("%s sound_control_kobj create failed!\n", + __FUNCTION__); + return -ENOMEM; + } + + sysfs_result = sysfs_create_group(sound_control_kobj, + &sound_control_attr_group); + + if (sysfs_result) { + pr_info("%s sysfs create failed!\n", __FUNCTION__); + kobject_put(sound_control_kobj); + } + return sysfs_result; +} + +static void sound_control_exit(void) +{ + if (sound_control_kobj != NULL) + kobject_put(sound_control_kobj); +} + +module_init(sound_control_init); +module_exit(sound_control_exit); +MODULE_LICENSE("GPL and additional rights"); +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("Sound Control Module 3.x"); + diff --git a/sound/soc/codecs/sound_control_gpl.c b/sound/soc/codecs/sound_control_gpl.c new file mode 100644 index 00000000000..db50d0d752c --- /dev/null +++ b/sound/soc/codecs/sound_control_gpl.c @@ -0,0 +1,325 @@ +/* + * Author: Paul Reioux aka Faux123 + * + * WCD93xx sound control module + * Copyright 2013 Paul Reioux + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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 + +extern struct snd_kcontrol_new *gpl_faux_snd_controls_ptr; + +#define SOUND_CONTROL_MAJOR_VERSION 2 +#define SOUND_CONTROL_MINOR_VERSION 1 + +#define CAMCORDER_MIC_OFFSET 20 +#define HANDSET_MIC_OFFSET 21 +#define SPEAKER_OFFSET 10 +#define HEADPHONE_L_OFFSET 8 +#define HEADPHONE_R_OFFSET 9 + +#define HEADPHONE_PA_L_OFFSET 6 +#define HEADPHONE_PA_R_OFFSET 7 + +static ssize_t cam_mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[CAMCORDER_MIC_OFFSET]. + private_value; + + return sprintf(buf, "%d", l_mixer_ptr->max); +} + +static ssize_t cam_mic_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max; + int l_delta; + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[CAMCORDER_MIC_OFFSET]. + private_value; + + sscanf(buf, "%d", &l_max); + + // limit the max gain + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + return (count); +} + +static ssize_t mic_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HANDSET_MIC_OFFSET]. + private_value; + + return sprintf(buf, "%d", l_mixer_ptr->max); +} + +static ssize_t mic_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max; + int l_delta; + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HANDSET_MIC_OFFSET]. + private_value; + + sscanf(buf, "%d", &l_max); + + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + return (count); +} + +static ssize_t speaker_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[SPEAKER_OFFSET]. + private_value; + + return sprintf(buf, "%d", l_mixer_ptr->max); +} + +static ssize_t speaker_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max; + int l_delta; + struct soc_mixer_control *l_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[SPEAKER_OFFSET]. + private_value; + + sscanf(buf, "%d", &l_max); + + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + return (count); +} + +static ssize_t headphone_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_L_OFFSET]. + private_value; + r_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_R_OFFSET]. + private_value; + + return sprintf(buf, "%d %d", + l_mixer_ptr->max, + r_mixer_ptr->max); +} + +static ssize_t headphone_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max, r_max; + int l_delta, r_delta; + struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_L_OFFSET]. + private_value; + r_mixer_ptr = + (struct soc_mixer_control *)gpl_faux_snd_controls_ptr[HEADPHONE_R_OFFSET]. + private_value; + + sscanf(buf, "%d %d", &l_max, &r_max); + + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + r_delta = r_max - r_mixer_ptr->platform_max; + r_mixer_ptr->platform_max = r_max; + r_mixer_ptr->max = r_max; + r_mixer_ptr->min += r_delta; + + return count; +} + +static ssize_t headphone_pa_gain_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *) + gpl_faux_snd_controls_ptr[HEADPHONE_PA_L_OFFSET]. + private_value; + r_mixer_ptr = + (struct soc_mixer_control *) + gpl_faux_snd_controls_ptr[HEADPHONE_PA_R_OFFSET]. + private_value; + + return sprintf(buf, "%d %d", + l_mixer_ptr->max, + r_mixer_ptr->max); +} + +static ssize_t headphone_pa_gain_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count) +{ + int l_max, r_max; + int l_delta, r_delta; + struct soc_mixer_control *l_mixer_ptr, *r_mixer_ptr; + + l_mixer_ptr = + (struct soc_mixer_control *) + gpl_faux_snd_controls_ptr[HEADPHONE_PA_L_OFFSET]. + private_value; + r_mixer_ptr = + (struct soc_mixer_control *) + gpl_faux_snd_controls_ptr[HEADPHONE_PA_R_OFFSET]. + private_value; + + sscanf(buf, "%d %d", &l_max, &r_max); + + l_delta = l_max - l_mixer_ptr->platform_max; + l_mixer_ptr->platform_max = l_max; + l_mixer_ptr->max = l_max; + l_mixer_ptr->min += l_delta; + + r_delta = r_max - r_mixer_ptr->platform_max; + r_mixer_ptr->platform_max = r_max; + r_mixer_ptr->max = r_max; + r_mixer_ptr->min += r_delta; + + return count; +} + +static ssize_t sound_control_version_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) +{ + return sprintf(buf, "version: %u.%u\n", + SOUND_CONTROL_MAJOR_VERSION, + SOUND_CONTROL_MINOR_VERSION); +} + +static struct kobj_attribute cam_mic_gain_attribute = + __ATTR(gpl_cam_mic_gain, + 0666, + cam_mic_gain_show, + cam_mic_gain_store); + +static struct kobj_attribute mic_gain_attribute = + __ATTR(gpl_mic_gain, + 0666, + mic_gain_show, + mic_gain_store); + +static struct kobj_attribute speaker_gain_attribute = + __ATTR(gpl_speaker_gain, + 0666, + speaker_gain_show, + speaker_gain_store); + +static struct kobj_attribute headphone_gain_attribute = + __ATTR(gpl_headphone_gain, + 0666, + headphone_gain_show, + headphone_gain_store); + +static struct kobj_attribute headphone_pa_gain_attribute = + __ATTR(gpl_headphone_pa_gain, + 0666, + headphone_pa_gain_show, + headphone_pa_gain_store); + +static struct kobj_attribute sound_control_version_attribute = + __ATTR(gpl_sound_control_version, + 0444, + sound_control_version_show, NULL); + +static struct attribute *sound_control_attrs[] = + { + &cam_mic_gain_attribute.attr, + &mic_gain_attribute.attr, + &speaker_gain_attribute.attr, + &headphone_gain_attribute.attr, + &headphone_pa_gain_attribute.attr, + &sound_control_version_attribute.attr, + NULL, + }; + +static struct attribute_group sound_control_attr_group = + { + .attrs = sound_control_attrs, + }; + +static struct kobject *sound_control_kobj; + +static int sound_control_init(void) +{ + int sysfs_result; + + if (gpl_faux_snd_controls_ptr == NULL) { + pr_err("%s sound_controls_ptr is NULL!\n", __FUNCTION__); + return -1; + } + + sound_control_kobj = + kobject_create_and_add("sound_control", kernel_kobj); + + if (!sound_control_kobj) { + pr_err("%s sound_control_kobj create failed!\n", + __FUNCTION__); + return -ENOMEM; + } + + sysfs_result = sysfs_create_group(sound_control_kobj, + &sound_control_attr_group); + + if (sysfs_result) { + pr_info("%s sysfs create failed!\n", __FUNCTION__); + kobject_put(sound_control_kobj); + } + return sysfs_result; +} + +static void sound_control_exit(void) +{ + if (sound_control_kobj != NULL) + kobject_put(sound_control_kobj); +} + +module_init(sound_control_init); +module_exit(sound_control_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Paul Reioux "); +MODULE_DESCRIPTION("Sound Control Module GPL Edition"); + diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c index 3b9fa6de897..db4664b0bd4 100644 --- a/sound/soc/codecs/wcd9310.c +++ b/sound/soc/codecs/wcd9310.c @@ -2887,11 +2887,27 @@ static int tabla_codec_reset_interpolator(struct snd_soc_dapm_widget *w, static int tabla_codec_enable_ldo_h(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { + struct snd_soc_codec *codec = w->codec; + struct tabla_priv *tabla = NULL; + + if (codec != NULL) + tabla = snd_soc_codec_get_drvdata(codec); + switch (event) { case SND_SOC_DAPM_POST_PMU: - case SND_SOC_DAPM_POST_PMD: usleep_range(1000, 1000); break; + case SND_SOC_DAPM_POST_PMD: + /* + * Don't disable LDO_H while headset is inserted. + * Headset need LDO_H always on. + */ + if (tabla->h2w_state == H2W_HEADSET) { + snd_soc_update_bits(codec, TABLA_A_LDO_H_MODE_1, + 0x80, 0x80); + } else + usleep_range(1000, 1000); + break; } return 0; } @@ -3852,6 +3868,7 @@ static int tabla_readable(struct snd_soc_codec *ssc, unsigned int reg) return tabla_reg_readable[reg]; } + static bool tabla_is_digital_gain_register(unsigned int reg) { bool rtn = false; @@ -3918,24 +3935,18 @@ static int tabla_volatile(struct snd_soc_codec *ssc, unsigned int reg) return 0; } - #define TABLA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) -static int tabla_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ - int ret; - BUG_ON(reg > TABLA_MAX_REGISTER); - if (!tabla_volatile(codec, reg)) { - ret = snd_soc_cache_write(codec, reg, value); - if (ret != 0) - dev_err(codec->dev, "Cache write to %x failed: %d\n", - reg, ret); - } +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +extern int snd_hax_reg_access(unsigned int); +extern unsigned int snd_hax_cache_read(unsigned int); +extern void snd_hax_cache_write(unsigned int, unsigned int); +#endif - return wcd9xxx_reg_write(codec->control_data, reg, value); -} -static unsigned int tabla_read(struct snd_soc_codec *codec, +#ifndef CONFIG_SOUND_CONTROL_HAX_3_GPL +static +#endif +unsigned int tabla_read(struct snd_soc_codec *codec, unsigned int reg) { unsigned int val; @@ -3956,6 +3967,46 @@ static unsigned int tabla_read(struct snd_soc_codec *codec, val = wcd9xxx_reg_read(codec->control_data, reg); return val; } +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +EXPORT_SYMBOL(tabla_read); +#endif + +#ifndef CONFIG_SOUND_CONTROL_HAX_3_GPL +static +#endif +int tabla_write(struct snd_soc_codec *codec, unsigned int reg, + unsigned int value) +{ + int ret; +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL + int val; +#endif + + BUG_ON(reg > TABLA_MAX_REGISTER); + + if (!tabla_volatile(codec, reg)) { + ret = snd_soc_cache_write(codec, reg, value); + if (ret != 0) + dev_err(codec->dev, "Cache write to %x failed: %d\n", + reg, ret); + } +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL + if (!snd_hax_reg_access(reg)) { + if (!((val = snd_hax_cache_read(reg)) != -1)) { + val = wcd9xxx_reg_read_safe(codec->control_data, reg); + } + } else { + snd_hax_cache_write(reg, value); + val = value; + } + return wcd9xxx_reg_write(codec->control_data, reg, val); +#else + return wcd9xxx_reg_write(codec->control_data, reg, value); +#endif +} +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +EXPORT_SYMBOL(tabla_write); +#endif static s16 tabla_get_current_v_ins(struct tabla_priv *tabla, bool hu) { @@ -5164,7 +5215,8 @@ static const struct snd_soc_dapm_widget tabla_dapm_widgets[] = { 0), SND_SOC_DAPM_SUPPLY("LDO_H", TABLA_A_LDO_H_MODE_1, 7, 0, - tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU), + tabla_codec_enable_ldo_h, SND_SOC_DAPM_POST_PMU | + SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_SUPPLY("COMP1_CLK", SND_SOC_NOPM, 0, 0, tabla_config_compander, SND_SOC_DAPM_PRE_PMU | @@ -8391,6 +8443,15 @@ static const struct file_operations codec_mbhc_debug_ops = { }; #endif +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL +struct snd_kcontrol_new *gpl_faux_snd_controls_ptr = + (struct snd_kcontrol_new *)tabla_snd_controls; +struct snd_soc_codec *fauxsound_codec_ptr; +EXPORT_SYMBOL(fauxsound_codec_ptr); +int wcd9xxx_hw_revision; +EXPORT_SYMBOL(wcd9xxx_hw_revision); +#endif + static int tabla_codec_probe(struct snd_soc_codec *codec) { struct wcd9xxx *control; @@ -8400,10 +8461,22 @@ static int tabla_codec_probe(struct snd_soc_codec *codec) int i; int ch_cnt; +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL + pr_info("tabla codec probe...\n"); + fauxsound_codec_ptr = codec; +#endif + codec->control_data = dev_get_drvdata(codec->dev->parent); control = codec->control_data; +#ifdef CONFIG_SOUND_CONTROL_HAX_3_GPL + if (TABLA_IS_2_0(control->version)) + wcd9xxx_hw_revision = 1; + else + wcd9xxx_hw_revision = 2; +#endif tabla = kzalloc(sizeof(struct tabla_priv), GFP_KERNEL); + if (!tabla) { dev_err(codec->dev, "Failed to allocate private data\n"); return -ENOMEM; diff --git a/sound/soc/msm/asustek_headset.c b/sound/soc/msm/asustek_headset.c index 3d4ce127ed9..68b34824d47 100644 --- a/sound/soc/msm/asustek_headset.c +++ b/sound/soc/msm/asustek_headset.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -104,11 +105,16 @@ struct work_struct lineout_work; static void set_hs_micbias(int status) { + struct snd_soc_dapm_widget *w = NULL; + if (wcd9310_codec == NULL) { printk(KERN_INFO "%s: wcd9310_codec = NULL\n", __func__); return; } + w = snd_soc_get_codec_widget(wcd9310_codec->card, + wcd9310_codec, "LDO_H"); + if (status) { snd_soc_update_bits(wcd9310_codec, TABLA_A_MICB_CFILT_2_VAL, 0xFC, (0x28 << 2)); @@ -127,8 +133,14 @@ static void set_hs_micbias(int status) } else { snd_soc_update_bits(wcd9310_codec, TABLA_A_MICB_2_CTL, 0xC0, 0x00); - snd_soc_update_bits(wcd9310_codec, TABLA_A_LDO_H_MODE_1, - 0xff, 0x6d); + /* Keep LDO_H power on while using */ + if (w != NULL && w->power) + printk(KERN_INFO "%s widget LDO_H power on. Keep it\n", + __func__); + else + snd_soc_update_bits(wcd9310_codec, + TABLA_A_LDO_H_MODE_1, 0xff, 0x6d); + if (tabla_check_bandgap_status(wcd9310_codec) == 0) { /* Disable Bandgap Reference power */ printk(KERN_INFO "%s badgap status: OFF power down bandgap\n", @@ -240,7 +252,7 @@ static void detection_work(struct work_struct *work) printk(KERN_INFO "HOOK_GPIO value: %d\n", mic_in); if (switch_get_state(&hs_data->sdev) == NO_DEVICE) insert_headset(); - else if (mic_in == 1) + if (mic_in == 1) goto closed_micbias; } else{ printk(KERN_INFO "HEADSET: Jack-in GPIO is low, but not a headset\n"); diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h deleted file mode 100644 index 070f3c6059f..00000000000 --- a/sound/soc/pxa/pxa2xx-i2s.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * linux/sound/soc/pxa/pxa2xx-i2s.h - * - * 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 _PXA2XX_I2S_H -#define _PXA2XX_I2S_H - -/* pxa2xx DAI ID's */ -#define PXA2XX_DAI_I2S 0 - -/* I2S clock */ -#define PXA2XX_I2S_SYSCLK 0 - -#endif diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h new file mode 120000 index 00000000000..070f3c6059f --- /dev/null +++ b/sound/soc/pxa/pxa2xx-i2s.h @@ -0,0 +1,18 @@ +/* + * linux/sound/soc/pxa/pxa2xx-i2s.h + * + * 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 _PXA2XX_I2S_H +#define _PXA2XX_I2S_H + +/* pxa2xx DAI ID's */ +#define PXA2XX_DAI_I2S 0 + +/* I2S clock */ +#define PXA2XX_I2S_SYSCLK 0 + +#endif diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ab23869c01b..04a09dbb4c4 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -1420,7 +1420,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid, void *r static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; - int err, val; + int err, val = 0; err = get_cur_ctl_value(cval, cval->control << 8, &val); if (err < 0 && cval->mixer->ignore_ctl_error) { @@ -1438,7 +1438,7 @@ static int mixer_ctl_procunit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, oval, err; + int val, oval = 0, err; err = get_cur_ctl_value(cval, cval->control << 8, &oval); if (err < 0) { @@ -1701,7 +1701,7 @@ static int mixer_ctl_selector_info(struct snd_kcontrol *kcontrol, struct snd_ctl static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, err; + int val = 0, err; err = get_cur_ctl_value(cval, cval->control << 8, &val); if (err < 0) { @@ -1720,7 +1720,7 @@ static int mixer_ctl_selector_get(struct snd_kcontrol *kcontrol, struct snd_ctl_ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct usb_mixer_elem_info *cval = kcontrol->private_data; - int val, oval, err; + int val, oval = 0, err; err = get_cur_ctl_value(cval, cval->control << 8, &oval); if (err < 0) { diff --git a/usr/Kconfig b/usr/Kconfig index 65b845bd4e3..16ffe99bbad 100644 --- a/usr/Kconfig +++ b/usr/Kconfig @@ -90,6 +90,15 @@ config RD_LZO Support loading of a LZO encoded initial ramdisk or cpio buffer If unsure, say N. +config RD_LZ4 + bool "Support initial ramdisks compressed using LZ4" if EXPERT + default !EXPERT + depends on BLK_DEV_INITRD + select DECOMPRESS_LZ4 + help + Support loading of a LZ4 encoded initial ramdisk or cpio buffer + If unsure, say N. + choice prompt "Built-in initramfs compression mode" if INITRAMFS_SOURCE!="" help