diff --git a/Documentation/Changes b/Documentation/Changes index 1de131bb49fb..9ad68f1819d3 100644 --- a/Documentation/Changes +++ b/Documentation/Changes @@ -25,7 +25,7 @@ o Gnu C 3.2 # gcc --version o Gnu make 3.80 # make --version o binutils 2.12 # ld -v o util-linux 2.10o # fdformat --version -o module-init-tools 0.9.10 # depmod -V +o kmod 13 # depmod -V o e2fsprogs 1.41.4 # e2fsck -V o jfsutils 1.1.3 # fsck.jfs -V o reiserfsprogs 3.6.3 # reiserfsck -V @@ -119,12 +119,6 @@ is not build with CONFIG_KALLSYMS and you have no way to rebuild and reproduce the Oops with that option, then you can still decode that Oops with ksymoops. -Module-Init-Tools ------------------ - -A new module loader is now in the kernel that requires module-init-tools -to use. It is backward compatible with the 2.4.x series kernels. - Mkinitrd -------- @@ -302,14 +296,15 @@ Util-linux ---------- o +Kmod +---- +o +o + Ksymoops -------- o -Module-Init-Tools ------------------ -o - Mkinitrd -------- o diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax.txt b/Documentation/devicetree/bindings/input/touchscreen/himax.txt deleted file mode 100644 index b54c85971927..000000000000 --- a/Documentation/devicetree/bindings/input/touchscreen/himax.txt +++ /dev/null @@ -1,22 +0,0 @@ -Himax touch controller - -Required properties: - - - compatible : Should be "himax,hxcommon" - - reg : i2c slave address of the device. - - interrupt-parent : parent of interrupt. - - himax,irq-gpio : irq gpio. - - himax,reset-gpio : reset gpio. - - vdd-supply : Power supply needed to power up the device. - - avdd-supply : Power source required to power up i2c bus. - - himax,panel-coords : panel coordinates for the chip in pixels. - It is a four tuple consisting of min x, - min y, max x and max y values. - - himax,display-coords : display coordinates in pixels. It is a four - tuple consisting of min x, min y, max x and - max y values - -Optional properties: - - himax,3v3-gpio : gpio acting as 3.3 v supply. - - report_type : Multi-touch protocol type. Default 0. - 0 for protocol A, 1 for protocol B. diff --git a/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt b/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt new file mode 100644 index 000000000000..9889f55dd4bb --- /dev/null +++ b/Documentation/devicetree/bindings/input/touchscreen/himax_i2c_ts.txt @@ -0,0 +1,57 @@ +Himax touch controller + +Required properties: + + - compatible : should be "himax,hxcommon" + - reg : i2c slave address of the device + - interrupt-parent : parent of interrupt + - interrupts : touch sample interrupt to indicate presense or release + of fingers on the panel. + - himax,irq-gpio : irq gpio + - himax,reset-gpio : reset gpio + +Optional property: + - vdd-supply : Analog power supply needed to power device + - vcc_i2c-supply : Power source required to pull up i2c bus + - himax,i2c-pull-up : specify to indicate pull up is needed + - himax,disable-gpios : specify to disable gpios in suspend (power saving) + - himax,button-map : virtual key code mappings to be used + - himax,x-flip : modify orientation of the x axis + - himax,y-flip : modify orientation of the y axis + - himax,panel-coords : touch panel min x, min y, max x and + max y resolution + - himax,display-coords : display min x, min y, max x and + max y resolution + - himax,reset-delay : reset delay for controller (ms), default 100 + - himax,fw-image-name : name of firmware .img file in /etc/firmware + - himax,power-down : fully power down regulators in suspend + - himax,do-lockdown : perform one time lockdown procedure + +Example: + i2c@f9927000 { /* BLSP1 QUP5 */ + cell-index = <5>; + compatible = "himax,hxcommon"; + #address-cells = <1>; + #size-cells = <0>; + reg-names = "qup_phys_addr"; + reg = <0xf9927000 0x1000>; + interrupt-names = "qup_err_intr"; + interrupts = <0 99 0>; + gpios = <&msmgpio 19 0>, /* SCL */ + <&msmgpio 18 0>; /* SDA */ + qcom,i2c-bus-freq = <100000>; + qcom,i2c-src-freq = <19200000>; + + himax_ts@20 { + compatible = "himax,hxcommon" + reg = <0x20>; + interrupt-parent = <&tlmm>; + interrupts = <255 0x2008>; + vdd-supply = <&pm8994_l15>; + avdd-supply = <&pm8994_l22>; + himax,panel-coords = <0 720 0 1440>; + himax,display-coords = <0 720 0 1440>; + himax,irq-gpio = <&tlmm 255 0x2008>; + himax,rst-gpio = <&tlmm 8 0x00>; + }; + }; diff --git a/Documentation/devicetree/bindings/input/touchscreen/hmxchipset.txt b/Documentation/devicetree/bindings/input/touchscreen/hmxchipset.txt deleted file mode 100644 index b1fc17fff80f..000000000000 --- a/Documentation/devicetree/bindings/input/touchscreen/hmxchipset.txt +++ /dev/null @@ -1,47 +0,0 @@ -Himax Touch Controller - -Required properties: - - - compatible : Should be "himax,hxcommon" - - reg : I2C slave address of the device. - - interrupt-parent : Parent of interrupt. - - interrupts : Configuration of touch panel controller interrupt - GPIO. - - interrupt-gpios : Interrupt gpio which is to provide interrupts to - host, same as "interrupts" node. - - reset-gpios : Reset gpio to control the reset of chip. - - himax,display-coords : Display coordinates in pixels. It is a four - tuple consisting of min x, min y, max x and - max y values. - -Optional properties: - - - avdd-supply : Power supply needed to power up the device, this is - for fixed voltage external regulator. - - vdd-supply : Power supply needed to power up the device, when use - external regulator, do not add this property. - - himax,panel-coords : Panel coordinates for the chip in pixels. - It is a four tuple consisting of min x, - min y, max x and max y values. - -Example: -&i2c_3 { - status = "okay"; - himax_ts@48 { - compatible = "himax,hxcommon"; - reg = <0x48>; - interrupt-parent = <&tlmm>; - interrupts = <65 0x2>; - vdd-supply = <&pm8953_l10>; - avdd-supply = <&pm8953_l5>; - pinctrl-names = "pmx_ts_active","pmx_ts_suspend","pmx_ts_release"; - pinctrl-0 = <&ts_int_active &ts_reset_active>; - pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>; - pinctrl-2 = <&ts_release>; - himax,panel-coords = <0 800 0 1280>; - himax,display-coords = <0 800 0 1280>; - himax,irq-gpio = <&tlmm 65 0x2008>; - //himax,rst-gpio = <&tlmm 64 0x0>; - report_type = <1>; - }; -}; diff --git a/Documentation/devicetree/bindings/platform/msm/ssm.txt b/Documentation/devicetree/bindings/platform/msm/ssm.txt deleted file mode 100644 index 7df3efd66577..000000000000 --- a/Documentation/devicetree/bindings/platform/msm/ssm.txt +++ /dev/null @@ -1,13 +0,0 @@ -* Qualcomm Technologies, Inc. Secure Service Module driver - -This module enables framework to which a client can register itself -specifying different attributes and defining various permission levels -associated with different combination of attribute values and mode of the system. - -Required properties: -- compatible: Must be "qcom,ssm" - -Example: - qcom,ssm { - compatible = "qcom,ssm"; - }; \ No newline at end of file diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt index 80c8fd14ef94..bc9727207289 100755 --- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt +++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt @@ -1371,6 +1371,16 @@ Required properties: When clock rate is set to zero, then external clock is assumed. + - qcom,msm-cpudai-tdm-afe-ebit-unsupported: Notify if ebit setting is needed + When this is set , alongwith + clock rate as zero then afe + is not configured for clock. + + - qcom,msm-cpudai-tdm-sec-port-start: For chipsets with the limitation where we need + to start both RX and TX AFE ports, this flag is + used to start TX/RX port for RX/TX streams. + + [Second Level Nodes] Required properties: @@ -1963,6 +1973,9 @@ Optional properties: - qcom,wsa-devs: This property contains list of wsa codec names. The names should comply with the wsa nodes configurations. - qcom,wsa-aux-dev-prefix: This property contains list of wsa codec prefixes. +- qcom,tdm-i2s-switch-enable: For chipsets where tdm mics are controlled by + switch, drive corresponding gpio to output high + to enable switch. Example: sound { diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt index 90bef273363d..5f8d2938b187 100644 --- a/Documentation/devicetree/bindings/sound/taiko_codec.txt +++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt @@ -536,6 +536,10 @@ Tasha audio CODEC in I2C mode - qcom,cdc-dmic-sample-rate - Specifies dmic sample rate. - qcom,cdc-variant - Specifies codec variant. + - qcom,wcd9xxx-mic-tristate: For chipsets where I2S TX line is shared between + the Codec and TDM mics, tristate the WCD mics to + avoid PCM interference as the end product uses + only TDM mics. Example: i2c_3: i2c@78B7000 { /* BLSP1 QUP3 */ diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index e9b27436f543..d5455ba063ec 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -78,6 +78,7 @@ haoyu Haoyu Microelectronic Co. Ltd. hisilicon Hisilicon Limited. honeywell Honeywell hp Hewlett Packard +himax Himax Coroporation i2se I2SE GmbH ibm International Business Machines (IBM) idt Integrated Device Technologies, Inc. diff --git a/Makefile b/Makefile index 1f203e0f8433..6b804d1a4e0b 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 3 PATCHLEVEL = 18 -SUBLEVEL = 116 +SUBLEVEL = 122 EXTRAVERSION = NAME = Diseased Newt @@ -615,6 +615,7 @@ KBUILD_CFLAGS += $(call cc-disable-warning,frame-address,) KBUILD_CFLAGS += $(call cc-disable-warning, format-truncation) KBUILD_CFLAGS += $(call cc-disable-warning, format-overflow) KBUILD_CFLAGS += $(call cc-disable-warning, int-in-bool-context) +KBUILD_CFLAGS += $(call cc-disable-warning, attribute-alias) KBUILD_CFLAGS += $(call cc-option,-fno-PIE) KBUILD_AFLAGS += $(call cc-option,-fno-PIE) diff --git a/arch/alpha/kernel/osf_sys.c b/arch/alpha/kernel/osf_sys.c index cb34a25a0168..755554ebd9dc 100644 --- a/arch/alpha/kernel/osf_sys.c +++ b/arch/alpha/kernel/osf_sys.c @@ -525,24 +525,19 @@ SYSCALL_DEFINE4(osf_mount, unsigned long, typenr, const char __user *, path, SYSCALL_DEFINE1(osf_utsname, char __user *, name) { int error; + char tmp[5 * 32]; down_read(&uts_sem); - error = -EFAULT; - if (copy_to_user(name + 0, utsname()->sysname, 32)) - goto out; - if (copy_to_user(name + 32, utsname()->nodename, 32)) - goto out; - if (copy_to_user(name + 64, utsname()->release, 32)) - goto out; - if (copy_to_user(name + 96, utsname()->version, 32)) - goto out; - if (copy_to_user(name + 128, utsname()->machine, 32)) - goto out; + memcpy(tmp + 0 * 32, utsname()->sysname, 32); + memcpy(tmp + 1 * 32, utsname()->nodename, 32); + memcpy(tmp + 2 * 32, utsname()->release, 32); + memcpy(tmp + 3 * 32, utsname()->version, 32); + memcpy(tmp + 4 * 32, utsname()->machine, 32); + up_read(&uts_sem); - error = 0; - out: - up_read(&uts_sem); - return error; + if (copy_to_user(name, tmp, sizeof(tmp))) + return -EFAULT; + return 0; } SYSCALL_DEFINE0(getpagesize) @@ -560,24 +555,22 @@ SYSCALL_DEFINE0(getdtablesize) */ SYSCALL_DEFINE2(osf_getdomainname, char __user *, name, int, namelen) { - unsigned len; - int i; + int len, err = 0; + char *kname; + char tmp[32]; - if (!access_ok(VERIFY_WRITE, name, namelen)) - return -EFAULT; - - len = namelen; - if (len > 32) - len = 32; + if (namelen < 0 || namelen > 32) + namelen = 32; down_read(&uts_sem); - for (i = 0; i < len; ++i) { - __put_user(utsname()->domainname[i], name + i); - if (utsname()->domainname[i] == '\0') - break; - } + kname = utsname()->domainname; + len = strnlen(kname, namelen); + len = min(len + 1, namelen); + memcpy(tmp, kname, len); up_read(&uts_sem); + if (copy_to_user(name, tmp, len)) + return -EFAULT; return 0; } @@ -740,13 +733,14 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) }; unsigned long offset; const char *res; - long len, err = -EINVAL; + long len; + char tmp[__NEW_UTS_LEN + 1]; offset = command-1; if (offset >= ARRAY_SIZE(sysinfo_table)) { /* Digital UNIX has a few unpublished interfaces here */ printk("sysinfo(%d)", command); - goto out; + return -EINVAL; } down_read(&uts_sem); @@ -754,13 +748,11 @@ SYSCALL_DEFINE3(osf_sysinfo, int, command, char __user *, buf, long, count) len = strlen(res)+1; if ((unsigned long)len > (unsigned long)count) len = count; - if (copy_to_user(buf, res, len)) - err = -EFAULT; - else - err = 0; + memcpy(tmp, res, len); up_read(&uts_sem); - out: - return err; + if (copy_to_user(buf, tmp, len)) + return -EFAULT; + return 0; } SYSCALL_DEFINE5(osf_getsysinfo, unsigned long, op, void __user *, buffer, diff --git a/arch/arc/include/asm/delay.h b/arch/arc/include/asm/delay.h index 43de30256981..ee08badc5b91 100644 --- a/arch/arc/include/asm/delay.h +++ b/arch/arc/include/asm/delay.h @@ -17,8 +17,11 @@ #ifndef __ASM_ARC_UDELAY_H #define __ASM_ARC_UDELAY_H +#include #include /* HZ */ +extern unsigned long loops_per_jiffy; + static inline void __delay(unsigned long loops) { __asm__ __volatile__( diff --git a/arch/arc/include/asm/page.h b/arch/arc/include/asm/page.h index 9c8aa41e45c2..25f6583a7a2c 100644 --- a/arch/arc/include/asm/page.h +++ b/arch/arc/include/asm/page.h @@ -97,7 +97,7 @@ typedef unsigned long pgtable_t; #define virt_addr_valid(kaddr) pfn_valid(__pa(kaddr) >> PAGE_SHIFT) /* Default Permissions for stack/heaps pages (Non Executable) */ -#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE) +#define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC) #define WANT_PAGE_VIRTUAL 1 diff --git a/arch/arc/include/asm/pgtable.h b/arch/arc/include/asm/pgtable.h index 7670f33b9ce2..0f12756d6389 100644 --- a/arch/arc/include/asm/pgtable.h +++ b/arch/arc/include/asm/pgtable.h @@ -372,7 +372,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, /* Decode a PTE containing swap "identifier "into constituents */ #define __swp_type(pte_lookalike) (((pte_lookalike).val) & 0x1f) -#define __swp_offset(pte_lookalike) ((pte_lookalike).val << 13) +#define __swp_offset(pte_lookalike) ((pte_lookalike).val >> 13) /* NOPs, to keep generic kernel happy */ #define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) diff --git a/arch/arc/mm/cache_arc700.c b/arch/arc/mm/cache_arc700.c index 2147ca2bc131..51cba86e8cc9 100644 --- a/arch/arc/mm/cache_arc700.c +++ b/arch/arc/mm/cache_arc700.c @@ -642,7 +642,7 @@ void flush_cache_mm(struct mm_struct *mm) void flush_cache_page(struct vm_area_struct *vma, unsigned long u_vaddr, unsigned long pfn) { - unsigned int paddr = pfn << PAGE_SHIFT; + phys_addr_t paddr = pfn << PAGE_SHIFT; u_vaddr &= PAGE_MASK; @@ -662,8 +662,9 @@ void flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long u_vaddr) { /* TBD: do we really need to clear the kernel mapping */ - __flush_dcache_page(page_address(page), u_vaddr); - __flush_dcache_page(page_address(page), page_address(page)); + __flush_dcache_page((phys_addr_t)page_address(page), u_vaddr); + __flush_dcache_page((phys_addr_t)page_address(page), + (phys_addr_t)page_address(page)); } diff --git a/arch/arm/boot/dts/am3517.dtsi b/arch/arm/boot/dts/am3517.dtsi index 5a452fdd7c5d..1f4b2033ba2b 100644 --- a/arch/arm/boot/dts/am3517.dtsi +++ b/arch/arm/boot/dts/am3517.dtsi @@ -62,6 +62,11 @@ }; }; +/* Table Table 5-79 of the TRM shows 480ab000 is reserved */ +&usb_otg_hs { + status = "disabled"; +}; + &iva { status = "disabled"; }; diff --git a/arch/arm/boot/dts/am437x-sk-evm.dts b/arch/arm/boot/dts/am437x-sk-evm.dts index 53bbfc90b26a..247ea36407cb 100644 --- a/arch/arm/boot/dts/am437x-sk-evm.dts +++ b/arch/arm/boot/dts/am437x-sk-evm.dts @@ -415,6 +415,8 @@ touchscreen-size-x = <480>; touchscreen-size-y = <272>; + + wakeup-source; }; tlv320aic3106: tlv320aic3106@1b { diff --git a/arch/arm/boot/dts/da850.dtsi b/arch/arm/boot/dts/da850.dtsi index 0bd98cd00816..4ef5c3410fcc 100644 --- a/arch/arm/boot/dts/da850.dtsi +++ b/arch/arm/boot/dts/da850.dtsi @@ -267,11 +267,7 @@ compatible = "ti,dm6441-gpio"; gpio-controller; reg = <0x226000 0x1000>; - interrupts = <42 IRQ_TYPE_EDGE_BOTH - 43 IRQ_TYPE_EDGE_BOTH 44 IRQ_TYPE_EDGE_BOTH - 45 IRQ_TYPE_EDGE_BOTH 46 IRQ_TYPE_EDGE_BOTH - 47 IRQ_TYPE_EDGE_BOTH 48 IRQ_TYPE_EDGE_BOTH - 49 IRQ_TYPE_EDGE_BOTH 50 IRQ_TYPE_EDGE_BOTH>; + interrupts = <42 43 44 45 46 47 48 49 50>; ti,ngpio = <144>; ti,davinci-gpio-unbanked = <0>; status = "disabled"; diff --git a/arch/arm/boot/dts/imx6sx.dtsi b/arch/arm/boot/dts/imx6sx.dtsi index 22c9fc0fbc9e..862e00cfeea7 100644 --- a/arch/arm/boot/dts/imx6sx.dtsi +++ b/arch/arm/boot/dts/imx6sx.dtsi @@ -1206,7 +1206,7 @@ /* non-prefetchable memory */ 0x82000000 0 0x08000000 0x08000000 0 0x00f00000>; num-lanes = <1>; - interrupts = ; + interrupts = ; clocks = <&clks IMX6SX_CLK_PCIE_REF_125M>, <&clks IMX6SX_CLK_PCIE_AXI>, <&clks IMX6SX_CLK_LVDS1_OUT>, diff --git a/arch/arm/boot/dts/qcom/apq8009-audio-external_codec.dtsi b/arch/arm/boot/dts/qcom/apq8009-audio-external_codec.dtsi index 57c3db93bb01..c70e5ec90cec 100644 --- a/arch/arm/boot/dts/qcom/apq8009-audio-external_codec.dtsi +++ b/arch/arm/boot/dts/qcom/apq8009-audio-external_codec.dtsi @@ -25,7 +25,9 @@ qcom,model = "apq8009-tashalite-snd-card"; qcom,msm-mbhc-hphl-swh = <0>; qcom,msm-mbhc-gnd-swh = <0>; + qcom,afe-rxtx-lb; qcom,msm-mclk-freq = <9600000>; + qcom,tdm-audio-intf; qcom,msm-hs-micbias-type = "internal"; qcom,audio-routing = "AIF4 VI", "MCLK", @@ -87,7 +89,9 @@ <&incall_record_rx>, <&incall_record_tx>, <&incall_music_rx>, <&incall_music_2_rx>, <&bt_sco_rx>, - <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>; + <&bt_sco_tx>, <&int_fm_rx>, <&int_fm_tx>, + <&afe_loopback_tx>, <&dai_pri_tdm_rx_0>, + <&dai_pri_tdm_tx_0>; asoc-cpu-names = "msm-dai-q6-auxpcm.1", "msm-dai-q6-hdmi.8", "msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3", @@ -101,7 +105,9 @@ "msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770", "msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289", - "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293"; + "msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293", + "msm-dai-q6-dev.24577", "msm-dai-q6-tdm.36864", + "msm-dai-q6-tdm.36865"; asoc-codec = <&stub_codec>; asoc-codec-names = "msm-stub-codec.1"; qcom,wsa-max-devs = <2>; @@ -221,4 +227,44 @@ }; }; }; + + pri_tdm_rx: qcom,msm-dai-tdm-pri-rx { + compatible = "qcom,msm-dai-tdm"; + qcom,msm-cpudai-tdm-group-id = <37120>; + qcom,msm-cpudai-tdm-group-num-ports = <1>; + qcom,msm-cpudai-tdm-group-port-id = <36864>; + qcom,msm-cpudai-tdm-clk-rate = <12288000>; + qcom,msm-cpudai-tdm-sec-port-enable; + qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>; + dai_pri_tdm_rx_0: qcom,msm-dai-q6-tdm-pri-rx-0 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36864>; + qcom,msm-cpudai-tdm-sync-mode = <0>; + qcom,msm-cpudai-tdm-sync-src = <1>; + qcom,msm-cpudai-tdm-data-out = <0>; + qcom,msm-cpudai-tdm-invert-sync = <0>; + qcom,msm-cpudai-tdm-data-delay = <1>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; + }; + + pri_tdm_tx: qcom,msm-dai-tdm-pri-tx { + compatible = "qcom,msm-dai-tdm"; + qcom,msm-cpudai-tdm-group-id = <37121>; + qcom,msm-cpudai-tdm-group-num-ports = <1>; + qcom,msm-cpudai-tdm-group-port-id = <36865>; + qcom,msm-cpudai-tdm-clk-rate = <12288000>; + qcom,msm-cpudai-tdm-sec-port-enable; + qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>; + dai_pri_tdm_tx_0: qcom,msm-dai-q6-tdm-pri-tx-0 { + compatible = "qcom,msm-dai-q6-tdm"; + qcom,msm-cpudai-tdm-dev-id = <36865>; + qcom,msm-cpudai-tdm-sync-mode = <0>; + qcom,msm-cpudai-tdm-sync-src = <1>; + qcom,msm-cpudai-tdm-data-out = <0>; + qcom,msm-cpudai-tdm-invert-sync = <0>; + qcom,msm-cpudai-tdm-data-delay = <1>; + qcom,msm-cpudai-tdm-data-align = <0>; + }; + }; }; diff --git a/arch/arm/boot/dts/qcom/apq8009-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8009-dragon.dtsi index 810b6ae7d0f6..f651fa2c0c6c 100644 --- a/arch/arm/boot/dts/qcom/apq8009-dragon.dtsi +++ b/arch/arm/boot/dts/qcom/apq8009-dragon.dtsi @@ -17,9 +17,14 @@ #include "msm8909-pm8916-mtp.dtsi" #include "apq8009-audio-external_codec.dtsi" +&audio_codec_mtp { + status = "disabled"; +}; + &soc { - ext-codec { - qcom,msm-mbhc-hphl-swh = <0>; + sound-9335 { + qcom,model = "apq8009-tashalite-snd-card-tdm"; + qcom,tdm-i2s-switch-enable = <&msm_gpio 88 0>; qcom,audio-routing = "AIF4 VI", "MCLK", "RX_BIAS", "MCLK", @@ -38,16 +43,32 @@ "SpkrRight IN", "SPK2 OUT"; }; - sound-9335 { - status = "disabled"; - }; - i2c@78b8000 { wcd9xxx_codec@d { - status = "disabled"; + qcom,wcd9xxx-mic-tristate; + qcom,cdc-reset-gpio = <&msm_gpio 23 0>; + + cdc-vdd-buck-supply = <&wcd_vdd_buck_1p8>; + qcom,cdc-vdd-buck-voltage = <0 0>; + qcom,cdc-vdd-buck-current = <250000>; + + cdc-buck-sido-supply = <&wcd_vdd_buck_1p8>; + qcom,cdc-buck-sido-voltage = <0 0>; + qcom,cdc-buck-sido-current = <250000>; }; }; + wcd_vdd_buck_1p8: wcd_vdd_buck_1p8 { + compatible = "regulator-fixed"; + regulator-name = "wcd_vdd_buck_1p8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + status = "ok"; + enable-active-high; + gpio = <&pm8916_gpios 4 0>; + vin-supply = <&pm8916_s4>; + }; + vph_pwr_vreg: vph_pwr_vreg { compatible = "regulator-fixed"; status = "ok"; @@ -128,6 +149,17 @@ }; }; +&pm8916_gpios { + gpio@c300 { + qcom,mode = <1>; /* DIGITAL OUT */ + qcom,pull = <1>; /* No Pull */ + qcom,vin-sel = <2>; /* 1.8 */ + qcom,src-sel = <0>; /* CONSTANT */ + qcom,master-en = <1>; /* ENABLE GPIO */ + status = "okay"; + }; +}; + &pm8916_bms { status = "ok"; qcom,disable-bms; diff --git a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi index 8649b2000e70..0cf97ceb1ca7 100644 --- a/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi +++ b/arch/arm/boot/dts/qcom/apq8053-lite-dragon.dtsi @@ -408,7 +408,8 @@ 2 &tlmm 133 0>; interrupt-names = "hc_irq", "pwr_irq", "status_irq"; - qcom,clk-rates = <400000 20000000 25000000 50000000>; + qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 + 177770000>; qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104"; status = "ok"; diff --git a/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts b/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts index c21b6d6cbc9e..a30813f4be6c 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v2-auto-dragonboard.dts @@ -30,7 +30,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <127 0>; + interrupts = <127 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts b/arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts index 74bb21eedf10..0f021e0ef437 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v3-auto-adp.dts @@ -30,7 +30,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <122 0>; + interrupts = <122 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts b/arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts index 82030c493f8d..4e683f632894 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v3-auto-cdp.dts @@ -38,7 +38,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <127 0>; + interrupts = <127 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts b/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts index cd02dacbdcee..2be4f89c0cc7 100644 --- a/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts +++ b/arch/arm/boot/dts/qcom/apq8096-v3-auto-dragonboard.dts @@ -30,7 +30,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <127 0>; + interrupts = <127 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts b/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts index e2d4f2b9babe..fa0da0c23743 100644 --- a/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/apq8096pro-auto-cdp.dts @@ -30,7 +30,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <127 0>; + interrupts = <127 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts index fdea81eb9322..3ee3238bae7b 100644 --- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp.dts @@ -31,7 +31,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <122 0>; + interrupts = <122 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts index d5eb6031e378..15bd28865e64 100644 --- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-cdp.dts @@ -30,7 +30,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <127 0>; + interrupts = <127 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi b/arch/arm/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi index 9ad11c4cf64d..c5b7575ef438 100644 --- a/arch/arm/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi +++ b/arch/arm/boot/dts/qcom/dsi-panel-hx83100a-800p-video.dtsi @@ -39,11 +39,6 @@ qcom,mdss-dsi-on-command = [ 39 01 00 00 78 00 02 11 00 39 01 00 00 14 00 02 29 00 - 39 01 00 00 00 00 04 B9 83 10 0A - 39 01 00 00 00 00 08 C9 1F 00 08 1E 81 1E 00 - 39 01 00 00 00 00 02 53 24 - 39 01 00 00 05 00 02 55 02 - 39 01 00 00 00 00 0A CA 40 3C 38 34 33 32 30 2C 28 ]; qcom,mdss-dsi-off-command = [05 01 00 00 96 00 02 28 00 05 01 00 00 00 00 02 10 00]; diff --git a/arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi b/arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi index 3ab680127d64..c32278a35ad1 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9650-ccard.dtsi @@ -613,7 +613,7 @@ reg = <0>; spi-max-frequency = <9600000>; interrupt-parent = <&tlmm_pinmux>; - interrupts = <87 0>; + interrupts = <87 2>; qcom,reset-gpio = <&tlmm_pinmux 89 0x1>; qcom,clk-freq-mhz = <20000000>; qcom,max-can-channels = <1>; diff --git a/arch/arm/boot/dts/qcom/mdm9650-ttp.dts b/arch/arm/boot/dts/qcom/mdm9650-ttp.dts index 8a951ffb004f..1638d1866ded 100644 --- a/arch/arm/boot/dts/qcom/mdm9650-ttp.dts +++ b/arch/arm/boot/dts/qcom/mdm9650-ttp.dts @@ -78,7 +78,7 @@ spi-max-frequency = <4800000>; reg = <0>; interrupt-parent = <&tlmm_pinmux>; - interrupts = <84 0>; + interrupts = <84 1>; reset-gpio = <&tlmm_pinmux 68 0x1>; pinctrl-names = "active", "sleep"; pinctrl-0 = <&can_rst_on>; diff --git a/arch/arm/boot/dts/qcom/mdm9650.dtsi b/arch/arm/boot/dts/qcom/mdm9650.dtsi index 2d46a23ce20e..94e02dc3239f 100644 --- a/arch/arm/boot/dts/qcom/mdm9650.dtsi +++ b/arch/arm/boot/dts/qcom/mdm9650.dtsi @@ -22,7 +22,7 @@ <286 0x10000>, <283 0x10000>, <359 0x10000>; interrupt-parent = <&intc>; - reserved-memory { + reserved_mem: reserved-memory { #address-cells = <1>; #size-cells = <1>; ranges; @@ -1058,8 +1058,8 @@ qcom,limit-temp = <60>; qcom,temp-hysteresis = <10>; qcom,freq-step = <2>; - qcom,vdd-restriction-temp = <5>; - qcom,vdd-restriction-temp-hysteresis = <10>; + qcom,vdd-restriction-temp = <10>; + qcom,vdd-restriction-temp-hysteresis = <15>; vdd-dig-supply = <&pmd9650_s5_floor_level>; qcom,disable-cx-phase-ctrl; qcom,disable-gfx-phase-ctrl; @@ -1069,9 +1069,9 @@ qcom,vdd-dig-rstr{ qcom,vdd-rstr-reg = "vdd-dig"; - qcom,levels = ; + qcom,levels = ; qcom,min-level = ; }; }; diff --git a/arch/arm/boot/dts/qcom/msm8909.dtsi b/arch/arm/boot/dts/qcom/msm8909.dtsi index 34a8cccbd5a4..d1d618d77786 100644 --- a/arch/arm/boot/dts/qcom/msm8909.dtsi +++ b/arch/arm/boot/dts/qcom/msm8909.dtsi @@ -1727,6 +1727,11 @@ qcom,msm-dai-q6-dev-id = <240>; }; + afe_loopback_tx: qcom,msm-dai-q6-afe-loopback-tx { + compatible = "qcom,msm-dai-q6-dev"; + qcom,msm-dai-q6-dev-id = <24577>; + }; + incall_record_rx: qcom,msm-dai-q6-incall-record-rx { compatible = "qcom,msm-dai-q6-dev"; qcom,msm-dai-q6-dev-id = <32771>; @@ -1861,6 +1866,10 @@ qcom,use-sw-aes-cbc-ecb-ctr-algo; qcom,use-sw-aes-xts-algo; qcom,use-sw-ahash-algo; + qcom,use-sw-aes-ccm-algo; + qcom,use-sw-hmac-algo; + qcom,use-sw-aead-algo; + status = "disabled"; qcom,ce-opp-freq = <100000000>; }; diff --git a/arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts b/arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts index d4cf58f9b8ea..4ff449a45d1a 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/msm8996-v3-auto-adp.dts @@ -31,7 +31,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <122 0>; + interrupts = <122 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts b/arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts index 33daf9d6f0e7..250ce9289c70 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/msm8996-v3-auto-cdp.dts @@ -43,7 +43,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <127 0>; + interrupts = <127 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts b/arch/arm/boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts index d84b0d781b29..cf1128b5d283 100644 --- a/arch/arm/boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts +++ b/arch/arm/boot/dts/qcom/msm8996-v3-pm8004-agave-adp.dts @@ -28,7 +28,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <122 0>; + interrupts = <122 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts index 15b00af5f0f4..91f9ab654e51 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts +++ b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp.dts @@ -31,7 +31,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <122 0>; + interrupts = <122 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts b/arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts index 4a78a2fef835..a4c0a0515995 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/msm8996pro-auto-cdp.dts @@ -30,7 +30,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <127 0>; + interrupts = <127 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts b/arch/arm/boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts index d75f56d12291..13a0e914cdfa 100644 --- a/arch/arm/boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts +++ b/arch/arm/boot/dts/qcom/msm8996pro-v1.1-auto-cdp.dts @@ -30,7 +30,7 @@ compatible = "qcom,renesas,rh850"; reg = <0>; interrupt-parent = <&tlmm>; - interrupts = <127 0>; + interrupts = <127 2>; spi-max-frequency = <5000000>; qcom,clk-freq-mhz = <16000000>; qcom,max-can-channels = <4>; diff --git a/arch/arm/boot/dts/qcom/sdx20.dtsi b/arch/arm/boot/dts/qcom/sdx20.dtsi index 811eef6f2755..6059ed7278f6 100644 --- a/arch/arm/boot/dts/qcom/sdx20.dtsi +++ b/arch/arm/boot/dts/qcom/sdx20.dtsi @@ -39,6 +39,17 @@ reg = <0x88000000 0x7300000>; }; +&reserved_mem { + linux,cma { + compatible = "shared-dma-pool"; + alloc-ranges = <0 0x00000000 0 0x90000000>; + reusable; + alignment = <0 0x400000>; + size = <0 0xc00000>; + linux,cma-default; + }; +}; + &soc { /* SD card 2.95 V supply */ sdc_vreg: sdc_vreg { @@ -138,6 +149,16 @@ /delete-node/ qcom,spm@b009000; /delete-node/ qcom,mpm@601b8; /delete-node/ qcom,lpm-levels; + + qcom,msm-thermal { + qcom,vdd-restriction-temp = <5>; + qcom,vdd-restriction-temp-hysteresis = <10>; + qcom,vdd-dig-rstr{ + qcom,levels = ; + }; + }; }; &clock_gcc { diff --git a/arch/arm/boot/dts/tegra30-cardhu.dtsi b/arch/arm/boot/dts/tegra30-cardhu.dtsi index a1b682ea01bd..224a7605877e 100644 --- a/arch/arm/boot/dts/tegra30-cardhu.dtsi +++ b/arch/arm/boot/dts/tegra30-cardhu.dtsi @@ -200,6 +200,7 @@ #address-cells = <1>; #size-cells = <0>; reg = <0x70>; + reset-gpio = <&gpio TEGRA_GPIO(BB, 0) GPIO_ACTIVE_LOW>; }; }; diff --git a/arch/arm/configs/imx_v4_v5_defconfig b/arch/arm/configs/imx_v4_v5_defconfig index e6b0007355f8..0dfa0029470f 100644 --- a/arch/arm/configs/imx_v4_v5_defconfig +++ b/arch/arm/configs/imx_v4_v5_defconfig @@ -146,9 +146,11 @@ CONFIG_USB_STORAGE=y CONFIG_USB_CHIPIDEA=y CONFIG_USB_CHIPIDEA_UDC=y CONFIG_USB_CHIPIDEA_HOST=y +CONFIG_USB_CHIPIDEA_ULPI=y CONFIG_NOP_USB_XCEIV=y CONFIG_USB_GADGET=y CONFIG_USB_ETH=m +CONFIG_USB_ULPI_BUS=y CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y diff --git a/arch/arm/configs/mdm-perf_defconfig b/arch/arm/configs/mdm-perf_defconfig index 9b207032aeee..09a3f1e14f6d 100644 --- a/arch/arm/configs/mdm-perf_defconfig +++ b/arch/arm/configs/mdm-perf_defconfig @@ -27,7 +27,6 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_PARTITION_ADVANCED=y CONFIG_ARCH_MSM=y -CONFIG_ARCH_MDM9640=y CONFIG_ARCH_MDM9650=y CONFIG_PCI_MSM=y CONFIG_PREEMPT=y @@ -205,7 +204,7 @@ CONFIG_TUN=y # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_NET_VENDOR_FARADAY is not set # CONFIG_NET_VENDOR_INTEL is not set -CONFIG_KS8851=y +# CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MICROCHIP is not set CONFIG_ECM_IPA=y CONFIG_RNDIS_IPA=y @@ -238,7 +237,6 @@ CONFIG_INPUT_EVDEV=y CONFIG_INPUT_MISC=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=m -CONFIG_SERIO_LIBPS2=y # CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_MSM_HS=y CONFIG_SERIAL_MSM_HSL=y @@ -282,12 +280,7 @@ CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y CONFIG_SND_SOC_MDM9650=y -CONFIG_UHID=y -CONFIG_HID_APPLE=y -CONFIG_HID_ELECOM=y -CONFIG_HID_MAGICMOUSE=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_GENERIC is not set CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y @@ -295,19 +288,6 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_MSM=y CONFIG_USB_EHCI_MSM_HSIC=y CONFIG_USB_ACM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_STORAGE_DEBUG=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_USBAT=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_STORAGE_ALAUDA=y -CONFIG_USB_STORAGE_ONETOUCH=y -CONFIG_USB_STORAGE_KARMA=y -CONFIG_USB_STORAGE_CYPRESS_ATACB=y CONFIG_USB_DWC3=y CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_NOP_USB_XCEIV=y @@ -399,8 +379,6 @@ CONFIG_DEVFREQ_SPDM=y CONFIG_IIO=y CONFIG_IIO_BUFFER=y CONFIG_IIO_BUFFER_CB=y -CONFIG_IIO_ST_ACCEL_3AXIS=y -CONFIG_IIO_ST_GYRO_3AXIS=y CONFIG_SENSORS_BMI160_IIO=y CONFIG_SENSORS_BMI160_IIO_RING=y CONFIG_ENABLE_ACC_GYRO_BUFFERING=y diff --git a/arch/arm/configs/mdm_defconfig b/arch/arm/configs/mdm_defconfig index bffd18813078..031eceff80ed 100644 --- a/arch/arm/configs/mdm_defconfig +++ b/arch/arm/configs/mdm_defconfig @@ -205,7 +205,7 @@ CONFIG_TUN=y # CONFIG_NET_VENDOR_CIRRUS is not set # CONFIG_NET_VENDOR_FARADAY is not set # CONFIG_NET_VENDOR_INTEL is not set -CONFIG_KS8851=y +# CONFIG_NET_VENDOR_MICREL is not set # CONFIG_NET_VENDOR_MICROCHIP is not set CONFIG_ECM_IPA=y CONFIG_RNDIS_IPA=y @@ -238,7 +238,6 @@ CONFIG_INPUT_EVDEV=y CONFIG_INPUT_MISC=y CONFIG_INPUT_UINPUT=y CONFIG_INPUT_GPIO=m -CONFIG_SERIO_LIBPS2=y # CONFIG_LEGACY_PTYS is not set CONFIG_SERIAL_MSM_HS=y CONFIG_SERIAL_MSM_HSL=y @@ -259,7 +258,6 @@ CONFIG_SPI_SPIDEV=m CONFIG_PPS_CLIENT_GPIO=y CONFIG_PTP_1588_CLOCK=y CONFIG_PINCTRL_MDM9607=y -CONFIG_PINCTRL_MDM9640=y CONFIG_PINCTRL_MDM9650=y CONFIG_DEBUG_GPIO=y CONFIG_GPIO_SYSFS=y @@ -289,12 +287,7 @@ CONFIG_SOUND=y CONFIG_SND=y CONFIG_SND_SOC=y CONFIG_SND_SOC_MDM9650=y -CONFIG_UHID=y -CONFIG_HID_APPLE=y -CONFIG_HID_ELECOM=y -CONFIG_HID_MAGICMOUSE=y -CONFIG_HID_MICROSOFT=y -CONFIG_HID_MULTITOUCH=y +# CONFIG_HID_GENERIC is not set CONFIG_USB=y CONFIG_USB_ANNOUNCE_NEW_DEVICES=y CONFIG_USB_XHCI_HCD=y @@ -302,19 +295,6 @@ CONFIG_USB_EHCI_HCD=y CONFIG_USB_EHCI_MSM=y CONFIG_USB_EHCI_MSM_HSIC=y CONFIG_USB_ACM=y -CONFIG_USB_STORAGE=y -CONFIG_USB_STORAGE_DEBUG=y -CONFIG_USB_STORAGE_DATAFAB=y -CONFIG_USB_STORAGE_FREECOM=y -CONFIG_USB_STORAGE_ISD200=y -CONFIG_USB_STORAGE_USBAT=y -CONFIG_USB_STORAGE_SDDR09=y -CONFIG_USB_STORAGE_SDDR55=y -CONFIG_USB_STORAGE_JUMPSHOT=y -CONFIG_USB_STORAGE_ALAUDA=y -CONFIG_USB_STORAGE_ONETOUCH=y -CONFIG_USB_STORAGE_KARMA=y -CONFIG_USB_STORAGE_CYPRESS_ATACB=y CONFIG_USB_DWC3=y CONFIG_USB_EHSET_TEST_FIXTURE=y CONFIG_NOP_USB_XCEIV=y @@ -411,8 +391,6 @@ CONFIG_DEVFREQ_SPDM=y CONFIG_IIO=y CONFIG_IIO_BUFFER=y CONFIG_IIO_BUFFER_CB=y -CONFIG_IIO_ST_ACCEL_3AXIS=y -CONFIG_IIO_ST_GYRO_3AXIS=y CONFIG_SENSORS_BMI160_IIO=y CONFIG_SENSORS_BMI160_IIO_RING=y CONFIG_ENABLE_ACC_GYRO_BUFFERING=y diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig index 5e79c10ae920..2557519188a3 100644 --- a/arch/arm/configs/msm8909-perf_defconfig +++ b/arch/arm/configs/msm8909-perf_defconfig @@ -256,6 +256,7 @@ CONFIG_SCSI_SCAN_ASYNC=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_FEC=y CONFIG_NETDEVICES=y @@ -531,10 +532,10 @@ CONFIG_HARDENED_USERCOPY=y CONFIG_SECURITY_SELINUX=y CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_CTR=y -CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y CONFIG_CRYPTO_DEV_QCRYPTO=y +CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCEDEV=y CONFIG_QMI_ENCDEC=y diff --git a/arch/arm/configs/msm8909_defconfig b/arch/arm/configs/msm8909_defconfig index 230bab172feb..de501ebb77c0 100644 --- a/arch/arm/configs/msm8909_defconfig +++ b/arch/arm/configs/msm8909_defconfig @@ -261,6 +261,7 @@ CONFIG_SCSI_SCAN_ASYNC=y CONFIG_MD=y CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y +CONFIG_DM_REQ_CRYPT=y CONFIG_DM_VERITY=y CONFIG_DM_VERITY_FEC=y CONFIG_NETDEVICES=y @@ -584,7 +585,6 @@ CONFIG_HARDENED_USERCOPY=y CONFIG_SECURITY_SELINUX=y CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_CTR=y -CONFIG_CRYPTO_XTS=y CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y diff --git a/arch/arm/configs/msmcortex_defconfig b/arch/arm/configs/msmcortex_defconfig index 2400e9efbf3f..c193a0eb7de5 100644 --- a/arch/arm/configs/msmcortex_defconfig +++ b/arch/arm/configs/msmcortex_defconfig @@ -670,7 +670,6 @@ CONFIG_CRYPTO_CTR=y CONFIG_CRYPTO_XCBC=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_TWOFISH=y -CONFIG_FIPS_ENABLE=y CONFIG_CRYPTO_DEV_QCRYPTO=y CONFIG_CRYPTO_DEV_QCOM_MSM_QCE=y CONFIG_CRYPTO_DEV_QCEDEV=y diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index c5a51e79e74f..1a5fe8f4797c 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h @@ -251,7 +251,7 @@ extern int __put_user_8(void *, unsigned long long); ({ \ unsigned long __limit = current_thread_info()->addr_limit - 1; \ const typeof(*(p)) __user *__tmp_p = (p); \ - register const typeof(*(p)) __r2 asm("r2") = (x); \ + register typeof(*(p)) __r2 asm("r2") = (x); \ register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \ register unsigned long __l asm("r1") = __limit; \ register int __e asm("r0"); \ diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c index 70ccd1ea5ba1..70b4254674a2 100644 --- a/arch/arm/kvm/mmu.c +++ b/arch/arm/kvm/mmu.c @@ -841,19 +841,35 @@ static int stage2_set_pmd_huge(struct kvm *kvm, struct kvm_mmu_memory_cache pmd = stage2_get_pmd(kvm, cache, addr); VM_BUG_ON(!pmd); - /* - * Mapping in huge pages should only happen through a fault. If a - * page is merged into a transparent huge page, the individual - * subpages of that huge page should be unmapped through MMU - * notifiers before we get here. - * - * Merging of CompoundPages is not supported; they should become - * splitting first, unmapped, merged, and mapped back in on-demand. - */ - VM_BUG_ON(pmd_present(*pmd) && pmd_pfn(*pmd) != pmd_pfn(*new_pmd)); - old_pmd = *pmd; if (pmd_present(old_pmd)) { + /* + * Multiple vcpus faulting on the same PMD entry, can + * lead to them sequentially updating the PMD with the + * same value. Following the break-before-make + * (pmd_clear() followed by tlb_flush()) process can + * hinder forward progress due to refaults generated + * on missing translations. + * + * Skip updating the page table if the entry is + * unchanged. + */ + if (pmd_val(old_pmd) == pmd_val(*new_pmd)) + return 0; + + /* + * Mapping in huge pages should only happen through a + * fault. If a page is merged into a transparent huge + * page, the individual subpages of that huge page + * should be unmapped through MMU notifiers before we + * get here. + * + * Merging of CompoundPages is not supported; they + * should become splitting first, unmapped, merged, + * and mapped back in on-demand. + */ + VM_BUG_ON(pmd_pfn(old_pmd) != pmd_pfn(*new_pmd)); + pmd_clear(pmd); kvm_tlb_flush_vmid_ipa(kvm, addr); } else { @@ -898,6 +914,10 @@ static int stage2_set_pte(struct kvm *kvm, struct kvm_mmu_memory_cache *cache, /* Create 2nd stage page table mapping - Level 3 */ old_pte = *pte; if (pte_present(old_pte)) { + /* Skip page table update if there is no change */ + if (pte_val(old_pte) == pte_val(*new_pte)) + return 0; + kvm_set_pte(pte, __pte(0)); kvm_tlb_flush_vmid_ipa(kvm, addr); } else { diff --git a/arch/arm/mach-pxa/irq.c b/arch/arm/mach-pxa/irq.c index 0eecd83c624e..d7f382856c42 100644 --- a/arch/arm/mach-pxa/irq.c +++ b/arch/arm/mach-pxa/irq.c @@ -160,7 +160,7 @@ static int pxa_irq_suspend(void) { int i; - for (i = 0; i < pxa_internal_irq_nr / 32; i++) { + for (i = 0; i < DIV_ROUND_UP(pxa_internal_irq_nr, 32); i++) { void __iomem *base = irq_base(i); saved_icmr[i] = __raw_readl(base + ICMR); @@ -179,7 +179,7 @@ static void pxa_irq_resume(void) { int i; - for (i = 0; i < pxa_internal_irq_nr / 32; i++) { + for (i = 0; i < DIV_ROUND_UP(pxa_internal_irq_nr, 32); i++) { void __iomem *base = irq_base(i); __raw_writel(saved_icmr[i], base + ICMR); diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 36f03792bc01..54605542196e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -85,6 +85,7 @@ config ARM64 select SPARSE_IRQ select SYSCTL_EXCEPTION_TRACE select HAVE_CONTEXT_TRACKING + select THREAD_INFO_IN_TASK select MSM_JTAGV8 if CORESIGHT_ETMV4 help ARM 64-bit (AArch64) Linux support. diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig index 3106c09e7ebd..e3cec69b09f4 100644 --- a/arch/arm64/configs/msm-perf_defconfig +++ b/arch/arm64/configs/msm-perf_defconfig @@ -250,6 +250,7 @@ CONFIG_TUSB320_TYPE_C=y CONFIG_FUSB301_TYPE_C=y CONFIG_PTN5150_TYPE_C=y CONFIG_TI_DRV2667=y +CONFIG_FORCE_FAST_CHARGE=y CONFIG_EEPROM_AT24=y CONFIG_DTS_EAGLE=y CONFIG_SCSI=y diff --git a/arch/arm64/include/asm/current.h b/arch/arm64/include/asm/current.h new file mode 100644 index 000000000000..2e61d21294ba --- /dev/null +++ b/arch/arm64/include/asm/current.h @@ -0,0 +1,27 @@ +#ifndef __ASM_CURRENT_H +#define __ASM_CURRENT_H + +#include + +#include + +#ifndef __ASSEMBLY__ + +#ifdef CONFIG_THREAD_INFO_IN_TASK +struct task_struct; + +static __always_inline struct task_struct *get_current(void) +{ + return (struct task_struct *)read_sysreg(sp_el0); +} +#define current get_current() +#else +#include +#define get_current() (current_thread_info()->task) +#define current get_current() +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __ASM_CURRENT_H */ + diff --git a/arch/arm64/include/asm/smp.h b/arch/arm64/include/asm/smp.h index c78ede618c48..c6dec25b1724 100644 --- a/arch/arm64/include/asm/smp.h +++ b/arch/arm64/include/asm/smp.h @@ -56,6 +56,9 @@ asmlinkage void secondary_start_kernel(void); */ struct secondary_data { void *stack; +#ifdef CONFIG_THREAD_INFO_IN_TASK + struct task_struct *task; +#endif }; extern struct secondary_data secondary_data; extern void secondary_entry(void); diff --git a/arch/arm64/include/asm/thread_info.h b/arch/arm64/include/asm/thread_info.h index 7193434e165d..756cbf10d5ab 100644 --- a/arch/arm64/include/asm/thread_info.h +++ b/arch/arm64/include/asm/thread_info.h @@ -46,15 +46,26 @@ typedef unsigned long mm_segment_t; struct thread_info { unsigned long flags; /* low level flags */ mm_segment_t addr_limit; /* address limit */ +#ifndef CONFIG_THREAD_INFO_IN_TASK struct task_struct *task; /* main task structure */ +#endif struct exec_domain *exec_domain; /* execution domain */ #ifdef CONFIG_ARM64_SW_TTBR0_PAN u64 ttbr0; /* saved TTBR0_EL1 */ #endif int preempt_count; /* 0 => preemptable, <0 => bug */ +#ifndef CONFIG_THREAD_INFO_IN_TASK int cpu; /* cpu */ +#endif }; +#ifdef CONFIG_THREAD_INFO_IN_TASK +#define INIT_THREAD_INFO(tsk) \ +{ \ + .preempt_count = INIT_PREEMPT_COUNT, \ + .addr_limit = KERNEL_DS, \ +} +#else #define INIT_THREAD_INFO(tsk) \ { \ .task = &tsk, \ @@ -65,7 +76,6 @@ struct thread_info { } #define init_thread_info (init_thread_union.thread_info) -#define init_stack (init_thread_union.stack) /* * how to get the current stack pointer from C @@ -88,6 +98,9 @@ static inline struct thread_info *current_thread_info(void) return (struct thread_info *)sp_el0; } +#endif + +#define init_stack (init_thread_union.stack) #define thread_saved_pc(tsk) \ ((unsigned long)(tsk->thread.cpu_context.pc)) diff --git a/arch/arm64/kernel/asm-offsets.c b/arch/arm64/kernel/asm-offsets.c index a865573461e1..1e5c7d0430ea 100644 --- a/arch/arm64/kernel/asm-offsets.c +++ b/arch/arm64/kernel/asm-offsets.c @@ -34,12 +34,17 @@ int main(void) { DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); BLANK(); +#ifdef CONFIG_THREAD_INFO_IN_TASK + DEFINE(TSK_TI_FLAGS, offsetof(struct task_struct, thread_info.flags)); + DEFINE(TSK_TI_PREEMPT, offsetof(struct task_struct, thread_info.preempt_count)); + DEFINE(TSK_TI_ADDR_LIMIT, offsetof(struct task_struct, thread_info.addr_limit)); + DEFINE(TSK_STACK, offsetof(struct task_struct, stack)); +#else DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_ADDR_LIMIT, offsetof(struct thread_info, addr_limit)); - DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_EXEC_DOMAIN, offsetof(struct thread_info, exec_domain)); - DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); +#endif #ifdef CONFIG_ARM64_SW_TTBR0_PAN DEFINE(TSK_TI_TTBR0, offsetof(struct thread_info, ttbr0)); #endif @@ -113,6 +118,11 @@ int main(void) DEFINE(TZ_MINWEST, offsetof(struct timezone, tz_minuteswest)); DEFINE(TZ_DSTTIME, offsetof(struct timezone, tz_dsttime)); BLANK(); +#ifdef CONFIG_THREAD_INFO_IN_TASK + DEFINE(CPU_BOOT_STACK, offsetof(struct secondary_data, stack)); + DEFINE(CPU_BOOT_TASK, offsetof(struct secondary_data, task)); + BLANK(); +#endif #ifdef CONFIG_KVM_ARM_HOST DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt)); DEFINE(CPU_GP_REGS, offsetof(struct kvm_cpu_context, gp_regs)); diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 709f8cf0af8e..07403f503818 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -116,18 +116,31 @@ alternative_else_nop_endif .if \el == 0 mrs x21, sp_el0 +#ifdef CONFIG_THREAD_INFO_IN_TASK + ldr_this_cpu tsk, __entry_task, x20 // Ensure MDSCR_EL1.SS is clear, + ldr x19, [tsk, #TSK_TI_FLAGS] // since we can unmask debug +#else mov tsk, sp and tsk, tsk, #~(THREAD_SIZE - 1) // Ensure MDSCR_EL1.SS is clear, ldr x19, [tsk, #TI_FLAGS] // since we can unmask debug +#endif disable_step_tsk x19, x20 // exceptions when scheduling. .else add x21, sp, #S_FRAME_SIZE get_thread_info tsk /* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */ +#ifdef CONFIG_THREAD_INFO_IN_TASK + ldr x20, [tsk, #TSK_TI_ADDR_LIMIT] +#else ldr x20, [tsk, #TI_ADDR_LIMIT] +#endif str x20, [sp, #S_ORIG_ADDR_LIMIT] mov x20, #TASK_SIZE_64 +#ifdef CONFIG_THREAD_INFO_IN_TASK + str x20, [tsk, #TSK_TI_ADDR_LIMIT] +#else str x20, [tsk, #TI_ADDR_LIMIT] +#endif ALTERNATIVE(nop, SET_PSTATE_UAO(0), ARM64_HAS_UAO, CONFIG_ARM64_UAO) .endif /* \el == 0 */ mrs x22, elr_el1 @@ -189,7 +202,11 @@ alternative_else_nop_endif .if \el != 0 /* Restore the task's original addr_limit. */ ldr x20, [sp, #S_ORIG_ADDR_LIMIT] +#ifdef CONFIG_THREAD_INFO_IN_TASK + str x20, [tsk, #TSK_TI_ADDR_LIMIT] +#else str x20, [tsk, #TI_ADDR_LIMIT] +#endif /* No need to restore UAO, it will be restored from SPSR_EL1 */ .endif @@ -487,9 +504,17 @@ el1_irq: #ifdef CONFIG_PREEMPT get_thread_info tsk +#ifdef CONFIG_THREAD_INFO_IN_TASK + ldr w24, [tsk, #TSK_TI_PREEMPT] // get preempt count +#else ldr w24, [tsk, #TI_PREEMPT] // get preempt count +#endif cbnz w24, 1f // preempt count != 0 +#ifdef CONFIG_THREAD_INFO_IN_TASK + ldr x0, [tsk, #TSK_TI_FLAGS] // get flags +#else ldr x0, [tsk, #TI_FLAGS] // get flags +#endif tbz x0, #TIF_NEED_RESCHED, 1f // needs rescheduling? bl el1_preempt 1: @@ -504,7 +529,11 @@ ENDPROC(el1_irq) el1_preempt: mov x24, lr 1: bl preempt_schedule_irq // irq en/disable is done inside +#ifdef CONFIG_THREAD_INFO_IN_TASK + ldr x0, [tsk, #TSK_TI_FLAGS] // get new tasks TI_FLAGS +#else ldr x0, [tsk, #TI_FLAGS] // get new tasks TI_FLAGS +#endif tbnz x0, #TIF_NEED_RESCHED, 1b // needs rescheduling? ret x24 #endif @@ -771,8 +800,12 @@ ENTRY(cpu_switch_to) mov v15.16b, v15.16b #endif mov sp, x9 +#ifdef CONFIG_THREAD_INFO_IN_TASK + msr sp_el0, x1 +#else and x9, x9, #~(THREAD_SIZE - 1) msr sp_el0, x9 +#endif ret ENDPROC(cpu_switch_to) @@ -783,7 +816,11 @@ ENDPROC(cpu_switch_to) ret_fast_syscall: disable_irq // disable interrupts str x0, [sp, #S_X0] // returned x0 +#ifdef CONFIG_THREAD_INFO_IN_TASK + ldr x1, [tsk, #TSK_TI_FLAGS] // re-check for syscall tracing +#else ldr x1, [tsk, #TI_FLAGS] // re-check for syscall tracing +#endif and x2, x1, #_TIF_SYSCALL_WORK cbnz x2, ret_fast_syscall_trace and x2, x1, #_TIF_WORK_MASK @@ -815,7 +852,11 @@ work_resched: */ ret_to_user: disable_irq // disable interrupts +#ifdef CONFIG_THREAD_INFO_IN_TASK + ldr x1, [tsk, #TSK_TI_FLAGS] +#else ldr x1, [tsk, #TI_FLAGS] +#endif and x2, x1, #_TIF_WORK_MASK cbnz x2, work_pending enable_step_tsk x1, x2 @@ -848,7 +889,11 @@ el0_svc_naked: // compat entry point enable_dbg_and_irq ct_user_exit 1 +#ifdef CONFIG_THREAD_INFO_IN_TASK + ldr x16, [tsk, #TSK_TI_FLAGS] // check for syscall hooks +#else ldr x16, [tsk, #TI_FLAGS] // check for syscall hooks +#endif tst x16, #_TIF_SYSCALL_WORK b.ne __sys_trace cmp scno, sc_nr // check upper syscall limit diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 517c821955b6..e34584fd690d 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -456,10 +456,18 @@ __mmap_switched: bl __pi_memset dsb ishst // Make zero page visible to PTW +#ifdef CONFIG_THREAD_INFO_IN_TASK + adrp x4, init_thread_union + add sp, x4, #THREAD_SIZE + adr_l x5, init_task + msr sp_el0, x5 // Save thread_info +#else adr_l sp, initial_sp, x4 mov x4, sp and x4, x4, #~(THREAD_SIZE - 1) msr sp_el0, x4 // Save thread_info +#endif + str_l x21, __fdt_pointer, x5 // Save FDT pointer str_l x24, memstart_addr, x6 // Save PHYS_OFFSET mov x29, #0 @@ -642,10 +650,18 @@ ENTRY(secondary_startup) ENDPROC(secondary_startup) ENTRY(__secondary_switched) +#ifdef CONFIG_THREAD_INFO_IN_TASK + adr_l x0, secondary_data + ldr x1, [x0, #CPU_BOOT_STACK] // get secondary_data.stack + mov sp, x1 + ldr x2, [x0, #CPU_BOOT_TASK] + msr sp_el0, x2 +#else ldr x0, [x21] // get secondary_data.stack mov sp, x0 and x0, x0, #~(THREAD_SIZE - 1) msr sp_el0, x0 // save thread_info +#endif mov x29, #0 b secondary_start_kernel ENDPROC(__secondary_switched) diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c index e21fd6559b68..4db258a02254 100644 --- a/arch/arm64/kernel/process.c +++ b/arch/arm64/kernel/process.c @@ -44,6 +44,9 @@ #include #include +#ifdef CONFIG_THREAD_INFO_IN_TASK +#include +#endif #include #include #include @@ -391,6 +394,22 @@ static void uao_thread_switch(struct task_struct *next) } } +#ifdef CONFIG_THREAD_INFO_IN_TASK +/* + * We store our current task in sp_el0, which is clobbered by userspace. Keep a + * shadow copy so that we can restore this upon entry from userspace. + * + * This is *only* for exception entry from EL0, and is not valid until we + * __switch_to() a user task. + */ +DEFINE_PER_CPU(struct task_struct *, __entry_task); + +static void entry_task_switch(struct task_struct *next) +{ + __this_cpu_write(__entry_task, next); +} +#endif + /* * Thread switching. */ @@ -403,6 +422,9 @@ struct task_struct *__switch_to(struct task_struct *prev, tls_thread_switch(next); hw_breakpoint_thread_switch(next); contextidr_thread_switch(next); +#ifdef CONFIG_THREAD_INFO_IN_TASK + entry_task_switch(next); +#endif uao_thread_switch(next); /* diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c index 5f80881df662..61cca6eb99ec 100644 --- a/arch/arm64/kernel/smp.c +++ b/arch/arm64/kernel/smp.c @@ -97,6 +97,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) * We need to tell the secondary core where to find its stack and the * page tables. */ +#ifdef CONFIG_THREAD_INFO_IN_TASK + secondary_data.task = idle; +#endif secondary_data.stack = task_stack_page(idle) + THREAD_START_SP; __flush_dcache_area(&secondary_data, sizeof(secondary_data)); @@ -120,6 +123,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) pr_err("CPU%u: failed to boot: %d\n", cpu, ret); } +#ifdef CONFIG_THREAD_INFO_IN_TASK + secondary_data.task = NULL; +#endif secondary_data.stack = NULL; return ret; @@ -134,7 +140,7 @@ static void smp_store_cpu_info(unsigned int cpuid) * This is the secondary CPU boot entry. We're using this CPUs * idle thread stack, but a set of temporary page tables. */ -asmlinkage void secondary_start_kernel(void) +asmlinkage notrace void secondary_start_kernel(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index d2de3ccb72d0..f23887c11664 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -114,11 +114,13 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max) } #ifdef CONFIG_HAVE_ARCH_PFN_VALID -#define PFN_MASK ((1UL << (64 - PAGE_SHIFT)) - 1) - int pfn_valid(unsigned long pfn) { - return (pfn & PFN_MASK) == pfn && memblock_is_memory(pfn << PAGE_SHIFT); + phys_addr_t addr = pfn << PAGE_SHIFT; + + if ((addr >> PAGE_SHIFT) != pfn) + return 0; + return memblock_is_memory(addr); } EXPORT_SYMBOL(pfn_valid); #endif diff --git a/arch/m68k/include/asm/mcf_pgalloc.h b/arch/m68k/include/asm/mcf_pgalloc.h index f9924fbcfe42..456e3f75ef3b 100644 --- a/arch/m68k/include/asm/mcf_pgalloc.h +++ b/arch/m68k/include/asm/mcf_pgalloc.h @@ -43,6 +43,7 @@ extern inline pmd_t *pmd_alloc_kernel(pgd_t *pgd, unsigned long address) static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t page, unsigned long address) { + pgtable_page_dtor(page); __free_page(page); } @@ -73,8 +74,9 @@ static inline struct page *pte_alloc_one(struct mm_struct *mm, return page; } -extern inline void pte_free(struct mm_struct *mm, struct page *page) +static inline void pte_free(struct mm_struct *mm, struct page *page) { + pgtable_page_dtor(page); __free_page(page); } diff --git a/arch/microblaze/boot/Makefile b/arch/microblaze/boot/Makefile index 8e211cc28dac..e0f2afb98098 100644 --- a/arch/microblaze/boot/Makefile +++ b/arch/microblaze/boot/Makefile @@ -21,18 +21,20 @@ $(obj)/linux.bin.gz: $(obj)/linux.bin FORCE quiet_cmd_cp = CP $< $@$2 cmd_cp = cat $< >$@$2 || (rm -f $@ && echo false) -quiet_cmd_strip = STRIP $@ +quiet_cmd_strip = STRIP $< $@$2 cmd_strip = $(STRIP) -K microblaze_start -K _end -K __log_buf \ - -K _fdt_start vmlinux -o $@ + -K _fdt_start $< -o $@$2 UIMAGE_LOADADDR = $(CONFIG_KERNEL_BASE_ADDR) +UIMAGE_IN = $@ +UIMAGE_OUT = $@.ub $(obj)/simpleImage.%: vmlinux FORCE $(call if_changed,cp,.unstrip) $(call if_changed,objcopy) $(call if_changed,uimage) - $(call if_changed,strip) - @echo 'Kernel: $@ is ready' ' (#'`cat .version`')' + $(call if_changed,strip,.strip) + @echo 'Kernel: $(UIMAGE_OUT) is ready' ' (#'`cat .version`')' clean-files += simpleImage.*.unstrip linux.bin.ub diff --git a/arch/mips/bcm47xx/setup.c b/arch/mips/bcm47xx/setup.c index 706bab38479d..c00585d915bc 100644 --- a/arch/mips/bcm47xx/setup.c +++ b/arch/mips/bcm47xx/setup.c @@ -269,12 +269,6 @@ static int __init bcm47xx_cpu_fixes(void) */ if (bcm47xx_bus.bcma.bus.chipinfo.id == BCMA_CHIP_ID_BCM4706) cpu_wait = NULL; - - /* - * BCM47XX Erratum "R10: PCIe Transactions Periodically Fail" - * Enable ExternalSync for sync instruction to take effect - */ - set_c0_config7(MIPS_CONF7_ES); break; #endif } diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index 9655d0a47e8c..f38ca68285ea 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -667,8 +667,6 @@ #define MIPS_CONF7_WII (_ULCAST_(1) << 31) #define MIPS_CONF7_RPS (_ULCAST_(1) << 2) -/* ExternalSync */ -#define MIPS_CONF7_ES (_ULCAST_(1) << 8) #define MIPS_CONF7_IAR (_ULCAST_(1) << 10) #define MIPS_CONF7_AR (_ULCAST_(1) << 16) @@ -1865,7 +1863,6 @@ __BUILD_SET_C0(status) __BUILD_SET_C0(cause) __BUILD_SET_C0(config) __BUILD_SET_C0(config5) -__BUILD_SET_C0(config7) __BUILD_SET_C0(intcontrol) __BUILD_SET_C0(intctl) __BUILD_SET_C0(srsmap) diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 578ece1e4a99..351a5a9e4f52 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h @@ -143,7 +143,7 @@ struct mips_fpu_struct { #define NUM_DSP_REGS 6 -typedef __u32 dspreg_t; +typedef unsigned long dspreg_t; struct mips_dsp_state { dspreg_t dspr[NUM_DSP_REGS]; diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index c1bd750494c1..0b16f07ada9f 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -751,7 +751,7 @@ long arch_ptrace(struct task_struct *child, long request, goto out; } dregs = __get_dsp_regs(child); - tmp = (unsigned long) (dregs[addr - DSP_BASE]); + tmp = dregs[addr - DSP_BASE]; break; } case DSP_CONTROL: diff --git a/arch/mips/kernel/ptrace32.c b/arch/mips/kernel/ptrace32.c index d95117e71f69..286ec2d24d47 100644 --- a/arch/mips/kernel/ptrace32.c +++ b/arch/mips/kernel/ptrace32.c @@ -140,7 +140,7 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, goto out; } dregs = __get_dsp_regs(child); - tmp = (unsigned long) (dregs[addr - DSP_BASE]); + tmp = dregs[addr - DSP_BASE]; break; } case DSP_CONTROL: diff --git a/arch/powerpc/include/asm/fadump.h b/arch/powerpc/include/asm/fadump.h index 493e72f64b35..5768ec3c1781 100644 --- a/arch/powerpc/include/asm/fadump.h +++ b/arch/powerpc/include/asm/fadump.h @@ -194,9 +194,6 @@ struct fadump_crash_info_header { struct cpumask cpu_online_mask; }; -/* Crash memory ranges */ -#define INIT_CRASHMEM_RANGES (INIT_MEMBLOCK_REGIONS + 2) - struct fad_crash_memory_ranges { unsigned long long base; unsigned long long size; diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c index 791d4c3329c3..c3c835290131 100644 --- a/arch/powerpc/kernel/fadump.c +++ b/arch/powerpc/kernel/fadump.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -48,8 +49,10 @@ static struct fadump_mem_struct fdm; static const struct fadump_mem_struct *fdm_active; static DEFINE_MUTEX(fadump_mutex); -struct fad_crash_memory_ranges crash_memory_ranges[INIT_CRASHMEM_RANGES]; +struct fad_crash_memory_ranges *crash_memory_ranges; +int crash_memory_ranges_size; int crash_mem_ranges; +int max_crash_mem_ranges; /* Scan the Firmware Assisted dump configuration details. */ int __init early_init_dt_scan_fw_dump(unsigned long node, @@ -726,38 +729,88 @@ static int __init process_fadump(const struct fadump_mem_struct *fdm_active) return 0; } -static inline void fadump_add_crash_memory(unsigned long long base, - unsigned long long end) +static void free_crash_memory_ranges(void) +{ + kfree(crash_memory_ranges); + crash_memory_ranges = NULL; + crash_memory_ranges_size = 0; + max_crash_mem_ranges = 0; +} + +/* + * Allocate or reallocate crash memory ranges array in incremental units + * of PAGE_SIZE. + */ +static int allocate_crash_memory_ranges(void) +{ + struct fad_crash_memory_ranges *new_array; + u64 new_size; + + new_size = crash_memory_ranges_size + PAGE_SIZE; + pr_debug("Allocating %llu bytes of memory for crash memory ranges\n", + new_size); + + new_array = krealloc(crash_memory_ranges, new_size, GFP_KERNEL); + if (new_array == NULL) { + pr_err("Insufficient memory for setting up crash memory ranges\n"); + free_crash_memory_ranges(); + return -ENOMEM; + } + + crash_memory_ranges = new_array; + crash_memory_ranges_size = new_size; + max_crash_mem_ranges = (new_size / + sizeof(struct fad_crash_memory_ranges)); + return 0; +} + +static inline int fadump_add_crash_memory(unsigned long long base, + unsigned long long end) { if (base == end) - return; + return 0; + + if (crash_mem_ranges == max_crash_mem_ranges) { + int ret; + + ret = allocate_crash_memory_ranges(); + if (ret) + return ret; + } pr_debug("crash_memory_range[%d] [%#016llx-%#016llx], %#llx bytes\n", crash_mem_ranges, base, end - 1, (end - base)); crash_memory_ranges[crash_mem_ranges].base = base; crash_memory_ranges[crash_mem_ranges].size = end - base; crash_mem_ranges++; + return 0; } -static void fadump_exclude_reserved_area(unsigned long long start, +static int fadump_exclude_reserved_area(unsigned long long start, unsigned long long end) { unsigned long long ra_start, ra_end; + int ret = 0; ra_start = fw_dump.reserve_dump_area_start; ra_end = ra_start + fw_dump.reserve_dump_area_size; if ((ra_start < end) && (ra_end > start)) { if ((start < ra_start) && (end > ra_end)) { - fadump_add_crash_memory(start, ra_start); - fadump_add_crash_memory(ra_end, end); + ret = fadump_add_crash_memory(start, ra_start); + if (ret) + return ret; + + ret = fadump_add_crash_memory(ra_end, end); } else if (start < ra_start) { - fadump_add_crash_memory(start, ra_start); + ret = fadump_add_crash_memory(start, ra_start); } else if (ra_end < end) { - fadump_add_crash_memory(ra_end, end); + ret = fadump_add_crash_memory(ra_end, end); } } else - fadump_add_crash_memory(start, end); + ret = fadump_add_crash_memory(start, end); + + return ret; } static int fadump_init_elfcore_header(char *bufp) @@ -793,10 +846,11 @@ static int fadump_init_elfcore_header(char *bufp) * Traverse through memblock structure and setup crash memory ranges. These * ranges will be used create PT_LOAD program headers in elfcore header. */ -static void fadump_setup_crash_memory_ranges(void) +static int fadump_setup_crash_memory_ranges(void) { struct memblock_region *reg; unsigned long long start, end; + int ret; pr_debug("Setup crash memory ranges.\n"); crash_mem_ranges = 0; @@ -807,7 +861,9 @@ static void fadump_setup_crash_memory_ranges(void) * specified during fadump registration. We need to create a separate * program header for this chunk with the correct offset. */ - fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size); + ret = fadump_add_crash_memory(RMA_START, fw_dump.boot_memory_size); + if (ret) + return ret; for_each_memblock(memory, reg) { start = (unsigned long long)reg->base; @@ -816,8 +872,12 @@ static void fadump_setup_crash_memory_ranges(void) start = fw_dump.boot_memory_size; /* add this range excluding the reserved dump area. */ - fadump_exclude_reserved_area(start, end); + ret = fadump_exclude_reserved_area(start, end); + if (ret) + return ret; } + + return 0; } /* @@ -941,6 +1001,7 @@ static void register_fadump(void) { unsigned long addr; void *vaddr; + int ret; /* * If no memory is reserved then we can not register for firmware- @@ -949,7 +1010,9 @@ static void register_fadump(void) if (!fw_dump.reserve_dump_area_size) return; - fadump_setup_crash_memory_ranges(); + ret = fadump_setup_crash_memory_ranges(); + if (ret) + return ret; addr = be64_to_cpu(fdm.rmr_region.destination_address) + be64_to_cpu(fdm.rmr_region.source_len); /* Initialize fadump crash info header. */ @@ -1028,6 +1091,7 @@ void fadump_cleanup(void) } else if (fw_dump.dump_registered) { /* Un-register Firmware-assisted dump if it was registered. */ fadump_unregister_dump(&fdm); + free_crash_memory_ranges(); } } diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index fafff8dbd5d9..3c957548f336 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S @@ -722,7 +722,7 @@ start_here: tovirt(r6,r6) lis r5, abatron_pteptrs@h ori r5, r5, abatron_pteptrs@l - stw r5, 0xf0(r0) /* Must match your Abatron config file */ + stw r5, 0xf0(0) /* Must match your Abatron config file */ tophys(r5,r5) stw r6, 0(r5) diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 432459c817fa..28724443d1a6 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/powerpc/platforms/chrp/time.c b/arch/powerpc/platforms/chrp/time.c index f803f4b8ab6f..8608e358217f 100644 --- a/arch/powerpc/platforms/chrp/time.c +++ b/arch/powerpc/platforms/chrp/time.c @@ -27,6 +27,8 @@ #include #include +#include + extern spinlock_t rtc_lock; #define NVRAM_AS0 0x74 @@ -62,7 +64,7 @@ long __init chrp_time_init(void) return 0; } -int chrp_cmos_clock_read(int addr) +static int chrp_cmos_clock_read(int addr) { if (nvram_as1 != 0) outb(addr>>8, nvram_as1); @@ -70,7 +72,7 @@ int chrp_cmos_clock_read(int addr) return (inb(nvram_data)); } -void chrp_cmos_clock_write(unsigned long val, int addr) +static void chrp_cmos_clock_write(unsigned long val, int addr) { if (nvram_as1 != 0) outb(addr>>8, nvram_as1); diff --git a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c index c269caee58f9..f44b382449ca 100644 --- a/arch/powerpc/platforms/embedded6xx/hlwd-pic.c +++ b/arch/powerpc/platforms/embedded6xx/hlwd-pic.c @@ -35,6 +35,8 @@ */ #define HW_BROADWAY_ICR 0x00 #define HW_BROADWAY_IMR 0x04 +#define HW_STARLET_ICR 0x08 +#define HW_STARLET_IMR 0x0c /* @@ -74,6 +76,9 @@ static void hlwd_pic_unmask(struct irq_data *d) void __iomem *io_base = irq_data_get_irq_chip_data(d); setbits32(io_base + HW_BROADWAY_IMR, 1 << irq); + + /* Make sure the ARM (aka. Starlet) doesn't handle this interrupt. */ + clrbits32(io_base + HW_STARLET_IMR, 1 << irq); } diff --git a/arch/powerpc/platforms/powermac/bootx_init.c b/arch/powerpc/platforms/powermac/bootx_init.c index 3e91ef538114..9adc9eaaf365 100644 --- a/arch/powerpc/platforms/powermac/bootx_init.c +++ b/arch/powerpc/platforms/powermac/bootx_init.c @@ -467,7 +467,7 @@ void __init bootx_init(unsigned long r3, unsigned long r4) boot_infos_t *bi = (boot_infos_t *) r4; unsigned long hdr; unsigned long space; - unsigned long ptr, x; + unsigned long ptr; char *model; unsigned long offset = reloc_offset(); @@ -561,6 +561,8 @@ void __init bootx_init(unsigned long r3, unsigned long r4) * MMU switched OFF, so this should not be useful anymore. */ if (bi->version < 4) { + unsigned long x __maybe_unused; + bootx_printf("Touching pages...\n"); /* diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index b127a29ac526..49148e2e13a8 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -359,6 +359,7 @@ static int pmac_late_init(void) } machine_late_initcall(powermac, pmac_late_init); +void note_bootable_part(dev_t dev, int part, int goodness); /* * This is __init_refok because we check for "initializing" before * touching any of the __init sensitive things and "initializing" diff --git a/arch/powerpc/platforms/pseries/ras.c b/arch/powerpc/platforms/pseries/ras.c index d263f7bc80fc..c85c76dc4400 100644 --- a/arch/powerpc/platforms/pseries/ras.c +++ b/arch/powerpc/platforms/pseries/ras.c @@ -298,7 +298,7 @@ static struct rtas_error_log *fwnmi_get_errinfo(struct pt_regs *regs) } savep = __va(regs->gpr[3]); - regs->gpr[3] = savep[0]; /* restore original r3 */ + regs->gpr[3] = be64_to_cpu(savep[0]); /* restore original r3 */ /* If it isn't an extended log we can use the per cpu 64bit buffer */ h = (struct rtas_error_log *)&savep[1]; diff --git a/arch/s390/include/asm/cpu_mf.h b/arch/s390/include/asm/cpu_mf.h index cb700d54bd83..0a1ca50298e8 100644 --- a/arch/s390/include/asm/cpu_mf.h +++ b/arch/s390/include/asm/cpu_mf.h @@ -118,7 +118,7 @@ struct hws_basic_entry { struct hws_diag_entry { unsigned int def:16; /* 0-15 Data Entry Format */ - unsigned int R:14; /* 16-19 and 20-30 reserved */ + unsigned int R:15; /* 16-19 and 20-30 reserved */ unsigned int I:1; /* 31 entry valid or invalid */ u8 data[]; /* Machine-dependent sample data */ } __packed; @@ -134,7 +134,9 @@ struct hws_trailer_entry { unsigned int f:1; /* 0 - Block Full Indicator */ unsigned int a:1; /* 1 - Alert request control */ unsigned int t:1; /* 2 - Timestamp format */ - unsigned long long:61; /* 3 - 63: Reserved */ + unsigned int :29; /* 3 - 31: Reserved */ + unsigned int bsdes:16; /* 32-47: size of basic SDE */ + unsigned int dsdes:16; /* 48-63: size of diagnostic SDE */ }; unsigned long long flags; /* 0 - 63: All indicators */ }; diff --git a/arch/s390/include/asm/qdio.h b/arch/s390/include/asm/qdio.h index 06f3034605a1..33894abf03df 100644 --- a/arch/s390/include/asm/qdio.h +++ b/arch/s390/include/asm/qdio.h @@ -271,7 +271,6 @@ struct qdio_outbuf_state { void *user; }; -#define QDIO_OUTBUF_STATE_FLAG_NONE 0x00 #define QDIO_OUTBUF_STATE_FLAG_PENDING 0x01 #define CHSC_AC1_INITIATE_INPUTQ 0x80 diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index fbe8f2cf9245..eecd61bdc0d9 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -494,6 +494,8 @@ static inline int do_exception(struct pt_regs *regs, int access) /* No reason to continue if interrupted by SIGKILL. */ if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) { fault = VM_FAULT_SIGNAL; + if (flags & FAULT_FLAG_RETRY_NOWAIT) + goto out_up; goto out; } if (unlikely(fault & VM_FAULT_ERROR)) diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c index b6b76785f879..f5101a890b57 100644 --- a/arch/s390/pci/pci.c +++ b/arch/s390/pci/pci.c @@ -397,6 +397,8 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type) hwirq = 0; list_for_each_entry(msi, &pdev->msi_list, list) { rc = -EIO; + if (hwirq >= msi_vecs) + break; irq = irq_alloc_desc(0); /* Alloc irq on node 0 */ if (irq < 0) goto out_msi; diff --git a/arch/sparc/kernel/sys_sparc_32.c b/arch/sparc/kernel/sys_sparc_32.c index 646988d4c1a3..740f43b9b541 100644 --- a/arch/sparc/kernel/sys_sparc_32.c +++ b/arch/sparc/kernel/sys_sparc_32.c @@ -201,23 +201,27 @@ SYSCALL_DEFINE5(rt_sigaction, int, sig, asmlinkage long sys_getdomainname(char __user *name, int len) { - int nlen, err; - + int nlen, err; + char tmp[__NEW_UTS_LEN + 1]; + if (len < 0) return -EINVAL; - down_read(&uts_sem); - + down_read(&uts_sem); + nlen = strlen(utsname()->domainname) + 1; err = -EINVAL; if (nlen > len) - goto out; + goto out_unlock; + memcpy(tmp, utsname()->domainname, nlen); - err = -EFAULT; - if (!copy_to_user(name, utsname()->domainname, nlen)) - err = 0; + up_read(&uts_sem); -out: + if (copy_to_user(name, tmp, nlen)) + return -EFAULT; + return 0; + +out_unlock: up_read(&uts_sem); return err; } diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 98a5cf313d39..7301fa2091bc 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -524,23 +524,27 @@ extern void check_pending(int signum); SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len) { - int nlen, err; + int nlen, err; + char tmp[__NEW_UTS_LEN + 1]; if (len < 0) return -EINVAL; - down_read(&uts_sem); - + down_read(&uts_sem); + nlen = strlen(utsname()->domainname) + 1; err = -EINVAL; if (nlen > len) - goto out; + goto out_unlock; + memcpy(tmp, utsname()->domainname, nlen); + + up_read(&uts_sem); - err = -EFAULT; - if (!copy_to_user(name, utsname()->domainname, nlen)) - err = 0; + if (copy_to_user(name, tmp, nlen)) + return -EFAULT; + return 0; -out: +out_unlock: up_read(&uts_sem); return err; } diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index d5d3af159bec..291cb502d141 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -2240,9 +2240,6 @@ static ssize_t store_int_with_restart(struct device *s, if (check_interval == old_check_interval) return ret; - if (check_interval < 1) - check_interval = 1; - mutex_lock(&mce_sysfs_mutex); mce_restart(); mutex_unlock(&mce_sysfs_mutex); diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore.c b/arch/x86/kernel/cpu/perf_event_intel_uncore.c index e98f68cfea02..cae9a3b6446b 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore.c @@ -175,7 +175,7 @@ void uncore_perf_event_update(struct intel_uncore_box *box, struct perf_event *e u64 prev_count, new_count, delta; int shift; - if (event->hw.idx >= UNCORE_PMC_IDX_FIXED) + if (event->hw.idx == UNCORE_PMC_IDX_FIXED) shift = 64 - uncore_fixed_ctr_bits(box); else shift = 64 - uncore_perf_ctr_bits(box); diff --git a/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c b/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c index 2749965afed0..83cadc2605a7 100644 --- a/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c +++ b/arch/x86/kernel/cpu/perf_event_intel_uncore_nhmex.c @@ -240,7 +240,7 @@ static void nhmex_uncore_msr_enable_event(struct intel_uncore_box *box, struct p { struct hw_perf_event *hwc = &event->hw; - if (hwc->idx >= UNCORE_PMC_IDX_FIXED) + if (hwc->idx == UNCORE_PMC_IDX_FIXED) wrmsrl(hwc->config_base, NHMEX_PMON_CTL_EN_BIT0); else if (box->pmu->type->event_mask & NHMEX_PMON_CTL_EN_BIT0) wrmsrl(hwc->config_base, hwc->config | NHMEX_PMON_CTL_EN_BIT22); diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c index 51947348fcb9..323d122267b2 100644 --- a/arch/x86/kernel/kprobes/core.c +++ b/arch/x86/kernel/kprobes/core.c @@ -365,7 +365,6 @@ int __copy_instruction(u8 *dest, u8 *src) newdisp = (u8 *) src + (s64) insn.displacement.value - (u8 *) dest; if ((s64) (s32) newdisp != newdisp) { pr_err("Kprobes error: new displacement does not fit into s32 (%llx)\n", newdisp); - pr_err("\tSrc: %p, Dest: %p, old disp: %x\n", src, dest, insn.displacement.value); return 0; } disp = (u8 *) dest + insn_offset_displacement(&insn); @@ -568,8 +567,7 @@ static int reenter_kprobe(struct kprobe *p, struct pt_regs *regs, * Raise a BUG or we'll continue in an endless reentering loop * and eventually a stack overflow. */ - printk(KERN_WARNING "Unrecoverable kprobe detected at %p.\n", - p->addr); + pr_err("Unrecoverable kprobe detected.\n"); dump_kprobe(p); BUG(); default: diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index f547f866e86c..ba48e77c8e9e 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c @@ -438,6 +438,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) return prev_p; } +EXPORT_SYMBOL_GPL(start_thread); void set_personality_64bit(void) { diff --git a/block/blk-core.c b/block/blk-core.c index 7d4cd21b123b..fb4160993001 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -2966,7 +2966,7 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src, blk_rq_init(NULL, rq); __rq_for_each_bio(bio_src, rq_src) { - bio = bio_clone_fast(bio_src, gfp_mask, bs); + bio = bio_clone_bioset(bio_src, gfp_mask, bs); if (!bio) goto free_and_out; diff --git a/crypto/ablkcipher.c b/crypto/ablkcipher.c index 520729d898fe..5061d7ad33e4 100644 --- a/crypto/ablkcipher.c +++ b/crypto/ablkcipher.c @@ -72,11 +72,9 @@ static inline u8 *ablkcipher_get_spot(u8 *start, unsigned int len) return max(start, end_page); } -static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk, - unsigned int bsize) +static inline void ablkcipher_done_slow(struct ablkcipher_walk *walk, + unsigned int n) { - unsigned int n = bsize; - for (;;) { unsigned int len_this_page = scatterwalk_pagelen(&walk->out); @@ -88,17 +86,13 @@ static inline unsigned int ablkcipher_done_slow(struct ablkcipher_walk *walk, n -= len_this_page; scatterwalk_start(&walk->out, scatterwalk_sg_next(walk->out.sg)); } - - return bsize; } -static inline unsigned int ablkcipher_done_fast(struct ablkcipher_walk *walk, - unsigned int n) +static inline void ablkcipher_done_fast(struct ablkcipher_walk *walk, + unsigned int n) { scatterwalk_advance(&walk->in, n); scatterwalk_advance(&walk->out, n); - - return n; } static int ablkcipher_walk_next(struct ablkcipher_request *req, @@ -108,39 +102,40 @@ int ablkcipher_walk_done(struct ablkcipher_request *req, struct ablkcipher_walk *walk, int err) { struct crypto_tfm *tfm = req->base.tfm; - unsigned int nbytes = 0; + unsigned int n; /* bytes processed */ + bool more; - if (likely(err >= 0)) { - unsigned int n = walk->nbytes - err; + if (unlikely(err < 0)) + goto finish; - if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW))) - n = ablkcipher_done_fast(walk, n); - else if (WARN_ON(err)) { - err = -EINVAL; - goto err; - } else - n = ablkcipher_done_slow(walk, n); + n = walk->nbytes - err; + walk->total -= n; + more = (walk->total != 0); - nbytes = walk->total - n; - err = 0; + if (likely(!(walk->flags & ABLKCIPHER_WALK_SLOW))) { + ablkcipher_done_fast(walk, n); + } else { + if (WARN_ON(err)) { + /* unexpected case; didn't process all bytes */ + err = -EINVAL; + goto finish; + } + ablkcipher_done_slow(walk, n); } - scatterwalk_done(&walk->in, 0, nbytes); - scatterwalk_done(&walk->out, 1, nbytes); - -err: - walk->total = nbytes; - walk->nbytes = nbytes; + scatterwalk_done(&walk->in, 0, more); + scatterwalk_done(&walk->out, 1, more); - if (nbytes) { + if (more) { crypto_yield(req->base.flags); return ablkcipher_walk_next(req, walk); } - + err = 0; +finish: + walk->nbytes = 0; if (walk->iv != req->info) memcpy(req->info, walk->iv, tfm->crt_ablkcipher.ivsize); kfree(walk->iv_buffer); - return err; } EXPORT_SYMBOL_GPL(ablkcipher_walk_done); diff --git a/crypto/authenc.c b/crypto/authenc.c index 78fb16cab13f..eb029ea72f98 100644 --- a/crypto/authenc.c +++ b/crypto/authenc.c @@ -112,6 +112,7 @@ static int crypto_authenc_setkey(struct crypto_aead *authenc, const u8 *key, CRYPTO_TFM_RES_MASK); out: + memzero_explicit(&keys, sizeof(keys)); return err; badkey: diff --git a/crypto/authencesn.c b/crypto/authencesn.c index 024bff2344fc..c248a966aa5b 100644 --- a/crypto/authencesn.c +++ b/crypto/authencesn.c @@ -86,6 +86,7 @@ static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 * CRYPTO_TFM_RES_MASK); out: + memzero_explicit(&keys, sizeof(keys)); return err; badkey: diff --git a/crypto/blkcipher.c b/crypto/blkcipher.c index f25799f351f7..5ebfdd0d4543 100644 --- a/crypto/blkcipher.c +++ b/crypto/blkcipher.c @@ -70,19 +70,18 @@ static inline u8 *blkcipher_get_spot(u8 *start, unsigned int len) return max(start, end_page); } -static inline unsigned int blkcipher_done_slow(struct blkcipher_walk *walk, - unsigned int bsize) +static inline void blkcipher_done_slow(struct blkcipher_walk *walk, + unsigned int bsize) { u8 *addr; addr = (u8 *)ALIGN((unsigned long)walk->buffer, walk->alignmask + 1); addr = blkcipher_get_spot(addr, bsize); scatterwalk_copychunks(addr, &walk->out, bsize, 1); - return bsize; } -static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk, - unsigned int n) +static inline void blkcipher_done_fast(struct blkcipher_walk *walk, + unsigned int n) { if (walk->flags & BLKCIPHER_WALK_COPY) { blkcipher_map_dst(walk); @@ -96,49 +95,48 @@ static inline unsigned int blkcipher_done_fast(struct blkcipher_walk *walk, scatterwalk_advance(&walk->in, n); scatterwalk_advance(&walk->out, n); - - return n; } int blkcipher_walk_done(struct blkcipher_desc *desc, struct blkcipher_walk *walk, int err) { - unsigned int nbytes = 0; + unsigned int n; /* bytes processed */ + bool more; - if (likely(err >= 0)) { - unsigned int n = walk->nbytes - err; + if (unlikely(err < 0)) + goto finish; - if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) - n = blkcipher_done_fast(walk, n); - else if (WARN_ON(err)) { - err = -EINVAL; - goto err; - } else - n = blkcipher_done_slow(walk, n); + n = walk->nbytes - err; + walk->total -= n; + more = (walk->total != 0); - nbytes = walk->total - n; - err = 0; + if (likely(!(walk->flags & BLKCIPHER_WALK_SLOW))) { + blkcipher_done_fast(walk, n); + } else { + if (WARN_ON(err)) { + /* unexpected case; didn't process all bytes */ + err = -EINVAL; + goto finish; + } + blkcipher_done_slow(walk, n); } - scatterwalk_done(&walk->in, 0, nbytes); - scatterwalk_done(&walk->out, 1, nbytes); - -err: - walk->total = nbytes; - walk->nbytes = nbytes; + scatterwalk_done(&walk->in, 0, more); + scatterwalk_done(&walk->out, 1, more); - if (nbytes) { + if (more) { crypto_yield(desc->flags); return blkcipher_walk_next(desc, walk); } - + err = 0; +finish: + walk->nbytes = 0; if (walk->iv != desc->info) memcpy(desc->info, walk->iv, walk->ivsize); if (walk->buffer != walk->page) kfree(walk->buffer); if (walk->page) free_page((unsigned long)walk->page); - return err; } EXPORT_SYMBOL_GPL(blkcipher_walk_done); diff --git a/crypto/pcrypt.c b/crypto/pcrypt.c index c305d4112735..bd5f14ea528e 100644 --- a/crypto/pcrypt.c +++ b/crypto/pcrypt.c @@ -306,6 +306,14 @@ static void pcrypt_aead_exit_tfm(struct crypto_tfm *tfm) crypto_free_aead(ctx->child); } +static void pcrypt_free(struct crypto_instance *inst) +{ + struct pcrypt_instance_ctx *ctx = crypto_instance_ctx(inst); + + crypto_drop_spawn(&ctx->spawn); + kfree(inst); +} + static struct crypto_instance *pcrypt_alloc_instance(struct crypto_alg *alg) { struct crypto_instance *inst; @@ -375,6 +383,7 @@ static struct crypto_instance *pcrypt_alloc_aead(struct rtattr **tb, inst->alg.cra_aead.encrypt = pcrypt_aead_encrypt; inst->alg.cra_aead.decrypt = pcrypt_aead_decrypt; inst->alg.cra_aead.givencrypt = pcrypt_aead_givencrypt; + inst->tmpl->free = pcrypt_free; out_put_alg: crypto_mod_put(alg); @@ -397,14 +406,6 @@ static struct crypto_instance *pcrypt_alloc(struct rtattr **tb) return ERR_PTR(-EINVAL); } -static void pcrypt_free(struct crypto_instance *inst) -{ - struct pcrypt_instance_ctx *ctx = crypto_instance_ctx(inst); - - crypto_drop_spawn(&ctx->spawn); - kfree(inst); -} - static int pcrypt_cpumask_change_notify(struct notifier_block *self, unsigned long val, void *data) { @@ -517,7 +518,6 @@ static void pcrypt_fini_padata(struct padata_pcrypt *pcrypt) static struct crypto_template pcrypt_tmpl = { .name = "pcrypt", .alloc = pcrypt_alloc, - .free = pcrypt_free, .module = THIS_MODULE, }; diff --git a/crypto/vmac.c b/crypto/vmac.c index df76a816cfb2..bb2fc787d615 100644 --- a/crypto/vmac.c +++ b/crypto/vmac.c @@ -1,6 +1,10 @@ /* - * Modified to interface to the Linux kernel + * VMAC: Message Authentication Code using Universal Hashing + * + * Reference: https://tools.ietf.org/html/draft-krovetz-vmac-01 + * * Copyright (c) 2009, Intel Corporation. + * Copyright (c) 2018, Google Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, @@ -16,14 +20,15 @@ * Place - Suite 330, Boston, MA 02111-1307 USA. */ -/* -------------------------------------------------------------------------- - * VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai. - * This implementation is herby placed in the public domain. - * The authors offers no warranty. Use at your own risk. - * Please send bug reports to the authors. - * Last modified: 17 APR 08, 1700 PDT - * ----------------------------------------------------------------------- */ +/* + * Derived from: + * VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai. + * This implementation is herby placed in the public domain. + * The authors offers no warranty. Use at your own risk. + * Last modified: 17 APR 08, 1700 PDT + */ +#include #include #include #include @@ -31,9 +36,35 @@ #include #include #include -#include #include +/* + * User definable settings. + */ +#define VMAC_TAG_LEN 64 +#define VMAC_KEY_SIZE 128/* Must be 128, 192 or 256 */ +#define VMAC_KEY_LEN (VMAC_KEY_SIZE/8) +#define VMAC_NHBYTES 128/* Must 2^i for any 3 < i < 13 Standard = 128*/ + +/* per-transform (per-key) context */ +struct vmac_tfm_ctx { + struct crypto_cipher *cipher; + u64 nhkey[(VMAC_NHBYTES/8)+2*(VMAC_TAG_LEN/64-1)]; + u64 polykey[2*VMAC_TAG_LEN/64]; + u64 l3key[2*VMAC_TAG_LEN/64]; +}; + +/* per-request context */ +struct vmac_desc_ctx { + union { + u8 partial[VMAC_NHBYTES]; /* partial block */ + __le64 partial_words[VMAC_NHBYTES / 8]; + }; + unsigned int partial_size; /* size of the partial block */ + bool first_block_processed; + u64 polytmp[2*VMAC_TAG_LEN/64]; /* running total of L2-hash */ +}; + /* * Constants and masks */ @@ -318,13 +349,6 @@ static void poly_step_func(u64 *ahi, u64 *alo, } while (0) #endif -static void vhash_abort(struct vmac_ctx *ctx) -{ - ctx->polytmp[0] = ctx->polykey[0] ; - ctx->polytmp[1] = ctx->polykey[1] ; - ctx->first_block_processed = 0; -} - static u64 l3hash(u64 p1, u64 p2, u64 k1, u64 k2, u64 len) { u64 rh, rl, t, z = 0; @@ -364,280 +388,209 @@ static u64 l3hash(u64 p1, u64 p2, u64 k1, u64 k2, u64 len) return rl; } -static void vhash_update(const unsigned char *m, - unsigned int mbytes, /* Pos multiple of VMAC_NHBYTES */ - struct vmac_ctx *ctx) +/* L1 and L2-hash one or more VMAC_NHBYTES-byte blocks */ +static void vhash_blocks(const struct vmac_tfm_ctx *tctx, + struct vmac_desc_ctx *dctx, + const __le64 *mptr, unsigned int blocks) { - u64 rh, rl, *mptr; - const u64 *kptr = (u64 *)ctx->nhkey; - int i; - u64 ch, cl; - u64 pkh = ctx->polykey[0]; - u64 pkl = ctx->polykey[1]; - - if (!mbytes) - return; - - BUG_ON(mbytes % VMAC_NHBYTES); - - mptr = (u64 *)m; - i = mbytes / VMAC_NHBYTES; /* Must be non-zero */ - - ch = ctx->polytmp[0]; - cl = ctx->polytmp[1]; - - if (!ctx->first_block_processed) { - ctx->first_block_processed = 1; + const u64 *kptr = tctx->nhkey; + const u64 pkh = tctx->polykey[0]; + const u64 pkl = tctx->polykey[1]; + u64 ch = dctx->polytmp[0]; + u64 cl = dctx->polytmp[1]; + u64 rh, rl; + + if (!dctx->first_block_processed) { + dctx->first_block_processed = true; nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, rh, rl); rh &= m62; ADD128(ch, cl, rh, rl); mptr += (VMAC_NHBYTES/sizeof(u64)); - i--; + blocks--; } - while (i--) { + while (blocks--) { nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, rh, rl); rh &= m62; poly_step(ch, cl, pkh, pkl, rh, rl); mptr += (VMAC_NHBYTES/sizeof(u64)); } - ctx->polytmp[0] = ch; - ctx->polytmp[1] = cl; + dctx->polytmp[0] = ch; + dctx->polytmp[1] = cl; } -static u64 vhash(unsigned char m[], unsigned int mbytes, - u64 *tagl, struct vmac_ctx *ctx) +static int vmac_setkey(struct crypto_shash *tfm, + const u8 *key, unsigned int keylen) { - u64 rh, rl, *mptr; - const u64 *kptr = (u64 *)ctx->nhkey; - int i, remaining; - u64 ch, cl; - u64 pkh = ctx->polykey[0]; - u64 pkl = ctx->polykey[1]; - - mptr = (u64 *)m; - i = mbytes / VMAC_NHBYTES; - remaining = mbytes % VMAC_NHBYTES; - - if (ctx->first_block_processed) { - ch = ctx->polytmp[0]; - cl = ctx->polytmp[1]; - } else if (i) { - nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, ch, cl); - ch &= m62; - ADD128(ch, cl, pkh, pkl); - mptr += (VMAC_NHBYTES/sizeof(u64)); - i--; - } else if (remaining) { - nh_16(mptr, kptr, 2*((remaining+15)/16), ch, cl); - ch &= m62; - ADD128(ch, cl, pkh, pkl); - mptr += (VMAC_NHBYTES/sizeof(u64)); - goto do_l3; - } else {/* Empty String */ - ch = pkh; cl = pkl; - goto do_l3; - } - - while (i--) { - nh_vmac_nhbytes(mptr, kptr, VMAC_NHBYTES/8, rh, rl); - rh &= m62; - poly_step(ch, cl, pkh, pkl, rh, rl); - mptr += (VMAC_NHBYTES/sizeof(u64)); - } - if (remaining) { - nh_16(mptr, kptr, 2*((remaining+15)/16), rh, rl); - rh &= m62; - poly_step(ch, cl, pkh, pkl, rh, rl); - } - -do_l3: - vhash_abort(ctx); - remaining *= 8; - return l3hash(ch, cl, ctx->l3key[0], ctx->l3key[1], remaining); -} + struct vmac_tfm_ctx *tctx = crypto_shash_ctx(tfm); + __be64 out[2]; + u8 in[16] = { 0 }; + unsigned int i; + int err; -static u64 vmac(unsigned char m[], unsigned int mbytes, - const unsigned char n[16], u64 *tagl, - struct vmac_ctx_t *ctx) -{ - u64 *in_n, *out_p; - u64 p, h; - int i; - - in_n = ctx->__vmac_ctx.cached_nonce; - out_p = ctx->__vmac_ctx.cached_aes; - - i = n[15] & 1; - if ((*(u64 *)(n+8) != in_n[1]) || (*(u64 *)(n) != in_n[0])) { - in_n[0] = *(u64 *)(n); - in_n[1] = *(u64 *)(n+8); - ((unsigned char *)in_n)[15] &= 0xFE; - crypto_cipher_encrypt_one(ctx->child, - (unsigned char *)out_p, (unsigned char *)in_n); - - ((unsigned char *)in_n)[15] |= (unsigned char)(1-i); + if (keylen != VMAC_KEY_LEN) { + crypto_shash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; } - p = be64_to_cpup(out_p + i); - h = vhash(m, mbytes, (u64 *)0, &ctx->__vmac_ctx); - return le64_to_cpu(p + h); -} -static int vmac_set_key(unsigned char user_key[], struct vmac_ctx_t *ctx) -{ - u64 in[2] = {0}, out[2]; - unsigned i; - int err = 0; - - err = crypto_cipher_setkey(ctx->child, user_key, VMAC_KEY_LEN); + err = crypto_cipher_setkey(tctx->cipher, key, keylen); if (err) return err; /* Fill nh key */ - ((unsigned char *)in)[0] = 0x80; - for (i = 0; i < sizeof(ctx->__vmac_ctx.nhkey)/8; i += 2) { - crypto_cipher_encrypt_one(ctx->child, - (unsigned char *)out, (unsigned char *)in); - ctx->__vmac_ctx.nhkey[i] = be64_to_cpup(out); - ctx->__vmac_ctx.nhkey[i+1] = be64_to_cpup(out+1); - ((unsigned char *)in)[15] += 1; + in[0] = 0x80; + for (i = 0; i < ARRAY_SIZE(tctx->nhkey); i += 2) { + crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in); + tctx->nhkey[i] = be64_to_cpu(out[0]); + tctx->nhkey[i+1] = be64_to_cpu(out[1]); + in[15]++; } /* Fill poly key */ - ((unsigned char *)in)[0] = 0xC0; - in[1] = 0; - for (i = 0; i < sizeof(ctx->__vmac_ctx.polykey)/8; i += 2) { - crypto_cipher_encrypt_one(ctx->child, - (unsigned char *)out, (unsigned char *)in); - ctx->__vmac_ctx.polytmp[i] = - ctx->__vmac_ctx.polykey[i] = - be64_to_cpup(out) & mpoly; - ctx->__vmac_ctx.polytmp[i+1] = - ctx->__vmac_ctx.polykey[i+1] = - be64_to_cpup(out+1) & mpoly; - ((unsigned char *)in)[15] += 1; + in[0] = 0xC0; + in[15] = 0; + for (i = 0; i < ARRAY_SIZE(tctx->polykey); i += 2) { + crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in); + tctx->polykey[i] = be64_to_cpu(out[0]) & mpoly; + tctx->polykey[i+1] = be64_to_cpu(out[1]) & mpoly; + in[15]++; } /* Fill ip key */ - ((unsigned char *)in)[0] = 0xE0; - in[1] = 0; - for (i = 0; i < sizeof(ctx->__vmac_ctx.l3key)/8; i += 2) { + in[0] = 0xE0; + in[15] = 0; + for (i = 0; i < ARRAY_SIZE(tctx->l3key); i += 2) { do { - crypto_cipher_encrypt_one(ctx->child, - (unsigned char *)out, (unsigned char *)in); - ctx->__vmac_ctx.l3key[i] = be64_to_cpup(out); - ctx->__vmac_ctx.l3key[i+1] = be64_to_cpup(out+1); - ((unsigned char *)in)[15] += 1; - } while (ctx->__vmac_ctx.l3key[i] >= p64 - || ctx->__vmac_ctx.l3key[i+1] >= p64); + crypto_cipher_encrypt_one(tctx->cipher, (u8 *)out, in); + tctx->l3key[i] = be64_to_cpu(out[0]); + tctx->l3key[i+1] = be64_to_cpu(out[1]); + in[15]++; + } while (tctx->l3key[i] >= p64 || tctx->l3key[i+1] >= p64); } - /* Invalidate nonce/aes cache and reset other elements */ - ctx->__vmac_ctx.cached_nonce[0] = (u64)-1; /* Ensure illegal nonce */ - ctx->__vmac_ctx.cached_nonce[1] = (u64)0; /* Ensure illegal nonce */ - ctx->__vmac_ctx.first_block_processed = 0; - - return err; + return 0; } -static int vmac_setkey(struct crypto_shash *parent, - const u8 *key, unsigned int keylen) +static int vmac_init(struct shash_desc *desc) { - struct vmac_ctx_t *ctx = crypto_shash_ctx(parent); + const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); + struct vmac_desc_ctx *dctx = shash_desc_ctx(desc); - if (keylen != VMAC_KEY_LEN) { - crypto_shash_set_flags(parent, CRYPTO_TFM_RES_BAD_KEY_LEN); - return -EINVAL; - } - - return vmac_set_key((u8 *)key, ctx); -} - -static int vmac_init(struct shash_desc *pdesc) -{ + dctx->partial_size = 0; + dctx->first_block_processed = false; + memcpy(dctx->polytmp, tctx->polykey, sizeof(dctx->polytmp)); return 0; } -static int vmac_update(struct shash_desc *pdesc, const u8 *p, - unsigned int len) +static int vmac_update(struct shash_desc *desc, const u8 *p, unsigned int len) { - struct crypto_shash *parent = pdesc->tfm; - struct vmac_ctx_t *ctx = crypto_shash_ctx(parent); - int expand; - int min; - - expand = VMAC_NHBYTES - ctx->partial_size > 0 ? - VMAC_NHBYTES - ctx->partial_size : 0; - - min = len < expand ? len : expand; - - memcpy(ctx->partial + ctx->partial_size, p, min); - ctx->partial_size += min; - - if (len < expand) - return 0; - - vhash_update(ctx->partial, VMAC_NHBYTES, &ctx->__vmac_ctx); - ctx->partial_size = 0; - - len -= expand; - p += expand; + const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); + struct vmac_desc_ctx *dctx = shash_desc_ctx(desc); + unsigned int n; + + if (dctx->partial_size) { + n = min(len, VMAC_NHBYTES - dctx->partial_size); + memcpy(&dctx->partial[dctx->partial_size], p, n); + dctx->partial_size += n; + p += n; + len -= n; + if (dctx->partial_size == VMAC_NHBYTES) { + vhash_blocks(tctx, dctx, dctx->partial_words, 1); + dctx->partial_size = 0; + } + } - if (len % VMAC_NHBYTES) { - memcpy(ctx->partial, p + len - (len % VMAC_NHBYTES), - len % VMAC_NHBYTES); - ctx->partial_size = len % VMAC_NHBYTES; + if (len >= VMAC_NHBYTES) { + n = round_down(len, VMAC_NHBYTES); + /* TODO: 'p' may be misaligned here */ + vhash_blocks(tctx, dctx, (const __le64 *)p, n / VMAC_NHBYTES); + p += n; + len -= n; } - vhash_update(p, len - len % VMAC_NHBYTES, &ctx->__vmac_ctx); + if (len) { + memcpy(dctx->partial, p, len); + dctx->partial_size = len; + } return 0; } -static int vmac_final(struct shash_desc *pdesc, u8 *out) +static u64 vhash_final(const struct vmac_tfm_ctx *tctx, + struct vmac_desc_ctx *dctx) { - struct crypto_shash *parent = pdesc->tfm; - struct vmac_ctx_t *ctx = crypto_shash_ctx(parent); - vmac_t mac; - u8 nonce[16] = {}; - - /* vmac() ends up accessing outside the array bounds that - * we specify. In appears to access up to the next 2-word - * boundary. We'll just be uber cautious and zero the - * unwritten bytes in the buffer. - */ - if (ctx->partial_size) { - memset(ctx->partial + ctx->partial_size, 0, - VMAC_NHBYTES - ctx->partial_size); + unsigned int partial = dctx->partial_size; + u64 ch = dctx->polytmp[0]; + u64 cl = dctx->polytmp[1]; + + /* L1 and L2-hash the final block if needed */ + if (partial) { + /* Zero-pad to next 128-bit boundary */ + unsigned int n = round_up(partial, 16); + u64 rh, rl; + + memset(&dctx->partial[partial], 0, n - partial); + nh_16(dctx->partial_words, tctx->nhkey, n / 8, rh, rl); + rh &= m62; + if (dctx->first_block_processed) + poly_step(ch, cl, tctx->polykey[0], tctx->polykey[1], + rh, rl); + else + ADD128(ch, cl, rh, rl); } - mac = vmac(ctx->partial, ctx->partial_size, nonce, NULL, ctx); - memcpy(out, &mac, sizeof(vmac_t)); - memzero_explicit(&mac, sizeof(vmac_t)); - memset(&ctx->__vmac_ctx, 0, sizeof(struct vmac_ctx)); - ctx->partial_size = 0; + + /* L3-hash the 128-bit output of L2-hash */ + return l3hash(ch, cl, tctx->l3key[0], tctx->l3key[1], partial * 8); +} + +static int vmac_final(struct shash_desc *desc, u8 *out) +{ + const struct vmac_tfm_ctx *tctx = crypto_shash_ctx(desc->tfm); + struct vmac_desc_ctx *dctx = shash_desc_ctx(desc); + static const u8 nonce[16] = {}; /* TODO: this is insecure */ + union { + u8 bytes[16]; + __be64 pads[2]; + } block; + int index; + u64 hash, pad; + + /* Finish calculating the VHASH of the message */ + hash = vhash_final(tctx, dctx); + + /* Generate pseudorandom pad by encrypting the nonce */ + memcpy(&block, nonce, 16); + index = block.bytes[15] & 1; + block.bytes[15] &= ~1; + crypto_cipher_encrypt_one(tctx->cipher, block.bytes, block.bytes); + pad = be64_to_cpu(block.pads[index]); + + /* The VMAC is the sum of VHASH and the pseudorandom pad */ + put_unaligned_le64(hash + pad, out); return 0; } static int vmac_init_tfm(struct crypto_tfm *tfm) { - struct crypto_cipher *cipher; - struct crypto_instance *inst = (void *)tfm->__crt_alg; + struct crypto_instance *inst = crypto_tfm_alg_instance(tfm); struct crypto_spawn *spawn = crypto_instance_ctx(inst); - struct vmac_ctx_t *ctx = crypto_tfm_ctx(tfm); + struct vmac_tfm_ctx *tctx = crypto_tfm_ctx(tfm); + struct crypto_cipher *cipher; cipher = crypto_spawn_cipher(spawn); if (IS_ERR(cipher)) return PTR_ERR(cipher); - ctx->child = cipher; + tctx->cipher = cipher; return 0; } static void vmac_exit_tfm(struct crypto_tfm *tfm) { - struct vmac_ctx_t *ctx = crypto_tfm_ctx(tfm); - crypto_free_cipher(ctx->child); + struct vmac_tfm_ctx *tctx = crypto_tfm_ctx(tfm); + + crypto_free_cipher(tctx->cipher); } static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb) @@ -655,6 +608,10 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb) if (IS_ERR(alg)) return PTR_ERR(alg); + err = -EINVAL; + if (alg->cra_blocksize != 16) + goto out_put_alg; + inst = shash_alloc_instance("vmac", alg); err = PTR_ERR(inst); if (IS_ERR(inst)) @@ -670,11 +627,12 @@ static int vmac_create(struct crypto_template *tmpl, struct rtattr **tb) inst->alg.base.cra_blocksize = alg->cra_blocksize; inst->alg.base.cra_alignmask = alg->cra_alignmask; - inst->alg.digestsize = sizeof(vmac_t); - inst->alg.base.cra_ctxsize = sizeof(struct vmac_ctx_t); + inst->alg.base.cra_ctxsize = sizeof(struct vmac_tfm_ctx); inst->alg.base.cra_init = vmac_init_tfm; inst->alg.base.cra_exit = vmac_exit_tfm; + inst->alg.descsize = sizeof(struct vmac_desc_ctx); + inst->alg.digestsize = VMAC_TAG_LEN / 8; inst->alg.init = vmac_init; inst->alg.update = vmac_update; inst->alg.final = vmac_final; diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index cd4de7e038ea..3e72f9b42097 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c @@ -476,9 +476,11 @@ static void negotiate_os_control(struct acpi_pci_root *root, int *no_aspm, } control = OSC_PCI_EXPRESS_CAPABILITY_CONTROL - | OSC_PCI_EXPRESS_NATIVE_HP_CONTROL | OSC_PCI_EXPRESS_PME_CONTROL; + if (IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE)) + control |= OSC_PCI_EXPRESS_NATIVE_HP_CONTROL; + if (pci_aer_available()) { if (aer_acpi_firmware_first()) dev_info(&device->dev, diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 9bdc1867137b..bdf540f8ca8a 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2173,12 +2173,16 @@ static void ata_eh_link_autopsy(struct ata_link *link) if (qc->err_mask & ~AC_ERR_OTHER) qc->err_mask &= ~AC_ERR_OTHER; - /* SENSE_VALID trumps dev/unknown error and revalidation */ + /* + * SENSE_VALID trumps dev/unknown error and revalidation. Upper + * layers will determine whether the command is worth retrying + * based on the sense data and device class/type. Otherwise, + * determine directly if the command is worth retrying using its + * error mask and flags. + */ if (qc->flags & ATA_QCFLAG_SENSE_VALID) qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER); - - /* determine whether the command is worth retrying */ - if (ata_eh_worth_retry(qc)) + else if (ata_eh_worth_retry(qc)) qc->flags |= ATA_QCFLAG_RETRY; /* accumulate error info */ diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index 998991a365b8..81fb29741dc1 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -2525,7 +2525,7 @@ static int cdrom_ioctl_drive_status(struct cdrom_device_info *cdi, if (!CDROM_CAN(CDC_SELECT_DISC) || (arg == CDSL_CURRENT || arg == CDSL_NONE)) return cdi->ops->drive_status(cdi, CDSL_CURRENT); - if (((int)arg >= cdi->capacity)) + if (arg >= cdi->capacity) return -EINVAL; return cdrom_slot_status(cdi, arg); } diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c index 37d1c3836d0a..69de8258d10f 100644 --- a/drivers/char/adsprpc.c +++ b/drivers/char/adsprpc.c @@ -1843,8 +1843,7 @@ static int fastrpc_file_free(struct fastrpc_file *fl) spin_unlock(&fl->apps->hlock); if (!fl->sctx) { - kfree(fl); - return 0; + goto bail; } (void)fastrpc_release_current_dsp_process(fl); @@ -1856,6 +1855,9 @@ static int fastrpc_file_free(struct fastrpc_file *fl) if (fl->ssrcount == fl->apps->channel[cid].ssrcount) kref_put_mutex(&fl->apps->channel[cid].kref, fastrpc_channel_close, &fl->apps->smd_mutex); + +bail: + mutex_destroy(&fl->map_mutex); kfree(fl); return 0; } @@ -2009,7 +2011,6 @@ static int fastrpc_device_release(struct inode *inode, struct file *file) } me->pending_free++; mutex_unlock(&me->flfree_mutex); - mutex_destroy(&fl->map_mutex); file->private_data = NULL; } bail: diff --git a/drivers/char/diag/diag_dci.c b/drivers/char/diag/diag_dci.c index e195d9d0931c..6e24f475d65d 100644 --- a/drivers/char/diag/diag_dci.c +++ b/drivers/char/diag/diag_dci.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef CONFIG_DIAG_OVER_USB #include #endif @@ -229,7 +230,7 @@ static int diag_dci_init_buffer(struct diag_dci_buffer_t *buffer, int type) switch (type) { case DCI_BUF_PRIMARY: buffer->capacity = IN_BUF_SIZE; - buffer->data = kzalloc(buffer->capacity, GFP_KERNEL); + buffer->data = vzalloc(buffer->capacity); if (!buffer->data) return -ENOMEM; break; @@ -239,7 +240,7 @@ static int diag_dci_init_buffer(struct diag_dci_buffer_t *buffer, int type) break; case DCI_BUF_CMD: buffer->capacity = DIAG_MAX_REQ_SIZE + DCI_BUF_SIZE; - buffer->data = kzalloc(buffer->capacity, GFP_KERNEL); + buffer->data = vzalloc(buffer->capacity); if (!buffer->data) return -ENOMEM; break; @@ -2615,7 +2616,7 @@ static int diag_dci_init_remote(void) create_dci_event_mask_tbl(temp->event_mask_composite); } - partial_pkt.data = kzalloc(MAX_DCI_PACKET_SZ, GFP_KERNEL); + partial_pkt.data = vzalloc(MAX_DCI_PACKET_SZ); if (!partial_pkt.data) { pr_err("diag: Unable to create partial pkt data\n"); return -ENOMEM; @@ -2671,7 +2672,7 @@ int diag_dci_init(void) goto err; if (driver->apps_dci_buf == NULL) { - driver->apps_dci_buf = kzalloc(DCI_BUF_SIZE, GFP_KERNEL); + driver->apps_dci_buf = vzalloc(DCI_BUF_SIZE); if (driver->apps_dci_buf == NULL) goto err; } @@ -2688,12 +2689,12 @@ int diag_dci_init(void) return DIAG_DCI_NO_ERROR; err: pr_err("diag: Could not initialize diag DCI buffers"); - kfree(driver->apps_dci_buf); + vfree(driver->apps_dci_buf); driver->apps_dci_buf = NULL; if (driver->diag_dci_wq) destroy_workqueue(driver->diag_dci_wq); - kfree(partial_pkt.data); + vfree(partial_pkt.data); partial_pkt.data = NULL; mutex_destroy(&driver->dci_mutex); mutex_destroy(&dci_log_mask_mutex); @@ -2713,9 +2714,9 @@ void diag_dci_channel_init(void) void diag_dci_exit(void) { - kfree(partial_pkt.data); + vfree(partial_pkt.data); partial_pkt.data = NULL; - kfree(driver->apps_dci_buf); + vfree(driver->apps_dci_buf); driver->apps_dci_buf = NULL; mutex_destroy(&driver->dci_mutex); mutex_destroy(&dci_log_mask_mutex); @@ -2855,7 +2856,7 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) new_entry->in_service = 0; INIT_LIST_HEAD(&new_entry->list_write_buf); mutex_init(&new_entry->write_buf_mutex); - new_entry->dci_log_mask = kzalloc(DCI_LOG_MASK_SIZE, GFP_KERNEL); + new_entry->dci_log_mask = vzalloc(DCI_LOG_MASK_SIZE); if (!new_entry->dci_log_mask) { pr_err("diag: Unable to create log mask for client, %d", driver->dci_client_id); @@ -2863,7 +2864,7 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) } create_dci_log_mask_tbl(new_entry->dci_log_mask, DCI_LOG_MASK_CLEAN); - new_entry->dci_event_mask = kzalloc(DCI_EVENT_MASK_SIZE, GFP_KERNEL); + new_entry->dci_event_mask = vzalloc(DCI_EVENT_MASK_SIZE); if (!new_entry->dci_event_mask) { pr_err("diag: Unable to create event mask for client, %d", driver->dci_client_id); @@ -2873,7 +2874,7 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) new_entry->buffers = kzalloc(new_entry->num_buffers * sizeof(struct diag_dci_buf_peripheral_t), - GFP_KERNEL); + GFP_KERNEL); if (!new_entry->buffers) { pr_err("diag: Unable to allocate buffers for peripherals in %s\n", __func__); @@ -2897,7 +2898,7 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) if (!proc_buf->buf_primary) goto fail_alloc; proc_buf->buf_cmd = kzalloc(sizeof(struct diag_dci_buffer_t), - GFP_KERNEL); + GFP_KERNEL); if (!proc_buf->buf_cmd) goto fail_alloc; err = diag_dci_init_buffer(proc_buf->buf_primary, @@ -2930,7 +2931,7 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) if (proc_buf) { mutex_destroy(&proc_buf->health_mutex); if (proc_buf->buf_primary) { - kfree(proc_buf->buf_primary->data); + vfree(proc_buf->buf_primary->data); proc_buf->buf_primary->data = NULL; mutex_destroy( &proc_buf->buf_primary->data_mutex); @@ -2938,7 +2939,7 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) kfree(proc_buf->buf_primary); proc_buf->buf_primary = NULL; if (proc_buf->buf_cmd) { - kfree(proc_buf->buf_cmd->data); + vfree(proc_buf->buf_cmd->data); proc_buf->buf_cmd->data = NULL; mutex_destroy( &proc_buf->buf_cmd->data_mutex); @@ -2947,9 +2948,9 @@ int diag_dci_register_client(struct diag_dci_reg_tbl_t *reg_entry) proc_buf->buf_cmd = NULL; } } - kfree(new_entry->dci_event_mask); + vfree(new_entry->dci_event_mask); new_entry->dci_event_mask = NULL; - kfree(new_entry->dci_log_mask); + vfree(new_entry->dci_log_mask); new_entry->dci_log_mask = NULL; kfree(new_entry->buffers); new_entry->buffers = NULL; @@ -2984,7 +2985,7 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry) * Clear the client's log and event masks, update the cumulative * masks and send the masks to peripherals */ - kfree(entry->dci_log_mask); + vfree(entry->dci_log_mask); entry->dci_log_mask = NULL; diag_dci_invalidate_cumulative_log_mask(token); if (token == DCI_LOCAL_PROC) @@ -2993,7 +2994,7 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry) if (ret != DIAG_DCI_NO_ERROR) { return ret; } - kfree(entry->dci_event_mask); + vfree(entry->dci_event_mask); entry->dci_event_mask = NULL; diag_dci_invalidate_cumulative_event_mask(token); if (token == DCI_LOCAL_PROC) @@ -3057,12 +3058,12 @@ int diag_dci_deinit_client(struct diag_dci_client_tbl *entry) } mutex_lock(&proc_buf->buf_primary->data_mutex); - kfree(proc_buf->buf_primary->data); + vfree(proc_buf->buf_primary->data); proc_buf->buf_primary->data = NULL; mutex_unlock(&proc_buf->buf_primary->data_mutex); mutex_lock(&proc_buf->buf_cmd->data_mutex); - kfree(proc_buf->buf_cmd->data); + vfree(proc_buf->buf_cmd->data); proc_buf->buf_cmd->data = NULL; mutex_unlock(&proc_buf->buf_cmd->data_mutex); diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c index dd20aec9983e..4b24df4b6e4c 100644 --- a/drivers/char/diag/diag_masks.c +++ b/drivers/char/diag/diag_masks.c @@ -168,10 +168,11 @@ static void diag_send_log_mask_update(uint8_t peripheral, int equip_id) } mask_info->update_buf = temp; mask_info->update_buf_len = header_len + mask_size; + buf = temp; } memcpy(buf, &ctrl_pkt, header_len); - if (mask_size > 0) + if (mask_size > 0 && mask_size <= LOG_MASK_SIZE) memcpy(buf + header_len, mask->ptr, mask_size); mutex_unlock(&mask->lock); @@ -255,9 +256,16 @@ static void diag_send_event_mask_update(uint8_t peripheral) } else { mask_info->update_buf = temp; mask_info->update_buf_len = temp_len; + buf = temp; } } - memcpy(buf + sizeof(header), mask_info->ptr, num_bytes); + if (num_bytes > 0 && num_bytes < mask_info->mask_len) + memcpy(buf + sizeof(header), mask_info->ptr, num_bytes); + else { + pr_err("diag: num_bytes(%d) is not satisfying length condition\n", + num_bytes); + goto err; + } write_len += num_bytes; break; default: @@ -360,6 +368,7 @@ static void diag_send_msg_mask_update(uint8_t peripheral, int first, int last) } else { mask_info->update_buf = temp; mask_info->update_buf_len = temp_len; + buf = temp; pr_debug("diag: In %s, successfully reallocated msg_mask update buffer to len: %d\n", __func__, mask_info->update_buf_len); } diff --git a/drivers/char/random.c b/drivers/char/random.c index 4ba5c7e4e254..28970b8e4564 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1417,14 +1417,22 @@ static int write_pool(struct entropy_store *r, const char __user *buffer, size_t count) { size_t bytes; - __u32 buf[16]; + __u32 t, buf[16]; const char __user *p = buffer; while (count > 0) { + int b, i = 0; + bytes = min(count, sizeof(buf)); if (copy_from_user(&buf, p, bytes)) return -EFAULT; + for (b = bytes ; b > 0 ; b -= sizeof(__u32), i++) { + if (!arch_get_random_int(&t)) + break; + buf[i] ^= t; + } + count -= bytes; p += bytes; diff --git a/drivers/clk/msm/clock-a7.c b/drivers/clk/msm/clock-a7.c index 96f52df8f830..1dd67b6daed6 100644 --- a/drivers/clk/msm/clock-a7.c +++ b/drivers/clk/msm/clock-a7.c @@ -221,6 +221,7 @@ static int of_get_fmax_vdd_class(struct platform_device *pdev, struct clk *c, devm_kfree(&pdev->dev, array); vdd->num_levels = prop_len; vdd->cur_level = prop_len; + vdd->use_max_uV = true; c->num_fmax = prop_len; return 0; } diff --git a/drivers/clk/msm/clock-gcc-9650.c b/drivers/clk/msm/clock-gcc-9650.c index e2912ff869b4..e454707952b0 100644 --- a/drivers/clk/msm/clock-gcc-9650.c +++ b/drivers/clk/msm/clock-gcc-9650.c @@ -1734,6 +1734,11 @@ static int msm_gcc_9650_probe(struct platform_device *pdev) if (ret) return ret; + if (of_device_is_compatible(pdev->dev.of_node, "qcom,gcc-9650")) { + vdd_dig.use_max_uV = true; + vdd_dig_ao.use_max_uV = true; + } + for_sdx20 = of_device_is_compatible(pdev->dev.of_node, "qcom,gcc-sdx20"); diff --git a/drivers/crypto/padlock-aes.c b/drivers/crypto/padlock-aes.c index c178ed8c3908..2250db026198 100644 --- a/drivers/crypto/padlock-aes.c +++ b/drivers/crypto/padlock-aes.c @@ -266,6 +266,8 @@ static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, return; } + count -= initial; + if (initial) asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ : "+S"(input), "+D"(output) @@ -273,7 +275,7 @@ static inline void padlock_xcrypt_ecb(const u8 *input, u8 *output, void *key, asm volatile (".byte 0xf3,0x0f,0xa7,0xc8" /* rep xcryptecb */ : "+S"(input), "+D"(output) - : "d"(control_word), "b"(key), "c"(count - initial)); + : "d"(control_word), "b"(key), "c"(count)); } static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, @@ -284,6 +286,8 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, if (count < cbc_fetch_blocks) return cbc_crypt(input, output, key, iv, control_word, count); + count -= initial; + if (initial) asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */ : "+S" (input), "+D" (output), "+a" (iv) @@ -291,7 +295,7 @@ static inline u8 *padlock_xcrypt_cbc(const u8 *input, u8 *output, void *key, asm volatile (".byte 0xf3,0x0f,0xa7,0xd0" /* rep xcryptcbc */ : "+S" (input), "+D" (output), "+a" (iv) - : "d" (control_word), "b" (key), "c" (count-initial)); + : "d" (control_word), "b" (key), "c" (count)); return iv; } diff --git a/drivers/dma/k3dma.c b/drivers/dma/k3dma.c index a1f911aaf220..a95f46c2a984 100644 --- a/drivers/dma/k3dma.c +++ b/drivers/dma/k3dma.c @@ -652,7 +652,7 @@ static struct dma_chan *k3_of_dma_simple_xlate(struct of_phandle_args *dma_spec, struct k3_dma_dev *d = ofdma->of_dma_data; unsigned int request = dma_spec->args[0]; - if (request > d->dma_requests) + if (request >= d->dma_requests) return NULL; return dma_get_slave_channel(&(d->chans[request].vc.chan)); diff --git a/drivers/gpu/drm/armada/armada_hw.h b/drivers/gpu/drm/armada/armada_hw.h index 27319a8335e2..345dc4d0851e 100644 --- a/drivers/gpu/drm/armada/armada_hw.h +++ b/drivers/gpu/drm/armada/armada_hw.h @@ -160,6 +160,7 @@ enum { CFG_ALPHAM_GRA = 0x1 << 16, CFG_ALPHAM_CFG = 0x2 << 16, CFG_ALPHA_MASK = 0xff << 8, +#define CFG_ALPHA(x) ((x) << 8) CFG_PIXCMD_MASK = 0xff, }; diff --git a/drivers/gpu/drm/armada/armada_overlay.c b/drivers/gpu/drm/armada/armada_overlay.c index 5c22b380f8f3..f8a69ec63550 100644 --- a/drivers/gpu/drm/armada/armada_overlay.c +++ b/drivers/gpu/drm/armada/armada_overlay.c @@ -27,6 +27,7 @@ struct armada_ovl_plane_properties { uint16_t contrast; uint16_t saturation; uint32_t colorkey_mode; + uint32_t colorkey_enable; }; struct armada_ovl_plane { @@ -62,11 +63,13 @@ armada_ovl_update_attr(struct armada_ovl_plane_properties *prop, writel_relaxed(0x00002000, dcrtc->base + LCD_SPU_CBSH_HUE); spin_lock_irq(&dcrtc->irq_lock); - armada_updatel(prop->colorkey_mode | CFG_ALPHAM_GRA, - CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, - dcrtc->base + LCD_SPU_DMA_CTRL1); - - armada_updatel(ADV_GRACOLORKEY, 0, dcrtc->base + LCD_SPU_ADV_REG); + armada_updatel(prop->colorkey_mode, + CFG_CKMODE_MASK | CFG_ALPHAM_MASK | CFG_ALPHA_MASK, + dcrtc->base + LCD_SPU_DMA_CTRL1); + if (dcrtc->variant->has_spu_adv_reg) + armada_updatel(prop->colorkey_enable, + ADV_GRACOLORKEY | ADV_VIDCOLORKEY, + dcrtc->base + LCD_SPU_ADV_REG); spin_unlock_irq(&dcrtc->irq_lock); } @@ -339,8 +342,17 @@ static int armada_ovl_plane_set_property(struct drm_plane *plane, dplane->prop.colorkey_vb |= K2B(val); update_attr = true; } else if (property == priv->colorkey_mode_prop) { - dplane->prop.colorkey_mode &= ~CFG_CKMODE_MASK; - dplane->prop.colorkey_mode |= CFG_CKMODE(val); + if (val == CKMODE_DISABLE) { + dplane->prop.colorkey_mode = + CFG_CKMODE(CKMODE_DISABLE) | + CFG_ALPHAM_CFG | CFG_ALPHA(255); + dplane->prop.colorkey_enable = 0; + } else { + dplane->prop.colorkey_mode = + CFG_CKMODE(val) | + CFG_ALPHAM_GRA | CFG_ALPHA(0); + dplane->prop.colorkey_enable = ADV_GRACOLORKEY; + } update_attr = true; } else if (property == priv->brightness_prop) { dplane->prop.brightness = val - 256; @@ -469,7 +481,9 @@ int armada_overlay_plane_create(struct drm_device *dev, unsigned long crtcs) dplane->prop.colorkey_yr = 0xfefefe00; dplane->prop.colorkey_ug = 0x01010100; dplane->prop.colorkey_vb = 0x01010100; - dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB); + dplane->prop.colorkey_mode = CFG_CKMODE(CKMODE_RGB) | + CFG_ALPHAM_GRA | CFG_ALPHA(0); + dplane->prop.colorkey_enable = ADV_GRACOLORKEY; dplane->prop.brightness = 0; dplane->prop.contrast = 0x4000; dplane->prop.saturation = 0x4000; diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c index 11b87d2a7913..ba69d1c72221 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c @@ -526,21 +526,25 @@ static int gsc_src_set_fmt(struct device *dev, u32 fmt) GSC_IN_CHROMA_ORDER_CRCB); break; case DRM_FORMAT_NV21: + cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_2P); + break; case DRM_FORMAT_NV61: - cfg |= (GSC_IN_CHROMA_ORDER_CRCB | - GSC_IN_YUV420_2P); + cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV422_2P); break; case DRM_FORMAT_YUV422: cfg |= GSC_IN_YUV422_3P; break; case DRM_FORMAT_YUV420: + cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_3P); + break; case DRM_FORMAT_YVU420: - cfg |= GSC_IN_YUV420_3P; + cfg |= (GSC_IN_CHROMA_ORDER_CRCB | GSC_IN_YUV420_3P); break; case DRM_FORMAT_NV12: + cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV420_2P); + break; case DRM_FORMAT_NV16: - cfg |= (GSC_IN_CHROMA_ORDER_CBCR | - GSC_IN_YUV420_2P); + cfg |= (GSC_IN_CHROMA_ORDER_CBCR | GSC_IN_YUV422_2P); break; default: dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt); @@ -800,18 +804,25 @@ static int gsc_dst_set_fmt(struct device *dev, u32 fmt) GSC_OUT_CHROMA_ORDER_CRCB); break; case DRM_FORMAT_NV21: - case DRM_FORMAT_NV61: cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_2P); break; + case DRM_FORMAT_NV61: + cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV422_2P); + break; case DRM_FORMAT_YUV422: + cfg |= GSC_OUT_YUV422_3P; + break; case DRM_FORMAT_YUV420: + cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_3P); + break; case DRM_FORMAT_YVU420: - cfg |= GSC_OUT_YUV420_3P; + cfg |= (GSC_OUT_CHROMA_ORDER_CRCB | GSC_OUT_YUV420_3P); break; case DRM_FORMAT_NV12: + cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV420_2P); + break; case DRM_FORMAT_NV16: - cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | - GSC_OUT_YUV420_2P); + cfg |= (GSC_OUT_CHROMA_ORDER_CBCR | GSC_OUT_YUV422_2P); break; default: dev_err(ippdrv->dev, "invalid target yuv order 0x%x.\n", fmt); diff --git a/drivers/gpu/drm/exynos/regs-gsc.h b/drivers/gpu/drm/exynos/regs-gsc.h index 9ad592707aaf..ade10966d6af 100644 --- a/drivers/gpu/drm/exynos/regs-gsc.h +++ b/drivers/gpu/drm/exynos/regs-gsc.h @@ -138,6 +138,7 @@ #define GSC_OUT_YUV420_3P (3 << 4) #define GSC_OUT_YUV422_1P (4 << 4) #define GSC_OUT_YUV422_2P (5 << 4) +#define GSC_OUT_YUV422_3P (6 << 4) #define GSC_OUT_YUV444 (7 << 4) #define GSC_OUT_TILE_TYPE_MASK (1 << 2) #define GSC_OUT_TILE_C_16x8 (0 << 2) diff --git a/drivers/gpu/drm/gma500/psb_intel_drv.h b/drivers/gpu/drm/gma500/psb_intel_drv.h index 860dd2177ca1..283570080d47 100644 --- a/drivers/gpu/drm/gma500/psb_intel_drv.h +++ b/drivers/gpu/drm/gma500/psb_intel_drv.h @@ -252,7 +252,7 @@ extern int intelfb_remove(struct drm_device *dev, extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode); -extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, +extern enum drm_mode_status psb_intel_lvds_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode); extern int psb_intel_lvds_set_property(struct drm_connector *connector, struct drm_property *property, diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index 61e3a097a478..ccd1b8bf0fd5 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -343,7 +343,7 @@ static void psb_intel_lvds_restore(struct drm_connector *connector) } } -int psb_intel_lvds_mode_valid(struct drm_connector *connector, +enum drm_mode_status psb_intel_lvds_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct drm_psb_private *dev_priv = connector->dev->dev_private; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c index b8520aadbc0c..c993ae279ca9 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -484,7 +484,7 @@ static int dsi_ctrl_init_regmap(struct platform_device *pdev, } ctrl->hw.base = ptr; - pr_debug("[%s] map dsi_ctrl registers to %p\n", ctrl->name, + pr_debug("[%s] map dsi_ctrl registers to %pK\n", ctrl->name, ctrl->hw.base); ptr = msm_ioremap(pdev, "mmss_misc", ctrl->name); @@ -494,7 +494,7 @@ static int dsi_ctrl_init_regmap(struct platform_device *pdev, } ctrl->hw.mmss_misc_base = ptr; - pr_debug("[%s] map mmss_misc registers to %p\n", ctrl->name, + pr_debug("[%s] map mmss_misc registers to %pK\n", ctrl->name, ctrl->hw.mmss_misc_base); return rc; } diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c index 7a8dd567bb1f..1af0a55f840f 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1469,7 +1469,7 @@ static int dsi_panel_parse_dba_config(struct dsi_panel *panel, "qcom,bridge-name", &len); if (!panel->dba_config.bridge_name || len <= 0) { SDE_ERROR( - "%s:%d Unable to read bridge_name, data=%p,len=%d\n", + "%s:%d Unable to read bridge_name, data=%pK,len=%d\n", __func__, __LINE__, panel->dba_config.bridge_name, len); rc = -EINVAL; goto error; diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c index 1ccbbe7df573..f7a77336e691 100644 --- a/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi-staging/dsi_phy.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -93,7 +93,8 @@ static int dsi_phy_regmap_init(struct platform_device *pdev, phy->hw.base = ptr; - pr_debug("[%s] map dsi_phy registers to %p\n", phy->name, phy->hw.base); + pr_debug("[%s] map dsi_phy registers to %pK\n", + phy->name, phy->hw.base); return rc; } diff --git a/drivers/gpu/drm/msm/edp/edp.c b/drivers/gpu/drm/msm/edp/edp.c index 0940e84b2821..253e022ffb09 100644 --- a/drivers/gpu/drm/msm/edp/edp.c +++ b/drivers/gpu/drm/msm/edp/edp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2015, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -54,7 +54,7 @@ static struct msm_edp *edp_init(struct platform_device *pdev) ret = -ENOMEM; goto fail; } - DBG("eDP probed=%p", edp); + DBG("eDP probed=%pK", edp); edp->pdev = pdev; platform_set_drvdata(pdev, edp); diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 62e3047e3f31..63a1de59c3a5 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -2,7 +2,7 @@ * Copyright (C) 2013 Red Hat * Author: Rob Clark * - * Copyright (c) 2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by @@ -99,7 +99,8 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, } if (reglog) - printk(KERN_DEBUG "IO:region %s %p %08lx\n", dbgname, ptr, size); + pr_debug("IO:region %s %pK %08lx\n", + dbgname, ptr, size); return ptr; } @@ -107,7 +108,7 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, void msm_writel(u32 data, void __iomem *addr) { if (reglog) - printk(KERN_DEBUG "IO:W %p %08x\n", addr, data); + pr_debug("IO:W %pK %08x\n", addr, data); writel(data, addr); } @@ -115,7 +116,7 @@ u32 msm_readl(const void __iomem *addr) { u32 val = readl(addr); if (reglog) - printk(KERN_ERR "IO:R %p %08x\n", addr, val); + pr_debug("IO:R %pK %08x\n", addr, val); return val; } @@ -598,7 +599,7 @@ static int msm_enable_vblank(struct drm_device *dev, unsigned int pipe) struct msm_kms *kms = priv->kms; if (!kms) return -ENXIO; - DBG("dev=%p, crtc=%u", dev, pipe); + DBG("dev=%pK crtc=%u", dev, pipe); return vblank_ctrl_queue_work(priv, pipe, true); } @@ -608,7 +609,7 @@ static void msm_disable_vblank(struct drm_device *dev, unsigned int pipe) struct msm_kms *kms = priv->kms; if (!kms) return; - DBG("dev=%p, crtc=%u", dev, pipe); + DBG("dev=%pK, crtc=%u", dev, pipe); vblank_ctrl_queue_work(priv, pipe, false); } diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c index dca4de382581..7b1a6246b268 100644 --- a/drivers/gpu/drm/msm/msm_fb.c +++ b/drivers/gpu/drm/msm/msm_fb.c @@ -43,7 +43,7 @@ static void msm_framebuffer_destroy(struct drm_framebuffer *fb) struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); int i, n = drm_format_num_planes(fb->pixel_format); - DBG("destroy: FB ID: %d (%p)", fb->base.id, fb); + DBG("destroy: FB ID: %d (%pK)", fb->base.id, fb); drm_framebuffer_cleanup(fb); @@ -178,7 +178,7 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, unsigned int hsub, vsub; bool is_modified = false; - DBG("create framebuffer: dev=%p, mode_cmd=%p (%dx%d@%4.4s)", + DBG("create framebuffer: dev=%pK, mode_cmd=%pK (%dx%d@%4.4s)", dev, mode_cmd, mode_cmd->width, mode_cmd->height, (char *)&mode_cmd->pixel_format); @@ -261,7 +261,7 @@ struct drm_framebuffer *msm_framebuffer_init(struct drm_device *dev, goto fail; } - DBG("create: FB ID: %d (%p)", fb->base.id, fb); + DBG("create: FB ID: %d (%pK)", fb->base.id, fb); return fb; diff --git a/drivers/gpu/drm/msm/msm_fbdev.c b/drivers/gpu/drm/msm/msm_fbdev.c index e49df634e3f2..14cdd10f29f9 100644 --- a/drivers/gpu/drm/msm/msm_fbdev.c +++ b/drivers/gpu/drm/msm/msm_fbdev.c @@ -146,7 +146,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, goto fail_unlock; } - DBG("fbi=%p, dev=%p", fbi, dev); + DBG("fbi=%pK, dev=%pK", fbi, dev); fbdev->fb = fb; helper->fb = fb; @@ -167,7 +167,7 @@ static int msm_fbdev_create(struct drm_fb_helper *helper, fbi->fix.smem_start = paddr; fbi->fix.smem_len = fbdev->bo->size; - DBG("par=%p, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); + DBG("par=%pK, %dx%d", fbi->par, fbi->var.xres, fbi->var.yres); DBG("allocated %dx%d fb", fbdev->fb->width, fbdev->fb->height); mutex_unlock(&dev->struct_mutex); diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 05ae5b7e4dc1..69bd4c53df65 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -290,7 +290,7 @@ int msm_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) pfn = page_to_pfn(pages[pgoff]); - VERB("Inserting %p pfn %lx, pa %lx", vmf->virtual_address, + VERB("Inserting %pK pfn %lx, pa %lx", vmf->virtual_address, pfn, pfn << PAGE_SHIFT); ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn); @@ -399,7 +399,7 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, msm_obj->domain[id].sgt, IOMMU_READ | IOMMU_NOEXEC); if (ret) { - DRM_ERROR("Unable to map phy buf=%p\n", + DRM_ERROR("Unable to map phy buf=%pK\n", (void *)pa); return ret; } @@ -414,7 +414,7 @@ int msm_gem_get_iova_locked(struct drm_gem_object *obj, int id, msm_obj->domain[id].iova = sg_dma_address(msm_obj->domain[id].sgt->sgl); } - DRM_DEBUG("iova=%p\n", + DRM_DEBUG("iova=%pK\n", (void *)msm_obj->domain[id].iova); } else { WARN_ONCE(1, "physical address being used\n"); @@ -599,7 +599,7 @@ void msm_gem_describe(struct drm_gem_object *obj, struct seq_file *m) uint64_t off = drm_vma_node_start(&obj->vma_node); WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %p %zu\n", + seq_printf(m, "%08x: %c(r=%u,w=%u) %2d (%2d) %08llx %pK %zu\n", msm_obj->flags, is_active(msm_obj) ? 'A' : 'I', msm_obj->read_timestamp, msm_obj->write_timestamp, obj->name, obj->refcount.refcount.counter, diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c index fd06bf826b2c..b3e5827719ba 100644 --- a/drivers/gpu/drm/msm/sde/sde_crtc.c +++ b/drivers/gpu/drm/msm/sde/sde_crtc.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1253,7 +1253,7 @@ struct drm_crtc *sde_crtc_init(struct drm_device *dev, sde_crtc_install_properties(crtc); - SDE_DEBUG("%s: successfully initialized crtc=%p\n", + SDE_DEBUG("%s: successfully initialized crtc=%pK\n", sde_crtc->name, crtc); return crtc; } diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c index 629ca373665c..1a5e0faf9e47 100644 --- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c +++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2016, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -133,7 +133,7 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev, u32 major, struct sde_mdss_cfg *cfg = NULL; if (!dev || !dev->dev) { - SDE_ERROR("dev=%p or dev->dev is NULL\n", dev); + SDE_ERROR("dev=%pK or dev->dev is NULL\n", dev); return NULL; } diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index cffdaad1de32..c013fc135a97 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2017, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1506,7 +1506,7 @@ u32 sde_plane_num_of_phy_pipe(struct drm_plane *plane) struct sde_plane *sde_plane = to_sde_plane(plane); if (!plane || !sde_plane) { - SDE_ERROR("plane=%p or sde_plane=%p is NULL\n", + SDE_ERROR("plane=%pK or sde_plane=%pK is NULL\n", plane, sde_plane); return 0; } diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 30f00748ed37..7fa9151be619 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -851,7 +851,7 @@ static int radeon_lvds_get_modes(struct drm_connector *connector) return ret; } -static int radeon_lvds_mode_valid(struct drm_connector *connector, +static enum drm_mode_status radeon_lvds_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct drm_encoder *encoder = radeon_best_single_encoder(connector); @@ -994,7 +994,7 @@ static int radeon_vga_get_modes(struct drm_connector *connector) return ret; } -static int radeon_vga_mode_valid(struct drm_connector *connector, +static enum drm_mode_status radeon_vga_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; @@ -1133,7 +1133,7 @@ static int radeon_tv_get_modes(struct drm_connector *connector) return 1; } -static int radeon_tv_mode_valid(struct drm_connector *connector, +static enum drm_mode_status radeon_tv_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { if ((mode->hdisplay > 1024) || (mode->vdisplay > 768)) @@ -1464,7 +1464,7 @@ static void radeon_dvi_force(struct drm_connector *connector) radeon_connector->use_digital = true; } -static int radeon_dvi_mode_valid(struct drm_connector *connector, +static enum drm_mode_status radeon_dvi_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; @@ -1761,7 +1761,7 @@ radeon_dp_detect(struct drm_connector *connector, bool force) return ret; } -static int radeon_dp_mode_valid(struct drm_connector *connector, +static enum drm_mode_status radeon_dp_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct drm_device *dev = connector->dev; diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 29bd801f5dad..0c648efd9a58 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -341,7 +341,7 @@ static int udl_fb_open(struct fb_info *info, int user) struct fb_deferred_io *fbdefio; - fbdefio = kmalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); + fbdefio = kzalloc(sizeof(struct fb_deferred_io), GFP_KERNEL); if (fbdefio) { fbdefio->delay = DL_DEFIO_WRITE_DELAY; diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 33dbfb2c4748..30bfeb1b2512 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -141,18 +141,13 @@ static void udl_free_urb_list(struct drm_device *dev) struct list_head *node; struct urb_node *unode; struct urb *urb; - int ret; unsigned long flags; DRM_DEBUG("Waiting for completes and freeing all render urbs\n"); /* keep waiting and freeing, until we've got 'em all */ while (count--) { - - /* Getting interrupted means a leak, but ok at shutdown*/ - ret = down_interruptible(&udl->urbs.limit_sem); - if (ret) - break; + down(&udl->urbs.limit_sem); spin_lock_irqsave(&udl->urbs.lock, flags); @@ -176,17 +171,22 @@ static void udl_free_urb_list(struct drm_device *dev) static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) { struct udl_device *udl = dev->dev_private; - int i = 0; struct urb *urb; struct urb_node *unode; char *buf; + size_t wanted_size = count * size; spin_lock_init(&udl->urbs.lock); +retry: udl->urbs.size = size; INIT_LIST_HEAD(&udl->urbs.list); - while (i < count) { + sema_init(&udl->urbs.limit_sem, 0); + udl->urbs.count = 0; + udl->urbs.available = 0; + + while (udl->urbs.count * size < wanted_size) { unode = kzalloc(sizeof(struct urb_node), GFP_KERNEL); if (!unode) break; @@ -202,11 +202,16 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) } unode->urb = urb; - buf = usb_alloc_coherent(udl->udev, MAX_TRANSFER, GFP_KERNEL, + buf = usb_alloc_coherent(udl->udev, size, GFP_KERNEL, &urb->transfer_dma); if (!buf) { kfree(unode); usb_free_urb(urb); + if (size > PAGE_SIZE) { + size /= 2; + udl_free_urb_list(dev); + goto retry; + } break; } @@ -217,16 +222,14 @@ static int udl_alloc_urb_list(struct drm_device *dev, int count, size_t size) list_add_tail(&unode->entry, &udl->urbs.list); - i++; + up(&udl->urbs.limit_sem); + udl->urbs.count++; + udl->urbs.available++; } - sema_init(&udl->urbs.limit_sem, i); - udl->urbs.count = i; - udl->urbs.available = i; - - DRM_DEBUG("allocated %d %d byte urbs\n", i, (int) size); + DRM_DEBUG("allocated %d %d byte urbs\n", udl->urbs.count, (int) size); - return i; + return udl->urbs.count; } struct urb *udl_get_urb(struct drm_device *dev) diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 2d86ac02b2cd..8463f83e037f 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -981,6 +981,14 @@ static int i2c_hid_probe(struct i2c_client *client, pm_runtime_set_active(&client->dev); pm_runtime_enable(&client->dev); + /* Make sure there is something at this address */ + ret = i2c_smbus_read_byte(client); + if (ret < 0) { + dev_dbg(&client->dev, "nothing at this address: %d\n", ret); + ret = -ENXIO; + goto err_pm; + } + ret = i2c_hid_fetch_hid_descriptor(ihid); if (ret < 0) goto err_pm; diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index f771c6afbab5..beab499d182c 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -587,7 +587,7 @@ static int ismt_access(struct i2c_adapter *adap, u16 addr, /* unmap the data buffer */ if (dma_size != 0) - dma_unmap_single(&adap->dev, dma_addr, dma_size, dma_direction); + dma_unmap_single(dev, dma_addr, dma_size, dma_direction); if (unlikely(!ret)) { dev_err(dev, "completion wait timed out\n"); diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c index 7c5245d9f99c..4cffd8fc5cae 100644 --- a/drivers/iio/frequency/ad9523.c +++ b/drivers/iio/frequency/ad9523.c @@ -507,7 +507,7 @@ static ssize_t ad9523_store(struct device *dev, return ret; if (!state) - return 0; + return len; mutex_lock(&indio_dev->mlock); switch ((u32)this_attr->address) { @@ -641,7 +641,7 @@ static int ad9523_read_raw(struct iio_dev *indio_dev, code = (AD9523_CLK_DIST_DIV_PHASE_REV(ret) * 3141592) / AD9523_CLK_DIST_DIV_REV(ret); *val = code / 1000000; - *val2 = (code % 1000000) * 10; + *val2 = code % 1000000; return IIO_VAL_INT_PLUS_MICRO; default: return -EINVAL; diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 74c30f4c557e..0c79b0626a6e 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -1466,7 +1466,8 @@ static int add_oui_reg_req(struct ib_mad_reg_req *mad_reg_req, mad_reg_req->oui, 3)) { method = &(*vendor_table)->vendor_class[ vclass]->method_table[i]; - BUG_ON(!*method); + if (!*method) + goto error3; goto check_in_use; } } @@ -1476,10 +1477,12 @@ static int add_oui_reg_req(struct ib_mad_reg_req *mad_reg_req, vclass]->oui[i])) { method = &(*vendor_table)->vendor_class[ vclass]->method_table[i]; - BUG_ON(*method); /* Allocate method table for this OUI */ - if ((ret = allocate_method_table(method))) - goto error3; + if (!*method) { + ret = allocate_method_table(method); + if (ret) + goto error3; + } memcpy((*vendor_table)->vendor_class[vclass]->oui[i], mad_reg_req->oui, 3); goto check_in_use; diff --git a/drivers/infiniband/core/ucma.c b/drivers/infiniband/core/ucma.c index 81dd84d0b68b..eaadd636c21b 100644 --- a/drivers/infiniband/core/ucma.c +++ b/drivers/infiniband/core/ucma.c @@ -180,7 +180,7 @@ static struct ucma_multicast* ucma_alloc_multicast(struct ucma_context *ctx) return NULL; mutex_lock(&mut); - mc->id = idr_alloc(&multicast_idr, mc, 0, 0, GFP_KERNEL); + mc->id = idr_alloc(&multicast_idr, NULL, 0, 0, GFP_KERNEL); mutex_unlock(&mut); if (mc->id < 0) goto error; @@ -1262,6 +1262,10 @@ static ssize_t ucma_process_join(struct ucma_file *file, goto err3; } + mutex_lock(&mut); + idr_replace(&multicast_idr, mc, mc->id); + mutex_unlock(&mut); + mutex_unlock(&file->mut); ucma_put_ctx(ctx); return 0; diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 3341d74c8c9b..3771e65bacab 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -1161,7 +1161,7 @@ config TOUCHSCREEN_HIMAX_CHIPSET HIMAX controllers are multi touch controllers which can report 10 touches at a time. - If unsure, say N. + If unsure, say N. source "drivers/input/touchscreen/hxchipset/Kconfig" diff --git a/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i b/drivers/input/touchscreen/hxchipset/HX83100_Amber_0901_030B.i deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_124.i b/drivers/input/touchscreen/hxchipset/HX_CRC_124.i deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_128.i b/drivers/input/touchscreen/hxchipset/HX_CRC_128.i deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_60.i b/drivers/input/touchscreen/hxchipset/HX_CRC_60.i deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/drivers/input/touchscreen/hxchipset/HX_CRC_64.i b/drivers/input/touchscreen/hxchipset/HX_CRC_64.i deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/drivers/input/touchscreen/hxchipset/Kconfig b/drivers/input/touchscreen/hxchipset/Kconfig index ebf3aa478af5..3dc5a026c851 100644 --- a/drivers/input/touchscreen/hxchipset/Kconfig +++ b/drivers/input/touchscreen/hxchipset/Kconfig @@ -3,19 +3,44 @@ # config TOUCHSCREEN_HIMAX_I2C - tristate "HIMAX chipset i2c touchscreen" - depends on TOUCHSCREEN_HIMAX_CHIPSET - help + tristate "HIMAX chipset i2c touchscreen" + depends on TOUCHSCREEN_HIMAX_CHIPSET + help + Say Y here to enable support for HIMAX CHIPSET over I2C based touchscreens. + If unsure, say N. + + To compile this driver as a module, This enables support for HIMAX CHIPSET over I2C based touchscreens. config TOUCHSCREEN_HIMAX_DEBUG - tristate "HIMAX debug function" - depends on TOUCHSCREEN_HIMAX_I2C - help + tristate "HIMAX debug function" + depends on TOUCHSCREEN_HIMAX_I2C + help + Say Y here to enable support for HIMAX debug function. + + If unsure, say N. + + To compile this driver as a module, This enables support for HIMAX debug function. +config TOUCHSCREEN_HIMAX_ITO_TEST + tristate "HIMAX driver test over Dragon Board" + depends on TOUCHSCREEN_HIMAX_I2C + help + Say Y here to enable support for HIMAX driver test over Dragon Board. + + If unsure, say N. + + To compile this driver as a module, + this enables support for HIMAX driver test over Dragon Board. + config HMX_DB tristate "HIMAX driver test over Dragon Board" depends on TOUCHSCREEN_HIMAX_I2C help - This enables support for HIMAX driver test over Dragon Board. + Say Y here to enable support for HIMAX driver test over Dragon Board. + + If unsure, say N. + + To compile this driver as a module, + this enables support for HIMAX driver test over Dragon Board. diff --git a/drivers/input/touchscreen/hxchipset/Makefile b/drivers/input/touchscreen/hxchipset/Makefile index 509d4913bc39..522907a48956 100644 --- a/drivers/input/touchscreen/hxchipset/Makefile +++ b/drivers/input/touchscreen/hxchipset/Makefile @@ -1,3 +1,4 @@ # Makefile for the Himax touchscreen drivers. obj-$(CONFIG_TOUCHSCREEN_HIMAX_I2C) += himax_platform.o himax_ic.o himax_common.o himax_debug.o +obj-$(CONFIG_TOUCHSCREEN_HIMAX_ITO_TEST) += himax_ito_test.o \ No newline at end of file diff --git a/drivers/input/touchscreen/hxchipset/himax_common.c b/drivers/input/touchscreen/hxchipset/himax_common.c index 417b0c08e361..d4bc5beb0203 100644 --- a/drivers/input/touchscreen/hxchipset/himax_common.c +++ b/drivers/input/touchscreen/hxchipset/himax_common.c @@ -1,4 +1,4 @@ -/* Himax Android Driver Sample Code for Himax chipset + /* Himax Android Driver Sample Code for Himax chipset * * Copyright (C) 2015 Himax Corporation. * @@ -21,107 +21,32 @@ #define FRAME_COUNT 5 #if defined(HX_AUTO_UPDATE_FW) - static unsigned char i_CTPM_FW[]= - { - #include "HX83100_Amber_0901_030B.i" - }; + char *i_CTPM_firmware_name = "HX83100_Amber_0B01_030E.bin"; + const struct firmware *i_CTPM_FW = NULL; #endif -#ifdef HX_ESD_WORKAROUND - extern void HX_report_ESD_event(void); - unsigned char ESD_00_counter = 0; - unsigned char ESD_00_Flag = 0; -#endif - -//static int tpd_keys_local[HX_KEY_MAX_COUNT] = HX_KEY_ARRAY; // for Virtual key array +/*static int tpd_keys_local[HX_KEY_MAX_COUNT] = HX_KEY_ARRAY; +// for Virtual key array */ struct himax_ts_data *private_ts; -struct himax_ic_data* ic_data; - -static int HX_TOUCH_INFO_POINT_CNT; - -#ifdef HX_AUTO_UPDATE_FW -extern unsigned long FW_VER_MAJ_FLASH_ADDR; -extern unsigned long FW_VER_MIN_FLASH_ADDR; -extern unsigned long CFG_VER_MAJ_FLASH_ADDR; -extern unsigned long CFG_VER_MIN_FLASH_ADDR; -#endif -extern unsigned long FW_VER_MAJ_FLASH_LENG; -extern unsigned long FW_VER_MIN_FLASH_LENG; -extern unsigned long CFG_VER_MAJ_FLASH_LENG; -extern unsigned long CFG_VER_MIN_FLASH_LENG; -extern unsigned char IC_TYPE; -extern unsigned char IC_CHECKSUM; - -#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) -extern int himax_touch_proc_init(void); -extern void himax_touch_proc_deinit(void); -//PROC-START -#ifdef HX_TP_PROC_FLASH_DUMP -extern void himax_ts_flash_func(void); -extern void setFlashBuffer(void); -extern bool getFlashDumpGoing(void); -extern uint8_t getSysOperation(void); -extern void setSysOperation(uint8_t operation); -#endif - -#ifdef HX_TP_PROC_HITOUCH -extern bool hitouch_is_connect; -#endif - -#ifdef HX_TP_PROC_DIAG - extern int touch_monitor_stop_flag; - extern int touch_monitor_stop_limit; - extern void himax_ts_diag_func(void); - extern int16_t *getMutualBuffer(void); - extern int16_t *getMutualNewBuffer(void); - extern int16_t *getMutualOldBuffer(void); - extern int16_t *getSelfBuffer(void); - extern uint8_t getXChannel(void); - extern uint8_t getYChannel(void); - extern uint8_t getDiagCommand(void); - extern void setXChannel(uint8_t x); - extern void setYChannel(uint8_t y); - extern void setMutualBuffer(void); - extern void setMutualNewBuffer(void); - extern void setMutualOldBuffer(void); - extern uint8_t coordinate_dump_enable; - extern struct file *coordinate_fn; - extern uint8_t diag_coor[128]; -#ifdef HX_TP_PROC_2T2R - extern int16_t *getMutualBuffer_2(void); - extern uint8_t getXChannel_2(void); - extern uint8_t getYChannel_2(void); - extern void setXChannel_2(uint8_t x); - extern void setYChannel_2(uint8_t y); - extern void setMutualBuffer_2(void); -#endif -#endif -//PROC-END -#endif - -extern int himax_parse_dt(struct himax_ts_data *ts, - struct himax_i2c_platform_data *pdata); -extern int himax_ts_pinctrl_init(struct himax_ts_data *ts); - -static uint8_t vk_press; -static uint8_t AA_press; -static uint8_t EN_NoiseFilter; -static uint8_t Last_EN_NoiseFilter; -static int hx_point_num; // for himax_ts_work_func use -static int p_point_num = 0xFFFF; -static int tpd_key; -static int tpd_key_old; -static int probe_fail_flag; -static bool config_load; +struct himax_ic_data *ic_data; + +static int HX_TOUCH_INFO_POINT_CNT; + +static uint8_t vk_press = 0x00; +static uint8_t AA_press = 0x00; +static uint8_t EN_NoiseFilter = 0x00; +static int hx_point_num; /*for himax_ts_work_func use*/ +static int p_point_num = 0xFFFF; +static int tpd_key = 0x00; +static int tpd_key_old = 0x00; +static int probe_fail_flag; +static bool config_load; static struct himax_config *config_selected; -//static int iref_number = 11; -//static bool iref_found = false; +/*static int iref_number = 11;*/ +/*static bool iref_found = false;*/ -#ifdef HX_USB_DETECT2 -extern bool USB_Flag; -#endif #if defined(CONFIG_FB) int fb_notifier_callback(struct notifier_block *self, @@ -134,6 +59,7 @@ static void himax_ts_late_resume(struct early_suspend *h); int himax_input_register(struct himax_ts_data *ts) { int ret; + ts->input_dev = input_allocate_device(); if (ts->input_dev == NULL) { ret = -ENOMEM; @@ -175,25 +101,36 @@ int himax_input_register(struct himax_ts_data *ts) set_bit(INPUT_PROP_DIRECT, ts->input_dev->propbit); if (ts->protocol_type == PROTOCOL_TYPE_A) { - //ts->input_dev->mtsize = ts->nFinger_support; + /*ts->input_dev->mtsize = ts->nFinger_support;*/ input_set_abs_params(ts->input_dev, ABS_MT_TRACKING_ID, 0, 3, 0, 0); } else {/* PROTOCOL_TYPE_B */ set_bit(MT_TOOL_FINGER, ts->input_dev->keybit); - input_mt_init_slots(ts->input_dev, ts->nFinger_support,0); + input_mt_init_slots(ts->input_dev, ts->nFinger_support, 0); } I("input_set_abs_params: mix_x %d, max_x %d, min_y %d, max_y %d\n", - ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); - - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X,ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0); - input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y,ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0); - input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0); - input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE,ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, ts->pdata->abs_pressure_fuzz, 0); - input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR,ts->pdata->abs_width_min, ts->pdata->abs_width_max, ts->pdata->abs_pressure_fuzz, 0); - -// input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, ((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0); -// input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, (BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0); + ts->pdata->abs_x_min, ts->pdata->abs_x_max, + ts->pdata->abs_y_min, ts->pdata->abs_y_max); + + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, + ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_x_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, + ts->pdata->abs_y_min, ts->pdata->abs_y_max, ts->pdata->abs_y_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, + ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, + ts->pdata->abs_pressure_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_PRESSURE, + ts->pdata->abs_pressure_min, ts->pdata->abs_pressure_max, + ts->pdata->abs_pressure_fuzz, 0); + input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, + ts->pdata->abs_width_min, ts->pdata->abs_width_max, + ts->pdata->abs_pressure_fuzz, 0); + +/*input_set_abs_params(ts->input_dev, ABS_MT_AMPLITUDE, 0, +((ts->pdata->abs_pressure_max << 16) | ts->pdata->abs_width_max), 0, 0);*/ +/*input_set_abs_params(ts->input_dev, ABS_MT_POSITION, 0, +(BIT(31) | (ts->pdata->abs_x_max << 16) | ts->pdata->abs_y_max), 0, 0);*/ return input_register_device(ts->input_dev); } @@ -201,87 +138,103 @@ int himax_input_register(struct himax_ts_data *ts) static void calcDataSize(uint8_t finger_num) { struct himax_ts_data *ts_data = private_ts; + ts_data->coord_data_size = 4 * finger_num; - ts_data->area_data_size = ((finger_num / 4) + (finger_num % 4 ? 1 : 0)) * 4; - ts_data->raw_data_frame_size = 128 - ts_data->coord_data_size - ts_data->area_data_size - 4 - 4 - 1; - ts_data->raw_data_nframes = ((uint32_t)ts_data->x_channel * ts_data->y_channel + - ts_data->x_channel + ts_data->y_channel) / ts_data->raw_data_frame_size + - (((uint32_t)ts_data->x_channel * ts_data->y_channel + - ts_data->x_channel + ts_data->y_channel) % ts_data->raw_data_frame_size)? 1 : 0; - I("%s: coord_data_size: %d, area_data_size:%d, raw_data_frame_size:%d, raw_data_nframes:%d", __func__, ts_data->coord_data_size, ts_data->area_data_size, ts_data->raw_data_frame_size, ts_data->raw_data_nframes); + ts_data->area_data_size = ((finger_num / 4) + + (finger_num % 4 ? 1 : 0)) * 4; + ts_data->raw_data_frame_size = 128 - + ts_data->coord_data_size - + ts_data->area_data_size - 4 - 4 - 1; + + ts_data->raw_data_nframes = + ((uint32_t)ts_data->x_channel * + ts_data->y_channel + ts_data->x_channel + ts_data->y_channel) / + ts_data->raw_data_frame_size + (((uint32_t)ts_data->x_channel * + ts_data->y_channel + ts_data->x_channel + ts_data->y_channel) % + ts_data->raw_data_frame_size) ? 1 : 0; + + I("%s: coord_data_size: %d, area_data_size:%d", + __func__, ts_data->coord_data_size, ts_data->area_data_size); + I("raw_data_frame_size:%d, raw_data_nframes:%d", + ts_data->raw_data_frame_size, ts_data->raw_data_nframes); } static void calculate_point_number(void) { - HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4 ; + HX_TOUCH_INFO_POINT_CNT = ic_data->HX_MAX_PT * 4; - if ( (ic_data->HX_MAX_PT % 4) == 0) - HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4 ; + if ((ic_data->HX_MAX_PT % 4) == 0) + HX_TOUCH_INFO_POINT_CNT += (ic_data->HX_MAX_PT / 4) * 4; else - HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) +1) * 4 ; + HX_TOUCH_INFO_POINT_CNT += ((ic_data->HX_MAX_PT / 4) + 1) * 4; } -#if 0 +/*#if 0*/ +#ifdef HX_EN_CHECK_PATCH static int himax_read_Sensor_ID(struct i2c_client *client) -{ - uint8_t val_high[1], val_low[1], ID0=0, ID1=0; +{ + uint8_t val_high[1], val_low[1], ID0 = 0, ID1 = 0; char data[3]; const int normalRetry = 10; int sensor_id; - - data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High*/ - i2c_himax_master_write(client, &data[0],3,normalRetry); - usleep_range(1000, 2000); - //read id pin high + data[0] = 0x56; data[1] = 0x02; + data[2] = 0x02;/*ID pin PULL High*/ + i2c_himax_master_write(client, &data[0], 3, normalRetry); + usleep(1000); + + /*read id pin high*/ i2c_himax_read(client, 0x57, val_high, 1, normalRetry); - data[0] = 0x56; data[1] = 0x01; data[2] = 0x01;/*ID pin PULL Low*/ - i2c_himax_master_write(client, &data[0],3,normalRetry); - usleep_range(1000, 2000); + data[0] = 0x56; data[1] = 0x01; + data[2] = 0x01;/*ID pin PULL Low*/ + i2c_himax_master_write(client, &data[0], 3, normalRetry); + usleep(1000); - //read id pin low + /*read id pin low*/ i2c_himax_read(client, 0x57, val_low, 1, normalRetry); - if((val_high[0] & 0x01) ==0) - ID0=0x02;/*GND*/ - else if((val_low[0] & 0x01) ==0) - ID0=0x01;/*Floating*/ + if ((val_high[0] & 0x01) == 0) + ID0 = 0x02;/*GND*/ + else if ((val_low[0] & 0x01) == 0) + ID0 = 0x01;/*Floating*/ else - ID0=0x04;/*VCC*/ - - if((val_high[0] & 0x02) ==0) - ID1=0x02;/*GND*/ - else if((val_low[0] & 0x02) ==0) - ID1=0x01;/*Floating*/ - else - ID1=0x04;/*VCC*/ - if((ID0==0x04)&&(ID1!=0x04)) - { - data[0] = 0x56; data[1] = 0x02; data[2] = 0x01;/*ID pin PULL High,Low*/ - i2c_himax_master_write(client, &data[0],3,normalRetry); - usleep_range(1000, 2000); - - } - else if((ID0!=0x04)&&(ID1==0x04)) - { - data[0] = 0x56; data[1] = 0x01; data[2] = 0x02;/*ID pin PULL Low,High*/ - i2c_himax_master_write(client, &data[0],3,normalRetry); - usleep_range(1000, 2000); + ID0 = 0x04;/*VCC*/ - } - else if((ID0==0x04)&&(ID1==0x04)) - { - data[0] = 0x56; data[1] = 0x02; data[2] = 0x02;/*ID pin PULL High,High*/ - i2c_himax_master_write(client, &data[0],3,normalRetry); - usleep_range(1000, 2000); + if ((val_high[0] & 0x02) == 0) + ID1 = 0x02;/*GND*/ + else if ((val_low[0] & 0x02) == 0) + ID1 = 0x01;/*Floating*/ + else + ID1 = 0x04;/*VCC*/ + if ((ID0 == 0x04) && (ID1 != 0x04)) { + data[0] = 0x56; data[1] = 0x02; + data[2] = 0x01;/*ID pin PULL High,Low*/ + i2c_himax_master_write(client, + &data[0], 3, normalRetry); + usleep(1000); + + } else if ((ID0 != 0x04) && (ID1 == 0x04)) { + data[0] = 0x56; data[1] = 0x01; + data[2] = 0x02;/*ID pin PULL Low,High*/ + i2c_himax_master_write(client, + &data[0], 3, normalRetry); + usleep(1000); + + } else if ((ID0 == 0x04) && (ID1 == 0x04)) { + data[0] = 0x56; data[1] = 0x02; + data[2] = 0x02;/*ID pin PULL High,High*/ + i2c_himax_master_write(client, + &data[0], 3, normalRetry); + usleep(1000); - } - sensor_id=(ID1<<4)|ID0; + } + sensor_id = (ID1<<4)|ID0; data[0] = 0xE4; data[1] = sensor_id; - i2c_himax_master_write(client, &data[0],2,normalRetry);/*Write to MCU*/ - usleep_range(1000, 2000); + i2c_himax_master_write(client, + &data[0], 2, normalRetry);/*Write to MCU*/ + usleep(1000); return sensor_id; @@ -290,125 +243,173 @@ static int himax_read_Sensor_ID(struct i2c_client *client) static void himax_power_on_initCMD(struct i2c_client *client) { I("%s:\n", __func__); - himax_touch_information(client); - - //himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM + /*himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM */ } #ifdef HX_AUTO_UPDATE_FW static int i_update_FW(void) { int upgrade_times = 0; - unsigned char* ImageBuffer = i_CTPM_FW; - int fullFileLength = sizeof(i_CTPM_FW); + int fullFileLength = 0; int i_FW_VER = 0, i_CFG_VER = 0; - uint8_t ret = -1, result = 0; -// uint8_t tmp_addr[4]; -// uint8_t tmp_data[4]; + int ret = -1, result = 0; + /*uint8_t tmp_addr[4];*/ + /*uint8_t tmp_data[4];*/ int CRC_from_FW = 0; int CRC_Check_result = 0; - i_FW_VER = i_CTPM_FW[FW_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[FW_VER_MIN_FLASH_ADDR]; - i_CFG_VER = i_CTPM_FW[CFG_VER_MAJ_FLASH_ADDR]<<8 |i_CTPM_FW[CFG_VER_MIN_FLASH_ADDR]; + ret = himax_load_CRC_bin_file(private_ts->client); + if (ret < 0) { + E("%s: himax_load_CRC_bin_file fail Error Code=%d.\n", + __func__, ret); + ret = -1; + return ret; + } + I("file name = %s\n", i_CTPM_firmware_name); + ret = request_firmware(&i_CTPM_FW, + i_CTPM_firmware_name, private_ts->dev); + if (ret < 0) { + E("%s,fail in line%d error code=%d\n", + __func__, __LINE__, ret); + ret = -2; + return ret; + } + + if (i_CTPM_FW == NULL) { + I("%s: i_CTPM_FW = NULL\n", __func__); + ret = -3; + return ret; + } + fullFileLength = i_CTPM_FW->size; - I("%s: i_fullFileLength = %d\n", __func__,fullFileLength); + i_FW_VER = i_CTPM_FW->data[FW_VER_MAJ_FLASH_ADDR]<<8 + | i_CTPM_FW->data[FW_VER_MIN_FLASH_ADDR]; + i_CFG_VER = i_CTPM_FW->data[CFG_VER_MAJ_FLASH_ADDR]<<8 + | i_CTPM_FW->data[CFG_VER_MIN_FLASH_ADDR]; + + I("%s: i_fullFileLength = %d\n", __func__, fullFileLength); himax_sense_off(private_ts->client); msleep(500); - CRC_from_FW = himax_check_CRC(private_ts->client,fw_image_64k); - CRC_Check_result = Calculate_CRC_with_AP(ImageBuffer, CRC_from_FW,fw_image_64k); - I("%s: Check sum result = %d\n", __func__,CRC_Check_result); - //I("%s: ic_data->vendor_fw_ver = %X, i_FW_VER = %X,\n", __func__,ic_data->vendor_fw_ver, i_FW_VER); - //I("%s: ic_data->vendor_config_ver = %X, i_CFG_VER = %X,\n", __func__,ic_data->vendor_config_ver, i_CFG_VER); - - if ((CRC_Check_result == 0)|| ( ic_data->vendor_fw_ver < i_FW_VER ) || ( ic_data->vendor_config_ver < i_CFG_VER )) - { - himax_int_enable(private_ts->client->irq,0); + CRC_from_FW = himax_check_CRC(private_ts->client, fw_image_64k); + CRC_Check_result = + Calculate_CRC_with_AP((unsigned char *)i_CTPM_FW->data, + CRC_from_FW, fw_image_64k); + I("%s: Check sum result = %d\n", __func__, CRC_Check_result); + /*I("%s: ic_data->vendor_fw_ver = %X, i_FW_VER = %X,\n", + __func__, ic_data->vendor_fw_ver, i_FW_VER);*/ + /*I("%s: ic_data->vendor_config_ver = %X, i_CFG_VER = %X,\n", + __func__, ic_data->vendor_config_ver, i_CFG_VER);*/ + + if ((CRC_Check_result == 0) || + (ic_data->vendor_fw_ver < i_FW_VER) || + (ic_data->vendor_config_ver < i_CFG_VER)) { + himax_int_enable(private_ts->client->irq, 0); update_retry: - if(fullFileLength == FW_SIZE_60k){ - ret = fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,ImageBuffer,fullFileLength,false); - }else if (fullFileLength == FW_SIZE_64k){ - ret = fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,ImageBuffer,fullFileLength,false); - }else if (fullFileLength == FW_SIZE_124k){ - ret = fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,ImageBuffer,fullFileLength,false); - }else if (fullFileLength == FW_SIZE_128k){ - ret = fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,ImageBuffer,fullFileLength,false); - } - if(ret == 0){ - upgrade_times++; - E("%s: TP upgrade error, upgrade_times = %d\n", __func__, upgrade_times); - if(upgrade_times < 3) - goto update_retry; - else - { - himax_sense_on(private_ts->client, 0x01); - msleep(120); -#ifdef HX_ESD_WORKAROUND - HX_ESD_RESET_ACTIVATE = 1; -#endif - result = -1;//upgrade fail - } - } - else if(ret == 1){ -/* - // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver) - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; - himax_register_write(private_ts->client, tmp_addr, 1, tmp_data); - - // 2. Write driver initial code condition - // write value from AHB I2C : 0x8001_C603 = 0x000000FF - tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xC6; tmp_addr[0] = 0x03; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xFF; - himax_register_write(private_ts->client, tmp_addr, 1, tmp_data); - - // 1. Set DDREG_Req = 0 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver) - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - himax_register_write(private_ts->client, tmp_addr, 1, tmp_data); -*/ + if (fullFileLength == FW_SIZE_60k) { + ret = fts_ctpm_fw_upgrade_with_sys_fs_60k + (private_ts->client, + (unsigned char *)i_CTPM_FW->data, + fullFileLength, false); + } else if (fullFileLength == FW_SIZE_64k) { + ret = fts_ctpm_fw_upgrade_with_sys_fs_64k + (private_ts->client, + (unsigned char *)i_CTPM_FW->data, + fullFileLength, false); + } else if (fullFileLength == FW_SIZE_124k) { + ret = fts_ctpm_fw_upgrade_with_sys_fs_124k + (private_ts->client, + (unsigned char *)i_CTPM_FW->data, + fullFileLength, false); + } else if (fullFileLength == FW_SIZE_128k) { + ret = fts_ctpm_fw_upgrade_with_sys_fs_128k + (private_ts->client, + (unsigned char *)i_CTPM_FW->data, + fullFileLength, false); + } + if (ret == 0) { + upgrade_times++; + E("%s: TP upgrade error, upgrade_times = %d\n", + __func__, upgrade_times); + if (upgrade_times < 3) + goto update_retry; + else { himax_sense_on(private_ts->client, 0x01); msleep(120); #ifdef HX_ESD_WORKAROUND HX_ESD_RESET_ACTIVATE = 1; #endif - - ic_data->vendor_fw_ver = i_FW_VER; - ic_data->vendor_config_ver = i_CFG_VER; - result = 1;//upgrade success - I("%s: TP upgrade OK\n", __func__); + result = -1;/*upgrade fail*/ } - - himax_int_enable(private_ts->client->irq,1); - return result; - } - else - { + } else if (ret == 1) { + /* + // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) + (Lock register R/W from driver) + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x01; + himax_register_write(private_ts->client, + tmp_addr, 1, tmp_data); + + // 2. Write driver initial code condition + //write value from AHB I2C:0x8001_C603 = 0x000000FF + tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; + tmp_addr[1] = 0xC6; tmp_addr[0] = 0x03; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0xFF; + himax_register_write(private_ts->client, + tmp_addr, 1, tmp_data); + + // 1. Set DDREG_Req = 0(0x9000_0020 = 0x0000_0001) + (Lock register R/W from driver) + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_register_write(private_ts->client, + tmp_addr, 1, tmp_data); + */ himax_sense_on(private_ts->client, 0x01); - return 0;//NO upgrade + msleep(120); +#ifdef HX_ESD_WORKAROUND + HX_ESD_RESET_ACTIVATE = 1; +#endif + + ic_data->vendor_fw_ver = i_FW_VER; + ic_data->vendor_config_ver = i_CFG_VER; + result = 1;/*upgrade success*/ + I("%s: TP upgrade OK\n", __func__); } + + himax_int_enable(private_ts->client->irq, 1); + return result; + + } else { + himax_sense_on(private_ts->client, 0x01); + return 0;/*NO upgrade*/ + } } -#endif +#endif #ifdef HX_RST_PIN_FUNC -void himax_HW_reset(uint8_t loadconfig,uint8_t int_off) +void himax_HW_reset(uint8_t loadconfig, uint8_t int_off) { struct himax_ts_data *ts = private_ts; int ret = 0; return; if (ts->rst_gpio) { - if(int_off) - { - if (ts->use_irq) - himax_int_enable(private_ts->client->irq,0); - else { - hrtimer_cancel(&ts->timer); - ret = cancel_work_sync(&ts->work); - } + if (int_off) { + if (ts->use_irq) + himax_int_enable(private_ts->client->irq, 0); + else { + hrtimer_cancel(&ts->timer); + ret = cancel_work_sync(&ts->work); } + } I("%s: Now reset the Touch chip.\n", __func__); @@ -417,51 +418,51 @@ void himax_HW_reset(uint8_t loadconfig,uint8_t int_off) himax_rst_gpio_set(ts->rst_gpio, 1); msleep(20); - if(loadconfig) - himax_loadSensorConfig(private_ts->client,private_ts->pdata); + if (loadconfig) + himax_loadSensorConfig(private_ts->client, + private_ts->pdata); - if(int_off) - { - if (ts->use_irq) - himax_int_enable(private_ts->client->irq,1); - else - hrtimer_start(&ts->timer, ktime_set(1, 0), HRTIMER_MODE_REL); - } + if (int_off) { + if (ts->use_irq) + himax_int_enable(private_ts->client->irq, 1); + else + hrtimer_start(&ts->timer, + ktime_set(1, 0), HRTIMER_MODE_REL); + } } } #endif -int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata) +int himax_loadSensorConfig(struct i2c_client *client, +struct himax_i2c_platform_data *pdata) { + int err = -1; if (!client) { E("%s: Necessary parameters client are null!\n", __func__); - return -EINVAL; + return err; } - - if(config_load == false) - { - config_selected = kzalloc(sizeof(*config_selected), GFP_KERNEL); - if (config_selected == NULL) { - E("%s: alloc config_selected fail!\n", __func__); - return -ENOMEM; - } + if (config_load == false) { + config_selected = kzalloc(sizeof(*config_selected), GFP_KERNEL); + if (config_selected == NULL) { + E("%s: alloc config_selected fail!\n", __func__); + return err; } + } + himax_power_on_initCMD(client); - himax_power_on_initCMD(client); - - himax_int_enable(client->irq,0); - himax_read_FW_ver(client); + himax_int_enable(client->irq, 0); + himax_read_FW_ver(client); #ifdef HX_RST_PIN_FUNC - himax_HW_reset(true,false); + himax_HW_reset(true, false); #endif - himax_int_enable(client->irq,1); - I("FW_VER : %X \n",ic_data->vendor_fw_ver); + himax_int_enable(client->irq, 1); + I("FW_VER : %X\n", ic_data->vendor_fw_ver); - ic_data->vendor_sensor_id=0x2602; - I("sensor_id=%x.\n",ic_data->vendor_sensor_id); + ic_data->vendor_sensor_id = 0x2602; + I("sensor_id=%x.\n", ic_data->vendor_sensor_id); - himax_sense_on(private_ts->client, 0x01);//1=Flash, 0=SRAM + himax_sense_on(private_ts->client, 0x01);/*1=Flash, 0=SRAM*/ msleep(120); #ifdef HX_ESD_WORKAROUND HX_ESD_RESET_ACTIVATE = 1; @@ -474,47 +475,49 @@ int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_ #ifdef HX_ESD_WORKAROUND void ESD_HW_REST(void) { - I("START_Himax TP: ESD - Reset\n"); - + I("START_Himax TP: ESD - Reset\n"); + HX_report_ESD_event(); ESD_00_counter = 0; ESD_00_Flag = 0; - /*************************************/ - if (private_ts->protocol_type == PROTOCOL_TYPE_A) + /*************************************/ + if (private_ts->protocol_type == PROTOCOL_TYPE_A) input_mt_sync(private_ts->input_dev); - input_report_key(private_ts->input_dev, BTN_TOUCH, 0); - input_sync(private_ts->input_dev); - /*************************************/ + input_report_key(private_ts->input_dev, BTN_TOUCH, 0); + input_sync(private_ts->input_dev); + /*************************************/ I("END_Himax TP: ESD - Reset\n"); } #endif #ifdef HX_HIGH_SENSE -void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable) +void himax_set_HSEN_func(struct i2c_client *client, uint8_t HSEN_enable) { uint8_t tmp_data[4]; - if(HSEN_enable) - { + if (HSEN_enable) { I(" %s in", __func__); - HSEN_bit_retry: - himax_set_HSEN_enable(client,HSEN_enable); +HSEN_bit_retry: + himax_set_HSEN_enable(client, HSEN_enable); msleep(20); - himax_get_HSEN_enable(client,tmp_data); - I("%s: Read HSEN bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ - ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); - if(tmp_data[0]!= 0x01) - { - I("%s: retry HSEN bit write data[0]=%x \n",__func__,tmp_data[0]); - goto HSEN_bit_retry; - } + himax_get_HSEN_enable(client, tmp_data); + I("%s: Read HSEN bit data[0]=%x data[1]=%x", + __func__, tmp_data[0], tmp_data[1]); + I("data[2]=%x data[3]=%x\n", + tmp_data[2], tmp_data[3]); + + if (tmp_data[0] != 0x01) { + I("%s: retry HSEN bit write data[0]=%x\n", + __func__, tmp_data[0]); + goto HSEN_bit_retry; + } } } static void himax_HSEN_func(struct work_struct *work) { - struct himax_ts_data *ts = container_of(work, struct himax_ts_data, - hsen_work.work); + struct himax_ts_data *ts = + container_of(work, struct himax_ts_data, hsen_work.work); himax_set_HSEN_func(ts->client, ts->HSEN_enable); } @@ -525,9 +528,10 @@ static void himax_HSEN_func(struct work_struct *work) #ifdef HX_GESTURE_TRACK static void gest_pt_log_coordinate(int rx, int tx) { - //driver report x y with range 0 - 255 , we scale it up to x/y pixel - gest_pt_x[gest_pt_cnt] = rx*(ic_data->HX_X_RES)/255; - gest_pt_y[gest_pt_cnt] = tx*(ic_data->HX_Y_RES)/255; + /*driver report x y with range 0 - 255*/ + /* And we scale it up to x/y coordinates*/ + gest_pt_x[gest_pt_cnt] = rx * (ic_data->HX_X_RES) / 255; + gest_pt_y[gest_pt_cnt] = tx * (ic_data->HX_Y_RES) / 255; } #endif static int himax_parse_wake_event(struct himax_ts_data *ts) @@ -535,145 +539,143 @@ static int himax_parse_wake_event(struct himax_ts_data *ts) uint8_t buf[64]; unsigned char check_sum_cal = 0; #ifdef HX_GESTURE_TRACK - int tmp_max_x=0x00,tmp_min_x=0xFFFF,tmp_max_y=0x00,tmp_min_y=0xFFFF; + int tmp_max_x = 0x00, tmp_min_x = 0xFFFF, + tmp_max_y = 0x00, tmp_min_y = 0xFFFF; int gest_len; #endif - int i=0, check_FC = 0, gesture_flag = 0; + int i = 0, check_FC = 0, gesture_flag = 0; himax_burst_enable(ts->client, 0); - himax_read_event_stack(ts->client,buf,56); + himax_read_event_stack(ts->client, buf, 56); - for(i=0;igest_pt_x[i]) - tmp_min_x=gest_pt_x[i]; - if(tmp_max_ygest_pt_y[i]) - tmp_min_y=gest_pt_y[i]; - } - I("gest_point x_min= %d, x_max= %d, y_min= %d, y_max= %d\n",tmp_min_x,tmp_max_x,tmp_min_y,tmp_max_y); - gest_start_x=gest_pt_x[0]; - gn_gesture_coor[0] = gest_start_x; - gest_start_y=gest_pt_y[0]; - gn_gesture_coor[1] = gest_start_y; - gest_end_x=gest_pt_x[gest_pt_cnt-1]; - gn_gesture_coor[2] = gest_end_x; - gest_end_y=gest_pt_y[gest_pt_cnt-1]; - gn_gesture_coor[3] = gest_end_y; - gest_width = tmp_max_x - tmp_min_x; - gn_gesture_coor[4] = gest_width; - gest_height = tmp_max_y - tmp_min_y; - gn_gesture_coor[5] = gest_height; - gest_mid_x = (tmp_max_x + tmp_min_x)/2; - gn_gesture_coor[6] = gest_mid_x; - gest_mid_y = (tmp_max_y + tmp_min_y)/2; - gn_gesture_coor[7] = gest_mid_y; - gn_gesture_coor[8] = gest_mid_x;//gest_up_x - gn_gesture_coor[9] = gest_mid_y-gest_height/2;//gest_up_y - gn_gesture_coor[10] = gest_mid_x;//gest_down_x - gn_gesture_coor[11] = gest_mid_y+gest_height/2; //gest_down_y - gn_gesture_coor[12] = gest_mid_x-gest_width/2; //gest_left_x - gn_gesture_coor[13] = gest_mid_y; //gest_left_y - gn_gesture_coor[14] = gest_mid_x+gest_width/2; //gest_right_x - gn_gesture_coor[15] = gest_mid_y; //gest_right_y - + if (gest_pt_cnt) { + for (i = 0 ; i < gest_pt_cnt ; i++) { + if (tmp_max_x < gest_pt_x[i]) + tmp_max_x = gest_pt_x[i]; + if (tmp_min_x > gest_pt_x[i]) + tmp_min_x = gest_pt_x[i]; + if (tmp_max_y < gest_pt_y[i]) + tmp_max_y = gest_pt_y[i]; + if (tmp_min_y > gest_pt_y[i]) + tmp_min_y = gest_pt_y[i]; } + I("gest_point x_min= %d, x_max= %d\n", + tmp_min_x, tmp_max_x); + I("y_min= %d, y_max= %d\n", + tmp_min_y, tmp_max_y); + gest_start_x = gest_pt_x[0]; + gn_gesture_coor[0] = gest_start_x; + gest_start_y = gest_pt_y[0]; + gn_gesture_coor[1] = gest_start_y; + gest_end_x = gest_pt_x[gest_pt_cnt - 1]; + gn_gesture_coor[2] = gest_end_x; + gest_end_y = gest_pt_y[gest_pt_cnt - 1]; + gn_gesture_coor[3] = gest_end_y; + gest_width = tmp_max_x - tmp_min_x; + gn_gesture_coor[4] = gest_width; + gest_height = tmp_max_y - tmp_min_y; + gn_gesture_coor[5] = gest_height; + gest_mid_x = (tmp_max_x + tmp_min_x) / 2; + gn_gesture_coor[6] = gest_mid_x; + gest_mid_y = (tmp_max_y + tmp_min_y) / 2; + gn_gesture_coor[7] = gest_mid_y; + /*gest_up_x*/ + gn_gesture_coor[8] = gest_mid_x; + /*gest_up_y*/ + gn_gesture_coor[9] = gest_mid_y - gest_height / 2; + /*gest_down_x*/ + gn_gesture_coor[10] = gest_mid_x; + /*gest_down_y*/ + gn_gesture_coor[11] = gest_mid_y + gest_height / 2; + /*gest_left_x*/ + gn_gesture_coor[12] = gest_mid_x - gest_width / 2; + /*gest_left_y*/ + gn_gesture_coor[13] = gest_mid_y; + /*gest_right_x*/ + gn_gesture_coor[14] = gest_mid_x + gest_width / 2; + /*gest_right_y*/ + gn_gesture_coor[15] = gest_mid_y; + + } } #endif - if(gesture_flag != 0x80) - { - if(!ts->gesture_cust_en[gesture_flag]) - { - I("%s NOT report customer key \n ",__func__); - return 0;//NOT report customer key - } - } - else - { - if(!ts->gesture_cust_en[0]) - { - I("%s NOT report report double click \n",__func__); - return 0;//NOT report power key - } + if (gesture_flag != 0x80) { + if (!ts->gesture_cust_en[gesture_flag]) { + I("%s NOT report customer key\n ", __func__); + return 0;/*NOT report customer key*/ + } + } else { + if (!ts->gesture_cust_en[0]) { + I("%s NOT report report double click\n", __func__); + return 0;/*NOT report power key*/ + } } - if(gesture_flag == 0x80) + if (gesture_flag == 0x80) return EV_GESTURE_PWR; else return gesture_flag; @@ -685,225 +687,242 @@ void himax_wake_check_func(void) ret_event = himax_parse_wake_event(private_ts); switch (ret_event) { - case EV_GESTURE_PWR: - KEY_EVENT = KEY_POWER; + case EV_GESTURE_PWR: + KEY_EVENT = KEY_POWER; break; - case EV_GESTURE_01: - KEY_EVENT = KEY_CUST_01; + case EV_GESTURE_01: + KEY_EVENT = KEY_CUST_01; break; - case EV_GESTURE_02: - KEY_EVENT = KEY_CUST_02; + case EV_GESTURE_02: + KEY_EVENT = KEY_CUST_02; break; - case EV_GESTURE_03: - KEY_EVENT = KEY_CUST_03; + case EV_GESTURE_03: + KEY_EVENT = KEY_CUST_03; break; - case EV_GESTURE_04: - KEY_EVENT = KEY_CUST_04; + case EV_GESTURE_04: + KEY_EVENT = KEY_CUST_04; break; - case EV_GESTURE_05: - KEY_EVENT = KEY_CUST_05; + case EV_GESTURE_05: + KEY_EVENT = KEY_CUST_05; break; - case EV_GESTURE_06: - KEY_EVENT = KEY_CUST_06; + case EV_GESTURE_06: + KEY_EVENT = KEY_CUST_06; break; - case EV_GESTURE_07: - KEY_EVENT = KEY_CUST_07; + case EV_GESTURE_07: + KEY_EVENT = KEY_CUST_07; break; - case EV_GESTURE_08: - KEY_EVENT = KEY_CUST_08; + case EV_GESTURE_08: + KEY_EVENT = KEY_CUST_08; break; - case EV_GESTURE_09: - KEY_EVENT = KEY_CUST_09; + case EV_GESTURE_09: + KEY_EVENT = KEY_CUST_09; break; - case EV_GESTURE_10: - KEY_EVENT = KEY_CUST_10; + case EV_GESTURE_10: + KEY_EVENT = KEY_CUST_10; break; - case EV_GESTURE_11: - KEY_EVENT = KEY_CUST_11; + case EV_GESTURE_11: + KEY_EVENT = KEY_CUST_11; break; - case EV_GESTURE_12: - KEY_EVENT = KEY_CUST_12; + case EV_GESTURE_12: + KEY_EVENT = KEY_CUST_12; break; - case EV_GESTURE_13: - KEY_EVENT = KEY_CUST_13; + case EV_GESTURE_13: + KEY_EVENT = KEY_CUST_13; break; - case EV_GESTURE_14: - KEY_EVENT = KEY_CUST_14; + case EV_GESTURE_14: + KEY_EVENT = KEY_CUST_14; break; - case EV_GESTURE_15: - KEY_EVENT = KEY_CUST_15; + case EV_GESTURE_15: + KEY_EVENT = KEY_CUST_15; break; } - if(ret_event) - { - I(" %s SMART WAKEUP KEY event %x press\n",__func__,KEY_EVENT); - input_report_key(private_ts->input_dev, KEY_EVENT, 1); - input_sync(private_ts->input_dev); - //msleep(100); - I(" %s SMART WAKEUP KEY event %x release\n",__func__,KEY_EVENT); - input_report_key(private_ts->input_dev, KEY_EVENT, 0); - input_sync(private_ts->input_dev); - FAKE_POWER_KEY_SEND=true; + if (ret_event) { + I(" %s SMART WAKEUP KEY event %x press\n", + __func__, KEY_EVENT); + input_report_key(private_ts->input_dev, KEY_EVENT, 1); + input_sync(private_ts->input_dev); + /*msleep(100);*/ + I(" %s SMART WAKEUP KEY event %x release\n", + __func__, KEY_EVENT); + input_report_key(private_ts->input_dev, KEY_EVENT, 0); + input_sync(private_ts->input_dev); + FAKE_POWER_KEY_SEND = true; #ifdef HX_GESTURE_TRACK - I("gest_start_x= %d, gest_start_y= %d, gest_end_x= %d, gest_end_y= %d\n",gest_start_x,gest_start_y, - gest_end_x,gest_end_y); - I("gest_width= %d, gest_height= %d, gest_mid_x= %d, gest_mid_y= %d\n",gest_width,gest_height, - gest_mid_x,gest_mid_y); - I("gest_up_x= %d, gest_up_y= %d, gest_down_x= %d, gest_down_y= %d\n",gn_gesture_coor[8],gn_gesture_coor[9], - gn_gesture_coor[10],gn_gesture_coor[11]); - I("gest_left_x= %d, gest_left_y= %d, gest_right_x= %d, gest_right_y= %d\n",gn_gesture_coor[12],gn_gesture_coor[13], - gn_gesture_coor[14],gn_gesture_coor[15]); + I("gest_start_x= %d, gest_start_y= %d\n", + gest_start_x, gest_start_y); + I("gest_end_x= %d, gest_end_y= %d\n", + gest_end_x, gest_end_y); + I("gest_width= %d, gest_height= %d\n", + gest_width, gest_height); + I("gest_mid_x= %d, gest_mid_y= %d\n", + gest_mid_x, gest_mid_y); + I("gest_up_x= %d, gest_up_y= %d\n", + gn_gesture_coor[8], gn_gesture_coor[9]); + I("gest_down_x= %d, gest_down_y= %d\n", + gn_gesture_coor[10], gn_gesture_coor[11]); + I("gest_left_x= %d, gest_left_y= %d\n", + gn_gesture_coor[12], gn_gesture_coor[13]); + I("gest_right_x= %d, gest_right_y= %d\n", + gn_gesture_coor[14], gn_gesture_coor[15]); #endif - } + } } #endif -static void himax_ts_button_func(int tp_key_index,struct himax_ts_data *ts) +static void himax_ts_button_func(int tp_key_index, struct himax_ts_data *ts) { uint16_t x_position = 0, y_position = 0; -if ( tp_key_index != 0x00) - { - I("virtual key index =%x\n",tp_key_index); - if ( tp_key_index == 0x01) { + + if (tp_key_index != 0x00) { + I("virtual key index =%x\n", tp_key_index); + if (tp_key_index == 0x01) { vk_press = 1; I("back key pressed\n"); - if (ts->pdata->virtual_key) - { - if (ts->button[0].index) { - x_position = (ts->button[0].x_range_min + ts->button[0].x_range_max) / 2; - y_position = (ts->button[0].y_range_min + ts->button[0].y_range_max) / 2; - } - if (ts->protocol_type == PROTOCOL_TYPE_A) { - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, - 100); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, - x_position); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, - y_position); - input_mt_sync(ts->input_dev); - } else if (ts->protocol_type == PROTOCOL_TYPE_B) { - input_mt_slot(ts->input_dev, 0); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, - 1); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, - 100); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, - x_position); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, - y_position); - } + if (ts->pdata->virtual_key) { + if (ts->button[0].index) { + x_position = (ts->button[0].x_range_min + + ts->button[0].x_range_max) / 2; + y_position = (ts->button[0].y_range_min + + ts->button[0].y_range_max) / 2; } - else - input_report_key(ts->input_dev, KEY_BACK, 1); - } - else if ( tp_key_index == 0x02) { + if (ts->protocol_type == PROTOCOL_TYPE_A) { + input_report_abs(ts->input_dev, + ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, + ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); + } else if (ts->protocol_type + == PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, 0); + + input_mt_report_slot_state + (ts->input_dev, MT_TOOL_FINGER, 1); + + input_report_abs(ts->input_dev, + ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_Y, y_position); + } + } else + input_report_key(ts->input_dev, KEY_BACK, 1); + } else if (tp_key_index == 0x02) { vk_press = 1; I("home key pressed\n"); - if (ts->pdata->virtual_key) - { - if (ts->button[1].index) { - x_position = (ts->button[1].x_range_min + ts->button[1].x_range_max) / 2; - y_position = (ts->button[1].y_range_min + ts->button[1].y_range_max) / 2; - } - if (ts->protocol_type == PROTOCOL_TYPE_A) { - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, - 100); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, - x_position); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, - y_position); - input_mt_sync(ts->input_dev); - } else if (ts->protocol_type == PROTOCOL_TYPE_B) { - input_mt_slot(ts->input_dev, 0); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, - 1); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, - 100); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, - x_position); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, - y_position); - } + if (ts->pdata->virtual_key) { + if (ts->button[1].index) { + x_position = (ts->button[1].x_range_min + + ts->button[1].x_range_max) / 2; + y_position = (ts->button[1].y_range_min + + ts->button[1].y_range_max) / 2; } - else - input_report_key(ts->input_dev, KEY_HOME, 1); - } - else if ( tp_key_index == 0x04) { + if (ts->protocol_type == PROTOCOL_TYPE_A) { + input_report_abs(ts->input_dev, + ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, + ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); + } else if (ts->protocol_type + == PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, 0); + + input_mt_report_slot_state + (ts->input_dev, MT_TOOL_FINGER, 1); + + input_report_abs(ts->input_dev, + ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_Y, y_position); + } + } else + input_report_key(ts->input_dev, KEY_HOME, 1); + } else if (tp_key_index == 0x04) { vk_press = 1; I("APP_switch key pressed\n"); - if (ts->pdata->virtual_key) - { - if (ts->button[2].index) { - x_position = (ts->button[2].x_range_min + ts->button[2].x_range_max) / 2; - y_position = (ts->button[2].y_range_min + ts->button[2].y_range_max) / 2; - } - if (ts->protocol_type == PROTOCOL_TYPE_A) { - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, 0); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, - 100); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, - x_position); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, - y_position); - input_mt_sync(ts->input_dev); - } else if (ts->protocol_type == PROTOCOL_TYPE_B) { - input_mt_slot(ts->input_dev, 0); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, - 1); - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, - 100); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, - 100); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, - x_position); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, - y_position); - } + if (ts->pdata->virtual_key) { + if (ts->button[2].index) { + x_position = (ts->button[2].x_range_min + + ts->button[2].x_range_max) / 2; + y_position = (ts->button[2].y_range_min + + ts->button[2].y_range_max) / 2; } - else - input_report_key(ts->input_dev, KEY_F10, 1); + if (ts->protocol_type == PROTOCOL_TYPE_A) { + input_report_abs(ts->input_dev, + ABS_MT_TRACKING_ID, 0); + input_report_abs(ts->input_dev, + ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_Y, y_position); + input_mt_sync(ts->input_dev); + } else if (ts->protocol_type == + PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, 0); + + input_mt_report_slot_state + (ts->input_dev, MT_TOOL_FINGER, 1); + + input_report_abs(ts->input_dev, + ABS_MT_TOUCH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_WIDTH_MAJOR, 100); + input_report_abs(ts->input_dev, + ABS_MT_PRESSURE, 100); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_X, x_position); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_Y, y_position); + } + } else + input_report_key(ts->input_dev, KEY_F10, 1); } input_sync(ts->input_dev); - } -else/*tp_key_index =0x00*/ - { + } else {/*tp_key_index =0x00*/ I("virtual key released\n"); vk_press = 0; if (ts->protocol_type == PROTOCOL_TYPE_A) { input_mt_sync(ts->input_dev); - } - else if (ts->protocol_type == PROTOCOL_TYPE_B) { + } else if (ts->protocol_type == PROTOCOL_TYPE_B) { input_mt_slot(ts->input_dev, 0); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); + input_mt_report_slot_state(ts->input_dev, + MT_TOOL_FINGER, 0); } input_report_key(ts->input_dev, KEY_BACK, 0); input_report_key(ts->input_dev, KEY_HOME, 0); input_report_key(ts->input_dev, KEY_F10, 0); - input_sync(ts->input_dev); + input_sync(ts->input_dev); } } @@ -915,8 +934,8 @@ void himax_ts_work(struct himax_ts_data *ts) uint8_t finger_on = 0; int32_t loop_i; uint16_t check_sum_cal = 0; - int raw_cnt_max ; - int raw_cnt_rmd ; + int raw_cnt_max; + int raw_cnt_rmd; int hx_touch_info_size; uint8_t coordInfoSize = ts->coord_data_size + ts->area_data_size + 4; @@ -924,121 +943,111 @@ void himax_ts_work(struct himax_ts_data *ts) int16_t *mutual_data; int16_t *self_data; uint8_t diag_cmd; - int i; - int mul_num; - int self_num; + int i; + int mul_num; + int self_num; int RawDataLen = 0; - //coordinate dump start - char coordinate_char[15+(ic_data->HX_MAX_PT+5)*2*5+2]; - //coordinate dump end + /*coordinate dump start*/ + char coordinate_char[15 + (ic_data->HX_MAX_PT + 5) * 2 * 5 + 2]; + struct timeval t; + struct tm broken; + /*coordinate dump end*/ #endif memset(buf, 0x00, sizeof(buf)); memset(hw_reset_check, 0x00, sizeof(hw_reset_check)); - raw_cnt_max = ic_data->HX_MAX_PT/4; - raw_cnt_rmd = ic_data->HX_MAX_PT%4; - + raw_cnt_max = ic_data->HX_MAX_PT / 4; + raw_cnt_rmd = ic_data->HX_MAX_PT % 4; #if defined(HX_USB_DETECT2) himax_cable_detect_func(); #endif - if (raw_cnt_rmd != 0x00) //more than 4 fingers - { - RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max); - hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+2)*4; - } - else //less than 4 fingers - { - RawDataLen = cal_data_len(raw_cnt_rmd, ic_data->HX_MAX_PT, raw_cnt_max); - hx_touch_info_size = (ic_data->HX_MAX_PT+raw_cnt_max+1)*4; + if (raw_cnt_rmd != 0x00) { /*more than 4 fingers*/ + RawDataLen = cal_data_len(raw_cnt_rmd, + ic_data->HX_MAX_PT, raw_cnt_max); + hx_touch_info_size = (ic_data->HX_MAX_PT + raw_cnt_max + 2) * 4; + } else { /*less than 4 fingers*/ + RawDataLen = cal_data_len(raw_cnt_rmd, + ic_data->HX_MAX_PT, raw_cnt_max); + hx_touch_info_size = (ic_data->HX_MAX_PT + raw_cnt_max + 1) * 4; } #ifdef HX_TP_PROC_DIAG diag_cmd = getDiagCommand(); - if( diag_cmd ){ + if (diag_cmd) { ret = read_event_stack(ts->client, buf, 128); - } - else{ - if(touch_monitor_stop_flag != 0){ + } else { + if (touch_monitor_stop_flag != 0) { ret = read_event_stack(ts->client, buf, 128); - touch_monitor_stop_flag-- ; - } - else{ - ret = read_event_stack(ts->client, buf, hx_touch_info_size); + touch_monitor_stop_flag--; + } else { + ret = read_event_stack(ts->client, + buf, hx_touch_info_size); } } if (!ret) #else - if(!read_event_stack(ts->client, buf, hx_touch_info_size)) -#endif - { - E("%s: can't read data from chip!\n", __func__); - goto err_workqueue_out; - } + if (!read_event_stack(ts->client, buf, hx_touch_info_size)) +#endif + { + E("%s: can't read data from chip!\n", __func__); + goto err_workqueue_out; + } post_read_event_stack(ts->client); #ifdef HX_ESD_WORKAROUND - for(i = 0; i < hx_touch_info_size; i++) - { - if(buf[i] == 0xED)/*case 1 ESD recovery flow*/ - { + for (i = 0; i < hx_touch_info_size; i++) { + if (buf[i] == 0xED) { /*case 1 ESD recovery flow*/ check_sum_cal = 1; - }else if(buf[i] == 0x00) - { + } else if (buf[i] == 0x00) { ESD_00_Flag = 1; - } - else - { + } else { check_sum_cal = 0; ESD_00_counter = 0; - ESD_00_Flag = 0; + ESD_00_Flag = 0; i = hx_touch_info_size; break; - } - } - if (ESD_00_Flag == 1){ - ESD_00_counter ++; + } } - if (ESD_00_counter > 1){ + if (ESD_00_Flag == 1) + ESD_00_counter++; + if (ESD_00_counter > 1) check_sum_cal = 2; + if (check_sum_cal == 2 && HX_ESD_RESET_ACTIVATE == 0) { + I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n"); + ESD_HW_REST(); + return; } - - if (check_sum_cal == 2 && HX_ESD_RESET_ACTIVATE == 0) - { - I("[HIMAX TP MSG]: ESD event checked - ALL Zero.\n"); - ESD_HW_REST(); - return; - } - - if (check_sum_cal == 1 && HX_ESD_RESET_ACTIVATE == 0) - { + if (check_sum_cal == 1 && HX_ESD_RESET_ACTIVATE == 0) { I("[HIMAX TP MSG]: ESD event checked - ALL 0xED.\n"); ESD_HW_REST(); return; - } - else if (HX_ESD_RESET_ACTIVATE) - { + } else if (HX_ESD_RESET_ACTIVATE) { #ifdef HX_SMART_WAKEUP - queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(50)); + queue_delayed_work(ts->himax_smwp_wq, + &ts->smwp_work, msecs_to_jiffies(50)); #endif #ifdef HX_HIGH_SENSE - queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(50)); + queue_delayed_work(ts->himax_hsen_wq, + &ts->hsen_work, msecs_to_jiffies(50)); #endif - HX_ESD_RESET_ACTIVATE = 0;/*drop 1st interrupts after chip reset*/ - I("[HIMAX TP MSG]:%s: Back from reset, ready to serve.\n", __func__); +/*drop 1st interrupts after chip reset*/ + HX_ESD_RESET_ACTIVATE = 0; + I("[HIMAX TP MSG]:%s: Back from reset,ready to serve.\n", + __func__); } #endif - for (loop_i = 0, check_sum_cal = 0; loop_i < hx_touch_info_size; loop_i++) + for (loop_i = 0, check_sum_cal = 0; + loop_i < hx_touch_info_size; loop_i++) check_sum_cal += buf[loop_i]; - - if ((check_sum_cal % 0x100 != 0) ) - { - I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n", check_sum_cal); + + if ((check_sum_cal % 0x100 != 0)) { + I("[HIMAX TP MSG] checksum fail : check_sum_cal: 0x%02X\n", + check_sum_cal); return; } - if (ts->debug_log_level & BIT(0)) { I("%s: raw data:\n", __func__); for (loop_i = 0; loop_i < hx_touch_info_size; loop_i++) { @@ -1048,260 +1057,289 @@ void himax_ts_work(struct himax_ts_data *ts) } } - //touch monitor raw data fetch + /*touch monitor raw data fetch*/ #ifdef HX_TP_PROC_DIAG diag_cmd = getDiagCommand(); - if (diag_cmd >= 1 && diag_cmd <= 6) - { - //Check 124th byte CRC - if(!diag_check_sum(hx_touch_info_size, buf)) - { + if (diag_cmd >= 1 && diag_cmd <= 6) { + /*Check 124th byte CRC*/ + if (!diag_check_sum(hx_touch_info_size, buf)) goto bypass_checksum_failed_packet; - } + #ifdef HX_TP_PROC_2T2R - if(Is_2T2R && diag_cmd == 4) - { + if (Is_2T2R && diag_cmd == 4) { mutual_data = getMutualBuffer_2(); - self_data = getSelfBuffer(); + self_data = getSelfBuffer(); - // initiallize the block number of mutual and self + /* initiallize the block number of mutual and self*/ mul_num = getXChannel_2() * getYChannel_2(); #ifdef HX_EN_SEL_BUTTON - self_num = getXChannel_2() + getYChannel_2() + ic_data->HX_BT_NUM; + self_num = getXChannel_2() + + getYChannel_2() + ic_data->HX_BT_NUM; #else self_num = getXChannel_2() + getYChannel_2(); #endif - } - else -#endif + } else +#endif { mutual_data = getMutualBuffer(); - self_data = getSelfBuffer(); + self_data = getSelfBuffer(); - // initiallize the block number of mutual and self + /* initiallize the block number of mutual and self*/ mul_num = getXChannel() * getYChannel(); #ifdef HX_EN_SEL_BUTTON - self_num = getXChannel() + getYChannel() + ic_data->HX_BT_NUM; + self_num = getXChannel() + + getYChannel() + ic_data->HX_BT_NUM; #else self_num = getXChannel() + getYChannel(); #endif } - diag_parse_raw_data(hx_touch_info_size, RawDataLen, mul_num, self_num, buf, diag_cmd, mutual_data, self_data); + diag_parse_raw_data(hx_touch_info_size, + RawDataLen, mul_num, self_num, buf, + diag_cmd, mutual_data, self_data); - } - else if (diag_cmd == 7) - { + } else if (diag_cmd == 7) { memcpy(&(diag_coor[0]), &buf[0], 128); } - //coordinate dump start - if (coordinate_dump_enable == 1) - { - for(i=0; i<(15 + (ic_data->HX_MAX_PT+5)*2*5); i++) - { + /*coordinate dump start*/ + if (coordinate_dump_enable == 1) { + for (i = 0; i < (15 + (ic_data-> + HX_MAX_PT + 5) * 2 * 5); + i++) { coordinate_char[i] = 0x20; } - coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5] = 0xD; - coordinate_char[15 + (ic_data->HX_MAX_PT+5)*2*5 + 1] = 0xA; + coordinate_char[15 + + (ic_data->HX_MAX_PT + 5) * 2 * 5] = 0xD; + coordinate_char[15 + + (ic_data->HX_MAX_PT + 5) * 2 * 5 + 1] = 0xA; } - //coordinate dump end + /*coordinate dump end*/ bypass_checksum_failed_packet: #endif - EN_NoiseFilter = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>3); - //I("EN_NoiseFilter=%d\n",EN_NoiseFilter); - EN_NoiseFilter = EN_NoiseFilter & 0x01; - //I("EN_NoiseFilter2=%d\n",EN_NoiseFilter); + EN_NoiseFilter = (buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 3); + /*I("EN_NoiseFilter=%d\n",EN_NoiseFilter);*/ + EN_NoiseFilter = EN_NoiseFilter & 0x01; + /*I("EN_NoiseFilter2=%d\n",EN_NoiseFilter);*/ #if defined(HX_EN_SEL_BUTTON) || defined(HX_EN_MUT_BUTTON) - tpd_key = (buf[HX_TOUCH_INFO_POINT_CNT+2]>>4); - if (tpd_key == 0x0F)/*All (VK+AA)leave*/ - { - tpd_key = 0x00; - } - //I("[DEBUG] tpd_key: %x\r\n", tpd_key); -#else + tpd_key = (buf[HX_TOUCH_INFO_POINT_CNT + 2] >> 4); + if (tpd_key == 0x0F) {/*All (VK+AA)leave*/ tpd_key = 0x00; + } + /*I("[DEBUG] tpd_key: %x\r\n", tpd_key);*/ +#else + tpd_key = 0x00; #endif - p_point_num = hx_point_num; - - if (buf[HX_TOUCH_INFO_POINT_CNT] == 0xff) - hx_point_num = 0; - else - hx_point_num= buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f; - - // Touch Point information - if (hx_point_num != 0 ) { - if(vk_press == 0x00) - { - uint16_t old_finger = ts->pre_finger_mask; - ts->pre_finger_mask = 0; - finger_num = buf[coordInfoSize - 4] & 0x0F; - finger_on = 1; - AA_press = 1; - for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { - int base = loop_i * 4; - int x = buf[base] << 8 | buf[base + 1]; - int y = (buf[base + 2] << 8 | buf[base + 3]); - int w = buf[(ts->nFinger_support * 4) + loop_i]; - if(x >= 0 && x <= ts->pdata->abs_x_max && y >= 0 && y <= ts->pdata->abs_y_max){ - finger_num--; - - if ((ts->debug_log_level & BIT(3)) > 0) - { - if (old_finger >> loop_i == 0) - { - if (ts->useScreenRes) - { - I("status: Screen:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n", - loop_i+1, x * ts->widthFactor >> SHIFTBITS, - y * ts->heightFactor >> SHIFTBITS, w, EN_NoiseFilter); - } - else - { - I("status: Raw:F:%02d Down, X:%d, Y:%d, W:%d, N:%d\n", - loop_i+1, x, y, w, EN_NoiseFilter); - } - } - } - - if (ts->protocol_type == PROTOCOL_TYPE_B) - { - input_mt_slot(ts->input_dev, loop_i); - } - - input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, w); - input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, w); - input_report_abs(ts->input_dev, ABS_MT_PRESSURE, w); - input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x); - input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y); - - if (ts->protocol_type == PROTOCOL_TYPE_A) - { - input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, loop_i); - input_mt_sync(ts->input_dev); - } - else - { - ts->last_slot = loop_i; - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 1); - } - - if (!ts->first_pressed) - { - ts->first_pressed = 1; - I("S1@%d, %d\n", x, y); - } - - ts->pre_finger_data[loop_i][0] = x; - ts->pre_finger_data[loop_i][1] = y; - - - if (ts->debug_log_level & BIT(1)) - I("Finger %d=> X:%d, Y:%d W:%d, Z:%d, F:%d, N:%d\n", - loop_i + 1, x, y, w, w, loop_i + 1, EN_NoiseFilter); - - ts->pre_finger_mask = ts->pre_finger_mask + (1 << loop_i); - - } else { - if (ts->protocol_type == PROTOCOL_TYPE_B) - { - input_mt_slot(ts->input_dev, loop_i); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); - } - - if (loop_i == 0 && ts->first_pressed == 1) - { - ts->first_pressed = 2; - I("E1@%d, %d\n", - ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]); - } - if ((ts->debug_log_level & BIT(3)) > 0) - { - if (old_finger >> loop_i == 1) - { - if (ts->useScreenRes) - { - I("status: Screen:F:%02d Up, X:%d, Y:%d, N:%d\n", - loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS, - ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter); - } - else - { - I("status: Raw:F:%02d Up, X:%d, Y:%d, N:%d\n", - loop_i+1, ts->pre_finger_data[loop_i][0], - ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter); - } - } - } - } - } + p_point_num = hx_point_num; + + if (buf[HX_TOUCH_INFO_POINT_CNT] == 0xff) + hx_point_num = 0; + else + hx_point_num = buf[HX_TOUCH_INFO_POINT_CNT] & 0x0f; + + /* Touch Point information*/ + if ((hx_point_num != 0) && (vk_press == 0x00)) { + uint16_t old_finger = ts->pre_finger_mask; - }else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) { - //temp_x[0] = 0xFFFF; - //temp_y[0] = 0xFFFF; - //temp_x[1] = 0xFFFF; - //temp_y[1] = 0xFFFF; - himax_ts_button_func(tpd_key,ts); - finger_on = 0; + ts->pre_finger_mask = 0; + finger_num = buf[coordInfoSize - 4] & 0x0F; + finger_on = 1; + AA_press = 1; + for (i = 0; i < ts->nFinger_support; i++) { + int base = i * 4; + int x = buf[base] << 8 | buf[base + 1]; + int y = (buf[base + 2] << 8 | buf[base + 3]); + int w = buf[(ts->nFinger_support * 4) + i]; + + if (x >= 0 && x <= ts->pdata->abs_x_max + && y >= 0 && y <= ts->pdata->abs_y_max) { + finger_num--; + if ((((ts->debug_log_level & BIT(3)) > 0) + && (old_finger >> i == 0)) + && (ts->useScreenRes)) { + I("status:Screen:F:%02d", i + 1); + I("Down,X:%d,Y:%d,W:%d,N:%d\n", + x * ts->widthFactor >> SHIFTBITS, + y * ts->heightFactor >> SHIFTBITS, + w, EN_NoiseFilter); + } else if ((((ts->debug_log_level & BIT(3)) > 0) + && (old_finger >> i == 0)) + && !(ts->useScreenRes)) { + I("status:Raw:F:%02d", i + 1); + I("Down,X:%d,Y:%d,W:%d,N:%d\n", + x, y, w, EN_NoiseFilter); } - input_report_key(ts->input_dev, BTN_TOUCH, finger_on); - input_sync(ts->input_dev); - } else if (hx_point_num == 0){ - if(AA_press) - { - // leave event - finger_on = 0; - AA_press = 0; - if (ts->protocol_type == PROTOCOL_TYPE_A) - input_mt_sync(ts->input_dev); - for (loop_i = 0; loop_i < ts->nFinger_support; loop_i++) { - if (((ts->pre_finger_mask >> loop_i) & 1) == 1) { - if (ts->protocol_type == PROTOCOL_TYPE_B) { - input_mt_slot(ts->input_dev, loop_i); - input_mt_report_slot_state(ts->input_dev, MT_TOOL_FINGER, 0); - } - } - } - if (ts->pre_finger_mask > 0) { - for (loop_i = 0; loop_i < ts->nFinger_support && (ts->debug_log_level & BIT(3)) > 0; loop_i++) { - if (((ts->pre_finger_mask >> loop_i) & 1) == 1) { - if (ts->useScreenRes) { - I("status:%X, Screen:F:%02d Up, X:%d, Y:%d, N:%d\n", 0, loop_i+1, ts->pre_finger_data[loop_i][0] * ts->widthFactor >> SHIFTBITS, - ts->pre_finger_data[loop_i][1] * ts->heightFactor >> SHIFTBITS, Last_EN_NoiseFilter); - } else { - I("status:%X, Raw:F:%02d Up, X:%d, Y:%d, N:%d\n",0, loop_i+1, ts->pre_finger_data[loop_i][0],ts->pre_finger_data[loop_i][1], Last_EN_NoiseFilter); - } - } - } - ts->pre_finger_mask = 0; + if (ts->protocol_type == PROTOCOL_TYPE_B) + input_mt_slot(ts->input_dev, i); + + input_report_abs(ts->input_dev, + ABS_MT_TOUCH_MAJOR, w); + input_report_abs(ts->input_dev, + ABS_MT_WIDTH_MAJOR, w); + input_report_abs(ts->input_dev, + ABS_MT_PRESSURE, w); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_X, x); + input_report_abs(ts->input_dev, + ABS_MT_POSITION_Y, y); + + if (ts->protocol_type == PROTOCOL_TYPE_A) { + input_report_abs(ts->input_dev, + ABS_MT_TRACKING_ID, i); + input_mt_sync(ts->input_dev); + } else { + ts->last_slot = i; + input_mt_report_slot_state + (ts->input_dev, + MT_TOOL_FINGER, 1); } - if (ts->first_pressed == 1) { - ts->first_pressed = 2; - I("E1@%d, %d\n",ts->pre_finger_data[0][0] , ts->pre_finger_data[0][1]); + if (!ts->first_pressed) { + ts->first_pressed = 1; + I("S1@%d, %d\n", x, y); } - if (ts->debug_log_level & BIT(1)) - I("All Finger leave\n"); + ts->pre_finger_data[i][0] = x; + ts->pre_finger_data[i][1] = y; + + if (ts->debug_log_level & BIT(1)) { + I("Finger %d=> X:%d,Y:%d,W:%d,", + i + 1, x, y, w); + I("Z:%d,F:%d,N:%d\n", + w, i + 1, EN_NoiseFilter); + } + ts->pre_finger_mask = + ts->pre_finger_mask + (1 << i); + } else { + if (ts->protocol_type == PROTOCOL_TYPE_B) { + input_mt_slot(ts->input_dev, i); + input_mt_report_slot_state + (ts->input_dev, MT_TOOL_FINGER, 0); + } + if (i == 0 && ts->first_pressed == 1) { + ts->first_pressed = 2; + I("E1@%d, %d\n", + ts->pre_finger_data[0][0], + ts->pre_finger_data[0][1]); + } + if ((((ts->debug_log_level & BIT(3)) > 0) + && (old_finger >> i == 1)) + && (ts->useScreenRes)) { + I("status:Screen:F:%02d,Up,X:%d,Y:%d\n", + i + 1, ts->pre_finger_data[i][0] + * ts->widthFactor >> SHIFTBITS, + ts->pre_finger_data[i][1] + * ts->heightFactor >> SHIFTBITS); + } else if ((((ts->debug_log_level & BIT(3)) > 0) + && (old_finger >> i == 1)) + && !(ts->useScreenRes)) { + I("status:Raw:F:%02d,Up,X:%d,Y:%d\n", + i + 1, ts->pre_finger_data[i][0], + ts->pre_finger_data[i][1]); + } } - else if (tpd_key != 0x00) { - himax_ts_button_func(tpd_key,ts); - finger_on = 1; + } + input_report_key(ts->input_dev, BTN_TOUCH, finger_on); + input_sync(ts->input_dev); + } else if ((hx_point_num != 0) + && ((tpd_key_old != 0x00) && (tpd_key == 0x00))) { + /*temp_x[0] = 0xFFFF;*/ + /*temp_y[0] = 0xFFFF;*/ + /*temp_x[1] = 0xFFFF;*/ + /*temp_y[1] = 0xFFFF;*/ + himax_ts_button_func(tpd_key, ts); + finger_on = 0; + input_report_key(ts->input_dev, BTN_TOUCH, finger_on); + input_sync(ts->input_dev); + } else if (hx_point_num == 0) { + if (AA_press) { + /*leave event*/ + finger_on = 0; + AA_press = 0; + if (ts->protocol_type == PROTOCOL_TYPE_A) + input_mt_sync(ts->input_dev); + + for (i = 0 ; i < ts->nFinger_support ; i++) { + if ((((ts->pre_finger_mask >> i) & 1) == 1) + && (ts->protocol_type == PROTOCOL_TYPE_B)) { + input_mt_slot(ts->input_dev, i); + input_mt_report_slot_state + (ts->input_dev, MT_TOOL_FINGER, 0); + } } - else if ((tpd_key_old != 0x00)&&(tpd_key == 0x00)) { - himax_ts_button_func(tpd_key,ts); - finger_on = 0; + if (ts->pre_finger_mask > 0) { + for (i = 0; i < ts->nFinger_support + && (ts->debug_log_level & BIT(3)) > 0; i++) { + if ((((ts->pre_finger_mask + >> i) & 1) == 1) + && (ts->useScreenRes)) { + I("status:%X,", 0); + I("Screen:F:%02d,", i + 1); + I("Up,X:%d,Y:%d\n", + ts->pre_finger_data[i][0] + * ts->widthFactor >> SHIFTBITS, + ts->pre_finger_data[i][1] + * ts->heightFactor >> SHIFTBITS + ); + } else if ((((ts->pre_finger_mask + >> i) & 1) == 1) + && !(ts->useScreenRes)) { + I("status:%X,", 0); + I("Screen:F:%02d,", i + 1); + I("Up,X:%d,Y:%d\n", + ts->pre_finger_data[i][0], + ts->pre_finger_data[i][1]); + } + } + ts->pre_finger_mask = 0; + } + + if (ts->first_pressed == 1) { + ts->first_pressed = 2; + I("E1@%d, %d\n", ts->pre_finger_data[0][0], + ts->pre_finger_data[0][1]); } - input_report_key(ts->input_dev, BTN_TOUCH, finger_on); - input_sync(ts->input_dev); + + if (ts->debug_log_level & BIT(1)) + I("All Finger leave\n"); + +#ifdef HX_TP_PROC_DIAG + /*coordinate dump start*/ + if (coordinate_dump_enable == 1) { + do_gettimeofday(&t); + time_to_tm(t.tv_sec, 0, &broken); + snprintf(&coordinate_char[0], 15, + "%2d:%2d:%2d:%lu,", broken.tm_hour, + broken.tm_min, broken.tm_sec, + t.tv_usec / 1000); + + snprintf(&coordinate_char[15], 10, + "Touch up!"); + + coordinate_fn->f_op->write + (coordinate_fn, &coordinate_char[0], + 15 + (ic_data->HX_MAX_PT + 5) + * 2 * sizeof(char) * 5 + 2, + &coordinate_fn->f_pos); + } + /*coordinate dump end*/ +#endif + } else if (tpd_key != 0x00) { + himax_ts_button_func(tpd_key, ts); + finger_on = 1; + } else if ((tpd_key_old != 0x00) && (tpd_key == 0x00)) { + himax_ts_button_func(tpd_key, ts); + finger_on = 0; } - tpd_key_old = tpd_key; - Last_EN_NoiseFilter = EN_NoiseFilter; + input_report_key(ts->input_dev, BTN_TOUCH, finger_on); + input_sync(ts->input_dev); + } + tpd_key_old = tpd_key; workqueue_out: return; @@ -1310,7 +1348,7 @@ void himax_ts_work(struct himax_ts_data *ts) I("%s: Now reset the Touch chip.\n", __func__); #ifdef HX_RST_PIN_FUNC - himax_HW_reset(true,false); + himax_HW_reset(true, false); #endif goto workqueue_out; @@ -1329,6 +1367,7 @@ enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer) static void himax_cable_tp_status_handler_func(int connect_status) { struct himax_ts_data *ts; + I("Touch: cable change to %d\n", connect_status); ts = private_ts; if (ts->cable_config) { @@ -1342,18 +1381,23 @@ static void himax_cable_tp_status_handler_func(int connect_status) ts->usb_connected = 0x00; } - i2c_himax_master_write(ts->client, ts->cable_config, - sizeof(ts->cable_config), HIMAX_I2C_RETRY_TIMES); + i2c_himax_master_write(ts->client, + ts->cable_config, + sizeof(ts->cable_config), + HIMAX_I2C_RETRY_TIMES); - I("%s: Cable status change: 0x%2.2X\n", __func__, ts->cable_config[1]); + I("%s: Cable status change: 0x%2.2X\n", + __func__, ts->cable_config[1]); } else - I("%s: Cable status is the same as previous one, ignore.\n", __func__); + I("%s: Cable status is same, ignore.\n", + __func__); } else { if (connect_status) ts->usb_connected = 0x01; else ts->usb_connected = 0x00; - I("%s: Cable status remembered: 0x%2.2X\n", __func__, ts->usb_connected); + I("%s: Cable status remembered: 0x%2.2X\n", + __func__, ts->usb_connected); } } } @@ -1373,16 +1417,20 @@ void himax_cable_detect_func(void) struct himax_ts_data *ts; u32 connect_status = 0; - connect_status = USB_Flag;//upmu_is_chr_det(); + connect_status = USB_Flag;/*upmu_is_chr_det();*/ ts = private_ts; - //I("Touch: cable status=%d, cable_config=%p, usb_connected=%d \n", connect_status,ts->cable_config, ts->usb_connected); + /*I("Touch: cable status=%d, cable_config=%p, + usb_connected=%d\n", connect_status, + ts->cable_config, ts->usb_connected);*/ + if (ts->cable_config) { if ((!!connect_status) != ts->usb_connected) { - //notify USB plug/unplug - // 0x9008_8060 ==> 0x0000_0000/0001 - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x60; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; - + /*notify USB plug/unplug*/ + /*0x9008_8060 ==> 0x0000_0000/0001*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x60; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; if (!!connect_status) { tmp_data[0] = 0x01; ts->usb_connected = 0x01; @@ -1393,10 +1441,13 @@ void himax_cable_detect_func(void) himax_flash_write_burst(ts->client, tmp_addr, tmp_data); - I("%s: Cable status change: 0x%2.2X\n", __func__, ts->usb_connected); - } - //else - //I("%s: Cable status is the same as previous one, ignore.\n", __func__); + I("%s: Cable status change: 0x%2.2X\n", + __func__, ts->usb_connected); + } + /*else*/ + /*I("%s: Cable status is the same as previous one, + ignore.\n", __func__);*/ + } } #endif @@ -1417,52 +1468,52 @@ int himax_fb_register(struct himax_ts_data *ts) #endif #ifdef HX_SMART_WAKEUP -void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable) +void himax_set_SMWP_func(struct i2c_client *client, uint8_t SMWP_enable) { uint8_t tmp_data[4]; - if(SMWP_enable) - { - SMWP_bit_retry: + if (SMWP_enable) { +SMWP_bit_retry: himax_set_SMWP_enable(client, SMWP_enable); msleep(20); - himax_get_SMWP_enable(client,tmp_data); - I("%s: Read SMWP bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ - ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); - if(tmp_data[0]!= 0x01) - { - I("%s: retry SMWP bit write data[0]=%x \n",__func__,tmp_data[0]); - goto SMWP_bit_retry; - } + himax_get_SMWP_enable(client, tmp_data); +I("%s: Read SMWP bit data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", +__func__, tmp_data[0], tmp_data[1], tmp_data[2], tmp_data[3]); + + if (tmp_data[0] != 0x01) { + I("%s: retry SMWP bit write data[0]=%x\n", + __func__, tmp_data[0]); + goto SMWP_bit_retry; + } } } static void himax_SMWP_work(struct work_struct *work) { - struct himax_ts_data *ts = container_of(work, struct himax_ts_data, - smwp_work.work); + struct himax_ts_data *ts = + container_of(work, struct himax_ts_data, smwp_work.work); I(" %s in", __func__); - himax_set_SMWP_func(ts->client,ts->SMWP_enable); + himax_set_SMWP_func(ts->client, ts->SMWP_enable); } #endif -#ifdef HX_TP_PROC_FLASH_DUMP +#ifdef HX_TP_PROC_FLASH_DUMP static void himax_ts_flash_work_func(struct work_struct *work) { himax_ts_flash_func(); } #endif -#ifdef HX_TP_PROC_DIAG +#ifdef HX_TP_PROC_DIAG static void himax_ts_diag_work_func(struct work_struct *work) { himax_ts_diag_func(); } #endif -void himax_ts_init(struct himax_ts_data *ts) +bool himax_ts_init(struct himax_ts_data *ts) { int ret = 0, err = 0; struct himax_i2c_platform_data *pdata; @@ -1476,15 +1527,14 @@ void himax_ts_init(struct himax_ts_data *ts) /* Set pinctrl in active state */ if (ts->ts_pinctrl) { ret = pinctrl_select_state(ts->ts_pinctrl, - ts->pinctrl_state_active); - if (ret < 0) { - E("Failed to set pin in active state %d",ret); - } + ts->pinctrl_state_active); + if (ret < 0) + E("Failed to set pin in active state %d", ret); } himax_burst_enable(client, 0); - //Get Himax IC Type / FW information / Calculate the point number + /*Get Himax IC Type / FW information / Calculate the point number */ if (himax_check_chip_version(ts->client) == false) { E("Himax chip doesn NOT EXIST"); goto err_ic_package_failed; @@ -1496,10 +1546,9 @@ void himax_ts_init(struct himax_ts_data *ts) if (pdata->virtual_key) ts->button = pdata->virtual_key; -#ifdef HX_TP_PROC_FLASH_DUMP +#ifdef HX_TP_PROC_FLASH_DUMP ts->flash_wq = create_singlethread_workqueue("himax_flash_wq"); - if (!ts->flash_wq) - { + if (!ts->flash_wq) { E("%s: create flash workqueue failed\n", __func__); err = -ENOMEM; goto err_create_wq_failed; @@ -1511,10 +1560,9 @@ void himax_ts_init(struct himax_ts_data *ts) setFlashBuffer(); #endif -#ifdef HX_TP_PROC_DIAG +#ifdef HX_TP_PROC_DIAG ts->himax_diag_wq = create_singlethread_workqueue("himax_diag"); - if (!ts->himax_diag_wq) - { + if (!ts->himax_diag_wq) { E("%s: create diag workqueue failed\n", __func__); err = -ENOMEM; goto err_create_wq_failed; @@ -1526,40 +1574,42 @@ himax_read_FW_ver(client); #ifdef HX_AUTO_UPDATE_FW I(" %s in", __func__); - if(i_update_FW() == false) - I("NOT Have new FW=NOT UPDATE=\n"); + if (i_update_FW() <= 0) + I("FW NOT UPDATE=\n"); else I("Have new FW=UPDATE=\n"); #endif - //Himax Power On and Load Config + /*Himax Power On and Load Config*/ if (himax_loadSensorConfig(client, pdata) < 0) { - E("%s: Load Sesnsor configuration failed, unload driver.\n", __func__); + E("%s: Load Sesnsor config failed,unload driver.\n", + __func__); goto err_detect_failed; } calculate_point_number(); #ifdef HX_TP_PROC_DIAG - setXChannel(ic_data->HX_RX_NUM); // X channel - setYChannel(ic_data->HX_TX_NUM); // Y channel + setXChannel(ic_data->HX_RX_NUM); /*X channel*/ + setYChannel(ic_data->HX_TX_NUM); /*Y channel*/ setMutualBuffer(); setMutualNewBuffer(); setMutualOldBuffer(); if (getMutualBuffer() == NULL) { E("%s: mutual buffer allocate fail failed\n", __func__); - return; + return false; } #ifdef HX_TP_PROC_2T2R - if(Is_2T2R){ - setXChannel_2(ic_data->HX_RX_NUM_2); // X channel - setYChannel_2(ic_data->HX_TX_NUM_2); // Y channel + if (Is_2T2R) { + setXChannel_2(ic_data->HX_RX_NUM_2); /*X channel*/ + setYChannel_2(ic_data->HX_TX_NUM_2); /*Y channel*/ setMutualBuffer_2(); if (getMutualBuffer_2() == NULL) { - E("%s: mutual buffer 2 allocate fail failed\n", __func__); - return; + E("%s: mutual buffer 2 allocate fail failed\n", + __func__); + return false; } } #endif @@ -1572,7 +1622,7 @@ himax_read_FW_ver(client); ts->x_channel = ic_data->HX_RX_NUM; ts->y_channel = ic_data->HX_TX_NUM; ts->nFinger_support = ic_data->HX_MAX_PT; - //calculate the i2c data size + /*calculate the i2c data size*/ calcDataSize(ts->nFinger_support); I("%s: calcDataSize complete\n", __func__); #ifdef CONFIG_OF @@ -1584,14 +1634,13 @@ himax_read_FW_ver(client); pdata->cable_config[1] = 0x00; #endif ts->suspended = false; -#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2) +#if defined(HX_USB_DETECT) || defined(HX_USB_DETECT2) ts->usb_connected = 0x00; ts->cable_config = pdata->cable_config; #endif ts->protocol_type = pdata->protocol_type; I("%s: Use Protocol Type %c\n", __func__, ts->protocol_type == PROTOCOL_TYPE_A ? 'A' : 'B'); - ret = himax_input_register(ts); if (ret) { E("%s: Unable to register %s input device\n", @@ -1599,8 +1648,9 @@ himax_read_FW_ver(client); goto err_input_register_device_failed; } #ifdef HX_SMART_WAKEUP - ts->SMWP_enable=0; - wake_lock_init(&ts->ts_SMWP_wake_lock, WAKE_LOCK_SUSPEND, HIMAX_common_NAME); + ts->SMWP_enable = 0; + wakeup_source_init(&ts->ts_SMWP_wake_lock, + WAKE_LOCK_SUSPEND, HIMAX_common_NAME); ts->himax_smwp_wq = create_singlethread_workqueue("HMX_SMWP_WORK"); if (!ts->himax_smwp_wq) { @@ -1611,7 +1661,7 @@ himax_read_FW_ver(client); INIT_DELAYED_WORK(&ts->smwp_work, himax_SMWP_work); #endif #ifdef HX_HIGH_SENSE - ts->HSEN_enable=0; + ts->HSEN_enable = 0; ts->himax_hsen_wq = create_singlethread_workqueue("HMX_HSEN_WORK"); if (!ts->himax_hsen_wq) { E(" allocate himax_hsen_wq failed\n"); @@ -1633,7 +1683,7 @@ himax_read_FW_ver(client); err = himax_ts_register_interrupt(ts->client); if (err) goto err_register_interrupt_failed; - return; + return true; err_register_interrupt_failed: #ifdef HX_HIGH_SENSE @@ -1641,26 +1691,26 @@ himax_read_FW_ver(client); #endif #ifdef HX_SMART_WAKEUP err_smwp_wq_failed: - wake_lock_destroy(&ts->ts_SMWP_wake_lock); + wakeup_source_trash(&ts->ts_SMWP_wake_lock); #endif err_input_register_device_failed: input_free_device(ts->input_dev); err_detect_failed: -#ifdef HX_TP_PROC_FLASH_DUMP +#ifdef HX_TP_PROC_FLASH_DUMP err_create_wq_failed: #endif err_ic_package_failed: - -return; +return false; } -int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id) +int himax_chip_common_probe(struct i2c_client *client, +const struct i2c_device_id *id) { int err = 0; struct himax_ts_data *ts; struct himax_i2c_platform_data *pdata; - //Check I2C functionality + /*Check I2C functionality*/ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { E("%s: i2c check functionality error\n", __func__); err = -ENODEV; @@ -1677,6 +1727,7 @@ int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_i i2c_set_clientdata(client, ts); ts->client = client; ts->dev = &client->dev; + mutex_init(&ts->rw_lock); pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); if (pdata == NULL) { /*Allocate Platform data space*/ @@ -1691,7 +1742,8 @@ int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_i } #ifdef CONFIG_OF - if (client->dev.of_node) { /*DeviceTree Init Platform_data*/ + /*DeviceTree Init Platform_data*/ + if (client->dev.of_node) { err = himax_parse_dt(ts, pdata); if (err < 0) { I(" pdata is NULL for DT\n"); @@ -1704,12 +1756,11 @@ int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_i ts->rst_gpio = pdata->gpio_reset; #endif -himax_gpio_power_config(ts->client, pdata); + himax_gpio_power_config(ts->client, pdata); err = himax_ts_pinctrl_init(ts); - if (err || ts->ts_pinctrl == NULL) { + if (err || ts->ts_pinctrl == NULL) E(" Pinctrl init failed\n"); - } #ifndef CONFIG_OF if (pdata->power) { @@ -1736,7 +1787,7 @@ himax_gpio_power_config(ts->client, pdata); } #endif - return 0; + return 0; #ifdef CONFIG_FB err_fb_notif_wq_create: @@ -1783,8 +1834,10 @@ int himax_chip_common_remove(struct i2c_client *client) himax_touch_proc_deinit(); #endif #ifdef CONFIG_FB - if (fb_unregister_client(&ts->fb_notif)) - dev_err(&client->dev, "Error occurred while unregistering fb_notifier.\n"); + if (fb_unregister_client(&ts->fb_notif)) { + dev_err(&client->dev, + "Error occurred while unregistering fb_notifier.\n"); + } #endif if (!ts->use_irq) @@ -1810,7 +1863,7 @@ int himax_chip_common_remove(struct i2c_client *client) } } #ifdef HX_SMART_WAKEUP - wake_lock_destroy(&ts->ts_SMWP_wake_lock); + wakeup_source_trash(&ts->ts_SMWP_wake_lock); #endif kfree(ts); @@ -1822,38 +1875,36 @@ int himax_chip_common_suspend(struct himax_ts_data *ts) { int ret; - if(ts->suspended) - { - I("%s: Already suspended. Skipped. \n", __func__); + if (ts->suspended) { + I("%s: Already suspended. Skipped.\n", __func__); return 0; - } - else - { + + } else { ts->suspended = true; - I("%s: enter \n", __func__); + I("%s: enter\n", __func__); } #ifdef HX_TP_PROC_FLASH_DUMP - if (getFlashDumpGoing()) - { - I("[himax] %s: Flash dump is going, reject suspend\n",__func__); + if (getFlashDumpGoing()) { + I("[himax] %s: Flash dump is going,reject suspend\n", + __func__); return 0; } #endif #ifdef HX_TP_PROC_HITOUCH - if(hitouch_is_connect) - { - I("[himax] %s: Hitouch connect, reject suspend\n",__func__); + if (hitouch_is_connect) { + I("[himax] %s: Hitouch connect,reject suspend\n", + __func__); return 0; } #endif #ifdef HX_SMART_WAKEUP - if(ts->SMWP_enable) - { + if (ts->SMWP_enable) { atomic_set(&ts->suspend_mode, 1); ts->pre_finger_mask = 0; - FAKE_POWER_KEY_SEND=false; - I("[himax] %s: SMART_WAKEUP enable, reject suspend\n",__func__); + FAKE_POWER_KEY_SEND = false; + I("[himax] %s: SMART_WAKEUP enable,reject suspend\n", + __func__); return 0; } #endif @@ -1864,19 +1915,18 @@ int himax_chip_common_suspend(struct himax_ts_data *ts) if (!ts->use_irq) { ret = cancel_work_sync(&ts->work); if (ret) - himax_int_enable(ts->client->irq,1); + himax_int_enable(ts->client->irq, 1); } - //ts->first_pressed = 0; + /*ts->first_pressed = 0;*/ atomic_set(&ts->suspend_mode, 1); ts->pre_finger_mask = 0; if (ts->ts_pinctrl) { ret = pinctrl_select_state(ts->ts_pinctrl, ts->pinctrl_state_suspend); - if (ret < 0) { + if (ret < 0) E("Failed to get idle pinctrl state %d\n", ret); - } } if (ts->pdata->powerOff3V3 && ts->pdata->power) @@ -1889,20 +1939,16 @@ int himax_chip_common_resume(struct himax_ts_data *ts) { int retval; - I("%s: enter \n", __func__); + I("%s: enter\n", __func__); if (ts->pdata->powerOff3V3 && ts->pdata->power) ts->pdata->power(1); - - - /*************************************/ + if (ts->protocol_type == PROTOCOL_TYPE_A) - input_mt_sync(ts->input_dev); + input_mt_sync(ts->input_dev); input_report_key(ts->input_dev, BTN_TOUCH, 0); input_sync(ts->input_dev); - /*************************************/ - - + if (ts->ts_pinctrl) { retval = pinctrl_select_state(ts->ts_pinctrl, ts->pinctrl_state_active); @@ -1914,7 +1960,7 @@ int himax_chip_common_resume(struct himax_ts_data *ts) atomic_set(&ts->suspend_mode, 0); - himax_int_enable(ts->client->irq,1); + himax_int_enable(ts->client->irq, 1); ts->suspended = false; #if defined(HX_USB_DETECT2) @@ -1922,10 +1968,12 @@ int himax_chip_common_resume(struct himax_ts_data *ts) himax_cable_detect_func(); #endif #ifdef HX_SMART_WAKEUP - queue_delayed_work(ts->himax_smwp_wq, &ts->smwp_work, msecs_to_jiffies(1000)); + queue_delayed_work(ts->himax_smwp_wq, + &ts->smwp_work, msecs_to_jiffies(1000)); #endif #ifdef HX_HIGH_SENSE - queue_delayed_work(ts->himax_hsen_wq, &ts->hsen_work, msecs_to_jiffies(1000)); + queue_delayed_work(ts->himax_hsen_wq, + &ts->hsen_work, msecs_to_jiffies(1000)); #endif return 0; err_pinctrl_select_resume: diff --git a/drivers/input/touchscreen/hxchipset/himax_common.h b/drivers/input/touchscreen/hxchipset/himax_common.h index 27ce9aafd959..41c97f7b5204 100644 --- a/drivers/input/touchscreen/hxchipset/himax_common.h +++ b/drivers/input/touchscreen/hxchipset/himax_common.h @@ -16,9 +16,13 @@ #ifndef HIMAX_COMMON_H #define HIMAX_COMMON_H +#include "himax_platform.h" + #include -#include -#include +/*#include */ +/*#include */ +#include +#include #include #include @@ -34,9 +38,9 @@ #include #include #include +#include #include #include -#include "himax_platform.h" #if defined(CONFIG_FB) #include @@ -48,7 +52,7 @@ #ifdef CONFIG_OF #include #endif -#define HIMAX_DRIVER_VER "0.2.4.0" +#define HIMAX_DRIVER_VER "0.3.1.0" #define FLASH_DUMP_FILE "/data/user/Flash_Dump.bin" #define DIAG_COORDINATE_FILE "/sdcard/Coordinate_Dump.csv" @@ -62,39 +66,39 @@ #define HX_TP_PROC_SELF_TEST #define HX_TP_PROC_RESET #define HX_TP_PROC_SENSE_ON_OFF -//#define HX_TP_PROC_2T2R +/*#define HX_TP_PROC_2T2R*/ int himax_touch_proc_init(void); void himax_touch_proc_deinit(void); #endif -//===========Himax Option function============= -//#define HX_RST_PIN_FUNC -//#define HX_AUTO_UPDATE_FW -//#define HX_HIGH_SENSE -//#define HX_SMART_WAKEUP -//#define HX_USB_DETECT -//#define HX_ESD_WORKAROUND -//#define HX_USB_DETECT2 - -//#define HX_EN_SEL_BUTTON // Support Self Virtual key ,default is close -#define HX_EN_MUT_BUTTON // Support Mutual Virtual Key ,default is close - -#define HX_KEY_MAX_COUNT 4 -#define DEFAULT_RETRY_CNT 3 - -#define HX_VKEY_0 KEY_BACK -#define HX_VKEY_1 KEY_HOME -#define HX_VKEY_2 KEY_RESERVED -#define HX_VKEY_3 KEY_RESERVED -#define HX_KEY_ARRAY {HX_VKEY_0, HX_VKEY_1, HX_VKEY_2, HX_VKEY_3} +/*===========Himax Option function=============*/ +/*#define HX_RST_PIN_FUNC*/ +#define HX_AUTO_UPDATE_FW +/*#define HX_HIGH_SENSE*/ +/*#define HX_SMART_WAKEUP*/ +/*#define HX_USB_DETECT*/ +/*#define HX_ESD_WORKAROUND*/ +/*#define HX_USB_DETECT2*/ +/*#define HX_EN_SEL_BUTTON*//* Support Self Virtual key ,default is close*/ +#define HX_EN_MUT_BUTTON/* Support Mutual Virtual Key ,default is close*/ +/*#define HX_EN_CHECK_PATCH*/ + +#define HX_KEY_MAX_COUNT 4 +#define DEFAULT_RETRY_CNT 3 + +#define HX_VKEY_0 KEY_BACK +#define HX_VKEY_1 KEY_HOME +#define HX_VKEY_2 KEY_RESERVED +#define HX_VKEY_3 KEY_RESERVED +#define HX_KEY_ARRAY {HX_VKEY_0, HX_VKEY_1, HX_VKEY_2, HX_VKEY_3} #define SHIFTBITS 5 -//#define FLASH_SIZE 131072 -#define FW_SIZE_60k 61440 -#define FW_SIZE_64k 65536 -#define FW_SIZE_124k 126976 -#define FW_SIZE_128k 131072 +/*#define FLASH_SIZE 131072*/ +#define FW_SIZE_60k 61440 +#define FW_SIZE_64k 65536 +#define FW_SIZE_124k 126976 +#define FW_SIZE_128k 131072 struct himax_ic_data { int vendor_fw_ver; @@ -183,12 +187,12 @@ struct himax_ts_data { bool suspended; bool probe_done; struct mutex fb_mutex; + struct mutex rw_lock; atomic_t suspend_mode; uint8_t x_channel; uint8_t y_channel; uint8_t useScreenRes; uint8_t diag_command; - uint8_t protocol_type; uint8_t first_pressed; uint8_t coord_data_size; @@ -198,11 +202,9 @@ struct himax_ts_data { uint8_t nFinger_support; uint8_t irq_enabled; uint8_t diag_self[50]; - uint16_t finger_pressed; uint16_t last_slot; uint16_t pre_finger_mask; - uint32_t debug_log_level; uint32_t widthFactor; uint32_t heightFactor; @@ -214,20 +216,20 @@ struct himax_ts_data { uint32_t pl_x_max; uint32_t pl_y_min; uint32_t pl_y_max; - + int use_irq; int (*power)(int on); int pre_finger_data[10][2]; - + struct device *dev; struct workqueue_struct *himax_wq; struct work_struct work; struct input_dev *input_dev; struct hrtimer timer; struct i2c_client *client; - struct himax_i2c_platform_data *pdata; + struct himax_i2c_platform_data *pdata; struct himax_virtual_key *button; - + #if defined(CONFIG_FB) struct notifier_block fb_notif; #elif defined(CONFIG_HAS_EARLYSUSPEND) @@ -235,8 +237,8 @@ struct himax_ts_data { #endif #ifdef HX_TP_PROC_FLASH_DUMP - struct workqueue_struct *flash_wq; - struct work_struct flash_work; + struct workqueue_struct *flash_wq; + struct work_struct flash_work; #endif #ifdef HX_RST_PIN_FUNC @@ -250,7 +252,7 @@ struct himax_ts_data { #ifdef HX_SMART_WAKEUP uint8_t SMWP_enable; uint8_t gesture_cust_en[16]; - struct wake_lock ts_SMWP_wake_lock; + struct wakeup_source ts_SMWP_wake_lock; struct workqueue_struct *himax_smwp_wq; struct delayed_work smwp_work; #endif @@ -261,7 +263,7 @@ struct himax_ts_data { struct delayed_work hsen_work; #endif -#if defined(HX_USB_DETECT)||defined(HX_USB_DETECT2) +#if defined(HX_USB_DETECT) || defined(HX_USB_DETECT2) uint8_t usb_connected; uint8_t *cable_config; #endif @@ -273,30 +275,30 @@ struct himax_ts_data { struct pinctrl_state *pinctrl_state_release; }; -#define HX_CMD_NOP 0x00 -#define HX_CMD_SETMICROOFF 0x35 -#define HX_CMD_SETROMRDY 0x36 -#define HX_CMD_TSSLPIN 0x80 -#define HX_CMD_TSSLPOUT 0x81 -#define HX_CMD_TSSOFF 0x82 -#define HX_CMD_TSSON 0x83 -#define HX_CMD_ROE 0x85 -#define HX_CMD_RAE 0x86 -#define HX_CMD_RLE 0x87 -#define HX_CMD_CLRES 0x88 -#define HX_CMD_TSSWRESET 0x9E -#define HX_CMD_SETDEEPSTB 0xD7 -#define HX_CMD_SET_CACHE_FUN 0xDD -#define HX_CMD_SETIDLE 0xF2 -#define HX_CMD_SETIDLEDELAY 0xF3 -#define HX_CMD_SELFTEST_BUFFER 0x8D +#define HX_CMD_NOP 0x00 +#define HX_CMD_SETMICROOFF 0x35 +#define HX_CMD_SETROMRDY 0x36 +#define HX_CMD_TSSLPIN 0x80 +#define HX_CMD_TSSLPOUT 0x81 +#define HX_CMD_TSSOFF 0x82 +#define HX_CMD_TSSON 0x83 +#define HX_CMD_ROE 0x85 +#define HX_CMD_RAE 0x86 +#define HX_CMD_RLE 0x87 +#define HX_CMD_CLRES 0x88 +#define HX_CMD_TSSWRESET 0x9E +#define HX_CMD_SETDEEPSTB 0xD7 +#define HX_CMD_SET_CACHE_FUN 0xDD +#define HX_CMD_SETIDLE 0xF2 +#define HX_CMD_SETIDLEDELAY 0xF3 +#define HX_CMD_SELFTEST_BUFFER 0x8D #define HX_CMD_MANUALMODE 0x42 -#define HX_CMD_FLASH_ENABLE 0x43 +#define HX_CMD_FLASH_ENABLE 0x43 #define HX_CMD_FLASH_SET_ADDRESS 0x44 #define HX_CMD_FLASH_WRITE_REGISTER 0x45 #define HX_CMD_FLASH_SET_COMMAND 0x47 #define HX_CMD_FLASH_WRITE_BUFFER 0x48 -#define HX_CMD_FLASH_PAGE_ERASE 0x4D +#define HX_CMD_FLASH_PAGE_ERASE 0x4D #define HX_CMD_FLASH_SECTOR_ERASE 0x4E #define HX_CMD_CB 0xCB #define HX_CMD_EA 0xEA @@ -311,7 +313,7 @@ enum input_protocol_type { }; #ifdef HX_HIGH_SENSE -void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable); +void himax_set_HSEN_func(struct i2c_client *client, uint8_t HSEN_enable); #endif #ifdef HX_SMART_WAKEUP @@ -319,18 +321,18 @@ void himax_set_HSEN_func(struct i2c_client *client,uint8_t HSEN_enable); #define GEST_PTLG_HDR_LEN (4) #define GEST_PTLG_HDR_ID1 (0xCC) #define GEST_PTLG_HDR_ID2 (0x44) -#define GEST_PT_MAX_NUM (128) +#define GEST_PT_MAX_NUM (128) #ifdef HX_GESTURE_TRACK static int gest_pt_cnt; static int gest_pt_x[GEST_PT_MAX_NUM]; static int gest_pt_y[GEST_PT_MAX_NUM]; -static int gest_start_x,gest_start_y,gest_end_x,gest_end_y; -static int gest_width,gest_height,gest_mid_x,gest_mid_y; +static int gest_start_x, gest_start_y, gest_end_x, gest_end_y; +static int gest_width, gest_height, gest_mid_x, gest_mid_y; static int gn_gesture_coor[16]; #endif -void himax_set_SMWP_func(struct i2c_client *client,uint8_t SMWP_enable); +void himax_set_SMWP_func(struct i2c_client *client, uint8_t SMWP_enable); extern bool FAKE_POWER_KEY_SEND; enum gesture_event_type { @@ -380,16 +382,91 @@ irqreturn_t himax_ts_thread(int irq, void *ptr); int himax_input_register(struct himax_ts_data *ts); #endif -extern int himax_chip_common_probe(struct i2c_client *client, const struct i2c_device_id *id); -extern int himax_chip_common_remove(struct i2c_client *client); -extern int himax_chip_common_suspend(struct himax_ts_data *ts); -extern int himax_chip_common_resume(struct himax_ts_data *ts); -int himax_loadSensorConfig(struct i2c_client *client, struct himax_i2c_platform_data *pdata); +int himax_chip_common_probe(struct i2c_client *client, +const struct i2c_device_id *id); +int himax_chip_common_remove(struct i2c_client *client); +int himax_chip_common_suspend(struct himax_ts_data *ts); +int himax_chip_common_resume(struct himax_ts_data *ts); +int himax_loadSensorConfig(struct i2c_client *client, +struct himax_i2c_platform_data *pdata); #ifdef HX_USB_DETECT2 -//extern kal_bool upmu_is_chr_det(void); +/*extern kal_bool upmu_is_chr_det(void);*/ void himax_cable_detect_func(void); #endif +#ifdef HX_AUTO_UPDATE_FW +extern unsigned long FW_VER_MAJ_FLASH_ADDR; +extern unsigned long FW_VER_MIN_FLASH_ADDR; +extern unsigned long CFG_VER_MAJ_FLASH_ADDR; +extern unsigned long CFG_VER_MIN_FLASH_ADDR; +#endif +extern unsigned long FW_VER_MAJ_FLASH_LENG; +extern unsigned long FW_VER_MIN_FLASH_LENG; +extern unsigned long CFG_VER_MAJ_FLASH_LENG; +extern unsigned long CFG_VER_MIN_FLASH_LENG; +extern unsigned char IC_TYPE; +extern unsigned char IC_CHECKSUM; + +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) +extern int himax_touch_proc_init(void); +extern void himax_touch_proc_deinit(void); +/*PROC-START*/ +#ifdef HX_TP_PROC_FLASH_DUMP +extern void himax_ts_flash_func(void); +extern void setFlashBuffer(void); +extern bool getFlashDumpGoing(void); +extern uint8_t getSysOperation(void); +extern void setSysOperation(uint8_t operation); +#endif + +#ifdef HX_TP_PROC_HITOUCH +extern bool hitouch_is_connect; +#endif + +#ifdef HX_TP_PROC_DIAG + extern int touch_monitor_stop_flag; + + extern int touch_monitor_stop_limit; + + extern void himax_ts_diag_func(void); + + extern int16_t *getMutualBuffer(void); + extern int16_t *getMutualNewBuffer(void); + extern int16_t *getMutualOldBuffer(void); + extern int16_t *getSelfBuffer(void); + extern uint8_t getXChannel(void); + extern uint8_t getYChannel(void); + extern uint8_t getDiagCommand(void); + extern void setXChannel(uint8_t x); + extern void setYChannel(uint8_t y); + extern void setMutualBuffer(void); + extern void setMutualNewBuffer(void); + extern void setMutualOldBuffer(void); + extern uint8_t coordinate_dump_enable; + extern struct file *coordinate_fn; + extern uint8_t diag_coor[128]; +#ifdef HX_TP_PROC_2T2R + extern int16_t *getMutualBuffer_2(void); + extern uint8_t getXChannel_2(void); + extern uint8_t getYChannel_2(void); + extern void setXChannel_2(uint8_t x); + extern void setYChannel_2(uint8_t y); + extern void setMutualBuffer_2(void); +#endif +#endif +/*PROC-END*/ +#endif + +#ifdef HX_USB_DETECT2 + extern bool USB_Flag; +#endif +#ifdef HX_ESD_WORKAROUND + extern void HX_report_ESD_event(void); + unsigned char ESD_00_counter = 0; + unsigned char ESD_00_Flag = 0; +#endif +bool himax_ts_init(struct himax_ts_data *ts); + #endif diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.c b/drivers/input/touchscreen/hxchipset/himax_debug.c index f8bee11b4351..55cc7ca92e4c 100644 --- a/drivers/input/touchscreen/hxchipset/himax_debug.c +++ b/drivers/input/touchscreen/hxchipset/himax_debug.c @@ -16,32 +16,16 @@ #include "himax_debug.h" #include "himax_ic.h" -//struct himax_debug_data* debug_data; - -extern struct himax_ic_data* ic_data; -extern struct himax_ts_data *private_ts; -extern unsigned char IC_TYPE; -extern unsigned char IC_CHECKSUM; -extern int himax_input_register(struct himax_ts_data *ts); -#ifdef QCT -extern irqreturn_t himax_ts_thread(int irq, void *ptr); -#endif -#ifdef MTK -#ifdef CONFIG_OF_TOUCH -extern irqreturn_t tpd_eint_interrupt_handler(int irq, void *desc); -#else -extern void tpd_eint_interrupt_handler(void); -#endif -#endif +/*struct himax_debug_data* debug_data;*/ #ifdef HX_TP_PROC_DIAG #ifdef HX_TP_PROC_2T2R -int HX_RX_NUM_2 = 0; -int HX_TX_NUM_2 = 0; +int HX_RX_NUM_2; +int HX_TX_NUM_2; #endif -int touch_monitor_stop_flag = 0; +int touch_monitor_stop_flag; int touch_monitor_stop_limit = 5; -uint8_t g_diag_arr_num = 0; +uint8_t g_diag_arr_num; #endif #ifdef HX_ESD_WORKAROUND @@ -52,11 +36,11 @@ u8 HX_ESD_RESET_ACTIVATE; bool FAKE_POWER_KEY_SEND; #endif -//============================================================================================================= -// -// Segment : Himax PROC Debug Function -// -//============================================================================================================= +/*======================================================== + +Segment : Himax PROC Debug Function + +==========================================================*/ #if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) static ssize_t himax_vendor_read(struct file *file, char *buf, @@ -65,33 +49,26 @@ static ssize_t himax_vendor_read(struct file *file, char *buf, ssize_t ret = 0; char *temp_buf; - if(!HX_PROC_SEND_FLAG) - { + if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } + ret += snprintf(temp_buf, len, + "%s_FW:%#x_CFG:%#x_SensorId:%#x\n", + HIMAX_common_NAME, ic_data->vendor_fw_ver, + ic_data->vendor_config_ver, ic_data->vendor_sensor_id); - ret += snprintf(temp_buf, len, "%s_FW:%#x_CFG:%#x_SensorId:%#x\n", HIMAX_common_NAME, - ic_data->vendor_fw_ver, ic_data->vendor_config_ver, ic_data->vendor_sensor_id); - HX_PROC_SEND_FLAG=1; + HX_PROC_SEND_FLAG = 1; if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return ret; } -static const struct file_operations himax_proc_vendor_ops = -{ +const struct file_operations himax_proc_vendor_ops = { .owner = THIS_MODULE, .read = himax_vendor_read, }; @@ -107,29 +84,21 @@ static ssize_t himax_attn_read(struct file *file, char *buf, if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } - ret += snprintf(temp_buf, len, "attn = %x\n", himax_int_gpio_read(ts_data->pdata->gpio_irq)); + ret += snprintf(temp_buf, len, "attn = %x\n", + himax_int_gpio_read(ts_data->pdata->gpio_irq)); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return ret; } - -static const struct file_operations himax_proc_attn_ops = -{ +const struct file_operations himax_proc_attn_ops = { .owner = THIS_MODULE, .read = himax_attn_read, }; @@ -143,23 +112,16 @@ static ssize_t himax_int_en_read(struct file *file, char *buf, if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } - ret += snprintf(temp_buf, len, "%d ", ts->irq_enabled); - ret += snprintf(temp_buf+ret, len-ret, "\n"); + ret += snprintf(temp_buf, len-1, "%d ", ts->irq_enabled); + ret += snprintf(temp_buf, 1, "\n"); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return ret; } @@ -167,18 +129,15 @@ static ssize_t himax_int_en_write(struct file *file, const char *buff, size_t len, loff_t *pos) { struct himax_ts_data *ts = private_ts; - char buf_tmp[12]= {0}; - int value, ret=0; + char buf_tmp[12] = {0}; + int value, ret = 0; - if (len >= 12) - { + if (len >= 12) { I("%s: no command exceeds 12 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf_tmp, buff, len)) - { return -EFAULT; - } if (buf_tmp[0] == '0') value = false; @@ -188,36 +147,43 @@ static ssize_t himax_int_en_write(struct file *file, const char *buff, return -EINVAL; if (value) { - if(ic_data->HX_INT_IS_EDGE) - { + if (ic_data->HX_INT_IS_EDGE) { #ifdef MTK #ifdef CONFIG_OF_TOUCH - himax_int_enable(ts->client->irq,1); + himax_int_enable(ts->client->irq, 1); #else - //mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE); - //mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN); - mt_eint_registration(ts->client->irq, EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1); + /*mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, + CUST_EINT_TOUCH_PANEL_TYPE); + mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, + CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);*/ + mt_eint_registration(ts->client->irq, + EINTF_TRIGGER_FALLING, tpd_eint_interrupt_handler, 1); #endif #endif #ifdef QCT - ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, ts->client->name, ts); + ret = request_threaded_irq(ts->client->irq, + NULL, himax_ts_thread, + IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + ts->client->name, ts); #endif - } - else - { + } else { #ifdef MTK #ifdef CONFIG_OF_TOUCH - himax_int_enable(ts->client->irq,1); + himax_int_enable(ts->client->irq, 1); #else - //mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_TYPE); - //mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN); - mt_eint_registration(ts->client->irq, EINTF_TRIGGER_LOW, tpd_eint_interrupt_handler, 1); + /*mt_eint_set_sens(CUST_EINT_TOUCH_PANEL_NUM, + CUST_EINT_TOUCH_PANEL_TYPE); + mt_eint_set_hw_debounce(CUST_EINT_TOUCH_PANEL_NUM, + CUST_EINT_TOUCH_PANEL_DEBOUNCE_CN);*/ + mt_eint_registration(ts->client->irq, + EINTF_TRIGGER_LOW, tpd_eint_interrupt_handler, 1); #endif #endif #ifdef QCT - ret = request_threaded_irq(ts->client->irq, NULL, himax_ts_thread, - IRQF_TRIGGER_LOW | IRQF_ONESHOT, ts->client->name, ts); + ret = request_threaded_irq(ts->client->irq, + NULL, himax_ts_thread, + IRQF_TRIGGER_LOW | IRQF_ONESHOT, + ts->client->name, ts); #endif } if (ret == 0) { @@ -225,7 +191,7 @@ static ssize_t himax_int_en_write(struct file *file, const char *buff, irq_enable_count = 1; } } else { - himax_int_enable(ts->client->irq,0); + himax_int_enable(ts->client->irq, 0); free_irq(ts->client->irq, ts); ts->irq_enabled = 0; } @@ -233,8 +199,7 @@ static ssize_t himax_int_en_write(struct file *file, const char *buff, return len; } -static const struct file_operations himax_proc_int_en_ops = -{ +const struct file_operations himax_proc_int_en_ops = { .owner = THIS_MODULE, .read = himax_int_en_read, .write = himax_int_en_write, @@ -249,26 +214,19 @@ static ssize_t himax_layout_read(struct file *file, char *buf, if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } - ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_min); - ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_x_max); - ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_min); - ret += snprintf(temp_buf+ret, len-ret, "%d ", ts->pdata->abs_y_max); - ret += snprintf(temp_buf+ret, len-ret, "\n"); + ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_min); + ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_x_max); + ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_y_min); + ret += snprintf(temp_buf, len, "%d ", ts->pdata->abs_y_max); + ret += snprintf(temp_buf, len, "\n"); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return ret; } @@ -283,17 +241,14 @@ static ssize_t himax_layout_write(struct file *file, const char *buff, int layout[4] = {0}; char buf[80] = {0}; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } - for (i = 0; i < 20; i++) { + for (i = 0 ; i < 20 ; i++) { if (buf[i] == ',' || buf[i] == '\n') { memset(buf_tmp, 0x0, sizeof(buf_tmp)); if (i - j <= 5) @@ -310,20 +265,24 @@ static ssize_t himax_layout_write(struct file *file, const char *buff, } } if (k == 4) { - ts->pdata->abs_x_min=layout[0]; - ts->pdata->abs_x_max=layout[1]; - ts->pdata->abs_y_min=layout[2]; - ts->pdata->abs_y_max=layout[3]; - I("%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + ts->pdata->abs_x_min = layout[0]; + ts->pdata->abs_x_max = layout[1]; + ts->pdata->abs_y_min = layout[2]; + ts->pdata->abs_y_max = layout[3]; + I("%d, %d, %d, %d\n", ts->pdata->abs_x_min, + ts->pdata->abs_x_max, ts->pdata->abs_y_min, + ts->pdata->abs_y_max); input_unregister_device(ts->input_dev); himax_input_register(ts); - } else - I("ERR@%d, %d, %d, %d\n",ts->pdata->abs_x_min, ts->pdata->abs_x_max, ts->pdata->abs_y_min, ts->pdata->abs_y_max); + } else { + I("ERR@%d, %d, %d, %d\n", ts->pdata->abs_x_min, + ts->pdata->abs_x_max, ts->pdata->abs_y_min, + ts->pdata->abs_y_max); + } return len; } -static const struct file_operations himax_proc_layout_ops = -{ +const struct file_operations himax_proc_layout_ops = { .owner = THIS_MODULE, .read = himax_layout_read, .write = himax_layout_write, @@ -335,26 +294,21 @@ static ssize_t himax_debug_level_read(struct file *file, char *buf, struct himax_ts_data *ts_data; size_t ret = 0; char *temp_buf; + ts_data = private_ts; if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } - ret += snprintf(temp_buf, len, "%d\n", ts_data->debug_log_level); + ret += snprintf(temp_buf, len, "%d\n", + ts_data->debug_log_level); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return ret; } @@ -365,29 +319,26 @@ static ssize_t himax_debug_level_write(struct file *file, const char *buff, struct himax_ts_data *ts; char buf_tmp[11]; int i; + ts = private_ts; - if (len >= 12) - { + if (len >= 12) { I("%s: no command exceeds 12 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf_tmp, buff, len)) - { return -EFAULT; - } ts->debug_log_level = 0; - for(i=0; i='0' && buf_tmp[i]<='9' ) - ts->debug_log_level |= (buf_tmp[i]-'0'); - else if( buf_tmp[i]>='A' && buf_tmp[i]<='F' ) - ts->debug_log_level |= (buf_tmp[i]-'A'+10); - else if( buf_tmp[i]>='a' && buf_tmp[i]<='f' ) - ts->debug_log_level |= (buf_tmp[i]-'a'+10); - - if(i!=len-2) + for (i = 0 ; i < len - 1 ; i++) { + if (buf_tmp[i] >= '0' && buf_tmp[i] <= '9') + ts->debug_log_level |= (buf_tmp[i] - '0'); + else if (buf_tmp[i] >= 'A' && buf_tmp[i] <= 'F') + ts->debug_log_level |= (buf_tmp[i]-'A' + 10); + else if (buf_tmp[i] >= 'a' && buf_tmp[i] <= 'f') + ts->debug_log_level |= (buf_tmp[i] - 'a' + 10); + + if (i != len - 2) ts->debug_log_level <<= 4; } @@ -395,8 +346,12 @@ static ssize_t himax_debug_level_write(struct file *file, const char *buff, if (ts->pdata->screenWidth > 0 && ts->pdata->screenHeight > 0 && (ts->pdata->abs_x_max - ts->pdata->abs_x_min) > 0 && (ts->pdata->abs_y_max - ts->pdata->abs_y_min) > 0) { - ts->widthFactor = (ts->pdata->screenWidth << SHIFTBITS)/(ts->pdata->abs_x_max - ts->pdata->abs_x_min); - ts->heightFactor = (ts->pdata->screenHeight << SHIFTBITS)/(ts->pdata->abs_y_max - ts->pdata->abs_y_min); + ts->widthFactor = + (ts->pdata->screenWidth << SHIFTBITS) + / (ts->pdata->abs_x_max - ts->pdata->abs_x_min); + ts->heightFactor = + (ts->pdata->screenHeight << SHIFTBITS) + / (ts->pdata->abs_y_max - ts->pdata->abs_y_min); if (ts->widthFactor > 0 && ts->heightFactor > 0) ts->useScreenRes = 1; else { @@ -415,8 +370,7 @@ static ssize_t himax_debug_level_write(struct file *file, const char *buff, return len; } -static const struct file_operations himax_proc_debug_level_ops = -{ +const struct file_operations himax_proc_debug_level_ops = { .owner = THIS_MODULE, .read = himax_debug_level_read, .write = himax_debug_level_write, @@ -433,35 +387,33 @@ static ssize_t himax_proc_register_read(struct file *file, char *buf, memset(data, 0x00, sizeof(data)); - I("himax_register_show: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]); - if(!HX_PROC_SEND_FLAG) - { + I("himax_register_show: %x,%x,%x,%x\n", register_command[0], + register_command[1], register_command[2], register_command[3]); + + if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } - himax_register_read(private_ts->client, register_command, 1, data); + himax_register_read(private_ts->client, + register_command, 1, data); - ret += snprintf(temp_buf, len, "command: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]); + ret += snprintf(temp_buf, len, "command: %x,%x,%x,%x\n", + register_command[0], register_command[1], + register_command[2], register_command[3]); - for (loop_i = 0; loop_i < 128; loop_i++) { - ret += snprintf(temp_buf+ret, len-ret, "0x%2.2X ", data[loop_i]); + for (loop_i = 0 ; loop_i < 128 ; loop_i++) { + ret += snprintf(temp_buf + ret, + sizeof(data[loop_i]), "0x%2.2X ", data[loop_i]); if ((loop_i % 16) == 15) - ret += snprintf(temp_buf+ret, len-ret, "\n"); + ret += snprintf(temp_buf + ret, 1, "\n"); } - ret += snprintf(temp_buf+ret, len-ret, "\n"); - HX_PROC_SEND_FLAG=1; + ret += snprintf(temp_buf + ret, len, "\n"); + HX_PROC_SEND_FLAG = 1; if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return ret; } @@ -475,40 +427,48 @@ static ssize_t himax_proc_register_write(struct file *file, const char *buff, uint8_t write_da[128]; char buf[80] = {0}; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } memset(buf_tmp, 0x0, sizeof(buf_tmp)); memset(write_da, 0x0, sizeof(write_da)); - I("himax %s \n",buf); + I("himax %s\n", buf); if ((buf[0] == 'r' || buf[0] == 'w') && buf[1] == ':') { if (buf[2] == 'x') { memcpy(buf_tmp, buf + 3, 8); - if (!kstrtoul(buf_tmp, 16, &result)) - { - register_command[0] = (uint8_t)result; - register_command[1] = (uint8_t)(result >> 8); - register_command[2] = (uint8_t)(result >> 16); - register_command[3] = (uint8_t)(result >> 24); - } + if (!kstrtoul(buf_tmp, 16, &result)) { + register_command[0] = + (uint8_t)result; + register_command[1] = + (uint8_t)(result >> 8); + register_command[2] = + (uint8_t)(result >> 16); + register_command[3] = + (uint8_t)(result >> 24); + } base = 11; - I("CMD: %x,%x,%x,%x\n", register_command[0],register_command[1],register_command[2],register_command[3]); + I("CMD: %x,%x,%x,%x\n", register_command[0], + register_command[1], register_command[2], + register_command[3]); - for (loop_i = 0; loop_i < 128 && (base+10)<80; loop_i++) { + for (loop_i = 0 ; loop_i < 128 ; loop_i++) { if (buf[base] == '\n') { if (buf[0] == 'w') { - himax_register_write(private_ts->client, register_command, 1, write_da); - I("CMD: %x, %x, %x, %x, len=%d\n", write_da[0], write_da[1],write_da[2],write_da[3],length); + himax_register_write + (private_ts->client, + register_command + , 1, write_da); + I("CMD:%x, %x, %x, %x,len=%d\n", + write_da[0], write_da[1], + write_da[2], write_da[3], + length); } I("\n"); return len; @@ -518,12 +478,16 @@ static ssize_t himax_proc_register_write(struct file *file, const char *buff, buf_tmp[11] = '\0'; memcpy(buf_tmp, buf + base + 2, 8); if (!kstrtoul(buf_tmp, 16, &result)) { - write_da[loop_i] = (uint8_t)result; - write_da[loop_i+1] = (uint8_t)(result >> 8); - write_da[loop_i+2] = (uint8_t)(result >> 16); - write_da[loop_i+3] = (uint8_t)(result >> 24); + write_da[loop_i] = + (uint8_t)result; + write_da[loop_i+1] = + (uint8_t)(result >> 8); + write_da[loop_i+2] = + (uint8_t)(result >> 16); + write_da[loop_i+3] = + (uint8_t)(result >> 24); } - length+=4; + length += 4; } base += 10; } @@ -532,8 +496,7 @@ static ssize_t himax_proc_register_write(struct file *file, const char *buff, return len; } -static const struct file_operations himax_proc_register_ops = -{ +const struct file_operations himax_proc_register_ops = { .owner = THIS_MODULE, .read = himax_proc_register_read, .write = himax_proc_register_write, @@ -579,15 +542,18 @@ void setYChannel(uint8_t y) } void setMutualBuffer(void) { - diag_mutual = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); + diag_mutual = kzalloc + (x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); } void setMutualNewBuffer(void) { - diag_mutual_new = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); + diag_mutual_new = kzalloc + (x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); } void setMutualOldBuffer(void) { - diag_mutual_old = kzalloc(x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); + diag_mutual_old = kzalloc + (x_channel * y_channel * sizeof(int16_t), GFP_KERNEL); } #ifdef HX_TP_PROC_2T2R @@ -613,94 +579,82 @@ void setYChannel_2(uint8_t y) } void setMutualBuffer_2(void) { - diag_mutual_2 = kzalloc(x_channel_2 * y_channel_2 * sizeof(int16_t), GFP_KERNEL); + diag_mutual_2 = kzalloc + (x_channel_2 * y_channel_2 * sizeof(int16_t), GFP_KERNEL); } #endif static ssize_t himax_diag_arrange_write(struct file *file, const char *buff, size_t len, loff_t *pos) { - //struct himax_ts_data *ts = private_ts; + /*struct himax_ts_data *ts = private_ts;*/ char buf[80] = {0}; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } g_diag_arr_num = buf[0] - '0'; - I("%s: g_diag_arr_num = %d \n", __func__,g_diag_arr_num); + I("%s: g_diag_arr_num = %d\n", __func__, g_diag_arr_num); return len; } -static const struct file_operations himax_proc_diag_arrange_ops = -{ +const struct file_operations himax_proc_diag_arrange_ops = { .owner = THIS_MODULE, .write = himax_diag_arrange_write, }; -static void himax_diag_arrange_print(struct seq_file *s, int i, int j, int transpose) +static void himax_diag_arrange_print +(struct seq_file *s, int i, int j, int transpose) { - if(transpose) - seq_printf(s, "%6d", diag_mutual[ j + i*x_channel]); + if (transpose) + seq_printf(s, "%6d", diag_mutual[j + i * x_channel]); else - seq_printf(s, "%6d", diag_mutual[ i + j*x_channel]); + seq_printf(s, "%6d", diag_mutual[i + j * x_channel]); } -static void himax_diag_arrange_inloop(struct seq_file *s, int in_init,bool transpose, int j) +static void himax_diag_arrange_inloop +(struct seq_file *s, int in_init, bool transpose, int j) { int i; int in_max = 0; - if(transpose) + if (transpose) in_max = y_channel; else in_max = x_channel; - if (in_init > 0) - { - for(i = in_init-1;i >= 0;i--) - { + if (in_init > 0) { + for (i = in_init - 1 ; i >= 0 ; i--) himax_diag_arrange_print(s, i, j, transpose); - } - } - else - { - for (i = 0; i < in_max; i++) - { + } else { + for (i = 0 ; i < in_max ; i++) himax_diag_arrange_print(s, i, j, transpose); - } } } -static void himax_diag_arrange_outloop(struct seq_file *s, int transpose, int out_init, int in_init) +static void himax_diag_arrange_outloop +(struct seq_file *s, int transpose, int out_init, int in_init) { int j; int out_max = 0; - if(transpose) + if (transpose) out_max = x_channel; else out_max = y_channel; - if(out_init > 0) - { - for(j = out_init-1;j >= 0;j--) - { + if (out_init > 0) { + for (j = out_init - 1 ; j >= 0 ; j--) { himax_diag_arrange_inloop(s, in_init, transpose, j); seq_printf(s, " %5d\n", diag_self[j]); } - } - else - { - for(j = 0;j < out_max;j++) - { + } else { + for (j = 0 ; j < out_max ; j++) { himax_diag_arrange_inloop(s, in_init, transpose, j); seq_printf(s, " %5d\n", diag_self[j]); } @@ -709,33 +663,35 @@ static void himax_diag_arrange_outloop(struct seq_file *s, int transpose, int ou static void himax_diag_arrange(struct seq_file *s) { - int bit2,bit1,bit0; + int bit2, bit1, bit0; int i; bit2 = g_diag_arr_num >> 2; bit1 = g_diag_arr_num >> 1 & 0x1; bit0 = g_diag_arr_num & 0x1; - if (g_diag_arr_num < 4) - { - himax_diag_arrange_outloop(s, bit2, bit1 * y_channel, bit0 * x_channel); - for (i = y_channel; i < x_channel + y_channel; i++) { + if (g_diag_arr_num < 4) { + himax_diag_arrange_outloop(s, + bit2, bit1 * y_channel, bit0 * x_channel); + + for (i = y_channel ; i < x_channel + y_channel ; i++) seq_printf(s, "%6d", diag_self[i]); - } - } - else - { - himax_diag_arrange_outloop(s, bit2, bit1 * x_channel, bit0 * y_channel); - for (i = x_channel; i < x_channel + y_channel; i++) { + + } else { + himax_diag_arrange_outloop(s, + bit2, bit1 * x_channel, bit0 * y_channel); + + for (i = x_channel ; i < x_channel + y_channel ; i++) seq_printf(s, "%6d", diag_self[i]); - } + } } static void *himax_diag_seq_start(struct seq_file *s, loff_t *pos) { - if (*pos>=1) return NULL; - return (void *)((unsigned long) *pos+1); + if (*pos >= 1) + return NULL; + return (void *)((unsigned long) *pos + 1); } static void *himax_diag_seq_next(struct seq_file *s, void *v, loff_t *pos) @@ -748,87 +704,96 @@ static void himax_diag_seq_stop(struct seq_file *s, void *v) static int himax_diag_seq_read(struct seq_file *s, void *v) { size_t count = 0; - int32_t loop_i;//,loop_j + int32_t loop_i;/*loop_j*/ uint16_t mutual_num, self_num, width; #ifdef HX_TP_PROC_2T2R - if(Is_2T2R && diag_command == 4) - { + if (Is_2T2R && diag_command == 4) { mutual_num = x_channel_2 * y_channel_2; - self_num = x_channel_2 + y_channel_2; //don't add KEY_COUNT + /*don't add KEY_COUNT*/ + self_num = x_channel_2 + y_channel_2; width = x_channel_2; - seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel_2, y_channel_2); - } - else + seq_printf(s, "ChannelStart: %4d, %4d\n\n", + x_channel_2, y_channel_2); + } else #endif { mutual_num = x_channel * y_channel; - self_num = x_channel + y_channel; //don't add KEY_COUNT + /*don't add KEY_COUNT*/ + self_num = x_channel + y_channel; width = x_channel; - seq_printf(s, "ChannelStart: %4d, %4d\n\n", x_channel, y_channel); + seq_printf(s, "ChannelStart: %4d, %4d\n\n", + x_channel, y_channel); } - // start to show out the raw data in adb shell + /* start to show out the raw data in adb shell*/ if (diag_command >= 1 && diag_command <= 6) { if (diag_command <= 3) { himax_diag_arrange(s); - seq_printf(s, "\n\n"); + seq_puts(s, "\n\n"); #ifdef HX_EN_SEL_BUTTON - seq_printf(s, "\n"); - for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++) - seq_printf(s, "%6d", diag_self[HX_RX_NUM + HX_TX_NUM + loop_i]); + seq_putc(s, '\n'); + for (loop_i = 0 ; loop_i < HX_BT_NUM ; loop_i++) + seq_printf(s, "%6d", + diag_self[HX_RX_NUM + HX_TX_NUM + loop_i]); #endif #ifdef HX_TP_PROC_2T2R - }else if(Is_2T2R && diag_command == 4 ) { - for (loop_i = 0; loop_i < mutual_num; loop_i++) { + } else if (Is_2T2R && diag_command == 4) { + for (loop_i = 0 ; loop_i < mutual_num ; loop_i++) { seq_printf(s, "%4d", diag_mutual_2[loop_i]); if ((loop_i % width) == (width - 1)) - seq_printf(s, " %6d\n", diag_self[width + loop_i/width]); + seq_printf(s, " %6d\n", + diag_self[width + loop_i / width]); } - seq_printf(s, "\n"); - for (loop_i = 0; loop_i < width; loop_i++) { + seq_putc(s, '\n'); + for (loop_i = 0 ; loop_i < width ; loop_i++) { seq_printf(s, "%6d", diag_self[loop_i]); if (((loop_i) % width) == (width - 1)) - seq_printf(s, "\n"); + seq_putc(s, '\n'); } #ifdef HX_EN_SEL_BUTTON - seq_printf(s, "\n"); - for (loop_i = 0; loop_i < HX_BT_NUM; loop_i++) - seq_printf(s, "%4d", diag_self[HX_RX_NUM_2 + HX_TX_NUM_2 + loop_i]); + seq_putc(s, '\n'); + for (loop_i = 0 ; loop_i < HX_BT_NUM ; loop_i++) { + seq_printf(s, "%4d", + diag_self[HX_RX_NUM_2 + HX_TX_NUM_2 + loop_i]); + } #endif #endif } else if (diag_command > 4) { - for (loop_i = 0; loop_i < self_num; loop_i++) { + for (loop_i = 0 ; loop_i < self_num ; loop_i++) { seq_printf(s, "%4d", diag_self[loop_i]); - if (((loop_i - mutual_num) % width) == (width - 1)) - seq_printf(s, "\n"); + if (((loop_i - mutual_num) % width) + == (width - 1)) { + seq_putc(s, '\n'); + } } } else { - for (loop_i = 0; loop_i < mutual_num; loop_i++) { + for (loop_i = 0 ; loop_i < mutual_num ; loop_i++) { seq_printf(s, "%4d", diag_mutual[loop_i]); if ((loop_i % width) == (width - 1)) - seq_printf(s, "\n"); + seq_putc(s, '\n'); } } - seq_printf(s, "ChannelEnd"); - seq_printf(s, "\n"); + seq_puts(s, "ChannelEnd"); + seq_putc(s, '\n'); } else if (diag_command == 7) { - for (loop_i = 0; loop_i < 128 ;loop_i++) { + for (loop_i = 0; loop_i < 128 ; loop_i++) { if ((loop_i % 16) == 0) - seq_printf(s, "LineStart:"); + seq_puts(s, "LineStart:"); seq_printf(s, "%4d", diag_coor[loop_i]); if ((loop_i % 16) == 15) - seq_printf(s, "\n"); + seq_putc(s, '\n'); } - } else if (diag_command == 9 || diag_command == 91 || diag_command == 92){ + } else if (diag_command == 9 || + diag_command == 91 || diag_command == 92) { + himax_diag_arrange(s); - seq_printf(s, "\n"); + seq_putc(s, '\n'); } return count; } -static const struct seq_operations himax_diag_seq_ops = -{ +const struct seq_operations himax_diag_seq_ops = { .start = himax_diag_seq_start, .next = himax_diag_seq_next, .stop = himax_diag_seq_stop, @@ -838,25 +803,24 @@ static int himax_diag_proc_open(struct inode *inode, struct file *file) { return seq_open(file, &himax_diag_seq_ops); }; -bool DSRAM_Flag; +bool DSRAM_Flag = false; -//DSRAM thread +/*DSRAM thread*/ void himax_ts_diag_func(void) { - int i=0, j=0; + int i = 0, j = 0; unsigned int index = 0; int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2; uint8_t info_data[total_size]; - int16_t *mutual_data = NULL; - int16_t *mutual_data_new = NULL; - int16_t *mutual_data_old = NULL; + int16_t *mutual_data; + int16_t *mutual_data_new; + int16_t *mutual_data_old; int16_t new_data; himax_burst_enable(private_ts->client, 1); - if(diag_command == 9 || diag_command == 91) - { + if (diag_command == 9 || diag_command == 91) { mutual_data = getMutualBuffer(); - }else if(diag_command == 92){ + } else if (diag_command == 92) { mutual_data = getMutualBuffer(); mutual_data_new = getMutualNewBuffer(); mutual_data_old = getMutualOldBuffer(); @@ -864,49 +828,63 @@ void himax_ts_diag_func(void) himax_get_DSRAM_data(private_ts->client, info_data); index = 0; - for (i = 0; i < ic_data->HX_TX_NUM; i++) - { - for (j = 0; j < ic_data->HX_RX_NUM; j++) - { - new_data = (short)(info_data[index + 1] << 8 | info_data[index]); - if(diag_command == 9){ - mutual_data[i*ic_data->HX_RX_NUM+j] = new_data; - }else if(diag_command == 91){ //Keep max data for 100 frame - if(mutual_data[i * ic_data->HX_RX_NUM + j] < new_data) - mutual_data[i * ic_data->HX_RX_NUM + j] = new_data; - }else if(diag_command == 92){ //Cal data for [N]-[N-1] frame - mutual_data_new[i * ic_data->HX_RX_NUM + j] = new_data; - mutual_data[i * ic_data->HX_RX_NUM + j] = mutual_data_new[i * ic_data->HX_RX_NUM + j] - mutual_data_old[i * ic_data->HX_RX_NUM + j]; + for (i = 0 ; i < ic_data->HX_TX_NUM ; i++) { + for (j = 0 ; j < ic_data->HX_RX_NUM ; j++) { + new_data = (short)(info_data[index + 1] + << 8 | info_data[index]); + if (diag_command == 9) { + mutual_data[i * ic_data->HX_RX_NUM + j] + = new_data; + /*Keep max data for 100 frame*/ + } else if (diag_command == 91) { + if (mutual_data[i * ic_data->HX_RX_NUM + j] + < new_data) { + mutual_data[i * ic_data->HX_RX_NUM + j] + = new_data; + } + /*Cal data for [N]-[N-1] frame*/ + } else if (diag_command == 92) { + mutual_data_new[i * ic_data->HX_RX_NUM + j] + = new_data; + + mutual_data[i * ic_data->HX_RX_NUM + j] = + mutual_data_new[i * ic_data->HX_RX_NUM + j] - + mutual_data_old[i * ic_data->HX_RX_NUM + j]; } index += 2; } } - if(diag_command == 92){ - memcpy(mutual_data_old,mutual_data_new,x_channel * y_channel * sizeof(int16_t)); //copy N data to N-1 array + /*copy N data to N-1 array*/ + if (diag_command == 92) { + memcpy(mutual_data_old, mutual_data_new, + x_channel * y_channel * sizeof(int16_t)); } + diag_max_cnt++; - if(diag_command == 9 || diag_command == 92){ - queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ); - }else if(diag_command == 91){ - if(diag_max_cnt > 100) //count for 100 frame - { - //Clear DSRAM flag + if (diag_command == 9 || diag_command == 92) { + queue_delayed_work(private_ts->himax_diag_wq, + &private_ts->himax_diag_delay_wrok, 1/10*HZ); + } else if (diag_command == 91) { + if (diag_max_cnt > 100) {/*count for 100 frame*/ + /*Clear DSRAM flag*/ DSRAM_Flag = false; - //Enable ISR - himax_int_enable(private_ts->client->irq,1); + /*Enable ISR*/ + himax_int_enable(private_ts->client->irq, 1); - //===================================== - // test result command : 0x8002_0324 ==> 0x00 - //===================================== + /*===================================== + test result command : 0x8002_0324 ==> 0x00 + =====================================*/ himax_diag_register_set(private_ts->client, 0x00); - }else{ - queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 1/10*HZ); + } else { + queue_delayed_work(private_ts->himax_diag_wq, + &private_ts->himax_diag_delay_wrok, 1 / 10 * HZ); } } } -static ssize_t himax_diag_write(struct file *filp, const char __user *buff, size_t len, loff_t *data) +static ssize_t himax_diag_write +(struct file *filp, const char __user *buff, size_t len, loff_t *data) { char messages[80] = {0}; @@ -915,67 +893,66 @@ static ssize_t himax_diag_write(struct file *filp, const char __user *buff, size memset(receive, 0x00, sizeof(receive)); - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(messages, buff, len)) - { return -EFAULT; - } - if (messages[1] == 0x0A){ - diag_command =messages[0] - '0'; - }else{ - diag_command =(messages[0] - '0')*10 + (messages[1] - '0'); - } - I("[Himax]diag_command=0x%x\n",diag_command); - if (diag_command < 0x04){ - if(DSRAM_Flag) - { - //1. Clear DSRAM flag + if (messages[1] == 0x0A) + diag_command = messages[0] - '0'; + else + diag_command = (messages[0] - '0') * 10 + (messages[1] - '0'); + + + I("[Himax]diag_command=0x%x\n", diag_command); + if (diag_command < 0x04) { + if (DSRAM_Flag) { + /*1. Clear DSRAM flag*/ DSRAM_Flag = false; - //2. Stop DSRAM thread - cancel_delayed_work_sync(&private_ts->himax_diag_delay_wrok); + /*2. Stop DSRAM thread*/ + cancel_delayed_work_sync + (&private_ts->himax_diag_delay_wrok); - //3. Enable ISR - himax_int_enable(private_ts->client->irq,1); + /*3. Enable ISR*/ + himax_int_enable(private_ts->client->irq, 1); } command[0] = diag_command; himax_diag_register_set(private_ts->client, command[0]); - } - //coordinate dump start - else if (diag_command == 0x08) { - E("%s: coordinate_dump_file_create error\n", __func__); - } - else if (diag_command == 0x09 || diag_command == 91 || diag_command == 92){ + /*coordinate dump start*/ + } else if (diag_command == 0x09 || + diag_command == 91 || diag_command == 92) { + diag_max_cnt = 0; - memset(diag_mutual, 0x00, x_channel * y_channel * sizeof(int16_t)); //Set data 0 everytime + /*Set data 0 everytime*/ + memset(diag_mutual, 0x00, + x_channel * y_channel * sizeof(int16_t)); - //1. Disable ISR - himax_int_enable(private_ts->client->irq,0); + /*1. Disable ISR*/ + himax_int_enable(private_ts->client->irq, 0); - //2. Start DSRAM thread - //himax_diag_register_set(private_ts->client, 0x0A); + /*2. Start DSRAM thread*/ + /*himax_diag_register_set(private_ts->client, 0x0A);*/ - queue_delayed_work(private_ts->himax_diag_wq, &private_ts->himax_diag_delay_wrok, 2*HZ/100); + queue_delayed_work(private_ts->himax_diag_wq, + &private_ts->himax_diag_delay_wrok, 2 * HZ / 100); I("%s: Start get raw data in DSRAM\n", __func__); - //3. Set DSRAM flag + /*3. Set DSRAM flag*/ DSRAM_Flag = true; - }else{ + } else { command[0] = 0x00; himax_diag_register_set(private_ts->client, command[0]); - E("[Himax]Diag command error!diag_command=0x%x\n",diag_command); + E("[Himax]Diag command error!diag_command=0x%x\n", + diag_command); } return len; } -static const struct file_operations himax_proc_diag_ops = -{ +const struct file_operations himax_proc_diag_ops = { .owner = THIS_MODULE, .open = himax_diag_proc_open, .read = seq_read, @@ -989,23 +966,20 @@ static ssize_t himax_reset_write(struct file *file, const char *buff, { char buf_tmp[12]; - if (len >= 12) - { + if (len >= 12) { I("%s: no command exceeds 12 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf_tmp, buff, len)) - { return -EFAULT; - } - //if (buf_tmp[0] == '1') - // ESD_HW_REST(); + + /*if (buf_tmp[0] == '1') + ESD_HW_REST();*/ return len; } -static const struct file_operations himax_proc_reset_ops = -{ +const struct file_operations himax_proc_reset_ops = { .owner = THIS_MODULE, .write = himax_reset_write, }; @@ -1018,291 +992,263 @@ static ssize_t himax_debug_read(struct file *file, char *buf, size_t count = 0; char *temp_buf; - if(!HX_PROC_SEND_FLAG) - { + if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf){ - HX_PROC_SEND_FLAG=0; - return count; - } - - if (debug_level_cmd == 't') - { - if (fw_update_complete) - count += snprintf(temp_buf+count, len-count, "FW Update Complete "); - else - { - count += snprintf(temp_buf+count, len-count, "FW Update Fail "); - } - } - else if (debug_level_cmd == 'h') - { - if (handshaking_result == 0) - { - count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Running)\n", handshaking_result); - } - else if (handshaking_result == 1) - { - count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (MCU Stop)\n", handshaking_result); - } - else if (handshaking_result == 2) - { - count += snprintf(temp_buf+count, len-count, "Handshaking Result = %d (I2C Error)\n", handshaking_result); - } - else - { - count += snprintf(temp_buf+count, len-count, "Handshaking Result = error\n"); - } - } - else if (debug_level_cmd == 'v') - { - count += snprintf(temp_buf+count, len-count, "FW_VER = "); - count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_fw_ver); - count += snprintf(temp_buf+count, len-count, "CONFIG_VER = "); - count += snprintf(temp_buf+count, len-count, "0x%2.2X\n", ic_data->vendor_config_ver); - count += snprintf(temp_buf+count, len-count, "\n"); - } - else if (debug_level_cmd == 'd') - { - count += snprintf(temp_buf+count, len-count, "Himax Touch IC Information :\n"); - if (IC_TYPE == HX_85XX_D_SERIES_PWON) - { - count += snprintf(temp_buf+count, len-count, "IC Type : D\n"); - } - else if (IC_TYPE == HX_85XX_E_SERIES_PWON) - { - count += snprintf(temp_buf+count, len-count, "IC Type : E\n"); - } - else if (IC_TYPE == HX_85XX_ES_SERIES_PWON) - { - count += snprintf(temp_buf+count, len-count, "IC Type : ES\n"); - } - else if (IC_TYPE == HX_85XX_F_SERIES_PWON) - { - count += snprintf(temp_buf+count, len-count, "IC Type : F\n"); - } - else - { - count += snprintf(temp_buf+count, len-count, "IC Type error.\n"); + if (debug_level_cmd == 't') { + if (fw_update_complete) { + count += snprintf(temp_buf, len, + "FW Update Complete "); + } else { + count += snprintf(temp_buf, len, + "FW Update Fail "); } - if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_SW) - { - count += snprintf(temp_buf+count, len-count, "IC Checksum : SW\n"); + } else if (debug_level_cmd == 'h') { + if (handshaking_result == 0) { + count += snprintf(temp_buf, len, + "Handshaking Result = %d (MCU Running)\n", + handshaking_result); + } else if (handshaking_result == 1) { + count += snprintf(temp_buf, len, + "Handshaking Result = %d (MCU Stop)\n", + handshaking_result); + } else if (handshaking_result == 2) { + count += snprintf(temp_buf, len, + "Handshaking Result = %d (I2C Error)\n", + handshaking_result); + } else { + count += snprintf(temp_buf, len, + "Handshaking Result = error\n"); } - else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_HW) - { - count += snprintf(temp_buf+count, len-count, "IC Checksum : HW\n"); + } else if (debug_level_cmd == 'v') { + count += snprintf(temp_buf + count, len, + "FW_VER = "); + count += snprintf(temp_buf + count, len, + "0x%2.2X\n", ic_data->vendor_fw_ver); + count += snprintf(temp_buf + count, len, + "CONFIG_VER = "); + count += snprintf(temp_buf + count, len, + "0x%2.2X\n", ic_data->vendor_config_ver); + count += snprintf(temp_buf + count, len, + "\n"); + } else if (debug_level_cmd == 'd') { + count += snprintf(temp_buf + count, len, + "Himax Touch IC Information :\n"); + if (IC_TYPE == HX_85XX_D_SERIES_PWON) { + count += snprintf(temp_buf + count, len, + "IC Type : D\n"); + } else if (IC_TYPE == HX_85XX_E_SERIES_PWON) { + count += snprintf(temp_buf + count, len, + "IC Type : E\n"); + } else if (IC_TYPE == HX_85XX_ES_SERIES_PWON) { + count += snprintf(temp_buf + count, len, + "IC Type : ES\n"); + } else if (IC_TYPE == HX_85XX_F_SERIES_PWON) { + count += snprintf(temp_buf + count, len, + "IC Type : F\n"); + } else { + count += snprintf(temp_buf + count, len, + "IC Type error.\n"); } - else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_CRC) - { - count += snprintf(temp_buf+count, len-count, "IC Checksum : CRC\n"); + if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_SW) { + count += snprintf(temp_buf + count, len, + "IC Checksum : SW\n"); + } else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_HW) { + count += snprintf(temp_buf + count, len, + "IC Checksum : HW\n"); + } else if (IC_CHECKSUM == HX_TP_BIN_CHECKSUM_CRC) { + count += snprintf(temp_buf + count, len, + "IC Checksum : CRC\n"); + } else { + count += snprintf(temp_buf + count, len, + "IC Checksum error.\n"); } - else - { - count += snprintf(temp_buf+count, len-count, "IC Checksum error.\n"); + if (ic_data->HX_INT_IS_EDGE) { + count += snprintf(temp_buf + count, len, + "Interrupt : EDGE TIRGGER\n"); + } else { + count += snprintf(temp_buf + count, len, + "Interrupt : LEVEL TRIGGER\n"); } - - if (ic_data->HX_INT_IS_EDGE) - { - count += snprintf(temp_buf+count, len-count, "Interrupt : EDGE TIRGGER\n"); - } - else - { - count += snprintf(temp_buf+count, len-count, "Interrupt : LEVEL TRIGGER\n"); - } - - count += snprintf(temp_buf+count, len-count, "RX Num : %d\n", ic_data->HX_RX_NUM); - count += snprintf(temp_buf+count, len-count, "TX Num : %d\n", ic_data->HX_TX_NUM); - count += snprintf(temp_buf+count, len-count, "BT Num : %d\n", ic_data->HX_BT_NUM); - count += snprintf(temp_buf+count, len-count, "X Resolution : %d\n", ic_data->HX_X_RES); - count += snprintf(temp_buf+count, len-count, "Y Resolution : %d\n", ic_data->HX_Y_RES); - count += snprintf(temp_buf+count, len-count, "Max Point : %d\n", ic_data->HX_MAX_PT); - count += snprintf(temp_buf+count, len-count, "XY reverse : %d\n", ic_data->HX_XY_REVERSE); + count += snprintf(temp_buf + count, len, + "RX Num : %d\n", ic_data->HX_RX_NUM); + count += snprintf(temp_buf + count, len, + "TX Num : %d\n", ic_data->HX_TX_NUM); + count += snprintf(temp_buf + count, len, + "BT Num : %d\n", ic_data->HX_BT_NUM); + count += snprintf(temp_buf + count, len, + "X Resolution : %d\n", ic_data->HX_X_RES); + count += snprintf(temp_buf + count, len, + "Y Resolution : %d\n", ic_data->HX_Y_RES); + count += snprintf(temp_buf + count, len, + "Max Point : %d\n", ic_data->HX_MAX_PT); + count += snprintf(temp_buf + count, len, + "XY reverse : %d\n", ic_data->HX_XY_REVERSE); #ifdef HX_TP_PROC_2T2R - if(Is_2T2R) - { - count += snprintf(temp_buf+count, len-count, "2T2R panel\n"); - count += snprintf(temp_buf+count, len-count, "RX Num_2 : %d\n", HX_RX_NUM_2); - count += snprintf(temp_buf+count, len-count, "TX Num_2 : %d\n", HX_TX_NUM_2); + if (Is_2T2R) { + count += snprintf(temp_buf + count, len, + "2T2R panel\n"); + count += snprintf(temp_buf + count, len, + "RX Num_2 : %d\n", HX_RX_NUM_2); + count += snprintf(temp_buf + count, len, + "TX Num_2 : %d\n", HX_TX_NUM_2); } #endif - } - else if (debug_level_cmd == 'i') - { - count += snprintf(temp_buf+count, len-count, "Himax Touch Driver Version:\n"); - count += snprintf(temp_buf+count, len-count, "%s\n", HIMAX_DRIVER_VER); + } else if (debug_level_cmd == 'i') { + count += snprintf(temp_buf + count, len, + "Himax Touch Driver Version:\n"); + count += snprintf(temp_buf + count, len, + "%s\n", HIMAX_DRIVER_VER); } if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); - HX_PROC_SEND_FLAG=1; - } - else - HX_PROC_SEND_FLAG=0; + HX_PROC_SEND_FLAG = 1; + } else + HX_PROC_SEND_FLAG = 0; return count; } static ssize_t himax_debug_write(struct file *file, const char *buff, size_t len, loff_t *pos) { - const struct firmware *fw = NULL; - unsigned char *fw_data = NULL; + int result = 0; char fileName[128]; char buf[80] = {0}; - int result; + const struct firmware *fw = NULL; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } - if ( buf[0] == 'h') //handshaking - { + if (buf[0] == 'h') {/*handshaking*/ debug_level_cmd = buf[0]; - himax_int_enable(private_ts->client->irq,0); + himax_int_enable(private_ts->client->irq, 0); - handshaking_result = himax_hand_shaking(private_ts->client); //0:Running, 1:Stop, 2:I2C Fail + /*0:Running, 1:Stop, 2:I2C Fail*/ + handshaking_result = himax_hand_shaking(private_ts->client); - himax_int_enable(private_ts->client->irq,1); + himax_int_enable(private_ts->client->irq, 1); return len; - } - - else if ( buf[0] == 'v') //firmware version - { + } else if (buf[0] == 'v') { /*firmware version*/ debug_level_cmd = buf[0]; - himax_int_enable(private_ts->client->irq,0); + himax_int_enable(private_ts->client->irq, 0); #ifdef HX_RST_PIN_FUNC - himax_HW_reset(false,false); + himax_HW_reset(false, false); #endif himax_read_FW_ver(private_ts->client); - //himax_check_chip_version(); + /*himax_check_chip_version();*/ #ifdef HX_RST_PIN_FUNC - himax_HW_reset(true,false); + himax_HW_reset(true, false); #endif - himax_int_enable(private_ts->client->irq,1); + himax_int_enable(private_ts->client->irq, 1); return len; - } + } else if (buf[0] == 'd') { /*ic information*/ - else if ( buf[0] == 'd') //ic information - { debug_level_cmd = buf[0]; return len; - } + } else if (buf[0] == 'i') {/*driver version*/ - else if ( buf[0] == 'i') //driver version - { debug_level_cmd = buf[0]; return len; - } - - else if (buf[0] == 't') - { + } else if (buf[0] == 't') { - himax_int_enable(private_ts->client->irq,0); + himax_int_enable(private_ts->client->irq, 0); + debug_level_cmd = buf[0]; + fw_update_complete = false; - debug_level_cmd = buf[0]; - fw_update_complete = false; + result = himax_load_CRC_bin_file(private_ts->client); + if (result < 0) { + E("%s: himax_load_CRC_bin_file fail Error Code=%d.\n", + __func__, result); + return result; + } memset(fileName, 0, 128); - // parse the file name +/* parse the file name*/ snprintf(fileName, len-4, "%s", &buf[4]); I("%s: upgrade from file(%s) start!\n", __func__, fileName); - // open file result = request_firmware(&fw, fileName, private_ts->dev); - if (result) { - E("%s: open firmware file failed\n", __func__); - goto firmware_upgrade_done; - //return len; - } - - I("%s: FW len %d\n", __func__, fw->size); - fw_data = (unsigned char *)fw->data; - - I("%s: FW image,len %d: %02X, %02X, %02X, %02X\n", __func__, result, upgrade_fw[0], upgrade_fw[1], upgrade_fw[2], upgrade_fw[3]); - - if (fw_data != NULL) - { - // start to upgrade - himax_int_enable(private_ts->client->irq,0); - - if ((buf[1] == '6') && (buf[2] == '0')) - { - if (fts_ctpm_fw_upgrade_with_sys_fs_60k(private_ts->client,upgrade_fw, result, false) == 0) - { - E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + if (result < 0) { + I("fail to request_firmware fwpath: %s (ret:%d)\n", + fileName, result); + return result; + } + I("%s: FW image: %02X, %02X, %02X, %02X ret=%d\n", __func__, + fw->data[0], fw->data[1], fw->data[2], fw->data[3], result); + if (result >= 0) { + /*start to upgrade*/ + himax_int_enable(private_ts->client->irq, 0); + + if ((buf[1] == '6') && (buf[2] == '0')) { + if (fts_ctpm_fw_upgrade_with_sys_fs_60k + (private_ts->client, (unsigned char *)fw->data, + fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", + __func__, __LINE__); fw_update_complete = false; - } - else - { - I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + } else { + I("%s: TP upgrade OK, line: %d\n", + __func__, __LINE__); fw_update_complete = true; } - } - else if ((buf[1] == '6') && (buf[2] == '4')) - { - if (fts_ctpm_fw_upgrade_with_sys_fs_64k(private_ts->client,upgrade_fw, result, false) == 0) - { - E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + } else if ((buf[1] == '6') && (buf[2] == '4')) { + if (fts_ctpm_fw_upgrade_with_sys_fs_64k + (private_ts->client, (unsigned char *)fw->data, + fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", + __func__, __LINE__); fw_update_complete = false; - } - else - { - I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + } else { + I("%s: TP upgrade OK, line: %d\n", + __func__, __LINE__); fw_update_complete = true; } - } - else if ((buf[1] == '2') && (buf[2] == '4')) - { - if (fts_ctpm_fw_upgrade_with_sys_fs_124k(private_ts->client,upgrade_fw, result, false) == 0) - { - E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + } else if ((buf[1] == '2') && (buf[2] == '4')) { + if (fts_ctpm_fw_upgrade_with_sys_fs_124k + (private_ts->client, (unsigned char *)fw->data, + fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", + __func__, __LINE__); fw_update_complete = false; - } - else - { - I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + } else { + I("%s: TP upgrade OK, line: %d\n", + __func__, __LINE__); fw_update_complete = true; } - } - else if ((buf[1] == '2') && (buf[2] == '8')) - { - if (fts_ctpm_fw_upgrade_with_sys_fs_128k(private_ts->client,upgrade_fw, result, false) == 0) - { - E("%s: TP upgrade error, line: %d\n", __func__, __LINE__); + } else if ((buf[1] == '2') && (buf[2] == '8')) { + if (fts_ctpm_fw_upgrade_with_sys_fs_128k + (private_ts->client, (unsigned char *)fw->data, + fw->size, false) == 0) { + E("%s: TP upgrade error, line: %d\n", + __func__, __LINE__); fw_update_complete = false; - } - else - { - I("%s: TP upgrade OK, line: %d\n", __func__, __LINE__); + } else { + I("%s: TP upgrade OK, line: %d\n", + __func__, __LINE__); fw_update_complete = true; } - } - else - { - E("%s: Flash command fail: %d\n", __func__, __LINE__); + } else { + E("%s: Flash command fail: %d\n", + __func__, __LINE__); fw_update_complete = false; } release_firmware(fw); goto firmware_upgrade_done; - //return count; + /*return count;*/ } } - firmware_upgrade_done: +firmware_upgrade_done: #ifdef HX_RST_PIN_FUNC - himax_HW_reset(true,false); + himax_HW_reset(true, false); #endif himax_sense_on(private_ts->client, 0x01); @@ -1310,16 +1256,15 @@ static ssize_t himax_debug_write(struct file *file, const char *buff, #ifdef HX_ESD_WORKAROUND HX_ESD_RESET_ACTIVATE = 1; #endif - himax_int_enable(private_ts->client->irq,1); + himax_int_enable(private_ts->client->irq, 1); - //todo himax_chip->tp_firmware_upgrade_proceed = 0; - //todo himax_chip->suspend_state = 0; - //todo enable_irq(himax_chip->irq); + /*todo himax_chip->tp_firmware_upgrade_proceed = 0; + todo himax_chip->suspend_state = 0; + todo enable_irq(himax_chip->irq);*/ return len; } -static const struct file_operations himax_proc_debug_ops = -{ +const struct file_operations himax_proc_debug_ops = { .owner = THIS_MODULE, .read = himax_debug_read, .write = himax_debug_write, @@ -1376,9 +1321,9 @@ bool getFlashDumpGoing(void) void setFlashBuffer(void) { - flash_buffer = kzalloc(Flash_Size * sizeof(uint8_t), GFP_KERNEL); - if (flash_buffer) - memset(flash_buffer,0x00,Flash_Size); + flash_buffer = kzalloc + (Flash_Size * sizeof(uint8_t), GFP_KERNEL); + memset(flash_buffer, 0x00, Flash_Size); } void setSysOperation(uint8_t operation) @@ -1389,7 +1334,8 @@ void setSysOperation(uint8_t operation) static void setFlashDumpProgress(uint8_t progress) { flash_progress = progress; - //I("setFlashDumpProgress : progress = %d ,flash_progress = %d \n",progress,flash_progress); + /*I("setFlashDumpProgress : progress = %d , + flash_progress = %d\n",progress,flash_progress);*/ } static void setFlashDumpComplete(uint8_t status) @@ -1432,130 +1378,113 @@ static ssize_t himax_proc_flash_read(struct file *file, char *buf, { int ret = 0; int loop_i; - uint8_t local_flash_read_step=0; + uint8_t local_flash_read_step = 0; uint8_t local_flash_complete = 0; uint8_t local_flash_progress = 0; uint8_t local_flash_command = 0; uint8_t local_flash_fail = 0; char *temp_buf; + local_flash_complete = getFlashDumpComplete(); local_flash_progress = getFlashDumpProgress(); local_flash_command = getFlashCommand(); local_flash_fail = getFlashDumpFail(); - I("flash_progress = %d \n",local_flash_progress); - if(!HX_PROC_SEND_FLAG) - { + I("flash_progress = %d\n", local_flash_progress); + if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } - - if (local_flash_fail) - { - ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Fail \n"); - ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); - ret += snprintf(temp_buf+ret, len-ret, "\n"); + if (local_flash_fail) { + ret += snprintf(temp_buf + ret, len, + "FlashStart:Fail\n"); + ret += snprintf(temp_buf + ret, len, + "FlashEnd"); + ret += snprintf(temp_buf + ret, len, + "\n"); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; return ret; } - if (!local_flash_complete) - { - ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Ongoing:0x%2.2x \n",flash_progress); - ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); - ret += snprintf(temp_buf+ret, len-ret, "\n"); + if (!local_flash_complete) { + ret += snprintf(temp_buf+ret, len, + "FlashStart:Ongoing:0x%2.2x\n", flash_progress); + ret += snprintf(temp_buf + ret, len, "FlashEnd"); + ret += snprintf(temp_buf + ret, len, "\n"); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; return ret; } - if (local_flash_command == 1 && local_flash_complete) - { - ret += snprintf(temp_buf+ret, len-ret, "FlashStart:Complete \n"); - ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); - ret += snprintf(temp_buf+ret, len-ret, "\n"); + if (local_flash_command == 1 && local_flash_complete) { + ret += snprintf(temp_buf+ret, len, + "FlashStart:Complete\n"); + ret += snprintf(temp_buf + ret, len, "FlashEnd"); + ret += snprintf(temp_buf + ret, len, "\n"); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; return ret; } - if (local_flash_command == 3 && local_flash_complete) - { - ret += snprintf(temp_buf+ret, len-ret, "FlashStart: \n"); - for(loop_i = 0; loop_i < 128; loop_i++) - { - ret += snprintf(temp_buf+ret, len-ret, "x%2.2x", flash_buffer[loop_i]); + if (local_flash_command == 3 && local_flash_complete) { + ret += snprintf(temp_buf+ret, len, "FlashStart:\n"); + for (loop_i = 0 ; loop_i < 128 ; loop_i++) { + ret += snprintf(temp_buf + ret, len, + "x%2.2x", flash_buffer[loop_i]); if ((loop_i % 16) == 15) - { - ret += snprintf(temp_buf+ret, len-ret, "\n"); - } + ret += snprintf(temp_buf + ret, len, + "\n"); } - ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); - ret += snprintf(temp_buf+ret, len-ret, "\n"); + ret += snprintf(temp_buf + ret, len, "FlashEnd"); + ret += snprintf(temp_buf + ret, len, "\n"); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; return ret; } - //flash command == 0 , report the data + /*flash command == 0 , report the data*/ local_flash_read_step = getFlashReadStep(); - ret += snprintf(temp_buf+ret, len-ret, "FlashStart:%2.2x \n",local_flash_read_step); + ret += snprintf(temp_buf + ret, len, + "FlashStart:%2.2x\n", local_flash_read_step); - for (loop_i = 0; loop_i < 1024; loop_i++) - { - ret += snprintf(temp_buf+ret, len-ret, "x%2.2X", flash_buffer[local_flash_read_step*1024 + loop_i]); + for (loop_i = 0 ; loop_i < 1024 ; loop_i++) { + ret += snprintf(temp_buf + ret, len, "x%2.2X", + flash_buffer[local_flash_read_step * 1024 + loop_i]); if ((loop_i % 16) == 15) - { - ret += snprintf(temp_buf+ret, len-ret, "\n"); - } + ret += snprintf(temp_buf + ret, len, "\n"); } - ret += snprintf(temp_buf+ret, len-ret, "FlashEnd"); - ret += snprintf(temp_buf+ret, len-ret, "\n"); + ret += snprintf(temp_buf + ret, len, "FlashEnd"); + ret += snprintf(temp_buf + ret, len, "\n"); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return ret; } -static ssize_t himax_proc_flash_write(struct file *file, const char *buff, - size_t len, loff_t *pos) +static ssize_t himax_proc_flash_write(struct file *file, +const char *buff, size_t len, loff_t *pos) { char buf_tmp[6]; unsigned long result = 0; @@ -1563,85 +1492,74 @@ static ssize_t himax_proc_flash_write(struct file *file, const char *buff, int base = 0; char buf[80] = {0}; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } memset(buf_tmp, 0x0, sizeof(buf_tmp)); I("%s: buf[0] = %s\n", __func__, buf); - if (getSysOperation() == 1) - { + if (getSysOperation() == 1) { E("%s: PROC is busy , return!\n", __func__); return len; } - if (buf[0] == '0') - { + if (buf[0] == '0') { setFlashCommand(0); - if (buf[1] == ':' && buf[2] == 'x') - { + if (buf[1] == ':' && buf[2] == 'x') { memcpy(buf_tmp, buf + 3, 2); I("%s: read_Step = %s\n", __func__, buf_tmp); - if (!kstrtoul(buf_tmp, 16, &result)) - { - I("%s: read_Step = %lu \n", __func__, result); + if (!kstrtoul(buf_tmp, 16, &result)) { + I("%s: read_Step = %lu\n", __func__, result); setFlashReadStep(result); } } - } - else if (buf[0] == '1')// 1_60,1_64,1_24,1_28 for flash size 60k,64k,124k,128k - { + /* 1_60,1_64,1_24,1_28 for flash size 60k,64k,124k,128k*/ + } else if (buf[0] == '1') { + setSysOperation(1); setFlashCommand(1); setFlashDumpProgress(0); setFlashDumpComplete(0); setFlashDumpFail(0); - if ((buf[1] == '_' ) && (buf[2] == '6' )){ - if (buf[3] == '0'){ + if ((buf[1] == '_') && (buf[2] == '6')) { + if (buf[3] == '0') Flash_Size = FW_SIZE_60k; - }else if (buf[3] == '4'){ + else if (buf[3] == '4') Flash_Size = FW_SIZE_64k; - } - }else if ((buf[1] == '_' ) && (buf[2] == '2' )){ - if (buf[3] == '4'){ + + } else if ((buf[1] == '_') && (buf[2] == '2')) { + if (buf[3] == '4') Flash_Size = FW_SIZE_124k; - }else if (buf[3] == '8'){ + else if (buf[3] == '8') Flash_Size = FW_SIZE_128k; - } } queue_work(private_ts->flash_wq, &private_ts->flash_work); - } - else if (buf[0] == '2') // 2_60,2_64,2_24,2_28 for flash size 60k,64k,124k,128k - { + /* 2_60,2_64,2_24,2_28 for flash size 60k,64k,124k,128k*/ + } else if (buf[0] == '2') { setSysOperation(1); setFlashCommand(2); setFlashDumpProgress(0); setFlashDumpComplete(0); setFlashDumpFail(0); - if ((buf[1] == '_' ) && (buf[2] == '6' )){ - if (buf[3] == '0'){ + if ((buf[1] == '_') && (buf[2] == '6')) { + if (buf[3] == '0') Flash_Size = FW_SIZE_60k; - }else if (buf[3] == '4'){ + else if (buf[3] == '4') Flash_Size = FW_SIZE_64k; - } - }else if ((buf[1] == '_' ) && (buf[2] == '2' )){ - if (buf[3] == '4'){ + + } else if ((buf[1] == '_') && (buf[2] == '2')) { + if (buf[3] == '4') Flash_Size = FW_SIZE_124k; - }else if (buf[3] == '8'){ + else if (buf[3] == '8') Flash_Size = FW_SIZE_128k; - } + } queue_work(private_ts->flash_wq, &private_ts->flash_work); - } - else if (buf[0] == '3') - { + } else if (buf[0] == '3') { setSysOperation(1); setFlashCommand(3); setFlashDumpProgress(0); @@ -1650,20 +1568,14 @@ static ssize_t himax_proc_flash_write(struct file *file, const char *buff, memcpy(buf_tmp, buf + 3, 2); if (!kstrtoul(buf_tmp, 16, &result)) - { setFlashDumpSector(result); - } memcpy(buf_tmp, buf + 7, 2); if (!kstrtoul(buf_tmp, 16, &result)) - { setFlashDumpPage(result); - } queue_work(private_ts->flash_wq, &private_ts->flash_work); - } - else if (buf[0] == '4') - { + } else if (buf[0] == '4') { I("%s: command 4 enter.\n", __func__); setSysOperation(1); setFlashCommand(4); @@ -1673,40 +1585,29 @@ static ssize_t himax_proc_flash_write(struct file *file, const char *buff, memcpy(buf_tmp, buf + 3, 2); if (!kstrtoul(buf_tmp, 16, &result)) - { setFlashDumpSector(result); - } else - { E("%s: command 4 , sector error.\n", __func__); return len; - } + memcpy(buf_tmp, buf + 7, 2); if (!kstrtoul(buf_tmp, 16, &result)) - { setFlashDumpPage(result); - } else - { E("%s: command 4 , page error.\n", __func__); return len; - } base = 11; I("=========Himax flash page buffer start=========\n"); - for(loop_i=0;loop_i<128 && base<80;loop_i++) - { + for (loop_i = 0 ; loop_i < 128 ; loop_i++) { memcpy(buf_tmp, buf + base, 2); - if (!kstrtoul(buf_tmp, 16, &result)) - { + if (!kstrtoul(buf_tmp, 16, &result)) { flash_buffer[loop_i] = result; - I("%d ",flash_buffer[loop_i]); + I("%d ", flash_buffer[loop_i]); if (loop_i % 16 == 15) - { I("\n"); - } } base += 3; } @@ -1717,8 +1618,7 @@ static ssize_t himax_proc_flash_write(struct file *file, const char *buff, return len; } -static const struct file_operations himax_proc_flash_ops = -{ +const struct file_operations himax_proc_flash_ops = { .owner = THIS_MODULE, .read = himax_proc_flash_read, .write = himax_proc_flash_write, @@ -1728,31 +1628,44 @@ void himax_ts_flash_func(void) { uint8_t local_flash_command = 0; - himax_int_enable(private_ts->client->irq,0); + himax_int_enable(private_ts->client->irq, 0); setFlashDumpGoing(true); - //sector = getFlashDumpSector(); - //page = getFlashDumpPage(); + /*sector = getFlashDumpSector();*/ + /*page = getFlashDumpPage();*/ local_flash_command = getFlashCommand(); msleep(100); - I("%s: local_flash_command = %d enter.\n", __func__,local_flash_command); + I("%s: local_flash_command = %d enter.\n", + __func__, local_flash_command); - if ((local_flash_command == 1 || local_flash_command == 2)|| (local_flash_command==0x0F)) - { - himax_flash_dump_func(private_ts->client, local_flash_command,Flash_Size, flash_buffer); + if ((local_flash_command == 1 || local_flash_command == 2) + || (local_flash_command == 0x0F)) { + himax_flash_dump_func(private_ts->client, + local_flash_command, Flash_Size, flash_buffer); } + I("Complete~~~~~~~~~~~~~~~~~~~~~~~\n"); - if (local_flash_command == 2) - { - E("Flash dump failed\n"); + if (local_flash_command == 2) { + struct file *fn; + struct filename *vts_name; + + vts_name = getname_kernel(FLASH_DUMP_FILE); + fn = file_open_name(vts_name, O_CREAT | O_WRONLY, 0); + if (!IS_ERR(fn)) { + I("%s create file and ready to write\n", __func__); + fn->f_op->write(fn, flash_buffer, + Flash_Size * sizeof(uint8_t), &fn->f_pos); + + filp_close(fn, NULL); + } } - himax_int_enable(private_ts->client->irq,1); + himax_int_enable(private_ts->client->irq, 1); setFlashDumpGoing(false); setFlashDumpComplete(1); @@ -1761,7 +1674,7 @@ void himax_ts_flash_func(void) /* Flash_Dump_i2c_transfer_error: - himax_int_enable(private_ts->client->irq,1); + himax_int_enable(private_ts->client->irq, 1); setFlashDumpGoing(false); setFlashDumpComplete(0); setFlashDumpFail(1); @@ -1776,53 +1689,47 @@ void himax_ts_flash_func(void) static ssize_t himax_self_test_read(struct file *file, char *buf, size_t len, loff_t *pos) { - int val=0x00; + int val = 0x00; int ret = 0; char *temp_buf; - I("%s: enter, %d \n", __func__, __LINE__); - if(!HX_PROC_SEND_FLAG) - { + I("%s:enter, %d\n", __func__, __LINE__); + if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } - himax_int_enable(private_ts->client->irq,0);//disable irq + himax_int_enable(private_ts->client->irq, 0);/*disable irq*/ val = himax_chip_self_test(private_ts->client); #ifdef HX_ESD_WORKAROUND HX_ESD_RESET_ACTIVATE = 1; #endif - himax_int_enable(private_ts->client->irq,1);//enable irq + himax_int_enable(private_ts->client->irq, 1);/*enable irq*/ if (val == 0x01) { - ret += snprintf(temp_buf+ret, len-ret, "Self_Test Pass\n"); + ret += snprintf(temp_buf + ret, len, + "Self_Test Pass\n"); } else { - ret += snprintf(temp_buf+ret, len-ret, "Self_Test Fail\n"); + ret += snprintf(temp_buf + ret, len, + "Self_Test Fail\n"); } - if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return ret; } /* -static ssize_t himax_chip_self_test_store(struct device *dev,struct device_attribute *attr, const char *buf, size_t count) +static ssize_t himax_chip_self_test_store(struct device *dev, +struct device_attribute *attr, const char *buf, size_t count) { char buf_tmp[2]; unsigned long result = 0; memset(buf_tmp, 0x0, sizeof(buf_tmp)); memcpy(buf_tmp, buf, 2); - if(!kstrtoul(buf_tmp, 16, &result)) + if (!kstrtoul(buf_tmp, 16, &result)) { sel_type = (uint8_t)result; } @@ -1831,8 +1738,7 @@ static ssize_t himax_chip_self_test_store(struct device *dev,struct device_attri } */ -static const struct file_operations himax_proc_self_test_ops = -{ +const struct file_operations himax_proc_self_test_ops = { .owner = THIS_MODULE, .read = himax_self_test_read, }; @@ -1844,42 +1750,33 @@ static ssize_t himax_sense_on_off_write(struct file *file, const char *buff, { char buf[80] = {0}; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } - if(buf[0] == '0') - { + if (buf[0] == '0') { himax_sense_off(private_ts->client); - I("Sense off \n"); - } - else if(buf[0] == '1') - { - if(buf[1] == '1'){ + I("Sense off\n"); + } else if (buf[0] == '1') { + if (buf[1] == '1') { himax_sense_on(private_ts->client, 0x01); - I("Sense on re-map off, run flash \n"); - }else if(buf[1] == '0'){ + I("Sense on re-map off, run flash\n"); + } else if (buf[1] == '0') { himax_sense_on(private_ts->client, 0x00); - I("Sense on re-map on, run sram \n"); - }else{ - I("Do nothing \n"); + I("Sense on re-map on, run sram\n"); + } else { + I("Do nothing\n"); } - } - else - { - I("Do nothing \n"); + } else { + I("Do nothing\n"); } return len; } -static const struct file_operations himax_proc_sense_on_off_ops = -{ +const struct file_operations himax_proc_sense_on_off_ops = { .owner = THIS_MODULE, .write = himax_sense_on_off_write, }; @@ -1893,25 +1790,18 @@ static ssize_t himax_HSEN_read(struct file *file, char *buf, size_t count = 0; char *temp_buf; - if(!HX_PROC_SEND_FLAG) - { + if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return count; - } count = snprintf(temp_buf, len, "%d\n", ts->HSEN_enable); - HX_PROC_SEND_FLAG=1; + HX_PROC_SEND_FLAG = 1; if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } + kfree(temp_buf); - } - else - HX_PROC_SEND_FLAG=0; + } else + HX_PROC_SEND_FLAG = 0; return count; } @@ -1922,22 +1812,17 @@ static ssize_t himax_HSEN_write(struct file *file, const char *buff, char buf[80] = {0}; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } - if (buf[0] == '0'){ + if (buf[0] == '0') ts->HSEN_enable = 0; - } - else if (buf[0] == '1'){ + else if (buf[0] == '1') ts->HSEN_enable = 1; - } else return -EINVAL; @@ -1948,8 +1833,7 @@ static ssize_t himax_HSEN_write(struct file *file, const char *buff, return len; } -static const struct file_operations himax_proc_HSEN_ops = -{ +const struct file_operations himax_proc_HSEN_ops = { .owner = THIS_MODULE, .read = himax_HSEN_read, .write = himax_HSEN_write, @@ -1964,25 +1848,17 @@ static ssize_t himax_SMWP_read(struct file *file, char *buf, struct himax_ts_data *ts = private_ts; char *temp_buf; - if(!HX_PROC_SEND_FLAG) - { + if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return count; - } - count = snprintf(temp_buf, len, "%d\n", ts->SMWP_enable); + count = snprintf(temp_buf, "%d\n", len, ts->SMWP_enable); if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); - HX_PROC_SEND_FLAG=1; - } - else - HX_PROC_SEND_FLAG=0; + HX_PROC_SEND_FLAG = 1; + } else + HX_PROC_SEND_FLAG = 0; return count; } @@ -1993,25 +1869,17 @@ static ssize_t himax_SMWP_write(struct file *file, const char *buff, struct himax_ts_data *ts = private_ts; char buf[80] = {0}; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } - if (buf[0] == '0') - { ts->SMWP_enable = 0; - } else if (buf[0] == '1') - { ts->SMWP_enable = 1; - } else return -EINVAL; @@ -2022,41 +1890,33 @@ static ssize_t himax_SMWP_write(struct file *file, const char *buff, return len; } -static const struct file_operations himax_proc_SMWP_ops = -{ +const struct file_operations himax_proc_SMWP_ops = { .owner = THIS_MODULE, .read = himax_SMWP_read, .write = himax_SMWP_write, }; -static ssize_t himax_GESTURE_read(struct file *file, char *buf, - size_t len, loff_t *pos) +static ssize_t himax_GESTURE_read(struct file *file, +char *buf, size_t len, loff_t *pos) { struct himax_ts_data *ts = private_ts; - int i =0; + int i = 0; int ret = 0; char *temp_buf; - if(!HX_PROC_SEND_FLAG) - { + if (!HX_PROC_SEND_FLAG) { temp_buf = kzalloc(len, GFP_KERNEL); - if (!temp_buf) { - HX_PROC_SEND_FLAG=0; - return ret; - } - for(i=0;i<16;i++) - ret += snprintf(temp_buf+ret, len-ret, "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]); + for (i = 0 ; i < 16 ; i++) + ret += snprintf(temp_buf + ret, len, + "ges_en[%d]=%d\n", i, ts->gesture_cust_en[i]); + HX_PROC_SEND_FLAG = 1; if (copy_to_user(buf, temp_buf, len)) - { I("%s,here:%d\n", __func__, __LINE__); - } kfree(temp_buf); HX_PROC_SEND_FLAG = 1; - } - else - { + } else { HX_PROC_SEND_FLAG = 0; ret = 0; } @@ -2067,35 +1927,30 @@ static ssize_t himax_GESTURE_write(struct file *file, const char *buff, size_t len, loff_t *pos) { struct himax_ts_data *ts = private_ts; - int i =0; + int i = 0; char buf[80] = {0}; - if (len >= 80) - { + if (len >= 80) { I("%s: no command exceeds 80 chars.\n", __func__); return -EFAULT; } if (copy_from_user(buf, buff, len)) - { return -EFAULT; - } - I("himax_GESTURE_store= %s \n",buf); - for (i=0;i<16;i++) - { + I("himax_GESTURE_store= %s\n", buf); + for (i = 0 ; i < 16 ; i++) { if (buf[i] == '0') - ts->gesture_cust_en[i]= 0; + ts->gesture_cust_en[i] = 0; else if (buf[i] == '1') - ts->gesture_cust_en[i]= 1; + ts->gesture_cust_en[i] = 1; else - ts->gesture_cust_en[i]= 0; - I("gesture en[%d]=%d \n", i, ts->gesture_cust_en[i]); + ts->gesture_cust_en[i] = 0; + I("gesture en[%d]=%d\n", i, ts->gesture_cust_en[i]); } return len; } -static const struct file_operations himax_proc_Gesture_ops = -{ +const struct file_operations himax_proc_Gesture_ops = { .owner = THIS_MODULE, .read = himax_GESTURE_read, .write = himax_GESTURE_write, @@ -2104,202 +1959,223 @@ static const struct file_operations himax_proc_Gesture_ops = int himax_touch_proc_init(void) { - himax_touch_proc_dir = proc_mkdir( HIMAX_PROC_TOUCH_FOLDER, NULL); - if (himax_touch_proc_dir == NULL) - { + himax_touch_proc_dir = proc_mkdir(HIMAX_PROC_TOUCH_FOLDER, NULL); + if (himax_touch_proc_dir == NULL) { E(" %s: himax_touch_proc_dir file create failed!\n", __func__); return -ENOMEM; } - himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_level_ops); - if (himax_proc_debug_level_file == NULL) - { + himax_proc_debug_level_file = proc_create(HIMAX_PROC_DEBUG_LEVEL_FILE, + (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_level_ops); + + if (himax_proc_debug_level_file == NULL) { E(" %s: proc debug_level file create failed!\n", __func__); goto fail_1; } - himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_vendor_ops); - if(himax_proc_vendor_file == NULL) - { + himax_proc_vendor_file = proc_create(HIMAX_PROC_VENDOR_FILE, + (S_IRUGO), himax_touch_proc_dir, &himax_proc_vendor_ops); + + if (himax_proc_vendor_file == NULL) { E(" %s: proc vendor file create failed!\n", __func__); goto fail_2; } - himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE, (S_IRUGO),himax_touch_proc_dir, &himax_proc_attn_ops); - if(himax_proc_attn_file == NULL) - { + himax_proc_attn_file = proc_create(HIMAX_PROC_ATTN_FILE, + (S_IRUGO), himax_touch_proc_dir, &himax_proc_attn_ops); + + if (himax_proc_attn_file == NULL) { E(" %s: proc attn file create failed!\n", __func__); goto fail_3; } - himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_int_en_ops); - if(himax_proc_int_en_file == NULL) - { + himax_proc_int_en_file = proc_create(HIMAX_PROC_INT_EN_FILE, + (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_int_en_ops); + + if (himax_proc_int_en_file == NULL) { E(" %s: proc int en file create failed!\n", __func__); goto fail_4; } - himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_layout_ops); - if(himax_proc_layout_file == NULL) - { + himax_proc_layout_file = proc_create(HIMAX_PROC_LAYOUT_FILE, + (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_layout_ops); + + if (himax_proc_layout_file == NULL) { E(" %s: proc layout file create failed!\n", __func__); goto fail_5; } #ifdef HX_TP_PROC_RESET - himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE, (S_IWUSR), himax_touch_proc_dir, &himax_proc_reset_ops); - if(himax_proc_reset_file == NULL) - { + himax_proc_reset_file = proc_create(HIMAX_PROC_RESET_FILE, + (S_IWUSR), himax_touch_proc_dir, &himax_proc_reset_ops); + + if (himax_proc_reset_file == NULL) { E(" %s: proc reset file create failed!\n", __func__); goto fail_6; } #endif #ifdef HX_TP_PROC_DIAG - himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_ops); - if(himax_proc_diag_file == NULL) - { + himax_proc_diag_file = proc_create(HIMAX_PROC_DIAG_FILE, + (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_ops); + + if (himax_proc_diag_file == NULL) { E(" %s: proc diag file create failed!\n", __func__); goto fail_7; } - himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_diag_arrange_ops); - if(himax_proc_diag_arrange_file == NULL) - { + himax_proc_diag_arrange_file = proc_create(HIMAX_PROC_DIAG_ARR_FILE, + (S_IWUSR | S_IRUGO), + himax_touch_proc_dir, &himax_proc_diag_arrange_ops); + + if (himax_proc_diag_arrange_file == NULL) { E(" %s: proc diag file create failed!\n", __func__); goto fail_7_1; } #endif #ifdef HX_TP_PROC_REGISTER - himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_register_ops); - if(himax_proc_register_file == NULL) - { + himax_proc_register_file = proc_create(HIMAX_PROC_REGISTER_FILE, + (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_register_ops); + + if (himax_proc_register_file == NULL) { E(" %s: proc register file create failed!\n", __func__); goto fail_8; } #endif #ifdef HX_TP_PROC_DEBUG - himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_ops); - if(himax_proc_debug_file == NULL) - { + himax_proc_debug_file = proc_create(HIMAX_PROC_DEBUG_FILE, + (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_debug_ops); + + if (himax_proc_debug_file == NULL) { E(" %s: proc debug file create failed!\n", __func__); goto fail_9; } #endif #ifdef HX_TP_PROC_FLASH_DUMP - himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE, (S_IWUSR|S_IRUGO), himax_touch_proc_dir, &himax_proc_flash_ops); - if(himax_proc_flash_dump_file == NULL) - { + himax_proc_flash_dump_file = proc_create(HIMAX_PROC_FLASH_DUMP_FILE, + (S_IWUSR | S_IRUGO), himax_touch_proc_dir, &himax_proc_flash_ops); + + if (himax_proc_flash_dump_file == NULL) { E(" %s: proc flash dump file create failed!\n", __func__); goto fail_10; } #endif #ifdef HX_TP_PROC_SELF_TEST - himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, (S_IRUGO), himax_touch_proc_dir, &himax_proc_self_test_ops); - if(himax_proc_self_test_file == NULL) - { + himax_proc_self_test_file = proc_create(HIMAX_PROC_SELF_TEST_FILE, + (S_IRUGO), himax_touch_proc_dir, &himax_proc_self_test_ops); + + if (himax_proc_self_test_file == NULL) { E(" %s: proc self_test file create failed!\n", __func__); goto fail_11; } #endif #ifdef HX_HIGH_SENSE - himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_HSEN_ops); - if(himax_proc_HSEN_file == NULL) - { + himax_proc_HSEN_file = proc_create(HIMAX_PROC_HSEN_FILE, + (S_IWUSR | S_IRUGO | S_IWUGO), + himax_touch_proc_dir, &himax_proc_HSEN_ops); + + if (himax_proc_HSEN_file == NULL) { E(" %s: proc HSEN file create failed!\n", __func__); goto fail_12; } #endif #ifdef HX_SMART_WAKEUP - himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_SMWP_ops); - if(himax_proc_SMWP_file == NULL) - { + himax_proc_SMWP_file = proc_create(HIMAX_PROC_SMWP_FILE, + (S_IWUSR | S_IRUGO | S_IWUGO), + himax_touch_proc_dir, &himax_proc_SMWP_ops); + + if (himax_proc_SMWP_file == NULL) { E(" %s: proc SMWP file create failed!\n", __func__); goto fail_13; } - himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_Gesture_ops); - if(himax_proc_GESTURE_file == NULL) - { + + himax_proc_GESTURE_file = proc_create(HIMAX_PROC_GESTURE_FILE, + (S_IWUSR | S_IRUGO | S_IWUGO), + himax_touch_proc_dir, &himax_proc_Gesture_ops); + + if (himax_proc_GESTURE_file == NULL) { E(" %s: proc GESTURE file create failed!\n", __func__); goto fail_14; } #endif #ifdef HX_TP_PROC_SENSE_ON_OFF - himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE, (S_IWUSR|S_IRUGO|S_IWUGO), himax_touch_proc_dir, &himax_proc_sense_on_off_ops); - if(himax_proc_SENSE_ON_OFF_file == NULL) - { + himax_proc_SENSE_ON_OFF_file = proc_create(HIMAX_PROC_SENSE_ON_OFF_FILE, + (S_IWUSR | S_IRUGO | S_IWUGO), + himax_touch_proc_dir, &himax_proc_sense_on_off_ops); + + if (himax_proc_SENSE_ON_OFF_file == NULL) { E(" %s: proc SENSE_ON_OFF file create failed!\n", __func__); goto fail_15; } #endif - return 0 ; + return 0; #ifdef HX_TP_PROC_SENSE_ON_OFF - fail_15: +fail_15: #endif #ifdef HX_SMART_WAKEUP - remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir ); - fail_14: - remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir ); - fail_13: + remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir); +fail_14: + remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir); +fail_13: #endif #ifdef HX_HIGH_SENSE - remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir ); - fail_12: + remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir); +fail_12: #endif #ifdef HX_TP_PROC_SELF_TEST - remove_proc_entry( HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir ); - fail_11: + remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir); +fail_11: #endif #ifdef HX_TP_PROC_FLASH_DUMP - remove_proc_entry( HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir ); - fail_10: + remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir); +fail_10: #endif #ifdef HX_TP_PROC_DEBUG - remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir ); - fail_9: + remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir); +fail_9: #endif #ifdef HX_TP_PROC_REGISTER - remove_proc_entry( HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir ); - fail_8: + remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir); +fail_8: #endif #ifdef HX_TP_PROC_DIAG - remove_proc_entry( HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir ); - fail_7: - remove_proc_entry( HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir ); - fail_7_1: + remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir); +fail_7: + remove_proc_entry(HIMAX_PROC_DIAG_ARR_FILE, himax_touch_proc_dir); +fail_7_1: #endif #ifdef HX_TP_PROC_RESET - remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir ); - fail_6: + remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir); +fail_6: #endif - remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir ); - fail_5: remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir ); - fail_4: remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir ); - fail_3: remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir ); - fail_2: remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir ); - fail_1: remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL ); + remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir); +fail_5: remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir); +fail_4: remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir); +fail_3: remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir); +fail_2: remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir); +fail_1: remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL); return -ENOMEM; } void himax_touch_proc_deinit(void) { #ifdef HX_TP_PROC_SENSE_ON_OFF - remove_proc_entry( HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir ); + remove_proc_entry(HIMAX_PROC_SENSE_ON_OFF_FILE, himax_touch_proc_dir); #endif #ifdef HX_SMART_WAKEUP - remove_proc_entry( HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir ); - remove_proc_entry( HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir ); + remove_proc_entry(HIMAX_PROC_GESTURE_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_SMWP_FILE, himax_touch_proc_dir); #endif #ifdef HX_DOT_VIEW - remove_proc_entry( HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir ); + remove_proc_entry(HIMAX_PROC_HSEN_FILE, himax_touch_proc_dir); #endif #ifdef HX_TP_PROC_SELF_TEST remove_proc_entry(HIMAX_PROC_SELF_TEST_FILE, himax_touch_proc_dir); @@ -2308,7 +2184,7 @@ void himax_touch_proc_deinit(void) remove_proc_entry(HIMAX_PROC_FLASH_DUMP_FILE, himax_touch_proc_dir); #endif #ifdef HX_TP_PROC_DEBUG - remove_proc_entry( HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir ); + remove_proc_entry(HIMAX_PROC_DEBUG_FILE, himax_touch_proc_dir); #endif #ifdef HX_TP_PROC_REGISTER remove_proc_entry(HIMAX_PROC_REGISTER_FILE, himax_touch_proc_dir); @@ -2317,13 +2193,13 @@ void himax_touch_proc_deinit(void) remove_proc_entry(HIMAX_PROC_DIAG_FILE, himax_touch_proc_dir); #endif #ifdef HX_TP_PROC_RESET - remove_proc_entry( HIMAX_PROC_RESET_FILE, himax_touch_proc_dir ); + remove_proc_entry(HIMAX_PROC_RESET_FILE, himax_touch_proc_dir); #endif - remove_proc_entry( HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir ); - remove_proc_entry( HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir ); - remove_proc_entry( HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir ); - remove_proc_entry( HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir ); - remove_proc_entry( HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir ); - remove_proc_entry( HIMAX_PROC_TOUCH_FOLDER, NULL ); + remove_proc_entry(HIMAX_PROC_LAYOUT_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_INT_EN_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_ATTN_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_VENDOR_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_DEBUG_LEVEL_FILE, himax_touch_proc_dir); + remove_proc_entry(HIMAX_PROC_TOUCH_FOLDER, NULL); } #endif diff --git a/drivers/input/touchscreen/hxchipset/himax_debug.h b/drivers/input/touchscreen/hxchipset/himax_debug.h index 91a7ae2eb7ab..7a24a170eaca 100644 --- a/drivers/input/touchscreen/hxchipset/himax_debug.h +++ b/drivers/input/touchscreen/hxchipset/himax_debug.h @@ -17,7 +17,7 @@ #include "himax_common.h" #if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) - #define HIMAX_PROC_TOUCH_FOLDER "android_touch" + #define HIMAX_PROC_TOUCH_FOLDER "android_touch" #define HIMAX_PROC_DEBUG_LEVEL_FILE "debug_level" #define HIMAX_PROC_VENDOR_FILE "vendor" #define HIMAX_PROC_ATTN_FILE "attn" @@ -33,60 +33,76 @@ uint8_t HX_PROC_SEND_FLAG; -extern int himax_touch_proc_init(void); -extern void himax_touch_proc_deinit(void); -bool getFlashDumpGoing(void); + extern int himax_touch_proc_init(void); + extern void himax_touch_proc_deinit(void); + bool getFlashDumpGoing(void); + + extern struct himax_ic_data *ic_data; + extern struct himax_ts_data *private_ts; + extern unsigned char IC_TYPE; + extern unsigned char IC_CHECKSUM; + +#ifdef QCT + extern irqreturn_t himax_ts_thread(int irq, void *ptr); +#endif +#ifdef MTK +#ifdef CONFIG_OF_TOUCH + extern irqreturn_t tpd_eint_interrupt_handler(int irq, void *desc); +#else + extern void tpd_eint_interrupt_handler(void); +#endif +#endif #ifdef HX_TP_PROC_REGISTER #define HIMAX_PROC_REGISTER_FILE "register" - struct proc_dir_entry *himax_proc_register_file; + struct proc_dir_entry *himax_proc_register_file = NULL; uint8_t register_command[4]; #endif #ifdef HX_TP_PROC_DIAG #define HIMAX_PROC_DIAG_FILE "diag" - struct proc_dir_entry *himax_proc_diag_file; + struct proc_dir_entry *himax_proc_diag_file = NULL; #define HIMAX_PROC_DIAG_ARR_FILE "diag_arr" - struct proc_dir_entry *himax_proc_diag_arrange_file; + struct proc_dir_entry *himax_proc_diag_arrange_file = NULL; #ifdef HX_TP_PROC_2T2R static bool Is_2T2R; static uint8_t x_channel_2; static uint8_t y_channel_2; static uint8_t *diag_mutual_2; - + int16_t *getMutualBuffer_2(void); - uint8_t getXChannel_2(void); - uint8_t getYChannel_2(void); - - void setMutualBuffer_2(void); - void setXChannel_2(uint8_t x); - void setYChannel_2(uint8_t y); + uint8_t getXChannel_2(void); + uint8_t getYChannel_2(void); + + void setMutualBuffer_2(void); + void setXChannel_2(uint8_t x); + void setYChannel_2(uint8_t y); #endif - uint8_t x_channel; - uint8_t y_channel; - int16_t *diag_mutual; - int16_t *diag_mutual_new; - int16_t *diag_mutual_old; - uint8_t diag_max_cnt; - - int diag_command; - uint8_t diag_coor[128];// = {0xFF}; + uint8_t x_channel = 0; + uint8_t y_channel = 0; + int16_t *diag_mutual = NULL; + int16_t *diag_mutual_new = NULL; + int16_t *diag_mutual_old = NULL; + uint8_t diag_max_cnt = 0; + + int diag_command = 0; + uint8_t diag_coor[128];/* = {0xFF};*/ int16_t diag_self[100] = {0}; int16_t *getMutualBuffer(void); int16_t *getMutualNewBuffer(void); int16_t *getMutualOldBuffer(void); int16_t *getSelfBuffer(void); - uint8_t getDiagCommand(void); - uint8_t getXChannel(void); - uint8_t getYChannel(void); - - void setMutualBuffer(void); - void setMutualNewBuffer(void); - void setMutualOldBuffer(void); - void setXChannel(uint8_t x); - void setYChannel(uint8_t y); + uint8_t getDiagCommand(void); + uint8_t getXChannel(void); + uint8_t getYChannel(void); + + void setMutualBuffer(void); + void setMutualNewBuffer(void); + void setMutualOldBuffer(void); + void setXChannel(uint8_t x); + void setYChannel(uint8_t y); uint8_t coordinate_dump_enable = 0; struct file *coordinate_fn; #endif @@ -106,24 +122,24 @@ bool getFlashDumpGoing(void); struct proc_dir_entry *himax_proc_flash_dump_file = NULL; static int Flash_Size = 131072; - static uint8_t *flash_buffer = NULL; - static uint8_t flash_command = 0; - static uint8_t flash_read_step = 0; - static uint8_t flash_progress = 0; - static uint8_t flash_dump_complete = 0; - static uint8_t flash_dump_fail = 0; - static uint8_t sys_operation = 0; - static uint8_t flash_dump_sector = 0; - static uint8_t flash_dump_page = 0; - static bool flash_dump_going = false; + static uint8_t *flash_buffer; + static uint8_t flash_command; + static uint8_t flash_read_step; + static uint8_t flash_progress; + static uint8_t flash_dump_complete; + static uint8_t flash_dump_fail; + static uint8_t sys_operation; + static uint8_t flash_dump_sector; + static uint8_t flash_dump_page; + static bool flash_dump_going; static uint8_t getFlashCommand(void); static uint8_t getFlashDumpComplete(void); static uint8_t getFlashDumpFail(void); static uint8_t getFlashDumpProgress(void); static uint8_t getFlashReadStep(void); - //static uint8_t getFlashDumpSector(void); - //static uint8_t getFlashDumpPage(void); + /*static uint8_t getFlashDumpSector(void);*/ + /*static uint8_t getFlashDumpPage(void);*/ void setFlashBuffer(void); uint8_t getSysOperation(void); @@ -150,8 +166,8 @@ bool getFlashDumpGoing(void); #ifdef HX_TP_PROC_RESET #define HIMAX_PROC_RESET_FILE "reset" -extern void himax_HW_reset(uint8_t loadconfig,uint8_t int_off); -struct proc_dir_entry *himax_proc_reset_file = NULL; +extern void himax_HW_reset(uint8_t loadconfig, uint8_t int_off); +struct proc_dir_entry *himax_proc_reset_file; #endif #ifdef HX_HIGH_SENSE @@ -165,16 +181,16 @@ struct proc_dir_entry *himax_proc_reset_file = NULL; #endif #ifdef HX_RST_PIN_FUNC - void himax_HW_reset(uint8_t loadconfig,uint8_t int_off); + void himax_HW_reset(uint8_t loadconfig, uint8_t int_off); #endif #ifdef HX_SMART_WAKEUP #define HIMAX_PROC_SMWP_FILE "SMWP" -struct proc_dir_entry *himax_proc_SMWP_file = NULL; +struct proc_dir_entry *himax_proc_SMWP_file; #define HIMAX_PROC_GESTURE_FILE "GESTURE" -struct proc_dir_entry *himax_proc_GESTURE_file = NULL; -uint8_t HX_SMWP_EN = 0; -//extern bool FAKE_POWER_KEY_SEND; +struct proc_dir_entry *himax_proc_GESTURE_file; +uint8_t HX_SMWP_EN; +/*extern bool FAKE_POWER_KEY_SEND;*/ #endif #endif diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.c b/drivers/input/touchscreen/hxchipset/himax_ic.c index 6ad8dc03149b..e2934c2d2396 100644 --- a/drivers/input/touchscreen/hxchipset/himax_ic.c +++ b/drivers/input/touchscreen/hxchipset/himax_ic.c @@ -15,45 +15,31 @@ #include "himax_ic.h" -static unsigned char i_TP_CRC_FW_128K[]= -{ - #include "HX_CRC_128.i" -}; -static unsigned char i_TP_CRC_FW_64K[]= -{ - #include "HX_CRC_64.i" -}; -static unsigned char i_TP_CRC_FW_124K[]= -{ - #include "HX_CRC_124.i" -}; -static unsigned char i_TP_CRC_FW_60K[]= -{ - #include "HX_CRC_60.i" -}; - - -unsigned long FW_VER_MAJ_FLASH_ADDR; -unsigned long FW_VER_MAJ_FLASH_LENG; -unsigned long FW_VER_MIN_FLASH_ADDR; -unsigned long FW_VER_MIN_FLASH_LENG; -unsigned long CFG_VER_MAJ_FLASH_ADDR; -unsigned long CFG_VER_MAJ_FLASH_LENG; -unsigned long CFG_VER_MIN_FLASH_ADDR; -unsigned long CFG_VER_MIN_FLASH_LENG; - -unsigned char IC_TYPE = 0; -unsigned char IC_CHECKSUM = 0; - -extern struct himax_ic_data* ic_data; - -int himax_hand_shaking(struct i2c_client *client) //0:Running, 1:Stop, 2:I2C Fail +const struct firmware *i_TP_CRC_FW_128K; +const struct firmware *i_TP_CRC_FW_64K; +const struct firmware *i_TP_CRC_FW_124K; +const struct firmware *i_TP_CRC_FW_60K; + +unsigned long FW_VER_MAJ_FLASH_ADDR; +unsigned long FW_VER_MAJ_FLASH_LENG; +unsigned long FW_VER_MIN_FLASH_ADDR; +unsigned long FW_VER_MIN_FLASH_LENG; +unsigned long CFG_VER_MAJ_FLASH_ADDR; +unsigned long CFG_VER_MAJ_FLASH_LENG; +unsigned long CFG_VER_MIN_FLASH_ADDR; +unsigned long CFG_VER_MIN_FLASH_LENG; + +unsigned char IC_TYPE; +unsigned char IC_CHECKSUM; + + /*0:Running, 1:Stop, 2:I2C Fail*/ +int himax_hand_shaking(struct i2c_client *client) { int ret, result; uint8_t hw_reset_check[1]; uint8_t hw_reset_check_2[1]; uint8_t buf0[2]; - uint8_t IC_STATUS_CHECK = 0xAA; + uint8_t IC_STATUS_CHECK = 0xAA; memset(hw_reset_check, 0x00, sizeof(hw_reset_check)); memset(hw_reset_check_2, 0x00, sizeof(hw_reset_check_2)); @@ -67,45 +53,50 @@ int himax_hand_shaking(struct i2c_client *client) //0:Running, 1:Stop, 2:I2C IC_STATUS_CHECK = 0xAA; } - ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES); + ret = i2c_himax_master_write(client, + buf0, 2, HIMAX_I2C_RETRY_TIMES); if (ret < 0) { - E("[Himax]:write 0xF2 failed line: %d \n",__LINE__); + E("[Himax]:write 0xF2 failed line: %d\n", __LINE__); goto work_func_send_i2c_msg_fail; } - msleep(50); - + msleep(50); + buf0[0] = 0xF2; buf0[1] = 0x00; - ret = i2c_himax_master_write(client, buf0, 2, HIMAX_I2C_RETRY_TIMES); + ret = i2c_himax_master_write(client, + buf0, 2, HIMAX_I2C_RETRY_TIMES); if (ret < 0) { - E("[Himax]:write 0x92 failed line: %d \n",__LINE__); + E("[Himax]:write 0x92 failed line: %d\n", __LINE__); goto work_func_send_i2c_msg_fail; } - usleep_range(2000, 4000); - - ret = i2c_himax_read(client, 0xD1, hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES); + usleep_range(1999, 2000); + + ret = i2c_himax_read(client, 0xD1, + hw_reset_check, 1, HIMAX_I2C_RETRY_TIMES); if (ret < 0) { - E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__); + E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n", __LINE__); goto work_func_send_i2c_msg_fail; } - - if ((IC_STATUS_CHECK != hw_reset_check[0])) { - usleep_range(2000, 4000); - ret = i2c_himax_read(client, 0xD1, hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES); + + if (IC_STATUS_CHECK != hw_reset_check[0]) { + usleep_range(1999, 2000); + ret = i2c_himax_read(client, 0xD1, + hw_reset_check_2, 1, HIMAX_I2C_RETRY_TIMES); if (ret < 0) { - E("[Himax]:i2c_himax_read 0xD1 failed line: %d \n",__LINE__); + E("[Himax]:i2c_himax_read 0xD1 failed line: %d\n", + __LINE__); goto work_func_send_i2c_msg_fail; } - - if (hw_reset_check[0] == hw_reset_check_2[0]) { - result = 1; - } else { - result = 0; - } + + if (hw_reset_check[0] == hw_reset_check_2[0]) + result = 1; + else + result = 0; + } else { - result = 0; + result = 0; } - + return result; work_func_send_i2c_msg_fail: @@ -117,66 +108,71 @@ void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command) uint8_t tmp_addr[4]; uint8_t tmp_data[4]; - if(diag_command != 0) + if (diag_command != 0) diag_command = diag_command + 5; - tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0x80; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = diag_command; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; + tmp_addr[1] = 0x01; tmp_addr[0] = 0x80; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = diag_command; himax_flash_write_burst(client, tmp_addr, tmp_data); } -void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer) +void himax_flash_dump_func(struct i2c_client *client, +uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer) { - //struct himax_ts_data *ts = container_of(work, struct himax_ts_data, flash_work); - -// uint8_t sector = 0; -// uint8_t page = 0; + /*struct himax_ts_data *ts = + container_of(work, struct himax_ts_data, flash_work);*/ + /*uint8_t sector = 0;*/ + /*uint8_t page = 0;*/ uint8_t tmp_addr[4]; uint8_t tmp_data[4]; uint8_t out_buffer[20]; - uint8_t in_buffer[260] = {0}; + uint8_t in_buffer[260]; int page_prog_start = 0; int i = 0; himax_sense_off(client); himax_burst_enable(client, 0); /*=============Dump Flash Start=============*/ - //===================================== - // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + /*=====================================*/ + /* SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780*/ + /*=====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; + tmp_data[1] = 0x07; tmp_data[0] = 0x80; himax_flash_write_burst(client, tmp_addr, tmp_data); - for (page_prog_start = 0; page_prog_start < Flash_Size; page_prog_start = page_prog_start + 256) - { - //================================= - // SPI Transfer Control - // Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF - // Set read start address : 0x8000_0028 ==> 0x0000_0000 - // Set command : 0x8000_0024 ==> 0x0000_003B - //================================= - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF; + for (page_prog_start = 0 ; page_prog_start < Flash_Size; + page_prog_start = page_prog_start + 256) { + /*===================================== + SPI Transfer Control + Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF + Set read start address : 0x8000_0028 ==> 0x0000_0000 + Set command : 0x8000_0024 ==> 0x0000_003B + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x69; tmp_data[2] = 0x40; + tmp_data[1] = 0x02; tmp_data[0] = 0xFF; himax_flash_write_burst(client, tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; - if (page_prog_start < 0x100) - { + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + if (page_prog_start < 0x100) { tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = (uint8_t)page_prog_start; - } - else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) - { + } else if (page_prog_start >= 0x100 + && page_prog_start < 0x10000) { tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start; - } - else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) - { + } else if (page_prog_start >= 0x10000 + && page_prog_start < 0x1000000) { tmp_data[3] = 0x00; tmp_data[2] = (uint8_t)(page_prog_start >> 16); tmp_data[1] = (uint8_t)(page_prog_start >> 8); @@ -184,43 +180,46 @@ void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_comman } himax_flash_write_burst(client, tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x3B; himax_flash_write_burst(client, tmp_addr, tmp_data); - //================================== - // AHB_I2C Burst Read - // Set SPI data register : 0x8000_002C ==> 0x00 - //================================== + /*===================================== + AHB_I2C Burst Read + Set SPI data register : 0x8000_002C ==> 0x00 + =====================================*/ out_buffer[0] = 0x2C; out_buffer[1] = 0x00; out_buffer[2] = 0x00; out_buffer[3] = 0x80; - i2c_himax_write(client, 0x00 ,out_buffer, 4, 3); + i2c_himax_write(client, 0x00, out_buffer, 4, 3); - //================================== - // Read access : 0x0C ==> 0x00 - //================================== + /*===================================== + Read access : 0x0C ==> 0x00 + =====================================*/ out_buffer[0] = 0x00; - i2c_himax_write(client, 0x0C ,out_buffer, 1, 3); + i2c_himax_write(client, 0x0C, out_buffer, 1, 3); - //================================== - // Read 128 bytes two times - //================================== - i2c_himax_read(client, 0x08 ,in_buffer, 128, 3); - for (i = 0; i < 128; i++) - flash_buffer[i + page_prog_start] = in_buffer[i]; + /*===================================== + Read 128 bytes two times + =====================================*/ + i2c_himax_read(client, 0x08, in_buffer, 128, 3); + for (i = 0 ; i < 128 ; i++) + flash_buffer[i + page_prog_start] + = in_buffer[i]; - i2c_himax_read(client, 0x08 ,in_buffer, 128, 3); - for (i = 0; i < 128; i++) - flash_buffer[(i + 128) + page_prog_start] = in_buffer[i]; + i2c_himax_read(client, 0x08 , in_buffer, 128, 3); + for (i = 0 ; i < 128 ; i++) + flash_buffer[(i + 128) + page_prog_start] + = in_buffer[i]; I("%s:Verify Progress: %x\n", __func__, page_prog_start); } /*=============Dump Flash End=============*/ - //msleep(100); - /* + /*//msleep(100); for( i=0 ; i<8 ;i++) { for(j=0 ; j<64 ; j++) @@ -239,7 +238,7 @@ int himax_chip_self_test(struct i2c_client *client) { uint8_t tmp_addr[4]; uint8_t tmp_data[128]; - int pf_value=0x00; + int pf_value = 0x00; uint8_t test_result_id = 0; int j; @@ -249,19 +248,24 @@ int himax_chip_self_test(struct i2c_client *client) himax_interface_on(client); himax_sense_off(client); - //Set criteria + /*Set criteria*/ himax_burst_enable(client, 1); - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x94; - tmp_data[3] = 0x14; tmp_data[2] = 0xC8; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - tmp_data[7] = 0x13; tmp_data[6] = 0x60; tmp_data[5] = 0x0A; tmp_data[4] = 0x99; - - himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 8); - - //start selftest - // 0x9008_805C ==> 0x0000_0001 - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x94; + tmp_data[3] = 0x14; tmp_data[2] = 0xC8; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_data[7] = 0x13; tmp_data[6] = 0x60; + tmp_data[5] = 0x0A; tmp_data[4] = 0x99; + + himax_flash_write_burst_length(client, tmp_addr, tmp_data, 8); + + /*start selftest*/ + /* 0x9008_805C ==> 0x0000_0001*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x5C; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x01; himax_flash_write_burst(client, tmp_addr, tmp_data); himax_sense_on(client, 1); @@ -271,19 +275,21 @@ int himax_chip_self_test(struct i2c_client *client) himax_sense_off(client); msleep(20); - //===================================== - // Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF - //===================================== - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x78; + /*===================================== + Read test result ID : 0x9008_8078 ==> 0xA/0xB/0xC/0xF + =====================================*/ + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x78; himax_register_read(client, tmp_addr, 1, tmp_data); test_result_id = tmp_data[0]; - I("%s: check test result, test_result_id=%x, test_result=%x\n", __func__ - ,test_result_id,tmp_data[0]); + I("%s: check test result, test_result_id=%x, test_result=%x\n", + __func__ , test_result_id, tmp_data[0]); - if (test_result_id==0xF) { + if (test_result_id == 0xF) { I("[Himax]: self-test pass\n"); pf_value = 0x1; } else { @@ -292,22 +298,28 @@ int himax_chip_self_test(struct i2c_client *client) } himax_burst_enable(client, 1); - for (j = 0;j < 10; j++){ - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - tmp_addr[3] = 0x90; tmp_addr[2] = 0x06; tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C; + for (j = 0 ; j < 10 ; j++) { + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x06; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x0C; himax_register_read(client, tmp_addr, 1, tmp_data); I("[Himax]: 9006000C = %d\n", tmp_data[0]); - if (tmp_data[0] != 0){ - tmp_data[3] = 0x90; tmp_data[2] = 0x06; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); - } - tmp_data[0] = 0x00; - if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); - } - i2c_himax_read(client, 0x08, tmp_data, 124,HIMAX_I2C_RETRY_TIMES); - }else{ + if (tmp_data[0] != 0) { + tmp_data[3] = 0x90; tmp_data[2] = 0x06; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + if (i2c_himax_write(client, 0x00, + tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + } + tmp_data[0] = 0x00; + if (i2c_himax_write(client, 0x0C, + tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + } + i2c_himax_read(client, 0x08, + tmp_data, 124, HIMAX_I2C_RETRY_TIMES); + } else { break; } } @@ -324,15 +336,18 @@ void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable) uint8_t tmp_data[4]; himax_burst_enable(client, 0); - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x50; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = HSEN_enable; himax_flash_write_burst(client, tmp_addr, tmp_data); } -void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data) +void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data) { uint8_t tmp_addr[4]; - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x50; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x50; himax_register_read(client, tmp_addr, 1, tmp_data); } @@ -341,206 +356,232 @@ void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable) uint8_t tmp_addr[4]; uint8_t tmp_data[4]; - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x54; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = SMWP_enable; himax_flash_write_burst(client, tmp_addr, tmp_data); } -void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data) +void himax_get_SMWP_enable(struct i2c_client *client, +uint8_t *tmp_data) { uint8_t tmp_addr[4]; - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x54; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x54; himax_register_read(client, tmp_addr, 1, tmp_data); } int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte) { uint8_t tmp_data[4]; + int err = -1; tmp_data[0] = 0x31; - if ( i2c_himax_write(client, 0x13 ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + + if (i2c_himax_write(client, 0x13, + tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); - return -EBUSY; + return err; } - + tmp_data[0] = (0x10 | auto_add_4_byte); - if ( i2c_himax_write(client, 0x0D ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x0D, + tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); - return -EBUSY; + return err; } return 0; } -void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data) +void himax_register_read(struct i2c_client *client, +uint8_t *read_addr, int read_length, uint8_t *read_data) { uint8_t tmp_data[4]; int i = 0; int address = 0; - if(read_length>256) - { + if (read_length > 256) { E("%s: read len over 256!\n", __func__); return; } if (read_length > 1) himax_burst_enable(client, 1); else - himax_burst_enable(client, 0); - address = (read_addr[3] << 24) + (read_addr[2] << 16) + (read_addr[1] << 8) + read_addr[0]; + himax_burst_enable(client, 0); + + address = (read_addr[3] << 24) + + (read_addr[2] << 16) + + (read_addr[1] << 8) + + read_addr[0]; + i = address; - tmp_data[0] = (uint8_t)i; - tmp_data[1] = (uint8_t)(i >> 8); - tmp_data[2] = (uint8_t)(i >> 16); - tmp_data[3] = (uint8_t)(i >> 24); - if ( i2c_himax_write(client, 0x00 ,tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } - tmp_data[0] = 0x00; - if ( i2c_himax_write(client, 0x0C ,tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } - - if ( i2c_himax_read(client, 0x08 ,read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } + tmp_data[0] = (uint8_t)i; + tmp_data[1] = (uint8_t)(i >> 8); + tmp_data[2] = (uint8_t)(i >> 16); + tmp_data[3] = (uint8_t)(i >> 24); + if (i2c_himax_write(client, 0x00, + tmp_data, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + tmp_data[0] = 0x00; + if (i2c_himax_write(client, 0x0C, + tmp_data, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } + if (i2c_himax_read(client, 0x08, + read_data, read_length * 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } if (read_length > 1) himax_burst_enable(client, 0); } -void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data) +void himax_flash_read(struct i2c_client *client, +uint8_t *reg_byte, uint8_t *read_data) { - uint8_t tmpbyte[2]; - - if ( i2c_himax_write(client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + uint8_t tmpbyte[2]; + + if (i2c_himax_write(client, 0x00, + ®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x01, + ®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x02, + ®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x03, + ®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - tmpbyte[0] = 0x00; - if ( i2c_himax_write(client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + tmpbyte[0] = 0x00; + if (i2c_himax_write(client, 0x0C, + &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_read(client, 0x08 ,&read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_read(client, 0x08, + &read_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_read(client, 0x09 ,&read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_read(client, 0x09, + &read_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_read(client, 0x0A ,&read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_read(client, 0x0A, + &read_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_read(client, 0x0B ,&read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_read(client, 0x0B, + &read_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_read(client, 0x18 ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_read(client, 0x18, + &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; - }// No bus request + } /* No bus request*/ - if ( i2c_himax_read(client, 0x0F ,&tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_read(client, 0x0F, + &tmpbyte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; - }// idle state + } /* idle state*/ } -void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data) +void himax_flash_write_burst(struct i2c_client *client, +uint8_t *reg_byte, uint8_t *write_data) { - uint8_t data_byte[8]; + uint8_t data_byte[8]; int i = 0, j = 0; - for (i = 0; i < 4; i++) - { - data_byte[i] = reg_byte[i]; - } - for (j = 4; j < 8; j++) - { - data_byte[j] = write_data[j-4]; - } - - if ( i2c_himax_write(client, 0x00 ,data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); - return; - } + for (i = 0 ; i < 4; i++) + data_byte[i] = reg_byte[i]; + + for (j = 4 ; j < 8; j++) + data_byte[j] = write_data[j-4]; + + if (i2c_himax_write(client, 0x00, + data_byte, 8, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + } } -int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length) +int himax_flash_write_burst_length(struct i2c_client *client, +uint8_t *reg_byte, uint8_t *write_data, int length) { - uint8_t data_byte[256]; - int i = 0, j = 0; + uint8_t data_byte[256]; + int i = 0, j = 0, err = -1; - for (i = 0; i < 4; i++) - { - data_byte[i] = reg_byte[i]; - } - for (j = 4; j < length + 4; j++) - { - data_byte[j] = write_data[j - 4]; - } - - if ( i2c_himax_write(client, 0x00 ,data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); - return -EBUSY; - } + for (i = 0 ; i < 4 ; i++) + data_byte[i] = reg_byte[i]; - return 0; + for (j = 4 ; j < length + 4 ; j++) + data_byte[j] = write_data[j - 4]; + + if (i2c_himax_write(client, 0x00, + data_byte, length + 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return err; + } + return 0; } -int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data) +int himax_register_write(struct i2c_client *client, +uint8_t *write_addr, int write_length, uint8_t *write_data) { - int i =0, address = 0; - int ret = 0; + int i = 0, address = 0; + int ret = 0, err = -1; - address = (write_addr[3] << 24) + (write_addr[2] << 16) + (write_addr[1] << 8) + write_addr[0]; + address = (write_addr[3] << 24) + + (write_addr[2] << 16) + + (write_addr[1] << 8) + + write_addr[0]; - for (i = address; i < address + write_length * 4; i = i + 4) - { - if (write_length > 1) - { + for (i = address ; i < address + write_length * 4; + i = i + 4) { + if (write_length > 1) { ret = himax_burst_enable(client, 1); - if(ret) - return ret; - } - else - { + if (ret) + return err; + } else { ret = himax_burst_enable(client, 0); - if(ret) - return ret; + if (ret) + return err; } - ret = himax_flash_write_burst_lenth(client, write_addr, write_data, write_length * 4); - if(ret < 0) - return ret; + ret = himax_flash_write_burst_length(client, + write_addr, write_data, write_length * 4); + if (ret < 0) + return err; } return 0; @@ -550,50 +591,62 @@ void himax_sense_off(struct i2c_client *client) { uint8_t wdt_off = 0x00; uint8_t tmp_addr[4]; - uint8_t tmp_data[5]; + uint8_t tmp_data[5]; himax_burst_enable(client, 0); - while(wdt_off == 0x00) - { - // 0x9000_800C ==> 0x0000_AC53 - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0xAC; tmp_data[0] = 0x53; + while (wdt_off == 0x00) { + /* 0x9000_800C ==> 0x0000_AC53*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0xAC; tmp_data[0] = 0x53; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // Read Watch Dog disable password : 0x9000_800C ==> 0x0000_AC53 - //===================================== - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C; + /*=====================================*/ + /* Read Watch Dog disable password : + 0x9000_800C ==> 0x0000_AC53 */ + /*=====================================*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x0C; himax_register_read(client, tmp_addr, 1, tmp_data); - - //Check WDT - if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC && tmp_data[2] == 0x00 && tmp_data[3] == 0x00) + + /*Check WDT*/ + if (tmp_data[0] == 0x53 && tmp_data[1] == 0xAC + && tmp_data[2] == 0x00 && tmp_data[3] == 0x00) wdt_off = 0x01; else wdt_off = 0x00; } - // VCOM //0x9008_806C ==> 0x0000_0001 - tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + /* VCOM //0x9008_806C ==> 0x0000_0001*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x6C; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x01; himax_flash_write_burst(client, tmp_addr, tmp_data); msleep(20); - // 0x9000_0010 ==> 0x0000_00DA - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xDA; + /* 0x9000_0010 ==> 0x0000_00DA*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0xDA; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA - //===================================== - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + /*===================================== + Read CPU clock off password : 0x9000_0010 ==> 0x0000_00DA + =====================================*/ + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; himax_register_read(client, tmp_addr, 1, tmp_data); - I("%s: CPU clock off password data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ - ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); + I("%s: CPU clock off password data[0]=%x", + __func__, tmp_data[0]); + I(" data[1]=%x data[2]=%x data[3]=%x\n", + tmp_data[1], tmp_data[2], tmp_data[3]); } @@ -602,11 +655,12 @@ void himax_interface_on(struct i2c_client *client) uint8_t tmp_addr[4]; uint8_t tmp_data[5]; - //=========================================== - // Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000 - //=========================================== - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; - himax_flash_read(client, tmp_addr, tmp_data); //avoid RD/WR fail + /*===================================== + Any Cmd for ineterface on : 0x9000_0000 ==> 0x0000_0000 + =====================================*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + himax_flash_read(client, tmp_addr, tmp_data); /*avoid RD/WR fail*/ } bool wait_wip(struct i2c_client *client, int Timing) @@ -614,55 +668,64 @@ bool wait_wip(struct i2c_client *client, int Timing) uint8_t tmp_addr[4]; uint8_t tmp_data[4]; uint8_t in_buffer[10]; - //uint8_t out_buffer[20]; + /*uint8_t out_buffer[20];*/ int retry_cnt = 0; - //===================================== - // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + /*===================================== + SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; + tmp_data[1] = 0x07; tmp_data[0] = 0x80; himax_flash_write_burst(client, tmp_addr, tmp_data); in_buffer[0] = 0x01; - do - { - //===================================== - // SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x42; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x03; + do { + /*===================================== + SPI Transfer Control : 0x8000_0020 ==> 0x4200_0003 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x42; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x03; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // SPI Command : 0x8000_0024 ==> 0x0000_0005 - // read 0x8000_002C for 0x01, means wait success - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x05; + /*===================================== + SPI Command : 0x8000_0024 ==> 0x0000_0005 + read 0x8000_002C for 0x01, means wait success + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x05; himax_flash_write_burst(client, tmp_addr, tmp_data); - in_buffer[0] = in_buffer[1] = in_buffer[2] = in_buffer[3] = 0xFF; - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; + in_buffer[0] = in_buffer[1] = + in_buffer[2] = in_buffer[3] = 0xFF; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; himax_register_read(client, tmp_addr, 1, in_buffer); - + if ((in_buffer[0] & 0x01) == 0x00) return true; retry_cnt++; - - if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00 || in_buffer[2] != 0x00 || in_buffer[3] != 0x00) - I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, buffer[1]=%d, buffer[2]=%d, buffer[3]=%d \n", __func__, - retry_cnt,in_buffer[0],in_buffer[1],in_buffer[2],in_buffer[3]); - if (retry_cnt > 100) - { + if (in_buffer[0] != 0x00 || in_buffer[1] != 0x00 + || in_buffer[2] != 0x00 || in_buffer[3] != 0x00){ + I("%s:Wait wip retry_cnt:%d, buffer[0]=%d, ", + __func__, retry_cnt, in_buffer[0]); + I("buffer[1]=%d, buffer[2]=%d, buffer[3]=%d\n", + in_buffer[1], in_buffer[2], in_buffer[3]); + } + if (retry_cnt > 100) { E("%s: Wait wip error!\n", __func__); - return false; - } + return false; + } msleep(Timing); - }while ((in_buffer[0] & 0x01) == 0x01); + } while ((in_buffer[0] & 0x01) == 0x01); return true; } @@ -673,74 +736,93 @@ void himax_sense_on(struct i2c_client *client, uint8_t FlashMode) himax_interface_on(client); himax_burst_enable(client, 0); - //CPU reset - // 0x9000_0014 ==> 0x0000_00CA - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xCA; + /*CPU reset*/ + /* 0x9000_0014 ==> 0x0000_00CA*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0xCA; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA - //===================================== - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; + /*===================================== + Read pull low CPU reset signal : 0x9000_0014 ==> 0x0000_00CA + =====================================*/ + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; himax_register_read(client, tmp_addr, 1, tmp_data); - I("%s: check pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ - ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); + I("%s: check pull low CPU reset signal data[0]=%x data[1]=%x ", + __func__, tmp_data[0], tmp_data[1]); + I("data[2]=%x data[3]=%x\n", + tmp_data[2], tmp_data[3]); - // 0x9000_0014 ==> 0x0000_0000 - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + /* 0x9000_0014 ==> 0x0000_0000*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000 - //===================================== - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; + /*===================================== + Read revert pull low CPU reset signal : 0x9000_0014 ==> 0x0000_0000 + =====================================*/ + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x14; himax_register_read(client, tmp_addr, 1, tmp_data); - I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x data[2]=%x data[3]=%x\n", __func__ - ,tmp_data[0],tmp_data[1],tmp_data[2],tmp_data[3]); - - //===================================== - // Reset TCON - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - himax_flash_write_burst(client, tmp_addr, tmp_data); - usleep_range(10000, 20000); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; - himax_flash_write_burst(client, tmp_addr, tmp_data); - - if (FlashMode == 0x00) //SRAM - { - //===================================== - // Re-map - //===================================== - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xF1; - himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4); + I("%s: revert pull low CPU reset signal data[0]=%x data[1]=%x ", + __func__, tmp_data[0], tmp_data[1]); + I("data[2]=%x data[3]=%x\n", + tmp_data[2], tmp_data[3]); + + /*===================================== + Reset TCON + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; + tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); + usleep_range(9999, 10000); + tmp_addr[3] = 0x80; tmp_addr[2] = 0x02; + tmp_addr[1] = 0x01; tmp_addr[0] = 0xE0; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x01; + himax_flash_write_burst(client, tmp_addr, tmp_data); + + if (FlashMode == 0x00) { /*SRAM*/ + /*===================================== + Re-map + =====================================*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0xF1; + himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4); I("%s:83100_Chip_Re-map ON\n", __func__); - } - else - { - //===================================== - // Re-map off - //===================================== - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4); + } else { + /*===================================== + Re-map off + =====================================*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4); I("%s:83100_Chip_Re-map OFF\n", __func__); } - //===================================== - // CPU clock on - //===================================== - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4); + /*===================================== + CPU clock on + =====================================*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst_length(client, tmp_addr, tmp_data, 4); } @@ -751,36 +833,45 @@ void himax_chip_erase(struct i2c_client *client) himax_burst_enable(client, 0); - //===================================== - // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + /*===================================== + SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; + tmp_data[1] = 0x07; tmp_data[0] = 0x80; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // Chip Erase - // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 - // 2. 0x8000_0024 ==> 0x0000_0006 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + /*===================================== + Chip Erase + Write Enable : + 1. 0x8000_0020 ==> 0x4700_0000 + 2. 0x8000_0024 ==> 0x0000_0006 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x47; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; himax_flash_write_burst(client, tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x06; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // Chip Erase - // Erase Command : 0x8000_0024 ==> 0x0000_00C7 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0xC7; + /*===================================== + Chip Erase + Erase Command : 0x8000_0024 ==> 0x0000_00C7 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0xC7; himax_flash_write_burst(client, tmp_addr, tmp_data); - + msleep(2000); - + if (!wait_wip(client, 100)) E("%s:83100_Chip_Erase Fail\n", __func__); @@ -793,53 +884,64 @@ bool himax_block_erase(struct i2c_client *client) himax_burst_enable(client, 0); - //===================================== - // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + /*===================================== + SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; + tmp_data[1] = 0x07; tmp_data[0] = 0x80; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // Chip Erase - // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 - // 2. 0x8000_0024 ==> 0x0000_0006 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + /*===================================== + Chip Erase + Write Enable : + 1. 0x8000_0020 ==> 0x4700_0000 + 2. 0x8000_0024 ==> 0x0000_0006 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x47; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; himax_flash_write_burst(client, tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x06; himax_flash_write_burst(client, tmp_addr, tmp_data); - //===================================== - // Block Erase - // Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr - // 0x8000_0020 ==> 0x6700_0000 //control - // 0x8000_0024 ==> 0x0000_0052 //BE - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + /*===================================== + Block Erase + Erase Command : + 0x8000_0028 ==> 0x0000_0000 //SPI addr + 0x8000_0020 ==> 0x6700_0000 //control + 0x8000_0024 ==> 0x0000_0052 //BE + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; himax_flash_write_burst(client, tmp_addr, tmp_data); - - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x67; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; himax_flash_write_burst(client, tmp_addr, tmp_data); - - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x52; + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x52; himax_flash_write_burst(client, tmp_addr, tmp_data); msleep(1000); - if (!wait_wip(client, 100)) - { + if (!wait_wip(client, 100)) { E("%s:83100_Erase Fail\n", __func__); return false; - } - else - { + } else { return true; } @@ -853,97 +955,110 @@ bool himax_sector_erase(struct i2c_client *client, int start_addr) himax_burst_enable(client, 0); - //===================================== - // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + /*===================================== + SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; + tmp_data[1] = 0x07; tmp_data[0] = 0x80; himax_flash_write_burst(client, tmp_addr, tmp_data); - for (page_prog_start = start_addr; page_prog_start < start_addr + 0x0F000; page_prog_start = page_prog_start + 0x1000) - { - //===================================== - // Chip Erase - // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 - // 2. 0x8000_0024 ==> 0x0000_0006 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - himax_flash_write_burst(client, tmp_addr, tmp_data); - - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06; - himax_flash_write_burst(client, tmp_addr, tmp_data); - - //===================================== - // Sector Erase - // Erase Command : 0x8000_0028 ==> 0x0000_0000 //SPI addr - // 0x8000_0020 ==> 0x6700_0000 //control - // 0x8000_0024 ==> 0x0000_0020 //SE - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; - if (page_prog_start < 0x100) - { - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = (uint8_t)page_prog_start; - } - else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) - { - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start; - } - else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) - { - tmp_data[3] = 0x00; tmp_data[2] = (uint8_t)(page_prog_start >> 16); tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start; - } - himax_flash_write_burst(client, tmp_addr, tmp_data); + for (page_prog_start = start_addr; + page_prog_start < start_addr + 0x0F000; + page_prog_start = page_prog_start + 0x1000) { + /*===================================== + Chip Erase + Write Enable : + 1. 0x8000_0020 ==> 0x4700_0000 + 2. 0x8000_0024 ==> 0x0000_0006 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x47; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x67; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - himax_flash_write_burst(client, tmp_addr, tmp_data); + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x06; + himax_flash_write_burst(client, tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x20; - himax_flash_write_burst(client, tmp_addr, tmp_data); + /*===================================== + Sector Erase + Erase Command : + 0x8000_0028 ==> 0x0000_0000 //SPI addr + 0x8000_0020 ==> 0x6700_0000 //control + 0x8000_0024 ==> 0x0000_0020 //SE + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + if (page_prog_start < 0x100) { + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; + tmp_data[0] = (uint8_t)page_prog_start; + } else if (page_prog_start >= 0x100 + && page_prog_start < 0x10000) { + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } else if (page_prog_start >= 0x10000 + && page_prog_start < 0x1000000) { + tmp_data[3] = 0x00; + tmp_data[2] = (uint8_t)(page_prog_start >> 16); + tmp_data[1] = (uint8_t)(page_prog_start >> 8); + tmp_data[0] = (uint8_t)page_prog_start; + } + himax_flash_write_burst(client, tmp_addr, tmp_data); + + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x67; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst(client, tmp_addr, tmp_data); - msleep(200); + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x20; + himax_flash_write_burst(client, tmp_addr, tmp_data); - if (!wait_wip(client, 100)) - { - E("%s:83100_Erase Fail\n", __func__); - return false; - } - } - return true; + msleep(200); + + if (!wait_wip(client, 100)) { + E("%s:83100_Erase Fail\n", __func__); + return false; + } + } + return true; } void himax_sram_write(struct i2c_client *client, uint8_t *FW_content) { int i = 0; uint8_t tmp_addr[4]; - uint8_t tmp_data[128]; - int FW_length = 0x4000; // 0x4000 = 16K bin file - - //himax_sense_off(client); + uint8_t tmp_data[64]; + int FW_length = 0x4000; /* 0x4000 = 16K bin file */ + + /*himax_sense_off(client);*/ - for (i = 0; i < FW_length; i = i + 128) - { + for (i = 0; i < FW_length; i = i + 64) { himax_burst_enable(client, 1); - if (i < 0x100) - { - tmp_addr[3] = 0x08; - tmp_addr[2] = 0x00; - tmp_addr[1] = 0x00; + if (i < 0x100) { + tmp_addr[3] = 0x08; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = i; - } - else if (i >= 0x100 && i < 0x10000) - { - tmp_addr[3] = 0x08; - tmp_addr[2] = 0x00; - tmp_addr[1] = (i >> 8); + } else if (i >= 0x100 && i < 0x10000) { + tmp_addr[3] = 0x08; + tmp_addr[2] = 0x00; + tmp_addr[1] = (i >> 8); tmp_addr[0] = i; } - memcpy(&tmp_data[0], &FW_content[i], 128); - himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 128); + memcpy(&tmp_data[0], &FW_content[i], 64); + himax_flash_write_burst_length(client, tmp_addr, tmp_data, 64); } @@ -951,182 +1066,197 @@ void himax_sram_write(struct i2c_client *client, uint8_t *FW_content) E("%s:83100_Sram_Write Fail\n", __func__); } -bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size) +bool himax_sram_verify(struct i2c_client *client, +uint8_t *FW_File, int FW_Size) { int i = 0; uint8_t out_buffer[20]; uint8_t in_buffer[128]; uint8_t *get_fw_content; - get_fw_content = kzalloc(0x4000*sizeof(uint8_t), GFP_KERNEL); - if (!get_fw_content) - return false; + get_fw_content = kzalloc(0x4000 * sizeof(uint8_t), GFP_KERNEL); - for (i = 0; i < 0x4000; i = i + 128) - { + for (i = 0 ; i < 0x4000 ; i = i + 128) { himax_burst_enable(client, 1); - //================================== - // AHB_I2C Burst Read - //================================== - if (i < 0x100) - { - out_buffer[3] = 0x08; - out_buffer[2] = 0x00; - out_buffer[1] = 0x00; + /*===================================== + AHB_I2C Burst Read + =====================================*/ + if (i < 0x100) { + out_buffer[3] = 0x08; + out_buffer[2] = 0x00; + out_buffer[1] = 0x00; out_buffer[0] = i; - } - else if (i >= 0x100 && i < 0x10000) - { - out_buffer[3] = 0x08; - out_buffer[2] = 0x00; - out_buffer[1] = (i >> 8); + } else if (i >= 0x100 && i < 0x10000) { + out_buffer[3] = 0x08; + out_buffer[2] = 0x00; + out_buffer[1] = (i >> 8); out_buffer[0] = i; } - if ( i2c_himax_write(client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x00, out_buffer, + 4, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return false; } - out_buffer[0] = 0x00; - if ( i2c_himax_write(client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + out_buffer[0] = 0x00; + if (i2c_himax_write(client, 0x0C, out_buffer, + 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return false; } - if ( i2c_himax_read(client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_read(client, 0x08, in_buffer, + 128, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return false; } memcpy(&get_fw_content[i], &in_buffer[0], 128); } - for (i = 0; i < FW_Size; i++) - { - if (FW_File[i] != get_fw_content[i]) - { - E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n", __func__,i,get_fw_content[i],FW_File[i]); - return false; - } + for (i = 0 ; i < FW_Size ; i++) { + if (FW_File[i] != get_fw_content[i]) { + E("%s: fail! SRAM[%x]=%x NOT CRC_ifile=%x\n", + __func__, i, get_fw_content[i], FW_File[i]); + return false; } + } kfree(get_fw_content); return true; } -void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size) +void himax_flash_programming(struct i2c_client *client, +uint8_t *FW_content, int FW_Size) { int page_prog_start = 0; int program_length = 48; int i = 0, j = 0, k = 0; uint8_t tmp_addr[4]; uint8_t tmp_data[4]; - uint8_t buring_data[256]; // Read for flash data, 128K - // 4 bytes for 0x80002C padding + /* // Read for flash data, 128K //4 bytes for 0x80002C padding */ + uint8_t buring_data[256]; - //himax_interface_on(client); + /*himax_interface_on(client);*/ himax_burst_enable(client, 0); - //===================================== - // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + /*===================================== + SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; + tmp_data[1] = 0x07; tmp_data[0] = 0x80; himax_flash_write_burst(client, tmp_addr, tmp_data); - for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256) - { - //msleep(5); - //===================================== - // Write Enable : 1. 0x8000_0020 ==> 0x4700_0000 - // 2. 0x8000_0024 ==> 0x0000_0006 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x47; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + for (page_prog_start = 0 ; page_prog_start < FW_Size; + page_prog_start = page_prog_start + 256) { + /*msleep(5);*/ + /*===================================== + Write Enable : + 1. 0x8000_0020 ==> 0x4700_0000 + 2. 0x8000_0024 ==> 0x0000_0006 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x47; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; himax_flash_write_burst(client, tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x06; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x06; himax_flash_write_burst(client, tmp_addr, tmp_data); - //================================= - // SPI Transfer Control - // Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000 - // Set read start address : 0x8000_0028 ==> 0x0000_0000 - //================================= - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x61; tmp_data[2] = 0x0F; tmp_data[1] = 0xF0; tmp_data[0] = 0x00; - // data bytes should be 0x6100_0000 + ((word_number)*4-1)*4096 = 0x6100_0000 + 0xFF000 = 0x610F_F000 - // Programmable size = 1 page = 256 bytes, word_number = 256 byte / 4 = 64 + /*===================================== + SPI Transfer Control + Set 256 bytes page write : 0x8000_0020 ==> 0x610F_F000 + Set read start address : 0x8000_0028 ==> 0x0000_0000 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x61; tmp_data[2] = 0x0F; + tmp_data[1] = 0xF0; tmp_data[0] = 0x00; + /*data bytes should be 0x6100_0000 + + ((word_number)*4-1)*4096 = 0x6100_0000 + + 0xFF000 = 0x610F_F000 + Programmable size = 1 page = 256 bytes, + word_number = 256 byte / 4 = 64*/ himax_flash_write_burst(client, tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; - //tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; // Flash start address 1st : 0x0000_0000 + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + /* tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + // Flash start address 1st : 0x0000_0000 */ - if (page_prog_start < 0x100) - { - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = 0x00; + if (page_prog_start < 0x100) { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = (uint8_t)page_prog_start; - } - else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) - { - tmp_data[3] = 0x00; - tmp_data[2] = 0x00; - tmp_data[1] = (uint8_t)(page_prog_start >> 8); + } else if (page_prog_start >= 0x100 + && page_prog_start < 0x10000) { + tmp_data[3] = 0x00; + tmp_data[2] = 0x00; + tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start; - } - else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) - { - tmp_data[3] = 0x00; - tmp_data[2] = (uint8_t)(page_prog_start >> 16); - tmp_data[1] = (uint8_t)(page_prog_start >> 8); + } else if (page_prog_start >= 0x10000 + && page_prog_start < 0x1000000) { + tmp_data[3] = 0x00; + tmp_data[2] = (uint8_t)(page_prog_start >> 16); + tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start; } - - himax_flash_write_burst(client, tmp_addr, tmp_data); + himax_flash_write_burst(client, tmp_addr, tmp_data); - //================================= - // Send 16 bytes data : 0x8000_002C ==> 16 bytes data - //================================= + /*===================================== + Send 16 bytes data : 0x8000_002C ==> 16 bytes data + =====================================*/ buring_data[0] = 0x2C; buring_data[1] = 0x00; buring_data[2] = 0x00; buring_data[3] = 0x80; - - for (i = /*0*/page_prog_start, j = 0; i < 16 + page_prog_start/**/; i++, j++) /// <------ bin file - { + + for (i = /*0*/page_prog_start, j = 0; + i < 16 + page_prog_start/**/; + i++, j++) { /* <------ bin file*/ + buring_data[j + 4] = FW_content[i]; } - - if ( i2c_himax_write(client, 0x00 ,buring_data, 20, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x00, buring_data, + 20, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - //================================= - // Write command : 0x8000_0024 ==> 0x0000_0002 - //================================= - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x02; + /*===================================== + Write command : 0x8000_0024 ==> 0x0000_0002 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x02; himax_flash_write_burst(client, tmp_addr, tmp_data); - //================================= - // Send 240 bytes data : 0x8000_002C ==> 240 bytes data - //================================= + /*===================================== + Send 240 bytes data : 0x8000_002C ==> 240 bytes data + =====================================*/ - for (j = 0; j < 5; j++) - { - for (i = (page_prog_start + 16 + (j * 48)), k = 0; i < (page_prog_start + 16 + (j * 48)) + program_length; i++, k++) /// <------ bin file - { - buring_data[k+4] = FW_content[i];//(byte)i; + for (j = 0; j < 5; j++) { + for (i = (page_prog_start + 16 + (j * 48)), k = 0; + i < (page_prog_start + 16 + (j * 48)) + program_length; + i++, k++) { /*<------ bin file*/ + buring_data[k+4] = FW_content[i];/*(byte)i;*/ } - if ( i2c_himax_write(client, 0x00 ,buring_data, program_length+4, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x00, buring_data, + program_length + 4, + HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } @@ -1145,52 +1275,61 @@ bool himax_check_chip_version(struct i2c_client *client) uint8_t ret_data = 0x00; int i = 0; int ret = 0; + himax_sense_off(client); - for (i = 0; i < 5; i++) - { - // 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) (Lock register R/W from driver) - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x01; + + for (i = 0 ; i < 5 ; i++) { + /* 1. Set DDREG_Req = 1 (0x9000_0020 = 0x0000_0001) + (Lock register R/W from driver) */ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x01; ret = himax_register_write(client, tmp_addr, 1, tmp_data); - if(ret) + if (ret) return false; - // 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000) - tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + /* 2. Set bank as 0 (0x8001_BD01 = 0x0000_0000)*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; + tmp_addr[1] = 0xBD; tmp_addr[0] = 0x01; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; ret = himax_register_write(client, tmp_addr, 1, tmp_data); - if(ret) + if (ret) return false; - // 3. Read driver ID register RF4H 1 byte (0x8001_F401) - // Driver register RF4H 1 byte value = 0x84H, read back value will become 0x84848484 - tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01; + /* 3. Read driver ID register RF4H 1 byte (0x8001_F401) + // Driver register RF4H 1 byte value = 0x84H, + read back value will become 0x84848484 */ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x01; + tmp_addr[1] = 0xF4; tmp_addr[0] = 0x01; himax_register_read(client, tmp_addr, 1, tmp_data); ret_data = tmp_data[0]; I("%s:Read driver IC ID = %X\n", __func__, ret_data); - if (ret_data == 0x84) - { + if (ret_data == 0x84) { IC_TYPE = HX_83100_SERIES_PWON; - //himax_sense_on(client, 0x01); + /*himax_sense_on(client, 0x01);*/ ret_data = true; break; - } - else - { + + } else { ret_data = false; E("%s:Read driver ID register Fail:\n", __func__); } } - // 4. After read finish, set DDREG_Req = 0 (0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver) - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; + /* 4. After read finish, set DDREG_Req = 0 + (0x9000_0020 = 0x0000_0000) (Unlock register R/W from driver)*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; himax_register_write(client, tmp_addr, 1, tmp_data); - //himax_sense_on(client, 0x01); + /*himax_sense_on(client, 0x01);*/ return ret_data; } -#if 1 +/*#if 1*/ int himax_check_CRC(struct i2c_client *client, int mode) { bool burnFW_success = false; @@ -1200,52 +1339,70 @@ int himax_check_CRC(struct i2c_client *client, int mode) int CRC_value = 0; memset(tmp_data, 0x00, sizeof(tmp_data)); + if (i_TP_CRC_FW_60K == NULL) { + I("%s: i_TP_CRC_FW_60K = NULL\n", __func__); + return 0; + } else if (i_TP_CRC_FW_64K == NULL) { + I("%s: i_TP_CRC_FW_64K = NULL\n", __func__); + return 0; + } else if (i_TP_CRC_FW_124K == NULL) { + I("%s: i_TP_CRC_FW_124K = NULL\n", __func__); + return 0; + } else if (i_TP_CRC_FW_128K == NULL) { + I("%s: i_TP_CRC_FW_128K = NULL\n", __func__); + return 0; + } - if (1) - { - if(mode == fw_image_60k) - { - himax_sram_write(client, (i_TP_CRC_FW_60K)); - burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_60K, 0x4000); - } - else if(mode == fw_image_64k) - { - himax_sram_write(client, (i_TP_CRC_FW_64K)); - burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_64K, 0x4000); - } - else if(mode == fw_image_124k) - { - himax_sram_write(client, (i_TP_CRC_FW_124K)); - burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_124K, 0x4000); + if (1) { + if (mode == fw_image_60k) { + himax_sram_write(client, + (unsigned char *)i_TP_CRC_FW_60K->data); + burnFW_success = himax_sram_verify(client, + (unsigned char *)i_TP_CRC_FW_60K->data, 0x4000); + } else if (mode == fw_image_64k) { + himax_sram_write(client, + (unsigned char *)i_TP_CRC_FW_64K->data); + burnFW_success = himax_sram_verify(client, + (unsigned char *)i_TP_CRC_FW_64K->data, 0x4000); + } else if (mode == fw_image_124k) { + himax_sram_write(client, + (unsigned char *)i_TP_CRC_FW_124K->data); + burnFW_success = himax_sram_verify(client, + (unsigned char *)i_TP_CRC_FW_124K->data, 0x4000); + } else if (mode == fw_image_128k) { + himax_sram_write(client, + (unsigned char *)i_TP_CRC_FW_128K->data); + burnFW_success = himax_sram_verify(client, + (unsigned char *)i_TP_CRC_FW_128K->data, 0x4000); } - else if(mode == fw_image_128k) - { - himax_sram_write(client, (i_TP_CRC_FW_128K)); - burnFW_success = himax_sram_verify(client, i_TP_CRC_FW_128K, 0x4000); - } - if (burnFW_success) - { - I("%s: Start to do CRC FW mode=%d \n", __func__,mode); - himax_sense_on(client, 0x00); // run CRC firmware + if (burnFW_success) { + I("%s: Start to do CRC FW mode=%d\n", __func__, mode); + himax_sense_on(client, 0x00); /* run CRC firmware*/ - while(true) - { + while (true) { msleep(100); - - tmp_addr[3] = 0x90; - tmp_addr[2] = 0x08; - tmp_addr[1] = 0x80; + tmp_addr[3] = 0x90; + tmp_addr[2] = 0x08; + tmp_addr[1] = 0x80; tmp_addr[0] = 0x94; - himax_register_read(client, tmp_addr, 1, tmp_data); - - I("%s: CRC from firmware is %x, %x, %x, %x \n", __func__,tmp_data[3], - tmp_data[2],tmp_data[1],tmp_data[0]); - - if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF && tmp_data[1] == 0xFF && tmp_data[0] == 0xFF) - { - } - else + himax_register_read(client, + tmp_addr, 1, tmp_data); + + I("%s: CRC from firmware is %x, %x, %x, %x\n", + __func__, tmp_data[3], tmp_data[2], + tmp_data[1], tmp_data[0]); +/* + if (tmp_data[3] == 0xFF && tmp_data[2] == 0xFF + && tmp_data[1] == 0xFF && tmp_data[0] == 0xFF) { + } else break; + */ + if (!(tmp_data[3] == 0xFF + && tmp_data[2] == 0xFF + && tmp_data[1] == 0xFF + && tmp_data[0] == 0xFF)) { + break; + } } CRC_value = tmp_data[3]; @@ -1259,30 +1416,32 @@ int himax_check_CRC(struct i2c_client *client, int mode) tmp_value = tmp_data[0] << 24; CRC_value += tmp_value; - I("%s: CRC Value is %x \n", __func__, CRC_value); + I("%s: CRC Value is %x\n", __func__, CRC_value); - //Close Remapping - //===================================== - // Re-map close - //===================================== - tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x00; - himax_flash_write_burst_lenth(client, tmp_addr, tmp_data, 4); - return CRC_value; - } - else - { + /*Close Remapping*/ + /*===================================== + Re-map close + =====================================*/ + tmp_addr[3] = 0x90; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x00; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x00; + himax_flash_write_burst_length(client, + tmp_addr, tmp_data, 4); + return CRC_value; + + } else { E("%s: SRAM write fail\n", __func__); return 0; - } - } - else - I("%s: NO CRC Check File \n", __func__); + } + } else + I("%s: NO CRC Check File\n", __func__); return 0; } -bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode) +bool Calculate_CRC_with_AP(unsigned char *FW_content, +int CRC_from_FW, int mode) { uint8_t tmp_data[4]; int i, j; @@ -1291,42 +1450,35 @@ bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode int CRC = 0xFFFFFFFF; int PolyNomial = 0x82F63B78; int length = 0; - + if (mode == fw_image_128k) length = 0x8000; else if (mode == fw_image_124k) length = 0x7C00; else if (mode == fw_image_64k) length = 0x4000; - else //if (mode == fw_image_60k) + else /*if (mode == fw_image_60k)*/ length = 0x3C00; - for (i = 0; i < length; i++) - { - fw_data = FW_content[i * 4 ]; - - for (j = 1; j < 4; j++) - { + for (i = 0 ; i < length ; i++) { + fw_data = FW_content[i * 4]; + + for (j = 1 ; j < 4 ; j++) { fw_data_2 = FW_content[i * 4 + j]; fw_data += (fw_data_2) << (8 * j); } CRC = fw_data ^ CRC; - for (j = 0; j < 32; j++) - { + for (j = 0 ; j < 32 ; j++) { if ((CRC % 2) != 0) - { - CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial; - } + CRC = ((CRC >> 1) & 0x7FFFFFFF) ^ PolyNomial; else - { - CRC = (((CRC >> 1) ^ 0x7FFFFFFF)& 0x7FFFFFFF); - } + CRC = (((CRC >> 1) ^ 0x7FFFFFFF) & 0x7FFFFFFF); } } - I("%s: CRC calculate from bin file is %x \n", __func__, CRC); + I("%s: CRC calculate from bin file is %x\n", __func__, CRC); tmp_data[0] = (uint8_t)(CRC >> 24); tmp_data[1] = (uint8_t)(CRC >> 16); @@ -1334,58 +1486,129 @@ bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode tmp_data[3] = (uint8_t) CRC; CRC = tmp_data[0]; - CRC += tmp_data[1] << 8; + CRC += tmp_data[1] << 8; CRC += tmp_data[2] << 16; CRC += tmp_data[3] << 24; - I("%s: CRC calculate from bin file REVERSE %x \n", __func__, CRC); - I("%s: CRC calculate from FWis %x \n", __func__, CRC_from_FW); + I("%s: CRC calculate from bin file REVERSE %x\n", __func__, CRC); + I("%s: CRC calculate from FWis %x\n", __func__, CRC_from_FW); if (CRC_from_FW == CRC) return true; else return false; } -#endif +/*#endif*/ -int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) +int himax_load_CRC_bin_file(struct i2c_client *client) +{ + int err = 0; + char *CRC_60_firmware_name = "HX_CRC_60.bin"; + char *CRC_64_firmware_name = "HX_CRC_64.bin"; + char *CRC_124_firmware_name = "HX_CRC_124.bin"; + char *CRC_128_firmware_name = "HX_CRC_128.bin"; + + I("%s,Entering\n", __func__); + if (i_TP_CRC_FW_60K == NULL) { + I("load file name = %s\n", CRC_60_firmware_name); + err = request_firmware(&i_TP_CRC_FW_60K, + CRC_60_firmware_name, private_ts->dev); + if (err < 0) { + E("%s,fail in line%d error code=%d\n", + __func__, __LINE__, err); + err = -1; + goto request_60k_fw_fail; + } + } else + I("%s already load i_TP_CRC_FW_60K\n", __func__); + + if (i_TP_CRC_FW_64K == NULL) { + I("load file name = %s\n", CRC_64_firmware_name); + err = request_firmware(&i_TP_CRC_FW_64K, + CRC_64_firmware_name, private_ts->dev); + if (err < 0) { + E("%s,fail in line%d error code=%d\n", + __func__, __LINE__, err); + err = -2; + goto request_64k_fw_fail; + } + } else + I("%s already load i_TP_CRC_FW_64K\n", __func__); + + if (i_TP_CRC_FW_124K == NULL) { + I("load file name = %s\n", CRC_124_firmware_name); + err = request_firmware(&i_TP_CRC_FW_124K, + CRC_124_firmware_name, private_ts->dev); + if (err < 0) { + E("%s,fail in line%d error code=%d\n", + __func__, __LINE__, err); + err = -3; + goto request_124k_fw_fail; + } + } else + I("%s already load i_TP_CRC_FW_124K\n", __func__); + + if (i_TP_CRC_FW_128K == NULL) { + I("load file name = %s\n", CRC_128_firmware_name); + err = request_firmware(&i_TP_CRC_FW_128K, + CRC_128_firmware_name, private_ts->dev); + if (err < 0) { + E("%s,fail in line%d error code=%d\n", + __func__, __LINE__, err); + err = -4; + goto request_128k_fw_fail; + } + } else + I("%s already load i_TP_CRC_FW_128K\n", __func__); + + return err; + +request_128k_fw_fail: + release_firmware(i_TP_CRC_FW_124K); +request_124k_fw_fail: + release_firmware(i_TP_CRC_FW_64K); +request_64k_fw_fail: + release_firmware(i_TP_CRC_FW_60K); +request_60k_fw_fail: + return err; +} +int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, +unsigned char *fw, int len, bool change_iref) { int CRC_from_FW = 0; int burnFW_success = 0; - if (len != 0x10000) //64k - { - E("%s: The file size is not 64K bytes\n", __func__); - return false; - } + if (len != 0x10000) {/*64k*/ + E("%s: The file size is not 64K bytes\n", __func__); + return false; + } himax_sense_off(client); msleep(500); himax_interface_on(client); - if (!himax_sector_erase(client, 0x00000)) - { - E("%s:Sector erase fail!Please restart the IC.\n", __func__); - return false; - } + if (!himax_sector_erase(client, 0x00000)) { + E("%s:Sector erase fail!Please restart the IC.\n", __func__); + return false; + } himax_flash_programming(client, fw, 0x0F000); - //burnFW_success = himax_83100_Verify(fw, len); - //if(burnFW_success==false) - // return burnFW_success; + /*burnFW_success = himax_83100_Verify(fw, len); + if(burnFW_success==false) + return burnFW_success;*/ - CRC_from_FW = himax_check_CRC(client,fw_image_60k); - burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_60k); - //himax_sense_on(client, 0x01); + CRC_from_FW = himax_check_CRC(client, fw_image_60k); + burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_60k); + /*himax_sense_on(client, 0x01);*/ return burnFW_success; } -int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) +int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, +unsigned char *fw, int len, bool change_iref) { int CRC_from_FW = 0; int burnFW_success = 0; - if (len != 0x10000) //64k - { - E("%s: The file size is not 64K bytes\n", __func__); - return false; + if (len != 0x10000) { /*64k*/ + E("%s: The file size is not 64K bytes\n", __func__); + return false; } himax_sense_off(client); msleep(500); @@ -1393,62 +1616,58 @@ int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char himax_chip_erase(client); himax_flash_programming(client, fw, len); - //burnFW_success = himax_83100_Verify(fw, len); - //if(burnFW_success==false) - // return burnFW_success; + /*burnFW_success = himax_83100_Verify(fw, len); + if(burnFW_success==false) + return burnFW_success;*/ - CRC_from_FW = himax_check_CRC(client,fw_image_64k); - burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_64k); - //himax_sense_on(client, 0x01); + CRC_from_FW = himax_check_CRC(client, fw_image_64k); + burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_64k); + /*himax_sense_on(client, 0x01);*/ return burnFW_success; } -int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) +int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, +unsigned char *fw, int len, bool change_iref) { int CRC_from_FW = 0; int burnFW_success = 0; - if (len != 0x20000) //128k - { - E("%s: The file size is not 128K bytes\n", __func__); - return false; + if (len != 0x20000) { /*128k*/ + E("%s: The file size is not 128K bytes\n", __func__); + return false; } himax_sense_off(client); msleep(500); himax_interface_on(client); - if (!himax_block_erase(client)) - { - E("%s:Block erase fail!Please restart the IC.\n", __func__); - return false; - } - - if (!himax_sector_erase(client, 0x10000)) - { - E("%s:Sector erase fail!Please restart the IC.\n", __func__); - return false; - } + if (!himax_block_erase(client)) { + E("%s:Block erase fail!Please restart the IC.\n", __func__); + return false; + } + if (!himax_sector_erase(client, 0x10000)) { + E("%s:Sector erase fail!Please restart the IC.\n", __func__); + return false; + } himax_flash_programming(client, fw, 0x1F000); + /*burnFW_success = himax_83100_Verify(fw, len); + if(burnFW_success==false) + return burnFW_success;*/ - //burnFW_success = himax_83100_Verify(fw, len); - //if(burnFW_success==false) - // return burnFW_success; - - CRC_from_FW = himax_check_CRC(client,fw_image_124k); - burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_124k); - //himax_sense_on(client, 0x01); + CRC_from_FW = himax_check_CRC(client, fw_image_124k); + burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_124k); + /*himax_sense_on(client, 0x01);*/ return burnFW_success; } -int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref) +int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, +unsigned char *fw, int len, bool change_iref) { int CRC_from_FW = 0; int burnFW_success = 0; - if (len != 0x20000) //128k - { - E("%s: The file size is not 128K bytes\n", __func__); - return false; + if (len != 0x20000) { /*128k*/ + E("%s: The file size is not 128K bytes\n", __func__); + return false; } himax_sense_off(client); msleep(500); @@ -1457,13 +1676,13 @@ int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned cha himax_flash_programming(client, fw, len); - //burnFW_success = himax_83100_Verify(fw, len); - //if(burnFW_success==false) - // return burnFW_success; + /*burnFW_success = himax_83100_Verify(fw, len); + if(burnFW_success==false) + return burnFW_success;*/ - CRC_from_FW = himax_check_CRC(client,fw_image_128k); - burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW,fw_image_128k); - //himax_sense_on(client, 0x01); + CRC_from_FW = himax_check_CRC(client, fw_image_128k); + burnFW_success = Calculate_CRC_with_AP(fw, CRC_from_FW, fw_image_128k); + /*himax_sense_on(client, 0x01); */ return burnFW_success; } @@ -1472,10 +1691,9 @@ void himax_touch_information(struct i2c_client *client) uint8_t cmd[4]; char data[12] = {0}; - I("%s:IC_TYPE =%d\n", __func__,IC_TYPE); + I("%s:IC_TYPE =%d\n", __func__, IC_TYPE); - if(IC_TYPE == HX_83100_SERIES_PWON) - { + if (IC_TYPE == HX_83100_SERIES_PWON) { cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xF8; himax_register_read(client, cmd, 1, data); @@ -1486,11 +1704,11 @@ void himax_touch_information(struct i2c_client *client) cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xFC; himax_register_read(client, cmd, 1, data); - if((data[1] & 0x04) == 0x04) { + if ((data[1] & 0x04) == 0x04) ic_data->HX_XY_REVERSE = true; - } else { + else ic_data->HX_XY_REVERSE = false; - } + ic_data->HX_Y_RES = data[3]*256; cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x01; cmd[0] = 0x00; himax_register_read(client, cmd, 1, data); @@ -1498,32 +1716,35 @@ void himax_touch_information(struct i2c_client *client) ic_data->HX_X_RES = data[1]*256 + data[2]; cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x8C; himax_register_read(client, cmd, 1, data); - if((data[0] & 0x01) == 1) { + if ((data[0] & 0x01) == 1) ic_data->HX_INT_IS_EDGE = true; - } else { + else ic_data->HX_INT_IS_EDGE = false; - } - if (ic_data->HX_RX_NUM > 40) + + if (ic_data->HX_RX_NUM > 40) ic_data->HX_RX_NUM = 29; - if (ic_data->HX_TX_NUM > 20) + if (ic_data->HX_TX_NUM > 20) ic_data->HX_TX_NUM = 16; - if (ic_data->HX_MAX_PT > 10) + if (ic_data->HX_MAX_PT > 10) ic_data->HX_MAX_PT = 10; - if (ic_data->HX_Y_RES > 2000) + if (ic_data->HX_Y_RES > 2000) ic_data->HX_Y_RES = 1280; - if (ic_data->HX_X_RES > 2000) + if (ic_data->HX_X_RES > 2000) ic_data->HX_X_RES = 720; #ifdef HX_EN_MUT_BUTTON cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0xE8; himax_register_read(client, cmd, 1, data); ic_data->HX_BT_NUM = data[3]; #endif - I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d \n", __func__,ic_data->HX_RX_NUM,ic_data->HX_TX_NUM,ic_data->HX_MAX_PT); - I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d \n", __func__,ic_data->HX_XY_REVERSE,ic_data->HX_Y_RES,ic_data->HX_X_RES); - I("%s:HX_INT_IS_EDGE =%d \n", __func__,ic_data->HX_INT_IS_EDGE); - } - else - { + I("%s:HX_RX_NUM =%d,HX_TX_NUM =%d,HX_MAX_PT=%d\n", + __func__, ic_data->HX_RX_NUM, + ic_data->HX_TX_NUM, ic_data->HX_MAX_PT); + I("%s:HX_XY_REVERSE =%d,HX_Y_RES =%d,HX_X_RES=%d\n", + __func__, ic_data->HX_XY_REVERSE, + ic_data->HX_Y_RES, ic_data->HX_X_RES); + I("%s:HX_INT_IS_EDGE =%d\n", + __func__, ic_data->HX_INT_IS_EDGE); + } else { ic_data->HX_RX_NUM = 0; ic_data->HX_TX_NUM = 0; ic_data->HX_BT_NUM = 0; @@ -1538,35 +1759,34 @@ void himax_touch_information(struct i2c_client *client) void himax_read_FW_ver(struct i2c_client *client) { uint8_t cmd[4]; - uint8_t data[64] = {0}; + uint8_t data[64]; - //===================================== - // Read FW version : 0x0000_E303 - //===================================== + /*===================================== + Read FW version : 0x0000_E303 + =====================================*/ cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x00; himax_register_read(client, cmd, 1, data); - ic_data->vendor_config_ver = data[3]<<8; + ic_data->vendor_config_ver = data[3] << 8; cmd[3] = 0x00; cmd[2] = 0x00; cmd[1] = 0xE3; cmd[0] = 0x04; himax_register_read(client, cmd, 1, data); ic_data->vendor_config_ver = data[0] | ic_data->vendor_config_ver; - I("CFG_VER : %X \n",ic_data->vendor_config_ver); + I("CFG_VER : %X\n", ic_data->vendor_config_ver); cmd[3] = 0x08; cmd[2] = 0x00; cmd[1] = 0x00; cmd[0] = 0x28; himax_register_read(client, cmd, 1, data); ic_data->vendor_fw_ver = data[0]<<8 | data[1]; - I("FW_VER : %X \n",ic_data->vendor_fw_ver); - + I("FW_VER : %X\n", ic_data->vendor_fw_ver); - return; } bool himax_ic_package_check(struct i2c_client *client) { -#if 0 +/*#if 0*/ +#ifdef HX_EN_CHECK_PATCH uint8_t cmd[3]; uint8_t data[3]; @@ -1574,260 +1794,284 @@ bool himax_ic_package_check(struct i2c_client *client) memset(data, 0x00, sizeof(data)); if (i2c_himax_read(client, 0xD1, cmd, 3, HIMAX_I2C_RETRY_TIMES) < 0) - return false ; + return false; if (i2c_himax_read(client, 0x31, data, 3, HIMAX_I2C_RETRY_TIMES) < 0) return false; - if((data[0] == 0x85 && data[1] == 0x29)) - { - IC_TYPE = HX_85XX_F_SERIES_PWON; - IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; - //Himax: Set FW and CFG Flash Address - FW_VER_MAJ_FLASH_ADDR = 64901; //0xFD85 - FW_VER_MAJ_FLASH_LENG = 1; - FW_VER_MIN_FLASH_ADDR = 64902; //0xFD86 - FW_VER_MIN_FLASH_LENG = 1; - CFG_VER_MAJ_FLASH_ADDR = 64928; //0xFDA0 - CFG_VER_MAJ_FLASH_LENG = 12; - CFG_VER_MIN_FLASH_ADDR = 64940; //0xFDAC - CFG_VER_MIN_FLASH_LENG = 12; - I("Himax IC package 852x F\n"); - } - if((data[0] == 0x85 && data[1] == 0x30) || (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29)) - { - IC_TYPE = HX_85XX_E_SERIES_PWON; - IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; - //Himax: Set FW and CFG Flash Address - FW_VER_MAJ_FLASH_ADDR = 133; //0x0085 - FW_VER_MAJ_FLASH_LENG = 1; - FW_VER_MIN_FLASH_ADDR = 134; //0x0086 - FW_VER_MIN_FLASH_LENG = 1; - CFG_VER_MAJ_FLASH_ADDR = 160; //0x00A0 - CFG_VER_MAJ_FLASH_LENG = 12; - CFG_VER_MIN_FLASH_ADDR = 172; //0x00AC - CFG_VER_MIN_FLASH_LENG = 12; - I("Himax IC package 852x E\n"); - } - else if((data[0] == 0x85 && data[1] == 0x31)) - { - IC_TYPE = HX_85XX_ES_SERIES_PWON; - IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; - //Himax: Set FW and CFG Flash Address - FW_VER_MAJ_FLASH_ADDR = 133; //0x0085 - FW_VER_MAJ_FLASH_LENG = 1; - FW_VER_MIN_FLASH_ADDR = 134; //0x0086 - FW_VER_MIN_FLASH_LENG = 1; - CFG_VER_MAJ_FLASH_ADDR = 160; //0x00A0 - CFG_VER_MAJ_FLASH_LENG = 12; - CFG_VER_MIN_FLASH_ADDR = 172; //0x00AC - CFG_VER_MIN_FLASH_LENG = 12; - I("Himax IC package 852x ES\n"); - } - else if ((data[0] == 0x85 && data[1] == 0x28) || (cmd[0] == 0x04 && cmd[1] == 0x85 && - (cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28))) { - IC_TYPE = HX_85XX_D_SERIES_PWON; - IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; - //Himax: Set FW and CFG Flash Address - FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085 - FW_VER_MAJ_FLASH_LENG = 1; - FW_VER_MIN_FLASH_ADDR = 134; // 0x0086 - FW_VER_MIN_FLASH_LENG = 1; - CFG_VER_MAJ_FLASH_ADDR = 160; // 0x00A0 + if ((data[0] == 0x85 && data[1] == 0x29)) { + IC_TYPE = HX_85XX_F_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + /*Himax: Set FW and CFG Flash Address*/ + FW_VER_MAJ_FLASH_ADDR = 64901; /*0xFD85*/ + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 64902; /*0xFD86*/ + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 64928; /*0xFDA0*/ CFG_VER_MAJ_FLASH_LENG = 12; - CFG_VER_MIN_FLASH_ADDR = 172; // 0x00AC + CFG_VER_MIN_FLASH_ADDR = 64940; /*0xFDAC*/ + CFG_VER_MIN_FLASH_LENG = 12; + I("Himax IC package 852x F\n"); + } + if ((data[0] == 0x85 && data[1] == 0x30) + || (cmd[0] == 0x05 && cmd[1] == 0x85 && cmd[2] == 0x29)) { + IC_TYPE = HX_85XX_E_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + /*Himax: Set FW and CFG Flash Address*/ + FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/ + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/ + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/ + CFG_VER_MAJ_FLASH_LENG = 12; + CFG_VER_MIN_FLASH_ADDR = 172; /*0x00AC*/ + CFG_VER_MIN_FLASH_LENG = 12; + I("Himax IC package 852x E\n"); + } else if ((data[0] == 0x85 && data[1] == 0x31)) { + IC_TYPE = HX_85XX_ES_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + /*Himax: Set FW and CFG Flash Address*/ + FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/ + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/ + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/ + CFG_VER_MAJ_FLASH_LENG = 12; + CFG_VER_MIN_FLASH_ADDR = 172; /*0x00AC*/ + CFG_VER_MIN_FLASH_LENG = 12; + I("Himax IC package 852x ES\n"); + } else if ((data[0] == 0x85 && data[1] == 0x28) + || (cmd[0] == 0x04 && cmd[1] == 0x85 + && (cmd[2] == 0x26 || cmd[2] == 0x27 + || cmd[2] == 0x28))) { + IC_TYPE = HX_85XX_D_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + /*Himax: Set FW and CFG Flash Address*/ + FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/ + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/ + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 160; /*0x00A0*/ + CFG_VER_MAJ_FLASH_LENG = 12; + CFG_VER_MIN_FLASH_ADDR = 172; /* 0x00AC*/ CFG_VER_MIN_FLASH_LENG = 12; I("Himax IC package 852x D\n"); - } else if ((data[0] == 0x85 && data[1] == 0x23) || (cmd[0] == 0x03 && cmd[1] == 0x85 && - (cmd[2] == 0x26 || cmd[2] == 0x27 || cmd[2] == 0x28 || cmd[2] == 0x29))) { - IC_TYPE = HX_85XX_C_SERIES_PWON; - IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW; - //Himax: Set FW and CFG Flash Address - FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085 - FW_VER_MAJ_FLASH_LENG = 1; - FW_VER_MIN_FLASH_ADDR = 134; // 0x0086 - FW_VER_MIN_FLASH_LENG = 1; - CFG_VER_MAJ_FLASH_ADDR = 135; // 0x0087 + } else if ((data[0] == 0x85 && data[1] == 0x23) || + (cmd[0] == 0x03 && cmd[1] == 0x85 && + (cmd[2] == 0x26 || cmd[2] == 0x27 || + cmd[2] == 0x28 || cmd[2] == 0x29))) { + IC_TYPE = HX_85XX_C_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW; + /*Himax: Set FW and CFG Flash Address*/ + FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/ + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 134; /*0x0086*/ + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 135; /*0x0087*/ CFG_VER_MAJ_FLASH_LENG = 12; - CFG_VER_MIN_FLASH_ADDR = 147; // 0x0093 + CFG_VER_MIN_FLASH_ADDR = 147; /*0x0093*/ CFG_VER_MIN_FLASH_LENG = 12; I("Himax IC package 852x C\n"); } else if ((data[0] == 0x85 && data[1] == 0x26) || - (cmd[0] == 0x02 && cmd[1] == 0x85 && - (cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) { + (cmd[0] == 0x02 && cmd[1] == 0x85 && + (cmd[2] == 0x19 || cmd[2] == 0x25 || cmd[2] == 0x26))) { IC_TYPE = HX_85XX_B_SERIES_PWON; IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW; - //Himax: Set FW and CFG Flash Address - FW_VER_MAJ_FLASH_ADDR = 133; // 0x0085 - FW_VER_MAJ_FLASH_LENG = 1; - FW_VER_MIN_FLASH_ADDR = 728; // 0x02D8 - FW_VER_MIN_FLASH_LENG = 1; - CFG_VER_MAJ_FLASH_ADDR = 692; // 0x02B4 + /*Himax: Set FW and CFG Flash Address*/ + FW_VER_MAJ_FLASH_ADDR = 133; /*0x0085*/ + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 728; /*0x02D8*/ + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 692; /*0x02B4*/ CFG_VER_MAJ_FLASH_LENG = 3; - CFG_VER_MIN_FLASH_ADDR = 704; // 0x02C0 + CFG_VER_MIN_FLASH_ADDR = 704; /*0x02C0*/ CFG_VER_MIN_FLASH_LENG = 3; I("Himax IC package 852x B\n"); } else if ((data[0] == 0x85 && data[1] == 0x20) || (cmd[0] == 0x01 && - cmd[1] == 0x85 && cmd[2] == 0x19)) { + cmd[1] == 0x85 && cmd[2] == 0x19)) { IC_TYPE = HX_85XX_A_SERIES_PWON; IC_CHECKSUM = HX_TP_BIN_CHECKSUM_SW; I("Himax IC package 852x A\n"); } else { E("Himax IC package incorrect!!\n"); - }*/ + } #else - IC_TYPE = HX_83100_SERIES_PWON; - IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; - //Himax: Set FW and CFG Flash Address - FW_VER_MAJ_FLASH_ADDR = 57384; //0xE028 - FW_VER_MAJ_FLASH_LENG = 1; - FW_VER_MIN_FLASH_ADDR = 57385; //0xE029 - FW_VER_MIN_FLASH_LENG = 1; - CFG_VER_MAJ_FLASH_ADDR = 58115; //0xE303 - CFG_VER_MAJ_FLASH_LENG = 1; - CFG_VER_MIN_FLASH_ADDR = 58116; //0xE304 - CFG_VER_MIN_FLASH_LENG = 1; + IC_TYPE = HX_83100_SERIES_PWON; + IC_CHECKSUM = HX_TP_BIN_CHECKSUM_CRC; + /*Himax: Set FW and CFG Flash Address*/ + FW_VER_MAJ_FLASH_ADDR = 57384; /*0xE028*/ + FW_VER_MAJ_FLASH_LENG = 1; + FW_VER_MIN_FLASH_ADDR = 57385; /*0xE029*/ + FW_VER_MIN_FLASH_LENG = 1; + CFG_VER_MAJ_FLASH_ADDR = 58115; /*0xE303*/ + CFG_VER_MAJ_FLASH_LENG = 1; + CFG_VER_MIN_FLASH_ADDR = 58116; /*0xE304*/ + CFG_VER_MIN_FLASH_LENG = 1; I("Himax IC package 83100_in\n"); #endif return true; } -void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length) +void himax_read_event_stack(struct i2c_client *client, +uint8_t *buf, uint8_t length) { uint8_t cmd[4]; - cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00; - if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); + cmd[3] = 0x90; cmd[2] = 0x06; + cmd[1] = 0x00; cmd[0] = 0x00; + if (i2c_himax_write(client, 0x00, + cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); } - cmd[0] = 0x00; - if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); + cmd[0] = 0x00; + if (i2c_himax_write(client, 0x0C, + cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); } - i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES); + i2c_himax_read(client, 0x08, + buf, length, HIMAX_I2C_RETRY_TIMES); } -#if 0 -static void himax_83100_Flash_Write(uint8_t * reg_byte, uint8_t * write_data) +/*#if 0*/ +#ifdef HX_EN_CHECK_PATCH +static void himax_83100_Flash_Write(uint8_t *reg_byte, uint8_t *write_data) { uint8_t tmpbyte[2]; - if ( i2c_himax_write(private_ts->client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x00, + ®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x01, + ®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x02, + ®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, + 0x03, ®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, + 0x04, &write_data[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, + 0x05, &write_data[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, + 0x06, &write_data[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, + 0x07, &write_data[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if (isBusrtOn == false) - { - tmpbyte[0] = 0x01; - if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { - E("%s: i2c access fail!\n", __func__); - return; + if (isBusrtOn == false) { + tmpbyte[0] = 0x01; + if (i2c_himax_write(private_ts->client, + 0x0C, &tmpbyte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + E("%s: i2c access fail!\n", __func__); + return; } - } + } } #endif -#if 0 -static void himax_83100_Flash_Burst_Write(uint8_t * reg_byte, uint8_t * write_data) +/*#if 0*/ +#ifdef HX_EN_CHECK_PATCH +static void himax_83100_Flash_Burst_Write +(uint8_t *reg_byte, uint8_t *write_data) { - //uint8_t tmpbyte[2]; + /*uint8_t tmpbyte[2];*/ int i = 0; - if ( i2c_himax_write(private_ts->client, 0x00 ,®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x00, + ®_byte[0], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x01 ,®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x01, + ®_byte[1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x02 ,®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x02, + ®_byte[2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x03 ,®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x03, + ®_byte[3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - // Write 256 bytes with continue burst mode - for (i = 0; i < 256; i = i + 4) - { - if ( i2c_himax_write(private_ts->client, 0x04 ,&write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + /*Write 256 bytes with continue burst mode*/ + for (i = 0 ; i < 256 ; i = i + 4) { + if (i2c_himax_write(private_ts->client, + 0x04, &write_data[i], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x05 ,&write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x05, + &write_data[i+1], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x06 ,&write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x06, + &write_data[i+2], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - if ( i2c_himax_write(private_ts->client, 0x07 ,&write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(private_ts->client, 0x07, + &write_data[i+3], 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); return; } - } + } - //if (isBusrtOn == false) - //{ - // tmpbyte[0] = 0x01; - // if ( i2c_himax_write(private_ts->client, 0x0C ,&tmpbyte[0], 1, 3) < 0) { - // E("%s: i2c access fail!\n", __func__); - // return; - // } - //} + /*if (isBusrtOn == false) + { + tmpbyte[0] = 0x01; + if (i2c_himax_write(private_ts->client, + 0x0C, &tmpbyte[0], 1, 3) < 0) { + E("%s: i2c access fail!\n", __func__); + return; + }*/ } #endif -#if 0 +/*#if 0*/ +#ifdef HX_EN_CHECK_PATCH static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size) { uint8_t tmp_addr[4]; @@ -1835,49 +2079,51 @@ static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size) uint8_t out_buffer[20]; uint8_t in_buffer[260]; - int fail_addr=0, fail_cnt=0; + int fail_addr = 0, fail_cnt = 0; int page_prog_start = 0; int i = 0; himax_interface_on(private_ts->client); himax_burst_enable(private_ts->client, 0); - //===================================== - // SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 - //===================================== - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; - tmp_data[3] = 0x00; tmp_data[2] = 0x02; tmp_data[1] = 0x07; tmp_data[0] = 0x80; + /*===================================== + SPI Transfer Format : 0x8000_0010 ==> 0x0002_0780 + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x10; + tmp_data[3] = 0x00; tmp_data[2] = 0x02; + tmp_data[1] = 0x07; tmp_data[0] = 0x80; himax_83100_Flash_Write(tmp_addr, tmp_data); - for (page_prog_start = 0; page_prog_start < FW_Size; page_prog_start = page_prog_start + 256) - { - //================================= - // SPI Transfer Control - // Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF - // Set read start address : 0x8000_0028 ==> 0x0000_0000 - // Set command : 0x8000_0024 ==> 0x0000_003B - //================================= - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; - tmp_data[3] = 0x69; tmp_data[2] = 0x40; tmp_data[1] = 0x02; tmp_data[0] = 0xFF; + for (page_prog_start = 0; page_prog_start < FW_Size; + page_prog_start = page_prog_start + 256) { + /*===================================== + SPI Transfer Control + Set 256 bytes page read : 0x8000_0020 ==> 0x6940_02FF + Set read start address : 0x8000_0028 ==> 0x0000_0000 + Set command : 0x8000_0024 ==> 0x0000_003B + =====================================*/ + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x20; + tmp_data[3] = 0x69; tmp_data[2] = 0x40; + tmp_data[1] = 0x02; tmp_data[0] = 0xFF; himax_83100_Flash_Write(tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; - if (page_prog_start < 0x100) - { + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x28; + if (page_prog_start < 0x100) { tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = (uint8_t)page_prog_start; - } - else if (page_prog_start >= 0x100 && page_prog_start < 0x10000) - { + } else if (page_prog_start >= 0x100 + && page_prog_start < 0x10000) { tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = (uint8_t)(page_prog_start >> 8); tmp_data[0] = (uint8_t)page_prog_start; - } - else if (page_prog_start >= 0x10000 && page_prog_start < 0x1000000) - { + } else if (page_prog_start >= 0x10000 + && page_prog_start < 0x1000000) { tmp_data[3] = 0x00; tmp_data[2] = (uint8_t)(page_prog_start >> 16); tmp_data[1] = (uint8_t)(page_prog_start >> 8); @@ -1885,65 +2131,73 @@ static bool himax_83100_Verify(uint8_t *FW_File, int FW_Size) } himax_83100_Flash_Write(tmp_addr, tmp_data); - tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x00; tmp_data[0] = 0x3B; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x24; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x00; tmp_data[0] = 0x3B; himax_83100_Flash_Write(tmp_addr, tmp_data); - //================================== - // AHB_I2C Burst Read - // Set SPI data register : 0x8000_002C ==> 0x00 - //================================== + /*================================== + AHB_I2C Burst Read + Set SPI data register : 0x8000_002C ==> 0x00 + ==================================*/ out_buffer[0] = 0x2C; out_buffer[1] = 0x00; out_buffer[2] = 0x00; out_buffer[3] = 0x80; - i2c_himax_write(private_ts->client, 0x00 ,out_buffer, 4, HIMAX_I2C_RETRY_TIMES); + i2c_himax_write(private_ts->client, 0x00, + out_buffer, 4, HIMAX_I2C_RETRY_TIMES); - //================================== - // Read access : 0x0C ==> 0x00 - //================================== + /*================================== + Read access : 0x0C ==> 0x00 + ==================================*/ out_buffer[0] = 0x00; - i2c_himax_write(private_ts->client, 0x0C ,out_buffer, 1, HIMAX_I2C_RETRY_TIMES); - - //================================== - // Read 128 bytes two times - //================================== - i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES); + i2c_himax_write(private_ts->client, 0x0C, + out_buffer, 1, HIMAX_I2C_RETRY_TIMES); + + /*================================== + Read 128 bytes two times + ==================================*/ + i2c_himax_read(private_ts->client, 0x08, + in_buffer, 128, HIMAX_I2C_RETRY_TIMES); for (i = 0; i < 128; i++) flash_buffer[i + page_prog_start] = in_buffer[i]; - i2c_himax_read(private_ts->client, 0x08 ,in_buffer, 128, HIMAX_I2C_RETRY_TIMES); + i2c_himax_read(private_ts->client, 0x08, + in_buffer, 128, HIMAX_I2C_RETRY_TIMES); for (i = 0; i < 128; i++) - flash_buffer[(i + 128) + page_prog_start] = in_buffer[i]; - - //tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; - //himax_register_read(tmp_addr, 32, out in_buffer); - //for (int i = 0; i < 128; i++) - // flash_buffer[i + page_prog_start] = in_buffer[i]; - //tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; - //himax_register_read(tmp_addr, 32, out in_buffer); - //for (int i = 0; i < 128; i++) - // flash_buffer[i + page_prog_start] = in_buffer[i]; - + flash_buffer[(i + 128) + + page_prog_start] = in_buffer[i]; + + /*tmp_addr[3] = 0x80; + tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; + himax_register_read(tmp_addr, 32, out in_buffer); + for (int i = 0; i < 128; i++) + flash_buffer[i + page_prog_start] = in_buffer[i]; + tmp_addr[3] = 0x80; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x00; tmp_addr[0] = 0x2C; + himax_register_read(tmp_addr, 32, out in_buffer); + for (int i = 0; i < 128; i++) + flash_buffer[i + page_prog_start] = in_buffer[i]; + */ I("%s:Verify Progress: %x\n", __func__, page_prog_start); } fail_cnt = 0; - for (i = 0; i < FW_Size; i++) - { - if (FW_File[i] != flash_buffer[i]) - { + for (i = 0; i < FW_Size; i++) { + if (FW_File[i] != flash_buffer[i]) { if (fail_cnt == 0) fail_addr = i; fail_cnt++; - //E("%s Fail Block:%x\n", __func__, i); - //return false; + /*E("%s Fail Block:%x\n", __func__, i); + return false;*/ } } - if (fail_cnt > 0) - { - E("%s:Start Fail Block:%x and fail block count=%x\n" , __func__,fail_addr,fail_cnt); + if (fail_cnt > 0) { + E("%s:Start Fail Block:%x and fail block count=%x\n", + __func__, fail_addr, fail_cnt); return false; } @@ -1959,56 +2213,60 @@ void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data) int cnt = 0; unsigned char tmp_addr[4]; unsigned char tmp_data[4]; - uint8_t max_i2c_size = 32; + uint8_t max_i2c_size = 32; int total_size = ic_data->HX_TX_NUM * ic_data->HX_RX_NUM * 2; int total_size_4bytes = total_size / 4; int total_read_times = 0; unsigned long address = 0x08000468; - tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64; - tmp_data[3] = 0x00; tmp_data[2] = 0x00; tmp_data[1] = 0x5A; tmp_data[0] = 0xA5; + + tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x04; tmp_addr[0] = 0x64; + tmp_data[3] = 0x00; tmp_data[2] = 0x00; + tmp_data[1] = 0x5A; tmp_data[0] = 0xA5; himax_flash_write_burst(client, tmp_addr, tmp_data); - do - { + do { cnt++; himax_register_read(client, tmp_addr, 1, tmp_data); - usleep_range(10000, 20000); + usleep_range(9999, 10000); } while ((tmp_data[1] != 0xA5 || tmp_data[0] != 0x5A) && cnt < 100); - tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x68; - if (total_size_4bytes % max_i2c_size == 0) - { + tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x04; tmp_addr[0] = 0x68; + if (total_size_4bytes % max_i2c_size == 0) total_read_times = total_size_4bytes / max_i2c_size; - } else - { total_read_times = total_size_4bytes / max_i2c_size + 1; - } - for (i = 0; i < (total_read_times); i++) - { - if ( total_size_4bytes >= max_i2c_size) - { - himax_register_read(client, tmp_addr, max_i2c_size, &info_data[i*max_i2c_size*4]); + + for (i = 0 ; i < (total_read_times) ; i++) { + if (total_size_4bytes >= max_i2c_size) { + himax_register_read(client, tmp_addr, + max_i2c_size, + &info_data[i*max_i2c_size*4]); total_size_4bytes = total_size_4bytes - max_i2c_size; + } else { + himax_register_read(client, tmp_addr, + total_size_4bytes % max_i2c_size, + &info_data[i*max_i2c_size*4]); } - else - { - himax_register_read(client, tmp_addr, total_size_4bytes % max_i2c_size, &info_data[i*max_i2c_size*4]); - } - address += max_i2c_size*4; - tmp_addr[1] = (uint8_t)((address>>8)&0x00FF); - tmp_addr[0] = (uint8_t)((address)&0x00FF); - } - tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; tmp_addr[1] = 0x04; tmp_addr[0] = 0x64; - tmp_data[3] = 0x11; tmp_data[2] = 0x22; tmp_data[1] = 0x33; tmp_data[0] = 0x44; + address += max_i2c_size * 4; + tmp_addr[1] = (uint8_t)((address>>8) & 0x00FF); + tmp_addr[0] = (uint8_t)((address) & 0x00FF); + } + tmp_addr[3] = 0x08; tmp_addr[2] = 0x00; + tmp_addr[1] = 0x04; tmp_addr[0] = 0x64; + tmp_data[3] = 0x11; tmp_data[2] = 0x22; + tmp_data[1] = 0x33; tmp_data[0] = 0x44; himax_flash_write_burst(client, tmp_addr, tmp_data); } -//ts_work -int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max){ +/*ts_work*/ +int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max) +{ int RawDataLen; - if (raw_cnt_rmd != 0x00) { - RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+3)*4) - 1; - }else{ - RawDataLen = 124 - ((HX_MAX_PT+raw_cnt_max+2)*4) - 1; - } + + if (raw_cnt_rmd != 0x00) + RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 3) * 4) - 1; + else + RawDataLen = 124 - ((HX_MAX_PT + raw_cnt_max + 2) * 4) - 1; + return RawDataLen; } @@ -2016,40 +2274,40 @@ bool read_event_stack(struct i2c_client *client, uint8_t *buf, int length) { uint8_t cmd[4]; - if(length > 56) + if (length > 56) length = 124; - //===================== - //AHB I2C Burst Read - //===================== + /*===================== + AHB I2C Burst Read + =====================*/ cmd[0] = 0x31; - if ( i2c_himax_write(client, 0x13 ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x13, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); goto err_workqueue_out; } cmd[0] = 0x10; - if ( i2c_himax_write(client, 0x0D ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x0D, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); goto err_workqueue_out; } - //===================== - //Read event stack - //===================== + /*===================== + Read event stack + =====================*/ cmd[3] = 0x90; cmd[2] = 0x06; cmd[1] = 0x00; cmd[0] = 0x00; - if ( i2c_himax_write(client, 0x00 ,cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x00, cmd, 4, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); goto err_workqueue_out; } cmd[0] = 0x00; - if ( i2c_himax_write(client, 0x0C ,cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { + if (i2c_himax_write(client, 0x0C, cmd, 1, HIMAX_I2C_RETRY_TIMES) < 0) { E("%s: i2c access fail!\n", __func__); goto err_workqueue_out; } - i2c_himax_read(client, 0x08, buf, length,HIMAX_I2C_RETRY_TIMES); + i2c_himax_read(client, 0x08, buf, length, HIMAX_I2C_RETRY_TIMES); return 1; - - err_workqueue_out: + +err_workqueue_out: return 0; } @@ -2057,62 +2315,67 @@ bool post_read_event_stack(struct i2c_client *client) { return 1; } -bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf) //return checksum value +bool diag_check_sum(uint8_t hx_touch_info_size, +uint8_t *buf) /*return checksum value*/ { uint16_t check_sum_cal = 0; int i; - //Check 124th byte CRC - for (i = hx_touch_info_size, check_sum_cal = 0; i < 124; i=i+2) - { - check_sum_cal += (buf[i+1]*256 + buf[i]); - } - if (check_sum_cal % 0x10000 != 0) - { - I("%s: diag check sum fail! check_sum_cal=%X, hx_touch_info_size=%d, \n",__func__,check_sum_cal, hx_touch_info_size); + /*Check 124th byte CRC*/ + for (i = hx_touch_info_size, check_sum_cal = 0 ; i < 124 ; i = i + 2) + check_sum_cal += (buf[i + 1] * 256 + buf[i]); + + if (check_sum_cal % 0x10000 != 0) { + I("%s:diag chksum fail!check_sum_cal=%X,hx_touchinfo_sz=%d,\n", + __func__, check_sum_cal, hx_touch_info_size); return 0; } return 1; } - -void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data) +void diag_parse_raw_data(int hx_touch_info_size, +int RawDataLen, int mul_num, int self_num, uint8_t *buf, +uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data) { int RawDataLen_word; int index = 0; - int temp1, temp2,i; - - if (buf[hx_touch_info_size] == 0x3A && buf[hx_touch_info_size+1] == 0xA3 && buf[hx_touch_info_size+2] > 0 && buf[hx_touch_info_size+3] == diag_cmd+5 ) - { - RawDataLen_word = RawDataLen/2; - index = (buf[hx_touch_info_size+2] - 1) * RawDataLen_word; - //I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num); - for (i = 0; i < RawDataLen_word; i++) - { + int temp1, temp2, i; + + if (buf[hx_touch_info_size] == 0x3A && + buf[hx_touch_info_size + 1] == 0xA3 && + buf[hx_touch_info_size + 2] > 0 && + buf[hx_touch_info_size + 3] == diag_cmd + 5) { + RawDataLen_word = RawDataLen / 2; + index = (buf[hx_touch_info_size + 2] - 1) * RawDataLen_word; + /*I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", + index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num);*/ + for (i = 0; i < RawDataLen_word; i++) { temp1 = index + i; - if (temp1 < mul_num) - { //mutual - mutual_data[index + i] = buf[i*2 + hx_touch_info_size+4+1]*256 + buf[i*2 + hx_touch_info_size+4]; //4: RawData Header, 1:HSB - } - else - {//self + if (temp1 < mul_num) { /*mutual*/ + /*4: RawData Header, 1:HSB */ + mutual_data[index + i] + = buf[i*2 + hx_touch_info_size + 4 + 1] + * 256 + + buf[i * 2 + hx_touch_info_size + 4]; + } else { /*self*/ temp1 = i + index; temp2 = self_num + mul_num; - + if (temp1 >= temp2) - { break; - } - self_data[i+index-mul_num] = buf[i*2 + hx_touch_info_size+4]; //4: RawData Header - self_data[i+index-mul_num+1] = buf[i*2 + hx_touch_info_size+4+1]; + /*4: RawData Header*/ + self_data[i + index - mul_num] + = buf[i * 2 + hx_touch_info_size + 4]; + self_data[i + index - mul_num + 1] + = buf[i * 2 + hx_touch_info_size + 4 + 1]; } } - } - else - { + } else { I("[HIMAX TP MSG]%s: header format is wrong!\n", __func__); - I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", index, buf[56], buf[57], buf[58], buf[59], mul_num, self_num); + I("Header[%d]: %x, %x, %x, %x, mutual: %d, self: %d\n", + index, buf[56], buf[57], buf[58], buf[59], + mul_num, self_num); } } diff --git a/drivers/input/touchscreen/hxchipset/himax_ic.h b/drivers/input/touchscreen/hxchipset/himax_ic.h index 18cd12b8b36f..ce7d0d49c362 100644 --- a/drivers/input/touchscreen/hxchipset/himax_ic.h +++ b/drivers/input/touchscreen/hxchipset/himax_ic.h @@ -18,7 +18,6 @@ #include - #define HX_85XX_A_SERIES_PWON 1 #define HX_85XX_B_SERIES_PWON 2 #define HX_85XX_C_SERIES_PWON 3 @@ -40,43 +39,110 @@ enum fw_image_type { }; int himax_hand_shaking(struct i2c_client *client); -void himax_set_SMWP_enable(struct i2c_client *client,uint8_t SMWP_enable); -void himax_get_SMWP_enable(struct i2c_client *client,uint8_t *tmp_data); -void himax_set_HSEN_enable(struct i2c_client *client,uint8_t HSEN_enable); -void himax_get_HSEN_enable(struct i2c_client *client,uint8_t *tmp_data); +void himax_set_SMWP_enable(struct i2c_client *client, uint8_t SMWP_enable); +void himax_get_SMWP_enable(struct i2c_client *client, uint8_t *tmp_data); +void himax_set_HSEN_enable(struct i2c_client *client, uint8_t HSEN_enable); +void himax_get_HSEN_enable(struct i2c_client *client, uint8_t *tmp_data); void himax_diag_register_set(struct i2c_client *client, uint8_t diag_command); -void himax_flash_dump_func(struct i2c_client *client, uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer); + +void himax_flash_dump_func(struct i2c_client *client, +uint8_t local_flash_command, int Flash_Size, uint8_t *flash_buffer); + int himax_chip_self_test(struct i2c_client *client); -int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte); ////himax_83100_BURST_INC0_EN -void himax_register_read(struct i2c_client *client, uint8_t *read_addr, int read_length, uint8_t *read_data); ////RegisterRead83100 -void himax_flash_read(struct i2c_client *client, uint8_t *reg_byte, uint8_t *read_data); ////himax_83100_Flash_Read -void himax_flash_write_burst(struct i2c_client *client, uint8_t * reg_byte, uint8_t * write_data); ////himax_83100_Flash_Write_Burst -int himax_flash_write_burst_lenth(struct i2c_client *client, uint8_t *reg_byte, uint8_t *write_data, int length); ////himax_83100_Flash_Write_Burst_lenth -int himax_register_write(struct i2c_client *client, uint8_t *write_addr, int write_length, uint8_t *write_data); ////RegisterWrite83100 -void himax_sense_off(struct i2c_client *client); ////himax_83100_SenseOff -void himax_interface_on(struct i2c_client *client); ////himax_83100_Interface_on + +/*himax_83100_BURST_INC0_EN*/ +int himax_burst_enable(struct i2c_client *client, uint8_t auto_add_4_byte); + +/*RegisterRead83100*/ +void himax_register_read(struct i2c_client *client, + uint8_t *read_addr, int read_length, uint8_t *read_data); + +/*himax_83100_Flash_Read*/ +void himax_flash_read(struct i2c_client *client, + uint8_t *reg_byte, uint8_t *read_data); + +/*himax_83100_Flash_Write_Burst*/ +void himax_flash_write_burst(struct i2c_client *client, + uint8_t *reg_byte, uint8_t *write_data); + +/*himax_83100_Flash_Write_Burst_length*/ +int himax_flash_write_burst_length(struct i2c_client *client, + uint8_t *reg_byte, uint8_t *write_data, int length); + +/*RegisterWrite83100*/ +int himax_register_write(struct i2c_client *client, + uint8_t *write_addr, int write_length, uint8_t *write_data); + +/*himax_83100_SenseOff*/ +void himax_sense_off(struct i2c_client *client); +/*himax_83100_Interface_on*/ +void himax_interface_on(struct i2c_client *client); bool wait_wip(struct i2c_client *client, int Timing); -void himax_sense_on(struct i2c_client *client, uint8_t FlashMode); ////himax_83100_SenseOn -void himax_chip_erase(struct i2c_client *client); ////himax_83100_Chip_Erase -bool himax_block_erase(struct i2c_client *client); ////himax_83100_Block_Erase -bool himax_sector_erase(struct i2c_client *client, int start_addr); ////himax_83100_Sector_Erase -void himax_sram_write(struct i2c_client *client, uint8_t *FW_content); ////himax_83100_Sram_Write -bool himax_sram_verify(struct i2c_client *client, uint8_t *FW_File, int FW_Size); ////himax_83100_Sram_Verify -void himax_flash_programming(struct i2c_client *client, uint8_t *FW_content, int FW_Size); ////himax_83100_Flash_Programming -bool himax_check_chip_version(struct i2c_client *client); ////himax_83100_CheckChipVersion -int himax_check_CRC(struct i2c_client *client, int mode); ////himax_83100_Check_CRC -bool Calculate_CRC_with_AP(unsigned char *FW_content , int CRC_from_FW, int mode); -int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref); -int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref); -int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref); -int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, unsigned char *fw, int len, bool change_iref); + +/*himax_83100_SenseOn*/ +void himax_sense_on(struct i2c_client *client, + uint8_t FlashMode); + +/*himax_83100_Chip_Erase*/ +void himax_chip_erase(struct i2c_client *client); +/*himax_83100_Block_Erase*/ +bool himax_block_erase(struct i2c_client *client); + +/*himax_83100_Sector_Erase*/ +bool himax_sector_erase(struct i2c_client *client, int start_addr); + +/*himax_83100_Sram_Write*/ +void himax_sram_write(struct i2c_client *client, uint8_t *FW_content); + +/*himax_83100_Sram_Verify*/ +bool himax_sram_verify(struct i2c_client *client, + uint8_t *FW_File, int FW_Size); + +/*himax_83100_Flash_Programming*/ +void himax_flash_programming(struct i2c_client *client, + uint8_t *FW_content, int FW_Size); + +/*himax_83100_CheckChipVersion*/ +bool himax_check_chip_version(struct i2c_client *client); + +/*himax_83100_Check_CRC*/ +int himax_check_CRC(struct i2c_client *client, int mode); + +bool Calculate_CRC_with_AP(unsigned char *FW_content, + int CRC_from_FW, int mode); + +int fts_ctpm_fw_upgrade_with_sys_fs_60k(struct i2c_client *client, + unsigned char *fw, int len, bool change_iref); + +int fts_ctpm_fw_upgrade_with_sys_fs_64k(struct i2c_client *client, + unsigned char *fw, int len, bool change_iref); + +int fts_ctpm_fw_upgrade_with_sys_fs_124k(struct i2c_client *client, + unsigned char *fw, int len, bool change_iref); + +int fts_ctpm_fw_upgrade_with_sys_fs_128k(struct i2c_client *client, + unsigned char *fw, int len, bool change_iref); + void himax_touch_information(struct i2c_client *client); void himax_read_FW_ver(struct i2c_client *client); bool himax_ic_package_check(struct i2c_client *client); -void himax_read_event_stack(struct i2c_client *client, uint8_t *buf, uint8_t length); + +void himax_read_event_stack(struct i2c_client *client, + uint8_t *buf, uint8_t length); + int cal_data_len(int raw_cnt_rmd, int HX_MAX_PT, int raw_cnt_max); bool read_event_stack(struct i2c_client *client, uint8_t *buf_ts, int length); bool post_read_event_stack(struct i2c_client *client); -bool diag_check_sum( uint8_t hx_touch_info_size, uint8_t *buf_ts); //return checksum value -void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, int mul_num, int self_num, uint8_t *buf_ts, uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data); -void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data); \ No newline at end of file + +/*return checksum value*/ +bool diag_check_sum(uint8_t hx_touch_info_size, uint8_t *buf_ts); + +void diag_parse_raw_data(int hx_touch_info_size, int RawDataLen, + int mul_num, int self_num, uint8_t *buf_ts, + uint8_t diag_cmd, int16_t *mutual_data, int16_t *self_data); + +void himax_get_DSRAM_data(struct i2c_client *client, uint8_t *info_data); +extern struct himax_ts_data *private_ts; +extern struct himax_ic_data *ic_data; + +int himax_load_CRC_bin_file(struct i2c_client *client); diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.c b/drivers/input/touchscreen/hxchipset/himax_platform.c index 7e8a1d6572c5..309bb5e01073 100644 --- a/drivers/input/touchscreen/hxchipset/himax_platform.c +++ b/drivers/input/touchscreen/hxchipset/himax_platform.c @@ -16,6 +16,13 @@ #include "himax_platform.h" #include "himax_common.h" +#if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) +#define D(x...) pr_info("[HXTP][DEBUG] " x) +#define I(x...) pr_info("[HXTP][INFO] " x) +#define W(x...) pr_info("[HXTP][WARNING] " x) +#define E(x...) pr_info("[HXTP][ERROR] " x) +#endif + int irq_enable_count = 0; #ifdef HX_SMART_WAKEUP #define TS_WAKE_LOCK_TIMEOUT (2 * HZ) @@ -25,16 +32,7 @@ int irq_enable_count = 0; #define PINCTRL_STATE_SUSPEND "pmx_ts_suspend" #define PINCTRL_STATE_RELEASE "pmx_ts_release" -extern struct himax_ic_data* ic_data; -extern void himax_ts_work(struct himax_ts_data *ts); -extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer); -extern int himax_ts_init(struct himax_ts_data *ts); - -extern int tp_rst_gpio; - -#ifdef HX_TP_PROC_DIAG -extern uint8_t getDiagCommand(void); -#endif +/*extern int himax_ts_init(struct himax_ts_data *ts);*/ void himax_vk_parser(struct device_node *dt, struct himax_i2c_platform_data *pdata) @@ -49,30 +47,34 @@ void himax_vk_parser(struct device_node *dt, if (node == NULL) { I(" DT-No vk info in DT"); return; + } else { while ((pp = of_get_next_child(node, pp))) cnt++; if (!cnt) return; - vk = kzalloc(cnt * (sizeof *vk), GFP_KERNEL); - if (!vk) - return; + vk = kcalloc(cnt, sizeof(*vk), GFP_KERNEL); pp = NULL; while ((pp = of_get_next_child(node, pp))) { if (of_property_read_u32(pp, "idx", &data) == 0) vk[i].index = data; - if (of_property_read_u32_array(pp, "range", coords, 4) == 0) { - vk[i].x_range_min = coords[0], vk[i].x_range_max = coords[1]; - vk[i].y_range_min = coords[2], vk[i].y_range_max = coords[3]; + if (of_property_read_u32_array(pp, "range", + coords, 4) == 0) { + vk[i].x_range_min = coords[0], + vk[i].x_range_max = coords[1]; + vk[i].y_range_min = coords[2], + vk[i].y_range_max = coords[3]; } else I(" range faile"); i++; } pdata->virtual_key = vk; for (i = 0; i < cnt; i++) - I(" vk[%d] idx:%d x_min:%d, y_max:%d", i,pdata->virtual_key[i].index, - pdata->virtual_key[i].x_range_min, pdata->virtual_key[i].y_range_max); + I(" vk[%d] idx:%d x_min:%d, y_max:%d", + i, pdata->virtual_key[i].index, + pdata->virtual_key[i].x_range_min, + pdata->virtual_key[i].y_range_max); } } @@ -89,25 +91,31 @@ int himax_parse_dt(struct himax_ts_data *ts, if (prop) { coords_size = prop->length / sizeof(u32); if (coords_size != 4) - D(" %s:Invalid panel coords size %d", __func__, coords_size); + D(" %s:Invalid panel coords size %d", + __func__, coords_size); } - if (of_property_read_u32_array(dt, "himax,panel-coords", coords, coords_size) == 0) { + if (of_property_read_u32_array(dt, "himax,panel-coords", + coords, coords_size) == 0) { pdata->abs_x_min = coords[0], pdata->abs_x_max = coords[1]; pdata->abs_y_min = coords[2], pdata->abs_y_max = coords[3]; - I(" DT-%s:panel-coords = %d, %d, %d, %d\n", __func__, pdata->abs_x_min, - pdata->abs_x_max, pdata->abs_y_min, pdata->abs_y_max); + I(" DT-%s:panel-coords = %d, %d, %d, %d\n", + __func__, pdata->abs_x_min, pdata->abs_x_max, + pdata->abs_y_min, pdata->abs_y_max); } prop = of_find_property(dt, "himax,display-coords", NULL); if (prop) { coords_size = prop->length / sizeof(u32); if (coords_size != 4) - D(" %s:Invalid display coords size %d", __func__, coords_size); + D(" %s:Invalid display coords size %d", + __func__, coords_size); } - rc = of_property_read_u32_array(dt, "himax,display-coords", coords, coords_size); + rc = of_property_read_u32_array(dt, "himax,display-coords", + coords, coords_size); if (rc && (rc != -EINVAL)) { - D(" %s:Fail to read display-coords %d\n", __func__, rc); + D(" %s:Fail to read display-coords %d\n", + __func__, rc); return rc; } pdata->screenWidth = coords[1]; @@ -116,19 +124,19 @@ int himax_parse_dt(struct himax_ts_data *ts, pdata->screenHeight); pdata->gpio_irq = of_get_named_gpio(dt, "himax,irq-gpio", 0); - if (!gpio_is_valid(pdata->gpio_irq)) { + if (!gpio_is_valid(pdata->gpio_irq)) I(" DT:gpio_irq value is not valid\n"); - } pdata->gpio_reset = of_get_named_gpio(dt, "himax,rst-gpio", 0); - if (!gpio_is_valid(pdata->gpio_reset)) { + if (!gpio_is_valid(pdata->gpio_reset)) I(" DT:gpio_rst value is not valid\n"); - } + pdata->gpio_3v3_en = of_get_named_gpio(dt, "himax,3v3-gpio", 0); - if (!gpio_is_valid(pdata->gpio_3v3_en)) { + if (!gpio_is_valid(pdata->gpio_3v3_en)) I(" DT:gpio_3v3_en value is not valid\n"); - } - I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d", pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en); + + I(" DT:gpio_irq=%d, gpio_rst=%d, gpio_3v3_en=%d", + pdata->gpio_irq, pdata->gpio_reset, pdata->gpio_3v3_en); if (of_property_read_u32(dt, "report_type", &data) == 0) { pdata->protocol_type = data; @@ -140,7 +148,8 @@ int himax_parse_dt(struct himax_ts_data *ts, return 0; } -int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry) +int i2c_himax_read(struct i2c_client *client, +uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry) { int retry; struct i2c_msg msg[] = { @@ -157,7 +166,7 @@ int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, ui .buf = data, } }; - + mutex_lock(&private_ts->rw_lock); for (retry = 0; retry < toRetry; retry++) { if (i2c_transfer(client->adapter, msg, 2) == 2) break; @@ -166,13 +175,16 @@ int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, ui if (retry == toRetry) { E("%s: i2c_read_block retry over %d\n", __func__, toRetry); + mutex_unlock(&private_ts->rw_lock); return -EIO; } + mutex_unlock(&private_ts->rw_lock); return 0; } -int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry) +int i2c_himax_write(struct i2c_client *client, +uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry) { int retry/*, loop_i*/; uint8_t buf[length + 1]; @@ -188,7 +200,7 @@ int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, u buf[0] = command; memcpy(buf+1, data, length); - + mutex_lock(&private_ts->rw_lock); for (retry = 0; retry < toRetry; retry++) { if (i2c_transfer(client->adapter, msg, 1) == 1) break; @@ -198,13 +210,16 @@ int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, u if (retry == toRetry) { E("%s: i2c_write_block retry over %d\n", __func__, toRetry); + mutex_unlock(&private_ts->rw_lock); return -EIO; } + mutex_unlock(&private_ts->rw_lock); return 0; } -int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry) +int i2c_himax_read_command(struct i2c_client *client, +uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry) { int retry; struct i2c_msg msg[] = { @@ -215,7 +230,7 @@ int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *d .buf = data, } }; - + mutex_lock(&private_ts->rw_lock); for (retry = 0; retry < toRetry; retry++) { if (i2c_transfer(client->adapter, msg, 1) == 1) break; @@ -224,17 +239,21 @@ int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *d if (retry == toRetry) { E("%s: i2c_read_block retry over %d\n", __func__, toRetry); + mutex_unlock(&private_ts->rw_lock); return -EIO; } + mutex_unlock(&private_ts->rw_lock); return 0; } -int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry) +int i2c_himax_write_command(struct i2c_client *client, +uint8_t command, uint8_t toRetry) { return i2c_himax_write(client, command, NULL, 0, toRetry); } -int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry) +int i2c_himax_master_write(struct i2c_client *client, +uint8_t *data, uint8_t length, uint8_t toRetry) { int retry/*, loop_i*/; uint8_t buf[length]; @@ -249,7 +268,7 @@ int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t len }; memcpy(buf, data, length); - + mutex_lock(&private_ts->rw_lock); for (retry = 0; retry < toRetry; retry++) { if (i2c_transfer(client->adapter, msg, 1) == 1) break; @@ -259,8 +278,10 @@ int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t len if (retry == toRetry) { E("%s: i2c_write_block retry over %d\n", __func__, toRetry); + mutex_unlock(&private_ts->rw_lock); return -EIO; } + mutex_unlock(&private_ts->rw_lock); return 0; } @@ -287,62 +308,51 @@ uint8_t himax_int_gpio_read(int pinnum) } #if defined(CONFIG_HMX_DB) -static int himax_regulator_configure(struct i2c_client *client,struct himax_i2c_platform_data *pdata) +static int himax_regulator_configure(struct i2c_client *client, +struct himax_i2c_platform_data *pdata) { - int retval; - pdata->vcc_dig = regulator_get(&client->dev, - "vdd"); - if (IS_ERR(pdata->vcc_dig)) - { - E("%s: Failed to get regulator vdd\n", - __func__); - retval = PTR_ERR(pdata->vcc_dig); - return retval; - } - pdata->vcc_ana = regulator_get(&client->dev, - "avdd"); - if (IS_ERR(pdata->vcc_ana)) - { - E("%s: Failed to get regulator avdd\n", - __func__); - retval = PTR_ERR(pdata->vcc_ana); - regulator_put(pdata->vcc_ana); - return retval; - } - - return 0; + int retval; + + pdata->vcc_dig = regulator_get(&client->dev, "vdd"); + if (IS_ERR(pdata->vcc_dig)) { + E("%s: Failed to get regulator vdd\n", __func__); + retval = PTR_ERR(pdata->vcc_dig); + return retval; + } + pdata->vcc_ana = regulator_get(&client->dev, "avdd"); + if (IS_ERR(pdata->vcc_ana)) { + E("%s: Failed to get regulator avdd\n", __func__); + retval = PTR_ERR(pdata->vcc_ana); + regulator_put(pdata->vcc_ana); + return retval; + } + + return 0; }; -static int himax_power_on(struct himax_i2c_platform_data *pdata, bool on) +static int himax_power_on(struct himax_i2c_platform_data *pdata, +bool on) { - int retval; - - if (on) - { - retval = regulator_enable(pdata->vcc_dig); - if (retval) - { - E("%s: Failed to enable regulator vdd\n", - __func__); - return retval; - } - msleep(100); - retval = regulator_enable(pdata->vcc_ana); - if (retval) - { - E("%s: Failed to enable regulator avdd\n", - __func__); - regulator_disable(pdata->vcc_dig); - return retval; - } - } - else - { - regulator_disable(pdata->vcc_dig); - regulator_disable(pdata->vcc_ana); - } - - return 0; + int retval; + + if (on) { + retval = regulator_enable(pdata->vcc_dig); + if (retval) { + E("%s: Failed to enable regulator vdd\n", __func__); + return retval; + } + msleep(100); + retval = regulator_enable(pdata->vcc_ana); + if (retval) { + E("%s: Failed to enable regulator avdd\n", __func__); + regulator_disable(pdata->vcc_dig); + return retval; + } + } else { + regulator_disable(pdata->vcc_dig); + regulator_disable(pdata->vcc_ana); + } + return 0; } int himax_ts_pinctrl_init(struct himax_ts_data *ts) @@ -353,41 +363,35 @@ int himax_ts_pinctrl_init(struct himax_ts_data *ts) ts->ts_pinctrl = devm_pinctrl_get(&(ts->client->dev)); if (IS_ERR_OR_NULL(ts->ts_pinctrl)) { retval = PTR_ERR(ts->ts_pinctrl); - dev_dbg(&ts->client->dev, - "Target does not use pinctrl %d\n", retval); + dev_dbg(&ts->client->dev, "Target does not use pinctrl %d\n", + retval); goto err_pinctrl_get; } - ts->pinctrl_state_active - = pinctrl_lookup_state(ts->ts_pinctrl, - PINCTRL_STATE_ACTIVE); + ts->pinctrl_state_active = pinctrl_lookup_state(ts->ts_pinctrl, + PINCTRL_STATE_ACTIVE); if (IS_ERR_OR_NULL(ts->pinctrl_state_active)) { retval = PTR_ERR(ts->pinctrl_state_active); - dev_err(&ts->client->dev, - "Can not lookup %s pinstate %d\n", - PINCTRL_STATE_ACTIVE, retval); + dev_err(&ts->client->dev, "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_ACTIVE, retval); goto err_pinctrl_lookup; } - ts->pinctrl_state_suspend - = pinctrl_lookup_state(ts->ts_pinctrl, - PINCTRL_STATE_SUSPEND); + ts->pinctrl_state_suspend = pinctrl_lookup_state(ts->ts_pinctrl, + PINCTRL_STATE_SUSPEND); if (IS_ERR_OR_NULL(ts->pinctrl_state_suspend)) { retval = PTR_ERR(ts->pinctrl_state_suspend); - dev_err(&ts->client->dev, - "Can not lookup %s pinstate %d\n", - PINCTRL_STATE_SUSPEND, retval); + dev_err(&ts->client->dev, "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_SUSPEND, retval); goto err_pinctrl_lookup; } - ts->pinctrl_state_release - = pinctrl_lookup_state(ts->ts_pinctrl, - PINCTRL_STATE_RELEASE); + ts->pinctrl_state_release = pinctrl_lookup_state(ts->ts_pinctrl, + PINCTRL_STATE_RELEASE); if (IS_ERR_OR_NULL(ts->pinctrl_state_release)) { retval = PTR_ERR(ts->pinctrl_state_release); - dev_dbg(&ts->client->dev, - "Can not lookup %s pinstate %d\n", - PINCTRL_STATE_RELEASE, retval); + dev_dbg(&ts->client->dev, "Can not lookup %s pinstate %d\n", + PINCTRL_STATE_RELEASE, retval); } return 0; @@ -399,185 +403,161 @@ int himax_ts_pinctrl_init(struct himax_ts_data *ts) return retval; } -int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata) +int himax_gpio_power_config(struct i2c_client *client, +struct himax_i2c_platform_data *pdata) { - int error; + int error; - error = himax_regulator_configure(client, pdata); - if (error) - { - E("Failed to intialize hardware\n"); - goto err_regulator_not_on; - } + error = himax_regulator_configure(client, pdata); + if (error) { + E("Failed to initialize hardware\n"); + goto err_regulator_not_on; + } #ifdef HX_RST_PIN_FUNC - if (gpio_is_valid(pdata->gpio_reset)) - { - /* configure touchscreen reset out gpio */ - error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio"); - if (error) - { - E("unable to request gpio [%d]\n", - pdata->gpio_reset); - goto err_regulator_on; - } - - error = gpio_direction_output(pdata->gpio_reset, 0); - if (error) - { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_reset); - goto err_gpio_reset_req; - } - } + if (gpio_is_valid(pdata->gpio_reset)) { + /* configure touchscreen reset out gpio */ + error = gpio_request(pdata->gpio_reset, "hmx_reset_gpio"); + if (error) { + E("unable to request gpio [%d]\n", + pdata->gpio_reset); + goto err_regulator_on; + } + error = gpio_direction_output(pdata->gpio_reset, 0); + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_reset_req; + } + } #endif - error = himax_power_on(pdata, true); - if (error) - { - E("Failed to power on hardware\n"); - goto err_gpio_reset_req; - } + error = himax_power_on(pdata, true); + if (error) { + E("Failed to power on hardware\n"); + goto err_gpio_reset_req; + } #ifdef HX_IRQ_PIN_FUNC - if (gpio_is_valid(pdata->gpio_irq)) - { - /* configure touchscreen irq gpio */ - error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq"); - if (error) - { - E("unable to request gpio [%d]\n", - pdata->gpio_irq); - goto err_power_on; - } - error = gpio_direction_input(pdata->gpio_irq); - if (error) - { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_irq); - goto err_gpio_irq_req; - } - client->irq = gpio_to_irq(pdata->gpio_irq); - } - else - { - E("irq gpio not provided\n"); - goto err_power_on; - } + /* configure touchscreen irq gpio */ + if (gpio_is_valid(pdata->gpio_irq)) { + error = gpio_request(pdata->gpio_irq, "hmx_gpio_irq"); + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_irq); + goto err_power_on; + } + error = gpio_direction_input(pdata->gpio_irq); + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_irq); + goto err_gpio_irq_req; + } + client->irq = gpio_to_irq(pdata->gpio_irq); + } else { + E("irq gpio not provided\n"); + goto err_power_on; + } #endif - - msleep(20); + msleep(20); #ifdef HX_RST_PIN_FUNC - if (gpio_is_valid(pdata->gpio_reset)) - { - error = gpio_direction_output(pdata->gpio_reset, 1); - if (error) - { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_reset); - goto err_gpio_irq_req; - } - } + if (gpio_is_valid(pdata->gpio_reset)) { + error = gpio_direction_output(pdata->gpio_reset, 1); + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + goto err_gpio_irq_req; + } + } #endif - return 0; + return 0; #ifdef HX_RST_PIN_FUNC - err_gpio_irq_req: +err_gpio_irq_req: #endif #ifdef HX_IRQ_PIN_FUNC - if (gpio_is_valid(pdata->gpio_irq)) - gpio_free(pdata->gpio_irq); - err_power_on: + if (gpio_is_valid(pdata->gpio_irq)) + gpio_free(pdata->gpio_irq); +err_power_on: #endif - himax_power_on(pdata, false); - err_gpio_reset_req: + himax_power_on(pdata, false); +err_gpio_reset_req: #ifdef HX_RST_PIN_FUNC - if (gpio_is_valid(pdata->gpio_reset)) - gpio_free(pdata->gpio_reset); - err_regulator_on: + if (gpio_is_valid(pdata->gpio_reset)) + gpio_free(pdata->gpio_reset); +err_regulator_on: #endif - err_regulator_not_on: +err_regulator_not_on: - return error; + return error; } #else -int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata) +int himax_gpio_power_config(struct i2c_client *client, +struct himax_i2c_platform_data *pdata) { - int error=0; - + int error = 0; + #ifdef HX_RST_PIN_FUNC - if (pdata->gpio_reset >= 0) - { - error = gpio_request(pdata->gpio_reset, "himax-reset"); - if (error < 0) - { - E("%s: request reset pin failed\n", __func__); - return error; - } - error = gpio_direction_output(pdata->gpio_reset, 0); - if (error) - { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_reset); - return error; - } + if (pdata->gpio_reset >= 0) { + error = gpio_request(pdata->gpio_reset, "himax-reset"); + if (error < 0) { + E("%s: request reset pin failed\n", __func__); + return error; } + error = gpio_direction_output(pdata->gpio_reset, 0); + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + return error; + } + } #endif - if (pdata->gpio_3v3_en >= 0) - { - error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en"); - if (error < 0) - { - E("%s: request 3v3_en pin failed\n", __func__); - return error; - } - gpio_direction_output(pdata->gpio_3v3_en, 1); - I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en)); + if (pdata->gpio_3v3_en >= 0) { + error = gpio_request(pdata->gpio_3v3_en, "himax-3v3_en"); + if (error < 0) { + E("%s: request 3v3_en pin failed\n", __func__); + return error; } + gpio_direction_output(pdata->gpio_3v3_en, 1); + I("3v3_en pin =%d\n", gpio_get_value(pdata->gpio_3v3_en)); + } #ifdef HX_IRQ_PIN_FUNC - if (gpio_is_valid(pdata->gpio_irq)) - { - /* configure touchscreen irq gpio */ - error = gpio_request(pdata->gpio_irq, "himax_gpio_irq"); - if (error) - { - E("unable to request gpio [%d]\n",pdata->gpio_irq); - return error; - } - error = gpio_direction_input(pdata->gpio_irq); - if (error) - { - E("unable to set direction for gpio [%d]\n",pdata->gpio_irq); - return error; - } - client->irq = gpio_to_irq(pdata->gpio_irq); + if (gpio_is_valid(pdata->gpio_irq)) { + /* configure touchscreen irq gpio */ + error = gpio_request(pdata->gpio_irq, "himax_gpio_irq"); + if (error) { + E("unable to request gpio [%d]\n", pdata->gpio_irq); + return error; } - else - { - E("irq gpio not provided\n"); + error = gpio_direction_input(pdata->gpio_irq); + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_irq); return error; } + client->irq = gpio_to_irq(pdata->gpio_irq); + } else { + E("irq gpio not provided\n"); + return error; + } #endif - msleep(20); - + msleep(20); + #ifdef HX_RST_PIN_FUNC - if (pdata->gpio_reset >= 0) - { - error = gpio_direction_output(pdata->gpio_reset, 1); - if (error) - { - E("unable to set direction for gpio [%d]\n", - pdata->gpio_reset); - return error; - } + if (pdata->gpio_reset >= 0) { + error = gpio_direction_output(pdata->gpio_reset, 1); + if (error) { + E("unable to set direction for gpio [%d]\n", + pdata->gpio_reset); + return error; } - msleep(20); -#endif - - return error; } + msleep(20); +#endif + + return error; +} #endif static void himax_ts_isr_func(struct himax_ts_data *ts) @@ -595,34 +575,40 @@ irqreturn_t himax_ts_thread(int irq, void *ptr) if (ts->debug_log_level & BIT(2)) { getnstimeofday(&timeStart); - usleep_range(5000, 7000); - //I(" Irq start time = %ld.%06ld s\n", - // timeStart.tv_sec, timeStart.tv_nsec/1000); + usleep_range(4999, 5000); + /*I(" Irq start time = %ld.%06ld s\n", + timeStart.tv_sec, timeStart.tv_nsec/1000);*/ } #ifdef HX_SMART_WAKEUP - if (atomic_read(&ts->suspend_mode)&&(!FAKE_POWER_KEY_SEND)&&(ts->SMWP_enable)&&(!diag_cmd)) { - wake_lock_timeout(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT); + if (atomic_read(&ts->suspend_mode) + && (!FAKE_POWER_KEY_SEND) + && (ts->SMWP_enable) + && (!diag_cmd)) { + __pm_wakeup_event(&ts->ts_SMWP_wake_lock, TS_WAKE_LOCK_TIMEOUT); msleep(200); himax_wake_check_func(); return IRQ_HANDLED; } #endif himax_ts_isr_func((struct himax_ts_data *)ptr); - if(ts->debug_log_level & BIT(2)) { - getnstimeofday(&timeEnd); - timeDelta.tv_nsec = (timeEnd.tv_sec*1000000000+timeEnd.tv_nsec) - -(timeStart.tv_sec*1000000000+timeStart.tv_nsec); - //I("Irq finish time = %ld.%06ld s\n", - // timeEnd.tv_sec, timeEnd.tv_nsec/1000); - //I("Touch latency = %ld us\n", timeDelta.tv_nsec/1000); + if (ts->debug_log_level & BIT(2)) { + getnstimeofday(&timeEnd); + timeDelta.tv_nsec + = (timeEnd.tv_sec * 1000000000 + timeEnd.tv_nsec) + - (timeStart.tv_sec * 1000000000 + timeStart.tv_nsec); + /*I("Irq finish time = %ld.%06ld s\n", + timeEnd.tv_sec, timeEnd.tv_nsec/1000); + I("Touch latency = %ld us\n", timeDelta.tv_nsec/1000);*/ } return IRQ_HANDLED; } static void himax_ts_work_func(struct work_struct *work) { - struct himax_ts_data *ts = container_of(work, struct himax_ts_data, work); + struct himax_ts_data *ts = + container_of(work, struct himax_ts_data, work); + himax_ts_work(ts); } @@ -634,24 +620,26 @@ int himax_ts_register_interrupt(struct i2c_client *client) int ret = 0; ts->irq_enabled = 0; - //Work functon + /*Work functon*/ if (client->irq) {/*INT mode*/ ts->use_irq = 1; - if(ic_data->HX_INT_IS_EDGE) - { - I("%s edge triiger falling\n ",__func__); - ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_FALLING | IRQF_ONESHOT, client->name, ts); - } - else - { - I("%s level trigger low\n ",__func__); - ret = request_threaded_irq(client->irq, NULL, himax_ts_thread,IRQF_TRIGGER_LOW | IRQF_ONESHOT, client->name, ts); + if (ic_data->HX_INT_IS_EDGE) { + I("%s edge triiger falling\n ", __func__); + ret = request_threaded_irq(client->irq, + NULL, himax_ts_thread, IRQF_TRIGGER_FALLING + | IRQF_ONESHOT, client->name, ts); + } else { + I("%s level trigger low\n ", __func__); + ret = request_threaded_irq(client->irq, + NULL, himax_ts_thread, IRQF_TRIGGER_LOW + | IRQF_ONESHOT, client->name, ts); } if (ret == 0) { ts->irq_enabled = 1; irq_enable_count = 1; tp_irq = client->irq; - I("%s: irq enabled at qpio: %d\n", __func__, client->irq); + I("%s: irq enabled at qpio: %d\n", + __func__, client->irq); #ifdef HX_SMART_WAKEUP irq_set_irq_wake(client->irq, 1); #endif @@ -662,8 +650,8 @@ int himax_ts_register_interrupt(struct i2c_client *client) } else { I("%s: client->irq is empty, use polling mode.\n", __func__); } - - if (!ts->use_irq) {/*if use polling mode need to disable HX_ESD_WORKAROUND function*/ + /*if use polling mode need to disable HX_ESD_WORKAROUND function*/ + if (!ts->use_irq) { ts->himax_wq = create_singlethread_workqueue("himax_touch"); INIT_WORK(&ts->work, himax_ts_work_func); @@ -680,7 +668,7 @@ static int himax_common_suspend(struct device *dev) { struct himax_ts_data *ts = dev_get_drvdata(dev); - I("%s: enter \n", __func__); + I("%s: enter\n", __func__); himax_chip_common_suspend(ts); return 0; @@ -690,7 +678,7 @@ static int himax_common_resume(struct device *dev) { struct himax_ts_data *ts = dev_get_drvdata(dev); - I("%s: enter \n", __func__); + I("%s: enter\n", __func__); himax_chip_common_resume(ts); return 0; @@ -702,23 +690,28 @@ int fb_notifier_callback(struct notifier_block *self, { struct fb_event *evdata = data; int *blank; - struct himax_ts_data *ts= - container_of(self, struct himax_ts_data, fb_notif); + struct himax_ts_data *ts + = container_of(self, struct himax_ts_data, fb_notif); + int ERR = 1; I(" %s\n", __func__); - if (evdata && evdata->data && event == FB_EVENT_BLANK && ts && - ts->client) { + if (evdata && evdata->data && event + == FB_EVENT_BLANK && ts && ts->client) { blank = evdata->data; mutex_lock(&ts->fb_mutex); switch (*blank) { case FB_BLANK_UNBLANK: if (!ts->probe_done) { - himax_ts_init(ts); - ts->probe_done = true; - } else { + if (himax_ts_init(ts) == true) { + I("himax_ts_init return OK\n"); + ts->probe_done = true; + } else { + I("himax_ts_init return Fail\n"); + return -ERR; + } + } else himax_common_resume(&ts->client->dev); - } break; case FB_BLANK_POWERDOWN: @@ -748,7 +741,7 @@ static const struct dev_pm_ops himax_common_pm_ops = { }; #ifdef CONFIG_OF -static const struct of_device_id himax_match_table[] = { +static struct of_device_id himax_match_table[] = { {.compatible = "himax,hxcommon" }, {}, }; @@ -770,16 +763,10 @@ static struct i2c_driver himax_common_driver = { }, }; -static void __init himax_common_init_async(void *unused, async_cookie_t cookie) -{ - I("%s:Enter \n", __func__); - i2c_add_driver(&himax_common_driver); -} - static int __init himax_common_init(void) { I("Himax common touch panel driver init\n"); - async_schedule(himax_common_init_async, NULL); + i2c_add_driver(&himax_common_driver); return 0; } @@ -792,5 +779,5 @@ module_init(himax_common_init); module_exit(himax_common_exit); MODULE_DESCRIPTION("Himax_common driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/input/touchscreen/hxchipset/himax_platform.h b/drivers/input/touchscreen/hxchipset/himax_platform.h index 1223685683aa..6871e53cd1f2 100644 --- a/drivers/input/touchscreen/hxchipset/himax_platform.h +++ b/drivers/input/touchscreen/hxchipset/himax_platform.h @@ -22,6 +22,7 @@ #include #include #include + #if defined(CONFIG_HMX_DB) #include #endif @@ -31,15 +32,11 @@ #define HIMAX_I2C_RETRY_TIMES 10 #if defined(CONFIG_TOUCHSCREEN_HIMAX_DEBUG) -#define D(x...) pr_debug("[HXTP] " x) -#define I(x...) pr_info("[HXTP] " x) -#define W(x...) pr_warning("[HXTP][WARNING] " x) -#define E(x...) pr_err("[HXTP][ERROR] " x) -#define DIF(x...) \ -do {\ - if (debug_flag) \ - pr_debug("[HXTP][DEBUG] " x) \ -} while(0) +#define D(x...) pr_info("[HXTP][DEBUG] " x) +#define I(x...) pr_info("[HXTP][INFO] " x) +#define W(x...) pr_info("[HXTP][WARNING] " x) +#define E(x...) pr_info("[HXTP][ERROR] " x) +#define DIF(x...) do { if (debug_flag) pr_info("[HXTP][DEBUG] " x) } while (0) #else #define D(x...) #define I(x...) @@ -53,24 +50,24 @@ do {\ #define HX_VTG_MIN_UV 2700000 #define HX_VTG_MAX_UV 3300000 #define HX_ACTIVE_LOAD_UA 15000 -#define HX_LPM_LOAD_UA 10 +#define HX_LPM_LOAD_UA 10 /* Digital voltage @1.8 V */ #define HX_VTG_DIG_MIN_UV 1800000 #define HX_VTG_DIG_MAX_UV 1800000 #define HX_ACTIVE_LOAD_DIG_UA 10000 -#define HX_LPM_LOAD_DIG_UA 10 +#define HX_LPM_LOAD_DIG_UA 10 #define HX_I2C_VTG_MIN_UV 1800000 #define HX_I2C_VTG_MAX_UV 1800000 -#define HX_I2C_LOAD_UA 10000 -#define HX_I2C_LPM_LOAD_UA 10 +#define HX_I2C_LOAD_UA 10000 +#define HX_I2C_LPM_LOAD_UA 10 #endif -#define HIMAX_common_NAME "himax_tp" +#define HIMAX_common_NAME "himax_tp" #define HIMAX_I2C_ADDR 0x48 #define INPUT_DEV_NAME "himax-touchscreen" -struct himax_i2c_platform_data { +struct himax_i2c_platform_data { int abs_x_min; int abs_x_max; int abs_x_fuzz; @@ -108,28 +105,53 @@ struct himax_i2c_platform_data { int irq_gpio; u32 irq_gpio_flags; - struct regulator *vcc_ana; //For Dragon Board - struct regulator *vcc_dig; //For Dragon Board - struct regulator *vcc_i2c; //For Dragon Board -#endif + struct regulator *vcc_ana; /*For Dragon Board*/ + struct regulator *vcc_dig; /*For Dragon Board*/ + struct regulator *vcc_i2c; /*For Dragon Board*/ +#endif }; extern int irq_enable_count; -extern int i2c_himax_read(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry); -extern int i2c_himax_write(struct i2c_client *client, uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry); -extern int i2c_himax_write_command(struct i2c_client *client, uint8_t command, uint8_t toRetry); -extern int i2c_himax_master_write(struct i2c_client *client, uint8_t *data, uint8_t length, uint8_t toRetry); -extern int i2c_himax_read_command(struct i2c_client *client, uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry); -extern void himax_int_enable(int irqnum, int enable); -extern int himax_ts_register_interrupt(struct i2c_client *client); -extern void himax_rst_gpio_set(int pinnum, uint8_t value); -extern uint8_t himax_int_gpio_read(int pinnum); - -extern int himax_gpio_power_config(struct i2c_client *client,struct himax_i2c_platform_data *pdata); +int i2c_himax_read(struct i2c_client *client, + uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry); + +int i2c_himax_write(struct i2c_client *client, + uint8_t command, uint8_t *data, uint8_t length, uint8_t toRetry); + +int i2c_himax_write_command(struct i2c_client *client, + uint8_t command, uint8_t toRetry); + +int i2c_himax_master_write(struct i2c_client *client, + uint8_t *data, uint8_t length, uint8_t toRetry); + +int i2c_himax_read_command(struct i2c_client *client, + uint8_t length, uint8_t *data, uint8_t *readlength, uint8_t toRetry); + +void himax_int_enable(int irqnum, int enable); +int himax_ts_register_interrupt(struct i2c_client *client); +void himax_rst_gpio_set(int pinnum, uint8_t value); +uint8_t himax_int_gpio_read(int pinnum); + +int himax_gpio_power_config(struct i2c_client *client, + struct himax_i2c_platform_data *pdata); #if defined(CONFIG_FB) -extern int fb_notifier_callback(struct notifier_block *self, unsigned long event, void *data); +extern int fb_notifier_callback(struct notifier_block *self, + unsigned long event, void *data); #endif +extern struct himax_ts_data *private_ts; +extern struct himax_ic_data *ic_data; +extern void himax_ts_work(struct himax_ts_data *ts); +extern enum hrtimer_restart himax_ts_timer_func(struct hrtimer *timer); +extern int tp_rst_gpio; + +#ifdef HX_TP_PROC_DIAG +extern uint8_t getDiagCommand(void); +#endif + +int himax_parse_dt(struct himax_ts_data *ts, + struct himax_i2c_platform_data *pdata); +int himax_ts_pinctrl_init(struct himax_ts_data *ts); #endif diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index e4c43a17b333..8088c34336aa 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1655,13 +1655,7 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) } else return -EINVAL; case IIOCDBGVAR: - if (arg) { - if (copy_to_user(argp, &dev, sizeof(ulong))) - return -EFAULT; - return 0; - } else - return -EINVAL; - break; + return -EINVAL; default: if ((cmd & IIOCDRVCTL) == IIOCDRVCTL) cmd = ((cmd >> _IOC_NRSHIFT) & _IOC_NRMASK) & ISDN_DRVIOCTL_MASK; diff --git a/drivers/md/bcache/writeback.c b/drivers/md/bcache/writeback.c index 6e3fae202b11..fe19e5841bfc 100644 --- a/drivers/md/bcache/writeback.c +++ b/drivers/md/bcache/writeback.c @@ -462,8 +462,10 @@ static int bch_writeback_thread(void *arg) * data on cache. BCACHE_DEV_DETACHING flag is set in * bch_cached_dev_detach(). */ - if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) + if (test_bit(BCACHE_DEV_DETACHING, &dc->disk.flags)) { + up_write(&dc->writeback_lock); break; + } } up_write(&dc->writeback_lock); diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index 1e64e9c50d85..aeb9ee6082d9 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c @@ -324,7 +324,7 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd) disk_super->version = cpu_to_le32(MAX_CACHE_VERSION); memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name)); memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version)); - disk_super->policy_hint_size = 0; + disk_super->policy_hint_size = cpu_to_le32(0); __copy_sm_root(cmd, disk_super); @@ -635,6 +635,7 @@ static int __commit_transaction(struct dm_cache_metadata *cmd, disk_super->policy_version[0] = cpu_to_le32(cmd->policy_version[0]); disk_super->policy_version[1] = cpu_to_le32(cmd->policy_version[1]); disk_super->policy_version[2] = cpu_to_le32(cmd->policy_version[2]); + disk_super->policy_hint_size = cpu_to_le32(cmd->policy_hint_size); disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits); disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses); diff --git a/drivers/md/dm-req-crypt.c b/drivers/md/dm-req-crypt.c index 05b3c3138d75..196952d49b40 100644 --- a/drivers/md/dm-req-crypt.c +++ b/drivers/md/dm-req-crypt.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. @@ -42,7 +42,7 @@ #define MAX_ENCRYPTION_BUFFERS 1 #define MIN_IOS 256 #define MIN_POOL_PAGES 32 -#define KEY_SIZE_XTS 32 +#define KEY_SIZE_XTS 64 #define AES_XTS_IV_LEN 16 #define MAX_MSM_ICE_KEY_LUT_SIZE 32 #define SECTOR_SIZE 512 @@ -457,22 +457,22 @@ static void req_cryptd_crypt_write_convert(struct req_dm_crypt_io *io) struct bio *bio_src = NULL; unsigned int total_sg_len_req_in = 0, total_sg_len_req_out = 0, total_bytes_in_req = 0, error = DM_MAPIO_REMAPPED, rc = 0; - struct req_iterator iter; - struct req_iterator iter1; struct ablkcipher_request *req = NULL; struct req_crypt_result result; - struct bio_vec bvec; struct scatterlist *req_sg_in = NULL; struct scatterlist *req_sg_out = NULL; int copy_bio_sector_to_req = 0; gfp_t gfp_mask = GFP_NOIO | __GFP_HIGHMEM; struct page *page = NULL; u8 IV[AES_XTS_IV_LEN]; - int remaining_size = 0, err = 0; + int size = 0, err = 0; struct crypto_engine_entry engine; unsigned int engine_list_total = 0; struct crypto_engine_entry *curr_engine_list = NULL; unsigned int *engine_cursor = NULL; + unsigned int i; + struct bio_vec *_bvec; + struct bio *_bio; if (io) { @@ -582,27 +582,31 @@ static void req_cryptd_crypt_write_convert(struct req_dm_crypt_io *io) goto ablkcipher_req_alloc_failure; } - rq_for_each_segment(bvec, clone, iter) { - if (bvec.bv_len > remaining_size) { - page = NULL; - while (page == NULL) { - page = mempool_alloc(req_page_pool, gfp_mask); - if (!page) { - DMERR("%s Crypt page alloc failed", + __rq_for_each_bio(_bio, clone) { + bio_for_each_segment_all(_bvec, _bio, i) { + if (_bvec->bv_len > size) { + page = NULL; + while (page == NULL) { + page = mempool_alloc(req_page_pool, + gfp_mask); + if (!page) { + DMERR("%s Page alloc failed", __func__); - congestion_wait(BLK_RW_ASYNC, HZ/100); + congestion_wait(BLK_RW_ASYNC, + HZ/100); + } } - } - bvec.bv_page = page; - bvec.bv_offset = 0; - remaining_size = PAGE_SIZE - bvec.bv_len; - if (remaining_size < 0) - BUG(); - } else { - bvec.bv_page = page; - bvec.bv_offset = PAGE_SIZE - remaining_size; - remaining_size = remaining_size - bvec.bv_len; + _bvec->bv_page = page; + _bvec->bv_offset = 0; + size = PAGE_SIZE - _bvec->bv_len; + if (size < 0) + BUG(); + } else { + _bvec->bv_page = page; + _bvec->bv_offset = PAGE_SIZE - size; + size = size - _bvec->bv_len; + } } } @@ -664,12 +668,16 @@ static void req_cryptd_crypt_write_convert(struct req_dm_crypt_io *io) ablkcipher_request_free(req); if (error == DM_REQ_CRYPT_ERROR_AFTER_PAGE_MALLOC) { - rq_for_each_segment(bvec, clone, iter1) { - if (bvec.bv_offset == 0) { - mempool_free(bvec.bv_page, req_page_pool); - bvec.bv_page = NULL; - } else - bvec.bv_page = NULL; + __rq_for_each_bio(_bio, clone) { + bio_for_each_segment_all(_bvec, _bio, i) { + if (_bvec->bv_offset == 0) { + mempool_free(_bvec->bv_page, + req_page_pool); + _bvec->bv_page = NULL; + } else { + _bvec->bv_page = NULL; + } + } } } @@ -866,8 +874,9 @@ static int req_crypt_endio(struct dm_target *ti, struct request *clone, int error, union map_info *map_context) { int err = 0; - struct req_iterator iter1; - struct bio_vec bvec; + struct bio_vec *_bvec; + struct bio *_bio; + unsigned int i; struct req_dm_crypt_io *req_io = map_context->ptr; /* If it is for ICE, free up req_io and return */ @@ -878,12 +887,17 @@ static int req_crypt_endio(struct dm_target *ti, struct request *clone, } if (rq_data_dir(clone) == WRITE) { - rq_for_each_segment(bvec, clone, iter1) { - if (req_io->should_encrypt && bvec.bv_offset == 0) { - mempool_free(bvec.bv_page, req_page_pool); - bvec.bv_page = NULL; - } else - bvec.bv_page = NULL; + __rq_for_each_bio(_bio, clone) { + bio_for_each_segment_all(_bvec, _bio, i) { + if (req_io->should_encrypt && + _bvec->bv_offset == 0) { + mempool_free(_bvec->bv_page, + req_page_pool); + _bvec->bv_page = NULL; + } else { + _bvec->bv_page = NULL; + } + } } mempool_free(req_io, req_io_pool); goto submit_request; @@ -1297,11 +1311,11 @@ static int req_crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv) } /* - * If underlying device supports flush/discard, mapped target + * If underlying device supports flush, mapped target * should also allow it */ ti->num_flush_bios = 1; - ti->num_discard_bios = 1; + /* TODO: Discard support */ err = 0; DMINFO("%s: Mapping block_device %s to dm-req-crypt ok!\n", diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 245731994cee..5558c8e77ecb 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -1427,13 +1427,13 @@ static void clone_bio(struct dm_target_io *tio, struct bio *bio, } static struct dm_target_io *alloc_tio(struct clone_info *ci, - struct dm_target *ti, + struct dm_target *ti, int nr_iovecs, unsigned target_bio_nr) { struct dm_target_io *tio; struct bio *clone; - clone = bio_alloc_bioset(GFP_NOIO, 0, ci->md->bs); + clone = bio_alloc_bioset(GFP_NOIO, nr_iovecs, ci->md->bs); tio = container_of(clone, struct dm_target_io, clone); tio->io = ci->io; @@ -1447,12 +1447,18 @@ static void __clone_and_map_simple_bio(struct clone_info *ci, struct dm_target *ti, unsigned target_bio_nr, unsigned *len) { - struct dm_target_io *tio = alloc_tio(ci, ti, target_bio_nr); + struct dm_target_io *tio = alloc_tio(ci, ti, ci->bio->bi_max_vecs, + target_bio_nr); struct bio *clone = &tio->clone; tio->len_ptr = len; - __bio_clone_fast(clone, ci->bio); + /* + * Discard requests require the bio's inline iovecs be initialized. + * ci->bio->bi_max_vecs is BIO_INLINE_VECS anyway, for both flush + * and discard, so no need for concern about wasted bvec allocations. + */ + __bio_clone_fast(clone, ci->bio); if (len) bio_setup_sector(clone, ci->sector, *len); @@ -1495,7 +1501,7 @@ static void __clone_and_map_data_bio(struct clone_info *ci, struct dm_target *ti num_target_bios = ti->num_write_bios(ti, bio); for (target_bio_nr = 0; target_bio_nr < num_target_bios; target_bio_nr++) { - tio = alloc_tio(ci, ti, target_bio_nr); + tio = alloc_tio(ci, ti, 0, target_bio_nr); tio->len_ptr = len; clone_bio(tio, bio, sector, *len); __map_bio(tio); @@ -3095,7 +3101,7 @@ struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity, u if (!pools->io_pool) goto out; - pools->bs = bioset_create_nobvec(pool_size, front_pad); + pools->bs = bioset_create(pool_size, front_pad); if (!pools->bs) goto out; diff --git a/drivers/md/md.c b/drivers/md/md.c index f88f912f0296..ba201db6afce 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5676,6 +5676,9 @@ static int hot_remove_disk(struct mddev *mddev, dev_t dev) char b[BDEVNAME_SIZE]; struct md_rdev *rdev; + if (!mddev->pers) + return -ENODEV; + rdev = find_rdev(mddev, dev); if (!rdev) return -ENXIO; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index b19149e45154..bd26567248b3 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -3770,6 +3770,13 @@ static int run(struct mddev *mddev) disk->rdev->saved_raid_disk < 0) conf->fullsync = 1; } + + if (disk->replacement && + !test_bit(In_sync, &disk->replacement->flags) && + disk->replacement->saved_raid_disk < 0) { + conf->fullsync = 1; + } + disk->recovery_disabled = mddev->recovery_disabled - 1; } diff --git a/drivers/media/common/siano/smsendian.c b/drivers/media/common/siano/smsendian.c index bfe831c10b1c..b95a631f23f9 100644 --- a/drivers/media/common/siano/smsendian.c +++ b/drivers/media/common/siano/smsendian.c @@ -35,7 +35,7 @@ void smsendian_handle_tx_message(void *buffer) switch (msg->x_msg_header.msg_type) { case MSG_SMS_DATA_DOWNLOAD_REQ: { - msg->msg_data[0] = le32_to_cpu(msg->msg_data[0]); + msg->msg_data[0] = le32_to_cpu((__force __le32)(msg->msg_data[0])); break; } @@ -44,7 +44,7 @@ void smsendian_handle_tx_message(void *buffer) sizeof(struct sms_msg_hdr))/4; for (i = 0; i < msg_words; i++) - msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]); + msg->msg_data[i] = le32_to_cpu((__force __le32)msg->msg_data[i]); break; } @@ -64,7 +64,7 @@ void smsendian_handle_rx_message(void *buffer) { struct sms_version_res *ver = (struct sms_version_res *) msg; - ver->chip_model = le16_to_cpu(ver->chip_model); + ver->chip_model = le16_to_cpu((__force __le16)ver->chip_model); break; } @@ -81,7 +81,7 @@ void smsendian_handle_rx_message(void *buffer) sizeof(struct sms_msg_hdr))/4; for (i = 0; i < msg_words; i++) - msg->msg_data[i] = le32_to_cpu(msg->msg_data[i]); + msg->msg_data[i] = le32_to_cpu((__force __le32)msg->msg_data[i]); break; } @@ -95,9 +95,9 @@ void smsendian_handle_message_header(void *msg) #ifdef __BIG_ENDIAN struct sms_msg_hdr *phdr = (struct sms_msg_hdr *)msg; - phdr->msg_type = le16_to_cpu(phdr->msg_type); - phdr->msg_length = le16_to_cpu(phdr->msg_length); - phdr->msg_flags = le16_to_cpu(phdr->msg_flags); + phdr->msg_type = le16_to_cpu((__force __le16)phdr->msg_type); + phdr->msg_length = le16_to_cpu((__force __le16)phdr->msg_length); + phdr->msg_flags = le16_to_cpu((__force __le16)phdr->msg_flags); #endif /* __BIG_ENDIAN */ } EXPORT_SYMBOL_GPL(smsendian_handle_message_header); diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c index b49254e4ea0a..6a2f204b902f 100644 --- a/drivers/media/i2c/smiapp/smiapp-core.c +++ b/drivers/media/i2c/smiapp/smiapp-core.c @@ -939,7 +939,7 @@ static int smiapp_read_nvm(struct smiapp_sensor *sensor, if (rval) goto out; - for (i = 0; i < 1000; i++) { + for (i = 1000; i > 0; i--) { rval = smiapp_read( sensor, SMIAPP_REG_U8_DATA_TRANSFER_IF_1_STATUS, &s); @@ -950,11 +950,10 @@ static int smiapp_read_nvm(struct smiapp_sensor *sensor, if (s & SMIAPP_DATA_TRANSFER_IF_1_STATUS_RD_READY) break; - if (--i == 0) { - rval = -ETIMEDOUT; - goto out; - } - + } + if (!i) { + rval = -ETIMEDOUT; + goto out; } for (i = 0; i < SMIAPP_NVM_PAGE_SIZE; i++) { diff --git a/drivers/media/pci/saa7164/saa7164-fw.c b/drivers/media/pci/saa7164/saa7164-fw.c index 86763203d61d..021c46da794d 100644 --- a/drivers/media/pci/saa7164/saa7164-fw.c +++ b/drivers/media/pci/saa7164/saa7164-fw.c @@ -430,7 +430,8 @@ int saa7164_downloadfirmware(struct saa7164_dev *dev) __func__, fw->size); if (fw->size != fwlength) { - printk(KERN_ERR "xc5000: firmware incorrect size\n"); + printk(KERN_ERR "saa7164: firmware incorrect size %zu != %u\n", + fw->size, fwlength); ret = -ENOMEM; goto out; } diff --git a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c index 437af72a6a55..76acbab8aefa 100644 --- a/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c +++ b/drivers/media/platform/msm/camera_v2/jpeg_10/msm_jpeg_dev.c @@ -32,6 +32,8 @@ #define MSM_JPEG_NAME "jpeg" #define DEV_NAME_LEN 10 +static char devname[DEV_NAME_LEN]; + static int msm_jpeg_open(struct inode *inode, struct file *filp) { int rc = 0; @@ -185,7 +187,6 @@ static int msm_jpeg_init_dev(struct platform_device *pdev) struct msm_jpeg_device *msm_jpeg_device_p; const struct of_device_id *device_id; const struct msm_jpeg_priv_data *priv_data; - char devname[DEV_NAME_LEN]; msm_jpeg_device_p = kzalloc(sizeof(struct msm_jpeg_device), GFP_ATOMIC); if (!msm_jpeg_device_p) { diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index 86b7b1b6f6c0..579f032949a1 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -22,6 +22,7 @@ #define MSM_VDEC_DVC_NAME "msm_vdec_8974" #define MIN_NUM_OUTPUT_BUFFERS 4 #define MIN_NUM_OUTPUT_BUFFERS_VP9 6 +#define MIN_NUM_OUTPUT_BUFFERS_HEVC 5 #define MIN_NUM_CAPTURE_BUFFERS 6 #define MIN_NUM_THUMBNAIL_MODE_CAPTURE_BUFFERS 1 #define MAX_NUM_OUTPUT_BUFFERS VB2_MAX_FRAME @@ -1494,6 +1495,10 @@ static int msm_vdec_queue_setup(struct vb2_queue *q, V4L2_PIX_FMT_VP9 && *num_buffers < MIN_NUM_OUTPUT_BUFFERS_VP9) *num_buffers = MIN_NUM_OUTPUT_BUFFERS_VP9; + else if (inst->fmts[OUTPUT_PORT].fourcc == + V4L2_PIX_FMT_HEVC && + *num_buffers < MIN_NUM_OUTPUT_BUFFERS_HEVC) + *num_buffers = MIN_NUM_OUTPUT_BUFFERS_HEVC; for (i = 0; i < *num_planes; i++) { sizes[i] = get_frame_size(inst, diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c index e5e7449a1ebf..d31ed91f66cf 100644 --- a/drivers/media/platform/msm/vidc/msm_vidc_common.c +++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2449,7 +2449,6 @@ static int msm_comm_session_abort(struct msm_vidc_inst *inst) } hdev = inst->core->device; abort_completion = SESSION_MSG_INDEX(HAL_SESSION_ABORT_DONE); - init_completion(&inst->completions[abort_completion]); rc = call_hfi_op(hdev, session_abort, (void *)inst->session); if (rc) { @@ -2608,8 +2607,6 @@ static int msm_comm_init_core(struct msm_vidc_inst *inst) __func__); } - init_completion(&core->completions - [SYS_MSG_INDEX(HAL_SYS_INIT_DONE)]); rc = call_hfi_op(hdev, core_init, hdev->hfi_device_data); if (rc) { dprintk(VIDC_ERR, "Failed to init core, id = %d\n", @@ -2713,8 +2710,6 @@ static int msm_comm_session_init(int flipped_state, dprintk(VIDC_ERR, "Invalid session\n"); return -EINVAL; } - init_completion( - &inst->completions[SESSION_MSG_INDEX(HAL_SESSION_INIT_DONE)]); rc = call_hfi_op(hdev, session_init, hdev->hfi_device_data, inst, get_hal_domain(inst->session_type), @@ -2852,8 +2847,6 @@ static int msm_vidc_start(int flipped_state, struct msm_vidc_inst *inst) inst, inst->state); goto exit; } - init_completion( - &inst->completions[SESSION_MSG_INDEX(HAL_SESSION_START_DONE)]); rc = call_hfi_op(hdev, session_start, (void *) inst->session); if (rc) { dprintk(VIDC_ERR, @@ -2883,8 +2876,6 @@ static int msm_vidc_stop(int flipped_state, struct msm_vidc_inst *inst) goto exit; } dprintk(VIDC_DBG, "Send Stop to hal\n"); - init_completion( - &inst->completions[SESSION_MSG_INDEX(HAL_SESSION_STOP_DONE)]); rc = call_hfi_op(hdev, session_stop, (void *) inst->session); if (rc) { dprintk(VIDC_ERR, "Failed to send stop\n"); @@ -2914,8 +2905,6 @@ static int msm_vidc_release_res(int flipped_state, struct msm_vidc_inst *inst) } dprintk(VIDC_DBG, "Send release res to hal\n"); - init_completion(&inst->completions[ - SESSION_MSG_INDEX(HAL_SESSION_RELEASE_RESOURCE_DONE)]); rc = call_hfi_op(hdev, session_release_res, (void *) inst->session); if (rc) { dprintk(VIDC_ERR, @@ -2946,8 +2935,6 @@ static int msm_comm_session_close(int flipped_state, } dprintk(VIDC_DBG, "Send session close to hal\n"); - init_completion( - &inst->completions[SESSION_MSG_INDEX(HAL_SESSION_END_DONE)]); rc = call_hfi_op(hdev, session_end, (void *) inst->session); if (rc) { dprintk(VIDC_ERR, @@ -3987,8 +3974,6 @@ int msm_comm_try_get_prop(struct msm_vidc_inst *inst, enum hal_property ptype, } mutex_unlock(&inst->sync_lock); - init_completion(&inst->completions[ - SESSION_MSG_INDEX(HAL_SESSION_PROPERTY_INFO)]); switch (ptype) { case HAL_PARAM_PROFILE_LEVEL_CURRENT: case HAL_CONFIG_VDEC_ENTROPY: @@ -4212,8 +4197,6 @@ int msm_comm_release_scratch_buffers(struct msm_vidc_inst *inst, if (inst->state != MSM_VIDC_CORE_INVALID && core->state != VIDC_CORE_INVALID) { buffer_info.response_required = true; - init_completion(&inst->completions[SESSION_MSG_INDEX - (HAL_SESSION_RELEASE_BUFFER_DONE)]); rc = call_hfi_op(hdev, session_release_buffers, (void *)inst->session, &buffer_info); if (rc) { @@ -4284,9 +4267,6 @@ int msm_comm_release_persist_buffers(struct msm_vidc_inst *inst) if (inst->state != MSM_VIDC_CORE_INVALID && core->state != VIDC_CORE_INVALID) { buffer_info.response_required = true; - init_completion( - &inst->completions[SESSION_MSG_INDEX - (HAL_SESSION_RELEASE_BUFFER_DONE)]); rc = call_hfi_op(hdev, session_release_buffers, (void *)inst->session, &buffer_info); if (rc) { diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c index 2346364fe959..fb4ede7a287b 100644 --- a/drivers/media/platform/msm/vidc/venus_hfi.c +++ b/drivers/media/platform/msm/vidc/venus_hfi.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -937,8 +937,6 @@ static int __core_set_resource(struct venus_hfi_device *device, return rc; } -static DECLARE_COMPLETION(release_resources_done); - static int __alloc_imem(struct venus_hfi_device *device, unsigned long size) { struct imem *imem = NULL; @@ -2158,8 +2156,6 @@ static int venus_hfi_core_init(void *device) dev = device; mutex_lock(&dev->lock); - init_completion(&release_resources_done); - rc = __load_fw(dev); if (rc) { dprintk(VIDC_ERR, "Failed to load Venus FW\n"); @@ -3461,7 +3457,6 @@ static int __response_handler(struct venus_hfi_device *device) break; case HAL_SYS_RELEASE_RESOURCE_DONE: dprintk(VIDC_DBG, "Received SYS_RELEASE_RESOURCE\n"); - complete(&release_resources_done); break; case HAL_SYS_INIT_DONE: dprintk(VIDC_DBG, "Received SYS_INIT_DONE\n"); diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 233eccc5c33e..3e91109b205d 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -2117,6 +2117,7 @@ static int isp_initialize_modules(struct isp_device *isp) static void isp_detach_iommu(struct isp_device *isp) { + arm_iommu_detach_device(isp->dev); arm_iommu_release_mapping(isp->mapping); isp->mapping = NULL; iommu_group_remove_device(isp->dev); @@ -2150,8 +2151,7 @@ static int isp_attach_iommu(struct isp_device *isp) mapping = arm_iommu_create_mapping(&platform_bus_type, SZ_1G, SZ_2G); if (IS_ERR(mapping)) { dev_err(isp->dev, "failed to create ARM IOMMU mapping\n"); - ret = PTR_ERR(mapping); - goto error; + return PTR_ERR(mapping); } isp->mapping = mapping; @@ -2166,7 +2166,8 @@ static int isp_attach_iommu(struct isp_device *isp) return 0; error: - isp_detach_iommu(isp); + arm_iommu_release_mapping(isp->mapping); + isp->mapping = NULL; return ret; } diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index 2a497c80c77f..80261e556367 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -96,7 +96,7 @@ MODULE_PARM_DESC(max_rds_errors, "RDS maximum block errors: *1*"); */ int si470x_get_register(struct si470x_device *radio, int regnr) { - u16 buf[READ_REG_NUM]; + __be16 buf[READ_REG_NUM]; struct i2c_msg msgs[1] = { { .addr = radio->client->addr, @@ -121,7 +121,7 @@ int si470x_get_register(struct si470x_device *radio, int regnr) int si470x_set_register(struct si470x_device *radio, int regnr) { int i; - u16 buf[WRITE_REG_NUM]; + __be16 buf[WRITE_REG_NUM]; struct i2c_msg msgs[1] = { { .addr = radio->client->addr, @@ -151,7 +151,7 @@ int si470x_set_register(struct si470x_device *radio, int regnr) static int si470x_get_all_registers(struct si470x_device *radio) { int i; - u16 buf[READ_REG_NUM]; + __be16 buf[READ_REG_NUM]; struct i2c_msg msgs[1] = { { .addr = radio->client->addr, diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c index de1b1ba28f83..c8c5efd3c4b9 100644 --- a/drivers/mfd/wcd9xxx-core.c +++ b/drivers/mfd/wcd9xxx-core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2881,6 +2881,8 @@ static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev) else pdata->cdc_variant = WCD9XXX; } + pdata->wcd9xxx_mic_tristate = of_property_read_bool(dev->of_node, + "qcom,wcd9xxx-mic-tristate"); return pdata; err: diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index 80ed8a3b81b0..8e7d82ce1eb9 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -643,6 +643,13 @@ config MEMORY_STATE_TIME help Memory time statistics exported to /sys/kernel/memory_state_time + +config FORCE_FAST_CHARGE + bool "Force faster charge rate for USB" + default n + help + This allows users to override default charge rate for USB + source "drivers/misc/c2port/Kconfig" source "drivers/misc/eeprom/Kconfig" source "drivers/misc/cb710/Kconfig" diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 2ebaa0c98532..2b7ca8226ae7 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -84,3 +84,4 @@ obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o obj-$(CONFIG_APDS9930) += apds993x.o obj-$(CONFIG_UID_SYS_STATS) += uid_sys_stats.o obj-$(CONFIG_MEMORY_STATE_TIME) += memory_state_time.o +obj-$(CONFIG_FORCE_FAST_CHARGE) += fastchg.o diff --git a/drivers/misc/fastchg.c b/drivers/misc/fastchg.c new file mode 100644 index 000000000000..a00d425bb57d --- /dev/null +++ b/drivers/misc/fastchg.c @@ -0,0 +1,102 @@ +/* + * Author: Chad Froebel + * + * Port to Thulium: engstk + * + * 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 - Force faster charge +*/ + +#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) +{ + sscanf(buf, "%d ", &force_fast_charge); + if (force_fast_charge < 0 || force_fast_charge > 1) + force_fast_charge = 0; + + return count; +} + +static struct kobj_attribute force_fast_charge_attribute = +__ATTR(force_fast_charge, 0664, 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_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/drivers/misc/qseecom.c b/drivers/misc/qseecom.c index f2955be61899..1fca674d3ed9 100644 --- a/drivers/misc/qseecom.c +++ b/drivers/misc/qseecom.c @@ -8648,6 +8648,7 @@ static int qseecom_probe(struct platform_device *pdev) static int qseecom_remove(struct platform_device *pdev) { struct qseecom_registered_kclient_list *kclient = NULL; + struct qseecom_registered_kclient_list *kclient_tmp = NULL; unsigned long flags = 0; int ret = 0; int i; @@ -8657,10 +8658,8 @@ static int qseecom_remove(struct platform_device *pdev) atomic_set(&qseecom.qseecom_state, QSEECOM_STATE_NOT_READY); spin_lock_irqsave(&qseecom.registered_kclient_list_lock, flags); - list_for_each_entry(kclient, &qseecom.registered_kclient_list_head, - list) { - if (!kclient) - goto exit_irqrestore; + list_for_each_entry_safe(kclient, kclient_tmp, + &qseecom.registered_kclient_list_head, list) { /* Break the loop if client handle is NULL */ if (!kclient->handle) @@ -8684,7 +8683,7 @@ static int qseecom_remove(struct platform_device *pdev) kzfree(kclient->handle); exit_free_kclient: kzfree(kclient); -exit_irqrestore: + spin_unlock_irqrestore(&qseecom.registered_kclient_list_lock, flags); if (qseecom.qseos_version > QSEEE_VERSION_00) diff --git a/drivers/net/can/mscan/mpc5xxx_can.c b/drivers/net/can/mscan/mpc5xxx_can.c index 44725296f72a..655a387eb9ad 100644 --- a/drivers/net/can/mscan/mpc5xxx_can.c +++ b/drivers/net/can/mscan/mpc5xxx_can.c @@ -86,6 +86,11 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev, return 0; } cdm = of_iomap(np_cdm, 0); + if (!cdm) { + of_node_put(np_cdm); + dev_err(&ofdev->dev, "can't map clock node!\n"); + return 0; + } if (in_8(&cdm->ipb_clk_sel) & 0x1) freq *= 2; diff --git a/drivers/net/can/spi/k61.c b/drivers/net/can/spi/k61.c index 4668d40a1612..6bb9204dfc2f 100644 --- a/drivers/net/can/spi/k61.c +++ b/drivers/net/can/spi/k61.c @@ -60,6 +60,7 @@ struct k61_can { int cmd_result; int bits_per_word; int reset_delay_msec; + s64 time_diff; }; struct k61_netdev_privdata { @@ -97,6 +98,9 @@ struct spi_miso { /* TLV for MISO line */ #define CMD_CAN_DATA_BUFF_REMOVE 0x88 #define CMD_CAN_RELEASE_BUFFER 0x89 #define CMD_CAN_DATA_BUFF_REMOVE_ALL 0x8A +#define CMD_UPDATE_TIME_INFO 0x9D +#define CMD_SUSPEND_EVENT 0x9E +#define CMD_RESUME_EVENT 0x9F #define IOCTL_RELEASE_CAN_BUFFER (SIOCDEVPRIVATE + 0) #define IOCTL_ENABLE_BUFFERING (SIOCDEVPRIVATE + 1) @@ -112,7 +116,7 @@ struct can_fw_resp { } __packed; struct can_write_req { - u32 ts; + u64 ts; u32 mid; u8 dlc; u8 data[]; @@ -123,7 +127,7 @@ struct can_write_resp { } __packed; struct can_receive_frame { - u32 ts; + u64 ts; u32 mid; u8 dlc; u8 data[]; @@ -136,6 +140,10 @@ struct can_add_filter_req { u8 type; } __packed; +struct can_time_info { + u64 time; +} __packed; + static struct can_bittiming_const k61_bittiming_const = { .name = "k61", .tseg1_min = 4, @@ -199,8 +207,7 @@ static void k61_receive_frame(struct k61_can *priv_data, struct can_frame *cf; struct sk_buff *skb; struct skb_shared_hwtstamps *skt; - struct timeval tv; - static int msec; + ktime_t nsec; struct net_device *netdev; int i; @@ -217,7 +224,7 @@ static void k61_receive_frame(struct k61_can *priv_data, return; } - LOGDI("rcv frame %d %x %d %x %x %x %x %x %x %x %x\n", + LOGDI("rcv frame %llu %x %d %x %x %x %x %x %x %x %x\n", frame->ts, frame->mid, frame->dlc, frame->data[0], frame->data[1], frame->data[2], frame->data[3], frame->data[4], frame->data[5], frame->data[6], frame->data[7]); @@ -227,13 +234,11 @@ static void k61_receive_frame(struct k61_can *priv_data, for (i = 0; i < cf->can_dlc; i++) cf->data[i] = frame->data[i]; - msec = le32_to_cpu(frame->ts); - tv.tv_sec = msec / 1000; - tv.tv_usec = (msec - tv.tv_sec * 1000) * 1000; + nsec = ms_to_ktime(le64_to_cpu(frame->ts) + priv_data->time_diff); skt = skb_hwtstamps(skb); - skt->hwtstamp = timeval_to_ktime(tv); + skt->hwtstamp = nsec; LOGDI(" hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp)); - skb->tstamp = timeval_to_ktime(tv); + skb->tstamp = nsec; netif_rx(skb); netdev->stats.rx_packets++; netdev->stats.rx_bytes += cf->can_dlc; @@ -243,6 +248,9 @@ static void k61_process_response(struct k61_can *priv_data, struct spi_miso *resp) { int ret = 0; + u64 mstime; + ktime_t ktime_now; + LOGDI("<%x %2d [%d]\n", resp->cmd, resp->len, resp->seq); if (resp->cmd == CMD_CAN_RECEIVE_FRAME) { struct can_receive_frame *frame = @@ -253,6 +261,12 @@ static void k61_process_response(struct k61_can *priv_data, dev_info(&priv_data->spidev->dev, "fw %d.%d.%d", fw_resp->maj, fw_resp->min, fw_resp->ver); + } else if (resp->cmd == CMD_UPDATE_TIME_INFO) { + struct can_time_info *time_data = + (struct can_time_info *)resp->data; + ktime_now = ktime_get_boottime(); + mstime = ktime_to_ms(ktime_now); + priv_data->time_diff = mstime - (le64_to_cpu(time_data->time)); } if (resp->cmd == priv_data->wait_cmd) { @@ -377,6 +391,30 @@ static int k61_query_firmware_version(struct k61_can *priv_data) return ret; } +static int k61_notify_power_events(struct k61_can *priv_data, u8 event_type) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = event_type; + req->len = 0; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + ret = k61_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + static int k61_can_write(struct k61_can *priv_data, struct can_frame *cf) { char *tx_buf, *rx_buf; @@ -813,6 +851,7 @@ static int k61_probe(struct spi_device *spi) int err, retry = 0, query_err = -1; struct k61_can *priv_data; struct device *dev; + u32 irq_type; dev = &spi->dev; dev_dbg(dev, "k61_probe"); @@ -869,8 +908,11 @@ static int k61_probe(struct spi_device *spi) goto unregister_candev; } + irq_type = irq_get_trigger_type(spi->irq); + if (irq_type == IRQ_TYPE_NONE) + irq_type = IRQ_TYPE_EDGE_FALLING; err = request_threaded_irq(spi->irq, NULL, k61_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + irq_type | IRQF_ONESHOT, "k61", priv_data); if (err) { dev_err(dev, "Failed to request irq: %d", err); @@ -924,7 +966,10 @@ static const struct of_device_id k61_match_table[] = { static int k61_suspend(struct device *dev) { struct spi_device *spi = to_spi_device(dev); + struct k61_can *priv_data = spi_get_drvdata(spi); + u8 power_event = CMD_SUSPEND_EVENT; + k61_notify_power_events(priv_data, power_event); enable_irq_wake(spi->irq); return 0; } @@ -933,9 +978,10 @@ static int k61_resume(struct device *dev) { struct spi_device *spi = to_spi_device(dev); struct k61_can *priv_data = spi_get_drvdata(spi); + u8 power_event = CMD_RESUME_EVENT; disable_irq_wake(spi->irq); - k61_rx_message(priv_data); + k61_notify_power_events(priv_data, power_event); return 0; } diff --git a/drivers/net/can/spi/qti-can.c b/drivers/net/can/spi/qti-can.c index 253e341dbb58..27bd2fe2edff 100644 --- a/drivers/net/can/spi/qti-can.c +++ b/drivers/net/can/spi/qti-can.c @@ -70,6 +70,7 @@ struct qti_can { bool can_fw_cmd_timeout_req; u32 rem_all_buffering_timeout_ms; u32 can_fw_cmd_timeout_ms; + s64 time_diff; }; struct qti_can_netdev_privdata { @@ -118,6 +119,10 @@ struct spi_miso { /* TLV for MISO line */ #define CMD_BEGIN_BOOT_ROM_UPGRADE 0x99 #define CMD_BOOT_ROM_UPGRADE_DATA 0x9A #define CMD_END_BOOT_ROM_UPGRADE 0x9B +#define CMD_END_FW_UPDATE_FILE 0x9C +#define CMD_UPDATE_TIME_INFO 0x9D +#define CMD_SUSPEND_EVENT 0x9E +#define CMD_RESUME_EVENT 0x9F #define IOCTL_RELEASE_CAN_BUFFER (SIOCDEVPRIVATE + 0) #define IOCTL_ENABLE_BUFFERING (SIOCDEVPRIVATE + 1) @@ -132,6 +137,7 @@ struct spi_miso { /* TLV for MISO line */ #define IOCTL_BEGIN_BOOT_ROM_UPGRADE (SIOCDEVPRIVATE + 11) #define IOCTL_BOOT_ROM_UPGRADE_DATA (SIOCDEVPRIVATE + 12) #define IOCTL_END_BOOT_ROM_UPGRADE (SIOCDEVPRIVATE + 13) +#define IOCTL_END_FW_UPDATE_FILE (SIOCDEVPRIVATE + 14) #define IFR_DATA_OFFSET 0x100 struct can_fw_resp { @@ -163,7 +169,7 @@ struct can_add_filter_resp { struct can_receive_frame { u8 can_if; - u32 ts; + u64 ts; u32 mid; u8 dlc; u8 data[8]; @@ -178,6 +184,10 @@ struct can_config_bit_timing { u32 brp; } __packed; +struct can_time_info { + u64 time; +} __packed; + static struct can_bittiming_const rh850_bittiming_const = { .name = "qti_can", .tseg1_min = 1, @@ -291,7 +301,7 @@ static void qti_can_receive_frame(struct qti_can *priv_data, return; } - LOGDI("rcv frame %d %d %x %d %x %x %x %x %x %x %x %x\n", + LOGDI("rcv frame %d %llu %x %d %x %x %x %x %x %x %x %x\n", frame->can_if, frame->ts, frame->mid, frame->dlc, frame->data[0], frame->data[1], frame->data[2], frame->data[3], frame->data[4], frame->data[5], frame->data[6], frame->data[7]); @@ -301,7 +311,8 @@ static void qti_can_receive_frame(struct qti_can *priv_data, for (i = 0; i < cf->can_dlc; i++) cf->data[i] = frame->data[i]; - nsec = ms_to_ktime(le32_to_cpu(frame->ts)); + nsec = ms_to_ktime(le64_to_cpu(frame->ts) + priv_data->time_diff); + skt = skb_hwtstamps(skb); skt->hwtstamp = nsec; LOGDI(" hwtstamp %lld\n", ktime_to_ms(skt->hwtstamp)); @@ -354,6 +365,8 @@ static int qti_can_process_response(struct qti_can *priv_data, struct spi_miso *resp, int length) { int ret = 0; + u64 mstime; + ktime_t ktime_now; LOGDI("<%x %2d [%d]\n", resp->cmd, resp->len, resp->seq); if (resp->cmd == CMD_CAN_RECEIVE_FRAME) { @@ -402,6 +415,12 @@ static int qti_can_process_response(struct qti_can *priv_data, ret |= (fw_resp->br_min & 0xFF) << 16; ret |= (fw_resp->maj & 0xF) << 8; ret |= (fw_resp->min & 0xFF); + } else if (resp->cmd == CMD_UPDATE_TIME_INFO) { + struct can_time_info *time_data = + (struct can_time_info *)resp->data; + ktime_now = ktime_get_boottime(); + mstime = ktime_to_ms(ktime_now); + priv_data->time_diff = mstime - (le64_to_cpu(time_data->time)); } if (resp->cmd == priv_data->wait_cmd) { @@ -563,6 +582,30 @@ static int qti_can_query_firmware_version(struct qti_can *priv_data) return ret; } +static int qti_can_notify_power_events(struct qti_can *priv_data, u8 event_type) +{ + char *tx_buf, *rx_buf; + int ret; + struct spi_mosi *req; + + mutex_lock(&priv_data->spi_lock); + tx_buf = priv_data->tx_buf; + rx_buf = priv_data->rx_buf; + memset(tx_buf, 0, XFER_BUFFER_SIZE); + memset(rx_buf, 0, XFER_BUFFER_SIZE); + priv_data->xfer_length = XFER_BUFFER_SIZE; + + req = (struct spi_mosi *)tx_buf; + req->cmd = event_type; + req->len = 0; + req->seq = atomic_inc_return(&priv_data->msg_seq); + + ret = qti_can_do_spi_transaction(priv_data); + mutex_unlock(&priv_data->spi_lock); + + return ret; +} + static int qti_can_set_bitrate(struct net_device *netdev) { char *tx_buf, *rx_buf; @@ -983,6 +1026,8 @@ static int qti_can_convert_ioctl_cmd_to_spi_cmd(int ioctl_cmd) return CMD_BOOT_ROM_UPGRADE_DATA; case IOCTL_END_BOOT_ROM_UPGRADE: return CMD_END_BOOT_ROM_UPGRADE; + case IOCTL_END_FW_UPDATE_FILE: + return CMD_END_FW_UPDATE_FILE; } return -EINVAL; } @@ -1119,6 +1164,7 @@ static int qti_can_netdev_do_ioctl(struct net_device *netdev, case IOCTL_BEGIN_BOOT_ROM_UPGRADE: case IOCTL_BOOT_ROM_UPGRADE_DATA: case IOCTL_END_BOOT_ROM_UPGRADE: + case IOCTL_END_FW_UPDATE_FILE: ret = qti_can_do_blocking_ioctl(netdev, ifr, cmd); break; } @@ -1243,6 +1289,7 @@ static int qti_can_probe(struct spi_device *spi) int err, retry = 0, query_err = -1, i; struct qti_can *priv_data = NULL; struct device *dev; + u32 irq_type; dev = &spi->dev; dev_info(dev, "qti_can_probe"); @@ -1319,7 +1366,7 @@ static int qti_can_probe(struct spi_device *spi) } priv_data->support_can_fd = of_property_read_bool(spi->dev.of_node, - "support-can-fd"); + "qcom,support-can-fd"); if (of_device_is_compatible(spi->dev.of_node, "qcom,nxp,mpc5746c")) qti_can_bittiming_const = flexcan_bittiming_const; @@ -1349,8 +1396,11 @@ static int qti_can_probe(struct spi_device *spi) } } + irq_type = irq_get_trigger_type(spi->irq); + if (irq_type == IRQ_TYPE_NONE) + irq_type = IRQ_TYPE_EDGE_FALLING; err = request_threaded_irq(spi->irq, NULL, qti_can_irq, - IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + irq_type | IRQF_ONESHOT, "qti-can", priv_data); if (err) { LOGDE("Failed to request irq: %d", err); @@ -1416,6 +1466,10 @@ static int qti_can_remove(struct spi_device *spi) static int qti_can_suspend(struct device *dev) { struct spi_device *spi = to_spi_device(dev); + struct qti_can *priv_data = spi_get_drvdata(spi); + u8 power_event = CMD_SUSPEND_EVENT; + + qti_can_notify_power_events(priv_data, power_event); enable_irq_wake(spi->irq); return 0; @@ -1425,9 +1479,10 @@ static int qti_can_resume(struct device *dev) { struct spi_device *spi = to_spi_device(dev); struct qti_can *priv_data = spi_get_drvdata(spi); + u8 power_event = CMD_RESUME_EVENT; disable_irq_wake(spi->irq); - qti_can_rx_message(priv_data); + qti_can_notify_power_events(priv_data, power_event); return 0; } diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index b1ca40552a84..2af6e3c8b718 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -1083,6 +1083,7 @@ static void ems_usb_disconnect(struct usb_interface *intf) usb_free_urb(dev->intr_urb); kfree(dev->intr_in_buffer); + kfree(dev->tx_msg_buffer); } } diff --git a/drivers/net/can/xilinx_can.c b/drivers/net/can/xilinx_can.c index 8a998e3884ce..8ca23539c23a 100644 --- a/drivers/net/can/xilinx_can.c +++ b/drivers/net/can/xilinx_can.c @@ -25,8 +25,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -100,7 +102,7 @@ enum xcan_reg { #define XCAN_INTR_ALL (XCAN_IXR_TXOK_MASK | XCAN_IXR_BSOFF_MASK |\ XCAN_IXR_WKUP_MASK | XCAN_IXR_SLP_MASK | \ XCAN_IXR_RXNEMP_MASK | XCAN_IXR_ERROR_MASK | \ - XCAN_IXR_ARBLST_MASK | XCAN_IXR_RXOK_MASK) + XCAN_IXR_RXOFLW_MASK | XCAN_IXR_ARBLST_MASK) /* CAN register bit shift - XCAN___SHIFT */ #define XCAN_BTR_SJW_SHIFT 7 /* Synchronous jump width */ @@ -117,6 +119,7 @@ enum xcan_reg { /** * struct xcan_priv - This definition define CAN driver instance * @can: CAN private data structure. + * @tx_lock: Lock for synchronizing TX interrupt handling * @tx_head: Tx CAN packets ready to send on the queue * @tx_tail: Tx CAN packets successfully sended on the queue * @tx_max: Maximum number packets the driver can send @@ -131,6 +134,7 @@ enum xcan_reg { */ struct xcan_priv { struct can_priv can; + spinlock_t tx_lock; unsigned int tx_head; unsigned int tx_tail; unsigned int tx_max; @@ -158,6 +162,11 @@ static const struct can_bittiming_const xcan_bittiming_const = { .brp_inc = 1, }; +#define XCAN_CAP_WATERMARK 0x0001 +struct xcan_devtype_data { + unsigned int caps; +}; + /** * xcan_write_reg_le - Write a value to the device register little endian * @priv: Driver private data structure @@ -237,6 +246,10 @@ static int set_reset_mode(struct net_device *ndev) usleep_range(500, 10000); } + /* reset clears FIFOs */ + priv->tx_head = 0; + priv->tx_tail = 0; + return 0; } @@ -391,6 +404,7 @@ static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) struct net_device_stats *stats = &ndev->stats; struct can_frame *cf = (struct can_frame *)skb->data; u32 id, dlc, data[2] = {0, 0}; + unsigned long flags; if (can_dropped_invalid_skb(ndev, skb)) return NETDEV_TX_OK; @@ -438,6 +452,9 @@ static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) data[1] = be32_to_cpup((__be32 *)(cf->data + 4)); can_put_echo_skb(skb, ndev, priv->tx_head % priv->tx_max); + + spin_lock_irqsave(&priv->tx_lock, flags); + priv->tx_head++; /* Write the Frame to Xilinx CAN TX FIFO */ @@ -453,10 +470,16 @@ static int xcan_start_xmit(struct sk_buff *skb, struct net_device *ndev) stats->tx_bytes += cf->can_dlc; } + /* Clear TX-FIFO-empty interrupt for xcan_tx_interrupt() */ + if (priv->tx_max > 1) + priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_TXFEMP_MASK); + /* Check if the TX buffer is full */ if ((priv->tx_head - priv->tx_tail) == priv->tx_max) netif_stop_queue(ndev); + spin_unlock_irqrestore(&priv->tx_lock, flags); + return NETDEV_TX_OK; } @@ -598,7 +621,6 @@ static void xcan_err_interrupt(struct net_device *ndev, u32 isr) if (isr & XCAN_IXR_RXOFLW_MASK) { stats->rx_over_errors++; stats->rx_errors++; - priv->write_reg(priv, XCAN_SRR_OFFSET, XCAN_SRR_RESET_MASK); if (skb) { cf->can_id |= CAN_ERR_CRTL; cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW; @@ -710,15 +732,7 @@ static int xcan_rx_poll(struct napi_struct *napi, int quota) isr = priv->read_reg(priv, XCAN_ISR_OFFSET); while ((isr & XCAN_IXR_RXNEMP_MASK) && (work_done < quota)) { - if (isr & XCAN_IXR_RXOK_MASK) { - priv->write_reg(priv, XCAN_ICR_OFFSET, - XCAN_IXR_RXOK_MASK); - work_done += xcan_rx(ndev); - } else { - priv->write_reg(priv, XCAN_ICR_OFFSET, - XCAN_IXR_RXNEMP_MASK); - break; - } + work_done += xcan_rx(ndev); priv->write_reg(priv, XCAN_ICR_OFFSET, XCAN_IXR_RXNEMP_MASK); isr = priv->read_reg(priv, XCAN_ISR_OFFSET); } @@ -729,7 +743,7 @@ static int xcan_rx_poll(struct napi_struct *napi, int quota) if (work_done < quota) { napi_complete(napi); ier = priv->read_reg(priv, XCAN_IER_OFFSET); - ier |= (XCAN_IXR_RXOK_MASK | XCAN_IXR_RXNEMP_MASK); + ier |= XCAN_IXR_RXNEMP_MASK; priv->write_reg(priv, XCAN_IER_OFFSET, ier); } return work_done; @@ -801,9 +815,9 @@ static irqreturn_t xcan_interrupt(int irq, void *dev_id) } /* Check for the type of receive interrupt and Processing it */ - if (isr & (XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK)) { + if (isr & XCAN_IXR_RXNEMP_MASK) { ier = priv->read_reg(priv, XCAN_IER_OFFSET); - ier &= ~(XCAN_IXR_RXNEMP_MASK | XCAN_IXR_RXOK_MASK); + ier &= ~XCAN_IXR_RXNEMP_MASK; priv->write_reg(priv, XCAN_IER_OFFSET, ier); napi_schedule(&priv->napi); } @@ -1032,6 +1046,18 @@ static int __maybe_unused xcan_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(xcan_dev_pm_ops, xcan_suspend, xcan_resume); +static const struct xcan_devtype_data xcan_zynq_data = { + .caps = XCAN_CAP_WATERMARK, +}; + +/* Match table for OF platform binding */ +static const struct of_device_id xcan_of_match[] = { + { .compatible = "xlnx,zynq-can-1.0", .data = &xcan_zynq_data }, + { .compatible = "xlnx,axi-can-1.00.a", }, + { /* end of list */ }, +}; +MODULE_DEVICE_TABLE(of, xcan_of_match); + /** * xcan_probe - Platform registration call * @pdev: Handle to the platform device structure @@ -1046,8 +1072,10 @@ static int xcan_probe(struct platform_device *pdev) struct resource *res; /* IO mem resources */ struct net_device *ndev; struct xcan_priv *priv; + const struct of_device_id *of_id; + int caps = 0; void __iomem *addr; - int ret, rx_max, tx_max; + int ret, rx_max, tx_max, tx_fifo_depth; /* Get the virtual base address for the device */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -1057,7 +1085,8 @@ static int xcan_probe(struct platform_device *pdev) goto err; } - ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", &tx_max); + ret = of_property_read_u32(pdev->dev.of_node, "tx-fifo-depth", + &tx_fifo_depth); if (ret < 0) goto err; @@ -1065,6 +1094,30 @@ static int xcan_probe(struct platform_device *pdev) if (ret < 0) goto err; + of_id = of_match_device(xcan_of_match, &pdev->dev); + if (of_id) { + const struct xcan_devtype_data *devtype_data = of_id->data; + + if (devtype_data) + caps = devtype_data->caps; + } + + /* There is no way to directly figure out how many frames have been + * sent when the TXOK interrupt is processed. If watermark programming + * is supported, we can have 2 frames in the FIFO and use TXFEMP + * to determine if 1 or 2 frames have been sent. + * Theoretically we should be able to use TXFWMEMP to determine up + * to 3 frames, but it seems that after putting a second frame in the + * FIFO, with watermark at 2 frames, it can happen that TXFWMEMP (less + * than 2 frames in FIFO) is set anyway with no TXOK (a frame was + * sent), which is not a sensible state - possibly TXFWMEMP is not + * completely synchronized with the rest of the bits? + */ + if (caps & XCAN_CAP_WATERMARK) + tx_max = min(tx_fifo_depth, 2); + else + tx_max = 1; + /* Create a CAN device instance */ ndev = alloc_candev(sizeof(struct xcan_priv), tx_max); if (!ndev) @@ -1079,6 +1132,7 @@ static int xcan_probe(struct platform_device *pdev) CAN_CTRLMODE_BERR_REPORTING; priv->reg_base = addr; priv->tx_max = tx_max; + spin_lock_init(&priv->tx_lock); /* Get IRQ for the device */ ndev->irq = platform_get_irq(pdev, 0); @@ -1146,9 +1200,9 @@ static int xcan_probe(struct platform_device *pdev) devm_can_led_init(ndev); clk_disable_unprepare(priv->bus_clk); clk_disable_unprepare(priv->can_clk); - netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth:%d\n", + netdev_dbg(ndev, "reg_base=0x%p irq=%d clock=%d, tx fifo depth: actual %d, using %d\n", priv->reg_base, ndev->irq, priv->can.clock.freq, - priv->tx_max); + tx_fifo_depth, priv->tx_max); return 0; @@ -1184,14 +1238,6 @@ static int xcan_remove(struct platform_device *pdev) return 0; } -/* Match table for OF platform binding */ -static struct of_device_id xcan_of_match[] = { - { .compatible = "xlnx,zynq-can-1.0", }, - { .compatible = "xlnx,axi-can-1.00.a", }, - { /* end of list */ }, -}; -MODULE_DEVICE_TABLE(of, xcan_of_match); - static struct platform_driver xcan_driver = { .probe = xcan_probe, .remove = xcan_remove, diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 067f2cb9b215..ae05c8734d49 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c @@ -1674,6 +1674,7 @@ static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter) skb = build_skb(page_address(page) + adapter->rx_page_offset, adapter->rx_frag_size); if (likely(skb)) { + skb_reserve(skb, NET_SKB_PAD); adapter->rx_page_offset += adapter->rx_frag_size; if (adapter->rx_page_offset >= PAGE_SIZE) adapter->rx_page = NULL; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index 29e8e6eceb64..3a794871423b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -1613,6 +1613,7 @@ struct bnx2x { struct link_vars link_vars; u32 link_cnt; struct bnx2x_link_report_data last_reported_link; + bool force_link_down; struct mdio_if_info mdio; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index f41f53fe1340..82e6c7f12ec2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c @@ -1257,6 +1257,11 @@ void __bnx2x_link_report(struct bnx2x *bp) { struct bnx2x_link_report_data cur_data; + if (bp->force_link_down) { + bp->link_vars.link_up = 0; + return; + } + /* reread mf_cfg */ if (IS_PF(bp) && !CHIP_IS_E1(bp)) bnx2x_read_mf_cfg(bp); @@ -2799,6 +2804,7 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode) bp->pending_max = 0; } + bp->force_link_down = false; if (bp->port.pmf) { rc = bnx2x_initial_phy_init(bp, load_mode); if (rc) diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 1edc931b1458..2a518c998ecc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c @@ -3296,14 +3296,18 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); - return bnx2x_rss(bp, &bp->rss_conf_obj, false, true); + if (bp->state == BNX2X_STATE_OPEN) + return bnx2x_rss(bp, &bp->rss_conf_obj, false, + true); } else if ((info->flow_type == UDP_V6_FLOW) && (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; DP(BNX2X_MSG_ETHTOOL, "rss re-configured, UDP 4-tupple %s\n", udp_rss_requested ? "enabled" : "disabled"); - return bnx2x_rss(bp, &bp->rss_conf_obj, false, true); + if (bp->state == BNX2X_STATE_OPEN) + return bnx2x_rss(bp, &bp->rss_conf_obj, false, + true); } return 0; @@ -3401,7 +3405,10 @@ static int bnx2x_set_rxfh(struct net_device *dev, const u32 *indir, bp->rss_conf_obj.ind_table[i] = indir[i] + bp->fp->cl_id; } - return bnx2x_config_rss_eth(bp, false); + if (bp->state == BNX2X_STATE_OPEN) + return bnx2x_config_rss_eth(bp, false); + + return 0; } /** diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index f8e8206d7620..8063e928827c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c @@ -10036,6 +10036,12 @@ static void bnx2x_sp_rtnl_task(struct work_struct *work) bp->sp_rtnl_state = 0; smp_mb(); + /* Immediately indicate link as down */ + bp->link_vars.link_up = 0; + bp->force_link_down = true; + netif_carrier_off(bp->dev); + BNX2X_ERR("Indicating link is down due to Tx-timeout\n"); + bnx2x_nic_unload(bp, UNLOAD_NORMAL, true); bnx2x_nic_load(bp, LOAD_NORMAL); diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index a9db2337d9e2..faee5ed88e5c 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -529,7 +529,7 @@ static void dcb_tx_queue_prio_enable(struct net_device *dev, int enable) "Can't %s DCB Priority on port %d, TX Queue %d: err=%d\n", enable ? "set" : "unset", pi->port_id, i, -err); else - txq->dcb_prio = value; + txq->dcb_prio = enable ? value : 0; } } #endif /* CONFIG_CHELSIO_T4_DCB */ diff --git a/drivers/net/ethernet/cisco/enic/enic_clsf.c b/drivers/net/ethernet/cisco/enic/enic_clsf.c index 0be6850be8a2..d911a3e94528 100644 --- a/drivers/net/ethernet/cisco/enic/enic_clsf.c +++ b/drivers/net/ethernet/cisco/enic/enic_clsf.c @@ -78,7 +78,6 @@ void enic_rfs_flw_tbl_init(struct enic *enic) enic->rfs_h.max = enic->config.num_arfs; enic->rfs_h.free = enic->rfs_h.max; enic->rfs_h.toclean = 0; - enic_rfs_timer_start(enic); } void enic_rfs_flw_tbl_free(struct enic *enic) @@ -87,7 +86,6 @@ void enic_rfs_flw_tbl_free(struct enic *enic) enic_rfs_timer_stop(enic); spin_lock_bh(&enic->rfs_h.lock); - enic->rfs_h.free = 0; for (i = 0; i < (1 << ENIC_RFS_FLW_BITSHIFT); i++) { struct hlist_head *hhead; struct hlist_node *tmp; @@ -98,6 +96,7 @@ void enic_rfs_flw_tbl_free(struct enic *enic) enic_delfltr(enic, n->fltr_id); hlist_del(&n->node); kfree(n); + enic->rfs_h.free++; } } spin_unlock_bh(&enic->rfs_h.lock); diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c index 14b19aa2125f..c6775de7b4f2 100644 --- a/drivers/net/ethernet/cisco/enic/enic_main.c +++ b/drivers/net/ethernet/cisco/enic/enic_main.c @@ -1643,7 +1643,7 @@ static int enic_open(struct net_device *netdev) vnic_intr_unmask(&enic->intr[i]); enic_notify_timer_start(enic); - enic_rfs_flw_tbl_init(enic); + enic_rfs_timer_start(enic); return 0; @@ -1717,10 +1717,32 @@ static int enic_stop(struct net_device *netdev) return 0; } +static int _enic_change_mtu(struct net_device *netdev, int new_mtu) +{ + bool running = netif_running(netdev); + int err = 0; + + ASSERT_RTNL(); + if (running) { + err = enic_stop(netdev); + if (err) + return err; + } + + netdev->mtu = new_mtu; + + if (running) { + err = enic_open(netdev); + if (err) + return err; + } + + return 0; +} + static int enic_change_mtu(struct net_device *netdev, int new_mtu) { struct enic *enic = netdev_priv(netdev); - int running = netif_running(netdev); if (new_mtu < ENIC_MIN_MTU || new_mtu > ENIC_MAX_MTU) return -EINVAL; @@ -1728,20 +1750,12 @@ static int enic_change_mtu(struct net_device *netdev, int new_mtu) if (enic_is_dynamic(enic) || enic_is_sriov_vf(enic)) return -EOPNOTSUPP; - if (running) - enic_stop(netdev); - - netdev->mtu = new_mtu; - if (netdev->mtu > enic->port_mtu) netdev_warn(netdev, - "interface MTU (%d) set higher than port MTU (%d)\n", - netdev->mtu, enic->port_mtu); + "interface MTU (%d) set higher than port MTU (%d)\n", + netdev->mtu, enic->port_mtu); - if (running) - enic_open(netdev); - - return 0; + return _enic_change_mtu(netdev, new_mtu); } static void enic_change_mtu_work(struct work_struct *work) @@ -1749,47 +1763,9 @@ static void enic_change_mtu_work(struct work_struct *work) struct enic *enic = container_of(work, struct enic, change_mtu_work); struct net_device *netdev = enic->netdev; int new_mtu = vnic_dev_mtu(enic->vdev); - int err; - unsigned int i; - - new_mtu = max_t(int, ENIC_MIN_MTU, min_t(int, ENIC_MAX_MTU, new_mtu)); rtnl_lock(); - - /* Stop RQ */ - del_timer_sync(&enic->notify_timer); - - for (i = 0; i < enic->rq_count; i++) - napi_disable(&enic->napi[i]); - - vnic_intr_mask(&enic->intr[0]); - enic_synchronize_irqs(enic); - err = vnic_rq_disable(&enic->rq[0]); - if (err) { - rtnl_unlock(); - netdev_err(netdev, "Unable to disable RQ.\n"); - return; - } - vnic_rq_clean(&enic->rq[0], enic_free_rq_buf); - vnic_cq_clean(&enic->cq[0]); - vnic_intr_clean(&enic->intr[0]); - - /* Fill RQ with new_mtu-sized buffers */ - netdev->mtu = new_mtu; - vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf); - /* Need at least one buffer on ring to get going */ - if (vnic_rq_desc_used(&enic->rq[0]) == 0) { - rtnl_unlock(); - netdev_err(netdev, "Unable to alloc receive buffers.\n"); - return; - } - - /* Start RQ */ - vnic_rq_enable(&enic->rq[0]); - napi_enable(&enic->napi[0]); - vnic_intr_unmask(&enic->intr[0]); - enic_notify_timer_start(enic); - + (void)_enic_change_mtu(netdev, new_mtu); rtnl_unlock(); netdev_info(netdev, "interface MTU set as %d\n", netdev->mtu); @@ -2508,6 +2484,7 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) enic->notify_timer.function = enic_notify_timer; enic->notify_timer.data = (unsigned long)enic; + enic_rfs_flw_tbl_init(enic); enic_set_rx_coal_setting(enic); INIT_WORK(&enic->reset, enic_reset); INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index b5f484bf3fda..4be0a22757d2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -1781,7 +1781,12 @@ s32 ixgbe_set_rar_generic(struct ixgbe_hw *hw, u32 index, u8 *addr, u32 vmdq, if (enable_addr != 0) rar_high |= IXGBE_RAH_AV; + /* Record lower 32 bits of MAC address and then make + * sure that write is flushed to hardware before writing + * the upper 16 bits and setting the valid bit. + */ IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low); + IXGBE_WRITE_FLUSH(hw); IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); return 0; @@ -1813,8 +1818,13 @@ s32 ixgbe_clear_rar_generic(struct ixgbe_hw *hw, u32 index) rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index)); rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV); - IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); + /* Clear the address valid bit and upper 16 bits of the address + * before clearing the lower bits. This way we aren't updating + * a live filter. + */ IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high); + IXGBE_WRITE_FLUSH(hw); + IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0); /* clear VMDq pool/queue selection for this RAR */ hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL); diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index fbb0c02276f9..816b614025b4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -2709,7 +2709,7 @@ int mlx4_RST2INIT_QP_wrapper(struct mlx4_dev *dev, int slave, u32 srqn = qp_get_srqn(qpc) & 0xffffff; int use_srq = (qp_get_srqn(qpc) >> 24) & 1; struct res_srq *srq; - int local_qpn = be32_to_cpu(qpc->local_qpn) & 0xffffff; + int local_qpn = vhcr->in_modifier & 0xffffff; err = qp_res_start_move_to(dev, slave, qpn, RES_QP_HW, &qp, 0); if (err) diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c index 59a721fba018..8c787fab7993 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c @@ -1136,6 +1136,8 @@ static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp, return QL_STATUS_INVALID_PARAM; ret = kstrtoul(buf, 16, &data); + if (ret) + return ret; switch (data) { case QLC_83XX_FLASH_SECTOR_ERASE_CMD: diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c index 487d6ab771e9..2ec7fa82b4cf 100644 --- a/drivers/net/ethernet/qualcomm/qca_spi.c +++ b/drivers/net/ethernet/qualcomm/qca_spi.c @@ -636,7 +636,7 @@ qcaspi_netdev_open(struct net_device *dev) return ret; } - netif_start_queue(qca->net_dev); + /* SPI thread takes care of TX queue */ return 0; } @@ -740,6 +740,9 @@ qcaspi_netdev_tx_timeout(struct net_device *dev) qca->net_dev->stats.tx_errors++; /* Trigger tx queue flush and QCA7000 reset */ qca->sync = QCASPI_SYNC_UNKNOWN; + + if (qca->spi_thread) + wake_up_process(qca->spi_thread); } static int diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 103ae8ef8643..fc7b5ac6d6fe 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -53,7 +53,7 @@ #include "stmmac.h" #include -#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x) +#define STMMAC_ALIGN(x) __ALIGN_KERNEL(x, SMP_CACHE_BYTES) /* Module parameters */ #define TX_TIMEO 5000 diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index ea712512c7d1..03fcce11ea4e 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -1514,6 +1514,10 @@ static int emac_devioctl(struct net_device *ndev, struct ifreq *ifrq, int cmd) static int match_first_device(struct device *dev, void *data) { + if (dev->parent && dev->parent->of_node) + return of_device_is_compatible(dev->parent->of_node, + "ti,davinci_mdio"); + return !strncmp(dev_name(dev), "davinci_mdio", 12); } diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c index 3b67d60d4378..bc42a1d7a43f 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_mdio.c @@ -219,6 +219,7 @@ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) ret = of_mdiobus_register(bus, np1); if (ret) { mdiobus_free(bus); + lp->mii_bus = NULL; return ret; } return 0; diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c index c2894e43840e..35db4fc691e7 100644 --- a/drivers/net/hamradio/bpqether.c +++ b/drivers/net/hamradio/bpqether.c @@ -90,10 +90,6 @@ static const char banner[] __initconst = KERN_INFO \ "AX.25: bpqether driver version 004\n"; -static char bcast_addr[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; - -static char bpq_eth_addr[6]; - static int bpq_rcv(struct sk_buff *, struct net_device *, struct packet_type *, struct net_device *); static int bpq_device_event(struct notifier_block *, unsigned long, void *); @@ -512,8 +508,8 @@ static int bpq_new_device(struct net_device *edev) bpq->ethdev = edev; bpq->axdev = ndev; - memcpy(bpq->dest_addr, bcast_addr, sizeof(bpq_eth_addr)); - memcpy(bpq->acpt_addr, bcast_addr, sizeof(bpq_eth_addr)); + eth_broadcast_addr(bpq->dest_addr); + eth_broadcast_addr(bpq->acpt_addr); err = register_netdevice(ndev); if (err) diff --git a/drivers/net/usb/rtl8150.c b/drivers/net/usb/rtl8150.c index 30b44326364e..ab9cfa8e6ac6 100644 --- a/drivers/net/usb/rtl8150.c +++ b/drivers/net/usb/rtl8150.c @@ -661,7 +661,7 @@ static void rtl8150_set_multicast(struct net_device *netdev) (netdev->flags & IFF_ALLMULTI)) { rx_creg &= 0xfffe; rx_creg |= 0x0002; - dev_info(&netdev->dev, "%s: allmulti set\n", netdev->name); + dev_dbg(&netdev->dev, "%s: allmulti set\n", netdev->name); } else { /* ~RX_MULTICAST, ~RX_PROMISCUOUS */ rx_creg &= 0x00fc; diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c index b1fccaaf96b8..c3b6815f07c3 100644 --- a/drivers/net/usb/smsc75xx.c +++ b/drivers/net/usb/smsc75xx.c @@ -81,6 +81,9 @@ static bool turbo_mode = true; module_param(turbo_mode, bool, 0644); MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); +static int smsc75xx_link_ok_nopm(struct usbnet *dev); +static int smsc75xx_phy_gig_workaround(struct usbnet *dev); + static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index, u32 *data, int in_pm) { @@ -840,6 +843,9 @@ static int smsc75xx_phy_initialize(struct usbnet *dev) return -EIO; } + /* phy workaround for gig link */ + smsc75xx_phy_gig_workaround(dev); + smsc75xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); @@ -978,6 +984,62 @@ static int smsc75xx_wait_ready(struct usbnet *dev, int in_pm) return -EIO; } +static int smsc75xx_phy_gig_workaround(struct usbnet *dev) +{ + struct mii_if_info *mii = &dev->mii; + int ret = 0, timeout = 0; + u32 buf, link_up = 0; + + /* Set the phy in Gig loopback */ + smsc75xx_mdio_write(dev->net, mii->phy_id, MII_BMCR, 0x4040); + + /* Wait for the link up */ + do { + link_up = smsc75xx_link_ok_nopm(dev); + usleep_range(10000, 20000); + timeout++; + } while ((!link_up) && (timeout < 1000)); + + if (timeout >= 1000) { + netdev_warn(dev->net, "Timeout waiting for PHY link up\n"); + return -EIO; + } + + /* phy reset */ + ret = smsc75xx_read_reg(dev, PMT_CTL, &buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", ret); + return ret; + } + + buf |= PMT_CTL_PHY_RST; + + ret = smsc75xx_write_reg(dev, PMT_CTL, buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to write PMT_CTL: %d\n", ret); + return ret; + } + + timeout = 0; + do { + usleep_range(10000, 20000); + ret = smsc75xx_read_reg(dev, PMT_CTL, &buf); + if (ret < 0) { + netdev_warn(dev->net, "Failed to read PMT_CTL: %d\n", + ret); + return ret; + } + timeout++; + } while ((buf & PMT_CTL_PHY_RST) && (timeout < 100)); + + if (timeout >= 100) { + netdev_warn(dev->net, "timeout waiting for PHY Reset\n"); + return -EIO; + } + + return 0; +} + static int smsc75xx_reset(struct usbnet *dev) { struct smsc75xx_priv *pdata = (struct smsc75xx_priv *)(dev->data[0]); diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index bea0f313a7a8..2b2d01a3e511 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -1384,7 +1384,7 @@ static irqreturn_t lmc_interrupt (int irq, void *dev_instance) /*fold00*/ case 0x001: printk(KERN_WARNING "%s: Master Abort (naughty)\n", dev->name); break; - case 0x010: + case 0x002: printk(KERN_WARNING "%s: Target Abort (not so naughty)\n", dev->name); break; default: diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h index 37f53bd8fcb1..184b6810cde9 100644 --- a/drivers/net/wireless/ath/regd.h +++ b/drivers/net/wireless/ath/regd.h @@ -68,12 +68,14 @@ enum CountryCode { CTRY_AUSTRALIA = 36, CTRY_AUSTRIA = 40, CTRY_AZERBAIJAN = 31, + CTRY_BAHAMAS = 44, CTRY_BAHRAIN = 48, CTRY_BANGLADESH = 50, CTRY_BARBADOS = 52, CTRY_BELARUS = 112, CTRY_BELGIUM = 56, CTRY_BELIZE = 84, + CTRY_BERMUDA = 60, CTRY_BOLIVIA = 68, CTRY_BOSNIA_HERZ = 70, CTRY_BRAZIL = 76, @@ -159,6 +161,7 @@ enum CountryCode { CTRY_ROMANIA = 642, CTRY_RUSSIA = 643, CTRY_SAUDI_ARABIA = 682, + CTRY_SERBIA = 688, CTRY_SERBIA_MONTENEGRO = 891, CTRY_SINGAPORE = 702, CTRY_SLOVAKIA = 703, @@ -170,11 +173,13 @@ enum CountryCode { CTRY_SWITZERLAND = 756, CTRY_SYRIA = 760, CTRY_TAIWAN = 158, + CTRY_TANZANIA = 834, CTRY_THAILAND = 764, CTRY_TRINIDAD_Y_TOBAGO = 780, CTRY_TUNISIA = 788, CTRY_TURKEY = 792, CTRY_UAE = 784, + CTRY_UGANDA = 800, CTRY_UKRAINE = 804, CTRY_UNITED_KINGDOM = 826, CTRY_UNITED_STATES = 840, diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h index bdd2b4d61f2f..15bbd1e0d912 100644 --- a/drivers/net/wireless/ath/regd_common.h +++ b/drivers/net/wireless/ath/regd_common.h @@ -35,6 +35,7 @@ enum EnumRd { FRANCE_RES = 0x31, FCC3_FCCA = 0x3A, FCC3_WORLD = 0x3B, + FCC3_ETSIC = 0x3F, ETSI1_WORLD = 0x37, ETSI3_ETSIA = 0x32, @@ -44,6 +45,7 @@ enum EnumRd { ETSI4_ETSIC = 0x38, ETSI5_WORLD = 0x39, ETSI6_WORLD = 0x34, + ETSI8_WORLD = 0x3D, ETSI_RESERVED = 0x33, MKK1_MKKA = 0x40, @@ -59,6 +61,7 @@ enum EnumRd { MKK1_MKKA1 = 0x4A, MKK1_MKKA2 = 0x4B, MKK1_MKKC = 0x4C, + APL2_FCCA = 0x4D, APL3_FCCA = 0x50, APL1_WORLD = 0x52, @@ -67,6 +70,7 @@ enum EnumRd { APL1_ETSIC = 0x55, APL2_ETSIC = 0x56, APL5_WORLD = 0x58, + APL13_WORLD = 0x5A, APL6_WORLD = 0x5B, APL7_FCCA = 0x5C, APL8_WORLD = 0x5D, @@ -168,6 +172,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, {FCC3_FCCA, CTL_FCC, CTL_FCC}, {FCC3_WORLD, CTL_FCC, CTL_ETSI}, + {FCC3_ETSIC, CTL_FCC, CTL_ETSI}, {FCC4_FCCA, CTL_FCC, CTL_FCC}, {FCC5_FCCA, CTL_FCC, CTL_FCC}, {FCC6_FCCA, CTL_FCC, CTL_FCC}, @@ -179,6 +184,7 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {ETSI4_WORLD, CTL_ETSI, CTL_ETSI}, {ETSI5_WORLD, CTL_ETSI, CTL_ETSI}, {ETSI6_WORLD, CTL_ETSI, CTL_ETSI}, + {ETSI8_WORLD, CTL_ETSI, CTL_ETSI}, /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */ {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI}, @@ -188,9 +194,11 @@ static struct reg_dmn_pair_mapping regDomainPairs[] = { {FCC1_FCCA, CTL_FCC, CTL_FCC}, {APL1_WORLD, CTL_FCC, CTL_ETSI}, {APL2_WORLD, CTL_FCC, CTL_ETSI}, + {APL2_FCCA, CTL_FCC, CTL_FCC}, {APL3_WORLD, CTL_FCC, CTL_ETSI}, {APL4_WORLD, CTL_FCC, CTL_ETSI}, {APL5_WORLD, CTL_FCC, CTL_ETSI}, + {APL13_WORLD, CTL_ETSI, CTL_ETSI}, {APL6_WORLD, CTL_ETSI, CTL_ETSI}, {APL8_WORLD, CTL_ETSI, CTL_ETSI}, {APL9_WORLD, CTL_ETSI, CTL_ETSI}, @@ -298,6 +306,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, + {CTRY_BAHAMAS, FCC3_WORLD, "BS"}, {CTRY_BAHRAIN, APL6_WORLD, "BH"}, {CTRY_BANGLADESH, NULL1_WORLD, "BD"}, {CTRY_BARBADOS, FCC2_WORLD, "BB"}, @@ -305,6 +314,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, {CTRY_BELIZE, APL1_ETSIC, "BZ"}, + {CTRY_BERMUDA, FCC3_FCCA, "BM"}, {CTRY_BOLIVIA, APL1_ETSIC, "BO"}, {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"}, {CTRY_BRAZIL, FCC3_WORLD, "BR"}, @@ -444,6 +454,7 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_ROMANIA, NULL1_WORLD, "RO"}, {CTRY_RUSSIA, NULL1_WORLD, "RU"}, {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, + {CTRY_SERBIA, ETSI1_WORLD, "RS"}, {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"}, {CTRY_SINGAPORE, APL6_WORLD, "SG"}, {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"}, @@ -455,10 +466,12 @@ static struct country_code_to_enum_rd allCountries[] = { {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"}, {CTRY_SYRIA, NULL1_WORLD, "SY"}, {CTRY_TAIWAN, APL3_FCCA, "TW"}, + {CTRY_TANZANIA, APL1_WORLD, "TZ"}, {CTRY_THAILAND, FCC3_WORLD, "TH"}, {CTRY_TRINIDAD_Y_TOBAGO, FCC3_WORLD, "TT"}, {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, {CTRY_TURKEY, ETSI3_WORLD, "TR"}, + {CTRY_UGANDA, FCC3_WORLD, "UG"}, {CTRY_UKRAINE, NULL1_WORLD, "UA"}, {CTRY_UAE, NULL1_WORLD, "AE"}, {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c index d20d4e6f391a..f6d35d9a06eb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c @@ -4201,6 +4201,13 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus) brcmf_dbg(TRACE, "Enter\n"); if (bus) { + /* Stop watchdog task */ + if (bus->watchdog_tsk) { + send_sig(SIGTERM, bus->watchdog_tsk, 1); + kthread_stop(bus->watchdog_tsk); + bus->watchdog_tsk = NULL; + } + /* De-register interrupt handler */ brcmf_sdiod_intr_unregister(bus->sdiodev); diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c index c99addac8e57..f92a8c08e9dd 100644 --- a/drivers/net/wireless/cnss/cnss_pci.c +++ b/drivers/net/wireless/cnss/cnss_pci.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2761,10 +2761,14 @@ static int cnss_powerup(const struct subsys_desc *subsys) cnss_configure_wlan_en_gpio(WLAN_EN_LOW); cnss_wlan_vreg_set(vreg_info, VREG_OFF); if (penv->pdev) { - pr_err("%d: Unregistering pci device\n", __LINE__); - pci_unregister_driver(&cnss_wlan_pci_driver); - penv->pdev = NULL; - penv->pci_register_again = true; + if (wdrv && wdrv->update_status) + wdrv->update_status(penv->pdev, CNSS_SSR_FAIL); + if (!penv->recovery_in_progress) { + pr_err("%d: Unregistering pci device\n", __LINE__); + pci_unregister_driver(&cnss_wlan_pci_driver); + penv->pdev = NULL; + penv->pci_register_again = true; + } } err_wlan_vreg_on: diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 4371e12b36f3..3f239f1ad203 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c @@ -556,6 +556,9 @@ static void mwifiex_usb_disconnect(struct usb_interface *intf) MWIFIEX_FUNC_SHUTDOWN); } + if (adapter->workqueue) + flush_workqueue(adapter->workqueue); + mwifiex_usb_free(card); dev_dbg(adapter->dev, "%s: removing card\n", __func__); diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c index 8428858204a6..fc895b466ebb 100644 --- a/drivers/net/wireless/rsi/rsi_91x_sdio.c +++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c @@ -155,7 +155,6 @@ static void rsi_reset_card(struct sdio_func *pfunction) int err; struct mmc_card *card = pfunction->card; struct mmc_host *host = card->host; - s32 bit = (fls(host->ocr_avail) - 1); u8 cmd52_resp; u32 clock, resp, i; u16 rca; @@ -175,7 +174,6 @@ static void rsi_reset_card(struct sdio_func *pfunction) msleep(20); /* Initialize the SDIO card */ - host->ios.vdd = bit; host->ios.chip_select = MMC_CS_DONTCARE; host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN; host->ios.power_mode = MMC_POWER_UP; diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index c172da56b550..e4a8280cea83 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -388,6 +388,11 @@ static int wl1271_suspend(struct device *dev) mmc_pm_flag_t sdio_flags; int ret = 0; + if (!wl) { + dev_err(dev, "no wilink module was probed\n"); + goto out; + } + dev_dbg(dev, "wl1271 suspend. wow_enabled: %d\n", wl->wow_enabled); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 9967733a397e..b780c059cc03 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -85,6 +85,7 @@ struct netfront_cb { /* IRQ name is queue name with "-tx" or "-rx" appended */ #define IRQ_NAME_SIZE (QUEUE_NAME_SIZE + 3) +static DECLARE_WAIT_QUEUE_HEAD(module_load_q); static DECLARE_WAIT_QUEUE_HEAD(module_unload_q); struct netfront_stats { @@ -902,7 +903,6 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue, struct sk_buff *skb, struct sk_buff_head *list) { - struct skb_shared_info *shinfo = skb_shinfo(skb); RING_IDX cons = queue->rx.rsp_cons; struct sk_buff *nskb; @@ -911,15 +911,16 @@ static RING_IDX xennet_fill_frags(struct netfront_queue *queue, RING_GET_RESPONSE(&queue->rx, ++cons); skb_frag_t *nfrag = &skb_shinfo(nskb)->frags[0]; - if (shinfo->nr_frags == MAX_SKB_FRAGS) { + if (skb_shinfo(skb)->nr_frags == MAX_SKB_FRAGS) { unsigned int pull_to = NETFRONT_SKB_CB(skb)->pull_to; BUG_ON(pull_to <= skb_headlen(skb)); __pskb_pull_tail(skb, pull_to - skb_headlen(skb)); } - BUG_ON(shinfo->nr_frags >= MAX_SKB_FRAGS); + BUG_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS); - skb_add_rx_frag(skb, shinfo->nr_frags, skb_frag_page(nfrag), + skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, + skb_frag_page(nfrag), rx->offset, rx->status, PAGE_SIZE); skb_shinfo(nskb)->nr_frags = 0; @@ -1359,6 +1360,11 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) netif_carrier_off(netdev); xenbus_switch_state(dev, XenbusStateInitialising); + wait_event(module_load_q, + xenbus_read_driver_state(dev->otherend) != + XenbusStateClosed && + xenbus_read_driver_state(dev->otherend) != + XenbusStateUnknown); return netdev; exit: diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index 56d8486dc167..cdc109ec5b82 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -457,8 +457,17 @@ int __pci_hp_register(struct hotplug_slot *slot, struct pci_bus *bus, list_add(&slot->slot_list, &pci_hotplug_slot_list); result = fs_add_slot(pci_slot); + if (result) + goto err_list_del; + kobject_uevent(&pci_slot->kobj, KOBJ_ADD); dbg("Added slot %s to the list\n", name); + goto out; + +err_list_del: + list_del(&slot->slot_list); + pci_slot->hotplug = NULL; + pci_destroy_slot(pci_slot); out: mutex_unlock(&pci_hp_mutex); return result; diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index 318707870cb2..6b66f9950b57 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -199,13 +199,16 @@ static ssize_t enable_store(struct device *dev, struct device_attribute *attr, if (!capable(CAP_SYS_ADMIN)) return -EPERM; - if (!val) { - if (pci_is_enabled(pdev)) - pci_disable_device(pdev); - else - result = -EIO; - } else + device_lock(dev); + if (dev->driver) + result = -EBUSY; + else if (val) result = pci_enable_device(pdev); + else if (pci_is_enabled(pdev)) + pci_disable_device(pdev); + else + result = -EIO; + device_unlock(dev); return result < 0 ? result : count; } diff --git a/drivers/pinctrl/freescale/pinctrl-imx1-core.c b/drivers/pinctrl/freescale/pinctrl-imx1-core.c index 5ac59fbb2440..d6115d3835ee 100644 --- a/drivers/pinctrl/freescale/pinctrl-imx1-core.c +++ b/drivers/pinctrl/freescale/pinctrl-imx1-core.c @@ -435,7 +435,7 @@ static void imx1_pinconf_group_dbg_show(struct pinctrl_dev *pctldev, const char *name; int i, ret; - if (group > info->ngroups) + if (group >= info->ngroups) return; seq_puts(s, "\n"); diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig index 0774fe4d29aa..198408ad3ea9 100644 --- a/drivers/platform/msm/Kconfig +++ b/drivers/platform/msm/Kconfig @@ -194,16 +194,6 @@ config IPA_UT The user interface to run and control the tests is debugfs file system. -config SSM - tristate "QTI Secure Service Module" - depends on QSEECOM - depends on MSM_SMD - help - Provides an interface for OEM driver to communicate with Trustzone - and modem for key exchange and mode change. - This driver uses Secure Channel Manager interface for trustzone - communication and communicates with modem over SMD channel. - config MSM_MHI tristate "Modem Host Interface Driver" help diff --git a/drivers/platform/msm/Makefile b/drivers/platform/msm/Makefile index 1ecb76f6a76b..5507a12a7ed3 100644 --- a/drivers/platform/msm/Makefile +++ b/drivers/platform/msm/Makefile @@ -25,4 +25,3 @@ obj-$(CONFIG_QPNP_VIBRATOR) += qpnp-vibrator.o obj-$(CONFIG_MSM_AVTIMER) += avtimer.o obj-$(CONFIG_MSM_11AD) += msm_11ad/ obj-$(CONFIG_MSM_MHI_DEV) += mhi_dev/ -obj-$(CONFIG_SSM) += ssm.o \ No newline at end of file diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c index 60a610199836..43d99b9c30d9 100644 --- a/drivers/platform/msm/gsi/gsi.c +++ b/drivers/platform/msm/gsi/gsi.c @@ -1099,13 +1099,14 @@ int gsi_alloc_evt_ring(struct gsi_evt_ring_props *props, unsigned long dev_hdl, uint32_t val; struct gsi_evt_ctx *ctx; int res; - int ee = gsi_ctx->per.ee; + int ee; unsigned long flags; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } + ee = gsi_ctx->per.ee; if (!props || !evt_ring_hdl || dev_hdl != (uintptr_t)gsi_ctx) { GSIERR("bad params props=%p dev_hdl=0x%lx evt_ring_hdl=%p\n", @@ -1637,7 +1638,7 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, struct gsi_chan_ctx *ctx; uint32_t val; int res; - int ee = gsi_ctx->per.ee; + int ee; enum gsi_ch_cmd_opcode op = GSI_CH_ALLOCATE; uint8_t erindex; void **user_data; @@ -1646,6 +1647,7 @@ int gsi_alloc_channel(struct gsi_chan_props *props, unsigned long dev_hdl, pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } + ee = gsi_ctx->per.ee; if (!props || !chan_hdl || dev_hdl != (uintptr_t)gsi_ctx) { GSIERR("bad params props=%p dev_hdl=0x%lx chan_hdl=%p\n", @@ -2287,12 +2289,13 @@ int gsi_query_channel_info(unsigned long chan_hdl, unsigned long flags; uint64_t rp; uint64_t wp; - int ee = gsi_ctx->per.ee; + int ee; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } + ee = gsi_ctx->per.ee; if (chan_hdl >= gsi_ctx->max_ch || !info) { GSIERR("bad params chan_hdl=%lu info=%p\n", chan_hdl, info); @@ -2357,12 +2360,13 @@ int gsi_is_channel_empty(unsigned long chan_hdl, bool *is_empty) unsigned long flags; uint64_t rp; uint64_t wp; - int ee = gsi_ctx->per.ee; + int ee; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } + ee = gsi_ctx->per.ee; if (chan_hdl >= gsi_ctx->max_ch || !is_empty) { GSIERR("bad params chan_hdl=%lu is_empty=%p\n", @@ -2546,13 +2550,14 @@ int gsi_poll_channel(unsigned long chan_hdl, { struct gsi_chan_ctx *ctx; uint64_t rp; - int ee = gsi_ctx->per.ee; + int ee; unsigned long flags; if (!gsi_ctx) { pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__); return -GSI_STATUS_NODEV; } + ee = gsi_ctx->per.ee; if (chan_hdl >= gsi_ctx->max_ch || !notify) { GSIERR("bad params chan_hdl=%lu notify=%p\n", chan_hdl, notify); diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c index 158be880b953..2143adbdac12 100644 --- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c +++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c @@ -2119,6 +2119,15 @@ int ipa_mhi_suspend(bool force) IPA_MHI_ERR("ipa_mhi_set_state failed %d\n", res); return res; } + + res = ipa_mhi_suspend_dl(force); + if (res) { + IPA_MHI_ERR("ipa_mhi_suspend_dl failed %d\n", res); + goto fail_suspend_dl_channel; + } + + usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN, IPA_MHI_SUSPEND_SLEEP_MAX); + res = ipa_mhi_suspend_ul(force, &empty, &force_clear); if (res) { IPA_MHI_ERR("ipa_mhi_suspend_ul failed %d\n", res); @@ -2147,12 +2156,6 @@ int ipa_mhi_suspend(bool force) usleep_range(IPA_MHI_SUSPEND_SLEEP_MIN, IPA_MHI_SUSPEND_SLEEP_MAX); - res = ipa_mhi_suspend_dl(force); - if (res) { - IPA_MHI_ERR("ipa_mhi_suspend_dl failed %d\n", res); - goto fail_suspend_dl_channel; - } - if (!empty) ipa_set_tag_process_before_gating(false); @@ -2166,14 +2169,12 @@ int ipa_mhi_suspend(bool force) IPA_MHI_FUNC_EXIT(); return 0; -fail_suspend_dl_channel: fail_release_cons: ipa_mhi_request_prod(); fail_release_prod: IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); fail_suspend_ul_channel: ipa_mhi_resume_channels(true, ipa_mhi_client_ctx->ul_channels); - ipa_mhi_set_state(IPA_MHI_STATE_STARTED); if (force_clear) { if ( ipa_mhi_disable_force_clear(ipa_mhi_client_ctx->qmi_req_id)) { @@ -2183,6 +2184,9 @@ int ipa_mhi_suspend(bool force) IPA_MHI_DBG("force clear datapath disabled\n"); ipa_mhi_client_ctx->qmi_req_id++; } +fail_suspend_dl_channel: + ipa_mhi_resume_channels(true, ipa_mhi_client_ctx->dl_channels); + ipa_mhi_set_state(IPA_MHI_STATE_STARTED); return res; } diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c index 02db3e5bf87e..8ac4137a8446 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -2584,6 +2584,9 @@ void ipa3_q6_pre_shutdown_cleanup(void) ipa3_q6_pipe_delay(true); ipa3_q6_avoid_holb(); + if (ipa3_ctx->ipa_config_is_mhi) + ipa3_set_reset_client_cons_pipe_sus_holb(true, + IPA_CLIENT_MHI_CONS); if (ipa3_q6_clean_q6_tables()) { IPAERR("Failed to clean Q6 tables\n"); BUG(); @@ -2596,8 +2599,11 @@ void ipa3_q6_pre_shutdown_cleanup(void) * on pipe reset procedure */ ipa3_q6_pipe_delay(false); - - ipa3_set_usb_prod_pipe_delay(); + ipa3_set_reset_client_prod_pipe_delay(true, + IPA_CLIENT_USB_PROD); + if (ipa3_ctx->ipa_config_is_mhi) + ipa3_set_reset_client_prod_pipe_delay(true, + IPA_CLIENT_MHI_PROD); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); IPADBG_LOW("Exit with success\n"); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 2478baff7ccd..9a6cda454435 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -1848,27 +1848,32 @@ static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id, } /* - * Set USB PROD pipe delay for MBIM/RMNET config + * Set reset eo_deay for CLEINT PROD pipe * Clocks, should be voted before calling this API * locks should be taken before calling this API */ -void ipa3_set_usb_prod_pipe_delay(void) +int ipa3_set_reset_client_prod_pipe_delay(bool set_reset, + enum ipa_client_type client) { - int result; + int result = 0; int pipe_idx; struct ipa3_ep_context *ep; struct ipa_ep_cfg_ctrl ep_ctrl; memset(&ep_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl)); - ep_ctrl.ipa_ep_delay = true; + ep_ctrl.ipa_ep_delay = set_reset; + if (IPA_CLIENT_IS_CONS(client)) { + IPAERR("client (%d) not PROD\n", client); + return -EINVAL; + } - pipe_idx = ipa3_get_ep_mapping(IPA_CLIENT_USB_PROD); + pipe_idx = ipa3_get_ep_mapping(client); if (pipe_idx == IPA_EP_NOT_ALLOCATED) { - IPAERR("client (%d) not valid\n", IPA_CLIENT_USB_PROD); - return; + IPAERR("client (%d) not valid\n", client); + return -EINVAL; } ep = &ipa3_ctx->ep[pipe_idx]; @@ -1885,6 +1890,59 @@ void ipa3_set_usb_prod_pipe_delay(void) IPADBG("client (ep: %d) success\n", pipe_idx); } client_lock_unlock_cb(pipe_idx, false); + return result; +} + +int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset, + enum ipa_client_type client) +{ + int pipe_idx; + struct ipa3_ep_context *ep; + struct ipa_ep_cfg_ctrl ep_suspend; + struct ipa_ep_cfg_holb ep_holb; + + memset(&ep_suspend, 0, sizeof(ep_suspend)); + memset(&ep_holb, 0, sizeof(ep_holb)); + + ep_suspend.ipa_ep_suspend = set_reset; + ep_holb.tmr_val = 0; + ep_holb.en = set_reset; + + if (IPA_CLIENT_IS_PROD(client)) { + IPAERR("client (%d) not CONS\n", client); + return -EINVAL; + } + + pipe_idx = ipa3_get_ep_mapping(client); + + if (pipe_idx == IPA_EP_NOT_ALLOCATED) { + IPAERR("client (%d) not valid\n", client); + return -EINVAL; + } + + ep = &ipa3_ctx->ep[pipe_idx]; + /* Setting sus/holb on MHI_CONS with skip_ep_cfg */ + client_lock_unlock_cb(pipe_idx, true); + if (ep->valid && ep->skip_ep_cfg) { + if (ipa3_ctx->ipa_hw_type < IPA_HW_v4_0) + ipahal_write_reg_n_fields( + IPA_ENDP_INIT_CTRL_n, + pipe_idx, &ep_suspend); + /* + * ipa3_cfg_ep_holb is not used here because we are + * setting HOLB on Q6 pipes, and from APPS perspective + * they are not valid, therefore, the above function + * will fail. + */ + ipahal_write_reg_n_fields( + IPA_ENDP_INIT_HOL_BLOCK_TIMER_n, + pipe_idx, &ep_holb); + ipahal_write_reg_n_fields( + IPA_ENDP_INIT_HOL_BLOCK_EN_n, + pipe_idx, &ep_holb); + } + client_lock_unlock_cb(pipe_idx, false); + return 0; } void ipa3_xdci_ep_delay_rm(u32 clnt_hdl) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index b53a58cf9f70..61e8d8a3dea1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1530,7 +1530,10 @@ int ipa3_xdci_disconnect(u32 clnt_hdl, bool should_force_clear, u32 qmi_req_id); void ipa3_xdci_ep_delay_rm(u32 clnt_hdl); void ipa3_register_lock_unlock_callback(int (*client_cb)(bool), u32 ipa_ep_idx); void ipa3_deregister_lock_unlock_callback(u32 ipa_ep_idx); -void ipa3_set_usb_prod_pipe_delay(void); +int ipa3_set_reset_client_prod_pipe_delay(bool set_reset, + enum ipa_client_type client); +int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset, + enum ipa_client_type client); int ipa3_xdci_suspend(u32 ul_clnt_hdl, u32 dl_clnt_hdl, bool should_force_clear, u32 qmi_req_id, bool is_dpl); diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c index c56a60f7a7fc..45340fcdd4d1 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c @@ -198,6 +198,7 @@ static int ipa_mhi_start_gsi_channel(enum ipa_client_type client, union __packed gsi_channel_scratch ch_scratch; struct ipa3_ep_context *ep; const struct ipa_gsi_ep_config *ep_cfg; + struct ipa_ep_cfg_ctrl ep_cfg_ctrl; IPA_MHI_FUNC_ENTRY(); @@ -323,6 +324,20 @@ static int ipa_mhi_start_gsi_channel(enum ipa_client_type client, *params->mhi = ch_scratch.mhi; + if (IPA_CLIENT_IS_PROD(ep->client) && ep->skip_ep_cfg) { + memset(&ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl)); + ep_cfg_ctrl.ipa_ep_delay = true; + ep->ep_delay_set = true; + res = ipa3_cfg_ep_ctrl(ipa_ep_idx, &ep_cfg_ctrl); + if (res) + IPA_MHI_ERR("client (ep: %d) failed result=%d\n", + ipa_ep_idx, res); + else + IPA_MHI_DBG("client (ep: %d) success\n", ipa_ep_idx); + } else { + ep->ep_delay_set = false; + } + IPA_MHI_DBG("Starting channel\n"); res = gsi_start_channel(ep->gsi_chan_hdl); if (res) { @@ -496,6 +511,7 @@ int ipa3_disconnect_mhi_pipe(u32 clnt_hdl) { struct ipa3_ep_context *ep; int res; + struct ipa_ep_cfg_ctrl ep_cfg_ctrl; IPA_MHI_FUNC_ENTRY(); @@ -510,6 +526,23 @@ int ipa3_disconnect_mhi_pipe(u32 clnt_hdl) } ep = &ipa3_ctx->ep[clnt_hdl]; + IPA_MHI_ERR("Debug --> Remove ep_delay start"); + if (ep->ep_delay_set == true) { + memset(&ep_cfg_ctrl, 0 , sizeof(struct ipa_ep_cfg_ctrl)); + ep_cfg_ctrl.ipa_ep_delay = false; + res = ipa3_cfg_ep_ctrl(clnt_hdl, + &ep_cfg_ctrl); + if (res) { + IPAERR + ("client(ep:%d) failed to remove delay res=%d\n", + clnt_hdl, res); + } else { + IPADBG("client (ep: %d) delay removed\n", + clnt_hdl); + ep->ep_delay_set = false; + } + } + IPA_MHI_ERR("Debug --> Remov ep_delay end"); if (ipa3_ctx->transport_prototype == IPA_TRANSPORT_TYPE_GSI) { res = gsi_dealloc_channel(ep->gsi_chan_hdl); diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c index 62a9cb0be81a..cc8e00fa9959 100644 --- a/drivers/platform/msm/mhi_dev/mhi.c +++ b/drivers/platform/msm/mhi_dev/mhi.c @@ -1406,16 +1406,20 @@ static void mhi_dev_transfer_completion_cb(void *mreq) union mhi_dev_ring_element_type *el; int rc = 0; struct mhi_req *req = (struct mhi_req *)mreq; - struct mhi_req *local_req = NULL; union mhi_dev_ring_element_type *compl_ev = NULL; struct mhi_dev *mhi = NULL; unsigned long flags; + size_t transfer_len; + u32 snd_cmpl; + uint32_t rd_offset; client = req->client; ch = client->channel; mhi = ch->ring->mhi_dev; el = req->el; - local_req = req; + transfer_len = req->len; + snd_cmpl = req->snd_cmpl; + rd_offset = req->rd_offset; ch->curr_ereq->context = ch; dma_unmap_single(&mhi_ctx->pdev->dev, req->dma, @@ -1429,14 +1433,13 @@ static void mhi_dev_transfer_completion_cb(void *mreq) compl_ev->evt_tr_comp.chid = ch->ch_id; compl_ev->evt_tr_comp.type = MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT; - compl_ev->evt_tr_comp.len = el->tre.len; + compl_ev->evt_tr_comp.len = transfer_len; compl_ev->evt_tr_comp.code = MHI_CMD_COMPL_CODE_EOT; compl_ev->evt_tr_comp.ptr = ch->ring->ring_ctx->generic.rbase + - local_req->rd_offset * TR_RING_ELEMENT_SZ; + rd_offset * TR_RING_ELEMENT_SZ; ch->curr_ereq->num_events++; - if (ch->curr_ereq->num_events >= MAX_TR_EVENTS || - local_req->snd_cmpl){ + if (ch->curr_ereq->num_events >= MAX_TR_EVENTS || snd_cmpl) { mhi_log(MHI_MSG_VERBOSE, "num of tr events %d for ch %d\n", ch->curr_ereq->num_events, ch->ch_id); @@ -1480,6 +1483,7 @@ static void mhi_dev_scheduler(struct work_struct *work) enum mhi_dev_state state; enum mhi_dev_event event = 0; bool mhi_reset = false; + uint32_t bhi_imgtxdb = 0; mutex_lock(&mhi_ctx->mhi_lock); /* Check for interrupts */ @@ -1517,6 +1521,10 @@ static void mhi_dev_scheduler(struct work_struct *work) pr_err("error sending SM event\n"); goto fail; } + + rc = mhi_dev_mmio_read(mhi, BHI_IMGTXDB, &bhi_imgtxdb); + mhi_log(MHI_MSG_VERBOSE, + "BHI_IMGTXDB = 0x%x\n", bhi_imgtxdb); } if (int_value & MHI_MMIO_CTRL_CRDB_STATUS_MSK) { @@ -1876,6 +1884,7 @@ int mhi_dev_open_channel(uint32_t chan_id, (struct mhi_dev_client_cb_reason *cb)) { int rc = 0; + int i = 0; struct mhi_dev_channel *ch; struct platform_device *pdev; @@ -1899,6 +1908,38 @@ int mhi_dev_open_channel(uint32_t chan_id, goto exit; } + /* Pre allocate event requests */ + ch->ereqs = kcalloc(MHI_MAX_EVT_REQ, sizeof(*ch->ereqs), GFP_KERNEL); + if (!ch->ereqs) { + rc = -ENOMEM; + goto free_client; + } + /* pre allocate buffers to queue transfer completion events */ + ch->tr_events = kcalloc(MHI_MAX_EVT_REQ, + MAX_TR_EVENTS * sizeof(*ch->tr_events), + GFP_KERNEL); + if (!ch->tr_events) { + rc = -ENOMEM; + goto free_ereqs; + } + + /* + * Organize the above allocated event request block and + * completion event block into linked lists. Each event + * request includes a pointer to a block of MAX_TR_EVENTS + * completion events. + */ + INIT_LIST_HEAD(&mhi_ctx->ch[chan_id].event_req_buffers); + for (i = 0; i < MHI_MAX_EVT_REQ; ++i) { + ch->ereqs[i].tr_events = ch->tr_events + i * MAX_TR_EVENTS; + list_add_tail(&ch->ereqs[i].list, + &mhi_ctx->ch[chan_id].event_req_buffers); + } + mhi_ctx->ch[chan_id].curr_ereq = + container_of(mhi_ctx->ch[chan_id].event_req_buffers.next, + struct event_req, list); + list_del_init(&mhi_ctx->ch[chan_id].curr_ereq->list); + ch->active_client = (*handle_client); (*handle_client)->channel = ch; (*handle_client)->event_trigger = mhi_dev_client_cb_reason; @@ -1911,6 +1952,13 @@ int mhi_dev_open_channel(uint32_t chan_id, else if (ch->state == MHI_DEV_CH_STOPPED) ch->state = MHI_DEV_CH_PENDING_START; + goto exit; + +free_ereqs: + kfree(ch->ereqs); + ch->ereqs = NULL; +free_client: + kfree(*handle_client); exit: mutex_unlock(&ch->ch_lock); return rc; @@ -1944,14 +1992,12 @@ int mhi_dev_close_channel(struct mhi_dev_client *handle) mhi_log(MHI_MSG_ERROR, "Trying to close an active channel (%d)\n", ch->ch_id); - mutex_unlock(&ch->ch_lock); rc = -EAGAIN; goto exit; } else if (ch->tre_loc) { mhi_log(MHI_MSG_ERROR, "Trying to close channel (%d) when a TRE is active", ch->ch_id); - mutex_unlock(&ch->ch_lock); rc = -EAGAIN; goto exit; } @@ -1959,6 +2005,10 @@ int mhi_dev_close_channel(struct mhi_dev_client *handle) ch->state = MHI_DEV_CH_CLOSED; ch->active_client = NULL; + kfree(ch->ereqs); + kfree(ch->tr_events); + ch->ereqs = NULL; + ch->tr_events = NULL; kfree(handle); exit: mutex_unlock(&ch->ch_lock); @@ -2666,40 +2716,8 @@ static int mhi_init(struct mhi_dev *mhi) if (!mhi->ch) return -ENOMEM; - - for (i = 0; i < mhi->cfg.channels; i++) { + for (i = 0; i < mhi->cfg.channels; i++) mutex_init(&mhi->ch[i].ch_lock); - if (i == MHI_CLIENT_IP_SW_4_OUT || i == MHI_CLIENT_IP_SW_4_IN) { - int nreq = 0; - - INIT_LIST_HEAD(&mhi->ch[i].event_req_buffers); - while (nreq < MHI_MAX_EVT_REQ) { - struct event_req *ereq; - /* Pre allocate event requests */ - ereq = kzalloc(sizeof(struct event_req), - GFP_KERNEL); - if (!ereq) - return -ENOMEM; - - /* pre allocate buffers to queue - * transfer completion events - */ - ereq->tr_events = kzalloc(RING_ELEMENT_TYPE_SZ* - MAX_TR_EVENTS, GFP_KERNEL); - if (!ereq->tr_events) { - kfree(ereq); - return -ENOMEM; - } - list_add_tail(&ereq->list, - &mhi->ch[i].event_req_buffers); - nreq++; - } - mhi->ch[i].curr_ereq = - container_of(mhi->ch[i].event_req_buffers.next, - struct event_req, list); - list_del_init(&mhi->ch[i].curr_ereq->list); - } - } spin_lock_init(&mhi->lock); mhi->mmio_backup = devm_kzalloc(&pdev->dev, diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h index d764e1c0eb67..147a435897a9 100644 --- a/drivers/platform/msm/mhi_dev/mhi.h +++ b/drivers/platform/msm/mhi_dev/mhi.h @@ -440,7 +440,13 @@ struct mhi_dev_channel { struct mutex ch_lock; /* client which the current inbound/outbound message is for */ struct mhi_dev_client *active_client; - + /* + * Pointer to event request structs used to temporarily store + * completion events and meta data before sending them to host + */ + struct event_req *ereqs; + /* Pointer to completion event buffers */ + union mhi_dev_ring_element_type *tr_events; struct list_head event_req_buffers; struct event_req *curr_ereq; diff --git a/drivers/platform/msm/mhi_dev/mhi_hwio.h b/drivers/platform/msm/mhi_dev/mhi_hwio.h index 40e1a91a980a..db46f2795c93 100644 --- a/drivers/platform/msm/mhi_dev/mhi_hwio.h +++ b/drivers/platform/msm/mhi_dev/mhi_hwio.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved. +/* Copyright (c) 2015, 2017-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -192,4 +192,6 @@ #define BHI_EXECENV_MASK 0xFFFFFFFF #define BHI_EXECENV_SHIFT 0 +#define BHI_IMGTXDB (0x218) + #endif diff --git a/drivers/platform/msm/mhi_dev/mhi_ring.c b/drivers/platform/msm/mhi_dev/mhi_ring.c index 785d6d00568d..91496a46f5c8 100644 --- a/drivers/platform/msm/mhi_dev/mhi_ring.c +++ b/drivers/platform/msm/mhi_dev/mhi_ring.c @@ -264,11 +264,12 @@ EXPORT_SYMBOL(mhi_dev_process_ring); int mhi_dev_add_element(struct mhi_dev_ring *ring, union mhi_dev_ring_element_type *element, - struct event_req *ereq, int evt_offset) + struct event_req *ereq, int size) { uint32_t old_offset = 0; struct mhi_addr host_addr; - uint32_t num_elem = 0; + uint32_t num_elem = 1; + uint32_t num_free_elem; if (!ring || !element) { pr_err("%s: Invalid context\n", __func__); @@ -277,16 +278,24 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, mhi_dev_update_wr_offset(ring); - if ((ring->rd_offset + 1) % ring->ring_size == ring->wr_offset) { - mhi_log(MHI_MSG_VERBOSE, "ring full to insert element\n"); + if (ereq) + num_elem = size / (sizeof(union mhi_dev_ring_element_type)); + + if (ring->rd_offset < ring->wr_offset) + num_free_elem = ring->wr_offset - ring->rd_offset - 1; + else + num_free_elem = ring->ring_size - ring->rd_offset + + ring->wr_offset - 1; + + if (num_free_elem < num_elem) { + mhi_log(MHI_MSG_ERROR, "No space to add %d elem in ring (%d)\n", + num_elem, ring->id); return -EINVAL; } old_offset = ring->rd_offset; - if (evt_offset) { - num_elem = evt_offset / - (sizeof(union mhi_dev_ring_element_type)); + if (ereq) { ring->rd_offset += num_elem; if (ring->rd_offset >= ring->ring_size) ring->rd_offset -= ring->ring_size; @@ -308,23 +317,47 @@ int mhi_dev_add_element(struct mhi_dev_ring *ring, host_addr.device_va = ring->ring_shadow.device_va + sizeof(union mhi_dev_ring_element_type) * old_offset; - host_addr.virt_addr = element; - - if (evt_offset) - host_addr.size = evt_offset; - else + if (!ereq) { + /* We're adding only a single ring element */ + host_addr.virt_addr = element; host_addr.size = sizeof(union mhi_dev_ring_element_type); - mhi_log(MHI_MSG_VERBOSE, "adding element to ring (%d)\n", ring->id); - mhi_log(MHI_MSG_VERBOSE, "rd_ofset %d\n", ring->rd_offset); - mhi_log(MHI_MSG_VERBOSE, "type %d\n", element->generic.type); + mhi_log(MHI_MSG_VERBOSE, "adding element to ring (%d)\n", + ring->id); + mhi_log(MHI_MSG_VERBOSE, "rd_ofset %d\n", ring->rd_offset); + mhi_log(MHI_MSG_VERBOSE, "type %d\n", element->generic.type); - if (ereq) mhi_dev_write_to_host(ring->mhi_dev, &host_addr, - ereq, MHI_DEV_DMA_ASYNC); - else + NULL, MHI_DEV_DMA_SYNC); + return 0; + } + + /* Adding multiple ring elements */ + if (ring->rd_offset == 0 || (ring->rd_offset > old_offset)) { + /* No wrap-around case */ + host_addr.virt_addr = element; + host_addr.size = size; + mhi_dev_write_to_host(ring->mhi_dev, &host_addr, + ereq, MHI_DEV_DMA_ASYNC); + } else { + /* Wrap-around case - first chunk uses dma sync */ + host_addr.virt_addr = element; + host_addr.size = (ring->ring_size - old_offset) * + sizeof(union mhi_dev_ring_element_type); + mhi_dev_write_to_host(ring->mhi_dev, &host_addr, + NULL, MHI_DEV_DMA_SYNC); + + /* Copy remaining elements */ + if (ring->mhi_dev->use_ipa) + host_addr.host_pa = ring->ring_shadow.host_pa; + else + host_addr.device_va = ring->ring_shadow.device_va; + host_addr.virt_addr = element + (ring->ring_size - old_offset); + host_addr.size = ring->rd_offset * + sizeof(union mhi_dev_ring_element_type); mhi_dev_write_to_host(ring->mhi_dev, &host_addr, - NULL, MHI_DEV_DMA_SYNC); + ereq, MHI_DEV_DMA_ASYNC); + } return 0; } EXPORT_SYMBOL(mhi_dev_add_element); diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c index 4d9aa2e5e83f..41360fbbafd6 100644 --- a/drivers/platform/msm/mhi_dev/mhi_uci.c +++ b/drivers/platform/msm/mhi_dev/mhi_uci.c @@ -35,9 +35,13 @@ #define MHI_SOFTWARE_CLIENT_LIMIT (MHI_MAX_SOFTWARE_CHANNELS/2) #define MHI_UCI_IPC_LOG_PAGES (100) -#define MAX_NR_TRBS_PER_CHAN 1 +/* Max number of MHI write request structures (used in async writes) */ +#define MAX_UCI_WR_REQ 10 +#define MAX_NR_TRBS_PER_CHAN 9 #define MHI_QTI_IFACE_ID 4 -#define DEVICE_NAME "mhi" +#define DEVICE_NAME "mhi" + +#define MHI_UCI_ASYNC_READ_TIMEOUT msecs_to_jiffies(100) enum uci_dbg_level { UCI_DBG_VERBOSE = 0x0, @@ -70,7 +74,131 @@ struct chan_attr { u32 nr_trbs; /* direction of the channel, see enum mhi_chan_dir */ enum mhi_chan_dir dir; - u32 uci_ownership; + /* need to register mhi channel state change callback */ + bool register_cb; +}; + +/* UCI channel attributes table */ +static const struct chan_attr uci_chan_attr_table[] = { + { + MHI_CLIENT_LOOPBACK_OUT, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_OUT, + false + }, + { + MHI_CLIENT_LOOPBACK_IN, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_IN, + false + }, + { + MHI_CLIENT_SAHARA_OUT, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_OUT, + false + }, + { + MHI_CLIENT_SAHARA_IN, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_IN, + false + }, + { + MHI_CLIENT_EFS_OUT, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_OUT, + false + }, + { + MHI_CLIENT_EFS_IN, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_IN, + false + }, + { + MHI_CLIENT_MBIM_OUT, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_OUT, + false + }, + { + MHI_CLIENT_MBIM_IN, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_IN, + false + }, + { + MHI_CLIENT_QMI_OUT, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_OUT, + false + }, + { + MHI_CLIENT_QMI_IN, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_IN, + false + }, + { + MHI_CLIENT_IP_CTRL_0_OUT, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_OUT, + false + }, + { + MHI_CLIENT_IP_CTRL_0_IN, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_IN, + false + }, + { + MHI_CLIENT_IP_CTRL_1_OUT, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_OUT, + false + }, + { + MHI_CLIENT_IP_CTRL_1_IN, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_IN, + false + }, + { + MHI_CLIENT_DUN_OUT, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_OUT, + false + }, + { + MHI_CLIENT_DUN_IN, + TRB_MAX_DATA_SIZE, + MAX_NR_TRBS_PER_CHAN, + MHI_DIR_IN, + false + }, + { /* Must be the last */ + MHI_CLIENT_INVALID, + 0, + 0, + MHI_DIR_INVALID, + false + }, }; struct uci_ctrl { @@ -87,6 +215,8 @@ struct uci_client { u32 in_chan; struct mhi_dev_client *out_handle; struct mhi_dev_client *in_handle; + const struct chan_attr *in_chan_attr; + const struct chan_attr *out_chan_attr; wait_queue_head_t read_wq; wait_queue_head_t write_wq; atomic_t read_data_ready; @@ -101,10 +231,16 @@ struct uci_client { struct mhi_uci_ctxt_t *uci_ctxt; struct mutex in_chan_lock; struct mutex out_chan_lock; + spinlock_t wr_req_lock; + unsigned int f_flags; + struct mhi_req *wreqs; + struct list_head wr_req_list; + struct completion read_done; + int (*send)(struct uci_client*, void*, u32); + int (*read)(struct uci_client*, struct mhi_req*, int*); }; struct mhi_uci_ctxt_t { - struct chan_attr chan_attrib[MHI_MAX_SOFTWARE_CHANNELS]; struct uci_client client_handles[MHI_SOFTWARE_CLIENT_LIMIT]; struct uci_ctrl ctrl_handle; void (*event_notifier)(struct mhi_dev_client_cb_reason *cb); @@ -119,6 +255,7 @@ struct mhi_uci_ctxt_t { }; #define CHAN_TO_CLIENT(_CHAN_NR) (_CHAN_NR / 2) +#define CLIENT_TO_CHAN(_CLIENT_NR) (_CLIENT_NR * 2) #define uci_log(_msg_lvl, _msg, ...) do { \ if (_msg_lvl >= mhi_uci_msg_lvl) { \ @@ -155,8 +292,8 @@ static int mhi_init_read_chan(struct uci_client *client_handle, enum mhi_client_channel chan) { int rc = 0; - u32 i , j; - struct chan_attr *chan_attributes; + u32 i, j; + const struct chan_attr *in_chan_attr; size_t buf_size; void *data_loc; @@ -169,10 +306,18 @@ static int mhi_init_read_chan(struct uci_client *client_handle, return -EINVAL; } - chan_attributes = &uci_ctxt.chan_attrib[chan]; - buf_size = chan_attributes->max_packet_size; + in_chan_attr = client_handle->in_chan_attr; + if (!in_chan_attr) { + uci_log(UCI_DBG_ERROR, "Null channel attributes for chan %d\n", + client_handle->in_chan); + return -EINVAL; + } - for (i = 0; i < (chan_attributes->nr_trbs); i++) { + /* Init the completion event for read */ + init_completion(&client_handle->read_done); + + buf_size = in_chan_attr->max_packet_size; + for (i = 0; i < (in_chan_attr->nr_trbs); i++) { data_loc = kmalloc(buf_size, GFP_KERNEL); if (!data_loc) { rc = -ENOMEM; @@ -191,48 +336,129 @@ static int mhi_init_read_chan(struct uci_client *client_handle, return rc; } -static int mhi_uci_send_packet(struct mhi_dev_client **client_handle, void *buf, - u32 size, u32 is_uspace_buf) +static void mhi_uci_write_completion_cb(void *req) { - void *data_loc = NULL; - uintptr_t memcpy_result = 0; - u32 data_inserted_so_far = 0; + struct mhi_req *ureq = req; struct uci_client *uci_handle; - struct mhi_req ureq; + unsigned long flags; + uci_handle = (struct uci_client *)ureq->context; + kfree(ureq->buf); + ureq->buf = NULL; - uci_handle = container_of(client_handle, struct uci_client, - out_handle); + spin_lock_irqsave(&uci_handle->wr_req_lock, flags); + list_add_tail(&ureq->list, &uci_handle->wr_req_list); + spin_unlock_irqrestore(&uci_handle->wr_req_lock, flags); +} - if (!client_handle || !buf || - !size || !uci_handle) - return -EINVAL; +static void mhi_uci_read_completion_cb(void *req) +{ + struct mhi_req *ureq = req; + struct uci_client *uci_handle; - if (is_uspace_buf) { - data_loc = kmalloc(size, GFP_KERNEL); - if (!data_loc) { - uci_log(UCI_DBG_ERROR, - "Failed to allocate memory 0x%x\n", - size); - return -ENOMEM; - } - memcpy_result = copy_from_user(data_loc, buf, size); - if (memcpy_result) - goto error_memcpy; - } else { - data_loc = buf; - } - ureq.client = *client_handle; + uci_handle = (struct uci_client *)ureq->context; + complete(&uci_handle->read_done); +} + +static int mhi_uci_send_sync(struct uci_client *uci_handle, + void *data_loc, u32 size) +{ + struct mhi_req ureq; + int ret_val; + + ureq.client = uci_handle->out_handle; ureq.buf = data_loc; ureq.len = size; ureq.chan = uci_handle->out_chan; ureq.mode = IPA_DMA_SYNC; - data_inserted_so_far = mhi_dev_write_channel(&ureq); + ret_val = mhi_dev_write_channel(&ureq); + + kfree(data_loc); + return ret_val; +} + +static int mhi_uci_send_async(struct uci_client *uci_handle, + void *data_loc, u32 size) +{ + int bytes_to_write; + struct mhi_req *ureq; + + uci_log(UCI_DBG_VERBOSE, + "Got async write for ch %d of size %d\n", + uci_handle->out_chan, size); + + spin_lock_irq(&uci_handle->wr_req_lock); + if (list_empty(&uci_handle->wr_req_list)) { + uci_log(UCI_DBG_ERROR, "Write request pool empty\n"); + spin_unlock_irq(&uci_handle->wr_req_lock); + return -ENOMEM; + } + ureq = container_of(uci_handle->wr_req_list.next, + struct mhi_req, list); + list_del_init(&ureq->list); + spin_unlock_irq(&uci_handle->wr_req_lock); + + ureq->client = uci_handle->out_handle; + ureq->context = uci_handle; + ureq->buf = data_loc; + ureq->len = size; + ureq->chan = uci_handle->out_chan; + ureq->mode = IPA_DMA_ASYNC; + ureq->client_cb = mhi_uci_write_completion_cb; + ureq->snd_cmpl = 1; + + bytes_to_write = mhi_dev_write_channel(ureq); + if (bytes_to_write != size) + goto error_async_transfer; + + return bytes_to_write; + +error_async_transfer: + kfree(data_loc); + ureq->buf = NULL; + spin_lock_irq(&uci_handle->wr_req_lock); + list_add_tail(&ureq->list, &uci_handle->wr_req_list); + spin_unlock_irq(&uci_handle->wr_req_lock); + + return bytes_to_write; +} + +static int mhi_uci_send_packet(struct mhi_dev_client **client_handle, + const char __user *buf, u32 size) +{ + void *data_loc; + unsigned long memcpy_result; + struct uci_client *uci_handle; + + if (!client_handle || !buf || !size) + return -EINVAL; + + if (size > TRB_MAX_DATA_SIZE) { + uci_log(UCI_DBG_ERROR, + "Too big write size: %d, max supported size is %d\n", + size, TRB_MAX_DATA_SIZE); + return -EFBIG; + } + + uci_handle = container_of(client_handle, struct uci_client, + out_handle); + data_loc = kmalloc(size, GFP_KERNEL); + if (!data_loc) { + uci_log(UCI_DBG_ERROR, + "Failed to allocate kernel buf for user requested size 0x%x\n", + size); + return -ENOMEM; + } + memcpy_result = copy_from_user(data_loc, buf, size); + if (memcpy_result) + goto error_memcpy; + + return uci_handle->send(uci_handle, data_loc, size); error_memcpy: kfree(data_loc); - return data_inserted_so_far; + return -EFAULT; } static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait) @@ -290,6 +516,119 @@ static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait) return mask; } +static int mhi_uci_alloc_write_reqs(struct uci_client *client) +{ + int i; + + client->wreqs = kcalloc(MAX_UCI_WR_REQ, + sizeof(struct mhi_req), + GFP_KERNEL); + if (!client->wreqs) { + uci_log(UCI_DBG_ERROR, "Write reqs alloc failed\n"); + return -ENOMEM; + } + + INIT_LIST_HEAD(&client->wr_req_list); + for (i = 0; i < MAX_UCI_WR_REQ; ++i) + list_add_tail(&client->wreqs[i].list, &client->wr_req_list); + + uci_log(UCI_DBG_INFO, + "UCI write reqs allocation successful\n"); + return 0; +} + +static int mhi_uci_read_async(struct uci_client *uci_handle, + struct mhi_req *ureq, int *bytes_avail) +{ + int ret_val = 0; + unsigned long compl_ret; + + uci_log(UCI_DBG_ERROR, + "Async read for ch %d\n", uci_handle->in_chan); + + ureq->mode = IPA_DMA_ASYNC; + ureq->client_cb = mhi_uci_read_completion_cb; + ureq->snd_cmpl = 1; + ureq->context = uci_handle; + + reinit_completion(&uci_handle->read_done); + + *bytes_avail = mhi_dev_read_channel(ureq); + uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%x bytes_read = 0x%x\n", + ureq->len, *bytes_avail); + if (*bytes_avail < 0) { + uci_log(UCI_DBG_ERROR, "Failed to read channel ret %d\n", + *bytes_avail); + return -EIO; + } + + if (*bytes_avail > 0) { + uci_log(UCI_DBG_VERBOSE, + "Waiting for async read completion!\n"); + compl_ret = + wait_for_completion_interruptible_timeout( + &uci_handle->read_done, + MHI_UCI_ASYNC_READ_TIMEOUT); + + if (compl_ret == -ERESTARTSYS) { + uci_log(UCI_DBG_ERROR, "Exit signal caught\n"); + return compl_ret; + } else if (compl_ret == 0) { + uci_log(UCI_DBG_ERROR, "Read timed out for ch %d\n", + uci_handle->in_chan); + return -EIO; + } + uci_log(UCI_DBG_VERBOSE, + "wk up Read completed on ch %d\n", ureq->chan); + + uci_handle->pkt_loc = (void *)ureq->buf; + uci_handle->pkt_size = ureq->actual_len; + + uci_log(UCI_DBG_VERBOSE, + "Got pkt of sz 0x%x at adr %pK, ch %d\n", + uci_handle->pkt_size, + ureq->buf, ureq->chan); + } else { + uci_handle->pkt_loc = NULL; + uci_handle->pkt_size = 0; + } + + return ret_val; +} + +static int mhi_uci_read_sync(struct uci_client *uci_handle, + struct mhi_req *ureq, int *bytes_avail) +{ + int ret_val = 0; + + ureq->mode = IPA_DMA_SYNC; + *bytes_avail = mhi_dev_read_channel(ureq); + + uci_log(UCI_DBG_VERBOSE, "buf_size = 0x%x bytes_read = 0x%x\n", + ureq->len, *bytes_avail); + + if (*bytes_avail < 0) { + uci_log(UCI_DBG_ERROR, "Failed to read channel ret %d\n", + *bytes_avail); + return -EIO; + } + + if (*bytes_avail > 0) { + uci_handle->pkt_loc = (void *)ureq->buf; + uci_handle->pkt_size = ureq->actual_len; + + uci_log(UCI_DBG_VERBOSE, + "Got pkt of sz 0x%x at adr %pK, ch %d\n", + uci_handle->pkt_size, + ureq->buf, ureq->chan); + } else { + uci_handle->pkt_loc = NULL; + uci_handle->pkt_size = 0; + } + + return ret_val; +} + static int open_client_mhi_channels(struct uci_client *uci_client) { int rc = 0; @@ -300,16 +639,27 @@ static int open_client_mhi_channels(struct uci_client *uci_client) uci_client->in_chan); mutex_lock(&uci_client->out_chan_lock); mutex_lock(&uci_client->in_chan_lock); + + /* Allocate write requests for async operations */ + if (!(uci_client->f_flags & O_SYNC)) { + rc = mhi_uci_alloc_write_reqs(uci_client); + if (rc) + goto handle_not_rdy_err; + uci_client->send = mhi_uci_send_async; + uci_client->read = mhi_uci_read_async; + } else { + uci_client->send = mhi_uci_send_sync; + uci_client->read = mhi_uci_read_sync; + } + uci_log(UCI_DBG_DBG, "Initializing inbound chan %d.\n", uci_client->in_chan); - rc = mhi_init_read_chan(uci_client, uci_client->in_chan); - if (rc < 0) { + if (rc < 0) uci_log(UCI_DBG_ERROR, "Failed to init inbound 0x%x, ret 0x%x\n", uci_client->in_chan, rc); - } rc = mhi_dev_open_channel(uci_client->out_chan, &uci_client->out_handle, @@ -320,7 +670,6 @@ static int open_client_mhi_channels(struct uci_client *uci_client) rc = mhi_dev_open_channel(uci_client->in_chan, &uci_client->in_handle, uci_ctxt.event_notifier); - if (rc < 0) { uci_log(UCI_DBG_ERROR, "Failed to open chan %d, ret 0x%x\n", @@ -375,6 +724,7 @@ static int mhi_uci_client_open(struct inode *mhi_inode, return -ENOMEM; } uci_handle->uci_ctxt = &uci_ctxt; + uci_handle->f_flags = file_handle->f_flags; if (!atomic_read(&uci_handle->mhi_chans_open)) { uci_log(UCI_DBG_INFO, "Opening channels client %d\n", @@ -397,20 +747,11 @@ static int mhi_uci_client_release(struct inode *mhi_inode, struct file *file_handle) { struct uci_client *uci_handle = file_handle->private_data; - struct mhi_uci_ctxt_t *uci_ctxt; - u32 nr_in_bufs = 0; int rc = 0; - int in_chan = 0; - u32 buf_size = 0; if (!uci_handle) return -EINVAL; - uci_ctxt = uci_handle->uci_ctxt; - in_chan = iminor(mhi_inode) + 1; - nr_in_bufs = uci_ctxt->chan_attrib[in_chan].nr_trbs; - buf_size = uci_ctxt->chan_attrib[in_chan].max_packet_size; - if (atomic_sub_return(1, &uci_handle->ref_count) == 0) { uci_log(UCI_DBG_DBG, "Last client left, closing channel 0x%x\n", @@ -418,6 +759,8 @@ static int mhi_uci_client_release(struct inode *mhi_inode, if (atomic_read(&uci_handle->mhi_chans_open)) { atomic_set(&uci_handle->mhi_chans_open, 0); + if (!(uci_handle->f_flags & O_SYNC)) + kfree(uci_handle->wreqs); mutex_lock(&uci_handle->out_chan_lock); rc = mhi_dev_close_channel(uci_handle->out_handle); wake_up(&uci_handle->write_wq); @@ -553,7 +896,6 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *ubuf, struct mutex *mutex; ssize_t bytes_copied = 0; u32 addr_offset = 0; - void *local_buf = NULL; struct mhi_req ureq; if (!file || !ubuf || !uspace_buf_size || @@ -569,44 +911,19 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *ubuf, ureq.client = client_handle; ureq.buf = uci_handle->in_buf_list[0].addr; ureq.len = uci_handle->in_buf_list[0].buf_size; - ureq.mode = IPA_DMA_SYNC; + uci_log(UCI_DBG_VERBOSE, "Client attempted read on chan %d\n", ureq.chan); do { if (!uci_handle->pkt_loc && - !atomic_read(&uci_ctxt.mhi_disabled)) { - - bytes_avail = mhi_dev_read_channel(&ureq); - - uci_log(UCI_DBG_VERBOSE, - "reading from mhi_core local_buf = %p", - local_buf); - uci_log(UCI_DBG_VERBOSE, - "buf_size = 0x%x bytes_read = 0x%x\n", - ureq.len, bytes_avail); - - if (bytes_avail < 0) { - uci_log(UCI_DBG_ERROR, - "Failed to read channel ret %d\n", - bytes_avail); - ret_val = -EIO; + !atomic_read(&uci_ctxt.mhi_disabled)) { + ret_val = uci_handle->read(uci_handle, &ureq, + &bytes_avail); + if (ret_val) goto error; - } - - if (bytes_avail > 0) { - uci_handle->pkt_loc = (void *) ureq.buf; - uci_handle->pkt_size = ureq.actual_len; - + if (bytes_avail > 0) *bytes_pending = (loff_t)uci_handle->pkt_size; - uci_log(UCI_DBG_VERBOSE, - "Got pkt of sz 0x%x at adr %p, ch %d\n", - uci_handle->pkt_size, - ureq.buf, ureq.chan); - } else { - uci_handle->pkt_loc = 0; - uci_handle->pkt_size = 0; - } } if (bytes_avail == 0) { @@ -615,7 +932,10 @@ static ssize_t mhi_uci_client_read(struct file *file, char __user *ubuf, "No data read_data_ready %d, chan %d\n", atomic_read(&uci_handle->read_data_ready), ureq.chan); - + if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY)) { + ret_val = -EAGAIN; + goto error; + } ret_val = wait_event_interruptible(uci_handle->read_wq, (!mhi_dev_channel_isempty(client_handle))); @@ -719,10 +1039,10 @@ static ssize_t mhi_uci_client_write(struct file *file, mutex_lock(&uci_handle->out_chan_lock); while (!ret_val) { ret_val = mhi_uci_send_packet(&uci_handle->out_handle, - (void *)buf, count, 1); + buf, count); if (ret_val < 0) { uci_log(UCI_DBG_ERROR, - "Error while writing data to MHI, chan %d, buf %p, size %d\n", + "Error while writing data to MHI, chan %d, buf %pK, size %d\n", chan, (void *)buf, count); ret_val = -EIO; break; @@ -732,6 +1052,8 @@ static ssize_t mhi_uci_client_write(struct file *file, "No descriptors available, did we poll, chan %d?\n", chan); mutex_unlock(&uci_handle->out_chan_lock); + if (uci_handle->f_flags & (O_NONBLOCK | O_NDELAY)) + return -EAGAIN; ret_val = wait_event_interruptible(uci_handle->write_wq, !mhi_dev_channel_isempty( uci_handle->out_handle)); @@ -750,54 +1072,27 @@ static ssize_t mhi_uci_client_write(struct file *file, static int uci_init_client_attributes(struct mhi_uci_ctxt_t *uci_ctxt) { - u32 i = 0; - u32 data_size = TRB_MAX_DATA_SIZE; - u32 index = 0; + u32 i; + u32 index; struct uci_client *client; - struct chan_attr *chan_attrib = NULL; - - for (i = 0; i < ARRAY_SIZE(uci_ctxt->chan_attrib); i++) { - chan_attrib = &uci_ctxt->chan_attrib[i]; - switch (i) { - case MHI_CLIENT_LOOPBACK_OUT: - case MHI_CLIENT_LOOPBACK_IN: - case MHI_CLIENT_SAHARA_OUT: - case MHI_CLIENT_SAHARA_IN: - case MHI_CLIENT_EFS_OUT: - case MHI_CLIENT_EFS_IN: - case MHI_CLIENT_MBIM_OUT: - case MHI_CLIENT_MBIM_IN: - case MHI_CLIENT_QMI_OUT: - case MHI_CLIENT_QMI_IN: - case MHI_CLIENT_IP_CTRL_0_OUT: - case MHI_CLIENT_IP_CTRL_0_IN: - case MHI_CLIENT_IP_CTRL_1_OUT: - case MHI_CLIENT_IP_CTRL_1_IN: - case MHI_CLIENT_DUN_OUT: - case MHI_CLIENT_DUN_IN: - chan_attrib->uci_ownership = 1; - break; - default: - chan_attrib->uci_ownership = 0; + const struct chan_attr *chan_attrib; + + for (i = 0; i < ARRAY_SIZE(uci_chan_attr_table); i += 2) { + chan_attrib = &uci_chan_attr_table[i]; + if (chan_attrib->chan_id == MHI_CLIENT_INVALID) break; - } - if (chan_attrib->uci_ownership) { - chan_attrib->chan_id = i; - chan_attrib->max_packet_size = data_size; - index = CHAN_TO_CLIENT(i); - client = &uci_ctxt->client_handles[index]; - chan_attrib->nr_trbs = 9; - client->in_buf_list = - kmalloc(sizeof(struct mhi_dev_iov) * - chan_attrib->nr_trbs, + index = CHAN_TO_CLIENT(chan_attrib->chan_id); + client = &uci_ctxt->client_handles[index]; + client->out_chan_attr = chan_attrib; + client->in_chan_attr = ++chan_attrib; + client->in_chan = index * 2; + client->out_chan = index * 2 + 1; + client->in_buf_list = + kcalloc(chan_attrib->nr_trbs, + sizeof(struct mhi_dev_iov), GFP_KERNEL); - if (NULL == client->in_buf_list) - return -ENOMEM; - } - if (i % 2 == 0) - chan_attrib->dir = MHI_DIR_OUT; - else - chan_attrib->dir = MHI_DIR_IN; + if (!client->in_buf_list) + return -ENOMEM; } return 0; } @@ -846,12 +1141,11 @@ static int mhi_register_client(struct uci_client *mhi_client, int index) { init_waitqueue_head(&mhi_client->read_wq); init_waitqueue_head(&mhi_client->write_wq); - mhi_client->out_chan = index * 2 + 1; - mhi_client->in_chan = index * 2; mhi_client->client_index = index; mutex_init(&mhi_client->in_chan_lock); mutex_init(&mhi_client->out_chan_lock); + spin_lock_init(&mhi_client->wr_req_lock); uci_log(UCI_DBG_DBG, "Registering chan %d.\n", mhi_client->out_chan); return 0; @@ -949,16 +1243,14 @@ int mhi_uci_init(void) uci_log(UCI_DBG_INFO, "Registering for MHI events.\n"); for (i = 0; i < MHI_SOFTWARE_CLIENT_LIMIT; i++) { - if (uci_ctxt.chan_attrib[i * 2].uci_ownership) { - mhi_client = &uci_ctxt.client_handles[i]; - - r = mhi_register_client(mhi_client, i); - - if (r) { - uci_log(UCI_DBG_CRITICAL, - "Failed to reg client %d ret %d\n", - r, i); - } + mhi_client = &uci_ctxt.client_handles[i]; + if (!mhi_client->in_chan_attr) + continue; + r = mhi_register_client(mhi_client, i); + if (r) { + uci_log(UCI_DBG_CRITICAL, + "Failed to reg client %d ret %d\n", + r, i); } } @@ -992,29 +1284,30 @@ int mhi_uci_init(void) uci_log(UCI_DBG_INFO, "Setting up device nodes.\n"); for (i = 0; i < MHI_SOFTWARE_CLIENT_LIMIT; i++) { - if (uci_ctxt.chan_attrib[i*2].uci_ownership) { - cdev_init(&uci_ctxt.cdev[i], &mhi_uci_client_fops); - uci_ctxt.cdev[i].owner = THIS_MODULE; - r = cdev_add(&uci_ctxt.cdev[i], - uci_ctxt.start_ctrl_nr + i , 1); - if (IS_ERR_VALUE(r)) { - uci_log(UCI_DBG_ERROR, - "Failed to add cdev %d, ret 0x%x\n", - i, r); - goto failed_char_add; - } + mhi_client = &uci_ctxt.client_handles[i]; + if (!mhi_client->in_chan_attr) + continue; + cdev_init(&uci_ctxt.cdev[i], &mhi_uci_client_fops); + uci_ctxt.cdev[i].owner = THIS_MODULE; + r = cdev_add(&uci_ctxt.cdev[i], + uci_ctxt.start_ctrl_nr + i, 1); + if (IS_ERR_VALUE(r)) { + uci_log(UCI_DBG_ERROR, + "Failed to add cdev %d, ret 0x%x\n", + i, r); + goto failed_char_add; + } - uci_ctxt.client_handles[i].dev = - device_create(uci_ctxt.mhi_uci_class, NULL, - uci_ctxt.start_ctrl_nr + i, - NULL, DEVICE_NAME "_pipe_%d", - i * 2); - if (IS_ERR(uci_ctxt.client_handles[i].dev)) { - uci_log(UCI_DBG_ERROR, - "Failed to add cdev %d\n", i); - cdev_del(&uci_ctxt.cdev[i]); - goto failed_device_create; - } + uci_ctxt.client_handles[i].dev = + device_create(uci_ctxt.mhi_uci_class, NULL, + uci_ctxt.start_ctrl_nr + i, + NULL, DEVICE_NAME "_pipe_%d", + i * 2); + if (IS_ERR(uci_ctxt.client_handles[i].dev)) { + uci_log(UCI_DBG_ERROR, + "Failed to add cdev %d\n", i); + cdev_del(&uci_ctxt.cdev[i]); + goto failed_device_create; } } diff --git a/drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c b/drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c index 146d7c6d70a8..816b3be86a9f 100644 --- a/drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c +++ b/drivers/platform/msm/msm_bus/msm_bus_fabric_adhoc.c @@ -1012,10 +1012,8 @@ static struct device *msm_bus_device_init( bus_node = kzalloc(sizeof(struct msm_bus_node_device_type), GFP_KERNEL); if (!bus_node) { - MSM_BUS_ERR("%s:Bus node alloc failed\n", __func__); - kfree(bus_dev); - bus_dev = NULL; - goto exit_device_init; + ret = -ENOMEM; + goto err_device_init; } bus_dev = &bus_node->dev; device_initialize(bus_dev); @@ -1023,47 +1021,37 @@ static struct device *msm_bus_device_init( node_info = devm_kzalloc(bus_dev, sizeof(struct msm_bus_node_info_type), GFP_KERNEL); if (!node_info) { - MSM_BUS_ERR("%s:Bus node info alloc failed\n", __func__); - devm_kfree(bus_dev, bus_node); - kfree(bus_dev); - bus_dev = NULL; - goto exit_device_init; + ret = -ENOMEM; + goto err_put_device; } bus_node->node_info = node_info; bus_node->ap_owned = pdata->ap_owned; bus_dev->of_node = pdata->of_node; - if (msm_bus_copy_node_info(pdata, bus_dev) < 0) { - devm_kfree(bus_dev, bus_node); - devm_kfree(bus_dev, node_info); - kfree(bus_dev); - bus_dev = NULL; - goto exit_device_init; - } + ret = msm_bus_copy_node_info(pdata, bus_dev); + if (ret) + goto err_put_device; bus_dev->bus = &msm_bus_type; dev_set_name(bus_dev, bus_node->node_info->name); ret = device_add(bus_dev); - if (ret < 0) { + if (ret) { MSM_BUS_ERR("%s: Error registering device %d", __func__, pdata->node_info->id); - devm_kfree(bus_dev, bus_node); - devm_kfree(bus_dev, node_info->dev_connections); - devm_kfree(bus_dev, node_info->connections); - devm_kfree(bus_dev, node_info->black_connections); - devm_kfree(bus_dev, node_info->black_listed_connections); - devm_kfree(bus_dev, node_info); - kfree(bus_dev); - bus_dev = NULL; - goto exit_device_init; + goto err_put_device; } device_create_file(bus_dev, &dev_attr_bw); INIT_LIST_HEAD(&bus_node->devlist); - -exit_device_init: return bus_dev; + +err_put_device: + put_device(bus_dev); + bus_dev = NULL; + kfree(bus_node); +err_device_init: + return ERR_PTR(ret); } static int msm_bus_setup_dev_conn(struct device *bus_dev, void *data) @@ -1258,10 +1246,10 @@ static int msm_bus_device_probe(struct platform_device *pdev) node_dev = msm_bus_device_init(&pdata->info[i]); - if (!node_dev) { + if (IS_ERR(node_dev)) { MSM_BUS_ERR("%s: Error during dev init for %d", __func__, pdata->info[i].node_info->id); - ret = -ENXIO; + ret = PTR_ERR(node_dev); goto exit_device_probe; } diff --git a/drivers/platform/msm/sps/sps.c b/drivers/platform/msm/sps/sps.c index 03cc14aa7e29..2237db198c53 100644 --- a/drivers/platform/msm/sps/sps.c +++ b/drivers/platform/msm/sps/sps.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1006,8 +1006,6 @@ static void sps_device_de_init(void) "sps:%s:BAMs are still registered", __func__); sps_map_de_init(); - - kfree(sps); } sps_mem_de_init(); @@ -2989,6 +2987,7 @@ static struct platform_driver msm_sps_driver = { .name = SPS_DRV_NAME, .owner = THIS_MODULE, .of_match_table = msm_sps_match, + .suppress_bind_attrs = true, }, .remove = msm_sps_remove, }; diff --git a/drivers/platform/msm/ssm.c b/drivers/platform/msm/ssm.c deleted file mode 100644 index 6a2909b8c5f4..000000000000 --- a/drivers/platform/msm/ssm.c +++ /dev/null @@ -1,516 +0,0 @@ -/* Copyright (c) 2013-2014, 2016 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. - */ -/* - * QTI Secure Service Module(SSM) driver - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../misc/qseecom_kernel.h" -#include "ssm.h" - -/* Macros */ -#define SSM_DEV_NAME "ssm" -#define MPSS_SUBSYS 0 -#define SSM_INFO_CMD_ID 1 -#define MAX_APP_NAME_SIZE 32 -#define SSM_MSG_LEN 200 -#define SSM_MSG_FIELD_LEN 11 -#define ATOM_MSG_LEN (SSM_MSG_FIELD_LEN + SSM_MSG_LEN + 40) - -#define TZAPP_NAME "SsmApp" -#define CHANNEL_NAME "SSM_RTR_MODEM_APPS" - -/* SSM driver structure.*/ -struct ssm_driver { - int32_t app_status; - int32_t update_status; - unsigned char *channel_name; - unsigned char *smd_buffer; - struct device *dev; - smd_channel_t *ch; - struct work_struct ipc_work; - struct mutex mutex; - struct qseecom_handle *qseecom_handle; - struct tzapp_get_mode_info_rsp *resp; - bool key_status; - bool ready; -}; - -static struct ssm_driver *ssm_drv; - -static unsigned int getint(char *buff, unsigned long *res) -{ - char value[SSM_MSG_FIELD_LEN]; - - memcpy(value, buff, SSM_MSG_FIELD_LEN); - value[SSM_MSG_FIELD_LEN - 1] = '\0'; - - return kstrtoul(skip_spaces(value), 10, res); -} - -/* - * Setup CMD/RSP pointers. - */ -static void setup_cmd_rsp_buffers(struct qseecom_handle *handle, void **cmd, - int *cmd_len, void **resp, int *resp_len) -{ - *cmd = handle->sbuf; - if (*cmd_len & QSEECOM_ALIGN_MASK) - *cmd_len = QSEECOM_ALIGN(*cmd_len); - - *resp = handle->sbuf + *cmd_len; - if (*resp_len & QSEECOM_ALIGN_MASK) - *resp_len = QSEECOM_ALIGN(*resp_len); -} - -/* - * Send packet to modem over SMD channel. - */ -static int update_modem(enum ssm_ipc_req ipc_req, struct ssm_driver *ssm, - int length, char *data) -{ - unsigned int packet_len = length + SSM_MSG_FIELD_LEN; - int rc = 0, count; - - snprintf(ssm->smd_buffer, SSM_MSG_FIELD_LEN + 1, "%10u|", ipc_req); - memcpy(ssm->smd_buffer + SSM_MSG_FIELD_LEN, data, length); - - if (smd_write_avail(ssm->ch) < packet_len) { - dev_err(ssm->dev, "Not enough space dropping request\n"); - rc = -ENOSPC; - goto out; - } - - count = smd_write(ssm->ch, ssm->smd_buffer, packet_len); - if (count < packet_len) { - dev_err(ssm->dev, "smd_write failed for %d\n", ipc_req); - rc = -EIO; - } - -out: - return rc; -} - -/* - * Header Format - * Each member of header is of 10 byte (ASCII). - * Each entry is separated by '|' delimiter. - * |<-10 bytes->|<-10 bytes->| - * |-------------------------| - * | IPC code | error code | - * |-------------------------| - * - */ -static int decode_packet(char *buffer, struct ssm_common_msg *pkt) -{ - int rc; - - rc = getint(buffer, (unsigned long *)&pkt->ipc_req); - if (rc < 0) - return -EINVAL; - - buffer += SSM_MSG_FIELD_LEN; - rc = getint(buffer, (unsigned long *)&pkt->err_code); - if (rc < 0) - return -EINVAL; - - dev_dbg(ssm_drv->dev, "req %d error code %d\n", - pkt->ipc_req, pkt->err_code); - return 0; -} - -static void process_message(struct ssm_common_msg pkt, struct ssm_driver *ssm) -{ - - switch (pkt.ipc_req) { - - case SSM_MTOA_MODE_UPDATE_STATUS: - if (pkt.err_code) { - dev_err(ssm->dev, "Modem mode update failed\n"); - ssm->update_status = FAILED; - } else - ssm->update_status = SUCCESS; - - dev_dbg(ssm->dev, "Modem mode update status %d\n", - pkt.err_code); - break; - - default: - dev_dbg(ssm->dev, "Invalid message\n"); - break; - }; -} - -/* - * Work function to handle and process packets coming from modem. - */ -static void ssm_app_modem_work_fn(struct work_struct *work) -{ - int sz, rc; - struct ssm_common_msg pkt; - struct ssm_driver *ssm; - - ssm = container_of(work, struct ssm_driver, ipc_work); - - mutex_lock(&ssm->mutex); - sz = smd_cur_packet_size(ssm->ch); - if ((sz < SSM_MSG_FIELD_LEN) || (sz > ATOM_MSG_LEN)) { - dev_dbg(ssm_drv->dev, "Garbled message size\n"); - goto unlock; - } - - if (smd_read_avail(ssm->ch) < sz) { - dev_err(ssm_drv->dev, "SMD error data in channel\n"); - goto unlock; - } - - if (smd_read(ssm->ch, ssm->smd_buffer, sz) != sz) { - dev_err(ssm_drv->dev, "Incomplete data\n"); - goto unlock; - } - - rc = decode_packet(ssm->smd_buffer, &pkt); - if (rc < 0) { - dev_err(ssm_drv->dev, "Corrupted header\n"); - goto unlock; - } - - process_message(pkt, ssm); - -unlock: - mutex_unlock(&ssm->mutex); -} - -/* - * MODEM-APPS smd channel callback function. - */ -static void modem_request(void *ctxt, unsigned event) -{ - struct ssm_driver *ssm; - - ssm = (struct ssm_driver *)ctxt; - - switch (event) { - case SMD_EVENT_OPEN: - case SMD_EVENT_CLOSE: - dev_dbg(ssm->dev, "SMD port status changed\n"); - break; - case SMD_EVENT_DATA: - if (smd_read_avail(ssm->ch) > 0) - schedule_work(&ssm->ipc_work); - break; - }; -} - -/* - * Load SSM application in TZ and start application: - */ -static int ssm_load_app(struct ssm_driver *ssm) -{ - int rc; - - /* Load the APP */ - rc = qseecom_start_app(&ssm->qseecom_handle, TZAPP_NAME, SZ_4K); - if (rc < 0) { - dev_err(ssm->dev, "Unable to load SSM app\n"); - ssm->app_status = FAILED; - return -EIO; - } - - ssm->app_status = SUCCESS; - return 0; -} - -static struct ssm_platform_data *populate_ssm_pdata(struct device *dev) -{ - struct ssm_platform_data *pdata; - - pdata = devm_kzalloc(dev, sizeof(struct ssm_platform_data), - GFP_KERNEL); - if (!pdata) - return NULL; - - pdata->need_key_exchg = - of_property_read_bool(dev->of_node, "qcom,need-keyexhg"); - - pdata->channel_name = CHANNEL_NAME; - - return pdata; -} - -static int ssm_probe(struct platform_device *pdev) -{ - int rc; - struct ssm_platform_data *pdata; - struct ssm_driver *drv; - - if (pdev->dev.of_node) - pdata = populate_ssm_pdata(&pdev->dev); - else - pdata = pdev->dev.platform_data; - - if (!pdata) { - dev_err(&pdev->dev, "Empty platform data\n"); - return -ENOMEM; - } - - drv = devm_kzalloc(&pdev->dev, sizeof(struct ssm_driver), - GFP_KERNEL); - if (!drv) - return -ENOMEM; - - /* Allocate response buffer */ - drv->resp = devm_kzalloc(&pdev->dev, - sizeof(struct tzapp_get_mode_info_rsp), - GFP_KERNEL); - if (!drv->resp) { - devm_kfree(&pdev->dev, drv); - rc = -ENOMEM; - goto exit; - } - - /* Initialize the driver structure */ - drv->app_status = RETRY; - drv->ready = false; - drv->update_status = FAILED; - mutex_init(&drv->mutex); - drv->key_status = !pdata->need_key_exchg; - drv->channel_name = (char *)pdata->channel_name; - INIT_WORK(&drv->ipc_work, ssm_app_modem_work_fn); - - /* Allocate memory for smd buffer */ - drv->smd_buffer = devm_kzalloc(&pdev->dev, - (sizeof(char) * ATOM_MSG_LEN), GFP_KERNEL); - if (!drv->smd_buffer) { - devm_kfree(&pdev->dev, drv->resp); - devm_kfree(&pdev->dev, drv); - rc = -ENOMEM; - goto exit; - } - - drv->dev = &pdev->dev; - ssm_drv = drv; - platform_set_drvdata(pdev, ssm_drv); - - dev_dbg(&pdev->dev, "probe success\n"); - return 0; - -exit: - mutex_destroy(&drv->mutex); - platform_set_drvdata(pdev, NULL); - return rc; - -} - -static int ssm_remove(struct platform_device *pdev) -{ - - if (!ssm_drv) - return 0; - /* - * Step to exit - * 1. set ready to 0 (oem access closed). - * 2. Close SMD modem connection closed. - * 3. cleanup ion. - */ - ssm_drv->ready = false; - smd_close(ssm_drv->ch); - flush_work(&ssm_drv->ipc_work); - - /* Shutdown tzapp */ - dev_dbg(&pdev->dev, "Shutting down TZapp\n"); - qseecom_shutdown_app(&ssm_drv->qseecom_handle); - - /* freeing the memory allocations - for the driver and the buffer */ - devm_kfree(&pdev->dev, ssm_drv->smd_buffer); - devm_kfree(&pdev->dev, ssm_drv->resp); - devm_kfree(&pdev->dev, ssm_drv); - - return 0; -} - -static struct of_device_id ssm_match_table[] = { - { - .compatible = "qcom,ssm", - }, - {} -}; - -static struct platform_driver ssm_pdriver = { - .probe = ssm_probe, - .remove = ssm_remove, - .driver = { - .name = SSM_DEV_NAME, - .owner = THIS_MODULE, - .of_match_table = ssm_match_table, - }, -}; -module_platform_driver(ssm_pdriver); - -/* - * Interface for external OEM driver. - * This interface supports following functionalities: - * 1. Set mode (encrypted mode and it's length is passed as parameter). - * 2. Set mode from TZ (read encrypted mode from TZ) - * 3. Get status of mode update. - * - */ -int ssm_oem_driver_intf(int cmd, char *mode, int len) -{ - int rc, req_len, resp_len; - struct tzapp_get_mode_info_req *get_mode_req; - struct tzapp_get_mode_info_rsp *get_mode_resp; - - /* If ssm_drv is NULL, probe failed */ - if (!ssm_drv) - return -ENODEV; - - mutex_lock(&ssm_drv->mutex); - - if (ssm_drv->app_status == RETRY) { - /* Load TZAPP */ - rc = ssm_load_app(ssm_drv); - if (rc) { - rc = -ENODEV; - goto unlock; - } - } else if (ssm_drv->app_status == FAILED) { - rc = -ENODEV; - goto unlock; - } - - /* Open modem SMD interface */ - if (!ssm_drv->ready) { - rc = smd_named_open_on_edge(ssm_drv->channel_name, - SMD_APPS_MODEM, - &ssm_drv->ch, - ssm_drv, - modem_request); - if (rc) { - rc = -EAGAIN; - goto unlock; - } else - ssm_drv->ready = true; - } - - /* Try again modem key-exchange not yet done.*/ - if (!ssm_drv->key_status) { - rc = -EAGAIN; - goto unlock; - } - - /* Set return status to success */ - rc = 0; - - switch (cmd) { - case SSM_READY: - break; - - case SSM_MODE_INFO_READY: - ssm_drv->update_status = RETRY; - /* Fill command structure */ - req_len = sizeof(struct tzapp_get_mode_info_req); - resp_len = sizeof(struct tzapp_get_mode_info_rsp); - setup_cmd_rsp_buffers(ssm_drv->qseecom_handle, - (void **)&get_mode_req, &req_len, - (void **)&get_mode_resp, &resp_len); - get_mode_req->tzapp_ssm_cmd = GET_ENC_MODE; - - rc = qseecom_set_bandwidth(ssm_drv->qseecom_handle, 1); - if (rc) { - ssm_drv->update_status = FAILED; - dev_err(ssm_drv->dev, "set bandwidth failed\n"); - rc = -EIO; - break; - } - rc = qseecom_send_command(ssm_drv->qseecom_handle, - (void *)get_mode_req, req_len, - (void *)get_mode_resp, resp_len); - if (rc || get_mode_resp->status) { - ssm_drv->update_status = FAILED; - break; - } - rc = qseecom_set_bandwidth(ssm_drv->qseecom_handle, 0); - if (rc) { - ssm_drv->update_status = FAILED; - dev_err(ssm_drv->dev, "clear bandwidth failed\n"); - rc = -EIO; - break; - } - - if (get_mode_resp->enc_mode_len > ENC_MODE_MAX_SIZE) { - ssm_drv->update_status = FAILED; - rc = -EINVAL; - break; - } - /* Send mode_info to modem */ - rc = update_modem(SSM_ATOM_MODE_UPDATE, ssm_drv, - get_mode_resp->enc_mode_len, - get_mode_resp->enc_mode_info); - if (rc) - ssm_drv->update_status = FAILED; - break; - - case SSM_SET_MODE: - ssm_drv->update_status = RETRY; - - if (len > ENC_MODE_MAX_SIZE) { - ssm_drv->update_status = FAILED; - rc = -EINVAL; - break; - } - memcpy(ssm_drv->resp->enc_mode_info, mode, len); - ssm_drv->resp->enc_mode_len = len; - - /* Send mode_info to modem */ - rc = update_modem(SSM_ATOM_MODE_UPDATE, ssm_drv, - ssm_drv->resp->enc_mode_len, - ssm_drv->resp->enc_mode_info); - if (rc) - ssm_drv->update_status = FAILED; - break; - - case SSM_GET_MODE_STATUS: - rc = ssm_drv->update_status; - break; - - default: - rc = -EINVAL; - dev_err(ssm_drv->dev, "Invalid command\n"); - break; - }; - -unlock: - mutex_unlock(&ssm_drv->mutex); - return rc; -} - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION("QTI Secure Service Module"); - diff --git a/drivers/platform/msm/ssm.h b/drivers/platform/msm/ssm.h deleted file mode 100644 index ee4f1bc1d83f..000000000000 --- a/drivers/platform/msm/ssm.h +++ /dev/null @@ -1,90 +0,0 @@ -/* Copyright (c) 2013-2014, 2016 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 __SSM_H_ -#define __SSM_H_ - -#define MAX_APP_NAME_SIZE 32 -#define ENC_MODE_MAX_SIZE 200 - -/* tzapp response.*/ -enum tz_response { - RESULT_SUCCESS = 0, - RESULT_FAILURE = 0xFFFFFFFF, -}; - -/* tzapp command list.*/ -enum tz_commands { - ENC_MODE, - GET_ENC_MODE, - KEY_EXCHANGE = 11, -}; - -/* MODEM/SSM command list.*/ -enum ssm_ipc_req { - SSM_IPC_MIN = 0x0000AAAB, - SSM_ATOM_MODE_UPDATE, - SSM_MTOA_MODE_UPDATE_STATUS = SSM_IPC_MIN + 4, - SSM_INVALID_REQ, -}; - -/* OEM request commands list.*/ -enum oem_req { - SSM_READY, - SSM_MODE_INFO_READY, - SSM_SET_MODE, - SSM_GET_MODE_STATUS, - SSM_INVALID, -}; - -/* Modem mode update status.*/ -enum modem_mode_status { - SUCCESS, - RETRY, - FAILED = -1, -}; - -/* tzapp encode mode request.*/ -__packed struct tzapp_mode_enc_req { - uint32_t tzapp_ssm_cmd; - uint8_t mode_info[4]; -}; - -/* tzapp encode mode response.*/ -__packed struct tzapp_mode_enc_rsp { - uint32_t tzapp_ssm_cmd; - uint8_t enc_mode_info[ENC_MODE_MAX_SIZE]; - uint32_t enc_mode_len; - uint32_t status; -}; - -/* tzapp get mode request.*/ -__packed struct tzapp_get_mode_info_req { - uint32_t tzapp_ssm_cmd; -}; - -/* tzapp get mode response.*/ -__packed struct tzapp_get_mode_info_rsp { - uint32_t tzapp_ssm_cmd; - uint8_t enc_mode_info[ENC_MODE_MAX_SIZE]; - uint32_t enc_mode_len; - uint32_t status; -}; - -/* Modem/SSM packet format.*/ -struct ssm_common_msg { - enum ssm_ipc_req ipc_req; - int err_code; - -}; - -#endif diff --git a/drivers/power/qpnp-smbcharger.c b/drivers/power/qpnp-smbcharger.c index 546581c80688..03cb261ec855 100644 --- a/drivers/power/qpnp-smbcharger.c +++ b/drivers/power/qpnp-smbcharger.c @@ -43,6 +43,11 @@ #include #include #include + +#ifdef CONFIG_FORCE_FAST_CHARGE +#include +#endif + #if defined(CONFIG_FB) #include #include @@ -2099,7 +2104,11 @@ static int smbchg_set_usb_current_max(struct smbchg_chip *chip, } chip->usb_max_current_ma = 500; } +#ifdef CONFIG_FORCE_FAST_CHARGE + if ((force_fast_charge > 0 && current_ma == CURRENT_500_MA) || current_ma == CURRENT_900_MA) { +#else if (current_ma == CURRENT_900_MA) { +#endif rc = smbchg_sec_masked_write(chip, chip->usb_chgpth_base + CHGPTH_CFG, CFG_USB_2_3_SEL_BIT, CFG_USB_3); diff --git a/drivers/ptp/ptp_chardev.c b/drivers/ptp/ptp_chardev.c index f8a76090cbca..52d023514560 100644 --- a/drivers/ptp/ptp_chardev.c +++ b/drivers/ptp/ptp_chardev.c @@ -88,6 +88,7 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin, case PTP_PF_PHYSYNC: if (chan != 0) return -EINVAL; + break; default: return -EINVAL; } diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c index cb75133085a8..acc9987475f5 100644 --- a/drivers/pwm/pwm-tiehrpwm.c +++ b/drivers/pwm/pwm-tiehrpwm.c @@ -384,6 +384,8 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) aqcsfrc_mask = AQCSFRC_CSFA_MASK; } + /* Update shadow register first before modifying active register */ + ehrpwm_modify(pc->mmio_base, AQCSFRC, aqcsfrc_mask, aqcsfrc_val); /* * Changes to immediate action on Action Qualifier. This puts * Action Qualifier control on PWM output from next TBCLK diff --git a/drivers/regulator/pfuze100-regulator.c b/drivers/regulator/pfuze100-regulator.c index c879dff597ee..eceb75105c08 100644 --- a/drivers/regulator/pfuze100-regulator.c +++ b/drivers/regulator/pfuze100-regulator.c @@ -142,6 +142,7 @@ static struct regulator_ops pfuze100_sw_regulator_ops = { static struct regulator_ops pfuze100_swb_regulator_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = regulator_set_voltage_sel_regmap, diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c index 11572354ce66..95d15411a455 100644 --- a/drivers/rtc/interface.c +++ b/drivers/rtc/interface.c @@ -381,6 +381,11 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) { int err; + if (!rtc->ops) + return -ENODEV; + else if (!rtc->ops->set_alarm) + return -EINVAL; + err = rtc_valid_tm(&alarm->time); if (err != 0) return err; diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index fb7298920c8c..90f93c2be8cd 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -640,21 +640,20 @@ static inline unsigned long qdio_aob_for_buffer(struct qdio_output_q *q, unsigned long phys_aob = 0; if (!q->use_cq) - goto out; + return 0; if (!q->aobs[bufnr]) { struct qaob *aob = qdio_allocate_aob(); q->aobs[bufnr] = aob; } if (q->aobs[bufnr]) { - q->sbal_state[bufnr].flags = QDIO_OUTBUF_STATE_FLAG_NONE; q->sbal_state[bufnr].aob = q->aobs[bufnr]; q->aobs[bufnr]->user1 = (u64) q->sbal_state[bufnr].user; phys_aob = virt_to_phys(q->aobs[bufnr]); WARN_ON_ONCE(phys_aob & 0xFF); } -out: + q->sbal_state[bufnr].flags = 0; return phys_aob; } diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c index 6adf9abdf955..632295144766 100644 --- a/drivers/scsi/3w-9xxx.c +++ b/drivers/scsi/3w-9xxx.c @@ -901,6 +901,11 @@ static int twa_chrdev_open(struct inode *inode, struct file *file) unsigned int minor_number; int retval = TW_IOCTL_ERROR_OS_ENODEV; + if (!capable(CAP_SYS_ADMIN)) { + retval = -EACCES; + goto out; + } + minor_number = iminor(inode); if (minor_number >= twa_device_extension_count) goto out; diff --git a/drivers/scsi/3w-xxxx.c b/drivers/scsi/3w-xxxx.c index b327742b95ef..c1e1051f94cc 100644 --- a/drivers/scsi/3w-xxxx.c +++ b/drivers/scsi/3w-xxxx.c @@ -1047,6 +1047,9 @@ static int tw_chrdev_open(struct inode *inode, struct file *file) dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_open()\n"); + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + minor_number = iminor(inode); if (minor_number >= tw_device_extension_count) return -ENODEV; diff --git a/drivers/scsi/fcoe/fcoe_ctlr.c b/drivers/scsi/fcoe/fcoe_ctlr.c index 34a1b1f333b4..d5184aa1ace4 100644 --- a/drivers/scsi/fcoe/fcoe_ctlr.c +++ b/drivers/scsi/fcoe/fcoe_ctlr.c @@ -752,9 +752,9 @@ int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport, case ELS_LOGO: if (fip->mode == FIP_MODE_VN2VN) { if (fip->state != FIP_ST_VNMP_UP) - return -EINVAL; + goto drop; if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI) - return -EINVAL; + goto drop; } else { if (fip->state != FIP_ST_ENABLED) return 0; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 9ca83ebef776..857bf9417817 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -283,11 +283,11 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) */ if (opcode != ISCSI_OP_SCSI_DATA_OUT) { iscsi_conn_printk(KERN_INFO, conn, - "task [op %x/%x itt " + "task [op %x itt " "0x%x/0x%x] " "rejected.\n", - task->hdr->opcode, opcode, - task->itt, task->hdr_itt); + opcode, task->itt, + task->hdr_itt); return -EACCES; } /* @@ -296,10 +296,10 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) */ if (conn->session->fast_abort) { iscsi_conn_printk(KERN_INFO, conn, - "task [op %x/%x itt " + "task [op %x itt " "0x%x/0x%x] fast abort.\n", - task->hdr->opcode, opcode, - task->itt, task->hdr_itt); + opcode, task->itt, + task->hdr_itt); return -EACCES; } break; diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index 2485255f3414..a8e6e32639ae 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -4200,6 +4200,9 @@ megaraid_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) int irq, i, j; int error = -ENODEV; + if (hba_count >= MAX_CONTROLLERS) + goto out; + if (pci_enable_device(pdev)) goto out; pci_set_master(pdev); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 99bdccf92136..6191c300faff 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -325,11 +325,10 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun, wait_for_completion(&tm_iocb->u.tmf.comp); - rval = tm_iocb->u.tmf.comp_status == CS_COMPLETE ? - QLA_SUCCESS : QLA_FUNCTION_FAILED; + rval = tm_iocb->u.tmf.data; - if ((rval != QLA_SUCCESS) || tm_iocb->u.tmf.data) { - ql_dbg(ql_dbg_taskm, vha, 0x8030, + if (rval != QLA_SUCCESS) { + ql_log(ql_log_warn, vha, 0x8030, "TM IOCB failed (%x).\n", rval); } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 26223ff51e66..7bc28c8d2832 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -5000,8 +5000,9 @@ qla2x00_do_dpc(void *data) } } - if (test_and_clear_bit(ISP_ABORT_NEEDED, - &base_vha->dpc_flags)) { + if (test_and_clear_bit + (ISP_ABORT_NEEDED, &base_vha->dpc_flags) && + !test_bit(UNLOADING, &base_vha->dpc_flags)) { ql_dbg(ql_dbg_dpc, base_vha, 0x4007, "ISP abort scheduled.\n"); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 46b9f39afe63..b0aa970fb999 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -676,8 +676,24 @@ static ssize_t sdev_store_delete(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - if (device_remove_file_self(dev, attr)) - scsi_remove_device(to_scsi_device(dev)); + struct kernfs_node *kn; + + kn = sysfs_break_active_protection(&dev->kobj, &attr->attr); + WARN_ON_ONCE(!kn); + /* + * Concurrent writes into the "delete" sysfs attribute may trigger + * concurrent calls to device_remove_file() and scsi_remove_device(). + * device_remove_file() handles concurrent removal calls by + * serializing these and by ignoring the second and later removal + * attempts. Concurrent calls of scsi_remove_device() are + * serialized. The second and later calls of scsi_remove_device() are + * ignored because the first call of that function changes the device + * state into SDEV_DEL. + */ + device_remove_file(dev, attr); + scsi_remove_device(to_scsi_device(dev)); + if (kn) + sysfs_unbreak_active_protection(kn); return count; }; static DEVICE_ATTR(delete, S_IWUSR, NULL, sdev_store_delete); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 8ae1d31a7337..160b9296ad18 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -2243,6 +2243,7 @@ sg_add_sfp(Sg_device * sdp) write_lock_irqsave(&sdp->sfd_lock, iflags); if (atomic_read(&sdp->detaching)) { write_unlock_irqrestore(&sdp->sfd_lock, iflags); + kfree(sfp); return ERR_PTR(-ENODEV); } list_add_tail(&sfp->sfd_siblings, &sdp->sfds); diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index 1a7154249e23..d5dd70049f81 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -567,9 +567,14 @@ static void pvscsi_complete_request(struct pvscsi_adapter *adapter, (btstat == BTSTAT_SUCCESS || btstat == BTSTAT_LINKED_COMMAND_COMPLETED || btstat == BTSTAT_LINKED_COMMAND_COMPLETED_WITH_FLAG)) { - cmd->result = (DID_OK << 16) | sdstat; - if (sdstat == SAM_STAT_CHECK_CONDITION && cmd->sense_buffer) - cmd->result |= (DRIVER_SENSE << 24); + if (sdstat == SAM_STAT_COMMAND_TERMINATED) { + cmd->result = (DID_RESET << 16); + } else { + cmd->result = (DID_OK << 16) | sdstat; + if (sdstat == SAM_STAT_CHECK_CONDITION && + cmd->sense_buffer) + cmd->result |= (DRIVER_SENSE << 24); + } } else switch (btstat) { case BTSTAT_SUCCESS: diff --git a/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c b/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c index 91395fdff16a..81b38023f70f 100644 --- a/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c +++ b/drivers/soc/qcom/qdsp6v2/msm_audio_ion.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2017, 2018 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -44,6 +44,7 @@ #define MSM_AUDIO_SMMU_SID_OFFSET 32 #define TZBSP_MEM_PROTECT_AUDIO_CMD_ID 0x00000005 +#define TZBSP_MEM_PROTECT_AUDIO_CMD_ID_2 0x00000006 struct addr_range { dma_addr_t start; @@ -811,11 +812,12 @@ u32 msm_audio_populate_upper_32_bits(ion_phys_addr_t pa) return upper_32_bits(pa); } -static void msm_audio_protect_memory_region(struct device *dev) +static int msm_audio_protect_memory_region(struct device *dev) { int ret = 0; unsigned long size = 0; phys_addr_t phys_addr = 0; + struct scm_desc desc2 = {0}; struct tz_mem_protect_cmd_buf desc = {0}; struct tz_resp resp = {0}; @@ -825,13 +827,24 @@ static void msm_audio_protect_memory_region(struct device *dev) pr_debug("%s: cma_audio_mem_addr %pK with size %lu\n", __func__, &phys_addr, size); - desc.phys_addr = phys_addr; - desc.size = size; - ret = scm_call(SCM_SVC_MP, TZBSP_MEM_PROTECT_AUDIO_CMD_ID, - (void *)&desc , sizeof(desc), (void *)&resp, sizeof(resp)); + desc2.args[0] = desc.phys_addr = phys_addr; + desc2.args[1] = desc.size = size; + desc2.arginfo = SCM_ARGS(2); + if (!is_scm_armv8()) { + ret = scm_call(SCM_SVC_MP, TZBSP_MEM_PROTECT_AUDIO_CMD_ID, + (void *)&desc , sizeof(desc), + (void *)&resp, sizeof(resp)); + } else { + ret = scm_call2(SCM_SIP_FNID(SCM_SVC_MP, + TZBSP_MEM_PROTECT_AUDIO_CMD_ID_2), &desc2); + resp.ret = desc2.ret[0]; + } if (ret < 0) pr_err("%s: SCM call failed, scm_call_ret %d tz_resp %d\n", __func__, ret, resp.ret); + if (!is_scm_armv8()) + return ret; + return desc2.ret[0]; } static int msm_audio_ion_probe(struct platform_device *pdev) diff --git a/drivers/spi/spi-davinci.c b/drivers/spi/spi-davinci.c index 63700ab7bd9f..1107a5d5a256 100644 --- a/drivers/spi/spi-davinci.c +++ b/drivers/spi/spi-davinci.c @@ -230,7 +230,7 @@ static void davinci_spi_chipselect(struct spi_device *spi, int value) } /* program delay transfers if tx_delay is non zero */ - if (spicfg->wdelay) + if (spicfg && spicfg->wdelay) spidat1 |= SPIDAT1_WDEL; /* diff --git a/drivers/staging/android/ion/ion.c b/drivers/staging/android/ion/ion.c index a7998777b8cc..80fef8a76026 100644 --- a/drivers/staging/android/ion/ion.c +++ b/drivers/staging/android/ion/ion.c @@ -404,7 +404,8 @@ static void ion_handle_get(struct ion_handle *handle) } /* Must hold the client lock */ -static struct ion_handle* ion_handle_get_check_overflow(struct ion_handle *handle) +static struct ion_handle *ion_handle_get_check_overflow( + struct ion_handle *handle) { if (atomic_read(&handle->ref.refcount) + 1 == 0) return ERR_PTR(-EOVERFLOW); diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c index 10e8a73cee3c..4d158a7134c1 100644 --- a/drivers/staging/android/ion/ion_system_heap.c +++ b/drivers/staging/android/ion/ion_system_heap.c @@ -2,7 +2,7 @@ * drivers/staging/android/ion/ion_system_heap.c * * Copyright (C) 2011 Google, Inc. - * Copyright (c) 2011-2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2011-2018, The Linux Foundation. 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 @@ -619,8 +619,10 @@ static void ion_system_heap_destroy_pools(struct ion_page_pool **pools) { int i; for (i = 0; i < num_orders; i++) - if (pools[i]) + if (pools[i]) { ion_page_pool_destroy(pools[i]); + pools[i] = NULL; + } } /** diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c index 4662e00b456a..62fdd670509c 100644 --- a/drivers/staging/imx-drm/imx-ldb.c +++ b/drivers/staging/imx-drm/imx-ldb.c @@ -460,6 +460,9 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) return PTR_ERR(imx_ldb->regmap); } + /* disable LDB by resetting the control register to POR default */ + regmap_write(imx_ldb->regmap, IOMUXC_GPR2, 0); + imx_ldb->dev = dev; if (of_id) @@ -497,14 +500,14 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) if (ret || i < 0 || i > 1) return -EINVAL; + if (!of_device_is_available(child)) + continue; + if (dual && i > 0) { dev_warn(dev, "dual-channel mode, ignoring second output\n"); continue; } - if (!of_device_is_available(child)) - continue; - channel = &imx_ldb->channel[i]; channel->ldb = imx_ldb; channel->chno = i; diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c index 5d6250337fec..4f84de43de7c 100644 --- a/drivers/staging/media/omap4iss/iss_video.c +++ b/drivers/staging/media/omap4iss/iss_video.c @@ -11,7 +11,6 @@ * (at your option) any later version. */ -#include #include #include #include @@ -22,6 +21,8 @@ #include #include +#include + #include "iss_video.h" #include "iss.h" diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c index a2cc5f834c63..ed18a98a15d8 100644 --- a/drivers/tty/hvc/hvc_opal.c +++ b/drivers/tty/hvc/hvc_opal.c @@ -337,7 +337,6 @@ static void udbg_init_opal_common(void) udbg_putc = udbg_opal_putc; udbg_getc = udbg_opal_getc; udbg_getc_poll = udbg_opal_getc_poll; - tb_ticks_per_usec = 0x200; /* Make udelay not suck */ } void __init hvc_opal_init_early(void) diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index 5222805bfb15..07428642821d 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c @@ -114,16 +114,19 @@ static int pty_space(struct tty_struct *to) static int pty_write(struct tty_struct *tty, const unsigned char *buf, int c) { struct tty_struct *to = tty->link; + unsigned long flags; if (tty->stopped) return 0; if (c > 0) { + spin_lock_irqsave(&to->port->lock, flags); /* Stuff the data into the input queue of the other end */ c = tty_insert_flip_string(to->port, buf, c); /* And shovel */ if (c) tty_flip_buffer_push(to->port); + spin_unlock_irqrestore(&to->port->lock, flags); } return c; } diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 5c247d7943aa..077e0667bbf8 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c @@ -202,7 +202,7 @@ static void dw8250_set_termios(struct uart_port *p, struct ktermios *termios, unsigned int rate; int ret; - if (IS_ERR(d->clk) || !old) + if (IS_ERR(d->clk)) goto out; /* Not requesting clock rates below 1.8432Mhz */ diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index e01d39509172..fabf77fca4ad 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1785,6 +1785,9 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */ .driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */ }, + { USB_DEVICE(0x0ca6, 0xa050), /* Castles VEGA3000 */ + .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ + }, { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */ .driver_info = CLEAR_HALT_CONDITIONS, diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 20000128b06c..1791e6d68f12 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -643,18 +643,21 @@ void usb_destroy_configuration(struct usb_device *dev) return; if (dev->rawdescriptors) { - for (i = 0; i < dev->descriptor.bNumConfigurations; i++) + for (i = 0; i < dev->descriptor.bNumConfigurations && + i < USB_MAXCONFIG; i++) kfree(dev->rawdescriptors[i]); kfree(dev->rawdescriptors); dev->rawdescriptors = NULL; } - for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { + for (c = 0; c < dev->descriptor.bNumConfigurations && + c < USB_MAXCONFIG; c++) { struct usb_host_config *cf = &dev->config[c]; kfree(cf->string); - for (i = 0; i < cf->desc.bNumInterfaces; i++) { + for (i = 0; i < cf->desc.bNumInterfaces && + i < USB_MAXINTERFACES; i++) { if (cf->intf_cache[i]) kref_put(&cf->intf_cache[i]->ref, usb_release_interface_cache); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index b5e5e5911a6f..e5d045756a8b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1201,10 +1201,14 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) if (!udev || udev->state == USB_STATE_NOTATTACHED) { /* Tell hub_wq to disconnect the device or - * check for a new connection + * check for a new connection or over current condition. + * Based on USB2.0 Spec Section 11.12.5, + * C_PORT_OVER_CURRENT could be set while + * PORT_OVER_CURRENT is not. So check for any of them. */ if (udev || (portstatus & USB_PORT_STAT_CONNECTION) || - (portstatus & USB_PORT_STAT_OVERCURRENT)) + (portstatus & USB_PORT_STAT_OVERCURRENT) || + (portchange & USB_PORT_STAT_C_OVERCURRENT)) set_bit(port1, hub->change_bits); } else if (portstatus & USB_PORT_STAT_ENABLE) { @@ -3337,6 +3341,10 @@ static int wait_for_ss_port_enable(struct usb_device *udev, while (delay_ms < 2000) { if (status || *portstatus & USB_PORT_STAT_CONNECTION) break; + if (!port_is_power_on(hub, *portstatus)) { + status = -ENODEV; + break; + } msleep(20); delay_ms += 20; status = hub_port_status(hub, *port1, portstatus, portchange); diff --git a/drivers/usb/dwc2/hcd_intr.c b/drivers/usb/dwc2/hcd_intr.c index 551ba878b003..e1675ea36a63 100644 --- a/drivers/usb/dwc2/hcd_intr.c +++ b/drivers/usb/dwc2/hcd_intr.c @@ -913,9 +913,8 @@ static int dwc2_xfercomp_isoc_split_in(struct dwc2_hsotg *hsotg, frame_desc = &qtd->urb->iso_descs[qtd->isoc_frame_index]; len = dwc2_get_actual_xfer_length(hsotg, chan, chnum, qtd, DWC2_HC_XFER_COMPLETE, NULL); - if (!len) { + if (!len && !qtd->isoc_split_offset) { qtd->complete_split = 0; - qtd->isoc_split_offset = 0; return 0; } diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index e216c58779cf..af4e2f204a30 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1761,6 +1761,8 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) value = 0; break; } + + spin_lock(&cdev->lock); value = f->set_alt(f, w_index, w_value); if (value == USB_GADGET_DELAYED_STATUS) { DBG(cdev, @@ -1770,6 +1772,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) DBG(cdev, "delayed_status count %d\n", cdev->delayed_status); } + spin_unlock(&cdev->lock); break; case USB_REQ_GET_INTERFACE: if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 424e2902423b..9d87c172bc3c 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -3175,7 +3175,7 @@ static int ffs_func_setup(struct usb_function *f, __ffs_event_add(ffs, FUNCTIONFS_SETUP); spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); - return USB_GADGET_DELAYED_STATUS; + return creq->wLength == 0 ? USB_GADGET_DELAYED_STATUS : 0; } static void ffs_func_suspend(struct usb_function *f) diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c index f8186613b53e..4848607b0798 100644 --- a/drivers/usb/gadget/udc/r8a66597-udc.c +++ b/drivers/usb/gadget/udc/r8a66597-udc.c @@ -835,11 +835,11 @@ static void init_controller(struct r8a66597 *r8a66597) r8a66597_bset(r8a66597, XCKE, SYSCFG0); - msleep(3); + mdelay(3); r8a66597_bset(r8a66597, PLLC, SYSCFG0); - msleep(1); + mdelay(1); r8a66597_bset(r8a66597, SCKE, SYSCFG0); @@ -1193,7 +1193,7 @@ __acquires(r8a66597->lock) r8a66597->ep0_req->length = 2; /* AV: what happens if we get called again before that gets through? */ spin_unlock(&r8a66597->lock); - r8a66597_queue(r8a66597->gadget.ep0, r8a66597->ep0_req, GFP_KERNEL); + r8a66597_queue(r8a66597->gadget.ep0, r8a66597->ep0_req, GFP_ATOMIC); spin_lock(&r8a66597->lock); } diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c index f1ea5990a50a..c9c5b539eb5e 100644 --- a/drivers/usb/phy/phy-fsl-usb.c +++ b/drivers/usb/phy/phy-fsl-usb.c @@ -913,6 +913,7 @@ int usb_otg_start(struct platform_device *pdev) if (pdata->init && pdata->init(pdev) != 0) return -EINVAL; +#ifdef CONFIG_PPC32 if (pdata->big_endian_mmio) { _fsl_readl = _fsl_readl_be; _fsl_writel = _fsl_writel_be; @@ -920,6 +921,7 @@ int usb_otg_start(struct platform_device *pdev) _fsl_readl = _fsl_readl_le; _fsl_writel = _fsl_writel_le; } +#endif /* request irq */ p_otg->irq = platform_get_irq(pdev, 0); @@ -1010,7 +1012,7 @@ int usb_otg_start(struct platform_device *pdev) /* * state file in sysfs */ -static int show_fsl_usb2_otg_state(struct device *dev, +static ssize_t show_fsl_usb2_otg_state(struct device *dev, struct device_attribute *attr, char *buf) { struct otg_fsm *fsm = &fsl_otg_dev->fsm; diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 46179a0828eb..493c3679620a 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -789,9 +789,9 @@ static void sierra_close(struct usb_serial_port *port) kfree(urb->transfer_buffer); usb_free_urb(urb); usb_autopm_put_interface_async(serial->interface); - spin_lock(&portdata->lock); + spin_lock_irq(&portdata->lock); portdata->outstanding_urbs--; - spin_unlock(&portdata->lock); + spin_unlock_irq(&portdata->lock); } sierra_stop_rx_urbs(port); diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c index 9474917de74d..34148637548c 100644 --- a/drivers/video/fbdev/core/fbmem.c +++ b/drivers/video/fbdev/core/fbmem.c @@ -1731,12 +1731,12 @@ static int do_register_framebuffer(struct fb_info *fb_info) return 0; } -static int do_unregister_framebuffer(struct fb_info *fb_info) +static int unbind_console(struct fb_info *fb_info) { struct fb_event event; - int i, ret = 0; + int ret; + int i = fb_info->node; - i = fb_info->node; if (i < 0 || i >= FB_MAX || registered_fb[i] != fb_info) return -EINVAL; @@ -1751,17 +1751,29 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) unlock_fb_info(fb_info); console_unlock(); + return ret; +} + +static int __unlink_framebuffer(struct fb_info *fb_info); + +static int do_unregister_framebuffer(struct fb_info *fb_info) +{ + struct fb_event event; + int ret; + + ret = unbind_console(fb_info); + if (ret) return -EINVAL; pm_vt_switch_unregister(fb_info->dev); - unlink_framebuffer(fb_info); + __unlink_framebuffer(fb_info); if (fb_info->pixmap.addr && (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) kfree(fb_info->pixmap.addr); fb_destroy_modelist(&fb_info->modelist); - registered_fb[i] = NULL; + registered_fb[fb_info->node] = NULL; num_registered_fb--; fb_cleanup_device(fb_info); event.info = fb_info; @@ -1774,7 +1786,7 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) return 0; } -int unlink_framebuffer(struct fb_info *fb_info) +static int __unlink_framebuffer(struct fb_info *fb_info) { int i; @@ -1786,6 +1798,20 @@ int unlink_framebuffer(struct fb_info *fb_info) device_destroy(fb_class, MKDEV(FB_MAJOR, i)); fb_info->dev = NULL; } + + return 0; +} + +int unlink_framebuffer(struct fb_info *fb_info) +{ + int ret; + + ret = __unlink_framebuffer(fb_info); + if (ret) + return ret; + + unbind_console(fb_info); + return 0; } EXPORT_SYMBOL(unlink_framebuffer); diff --git a/drivers/video/msm/mdss/mdss_compat_utils.c b/drivers/video/msm/mdss/mdss_compat_utils.c index 558c2d7c1dde..7a93d292a6da 100644 --- a/drivers/video/msm/mdss/mdss_compat_utils.c +++ b/drivers/video/msm/mdss/mdss_compat_utils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * Copyright (C) 1994 Martin Schaller * * 2001 - Documented with DocBook @@ -2878,26 +2878,28 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, *pp = compat_alloc_user_space(alloc_size); if (NULL == *pp) return -ENOMEM; - memset(*pp, 0, alloc_size); - - (*pp)->data.lut_cfg_data.data.pgc_lut_data.r_data = - (struct mdp_ar_gc_lut_data *) - ((unsigned long) *pp + - sizeof(struct msmfb_mdp_pp)); - (*pp)->data.lut_cfg_data.data.pgc_lut_data.g_data = - (struct mdp_ar_gc_lut_data *) + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((struct mdp_ar_gc_lut_data *) + ((unsigned long) *pp + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.lut_cfg_data.data.pgc_lut_data.r_data) || + put_user((struct mdp_ar_gc_lut_data *) ((unsigned long) *pp + sizeof(struct msmfb_mdp_pp) + - pgc_size); - (*pp)->data.lut_cfg_data.data.pgc_lut_data.b_data = - (struct mdp_ar_gc_lut_data *) + pgc_size), + &(*pp)->data.lut_cfg_data.data.pgc_lut_data.g_data) || + put_user((struct mdp_ar_gc_lut_data *) ((unsigned long) *pp + sizeof(struct msmfb_mdp_pp) + - (2 * pgc_size)); - (*pp)->data.lut_cfg_data.data.pgc_lut_data.cfg_payload - = (void *)((unsigned long) *pp + + (2 * pgc_size)), + &(*pp)->data.lut_cfg_data.data.pgc_lut_data.b_data) || + put_user((void *)((unsigned long) *pp + sizeof(struct msmfb_mdp_pp) + - (3 * pgc_size)); + (3 * pgc_size)), + &(*pp)->data.lut_cfg_data.data. + pgc_lut_data.cfg_payload)) + return -EFAULT; break; case mdp_lut_igc: alloc_size += __pp_compat_size_igc(); @@ -2907,10 +2909,13 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.lut_cfg_data.data.igc_lut_data.cfg_payload - = (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.lut_cfg_data.data. + igc_lut_data.cfg_payload)) + return -EFAULT; break; case mdp_lut_hist: alloc_size += __pp_compat_size_hist_lut(); @@ -2920,10 +2925,13 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.lut_cfg_data.data.hist_lut_data.cfg_payload - = (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.lut_cfg_data.data. + hist_lut_data.cfg_payload)) + return -EFAULT; break; default: *pp = compat_alloc_user_space(alloc_size); @@ -2932,7 +2940,8 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size, lut_type); return -ENOMEM; } - memset(*pp, 0, alloc_size); + if (clear_user(*pp, alloc_size)) + return -EFAULT; break; } break; @@ -2944,10 +2953,12 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.pcc_cfg_data.cfg_payload = - (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.pcc_cfg_data.cfg_payload)) + return -EFAULT; break; case mdp_op_gamut_cfg: alloc_size += __pp_compat_size_gamut(); @@ -2957,10 +2968,12 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.gamut_cfg_data.cfg_payload = - (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.gamut_cfg_data.cfg_payload)) + return -EFAULT; break; case mdp_op_pa_v2_cfg: alloc_size += __pp_compat_size_pa(); @@ -2970,16 +2983,19 @@ static int __pp_compat_alloc(struct msmfb_mdp_pp32 __user *pp32, alloc_size); return -ENOMEM; } - memset(*pp, 0, alloc_size); - (*pp)->data.pa_v2_cfg_data.cfg_payload = - (void *)((unsigned long)(*pp) + - sizeof(struct msmfb_mdp_pp)); + if (clear_user(*pp, alloc_size)) + return -EFAULT; + if (put_user((void *)((unsigned long)(*pp) + + sizeof(struct msmfb_mdp_pp)), + &(*pp)->data.pa_v2_cfg_data.cfg_payload)) + return -EFAULT; break; default: *pp = compat_alloc_user_space(alloc_size); if (NULL == *pp) return -ENOMEM; - memset(*pp, 0, alloc_size); + if (clear_user(*pp, alloc_size)) + return -EFAULT; break; } return 0; @@ -3397,7 +3413,9 @@ static int mdss_histo_compat_ioctl(struct fb_info *info, unsigned int cmd, sizeof(struct mdp_histogram_start_req)); return -EINVAL; } - memset(hist_req, 0, sizeof(struct mdp_histogram_start_req)); + if (clear_user(hist_req, + sizeof(struct mdp_histogram_start_req))) + return -EFAULT; ret = __from_user_hist_start_req(hist_req32, hist_req); if (ret) goto histo_compat_err; @@ -3417,7 +3435,8 @@ static int mdss_histo_compat_ioctl(struct fb_info *info, unsigned int cmd, sizeof(struct mdp_histogram_data)); return -EINVAL; } - memset(hist, 0, sizeof(struct mdp_histogram_data)); + if (clear_user(hist, sizeof(struct mdp_histogram_data))) + return -EFAULT; ret = __from_user_hist_data(hist32, hist); if (ret) goto histo_compat_err; @@ -3920,7 +3939,7 @@ static int __to_user_mdp_overlay(struct mdp_overlay32 __user *ov32, } -static int __from_user_mdp_overlay(struct mdp_overlay *ov, +static int __from_user_mdp_overlay(struct mdp_overlay __user *ov, struct mdp_overlay32 __user *ov32) { __u32 data; @@ -3979,12 +3998,12 @@ static int __from_user_mdp_overlay(struct mdp_overlay *ov, return 0; } -static int __from_user_mdp_overlaylist(struct mdp_overlay_list *ovlist, - struct mdp_overlay_list32 *ovlist32, +static int __from_user_mdp_overlaylist(struct mdp_overlay_list __user *ovlist, + struct mdp_overlay_list32 __user *ovlist32, struct mdp_overlay **to_list_head) { __u32 i, ret; - unsigned long data, from_list_head; + unsigned long data, from_list_head, num_overlays; struct mdp_overlay32 *iter; if (!to_list_head || !ovlist32 || !ovlist) { @@ -4005,11 +4024,13 @@ static int __from_user_mdp_overlaylist(struct mdp_overlay_list *ovlist, sizeof(ovlist32->processed_overlays))) return -EFAULT; - if (get_user(data, &ovlist32->overlay_list)) { + if (get_user(data, &ovlist32->overlay_list) || + get_user(num_overlays, &ovlist32->num_overlays)) { ret = -EFAULT; goto validate_exit; } - for (i = 0; i < ovlist32->num_overlays; i++) { + + for (i = 0; i < num_overlays; i++) { if (get_user(from_list_head, (__u32 *)data + i)) { ret = -EFAULT; goto validate_exit; @@ -4022,7 +4043,8 @@ static int __from_user_mdp_overlaylist(struct mdp_overlay_list *ovlist, goto validate_exit; } } - ovlist->overlay_list = to_list_head; + if (put_user(to_list_head, &ovlist->overlay_list)) + return -EFAULT; return 0; @@ -4031,8 +4053,8 @@ static int __from_user_mdp_overlaylist(struct mdp_overlay_list *ovlist, return -EFAULT; } -static int __to_user_mdp_overlaylist(struct mdp_overlay_list32 *ovlist32, - struct mdp_overlay_list *ovlist, +static int __to_user_mdp_overlaylist(struct mdp_overlay_list32 __user *ovlist32, + struct mdp_overlay_list __user *ovlist, struct mdp_overlay **l_ptr) { __u32 i, ret; @@ -4105,31 +4127,33 @@ static u32 __pp_sspp_size(void) return size; } -static int __pp_sspp_set_offsets(struct mdp_overlay *ov) +static int __pp_sspp_set_offsets(struct mdp_overlay __user *ov) { if (!ov) { pr_err("invalid overlay pointer\n"); return -EFAULT; } - ov->overlay_pp_cfg.igc_cfg.cfg_payload = (void *)((unsigned long)ov + - sizeof(struct mdp_overlay)); - ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload = - ov->overlay_pp_cfg.igc_cfg.cfg_payload + - sizeof(struct mdp_igc_lut_data_v1_7); - ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload = - ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload + - sizeof(struct mdp_pa_data_v1_7); - ov->overlay_pp_cfg.hist_lut_cfg.cfg_payload = - ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload + - sizeof(struct mdp_pcc_data_v1_7); + if (put_user((void *)((unsigned long)ov + sizeof(struct mdp_overlay)), + &(ov->overlay_pp_cfg.igc_cfg.cfg_payload)) || + put_user(ov->overlay_pp_cfg.igc_cfg.cfg_payload + + sizeof(struct mdp_igc_lut_data_v1_7), + &(ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload)) || + put_user(ov->overlay_pp_cfg.pa_v2_cfg_data.cfg_payload + + sizeof(struct mdp_pa_data_v1_7), + &(ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload)) || + put_user(ov->overlay_pp_cfg.pcc_cfg_data.cfg_payload + + sizeof(struct mdp_pcc_data_v1_7), + &(ov->overlay_pp_cfg.hist_lut_cfg.cfg_payload))) + return -EFAULT; return 0; } int mdss_compat_overlay_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg, struct file *file) { - struct mdp_overlay *ov, **layers_head; - struct mdp_overlay32 *ov32; + struct mdp_overlay **layers_head; + struct mdp_overlay __user *ov; + struct mdp_overlay32 __user *ov32; struct mdp_overlay_list __user *ovlist; struct mdp_overlay_list32 __user *ovlist32; size_t layers_refs_sz, layers_sz, prepare_sz; diff --git a/drivers/video/msm/mdss/mdss_dsi_host.c b/drivers/video/msm/mdss/mdss_dsi_host.c index 799a4e6ce371..9f28380b151b 100644 --- a/drivers/video/msm/mdss/mdss_dsi_host.c +++ b/drivers/video/msm/mdss/mdss_dsi_host.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -2104,7 +2104,7 @@ static int mdss_dsi_cmd_dma_tx(struct mdss_dsi_ctrl_pdata *ctrl, /* clear CMD DMA and BTA_DONE isr only */ reg_val |= (DSI_INTR_CMD_DMA_DONE | DSI_INTR_BTA_DONE); MIPI_OUTP(ctrl->ctrl_base + 0x0110, reg_val); - mdss_dsi_disable_irq_nosync(ctrl, DSI_CMD_TERM); + mdss_dsi_disable_irq(ctrl, DSI_CMD_TERM); complete(&ctrl->dma_comp); pr_warn("%s: dma tx done but irq not triggered\n", diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index 771d9e76fcc1..5bad60a6dadd 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -416,7 +416,9 @@ static int virtballoon_migratepage(struct balloon_dev_info *vb_dev_info, tell_host(vb, vb->inflate_vq); /* balloon's page migration 2nd step -- deflate "page" */ + spin_lock_irqsave(&vb_dev_info->pages_lock, flags); balloon_page_delete(page); + spin_unlock_irqrestore(&vb_dev_info->pages_lock, flags); vb->num_pfns = VIRTIO_BALLOON_PAGES_PER_PAGE; set_page_pfns(vb->pfns, page); tell_host(vb, vb->deflate_vq); diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 3f5fc150c2b7..b2937b645b62 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c @@ -4281,7 +4281,7 @@ static int flush_space(struct btrfs_root *root, break; } - return ret; + return 0; } static inline u64 diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index e12f189d539b..80ed75bde04a 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -193,7 +193,6 @@ static int cachefiles_mark_object_active(struct cachefiles_cache *cache, pr_err("\n"); pr_err("Error: Unexpected object collision\n"); cachefiles_printk_object(object, xobject); - BUG(); } atomic_inc(&xobject->usage); write_unlock(&cache->active_lock); diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 616db0e77b44..a899e69cd5fd 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c @@ -27,6 +27,7 @@ static int cachefiles_read_waiter(wait_queue_t *wait, unsigned mode, struct cachefiles_one_read *monitor = container_of(wait, struct cachefiles_one_read, monitor); struct cachefiles_object *object; + struct fscache_retrieval *op = monitor->op; struct wait_bit_key *key = _key; struct page *page = wait->private; @@ -51,16 +52,22 @@ static int cachefiles_read_waiter(wait_queue_t *wait, unsigned mode, list_del(&wait->task_list); /* move onto the action list and queue for FS-Cache thread pool */ - ASSERT(monitor->op); + ASSERT(op); - object = container_of(monitor->op->op.object, - struct cachefiles_object, fscache); + /* We need to temporarily bump the usage count as we don't own a ref + * here otherwise cachefiles_read_copier() may free the op between the + * monitor being enqueued on the op->to_do list and the op getting + * enqueued on the work queue. + */ + fscache_get_retrieval(op); + object = container_of(op->op.object, struct cachefiles_object, fscache); spin_lock(&object->work_lock); - list_add_tail(&monitor->op_link, &monitor->op->to_do); + list_add_tail(&monitor->op_link, &op->to_do); spin_unlock(&object->work_lock); - fscache_enqueue_retrieval(monitor->op); + fscache_enqueue_retrieval(op); + fscache_put_retrieval(op); return 0; } diff --git a/fs/dcache.c b/fs/dcache.c index c99ef9daa6b3..233acac6750a 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1850,10 +1850,12 @@ struct dentry *d_make_root(struct inode *root_inode) static const struct qstr name = QSTR_INIT("/", 1); res = __d_alloc(root_inode->i_sb, &name); - if (res) + if (res) { + res->d_flags |= DCACHE_RCUACCESS; d_instantiate(res, root_inode); - else + } else { iput(root_inode); + } } return res; } diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 5834799733ff..1d29039dc85c 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1391,6 +1391,7 @@ static struct buffer_head * ext4_find_entry (struct inode *dir, goto cleanup_and_exit; dxtrace(printk(KERN_DEBUG "ext4_find_entry: dx failed, " "falling back\n")); + ret = NULL; } nblocks = dir->i_size >> EXT4_BLOCK_SIZE_BITS(sb); if (!nblocks) { diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 75b5a159d607..3df305d6783c 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -610,13 +610,21 @@ static void fat_set_state(struct super_block *sb, brelse(bh); } +static void fat_reset_iocharset(struct fat_mount_options *opts) +{ + if (opts->iocharset != fat_default_iocharset) { + /* Note: opts->iocharset can be NULL here */ + kfree(opts->iocharset); + opts->iocharset = fat_default_iocharset; + } +} + static void delayed_free(struct rcu_head *p) { struct msdos_sb_info *sbi = container_of(p, struct msdos_sb_info, rcu); unload_nls(sbi->nls_disk); unload_nls(sbi->nls_io); - if (sbi->options.iocharset != fat_default_iocharset) - kfree(sbi->options.iocharset); + fat_reset_iocharset(&sbi->options); kfree(sbi); } @@ -1031,7 +1039,7 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, opts->fs_fmask = opts->fs_dmask = current_umask(); opts->allow_utime = -1; opts->codepage = fat_default_codepage; - opts->iocharset = fat_default_iocharset; + fat_reset_iocharset(opts); if (is_vfat) { opts->shortname = VFAT_SFN_DISPLAY_WINNT|VFAT_SFN_CREATE_WIN95; opts->rodir = 0; @@ -1181,8 +1189,7 @@ static int parse_options(struct super_block *sb, char *options, int is_vfat, /* vfat specific */ case Opt_charset: - if (opts->iocharset != fat_default_iocharset) - kfree(opts->iocharset); + fat_reset_iocharset(opts); iocharset = match_strdup(&args[0]); if (!iocharset) return -ENOMEM; @@ -1774,8 +1781,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, int isvfat, iput(fat_inode); unload_nls(sbi->nls_io); unload_nls(sbi->nls_disk); - if (sbi->options.iocharset != fat_default_iocharset) - kfree(sbi->options.iocharset); + fat_reset_iocharset(&sbi->options); sb->s_fs_info = NULL; kfree(sbi); return error; diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c index e7b87a0e5185..deac2e89d176 100644 --- a/fs/fscache/operation.c +++ b/fs/fscache/operation.c @@ -37,7 +37,8 @@ void fscache_enqueue_operation(struct fscache_operation *op) ASSERT(op->processor != NULL); ASSERT(fscache_object_is_available(op->object)); ASSERTCMP(atomic_read(&op->usage), >, 0); - ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS); + ASSERTIFCMP(op->state != FSCACHE_OP_ST_IN_PROGRESS, + op->state, ==, FSCACHE_OP_ST_CANCELLED); fscache_stat(&fscache_n_op_enqueue); switch (op->flags & FSCACHE_OP_TYPE) { @@ -401,7 +402,8 @@ void fscache_put_operation(struct fscache_operation *op) struct fscache_cache *cache; _enter("{OBJ%x OP%x,%d}", - op->object->debug_id, op->debug_id, atomic_read(&op->usage)); + op->object ? op->object->debug_id : 0, + op->debug_id, atomic_read(&op->usage)); ASSERTCMP(atomic_read(&op->usage), >, 0); diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a5a95a058ea2..d49d63c3be9b 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1925,11 +1925,14 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe, if (!fc) return -EPERM; + pipe_lock(pipe); + bufs = kmalloc(pipe->buffers * sizeof(struct pipe_buffer), GFP_KERNEL); - if (!bufs) + if (!bufs) { + pipe_unlock(pipe); return -ENOMEM; + } - pipe_lock(pipe); nbuf = 0; rem = 0; for (idx = 0; idx < pipe->nrbufs && rem < len; idx++) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index cccc217dbab4..a8e3026e6f7b 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -926,6 +926,7 @@ static int fuse_readpages_fill(void *_data, struct page *page) } if (WARN_ON(req->num_pages >= req->max_pages)) { + unlock_page(page); fuse_put_request(fc, req); return -EIO; } diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c index 46325d5c34fc..405e8c42cb1a 100644 --- a/fs/jfs/xattr.c +++ b/fs/jfs/xattr.c @@ -493,15 +493,17 @@ static int ea_get(struct inode *inode, struct ea_buffer *ea_buf, int min_size) if (size > PSIZE) { /* * To keep the rest of the code simple. Allocate a - * contiguous buffer to work with + * contiguous buffer to work with. Make the buffer large + * enough to make use of the whole extent. */ - ea_buf->xattr = kmalloc(size, GFP_KERNEL); + ea_buf->max_size = (size + sb->s_blocksize - 1) & + ~(sb->s_blocksize - 1); + + ea_buf->xattr = kmalloc(ea_buf->max_size, GFP_KERNEL); if (ea_buf->xattr == NULL) return -ENOMEM; ea_buf->flag = EA_MALLOC; - ea_buf->max_size = (size + sb->s_blocksize - 1) & - ~(sb->s_blocksize - 1); if (ea_size == 0) return 0; diff --git a/fs/namespace.c b/fs/namespace.c index 214780c5e541..de824e10ec46 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -592,12 +592,21 @@ bool legitimize_mnt(struct vfsmount *bastard, unsigned seq) return true; mnt = real_mount(bastard); mnt_add_count(mnt, 1); + smp_mb(); // see mntput_no_expire() if (likely(!read_seqretry(&mount_lock, seq))) return true; if (bastard->mnt_flags & MNT_SYNC_UMOUNT) { mnt_add_count(mnt, -1); return false; } + lock_mount_hash(); + if (unlikely(bastard->mnt_flags & MNT_DOOMED)) { + mnt_add_count(mnt, -1); + unlock_mount_hash(); + return true; + } + unlock_mount_hash(); + rcu_read_unlock(); mntput(bastard); rcu_read_lock(); @@ -1067,12 +1076,27 @@ static DECLARE_DELAYED_WORK(delayed_mntput_work, delayed_mntput); static void mntput_no_expire(struct mount *mnt) { rcu_read_lock(); - mnt_add_count(mnt, -1); - if (likely(mnt->mnt_ns)) { /* shouldn't be the last one */ + if (likely(READ_ONCE(mnt->mnt_ns))) { + /* + * Since we don't do lock_mount_hash() here, + * ->mnt_ns can change under us. However, if it's + * non-NULL, then there's a reference that won't + * be dropped until after an RCU delay done after + * turning ->mnt_ns NULL. So if we observe it + * non-NULL under rcu_read_lock(), the reference + * we are dropping is not the final one. + */ + mnt_add_count(mnt, -1); rcu_read_unlock(); return; } lock_mount_hash(); + /* + * make sure that if __legitimize_mnt() has not seen us grab + * mount_lock, we'll see their refcount increment here. + */ + smp_mb(); + mnt_add_count(mnt, -1); if (mnt_get_count(mnt)) { rcu_read_unlock(); unlock_mount_hash(); diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c index 5aed4f98df41..00727659e439 100644 --- a/fs/nfs/blocklayout/dev.c +++ b/fs/nfs/blocklayout/dev.c @@ -157,7 +157,7 @@ static bool bl_map_stripe(struct pnfs_block_dev *dev, u64 offset, chunk = div_u64(offset, dev->chunk_size); div_u64_rem(chunk, dev->nr_children, &chunk_idx); - if (chunk_idx > dev->nr_children) { + if (chunk_idx >= dev->nr_children) { dprintk("%s: invalid chunk idx %d (%lld/%lld)\n", __func__, chunk_idx, offset, dev->chunk_size); /* error, should not happen */ diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index 7c36898af402..59b29acb6419 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c @@ -842,8 +842,10 @@ static int listxattr_filler(void *buf, const char *name, int namelen, size = handler->list(b->dentry, b->buf + b->pos, b->size, name, namelen, handler->flags); - if (size > b->size) + if (b->pos + size > b->size) { + b->pos = -ERANGE; return -ERANGE; + } } else { size = handler->list(b->dentry, NULL, 0, name, namelen, handler->flags); diff --git a/fs/squashfs/cache.c b/fs/squashfs/cache.c index 6785d086ab38..7d78c3d28bbd 100644 --- a/fs/squashfs/cache.c +++ b/fs/squashfs/cache.c @@ -340,6 +340,9 @@ int squashfs_read_metadata(struct super_block *sb, void *buffer, TRACE("Entered squashfs_read_metadata [%llx:%x]\n", *block, *offset); + if (unlikely(length < 0)) + return -EIO; + while (length) { entry = squashfs_cache_get(sb, msblk->block_cache, *block, 0); if (entry->error) { diff --git a/fs/squashfs/file.c b/fs/squashfs/file.c index d778763de26e..a61632c9ad68 100644 --- a/fs/squashfs/file.c +++ b/fs/squashfs/file.c @@ -198,7 +198,11 @@ static long long read_indexes(struct super_block *sb, int n, } for (i = 0; i < blocks; i++) { - int size = le32_to_cpu(blist[i]); + int size = squashfs_block_size(blist[i]); + if (size < 0) { + err = size; + goto failure; + } block += SQUASHFS_COMPRESSED_SIZE_BLOCK(size); } n -= blocks; @@ -371,7 +375,7 @@ static int read_blocklist(struct inode *inode, int index, u64 *block) sizeof(size)); if (res < 0) return res; - return le32_to_cpu(size); + return squashfs_block_size(size); } /* Copy data into page cache */ diff --git a/fs/squashfs/fragment.c b/fs/squashfs/fragment.c index 0ed6edbc5c71..0681feab4a84 100644 --- a/fs/squashfs/fragment.c +++ b/fs/squashfs/fragment.c @@ -49,11 +49,16 @@ int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment, u64 *fragment_block) { struct squashfs_sb_info *msblk = sb->s_fs_info; - int block = SQUASHFS_FRAGMENT_INDEX(fragment); - int offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); - u64 start_block = le64_to_cpu(msblk->fragment_index[block]); + int block, offset, size; struct squashfs_fragment_entry fragment_entry; - int size; + u64 start_block; + + if (fragment >= msblk->fragments) + return -EIO; + block = SQUASHFS_FRAGMENT_INDEX(fragment); + offset = SQUASHFS_FRAGMENT_INDEX_OFFSET(fragment); + + start_block = le64_to_cpu(msblk->fragment_index[block]); size = squashfs_read_metadata(sb, &fragment_entry, &start_block, &offset, sizeof(fragment_entry)); @@ -61,9 +66,7 @@ int squashfs_frag_lookup(struct super_block *sb, unsigned int fragment, return size; *fragment_block = le64_to_cpu(fragment_entry.start_block); - size = le32_to_cpu(fragment_entry.size); - - return size; + return squashfs_block_size(fragment_entry.size); } diff --git a/fs/squashfs/squashfs_fs.h b/fs/squashfs/squashfs_fs.h index 506f4ba5b983..e66486366f02 100644 --- a/fs/squashfs/squashfs_fs.h +++ b/fs/squashfs/squashfs_fs.h @@ -129,6 +129,12 @@ #define SQUASHFS_COMPRESSED_BLOCK(B) (!((B) & SQUASHFS_COMPRESSED_BIT_BLOCK)) +static inline int squashfs_block_size(__le32 raw) +{ + u32 size = le32_to_cpu(raw); + return (size >> 25) ? -EIO : size; +} + /* * Inode number ops. Inodes consist of a compressed block number, and an * uncompressed offset within that block diff --git a/fs/squashfs/squashfs_fs_sb.h b/fs/squashfs/squashfs_fs_sb.h index 8a6995de0277..3b767ce1e46d 100644 --- a/fs/squashfs/squashfs_fs_sb.h +++ b/fs/squashfs/squashfs_fs_sb.h @@ -75,6 +75,7 @@ struct squashfs_sb_info { unsigned short block_log; long long bytes_used; unsigned int inodes; + unsigned int fragments; int xattr_ids; }; #endif diff --git a/fs/squashfs/super.c b/fs/squashfs/super.c index 61cd0b39ed0e..4ffbddb688aa 100644 --- a/fs/squashfs/super.c +++ b/fs/squashfs/super.c @@ -176,6 +176,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) msblk->inode_table = le64_to_cpu(sblk->inode_table_start); msblk->directory_table = le64_to_cpu(sblk->directory_table_start); msblk->inodes = le32_to_cpu(sblk->inodes); + msblk->fragments = le32_to_cpu(sblk->fragments); flags = le16_to_cpu(sblk->flags); TRACE("Found valid superblock on %s\n", bdevname(sb->s_bdev, b)); @@ -186,7 +187,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) TRACE("Filesystem size %lld bytes\n", msblk->bytes_used); TRACE("Block size %d\n", msblk->block_size); TRACE("Number of inodes %d\n", msblk->inodes); - TRACE("Number of fragments %d\n", le32_to_cpu(sblk->fragments)); + TRACE("Number of fragments %d\n", msblk->fragments); TRACE("Number of ids %d\n", le16_to_cpu(sblk->no_ids)); TRACE("sblk->inode_table_start %llx\n", msblk->inode_table); TRACE("sblk->directory_table_start %llx\n", msblk->directory_table); @@ -273,7 +274,7 @@ static int squashfs_fill_super(struct super_block *sb, void *data, int silent) sb->s_export_op = &squashfs_export_ops; handle_fragments: - fragments = le32_to_cpu(sblk->fragments); + fragments = msblk->fragments; if (fragments == 0) goto check_directory_table; diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index e9ef59b3abb1..154a4a953887 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -356,6 +356,50 @@ int sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, } EXPORT_SYMBOL_GPL(sysfs_chmod_file); +/** + * sysfs_break_active_protection - break "active" protection + * @kobj: The kernel object @attr is associated with. + * @attr: The attribute to break the "active" protection for. + * + * With sysfs, just like kernfs, deletion of an attribute is postponed until + * all active .show() and .store() callbacks have finished unless this function + * is called. Hence this function is useful in methods that implement self + * deletion. + */ +struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj, + const struct attribute *attr) +{ + struct kernfs_node *kn; + + kobject_get(kobj); + kn = kernfs_find_and_get(kobj->sd, attr->name); + if (kn) + kernfs_break_active_protection(kn); + return kn; +} +EXPORT_SYMBOL_GPL(sysfs_break_active_protection); + +/** + * sysfs_unbreak_active_protection - restore "active" protection + * @kn: Pointer returned by sysfs_break_active_protection(). + * + * Undo the effects of sysfs_break_active_protection(). Since this function + * calls kernfs_put() on the kernfs node that corresponds to the 'attr' + * argument passed to sysfs_break_active_protection() that attribute may have + * been removed between the sysfs_break_active_protection() and + * sysfs_unbreak_active_protection() calls, it is not safe to access @kn after + * this function has returned. + */ +void sysfs_unbreak_active_protection(struct kernfs_node *kn) +{ + struct kobject *kobj = kn->parent->priv; + + kernfs_unbreak_active_protection(kn); + kernfs_put(kn); + kobject_put(kobj); +} +EXPORT_SYMBOL_GPL(sysfs_unbreak_active_protection); + /** * sysfs_remove_file_ns - remove an object attribute with a custom ns tag * @kobj: object we're acting for diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c index ff53c030c5f7..08b7d288d192 100644 --- a/fs/ubifs/journal.c +++ b/fs/ubifs/journal.c @@ -661,6 +661,11 @@ int ubifs_jnl_update(struct ubifs_info *c, const struct inode *dir, spin_lock(&ui->ui_lock); ui->synced_i_size = ui->ui_size; spin_unlock(&ui->ui_lock); + if (xent) { + spin_lock(&host_ui->ui_lock); + host_ui->synced_i_size = host_ui->ui_size; + spin_unlock(&host_ui->ui_lock); + } mark_inode_clean(c, ui); mark_inode_clean(c, host_ui); return 0; @@ -1107,7 +1112,7 @@ static int recomp_data_node(const struct ubifs_info *c, int err, len, compr_type, out_len; out_len = le32_to_cpu(dn->size); - buf = kmalloc_array(out_len, WORST_COMPR_FACTOR, GFP_NOFS); + buf = kmalloc(out_len * WORST_COMPR_FACTOR, GFP_NOFS); if (!buf) return -ENOMEM; diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c index a0011aa3a779..f43f162e36f4 100644 --- a/fs/ubifs/lprops.c +++ b/fs/ubifs/lprops.c @@ -1091,10 +1091,6 @@ static int scan_check_cb(struct ubifs_info *c, } } - buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); - if (!buf) - return -ENOMEM; - /* * After an unclean unmount, empty and freeable LEBs * may contain garbage - do not scan them. @@ -1113,6 +1109,10 @@ static int scan_check_cb(struct ubifs_info *c, return LPT_SCAN_CONTINUE; } + buf = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL); + if (!buf) + return -ENOMEM; + sleb = ubifs_scan(c, lnum, 0, buf, 0); if (IS_ERR(sleb)) { ret = PTR_ERR(sleb); diff --git a/fs/xattr.c b/fs/xattr.c index d536edbd377e..cfc6324cfd6e 100644 --- a/fs/xattr.c +++ b/fs/xattr.c @@ -455,7 +455,7 @@ getxattr(struct dentry *d, const char __user *name, void __user *value, if (error > 0) { if ((strcmp(kname, XATTR_NAME_POSIX_ACL_ACCESS) == 0) || (strcmp(kname, XATTR_NAME_POSIX_ACL_DEFAULT) == 0)) - posix_acl_fix_xattr_to_user(kvalue, size); + posix_acl_fix_xattr_to_user(kvalue, error); if (size && copy_to_user(value, kvalue, error)) error = -EFAULT; } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { diff --git a/include/crypto/vmac.h b/include/crypto/vmac.h deleted file mode 100644 index 6b700c7b2fe1..000000000000 --- a/include/crypto/vmac.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Modified to interface to the Linux kernel - * Copyright (c) 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * 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. - */ - -#ifndef __CRYPTO_VMAC_H -#define __CRYPTO_VMAC_H - -/* -------------------------------------------------------------------------- - * VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai. - * This implementation is herby placed in the public domain. - * The authors offers no warranty. Use at your own risk. - * Please send bug reports to the authors. - * Last modified: 17 APR 08, 1700 PDT - * ----------------------------------------------------------------------- */ - -/* - * User definable settings. - */ -#define VMAC_TAG_LEN 64 -#define VMAC_KEY_SIZE 128/* Must be 128, 192 or 256 */ -#define VMAC_KEY_LEN (VMAC_KEY_SIZE/8) -#define VMAC_NHBYTES 128/* Must 2^i for any 3 < i < 13 Standard = 128*/ - -/* - * This implementation uses u32 and u64 as names for unsigned 32- - * and 64-bit integer types. These are defined in C99 stdint.h. The - * following may need adaptation if you are not running a C99 or - * Microsoft C environment. - */ -struct vmac_ctx { - u64 nhkey[(VMAC_NHBYTES/8)+2*(VMAC_TAG_LEN/64-1)]; - u64 polykey[2*VMAC_TAG_LEN/64]; - u64 l3key[2*VMAC_TAG_LEN/64]; - u64 polytmp[2*VMAC_TAG_LEN/64]; - u64 cached_nonce[2]; - u64 cached_aes[2]; - int first_block_processed; -}; - -typedef u64 vmac_t; - -struct vmac_ctx_t { - struct crypto_cipher *child; - struct vmac_ctx __vmac_ctx; - u8 partial[VMAC_NHBYTES]; /* partial block */ - int partial_size; /* size of the partial block */ -}; - -#endif /* __CRYPTO_VMAC_H */ diff --git a/include/linux/diagchar.h b/include/linux/diagchar.h index c3364dce7eea..332cb1b38413 100644 --- a/include/linux/diagchar.h +++ b/include/linux/diagchar.h @@ -144,10 +144,10 @@ the appropriate macros. */ /* This needs to be modified manually now, when we add a new RANGE of SSIDs to the msg_mask_tbl */ #define MSG_MASK_TBL_CNT 26 -#define APPS_EVENT_LAST_ID 0x0B2A +#define APPS_EVENT_LAST_ID 0x0C5A #define MSG_SSID_0 0 -#define MSG_SSID_0_LAST 120 +#define MSG_SSID_0_LAST 125 #define MSG_SSID_1 500 #define MSG_SSID_1_LAST 506 #define MSG_SSID_2 1000 @@ -159,11 +159,11 @@ the appropriate macros. */ #define MSG_SSID_5 4000 #define MSG_SSID_5_LAST 4010 #define MSG_SSID_6 4500 -#define MSG_SSID_6_LAST 4573 +#define MSG_SSID_6_LAST 4584 #define MSG_SSID_7 4600 -#define MSG_SSID_7_LAST 4615 +#define MSG_SSID_7_LAST 4616 #define MSG_SSID_8 5000 -#define MSG_SSID_8_LAST 5033 +#define MSG_SSID_8_LAST 5034 #define MSG_SSID_9 5500 #define MSG_SSID_9_LAST 5516 #define MSG_SSID_10 6000 @@ -183,7 +183,7 @@ the appropriate macros. */ #define MSG_SSID_17 9000 #define MSG_SSID_17_LAST 9008 #define MSG_SSID_18 9500 -#define MSG_SSID_18_LAST 9510 +#define MSG_SSID_18_LAST 9521 #define MSG_SSID_19 10200 #define MSG_SSID_19_LAST 10210 #define MSG_SSID_20 10251 @@ -263,7 +263,7 @@ static const uint32_t msg_bld_masks_0[] = { MSG_MASK_6|MSG_MASK_7|MSG_MASK_8|MSG_MASK_9|MSG_MASK_10, MSG_LVL_MED, MSG_LVL_LOW, - MSG_LVL_LOW, + MSG_LVL_MED, MSG_LVL_MED, MSG_LVL_LOW, MSG_LVL_LOW, @@ -316,7 +316,7 @@ static const uint32_t msg_bld_masks_0[] = { MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL, MSG_LVL_MED, MSG_LVL_HIGH, - MSG_LVL_LOW, + MSG_LVL_MED, MSG_LVL_HIGH, MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL, MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR, @@ -340,7 +340,8 @@ static const uint32_t msg_bld_masks_0[] = { MSG_LVL_MED, MSG_LVL_HIGH, MSG_LVL_LOW, - MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL + MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL, + MSG_LVL_HIGH }; static const uint32_t msg_bld_masks_1[] = { @@ -484,6 +485,7 @@ static const uint32_t msg_bld_masks_6[] = { MSG_LVL_LOW, MSG_LVL_LOW, MSG_LVL_LOW, + MSG_LVL_LOW, MSG_LVL_LOW }; @@ -503,7 +505,9 @@ static const uint32_t msg_bld_masks_7[] = { MSG_LVL_LOW, MSG_LVL_LOW, MSG_LVL_LOW, - MSG_LVL_LOW|MSG_LVL_MED|MSG_LVL_HIGH|MSG_LVL_ERROR|MSG_LVL_FATAL + MSG_LVL_LOW | MSG_LVL_MED | MSG_LVL_HIGH | MSG_LVL_ERROR | + MSG_LVL_FATAL, + MSG_LVL_LOW }; static const uint32_t msg_bld_masks_8[] = { @@ -523,9 +527,6 @@ static const uint32_t msg_bld_masks_8[] = { MSG_LVL_MED, MSG_LVL_MED, MSG_LVL_MED, - MSG_LVL_LOW, - MSG_LVL_LOW, - MSG_LVL_LOW, MSG_LVL_MED, MSG_LVL_MED, MSG_LVL_MED, @@ -540,6 +541,10 @@ static const uint32_t msg_bld_masks_8[] = { MSG_LVL_MED, MSG_LVL_MED, MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_HIGH, MSG_LVL_HIGH }; @@ -642,14 +647,14 @@ static const uint32_t msg_bld_masks_10[] = { MSG_LVL_MED, MSG_LVL_MED, MSG_LVL_LOW, - MSG_LVL_LOW, - MSG_LVL_LOW, - MSG_LVL_LOW, - MSG_LVL_LOW, - MSG_LVL_LOW, - MSG_LVL_LOW, - MSG_LVL_LOW, - MSG_LVL_LOW, + MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_MED, + MSG_LVL_MED, MSG_LVL_MED }; @@ -795,7 +800,9 @@ static const uint32_t msg_bld_masks_19[] = { }; static const uint32_t msg_bld_masks_20[] = { - MSG_LVL_LOW, + MSG_LVL_LOW | MSG_MASK_5 | MSG_MASK_6 | MSG_MASK_7 | + MSG_MASK_8 | MSG_MASK_9 | MSG_MASK_10 | MSG_MASK_11 | + MSG_MASK_12, MSG_LVL_LOW, MSG_LVL_LOW, MSG_LVL_LOW, @@ -873,7 +880,7 @@ static const uint32_t msg_bld_masks_25[] = { /* LOG CODES */ static const uint32_t log_code_last_tbl[] = { 0x0, /* EQUIP ID 0 */ - 0x1A02, /* EQUIP ID 1 */ + 0x1C6A, /* EQUIP ID 1 */ 0x0, /* EQUIP ID 2 */ 0x0, /* EQUIP ID 3 */ 0x4910, /* EQUIP ID 4 */ @@ -883,7 +890,7 @@ static const uint32_t log_code_last_tbl[] = { 0x0, /* EQUIP ID 8 */ 0x0, /* EQUIP ID 9 */ 0xA38A, /* EQUIP ID 10 */ - 0xB201, /* EQUIP ID 11 */ + 0xB9FF, /* EQUIP ID 11 */ 0x0, /* EQUIP ID 12 */ 0xD1FF, /* EQUIP ID 13 */ 0x0, /* EQUIP ID 14 */ diff --git a/include/linux/fastchg.h b/include/linux/fastchg.h new file mode 100644 index 000000000000..9dc0adb63d75 --- /dev/null +++ b/include/linux/fastchg.h @@ -0,0 +1,22 @@ +/* + * Author: Chad Froebel + * + * Port to Thulium: engstk + * + * 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; + +#endif diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 7693858c5583..16842b4e2056 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -15,8 +15,6 @@ #include #include -#include - #ifdef CONFIG_SMP # define INIT_PUSHABLE_TASKS(tsk) \ .pushable_tasks = PLIST_NODE_INIT(tsk.pushable_tasks, MAX_PRIO), @@ -175,19 +173,12 @@ extern struct task_group root_task_group; # define INIT_KASAN(tsk) #endif -#ifdef CONFIG_THREAD_INFO_IN_TASK -# define INIT_TASK_TI(tsk) .thread_info = INIT_THREAD_INFO(tsk), -#else -# define INIT_TASK_TI(tsk) -#endif - /* * INIT_TASK is used to set up the first task table, touch at * your own risk!. Base=0, limit=0x1fffff (=2MB) */ #define INIT_TASK(tsk) \ { \ - INIT_TASK_TI(tsk) \ .state = 0, \ .stack = &init_thread_info, \ .usage = ATOMIC_INIT(2), \ diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h index f3cbfbe80c7c..d876386d8ace 100644 --- a/include/linux/mfd/wcd9xxx/pdata.h +++ b/include/linux/mfd/wcd9xxx/pdata.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -192,6 +192,7 @@ struct wcd9xxx_pdata { u32 mic_unmute_delay; enum codec_variant cdc_variant; u16 use_pinctrl; + bool wcd9xxx_mic_tristate; }; #endif diff --git a/include/linux/msm_mhi_dev.h b/include/linux/msm_mhi_dev.h index 7eb1d06f956d..e7656972c13c 100644 --- a/include/linux/msm_mhi_dev.h +++ b/include/linux/msm_mhi_dev.h @@ -135,6 +135,7 @@ enum mhi_client_channel { MHI_CLIENT_RESERVED_2_LOWER = 102, MHI_CLIENT_RESERVED_2_UPPER = 127, MHI_MAX_CHANNELS = 102, + MHI_CLIENT_INVALID = 0xFFFFFFFF }; struct mhi_dev_client_cb_data { diff --git a/include/linux/ring_buffer.h b/include/linux/ring_buffer.h index e2c13cd863bd..4daa5069cbdb 100644 --- a/include/linux/ring_buffer.h +++ b/include/linux/ring_buffer.h @@ -162,6 +162,7 @@ void ring_buffer_record_enable(struct ring_buffer *buffer); void ring_buffer_record_off(struct ring_buffer *buffer); void ring_buffer_record_on(struct ring_buffer *buffer); int ring_buffer_record_is_on(struct ring_buffer *buffer); +int ring_buffer_record_is_set_on(struct ring_buffer *buffer); void ring_buffer_record_disable_cpu(struct ring_buffer *buffer, int cpu); void ring_buffer_record_enable_cpu(struct ring_buffer *buffer, int cpu); diff --git a/include/linux/sched.h b/include/linux/sched.h index 004733cd7d46..0e00bf883bea 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1457,13 +1457,6 @@ enum perf_event_task_context { }; struct task_struct { -#ifdef CONFIG_THREAD_INFO_IN_TASK - /* - * For reasons of header soup (see current_thread_info()), this - * must be the first element of task_struct. - */ - struct thread_info thread_info; -#endif volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ void *stack; atomic_t usage; @@ -1477,9 +1470,6 @@ struct task_struct { #ifdef CONFIG_SMP struct llist_node wake_entry; int on_cpu; -#ifdef CONFIG_THREAD_INFO_IN_TASK - unsigned int cpu; /* current CPU */ -#endif unsigned int wakee_flips; unsigned long wakee_flip_decay_ts; struct task_struct *last_wakee; @@ -2535,9 +2525,7 @@ void yield(void); extern struct exec_domain default_exec_domain; union thread_union { -#ifndef CONFIG_THREAD_INFO_IN_TASK struct thread_info thread_info; -#endif unsigned long stack[THREAD_SIZE/sizeof(long)]; }; @@ -2923,26 +2911,10 @@ static inline void threadgroup_lock(struct task_struct *tsk) {} static inline void threadgroup_unlock(struct task_struct *tsk) {} #endif -#ifdef CONFIG_THREAD_INFO_IN_TASK - -static inline struct thread_info *task_thread_info(struct task_struct *task) -{ - return &task->thread_info; -} -static inline void *task_stack_page(const struct task_struct *task) -{ - return task->stack; -} -#define setup_thread_stack(new,old) do { } while(0) -static inline unsigned long *end_of_stack(const struct task_struct *task) -{ - return task->stack; -} - -#elif !defined(__HAVE_THREAD_FUNCTIONS) +#ifndef __HAVE_THREAD_FUNCTIONS #define task_thread_info(task) ((struct thread_info *)(task)->stack) -#define task_stack_page(task) ((void *)(task)->stack) +#define task_stack_page(task) ((task)->stack) static inline void setup_thread_stack(struct task_struct *p, struct task_struct *org) { @@ -3245,11 +3217,7 @@ static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume) static inline unsigned int task_cpu(const struct task_struct *p) { -#ifdef CONFIG_THREAD_INFO_IN_TASK - return p->cpu; -#else return task_thread_info(p)->cpu; -#endif } static inline int task_node(const struct task_struct *p) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 3dbe99528735..393e3e459bf1 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -475,6 +475,7 @@ static inline u32 skb_mstamp_us_delta(const struct skb_mstamp *t1, * @hash: the packet hash * @queue_mapping: Queue mapping for multiqueue devices * @xmit_more: More SKBs are pending for this queue + * @pfmemalloc: skbuff was allocated from PFMEMALLOC reserves * @ndisc_nodetype: router type (from link layer) * @ooo_okay: allow the mapping of a socket to a queue to be changed * @l4_hash: indicate hash is a canonical 4-tuple hash over transport @@ -551,8 +552,8 @@ struct sk_buff { fclone:2, peeked:1, head_frag:1, - xmit_more:1; - /* one bit hole */ + xmit_more:1, + pfmemalloc:1; kmemcheck_bitfield_end(flags1); /* fields enclosed in headers_start/headers_end are copied @@ -572,19 +573,18 @@ struct sk_buff { __u8 __pkt_type_offset[0]; __u8 pkt_type:3; - __u8 pfmemalloc:1; __u8 ignore_df:1; __u8 nfctinfo:3; - __u8 nf_trace:1; + __u8 ip_summed:2; __u8 ooo_okay:1; __u8 l4_hash:1; __u8 sw_hash:1; __u8 wifi_acked_valid:1; __u8 wifi_acked:1; - __u8 no_fcs:1; + /* Indicates the inner headers are valid in the skbuff. */ __u8 encapsulation:1; __u8 encap_hdr_csum:1; @@ -592,11 +592,11 @@ struct sk_buff { __u8 csum_complete_sw:1; __u8 csum_level:2; __u8 csum_bad:1; - #ifdef CONFIG_IPV6_NDISC_NODETYPE __u8 ndisc_nodetype:2; #endif __u8 ipvs_property:1; + __u8 inner_protocol_type:1; __u8 fast_forwarded:1; /* 4 or 6 bit hole */ diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h index 70ceb2a14a57..8e0c151cc07c 100644 --- a/include/linux/sysfs.h +++ b/include/linux/sysfs.h @@ -200,6 +200,9 @@ int __must_check sysfs_create_files(struct kobject *kobj, const struct attribute **attr); int __must_check sysfs_chmod_file(struct kobject *kobj, const struct attribute *attr, umode_t mode); +struct kernfs_node *sysfs_break_active_protection(struct kobject *kobj, + const struct attribute *attr); +void sysfs_unbreak_active_protection(struct kernfs_node *kn); void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, const void *ns); bool sysfs_remove_file_self(struct kobject *kobj, const struct attribute *attr); @@ -299,6 +302,17 @@ static inline int sysfs_chmod_file(struct kobject *kobj, return 0; } +static inline struct kernfs_node * +sysfs_break_active_protection(struct kobject *kobj, + const struct attribute *attr) +{ + return NULL; +} + +static inline void sysfs_unbreak_active_protection(struct kernfs_node *kn) +{ +} + static inline void sysfs_remove_file_ns(struct kobject *kobj, const struct attribute *attr, const void *ns) diff --git a/include/linux/thread_info.h b/include/linux/thread_info.h index 8784cebd0f51..4cf89517783a 100644 --- a/include/linux/thread_info.h +++ b/include/linux/thread_info.h @@ -13,21 +13,6 @@ struct timespec; struct compat_timespec; -#ifdef CONFIG_THREAD_INFO_IN_TASK -struct thread_info { - u32 flags; /* low level flags */ -}; - -#define INIT_THREAD_INFO(tsk) \ -{ \ - .flags = 0, \ -} -#endif - -#ifdef CONFIG_THREAD_INFO_IN_TASK -#define current_thread_info() ((struct thread_info *)current) -#endif - /* * System call restart block. */ diff --git a/include/net/af_vsock.h b/include/net/af_vsock.h index 428277869400..8f9f676f1e16 100644 --- a/include/net/af_vsock.h +++ b/include/net/af_vsock.h @@ -59,7 +59,8 @@ struct vsock_sock { struct list_head pending_links; struct list_head accept_queue; bool rejected; - struct delayed_work dwork; + struct delayed_work connect_work; + struct delayed_work pending_work; u32 peer_shutdown; bool sent_request; bool ignore_connecting_rst; @@ -70,7 +71,6 @@ struct vsock_sock { s64 vsock_stream_has_data(struct vsock_sock *vsk); s64 vsock_stream_has_space(struct vsock_sock *vsk); -void vsock_pending_work(struct work_struct *work); struct sock *__vsock_create(struct net *net, struct socket *sock, struct sock *parent, diff --git a/include/net/cnss.h b/include/net/cnss.h index f005b2833706..2375605bb425 100644 --- a/include/net/cnss.h +++ b/include/net/cnss.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -102,11 +102,14 @@ struct cnss_platform_cap { u32 cap_flag; }; -/* WLAN driver status */ +/* WLAN driver status, keep it aligned with cnss2 */ enum cnss_driver_status { CNSS_UNINITIALIZED, CNSS_INITIALIZED, - CNSS_LOAD_UNLOAD + CNSS_LOAD_UNLOAD, + CNSS_RECOVERY, + CNSS_FW_DOWN, + CNSS_SSR_FAIL, }; enum cnss_runtime_request { diff --git a/include/net/llc.h b/include/net/llc.h index e8e61d4fb458..82d989995d18 100644 --- a/include/net/llc.h +++ b/include/net/llc.h @@ -116,6 +116,11 @@ static inline void llc_sap_hold(struct llc_sap *sap) atomic_inc(&sap->refcnt); } +static inline bool llc_sap_hold_safe(struct llc_sap *sap) +{ + return atomic_inc_not_zero(&sap->refcnt); +} + void llc_sap_close(struct llc_sap *sap); static inline void llc_sap_put(struct llc_sap *sap) diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index ff4081af4d9c..7c9518bf0453 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h @@ -112,6 +112,7 @@ struct net { #endif #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) struct netns_nf_frag nf_frag; + struct ctl_table_header *nf_frag_frags_hdr; #endif struct sock *nfnl; struct sock *nfnl_stash; diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h index 69ae41f2098c..c57d055f76bc 100644 --- a/include/net/netns/ipv6.h +++ b/include/net/netns/ipv6.h @@ -81,7 +81,6 @@ struct netns_ipv6 { #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) struct netns_nf_frag { - struct netns_sysctl_ipv6 sysctl; struct netns_frags frags; }; #endif diff --git a/include/net/tcp.h b/include/net/tcp.h index 4969c879a5d6..ee336e033246 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -387,6 +387,7 @@ extern int tcp_use_userconfig_sysctl_handler(struct ctl_table *, int, extern int tcp_proc_delayed_ack_control(struct ctl_table *, int, void __user *, size_t *, loff_t *); +void tcp_enter_quickack_mode(struct sock *sk, unsigned int max_quickacks); static inline void tcp_dec_quickack_mode(struct sock *sk, const unsigned int pkts) { @@ -545,6 +546,7 @@ int tcp_send_synack(struct sock *); bool tcp_syn_flood_action(struct sock *sk, const struct sk_buff *skb, const char *proto); void tcp_push_one(struct sock *, unsigned int mss_now); +void __tcp_send_ack(struct sock *sk, u32 rcv_nxt); void tcp_send_ack(struct sock *sk); void tcp_send_delayed_ack(struct sock *sk); void tcp_send_loss_probe(struct sock *sk); diff --git a/include/sound/apr_audio-v2.h b/include/sound/apr_audio-v2.h index 6f88d5348f2f..d7f7212a74ca 100644 --- a/include/sound/apr_audio-v2.h +++ b/include/sound/apr_audio-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -3391,6 +3391,8 @@ struct asm_softvolume_params { #define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 0x00010DDC +#define ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4 0x0001320C + #define ASM_MEDIA_FMT_EVRCB_FS 0x00010BEF #define ASM_MEDIA_FMT_EVRCWB_FS 0x00010BF0 @@ -3493,6 +3495,56 @@ struct asm_multi_channel_pcm_fmt_blk_v3 { */ } __packed; +struct asm_multi_channel_pcm_fmt_blk_v4 { + uint16_t num_channels; +/* + * Number of channels + * Supported values: 1 to 8 + */ + + uint16_t bits_per_sample; +/* + * Number of bits per sample per channel + * Supported values: 16, 24, 32 + */ + + uint32_t sample_rate; +/* + * Number of samples per second + * Supported values: 2000 to 48000, 96000,192000 Hz + */ + + uint16_t is_signed; +/* Flag that indicates that PCM samples are signed (1) */ + + uint16_t sample_word_size; +/* + * Size in bits of the word that holds a sample of a channel. + * Supported values: 12,24,32 + */ + + uint8_t channel_mapping[8]; +/* + * Each element, i, in the array describes channel i inside the buffer where + * 0 <= i < num_channels. Unused channels are set to 0. + */ + uint16_t endianness; +/* + * Flag to indicate the endianness of the pcm sample + * Supported values: 0 - Little endian (all other formats) + * 1 - Big endian (AIFF) + */ + uint16_t mode; +/* + * Mode to provide additional info about the pcm input data. + * Supported values: 0 - Default QFs (Q15 for 16b, Q23 for packed 24b, + * Q31 for unpacked 24b or 32b) + * 15 - for 16 bit + * 23 - for 24b packed or 8.24 format + * 31 - for 24b unpacked or 32bit + */ +} __packed; + /* * Payload of the multichannel PCM configuration parameters in * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3 media format. @@ -3503,6 +3555,16 @@ struct asm_multi_channel_pcm_fmt_blk_param_v3 { struct asm_multi_channel_pcm_fmt_blk_v3 param; } __packed; +/* + * Payload of the multichannel PCM configuration parameters in + * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4 media format. + */ +struct asm_multi_channel_pcm_fmt_blk_param_v4 { + struct apr_hdr hdr; + struct asm_data_cmd_media_fmt_update_v2 fmt_blk; + struct asm_multi_channel_pcm_fmt_blk_v4 param; +} __packed; + struct asm_stream_cmd_set_encdec_param { u32 param_id; /* ID of the parameter. */ @@ -3538,6 +3600,79 @@ struct asm_dec_ddp_endp_param_v2 { int endp_param_value; } __packed; +/* + * Payload of the multichannel PCM encoder configuration parameters in + * the ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4 media format. + */ + +struct asm_multi_channel_pcm_enc_cfg_v4 { + struct apr_hdr hdr; + struct asm_stream_cmd_set_encdec_param encdec; + struct asm_enc_cfg_blk_param_v2 encblk; + uint16_t num_channels; + /* + * Number of PCM channels. + * @values + * - 0 -- Native mode + * - 1 -- 8 channels + * Native mode indicates that encoding must be performed with the number + * of channels at the input. + */ + uint16_t bits_per_sample; + /* + * Number of bits per sample per channel. + * @values 16, 24 + */ + uint32_t sample_rate; + /* + * Number of samples per second. + * @values 0, 8000 to 48000 Hz + * A value of 0 indicates the native sampling rate. Encoding is + * performed at the input sampling rate. + */ + uint16_t is_signed; + /* + * Flag that indicates the PCM samples are signed (1). Currently, only + * signed PCM samples are supported. + */ + uint16_t sample_word_size; + /* + * The size in bits of the word that holds a sample of a channel. + * @values 16, 24, 32 + * 16-bit samples are always placed in 16-bit words: + * sample_word_size = 1. + * 24-bit samples can be placed in 32-bit words or in consecutive + * 24-bit words. + * - If sample_word_size = 32, 24-bit samples are placed in the + * most significant 24 bits of a 32-bit word. + * - If sample_word_size = 24, 24-bit samples are placed in + * 24-bit words. @tablebulletend + */ + uint8_t channel_mapping[8]; + /* + * Channel mapping array expected at the encoder output. + * Channel[i] mapping describes channel i inside the buffer, where + * 0 @le i < num_channels. All valid used channels must be present at + * the beginning of the array. + * If Native mode is set for the channels, this field is ignored. + * @values See Section @xref{dox:PcmChannelDefs} + */ + uint16_t endianness; + /* + * Flag to indicate the endianness of the pcm sample + * Supported values: 0 - Little endian (all other formats) + * 1 - Big endian (AIFF) + */ + uint16_t mode; + /* + * Mode to provide additional info about the pcm input data. + * Supported values: 0 - Default QFs (Q15 for 16b, Q23 for packed 24b, + * Q31 for unpacked 24b or 32b) + * 15 - for 16 bit + * 23 - for 24b packed or 8.24 format + * 31 - for 24b unpacked or 32bit + */ +} __packed; /* * Payload of the multichannel PCM encoder configuration parameters in diff --git a/include/sound/q6adm-v2.h b/include/sound/q6adm-v2.h index c3638978567e..19daccf4b3df 100644 --- a/include/sound/q6adm-v2.h +++ b/include/sound/q6adm-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -28,6 +28,8 @@ #define AUD_VOL_BLOCK_SIZE 4096 #define AUDIO_RX_CALIBRATION_SIZE (AUD_PROC_BLOCK_SIZE + \ AUD_VOL_BLOCK_SIZE) +#define SESSION_TYPE_RX 0 +#define SESSION_TYPE_TX 1 enum { ADM_CUSTOM_TOP_CAL = 0, ADM_AUDPROC_CAL, @@ -181,5 +183,6 @@ int adm_get_source_tracking(int port_id, int copp_idx, int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, int session_type, struct msm_pcm_channel_mixer *ch_mixer, - int channel_index); + int channel_index, bool use_default_chmap, + char *ch_map); #endif /* __Q6_ADM_V2_H__ */ diff --git a/include/sound/q6asm-v2.h b/include/sound/q6asm-v2.h index 7771f2468eee..d58cf56c3eb9 100644 --- a/include/sound/q6asm-v2.h +++ b/include/sound/q6asm-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -103,6 +103,24 @@ #define ASM_SHIFT_GAPLESS_MODE_FLAG 31 #define ASM_SHIFT_LAST_BUFFER_FLAG 30 +#define ASM_LITTLE_ENDIAN 0 +#define ASM_BIG_ENDIAN 1 + +/* PCM_MEDIA_FORMAT_Version */ +enum { + PCM_MEDIA_FORMAT_V2 = 0, + PCM_MEDIA_FORMAT_V3, + PCM_MEDIA_FORMAT_V4, +}; + +/* PCM format modes in DSP */ +enum { + DEFAULT_QF = 0, + Q15 = 15, + Q23 = 23, + Q31 = 31, +}; + /* payload structure bytes */ #define READDONE_IDX_STATUS 0 #define READDONE_IDX_BUFADD_LSW 1 @@ -270,6 +288,9 @@ int q6asm_open_shared_io(struct audio_client *ac, int q6asm_open_write_v3(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample); +int q6asm_open_write_v4(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample); + int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode); @@ -278,6 +299,10 @@ int q6asm_stream_open_write_v3(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode); +int q6asm_stream_open_write_v4(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample, int32_t stream_id, + bool is_gapless_mode); + int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format, uint32_t passthrough_flag); @@ -386,6 +411,13 @@ int q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac, bool use_back_flavor, u8 *channel_map, uint16_t sample_word_size); +int q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, bool use_default_chmap, + bool use_back_flavor, u8 *channel_map, + uint16_t sample_word_size, uint16_t endianness, + uint16_t mode); + int q6asm_enc_cfg_blk_pcm_format_support(struct audio_client *ac, uint32_t rate, uint32_t channels, uint16_t bits_per_sample); @@ -395,6 +427,13 @@ int q6asm_enc_cfg_blk_pcm_format_support_v3(struct audio_client *ac, uint16_t bits_per_sample, uint16_t sample_word_size); +int q6asm_enc_cfg_blk_pcm_format_support_v4(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode); + int q6asm_set_encdec_chan_map(struct audio_client *ac, uint32_t num_channels); @@ -444,6 +483,17 @@ int q6asm_media_format_block_pcm_format_support_v3(struct audio_client *ac, char *channel_map, uint16_t sample_word_size); +int q6asm_media_format_block_pcm_format_support_v4(struct audio_client *ac, + uint32_t rate, + uint32_t channels, + uint16_t bits_per_sample, + int stream_id, + bool use_default_chmap, + char *channel_map, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode); + int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, uint32_t rate, uint32_t channels, bool use_default_chmap, char *channel_map); @@ -461,6 +511,15 @@ int q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac, uint16_t bits_per_sample, uint16_t sample_word_size); +int q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac, + uint32_t rate, uint32_t channels, + bool use_default_chmap, + char *channel_map, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode); + int q6asm_media_format_block_aac(struct audio_client *ac, struct asm_aac_cfg *cfg); diff --git a/include/sound/q6core.h b/include/sound/q6core.h index f21e790ce600..975eda177664 100644 --- a/include/sound/q6core.h +++ b/include/sound/q6core.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -157,4 +157,23 @@ struct avcs_cmd_deregister_topologies { int32_t core_set_license(uint32_t key, uint32_t module_id); int32_t core_get_license_status(uint32_t module_id); +#define AVCS_GET_VERSIONS 0x00012905 +struct avcs_cmd_get_version_result { + struct apr_hdr hdr; + uint32_t id; +}; +#define AVCS_GET_VERSIONS_RSP 0x00012906 + +#define AVCS_CMDRSP_Q6_ID_2_6 0x00040000 +#define AVCS_CMDRSP_Q6_ID_2_7 0x00040001 +#define AVCS_CMDRSP_Q6_ID_2_8 0x00040002 + +enum q6_subsys_image { + Q6_SUBSYS_AVS2_6 = 1, + Q6_SUBSYS_AVS2_7, + Q6_SUBSYS_AVS2_8, + Q6_SUBSYS_INVALID, +}; +enum q6_subsys_image q6core_get_avs_version(void); +int core_get_adsp_ver(void); #endif /* __Q6CORE_H__ */ diff --git a/include/video/udlfb.h b/include/video/udlfb.h index f9466fa54ba4..2ad9a6d37ff4 100644 --- a/include/video/udlfb.h +++ b/include/video/udlfb.h @@ -87,7 +87,7 @@ struct dlfb_data { #define MIN_RAW_PIX_BYTES 2 #define MIN_RAW_CMD_BYTES (RAW_HEADER_BYTES + MIN_RAW_PIX_BYTES) -#define DL_DEFIO_WRITE_DELAY 5 /* fb_deferred_io.delay in jiffies */ +#define DL_DEFIO_WRITE_DELAY msecs_to_jiffies(HZ <= 300 ? 4 : 10) /* optimal value for 720p video */ #define DL_DEFIO_WRITE_DISABLE (HZ*60) /* "disable" with long delay */ /* remove these once align.h patch is taken into kernel */ diff --git a/init/Kconfig b/init/Kconfig index 7e042a043a62..ed4a0cf9845b 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -26,13 +26,6 @@ config IRQ_WORK config BUILDTIME_EXTABLE_SORT bool -config THREAD_INFO_IN_TASK - bool - help - Select this to move thread_info off the stack into task_struct. To - make this work, an arch will need to remove all thread_info fields - except flags and fix any runtime bugs. - menu "General setup" config BROKEN diff --git a/init/init_task.c b/init/init_task.c index 11f83be1fa79..ba0a7f362d9e 100644 --- a/init/init_task.c +++ b/init/init_task.c @@ -22,8 +22,5 @@ EXPORT_SYMBOL(init_task); * Initial thread structure. Alignment of this is handled by a special * linker map entry. */ -union thread_union init_thread_union __init_task_data = { -#ifndef CONFIG_THREAD_INFO_IN_TASK - INIT_THREAD_INFO(init_task) -#endif -}; +union thread_union init_thread_union __init_task_data = + { INIT_THREAD_INFO(init_task) }; diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 25a82734790b..9a5761fe8720 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -1774,7 +1774,7 @@ static int replace_map_fd_with_map_ptr(struct verifier_env *env) /* hold the map. If the program is rejected by verifier, * the map will be released by release_maps() or it * will be used by the valid program until it's unloaded - * and all maps are released in free_bpf_prog_info() + * and all maps are released in free_used_maps() */ atomic_inc(&map->refcnt); @@ -1940,7 +1940,7 @@ int bpf_check(struct bpf_prog *prog, union bpf_attr *attr) free_env: if (!prog->aux->used_maps) /* if we didn't copy map pointers into bpf_prog_info, release - * them now. Otherwise free_bpf_prog_info() will release them. + * them now. Otherwise free_used_maps() will release them. */ release_maps(env); kfree(env); diff --git a/kernel/futex.c b/kernel/futex.c index e75c3c414af5..55e87606f80b 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -1918,8 +1918,12 @@ static int unqueue_me(struct futex_q *q) /* In the common case we don't take the spinlock, which is nice. */ retry: - lock_ptr = q->lock_ptr; - barrier(); + /* + * q->lock_ptr can change between this read and the following spin_lock. + * Use READ_ONCE to forbid the compiler from reloading q->lock_ptr and + * optimizing lock_ptr out of the logic below. + */ + lock_ptr = READ_ONCE(q->lock_ptr); if (lock_ptr != NULL) { spin_lock(lock_ptr); /* diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 55240ca8b12c..6780e32471f3 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -2425,7 +2425,7 @@ static int __init debugfs_kprobe_init(void) if (!dir) return -ENOMEM; - file = debugfs_create_file("list", 0444, dir, NULL, + file = debugfs_create_file("list", 0400, dir, NULL, &debugfs_kprobes_operations); if (!file) goto error; @@ -2435,7 +2435,7 @@ static int __init debugfs_kprobe_init(void) if (!file) goto error; - file = debugfs_create_file("blacklist", 0444, dir, NULL, + file = debugfs_create_file("blacklist", 0400, dir, NULL, &debugfs_kprobe_blacklist_ops); if (!file) goto error; diff --git a/kernel/kthread.c b/kernel/kthread.c index 79bfca4170d9..6b03c6cab7da 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -309,10 +309,16 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), task = create->result; if (!IS_ERR(task)) { static const struct sched_param param = { .sched_priority = 0 }; + char name[TASK_COMM_LEN]; va_list args; va_start(args, namefmt); - vsnprintf(task->comm, sizeof(task->comm), namefmt, args); + /* + * task is already visible to other tasks, so updating + * COMM must be protected. + */ + vsnprintf(name, sizeof(name), namefmt, args); + set_task_comm(task, name); va_end(args); /* * root may have changed our (kthreadd's) priority or CPU mask. diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index 3467618cc0ea..f99008534275 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -1253,11 +1253,11 @@ unsigned long lockdep_count_forward_deps(struct lock_class *class) this.parent = NULL; this.class = class; - local_irq_save(flags); + raw_local_irq_save(flags); arch_spin_lock(&lockdep_lock); ret = __lockdep_count_forward_deps(&this); arch_spin_unlock(&lockdep_lock); - local_irq_restore(flags); + raw_local_irq_restore(flags); return ret; } @@ -1280,11 +1280,11 @@ unsigned long lockdep_count_backward_deps(struct lock_class *class) this.parent = NULL; this.class = class; - local_irq_save(flags); + raw_local_irq_save(flags); arch_spin_lock(&lockdep_lock); ret = __lockdep_count_backward_deps(&this); arch_spin_unlock(&lockdep_lock); - local_irq_restore(flags); + raw_local_irq_restore(flags); return ret; } @@ -4083,7 +4083,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) if (unlikely(!debug_locks)) return; - local_irq_save(flags); + raw_local_irq_save(flags); for (i = 0; i < curr->lockdep_depth; i++) { hlock = curr->held_locks + i; @@ -4094,7 +4094,7 @@ void debug_check_no_locks_freed(const void *mem_from, unsigned long mem_len) print_freed_lock_bug(curr, mem_from, mem_from + mem_len, hlock); break; } - local_irq_restore(flags); + raw_local_irq_restore(flags); } EXPORT_SYMBOL_GPL(debug_check_no_locks_freed); diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h index 9b08657c6915..7cdb1f5a388e 100644 --- a/kernel/sched/sched.h +++ b/kernel/sched/sched.h @@ -1019,11 +1019,7 @@ static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) * per-task data have been completed by this moment. */ smp_wmb(); -#ifdef CONFIG_THREAD_INFO_IN_TASK - p->cpu = cpu; -#else task_thread_info(p)->cpu = cpu; -#endif p->wake_cpu = cpu; #endif } diff --git a/kernel/sys.c b/kernel/sys.c index 38a20992febf..56978d0bfb86 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -1128,18 +1128,19 @@ static int override_release(char __user *release, size_t len) SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) { - int errno = 0; + struct new_utsname tmp; down_read(&uts_sem); - if (copy_to_user(name, utsname(), sizeof *name)) - errno = -EFAULT; + memcpy(&tmp, utsname(), sizeof(tmp)); up_read(&uts_sem); + if (copy_to_user(name, &tmp, sizeof(tmp))) + return -EFAULT; - if (!errno && override_release(name->release, sizeof(name->release))) - errno = -EFAULT; - if (!errno && override_architecture(name)) - errno = -EFAULT; - return errno; + if (override_release(name->release, sizeof(name->release))) + return -EFAULT; + if (override_architecture(name)) + return -EFAULT; + return 0; } #ifdef __ARCH_WANT_SYS_OLD_UNAME @@ -1148,55 +1149,46 @@ SYSCALL_DEFINE1(newuname, struct new_utsname __user *, name) */ SYSCALL_DEFINE1(uname, struct old_utsname __user *, name) { - int error = 0; + struct old_utsname tmp; if (!name) return -EFAULT; down_read(&uts_sem); - if (copy_to_user(name, utsname(), sizeof(*name))) - error = -EFAULT; + memcpy(&tmp, utsname(), sizeof(tmp)); up_read(&uts_sem); + if (copy_to_user(name, &tmp, sizeof(tmp))) + return -EFAULT; - if (!error && override_release(name->release, sizeof(name->release))) - error = -EFAULT; - if (!error && override_architecture(name)) - error = -EFAULT; - return error; + if (override_release(name->release, sizeof(name->release))) + return -EFAULT; + if (override_architecture(name)) + return -EFAULT; + return 0; } SYSCALL_DEFINE1(olduname, struct oldold_utsname __user *, name) { - int error; + struct oldold_utsname tmp = {}; if (!name) return -EFAULT; - if (!access_ok(VERIFY_WRITE, name, sizeof(struct oldold_utsname))) - return -EFAULT; down_read(&uts_sem); - error = __copy_to_user(&name->sysname, &utsname()->sysname, - __OLD_UTS_LEN); - error |= __put_user(0, name->sysname + __OLD_UTS_LEN); - error |= __copy_to_user(&name->nodename, &utsname()->nodename, - __OLD_UTS_LEN); - error |= __put_user(0, name->nodename + __OLD_UTS_LEN); - error |= __copy_to_user(&name->release, &utsname()->release, - __OLD_UTS_LEN); - error |= __put_user(0, name->release + __OLD_UTS_LEN); - error |= __copy_to_user(&name->version, &utsname()->version, - __OLD_UTS_LEN); - error |= __put_user(0, name->version + __OLD_UTS_LEN); - error |= __copy_to_user(&name->machine, &utsname()->machine, - __OLD_UTS_LEN); - error |= __put_user(0, name->machine + __OLD_UTS_LEN); + memcpy(&tmp.sysname, &utsname()->sysname, __OLD_UTS_LEN); + memcpy(&tmp.nodename, &utsname()->nodename, __OLD_UTS_LEN); + memcpy(&tmp.release, &utsname()->release, __OLD_UTS_LEN); + memcpy(&tmp.version, &utsname()->version, __OLD_UTS_LEN); + memcpy(&tmp.machine, &utsname()->machine, __OLD_UTS_LEN); up_read(&uts_sem); + if (copy_to_user(name, &tmp, sizeof(tmp))) + return -EFAULT; - if (!error && override_architecture(name)) - error = -EFAULT; - if (!error && override_release(name->release, sizeof(name->release))) - error = -EFAULT; - return error ? -EFAULT : 0; + if (override_architecture(name)) + return -EFAULT; + if (override_release(name->release, sizeof(name->release))) + return -EFAULT; + return 0; } #endif @@ -1210,17 +1202,18 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) if (len < 0 || len > __NEW_UTS_LEN) return -EINVAL; - down_write(&uts_sem); errno = -EFAULT; if (!copy_from_user(tmp, name, len)) { - struct new_utsname *u = utsname(); + struct new_utsname *u; + down_write(&uts_sem); + u = utsname(); memcpy(u->nodename, tmp, len); memset(u->nodename + len, 0, sizeof(u->nodename) - len); errno = 0; uts_proc_notify(UTS_PROC_HOSTNAME); + up_write(&uts_sem); } - up_write(&uts_sem); return errno; } @@ -1228,8 +1221,9 @@ SYSCALL_DEFINE2(sethostname, char __user *, name, int, len) SYSCALL_DEFINE2(gethostname, char __user *, name, int, len) { - int i, errno; + int i; struct new_utsname *u; + char tmp[__NEW_UTS_LEN + 1]; if (len < 0) return -EINVAL; @@ -1238,11 +1232,11 @@ SYSCALL_DEFINE2(gethostname, char __user *, name, int, len) i = 1 + strlen(u->nodename); if (i > len) i = len; - errno = 0; - if (copy_to_user(name, u->nodename, i)) - errno = -EFAULT; + memcpy(tmp, u->nodename, i); up_read(&uts_sem); - return errno; + if (copy_to_user(name, tmp, i)) + return -EFAULT; + return 0; } #endif @@ -1261,17 +1255,18 @@ SYSCALL_DEFINE2(setdomainname, char __user *, name, int, len) if (len < 0 || len > __NEW_UTS_LEN) return -EINVAL; - down_write(&uts_sem); errno = -EFAULT; if (!copy_from_user(tmp, name, len)) { - struct new_utsname *u = utsname(); + struct new_utsname *u; + down_write(&uts_sem); + u = utsname(); memcpy(u->domainname, tmp, len); memset(u->domainname + len, 0, sizeof(u->domainname) - len); errno = 0; uts_proc_notify(UTS_PROC_DOMAINNAME); + up_write(&uts_sem); } - up_write(&uts_sem); return errno; } diff --git a/kernel/sysctl.c b/kernel/sysctl.c index cd23638d823f..fd5e53ccdfb0 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -397,7 +397,8 @@ static struct ctl_table kern_table[] = { .data = &sysctl_sched_time_avg, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = proc_dointvec, + .proc_handler = proc_dointvec_minmax, + .extra1 = &one, }, { .procname = "sched_shares_window_ns", diff --git a/kernel/trace/blktrace.c b/kernel/trace/blktrace.c index 5d7e2ca08342..a1f2a0450e99 100644 --- a/kernel/trace/blktrace.c +++ b/kernel/trace/blktrace.c @@ -1786,6 +1786,10 @@ static ssize_t sysfs_blk_trace_attr_store(struct device *dev, mutex_lock(&bdev->bd_mutex); if (attr == &dev_attr_enable) { + if (!!value == !!q->blk_trace) { + ret = 0; + goto out_unlock_bdev; + } if (value) ret = blk_trace_setup_queue(q, bdev); else diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c index 68fcf6829bc5..5821def0b7a0 100644 --- a/kernel/trace/ring_buffer.c +++ b/kernel/trace/ring_buffer.c @@ -3152,6 +3152,22 @@ int ring_buffer_record_is_on(struct ring_buffer *buffer) return !atomic_read(&buffer->record_disabled); } +/** + * ring_buffer_record_is_set_on - return true if the ring buffer is set writable + * @buffer: The ring buffer to see if write is set enabled + * + * Returns true if the ring buffer is set writable by ring_buffer_record_on(). + * Note that this does NOT mean it is in a writable state. + * + * It may return true when the ring buffer has been disabled by + * ring_buffer_record_disable(), as that is a temporary disabling of + * the ring buffer. + */ +int ring_buffer_record_is_set_on(struct ring_buffer *buffer) +{ + return !(atomic_read(&buffer->record_disabled) & RB_BUFFER_OFF); +} + /** * ring_buffer_record_disable_cpu - stop all writes into the cpu_buffer * @buffer: The ring buffer to stop writes to. diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 92e73e37f4bf..1db5a2ec2264 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -1030,6 +1030,12 @@ update_max_tr(struct trace_array *tr, struct task_struct *tsk, int cpu) arch_spin_lock(&tr->max_lock); + /* Inherit the recordable setting from trace_buffer */ + if (ring_buffer_record_is_set_on(tr->trace_buffer.buffer)) + ring_buffer_record_on(tr->max_buffer.buffer); + else + ring_buffer_record_off(tr->max_buffer.buffer); + buf = tr->trace_buffer.buffer; tr->trace_buffer.buffer = tr->max_buffer.buffer; tr->max_buffer.buffer = buf; @@ -2183,6 +2189,7 @@ int trace_vbprintk(unsigned long ip, const char *fmt, va_list args) } EXPORT_SYMBOL_GPL(trace_vbprintk); +__printf(3, 0) static int __trace_array_vprintk(struct ring_buffer *buffer, unsigned long ip, const char *fmt, va_list args) @@ -2237,12 +2244,14 @@ __trace_array_vprintk(struct ring_buffer *buffer, return len; } +__printf(3, 0) int trace_array_vprintk(struct trace_array *tr, unsigned long ip, const char *fmt, va_list args) { return __trace_array_vprintk(tr->trace_buffer.buffer, ip, fmt, args); } +__printf(3, 0) int trace_array_printk(struct trace_array *tr, unsigned long ip, const char *fmt, ...) { @@ -2258,6 +2267,7 @@ int trace_array_printk(struct trace_array *tr, return ret; } +__printf(3, 4) int trace_array_printk_buf(struct ring_buffer *buffer, unsigned long ip, const char *fmt, ...) { @@ -2273,6 +2283,7 @@ int trace_array_printk_buf(struct ring_buffer *buffer, return ret; } +__printf(2, 0) int trace_vprintk(unsigned long ip, const char *fmt, va_list args) { return trace_array_vprintk(&global_trace, ip, fmt, args); @@ -6326,7 +6337,9 @@ rb_simple_write(struct file *filp, const char __user *ubuf, if (buffer) { mutex_lock(&trace_types_lock); - if (val) { + if (!!val == tracer_tracing_is_on(tr)) { + val = 0; /* do nothing */ + } else if (val) { tracer_tracing_on(tr); if (tr->current_trace->start) tr->current_trace->start(tr); diff --git a/kernel/trace/trace_events_trigger.c b/kernel/trace/trace_events_trigger.c index b743e758241e..a958d3397a52 100644 --- a/kernel/trace/trace_events_trigger.c +++ b/kernel/trace/trace_events_trigger.c @@ -663,6 +663,8 @@ event_trigger_callback(struct event_command *cmd_ops, goto out_free; out_reg: + /* Up the trigger_data count to make sure reg doesn't free it on failure */ + event_trigger_init(trigger_ops, trigger_data); ret = cmd_ops->reg(glob, trigger_ops, trigger_data, file); /* * The above returns on success the # of functions enabled, @@ -670,11 +672,13 @@ event_trigger_callback(struct event_command *cmd_ops, * Consider no functions a failure too. */ if (!ret) { + cmd_ops->unreg(glob, trigger_ops, trigger_data, file); ret = -ENOENT; - goto out_free; - } else if (ret < 0) - goto out_free; - ret = 0; + } else if (ret > 0) + ret = 0; + + /* Down the counter of trigger_data or free it if not used anymore */ + event_trigger_free(trigger_ops, trigger_data); out: return ret; @@ -1227,6 +1231,9 @@ event_enable_trigger_func(struct event_command *cmd_ops, goto out; } + /* Up the trigger_data count to make sure nothing frees it on failure */ + event_trigger_init(trigger_ops, trigger_data); + if (trigger) { number = strsep(&trigger, ":"); @@ -1277,6 +1284,7 @@ event_enable_trigger_func(struct event_command *cmd_ops, goto out_disable; /* Just return zero, not the number of enabled functions */ ret = 0; + event_trigger_free(trigger_ops, trigger_data); out: return ret; @@ -1287,7 +1295,7 @@ event_enable_trigger_func(struct event_command *cmd_ops, out_free: if (cmd_ops->set_filter) cmd_ops->set_filter(NULL, trigger_data, NULL); - kfree(trigger_data); + event_trigger_free(trigger_ops, trigger_data); kfree(enable_data); goto out; } diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 940a91ac7d86..efbb9aa0c8ba 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -361,11 +361,10 @@ static struct trace_kprobe *find_trace_kprobe(const char *event, static int enable_trace_kprobe(struct trace_kprobe *tk, struct ftrace_event_file *file) { + struct event_file_link *link = NULL; int ret = 0; if (file) { - struct event_file_link *link; - link = kmalloc(sizeof(*link), GFP_KERNEL); if (!link) { ret = -ENOMEM; @@ -385,6 +384,18 @@ enable_trace_kprobe(struct trace_kprobe *tk, struct ftrace_event_file *file) else ret = enable_kprobe(&tk->rp.kp); } + + if (ret) { + if (file) { + /* Notice the if is true on not WARN() */ + if (!WARN_ON_ONCE(!link)) + list_del_rcu(&link->list); + kfree(link); + tk->tp.flags &= ~TP_FLAG_TRACE; + } else { + tk->tp.flags &= ~TP_FLAG_PROFILE; + } + } out: return ret; } diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c index c2af9b9e32d4..47221e802a4a 100644 --- a/kernel/trace/trace_uprobe.c +++ b/kernel/trace/trace_uprobe.c @@ -957,7 +957,7 @@ probe_event_disable(struct trace_uprobe *tu, struct ftrace_event_file *file) list_del_rcu(&link->list); /* synchronize with u{,ret}probe_trace_func */ - synchronize_sched(); + synchronize_rcu(); kfree(link); if (!list_empty(&tu->tp.files)) diff --git a/kernel/user_namespace.c b/kernel/user_namespace.c index cc9689628427..69210b6d5013 100644 --- a/kernel/user_namespace.c +++ b/kernel/user_namespace.c @@ -601,9 +601,26 @@ static ssize_t map_write(struct file *file, const char __user *buf, struct uid_gid_map new_map; unsigned idx; struct uid_gid_extent *extent = NULL; - unsigned long page = 0; + unsigned long page; char *kbuf, *pos, *next_line; - ssize_t ret = -EINVAL; + ssize_t ret; + + /* Only allow < page size writes at the beginning of the file */ + if ((*ppos != 0) || (count >= PAGE_SIZE)) + return -EINVAL; + + /* Get a buffer */ + page = __get_free_page(GFP_TEMPORARY); + kbuf = (char *) page; + if (!page) + return -ENOMEM; + + /* Slurp in the user data */ + if (copy_from_user(kbuf, buf, count)) { + free_page(page); + return -EFAULT; + } + kbuf[count] = '\0'; /* * The userns_state_mutex serializes all writes to any given map. @@ -637,24 +654,6 @@ static ssize_t map_write(struct file *file, const char __user *buf, if (cap_valid(cap_setid) && !file_ns_capable(file, ns, CAP_SYS_ADMIN)) goto out; - /* Get a buffer */ - ret = -ENOMEM; - page = __get_free_page(GFP_TEMPORARY); - kbuf = (char *) page; - if (!page) - goto out; - - /* Only allow <= page size writes at the beginning of the file */ - ret = -EINVAL; - if ((*ppos != 0) || (count >= PAGE_SIZE)) - goto out; - - /* Slurp in the user data */ - ret = -EFAULT; - if (copy_from_user(kbuf, buf, count)) - goto out; - kbuf[count] = '\0'; - /* Parse the user data */ ret = -EINVAL; pos = kbuf; diff --git a/kernel/utsname_sysctl.c b/kernel/utsname_sysctl.c index c8eac43267e9..d2b3b2973456 100644 --- a/kernel/utsname_sysctl.c +++ b/kernel/utsname_sysctl.c @@ -17,7 +17,7 @@ #ifdef CONFIG_PROC_SYSCTL -static void *get_uts(struct ctl_table *table, int write) +static void *get_uts(struct ctl_table *table) { char *which = table->data; struct uts_namespace *uts_ns; @@ -25,21 +25,9 @@ static void *get_uts(struct ctl_table *table, int write) uts_ns = current->nsproxy->uts_ns; which = (which - (char *)&init_uts_ns) + (char *)uts_ns; - if (!write) - down_read(&uts_sem); - else - down_write(&uts_sem); return which; } -static void put_uts(struct ctl_table *table, int write, void *which) -{ - if (!write) - up_read(&uts_sem); - else - up_write(&uts_sem); -} - /* * Special case of dostring for the UTS structure. This has locks * to observe. Should this be in kernel/sys.c ???? @@ -49,13 +37,34 @@ static int proc_do_uts_string(struct ctl_table *table, int write, { struct ctl_table uts_table; int r; + char tmp_data[__NEW_UTS_LEN + 1]; + memcpy(&uts_table, table, sizeof(uts_table)); - uts_table.data = get_uts(table, write); + uts_table.data = tmp_data; + + /* + * Buffer the value in tmp_data so that proc_dostring() can be called + * without holding any locks. + * We also need to read the original value in the write==1 case to + * support partial writes. + */ + down_read(&uts_sem); + memcpy(tmp_data, get_uts(table), sizeof(tmp_data)); + up_read(&uts_sem); r = proc_dostring(&uts_table, write, buffer, lenp, ppos); - put_uts(table, write, uts_table.data); - if (write) + if (write) { + /* + * Write back the new value. + * Note that, since we dropped uts_sem, the result can + * theoretically be incorrect if there are two parallel writes + * at non-zero offsets to the same sysctl. + */ + down_write(&uts_sem); + memcpy(get_uts(table), tmp_data, sizeof(tmp_data)); + up_write(&uts_sem); proc_sys_poll_notify(table->poll); + } return r; } diff --git a/mm/memory.c b/mm/memory.c index 8e65576031c2..376854e7367b 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -359,15 +359,6 @@ void tlb_remove_table(struct mmu_gather *tlb, void *table) { struct mmu_table_batch **batch = &tlb->batch; - /* - * When there's less then two users of this mm there cannot be a - * concurrent page-table walk. - */ - if (atomic_read(&tlb->mm->mm_users) < 2) { - __tlb_remove_table(table); - return; - } - if (*batch == NULL) { *batch = (struct mmu_table_batch *)__get_free_page(GFP_NOWAIT | __GFP_NOWARN); if (*batch == NULL) { @@ -3523,6 +3514,9 @@ int generic_access_phys(struct vm_area_struct *vma, unsigned long addr, return -EINVAL; maddr = ioremap_prot(phys_addr, PAGE_ALIGN(len + offset), prot); + if (!maddr) + return -ENOMEM; + if (write) memcpy_toio(maddr + offset, buf, len); else diff --git a/mm/slub.c b/mm/slub.c index 6a2f3f115203..35a432cc3e24 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -699,7 +699,7 @@ void object_err(struct kmem_cache *s, struct page *page, slab_panic(reason); } -static void slab_err(struct kmem_cache *s, struct page *page, +static __printf(3, 4) void slab_err(struct kmem_cache *s, struct page *page, const char *fmt, ...) { va_list args; @@ -925,12 +925,12 @@ static int check_slab(struct kmem_cache *s, struct page *page) maxobj = order_objects(compound_order(page), s->size, s->reserved); if (page->objects > maxobj) { slab_err(s, page, "objects %u > max %u", - s->name, page->objects, maxobj); + page->objects, maxobj); return 0; } if (page->inuse > page->objects) { slab_err(s, page, "inuse %u > max %u", - s->name, page->inuse, page->objects); + page->inuse, page->objects); return 0; } /* Slab_pad_check fixes things up after itself */ @@ -947,7 +947,7 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search) int nr = 0; void *fp; void *object = NULL; - unsigned long max_objects; + int max_objects; fp = page->freelist; while (fp && nr <= page->objects) { diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 80ece7cedc9f..3066e7236772 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1527,7 +1527,7 @@ static void __vunmap(const void *addr, int deallocate_pages) addr)) return; - area = remove_vm_area(addr); + area = find_vmap_area((unsigned long)addr)->vm; if (unlikely(!area)) { WARN(1, KERN_ERR "Trying to vfree() nonexistent vm area (%p)\n", addr); @@ -1537,6 +1537,7 @@ static void __vunmap(const void *addr, int deallocate_pages) debug_check_no_locks_freed(addr, get_vm_area_size(area)); debug_check_no_obj_freed(addr, get_vm_area_size(area)); + remove_vm_area(addr); if (deallocate_pages) { int i; diff --git a/mm/zswap.c b/mm/zswap.c index e2f8c7e3c643..7af943e25ddd 100644 --- a/mm/zswap.c +++ b/mm/zswap.c @@ -662,6 +662,15 @@ static int zswap_frontswap_store(unsigned type, pgoff_t offset, ret = -ENOMEM; goto reject; } + + /* A second zswap_is_full() check after + * zswap_shrink() to make sure it's now + * under the max_pool_percent + */ + if (zswap_is_full()) { + ret = -ENOMEM; + goto reject; + } } /* allocate entry */ diff --git a/net/9p/client.c b/net/9p/client.c index f24b774d2215..7122b32b310f 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -938,7 +938,7 @@ static int p9_client_version(struct p9_client *c) { int err = 0; struct p9_req_t *req; - char *version; + char *version = NULL; int msize; p9_debug(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n", diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 80d08f6664cb..9d935dc71b83 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -185,6 +185,8 @@ static void p9_mux_poll_stop(struct p9_conn *m) spin_lock_irqsave(&p9_poll_lock, flags); list_del_init(&m->poll_pending_link); spin_unlock_irqrestore(&p9_poll_lock, flags); + + flush_work(&p9_poll_work); } /** @@ -932,7 +934,7 @@ p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) if (err < 0) return err; - if (valid_ipaddr4(addr) < 0) + if (addr == NULL || valid_ipaddr4(addr) < 0) return -EINVAL; csocket = NULL; @@ -980,6 +982,9 @@ p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) csocket = NULL; + if (addr == NULL) + return -EINVAL; + if (strlen(addr) >= UNIX_PATH_MAX) { pr_err("%s (%d): address too long: %s\n", __func__, task_pid_nr(current), addr); diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 14ad43b5cf89..d00cb890398b 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c @@ -623,6 +623,9 @@ rdma_create_trans(struct p9_client *client, const char *addr, char *args) struct ib_qp_init_attr qp_attr; struct ib_device_attr devattr; + if (addr == NULL) + return -EINVAL; + /* Parse the transport specific mount options */ err = parse_opts(args, &opts); if (err < 0) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 071ac5c495fc..130180f67ae3 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -192,7 +192,7 @@ static int pack_sg_list(struct scatterlist *sg, int start, s = rest_of_page(data); if (s > count) s = count; - BUG_ON(index > limit); + BUG_ON(index >= limit); /* Make sure we don't terminate early. */ sg_unmark_end(&sg[index]); sg_set_buf(&sg[index++], data, s); @@ -238,6 +238,7 @@ pack_sg_list_p(struct scatterlist *sg, int start, int limit, s = rest_of_page(data); if (s > count) s = count; + BUG_ON(index >= limit); /* Make sure we don't terminate early. */ sg_unmark_end(&sg[index]); sg_set_page(&sg[index++], pdata[i++], s, data_off); @@ -616,6 +617,9 @@ p9_virtio_create(struct p9_client *client, const char *devname, char *args) int ret = -ENOENT; int found = 0; + if (devname == NULL) + return -EINVAL; + mutex_lock(&virtio_9p_lock); list_for_each_entry(chan, &virtio_chan_list, chan_list) { if (!strncmp(devname, chan->tag, chan->tag_len) && diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 99624495f6c2..3af082bf7c64 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -416,8 +416,8 @@ static void hidp_del_timer(struct hidp_session *session) del_timer(&session->timer); } -static void hidp_process_report(struct hidp_session *session, - int type, const u8 *data, int len, int intr) +static void hidp_process_report(struct hidp_session *session, int type, + const u8 *data, unsigned int len, int intr) { if (len > HID_MAX_BUFFER_SIZE) len = HID_MAX_BUFFER_SIZE; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 8c54cb211a4d..0882ce101ac8 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -390,7 +390,8 @@ static void sco_sock_cleanup_listen(struct sock *parent) */ static void sco_sock_kill(struct sock *sk) { - if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket) + if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket || + sock_flag(sk, SOCK_DEAD)) return; BT_DBG("sk %pK state %d", sk, sk->sk_state); diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index edbca468fa73..d8e56a5c1a94 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c @@ -131,8 +131,10 @@ static void caif_flow_cb(struct sk_buff *skb) caifd = caif_get(skb->dev); WARN_ON(caifd == NULL); - if (caifd == NULL) + if (!caifd) { + rcu_read_unlock(); return; + } caifd_hold(caifd); rcu_read_unlock(); diff --git a/net/core/dev.c b/net/core/dev.c index af29dd323dbe..dfbf18114d18 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -7046,7 +7046,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char /* We get here if we can't use the current device name */ if (!pat) goto out; - if (dev_get_valid_name(net, dev, pat) < 0) + err = dev_get_valid_name(net, dev, pat); + if (err < 0) goto out; } @@ -7058,7 +7059,6 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char dev_close(dev); /* And unlink it from device chain */ - err = -ENODEV; unlist_netdevice(dev); synchronize_net(); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9fd2c9eb54e8..51301ad3c2d9 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -1842,9 +1842,12 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) return err; } - dev->rtnl_link_state = RTNL_LINK_INITIALIZED; - - __dev_notify_flags(dev, old_flags, ~0U); + if (dev->rtnl_link_state == RTNL_LINK_INITIALIZED) { + __dev_notify_flags(dev, old_flags, 0U); + } else { + dev->rtnl_link_state = RTNL_LINK_INITIALIZED; + __dev_notify_flags(dev, old_flags, ~0U); + } return 0; } EXPORT_SYMBOL(rtnl_configure_link); diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 7f13431d0633..2f7adf089922 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -803,6 +803,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb) n->cloned = 1; n->nohdr = 0; n->peeked = 0; + C(pfmemalloc); n->destructor = NULL; C(tail); C(end); diff --git a/net/dccp/ccids/ccid2.c b/net/dccp/ccids/ccid2.c index 86a2ed0fb219..161dfcf86126 100644 --- a/net/dccp/ccids/ccid2.c +++ b/net/dccp/ccids/ccid2.c @@ -228,14 +228,16 @@ static void ccid2_cwnd_restart(struct sock *sk, const u32 now) struct ccid2_hc_tx_sock *hc = ccid2_hc_tx_sk(sk); u32 cwnd = hc->tx_cwnd, restart_cwnd, iwnd = rfc3390_bytes_to_packets(dccp_sk(sk)->dccps_mss_cache); + s32 delta = now - hc->tx_lsndtime; hc->tx_ssthresh = max(hc->tx_ssthresh, (cwnd >> 1) + (cwnd >> 2)); /* don't reduce cwnd below the initial window (IW) */ restart_cwnd = min(cwnd, iwnd); - cwnd >>= (now - hc->tx_lsndtime) / hc->tx_rto; - hc->tx_cwnd = max(cwnd, restart_cwnd); + while ((delta -= hc->tx_rto) >= 0 && cwnd > restart_cwnd) + cwnd >>= 1; + hc->tx_cwnd = max(cwnd, restart_cwnd); hc->tx_cwnd_stamp = now; hc->tx_cwnd_used = 0; diff --git a/net/dsa/slave.c b/net/dsa/slave.c index ab03e00ffe8f..95f63b79f03e 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c @@ -503,6 +503,9 @@ int dsa_slave_suspend(struct net_device *slave_dev) { struct dsa_slave_priv *p = netdev_priv(slave_dev); + if (!netif_running(slave_dev)) + return 0; + netif_device_detach(slave_dev); if (p->phy) { @@ -520,6 +523,9 @@ int dsa_slave_resume(struct net_device *slave_dev) { struct dsa_slave_priv *p = netdev_priv(slave_dev); + if (!netif_running(slave_dev)) + return 0; + netif_device_attach(slave_dev); if (p->phy) { diff --git a/net/ipc_router/ipc_router_socket.c b/net/ipc_router/ipc_router_socket.c index 8604152dc577..1641509c9352 100644 --- a/net/ipc_router/ipc_router_socket.c +++ b/net/ipc_router/ipc_router_socket.c @@ -155,6 +155,7 @@ static int msm_ipc_router_extract_msg(struct msghdr *m, return -EINVAL; } ctl_msg = (union rr_control_msg *)(temp->data); + memset(addr, 0x0, sizeof(*addr)); addr->family = AF_MSM_IPC; addr->address.addrtype = MSM_IPC_ADDR_ID; addr->address.addr.port_addr.node_id = ctl_msg->cli.node_id; @@ -163,6 +164,7 @@ static int msm_ipc_router_extract_msg(struct msghdr *m, return offset; } if (addr && (hdr->type == IPC_ROUTER_CTRL_CMD_DATA)) { + memset(addr, 0x0, sizeof(*addr)); addr->family = AF_MSM_IPC; addr->address.addrtype = MSM_IPC_ADDR_ID; addr->address.addr.port_addr.node_id = hdr->src_node_id; diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index e08003d026eb..a5e2646c859d 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -1591,9 +1591,17 @@ unsigned char *cipso_v4_optptr(const struct sk_buff *skb) int taglen; for (optlen = iph->ihl*4 - sizeof(struct iphdr); optlen > 0; ) { - if (optptr[0] == IPOPT_CIPSO) + switch (optptr[0]) { + case IPOPT_CIPSO: return optptr; - taglen = optptr[1]; + case IPOPT_END: + return NULL; + case IPOPT_NOOP: + taglen = 1; + break; + default: + taglen = optptr[1]; + } optlen -= taglen; optptr += taglen; } diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 82dc74052ee3..3ca7b4b66b8b 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c @@ -209,19 +209,19 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb) return ip_hdr(skb)->daddr; in_dev = __in_dev_get_rcu(dev); - BUG_ON(!in_dev); net = dev_net(dev); scope = RT_SCOPE_UNIVERSE; if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) { + bool vmark = in_dev && IN_DEV_SRC_VMARK(in_dev); fl4.flowi4_oif = 0; fl4.flowi4_iif = LOOPBACK_IFINDEX; fl4.daddr = ip_hdr(skb)->saddr; fl4.saddr = 0; fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); fl4.flowi4_scope = scope; - fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0; + fl4.flowi4_mark = vmark ? skb->mark : 0; if (!fib_lookup(net, &fl4, &res)) return FIB_RES_PREFSRC(net, res); } else { diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 19419b60cb37..0d950edb33c2 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c @@ -379,11 +379,6 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, { struct inet_frag_queue *q; - if (frag_mem_limit(nf) > nf->high_thresh) { - inet_frag_schedule_worker(f); - return NULL; - } - q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC); if (q == NULL) return NULL; @@ -420,6 +415,11 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, struct inet_frag_queue *q; int depth = 0; + if (!nf->high_thresh || frag_mem_limit(nf) > nf->high_thresh) { + inet_frag_schedule_worker(f); + return NULL; + } + if (frag_mem_limit(nf) > nf->low_thresh) inet_frag_schedule_worker(f); diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 7f7bf44b1b91..638adc599e06 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c @@ -459,6 +459,8 @@ static void ip_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->dev = from->dev; to->mark = from->mark; + skb_copy_hash(to, from); + /* Copy the flags to each fragment. */ IPCB(to)->flags = IPCB(from)->flags; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 648fa1490ea7..3da772ae8808 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -772,6 +772,11 @@ static void __init ic_bootp_init_ext(u8 *e) */ static inline void __init ic_bootp_init(void) { + /* Re-initialise all name servers to NONE, in case any were set via the + * "ip=" or "nfsaddrs=" kernel command line parameters: any IP addresses + * specified there will already have been decoded but are no longer + * needed + */ ic_nameservers_predef(); dev_add_pack(&bootp_packet_type); @@ -1404,6 +1409,13 @@ static int __init ip_auto_config(void) int err; unsigned int i; + /* Initialise all name servers to NONE (but only if the "ip=" or + * "nfsaddrs=" kernel command line parameters weren't decoded, otherwise + * we'll overwrite the IP addresses specified there) + */ + if (ic_set_manually == 0) + ic_nameservers_predef(); + #ifdef CONFIG_PROC_FS proc_create("pnp", S_IRUGO, init_net.proc_net, &pnp_seq_fops); #endif /* CONFIG_PROC_FS */ @@ -1605,6 +1617,7 @@ static int __init ip_auto_config_setup(char *addrs) return 1; } + /* Initialise all name servers to NONE */ ic_nameservers_predef(); /* Parse string for static IP assignment. */ diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 3f2e38a971dc..2bd31846858c 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -2081,6 +2081,7 @@ static struct xt_match ipt_builtin_mt[] __read_mostly = { .checkentry = icmp_checkentry, .proto = IPPROTO_ICMP, .family = NFPROTO_IPV4, + .me = THIS_MODULE, }, }; diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 562f50e272b6..f8841a5f8e0c 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -138,8 +138,9 @@ static int ipv4_ping_group_range(struct ctl_table *table, int write, if (write && ret == 0) { low = make_kgid(user_ns, urange[0]); high = make_kgid(user_ns, urange[1]); - if (!gid_valid(low) || !gid_valid(high) || - (urange[1] < urange[0]) || gid_lt(high, low)) { + if (!gid_valid(low) || !gid_valid(high)) + return -EINVAL; + if (urange[1] < urange[0] || gid_lt(high, low)) { low = make_kgid(&init_user_ns, 1); high = make_kgid(&init_user_ns, 0); } diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 179506f53e1e..391ef03ce2f6 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1684,7 +1684,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, * shouldn't happen. */ if (WARN(before(*seq, TCP_SKB_CB(skb)->seq), - "recvmsg bug: copied %X seq %X rcvnxt %X fl %X\n", + "TCP recvmsg seq # bug: copied %X, seq %X, rcvnxt %X, fl %X\n", *seq, TCP_SKB_CB(skb)->seq, tp->rcv_nxt, flags)) break; @@ -1697,7 +1697,7 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN) goto found_fin_ok; WARN(!(flags & MSG_PEEK), - "recvmsg bug 2: copied %X seq %X rcvnxt %X fl %X\n", + "TCP recvmsg seq # bug 2: copied %X, seq %X, rcvnxt %X, fl %X\n", *seq, TCP_SKB_CB(skb)->seq, tp->rcv_nxt, flags); } diff --git a/net/ipv4/tcp_dctcp.c b/net/ipv4/tcp_dctcp.c index b504371af742..583b9935ebb5 100644 --- a/net/ipv4/tcp_dctcp.c +++ b/net/ipv4/tcp_dctcp.c @@ -128,23 +128,14 @@ static void dctcp_ce_state_0_to_1(struct sock *sk) struct dctcp *ca = inet_csk_ca(sk); struct tcp_sock *tp = tcp_sk(sk); - /* State has changed from CE=0 to CE=1 and delayed - * ACK has not sent yet. - */ - if (!ca->ce_state && ca->delayed_ack_reserved) { - u32 tmp_rcv_nxt; - - /* Save current rcv_nxt. */ - tmp_rcv_nxt = tp->rcv_nxt; - - /* Generate previous ack with CE=0. */ - tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR; - tp->rcv_nxt = ca->prior_rcv_nxt; - - tcp_send_ack(sk); - - /* Recover current rcv_nxt. */ - tp->rcv_nxt = tmp_rcv_nxt; + if (!ca->ce_state) { + /* State has changed from CE=0 to CE=1, force an immediate + * ACK to reflect the new CE state. If an ACK was delayed, + * send that first to reflect the prior CE state. + */ + if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER) + __tcp_send_ack(sk, ca->prior_rcv_nxt); + tcp_enter_quickack_mode(sk, 1); } ca->prior_rcv_nxt = tp->rcv_nxt; @@ -158,23 +149,14 @@ static void dctcp_ce_state_1_to_0(struct sock *sk) struct dctcp *ca = inet_csk_ca(sk); struct tcp_sock *tp = tcp_sk(sk); - /* State has changed from CE=1 to CE=0 and delayed - * ACK has not sent yet. - */ - if (ca->ce_state && ca->delayed_ack_reserved) { - u32 tmp_rcv_nxt; - - /* Save current rcv_nxt. */ - tmp_rcv_nxt = tp->rcv_nxt; - - /* Generate previous ack with CE=1. */ - tp->ecn_flags |= TCP_ECN_DEMAND_CWR; - tp->rcv_nxt = ca->prior_rcv_nxt; - - tcp_send_ack(sk); - - /* Recover current rcv_nxt. */ - tp->rcv_nxt = tmp_rcv_nxt; + if (ca->ce_state) { + /* State has changed from CE=1 to CE=0, force an immediate + * ACK to reflect the new CE state. If an ACK was delayed, + * send that first to reflect the prior CE state. + */ + if (inet_csk(sk)->icsk_ack.pending & ICSK_ACK_TIMER) + __tcp_send_ack(sk, ca->prior_rcv_nxt); + tcp_enter_quickack_mode(sk, 1); } ca->prior_rcv_nxt = tp->rcv_nxt; diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index c69d8d2b8a94..25e1dab3e2b0 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -172,24 +172,27 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) } } -static void tcp_incr_quickack(struct sock *sk) +static void tcp_incr_quickack(struct sock *sk, unsigned int max_quickacks) { struct inet_connection_sock *icsk = inet_csk(sk); unsigned int quickacks = tcp_sk(sk)->rcv_wnd / (2 * icsk->icsk_ack.rcv_mss); if (quickacks == 0) quickacks = 2; + quickacks = min(quickacks, max_quickacks); if (quickacks > icsk->icsk_ack.quick) - icsk->icsk_ack.quick = min(quickacks, TCP_MAX_QUICKACKS); + icsk->icsk_ack.quick = quickacks; } -static void tcp_enter_quickack_mode(struct sock *sk) +void tcp_enter_quickack_mode(struct sock *sk, unsigned int max_quickacks) { struct inet_connection_sock *icsk = inet_csk(sk); - tcp_incr_quickack(sk); + + tcp_incr_quickack(sk, max_quickacks); icsk->icsk_ack.pingpong = 0; icsk->icsk_ack.ato = TCP_ATO_MIN; } +EXPORT_SYMBOL(tcp_enter_quickack_mode); /* Send ACKs quickly, if "quick" count is not exhausted * and the session is not interactive. @@ -219,8 +222,10 @@ static void tcp_ecn_withdraw_cwr(struct tcp_sock *tp) tp->ecn_flags &= ~TCP_ECN_DEMAND_CWR; } -static void __tcp_ecn_check_ce(struct tcp_sock *tp, const struct sk_buff *skb) +static void __tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb) { + struct tcp_sock *tp = tcp_sk(sk); + switch (TCP_SKB_CB(skb)->ip_dsfield & INET_ECN_MASK) { case INET_ECN_NOT_ECT: /* Funny extension: if ECT is not set on a segment, @@ -228,31 +233,31 @@ static void __tcp_ecn_check_ce(struct tcp_sock *tp, const struct sk_buff *skb) * it is probably a retransmit. */ if (tp->ecn_flags & TCP_ECN_SEEN) - tcp_enter_quickack_mode((struct sock *)tp); + tcp_enter_quickack_mode(sk, 2); break; case INET_ECN_CE: - if (tcp_ca_needs_ecn((struct sock *)tp)) - tcp_ca_event((struct sock *)tp, CA_EVENT_ECN_IS_CE); + if (tcp_ca_needs_ecn(sk)) + tcp_ca_event(sk, CA_EVENT_ECN_IS_CE); if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) { /* Better not delay acks, sender can have a very low cwnd */ - tcp_enter_quickack_mode((struct sock *)tp); + tcp_enter_quickack_mode(sk, 2); tp->ecn_flags |= TCP_ECN_DEMAND_CWR; } tp->ecn_flags |= TCP_ECN_SEEN; break; default: - if (tcp_ca_needs_ecn((struct sock *)tp)) - tcp_ca_event((struct sock *)tp, CA_EVENT_ECN_NO_CE); + if (tcp_ca_needs_ecn(sk)) + tcp_ca_event(sk, CA_EVENT_ECN_NO_CE); tp->ecn_flags |= TCP_ECN_SEEN; break; } } -static void tcp_ecn_check_ce(struct tcp_sock *tp, const struct sk_buff *skb) +static void tcp_ecn_check_ce(struct sock *sk, const struct sk_buff *skb) { - if (tp->ecn_flags & TCP_ECN_OK) - __tcp_ecn_check_ce(tp, skb); + if (tcp_sk(sk)->ecn_flags & TCP_ECN_OK) + __tcp_ecn_check_ce(sk, skb); } static void tcp_ecn_rcv_synack(struct tcp_sock *tp, const struct tcphdr *th) @@ -644,7 +649,7 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb) /* The _first_ data packet received, initialize * delayed ACK engine. */ - tcp_incr_quickack(sk); + tcp_incr_quickack(sk, TCP_MAX_QUICKACKS); icsk->icsk_ack.ato = TCP_ATO_MIN; } else { int m = now - icsk->icsk_ack.lrcvtime; @@ -660,13 +665,13 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb) /* Too long gap. Apparently sender failed to * restart window, so that we send ACKs quickly. */ - tcp_incr_quickack(sk); + tcp_incr_quickack(sk, TCP_MAX_QUICKACKS); sk_mem_reclaim(sk); } } icsk->icsk_ack.lrcvtime = now; - tcp_ecn_check_ce(tp, skb); + tcp_ecn_check_ce(sk, skb); if (skb->len >= 128) tcp_grow_window(sk, skb); @@ -4007,7 +4012,7 @@ static void tcp_send_dupack(struct sock *sk, const struct sk_buff *skb) if (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq && before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOST); - tcp_enter_quickack_mode(sk); + tcp_enter_quickack_mode(sk, TCP_MAX_QUICKACKS); if (tcp_is_sack(tp) && sysctl_tcp_dsack) { u32 end_seq = TCP_SKB_CB(skb)->end_seq; @@ -4235,7 +4240,7 @@ static void tcp_data_queue_ofo(struct sock *sk, struct sk_buff *skb) struct sk_buff *skb1; u32 seq, end_seq; - tcp_ecn_check_ce(tp, skb); + tcp_ecn_check_ce(sk, skb); if (unlikely(tcp_try_rmem_schedule(sk, skb, skb->truesize))) { NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPOFODROP); @@ -4507,7 +4512,7 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) tcp_dsack_set(sk, TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq); out_of_window: - tcp_enter_quickack_mode(sk); + tcp_enter_quickack_mode(sk, TCP_MAX_QUICKACKS); inet_csk_schedule_ack(sk); drop: __kfree_skb(skb); @@ -4518,8 +4523,6 @@ static void tcp_data_queue(struct sock *sk, struct sk_buff *skb) if (!before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt + tcp_receive_window(tp))) goto out_of_window; - tcp_enter_quickack_mode(sk); - if (before(TCP_SKB_CB(skb)->seq, tp->rcv_nxt)) { /* Partial packet, seq < rcv_next < end_seq */ SOCK_DEBUG(sk, "partial packet: rcv_next %X seq %X - %X\n", @@ -4658,6 +4661,7 @@ tcp_collapse(struct sock *sk, struct sk_buff_head *list, static void tcp_collapse_ofo_queue(struct sock *sk) { struct tcp_sock *tp = tcp_sk(sk); + u32 range_truesize, sum_tiny = 0; struct sk_buff *skb = skb_peek(&tp->out_of_order_queue); struct sk_buff *head; u32 start, end; @@ -4667,6 +4671,7 @@ static void tcp_collapse_ofo_queue(struct sock *sk) start = TCP_SKB_CB(skb)->seq; end = TCP_SKB_CB(skb)->end_seq; + range_truesize = skb->truesize; head = skb; for (;;) { @@ -4681,14 +4686,24 @@ static void tcp_collapse_ofo_queue(struct sock *sk) if (!skb || after(TCP_SKB_CB(skb)->seq, end) || before(TCP_SKB_CB(skb)->end_seq, start)) { - tcp_collapse(sk, &tp->out_of_order_queue, - head, skb, start, end); + /* Do not attempt collapsing tiny skbs */ + if (range_truesize != head->truesize || + end - start >= SKB_WITH_OVERHEAD(SK_MEM_QUANTUM)) { + tcp_collapse(sk, &tp->out_of_order_queue, + head, skb, start, end); + } else { + sum_tiny += range_truesize; + if (sum_tiny > sk->sk_rcvbuf >> 3) + return; + } + head = skb; if (!skb) break; /* Start new segment */ start = TCP_SKB_CB(skb)->seq; end = TCP_SKB_CB(skb)->end_seq; + range_truesize = skb->truesize; } else { if (before(TCP_SKB_CB(skb)->seq, start)) start = TCP_SKB_CB(skb)->seq; @@ -4744,6 +4759,9 @@ static int tcp_prune_queue(struct sock *sk) else if (sk_under_memory_pressure(sk)) tp->rcv_ssthresh = min(tp->rcv_ssthresh, 4U * tp->advmss); + if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) + return 0; + tcp_collapse_ofo_queue(sk); if (!skb_queue_empty(&sk->sk_receive_queue)) tcp_collapse(sk, &sk->sk_receive_queue, @@ -5515,7 +5533,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, * to stand against the temptation 8) --ANK */ inet_csk_schedule_ack(sk); - tcp_enter_quickack_mode(sk); + tcp_enter_quickack_mode(sk, TCP_MAX_QUICKACKS); inet_csk_reset_xmit_timer(sk, ICSK_TIME_DACK, TCP_DELACK_MAX, TCP_RTO_MAX); diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3d4e828a20e2..98b471eaf4a0 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -183,8 +183,13 @@ static void tcp_event_data_sent(struct tcp_sock *tp, } /* Account for an ACK we sent. */ -static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts) +static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, + u32 rcv_nxt) { + struct tcp_sock *tp = tcp_sk(sk); + + if (unlikely(rcv_nxt != tp->rcv_nxt)) + return; /* Special ACK sent by DCTCP to reflect ECN */ tcp_dec_quickack_mode(sk, pkts); inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); } @@ -884,8 +889,8 @@ void tcp_wfree(struct sk_buff *skb) * We are working here with either a clone of the original * SKB, or a fresh unique copy made by the retransmit engine. */ -static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, - gfp_t gfp_mask) +static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, + int clone_it, gfp_t gfp_mask, u32 rcv_nxt) { const struct inet_connection_sock *icsk = inet_csk(sk); struct inet_sock *inet; @@ -948,7 +953,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, th->source = inet->inet_sport; th->dest = inet->inet_dport; th->seq = htonl(tcb->seq); - th->ack_seq = htonl(tp->rcv_nxt); + th->ack_seq = htonl(rcv_nxt); *(((__be16 *)th) + 6) = htons(((tcp_header_size >> 2) << 12) | tcb->tcp_flags); @@ -990,7 +995,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, icsk->icsk_af_ops->send_check(sk, skb); if (likely(tcb->tcp_flags & TCPHDR_ACK)) - tcp_event_ack_sent(sk, tcp_skb_pcount(skb)); + tcp_event_ack_sent(sk, tcp_skb_pcount(skb), rcv_nxt); if (skb->len != tcp_header_size) tcp_event_data_sent(tp, sk); @@ -1019,6 +1024,13 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, return net_xmit_eval(err); } +static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, + gfp_t gfp_mask) +{ + return __tcp_transmit_skb(sk, skb, clone_it, gfp_mask, + tcp_sk(sk)->rcv_nxt); +} + /* This routine just queues the buffer for sending. * * NOTE: probe0 timer is not checked, do not forget tcp_push_pending_frames, @@ -3220,7 +3232,7 @@ void tcp_send_delayed_ack(struct sock *sk) } /* This routine sends an ack and also updates the window. */ -void tcp_send_ack(struct sock *sk) +void __tcp_send_ack(struct sock *sk, u32 rcv_nxt) { struct sk_buff *buff; @@ -3249,9 +3261,14 @@ void tcp_send_ack(struct sock *sk) /* Send it off, this clears delayed acks for us. */ skb_mstamp_get(&buff->skb_mstamp); - tcp_transmit_skb(sk, buff, 0, sk_gfp_atomic(sk, GFP_ATOMIC)); + __tcp_transmit_skb(sk, buff, 0, sk_gfp_atomic(sk, GFP_ATOMIC), rcv_nxt); +} +EXPORT_SYMBOL_GPL(__tcp_send_ack); + +void tcp_send_ack(struct sock *sk) +{ + __tcp_send_ack(sk, tcp_sk(sk)->rcv_nxt); } -EXPORT_SYMBOL_GPL(tcp_send_ack); /* This routine sends a packet with an out of date sequence * number. It assumes the other end will try to ack it. diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 08c58e46bb51..1101e67a0ee1 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -533,6 +533,8 @@ static void ip6_copy_metadata(struct sk_buff *to, struct sk_buff *from) to->dev = from->dev; to->mark = from->mark; + skb_copy_hash(to, from); + #ifdef CONFIG_NET_SCHED to->tc_index = from->tc_index; #endif diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 9cc16fa524a6..5a8c7b764253 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -2062,7 +2062,8 @@ void ipv6_mc_dad_complete(struct inet6_dev *idev) mld_send_initial_cr(idev); idev->mc_dad_count--; if (idev->mc_dad_count) - mld_dad_start_timer(idev, idev->mc_maxdelay); + mld_dad_start_timer(idev, + unsolicited_report_interval(idev)); } } @@ -2074,7 +2075,8 @@ static void mld_dad_timer_expire(unsigned long data) if (idev->mc_dad_count) { idev->mc_dad_count--; if (idev->mc_dad_count) - mld_dad_start_timer(idev, idev->mc_maxdelay); + mld_dad_start_timer(idev, + unsolicited_report_interval(idev)); } in6_dev_put(idev); } @@ -2432,7 +2434,8 @@ static void mld_ifc_timer_expire(unsigned long data) if (idev->mc_ifc_count) { idev->mc_ifc_count--; if (idev->mc_ifc_count) - mld_ifc_start_timer(idev, idev->mc_maxdelay); + mld_ifc_start_timer(idev, + unsolicited_report_interval(idev)); } in6_dev_put(idev); } diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 22d5002f6030..71e0084ca383 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -2083,6 +2083,7 @@ static struct xt_match ip6t_builtin_mt[] __read_mostly = { .checkentry = icmp6_checkentry, .proto = IPPROTO_ICMPV6, .family = NFPROTO_IPV6, + .me = THIS_MODULE, }, }; diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index d235ed7f47ab..4644d4e2a8bc 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c @@ -118,7 +118,7 @@ static int nf_ct_frag6_sysctl_register(struct net *net) if (hdr == NULL) goto err_reg; - net->nf_frag.sysctl.frags_hdr = hdr; + net->nf_frag_frags_hdr = hdr; return 0; err_reg: @@ -132,8 +132,8 @@ static void __net_exit nf_ct_frags6_sysctl_unregister(struct net *net) { struct ctl_table *table; - table = net->nf_frag.sysctl.frags_hdr->ctl_table_arg; - unregister_net_sysctl_table(net->nf_frag.sysctl.frags_hdr); + table = net->nf_frag_frags_hdr->ctl_table_arg; + unregister_net_sysctl_table(net->nf_frag_frags_hdr); if (!net_eq(net, &init_net)) kfree(table); } diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index e3344bb096bd..9877e2ed1755 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c @@ -1141,7 +1141,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len /* Get routing info from the tunnel socket */ skb_dst_drop(skb); - skb_dst_set(skb, dst_clone(__sk_dst_check(sk, 0))); + skb_dst_set(skb, sk_dst_check(sk, 0)); inet = inet_sk(sk); fl = &inet->cork.fl; diff --git a/net/llc/llc_core.c b/net/llc/llc_core.c index 842851cef698..e896a2c53b12 100644 --- a/net/llc/llc_core.c +++ b/net/llc/llc_core.c @@ -73,8 +73,8 @@ struct llc_sap *llc_sap_find(unsigned char sap_value) rcu_read_lock_bh(); sap = __llc_sap_find(sap_value); - if (sap) - llc_sap_hold(sap); + if (!sap || !llc_sap_hold_safe(sap)) + sap = NULL; rcu_read_unlock_bh(); return sap; } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 9f5a931eedb9..285c82cdac86 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1876,7 +1876,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) if (!sta->uploaded) continue; - if (sta->sdata->vif.type != NL80211_IFTYPE_AP) + if (sta->sdata->vif.type != NL80211_IFTYPE_AP && + sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN) continue; for (state = IEEE80211_STA_NOTEXIST; diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index cb372f96f10d..a46e6915a9ce 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c @@ -244,14 +244,14 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = * We currently ignore Sync packets * * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ - sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, + sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, }, [DCCP_PKT_SYNCACK] = { /* * We currently ignore SyncAck packets * * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ - sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, + sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, }, }, [CT_DCCP_ROLE_SERVER] = { @@ -372,14 +372,14 @@ dccp_state_table[CT_DCCP_ROLE_MAX + 1][DCCP_PKT_SYNCACK + 1][CT_DCCP_MAX + 1] = * We currently ignore Sync packets * * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ - sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, + sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, }, [DCCP_PKT_SYNCACK] = { /* * We currently ignore SyncAck packets * * sNO, sRQ, sRS, sPO, sOP, sCR, sCG, sTW */ - sIG, sIG, sIG, sIG, sIG, sIG, sIG, sIG, + sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, }, }, }; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 154cc0556dc1..bb7cf74d881c 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -3873,6 +3873,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, } if (req->tp_block_nr) { + unsigned int min_frame_size; + /* Sanity tests and some calculations */ err = -EBUSY; if (unlikely(rb->pg_vec)) @@ -3895,12 +3897,12 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, goto out; if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) goto out; + min_frame_size = po->tp_hdrlen + po->tp_reserve; if (po->tp_version >= TPACKET_V3 && - req->tp_block_size <= - BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + sizeof(struct tpacket3_hdr)) + req->tp_block_size < + BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv) + min_frame_size) goto out; - if (unlikely(req->tp_frame_size < po->tp_hdrlen + - po->tp_reserve)) + if (unlikely(req->tp_frame_size < min_frame_size)) goto out; if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) goto out; diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index 30f10fb07f4a..30ec75976d29 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c @@ -368,22 +368,20 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base, tcf_bind_filter(tp, &cr.res, base); } - if (old_r) - tcf_exts_change(tp, &r->exts, &e); - else - tcf_exts_change(tp, &cr.exts, &e); - if (old_r && old_r != r) tcindex_filter_result_init(old_r); oldp = p; r->res = cr.res; + tcf_exts_change(tp, &r->exts, &e); + rcu_assign_pointer(tp->root, cp); if (r == &new_filter_result) { struct tcindex_filter *nfp; struct tcindex_filter __rcu **fp; + f->result.res = r->res; tcf_exts_change(tp, &f->result.exts, &r->exts); fp = cp->h + (handle % cp->hash); diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c index e8d3313ea2c9..b1c9741d5da8 100644 --- a/net/vmw_vsock/af_vsock.c +++ b/net/vmw_vsock/af_vsock.c @@ -431,14 +431,14 @@ static int vsock_send_shutdown(struct sock *sk, int mode) return transport->shutdown(vsock_sk(sk), mode); } -void vsock_pending_work(struct work_struct *work) +static void vsock_pending_work(struct work_struct *work) { struct sock *sk; struct sock *listener; struct vsock_sock *vsk; bool cleanup; - vsk = container_of(work, struct vsock_sock, dwork.work); + vsk = container_of(work, struct vsock_sock, pending_work.work); sk = sk_vsock(vsk); listener = vsk->listener; cleanup = true; @@ -478,7 +478,6 @@ void vsock_pending_work(struct work_struct *work) sock_put(sk); sock_put(listener); } -EXPORT_SYMBOL_GPL(vsock_pending_work); /**** SOCKET OPERATIONS ****/ @@ -577,6 +576,8 @@ static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr) return retval; } +static void vsock_connect_timeout(struct work_struct *work); + struct sock *__vsock_create(struct net *net, struct socket *sock, struct sock *parent, @@ -618,6 +619,8 @@ struct sock *__vsock_create(struct net *net, vsk->sent_request = false; vsk->ignore_connecting_rst = false; vsk->peer_shutdown = 0; + INIT_DELAYED_WORK(&vsk->connect_work, vsock_connect_timeout); + INIT_DELAYED_WORK(&vsk->pending_work, vsock_pending_work); psk = parent ? vsock_sk(parent) : NULL; if (parent) { @@ -1095,7 +1098,7 @@ static void vsock_connect_timeout(struct work_struct *work) struct sock *sk; struct vsock_sock *vsk; - vsk = container_of(work, struct vsock_sock, dwork.work); + vsk = container_of(work, struct vsock_sock, connect_work.work); sk = sk_vsock(vsk); lock_sock(sk); @@ -1196,9 +1199,7 @@ static int vsock_stream_connect(struct socket *sock, struct sockaddr *addr, * timeout fires. */ sock_hold(sk); - INIT_DELAYED_WORK(&vsk->dwork, - vsock_connect_timeout); - schedule_delayed_work(&vsk->dwork, timeout); + schedule_delayed_work(&vsk->connect_work, timeout); /* Skip ahead to preserve error code set above. */ goto out_wait; diff --git a/net/vmw_vsock/vmci_transport.c b/net/vmw_vsock/vmci_transport.c index 9bb63ffec4f2..88ed7cf8eda6 100644 --- a/net/vmw_vsock/vmci_transport.c +++ b/net/vmw_vsock/vmci_transport.c @@ -1127,8 +1127,7 @@ static int vmci_transport_recv_listen(struct sock *sk, vpending->listener = sk; sock_hold(sk); sock_hold(pending); - INIT_DELAYED_WORK(&vpending->dwork, vsock_pending_work); - schedule_delayed_work(&vpending->dwork, HZ); + schedule_delayed_work(&vpending->pending_work, HZ); out: return err; diff --git a/net/wireless/db.txt b/net/wireless/db.txt index 7bdcb4be5b7b..3048c5e0aaec 100644 --- a/net/wireless/db.txt +++ b/net/wireless/db.txt @@ -37,9 +37,10 @@ country AI: DFS-ETSI country AL: DFS-ETSI (2402 - 2482 @ 40), (20) - (5150 - 5250 @ 80), (23), AUTO-BW - (5250 - 5350 @ 80), (23), DFS, AUTO-BW - (5470 - 5710 @ 160), (30), DFS + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country AM: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -50,7 +51,8 @@ country AN: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country AR: (2402 - 2482 @ 40), (36) @@ -71,16 +73,8 @@ country AT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -107,7 +101,8 @@ country BA: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -125,16 +120,8 @@ country BE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -149,16 +136,8 @@ country BG: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -241,16 +220,8 @@ country CH: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country CI: DFS-FCC (2402 - 2482 @ 40), (20) @@ -300,16 +271,8 @@ country CY: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -321,16 +284,8 @@ country CZ: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -351,16 +306,8 @@ country DE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -368,16 +315,8 @@ country DK: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -410,16 +349,8 @@ country EE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -432,16 +363,8 @@ country ES: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -455,16 +378,8 @@ country FI: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -479,16 +394,8 @@ country FR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -496,16 +403,8 @@ country GB: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -527,7 +426,8 @@ country GF: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country GH: DFS-FCC (2402 - 2482 @ 40), (20) @@ -558,16 +458,8 @@ country GR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -605,16 +497,8 @@ country HR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -629,16 +513,8 @@ country HU: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -651,17 +527,8 @@ country IE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 60 gHz band channels 1-4, ref: Etsi En 302 567 - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -685,16 +552,8 @@ country IS: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -702,16 +561,8 @@ country IT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -729,9 +580,9 @@ country JO: country JP: DFS-JP (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (20), AUTO-BW, NO-OUTDOOR - (5250 - 5330 @ 80), (20), DFS, AUTO-BW, NO-OUTDOOR - (5490 - 5710 @ 160), (20), DFS + (5170 - 5250 @ 80), (23), AUTO-BW, NO-OUTDOOR + (5250 - 5330 @ 80), (26), DFS, AUTO-BW, NO-OUTDOOR + (5490 - 5710 @ 160), (26), DFS # 60 GHz band channels 2-4 at 10mW, # ref: http://www.arib.or.jp/english/html/overview/doc/1-STD-T74v1_1.pdf (59000 - 66000 @ 2160), (10 mW) @@ -758,8 +609,8 @@ country KN: DFS-FCC country KR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (20), AUTO-BW - (5250 - 5330 @ 80), (20), DFS, AUTO-BW - (5490 - 5730 @ 160), (30), DFS + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5710 @ 160), (30), DFS (5735 - 5835 @ 80), (30) # 60 GHz band channels 1-4, # ref: http://www.law.go.kr/%ED%96%89%EC%A0%95%EA%B7%9C%EC%B9%99/%EB%AC%B4%EC%84%A0%EC%84%A4%EB%B9%84%EA%B7%9C%EC%B9%99 @@ -804,16 +655,8 @@ country LI: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country LK: DFS-FCC (2402 - 2482 @ 40), (20) @@ -832,16 +675,8 @@ country LT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -849,16 +684,8 @@ country LU: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -866,16 +693,8 @@ country LV: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -888,19 +707,22 @@ country MC: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MD: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country ME: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MF: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -919,7 +741,8 @@ country MK: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -948,7 +771,8 @@ country MQ: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MR: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -960,25 +784,17 @@ country MT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR -country MU: DFS-FCC +country MU: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (24), AUTO-BW - (5250 - 5330 @ 80), (24), DFS, AUTO-BW - (5490 - 5730 @ 160), (24), DFS - (5735 - 5835 @ 80), (30) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country MV: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -1029,16 +845,8 @@ country NL: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1046,16 +854,8 @@ country NO: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1079,9 +879,10 @@ country OM: DFS-ETSI country PA: (2402 - 2472 @ 40), (36) - (5170 - 5250 @ 80), (23), AUT0-BW - (5250 - 5330 @ 80), (30), AUTO-BW - (5735 - 5835 @ 80), (36) + (5170 - 5250 @ 80), (30), AUT0-BW + (5250 - 5330 @ 80), (24), AUTO-BW + (5490 - 5730 @ 160), (24), + (5735 - 5835 @ 80), (30) country PE: DFS-FCC (2402 - 2482 @ 40), (20) @@ -1094,7 +895,8 @@ country PF: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country PG: DFS-FCC (2402 - 2482 @ 40), (20) @@ -1118,16 +920,8 @@ country PL: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1135,7 +929,8 @@ country PM: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country PR: DFS-FCC (2402 - 2472 @ 40), (30) @@ -1148,16 +943,8 @@ country PT: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1175,9 +962,12 @@ country PY: DFS-FCC (5490 - 5730 @ 160), (24), DFS (5735 - 5835 @ 80), (30) -country QA: +country QA: DFS-ETSI (2402 - 2482 @ 40), (20) - (5735 - 5835 @ 80), (30) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5730 @ 160), (20), DFS + (5735 - 5875 @ 80), (20) country RE: DFS-ETSI (2402 - 2482 @ 40), (20) @@ -1189,16 +979,8 @@ country RO: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1208,7 +990,8 @@ country RS: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1237,16 +1020,8 @@ country SE: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1261,16 +1036,8 @@ country SI: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1278,16 +1045,8 @@ country SK: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS - # 5.9ghz band - # reference: http://www.etsi.org/deliver/etsi_en/302500_302599/302571/01.02.00_20/en_302571v010200a.pdf - (5850 - 5870 @ 10), (30) - (5860 - 5880 @ 10), (30) - (5870 - 5890 @ 10), (30) - (5880 - 5900 @ 10), (30) - (5890 - 5910 @ 10), (30) - (5900 - 5920 @ 10), (30) - (5910 - 5930 @ 10), (30) + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1344,7 +1103,8 @@ country TR: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1375,10 +1135,10 @@ country TZ: # disputable definitions there. country UA: DFS-ETSI (2402 - 2482 @ 40), (20) - (5170 - 5250 @ 80), (20), AUTO-BW - (5250 - 5330 @ 80), (20), DFS, AUTO-BW - (5490 - 5670 @ 160), (20), DFS - (5735 - 5835 @ 80), (20) + (5170 - 5250 @ 80), (23), AUTO-BW + (5250 - 5330 @ 80), (23), DFS, AUTO-BW + (5490 - 5710 @ 160), (24), DFS + (5735 - 5835 @ 80), (24) # 60 gHz band channels 1-4, ref: Etsi En 302 567 (57240 - 65880 @ 2160), (40), NO-OUTDOOR @@ -1427,7 +1187,8 @@ country VC: DFS-ETSI (2402 - 2482 @ 40), (20) (5170 - 5250 @ 80), (23), AUTO-BW (5250 - 5330 @ 80), (23), DFS, AUTO-BW - (5490 - 5710 @ 160), (30), DFS + (5490 - 5730 @ 160), (30), DFS + (5735 - 5875 @ 80), (14) country VE: DFS-FCC (2402 - 2482 @ 40), (30) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index d442f8736d6c..b900f06436bc 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3899,6 +3899,7 @@ static int parse_station_flags(struct genl_info *info, params->sta_flags_mask = BIT(NL80211_STA_FLAG_AUTHENTICATED) | BIT(NL80211_STA_FLAG_MFP) | BIT(NL80211_STA_FLAG_AUTHORIZED); + break; default: return -EINVAL; } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index e708d6d24898..a408410f428d 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -2297,6 +2297,9 @@ struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE) return make_blackhole(net, dst_orig->ops->family, dst_orig); + if (IS_ERR(dst)) + dst_release(dst_orig); + return dst; } EXPORT_SYMBOL(xfrm_lookup_route); diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index a4f14350563e..bb5ae90b5011 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c @@ -956,10 +956,12 @@ static inline int xfrm_nlmsg_multicast(struct net *net, struct sk_buff *skb, { struct sock *nlsk = rcu_dereference(net->xfrm.nlsk); - if (nlsk) - return nlmsg_multicast(nlsk, skb, pid, group, GFP_ATOMIC); - else - return -1; + if (!nlsk) { + kfree_skb(skb); + return -EPIPE; + } + + return nlmsg_multicast(nlsk, skb, pid, group, GFP_ATOMIC); } static inline size_t xfrm_spdinfo_msgsize(void) @@ -1598,9 +1600,11 @@ static inline size_t userpolicy_type_attrsize(void) #ifdef CONFIG_XFRM_SUB_POLICY static int copy_to_user_policy_type(u8 type, struct sk_buff *skb) { - struct xfrm_userpolicy_type upt = { - .type = type, - }; + struct xfrm_userpolicy_type upt; + + /* Sadly there are two holes in struct xfrm_userpolicy_type */ + memset(&upt, 0, sizeof(upt)); + upt.type = type; return nla_put(skb, XFRMA_POLICY_TYPE, sizeof(upt), &upt); } diff --git a/scripts/depmod.sh b/scripts/depmod.sh index 122599b1c13b..ea1e96921e3b 100755 --- a/scripts/depmod.sh +++ b/scripts/depmod.sh @@ -10,10 +10,16 @@ DEPMOD=$1 KERNELRELEASE=$2 SYMBOL_PREFIX=$3 -if ! test -r System.map -a -x "$DEPMOD"; then +if ! test -r System.map ; then exit 0 fi +if [ -z $(command -v $DEPMOD) ]; then + echo "'make modules_install' requires $DEPMOD. Please install it." >&2 + echo "This is probably in the kmod package." >&2 + exit 1 +fi + # older versions of depmod don't support -P # support was added in module-init-tools 3.13 if test -n "$SYMBOL_PREFIX"; then diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index a72b516b319e..59350f6b7e8d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2037,6 +2037,7 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) struct smack_known *skp = smk_of_task_struct(p); isp->smk_inode = skp; + isp->smk_flags |= SMK_INODE_INSTANT; } /* diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index 082509eb805d..c5fc489de26f 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c @@ -239,16 +239,12 @@ int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size, int err; while ((err = snd_dma_alloc_pages(type, device, size, dmab)) < 0) { - size_t aligned_size; if (err != -ENOMEM) return err; if (size <= PAGE_SIZE) return -ENOMEM; - aligned_size = PAGE_SIZE << get_order(size); - if (size != aligned_size) - size = aligned_size; - else - size >>= 1; + size >>= 1; + size = PAGE_SIZE << get_order(size); } if (! dmab->area) return -ENOMEM; diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c index ef494ffc1369..975a7c939d2f 100644 --- a/sound/core/seq/seq_virmidi.c +++ b/sound/core/seq/seq_virmidi.c @@ -163,6 +163,7 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, int count, res; unsigned char buf[32], *pbuf; unsigned long flags; + bool check_resched = !in_atomic(); if (up) { vmidi->trigger = 1; @@ -200,6 +201,15 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream, vmidi->event.type = SNDRV_SEQ_EVENT_NONE; } } + if (!check_resched) + continue; + /* do temporary unlock & cond_resched() for avoiding + * CPU soft lockup, which may happen via a write from + * a huge rawmidi buffer + */ + spin_unlock_irqrestore(&substream->runtime->lock, flags); + cond_resched(); + spin_lock_irqsave(&substream->runtime->lock, flags); } out: spin_unlock_irqrestore(&substream->runtime->lock, flags); diff --git a/sound/pci/cs5535audio/cs5535audio.h b/sound/pci/cs5535audio/cs5535audio.h index 0579daa62215..425d1b664029 100644 --- a/sound/pci/cs5535audio/cs5535audio.h +++ b/sound/pci/cs5535audio/cs5535audio.h @@ -66,9 +66,9 @@ struct cs5535audio_dma_ops { }; struct cs5535audio_dma_desc { - u32 addr; - u16 size; - u16 ctlreserved; + __le32 addr; + __le16 size; + __le16 ctlreserved; }; struct cs5535audio_dma { diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c index 9c2dc911d8d7..709f1c584d3e 100644 --- a/sound/pci/cs5535audio/cs5535audio_pcm.c +++ b/sound/pci/cs5535audio/cs5535audio_pcm.c @@ -158,8 +158,8 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au, lastdesc->addr = cpu_to_le32((u32) dma->desc_buf.addr); lastdesc->size = 0; lastdesc->ctlreserved = cpu_to_le16(PRD_JMP); - jmpprd_addr = cpu_to_le32(lastdesc->addr + - (sizeof(struct cs5535audio_dma_desc)*periods)); + jmpprd_addr = (u32)dma->desc_buf.addr + + sizeof(struct cs5535audio_dma_desc) * periods; dma->substream = substream; dma->period_bytes = period_bytes; diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c index 36f0b8646417..0e6dd2464e81 100644 --- a/sound/pci/emu10k1/emupcm.c +++ b/sound/pci/emu10k1/emupcm.c @@ -1875,7 +1875,9 @@ int snd_emu10k1_pcm_efx(struct snd_emu10k1 *emu, int device, if (!kctl) return -ENOMEM; kctl->id.device = device; - snd_ctl_add(emu->card, kctl); + err = snd_ctl_add(emu->card, kctl); + if (err < 0) + return err; snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(emu->pci), 64*1024, 64*1024); diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c index 4f1f69be1865..8c778fa33031 100644 --- a/sound/pci/emu10k1/memory.c +++ b/sound/pci/emu10k1/memory.c @@ -237,13 +237,13 @@ search_empty(struct snd_emu10k1 *emu, int size) static int is_valid_page(struct snd_emu10k1 *emu, dma_addr_t addr) { if (addr & ~emu->dma_mask) { - dev_err(emu->card->dev, + dev_err_ratelimited(emu->card->dev, "max memory size is 0x%lx (addr = 0x%lx)!!\n", emu->dma_mask, (unsigned long)addr); return 0; } if (addr & (EMUPAGESIZE-1)) { - dev_err(emu->card->dev, "page is not aligned\n"); + dev_err_ratelimited(emu->card->dev, "page is not aligned\n"); return 0; } return 1; @@ -334,7 +334,7 @@ snd_emu10k1_alloc_pages(struct snd_emu10k1 *emu, struct snd_pcm_substream *subst else addr = snd_pcm_sgbuf_get_addr(substream, ofs); if (! is_valid_page(emu, addr)) { - dev_err(emu->card->dev, + dev_err_ratelimited(emu->card->dev, "emu: failure page = %d\n", idx); mutex_unlock(&hdr->block_mutex); return NULL; diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c index c5038303a126..0fd39b2f75cc 100644 --- a/sound/pci/fm801.c +++ b/sound/pci/fm801.c @@ -1070,11 +1070,19 @@ static int snd_fm801_mixer(struct fm801 *chip) if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97_sec)) < 0) return err; } - for (i = 0; i < FM801_CONTROLS; i++) - snd_ctl_add(chip->card, snd_ctl_new1(&snd_fm801_controls[i], chip)); + for (i = 0; i < FM801_CONTROLS; i++) { + err = snd_ctl_add(chip->card, + snd_ctl_new1(&snd_fm801_controls[i], chip)); + if (err < 0) + return err; + } if (chip->multichannel) { - for (i = 0; i < FM801_CONTROLS_MULTI; i++) - snd_ctl_add(chip->card, snd_ctl_new1(&snd_fm801_controls_multi[i], chip)); + for (i = 0; i < FM801_CONTROLS_MULTI; i++) { + err = snd_ctl_add(chip->card, + snd_ctl_new1(&snd_fm801_controls_multi[i], chip)); + if (err < 0) + return err; + } } return 0; } diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c index 4f7ffa8c4a0d..c1ecee56c7f9 100644 --- a/sound/pci/hda/patch_ca0132.c +++ b/sound/pci/hda/patch_ca0132.c @@ -38,6 +38,10 @@ /* Enable this to see controls for tuning purpose. */ /*#define ENABLE_TUNING_CONTROLS*/ +#ifdef ENABLE_TUNING_CONTROLS +#include +#endif + #define FLOAT_ZERO 0x00000000 #define FLOAT_ONE 0x3f800000 #define FLOAT_TWO 0x40000000 @@ -3037,8 +3041,8 @@ static int equalizer_ctl_put(struct snd_kcontrol *kcontrol, return 1; } -static const DECLARE_TLV_DB_SCALE(voice_focus_db_scale, 2000, 100, 0); -static const DECLARE_TLV_DB_SCALE(eq_db_scale, -2400, 100, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(voice_focus_db_scale, 2000, 100, 0); +static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(eq_db_scale, -2400, 100, 0); static int add_tuning_control(struct hda_codec *codec, hda_nid_t pnid, hda_nid_t nid, diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c index 5c541ed723dd..5c7fbf403451 100644 --- a/sound/pci/vx222/vx222_ops.c +++ b/sound/pci/vx222/vx222_ops.c @@ -270,7 +270,7 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, length >>= 2; /* in 32bit words */ /* Transfer using pseudo-dma. */ for (; length > 0; length--) { - outl(cpu_to_le32(*addr), port); + outl(*addr, port); addr++; } addr = (u32 *)runtime->dma_area; @@ -280,7 +280,7 @@ static void vx2_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, count >>= 2; /* in 32bit words */ /* Transfer using pseudo-dma. */ for (; count > 0; count--) { - outl(cpu_to_le32(*addr), port); + outl(*addr, port); addr++; } @@ -308,7 +308,7 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, length >>= 2; /* in 32bit words */ /* Transfer using pseudo-dma. */ for (; length > 0; length--) - *addr++ = le32_to_cpu(inl(port)); + *addr++ = inl(port); addr = (u32 *)runtime->dma_area; pipe->hw_ptr = 0; } @@ -316,7 +316,7 @@ static void vx2_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, count >>= 2; /* in 32bit words */ /* Transfer using pseudo-dma. */ for (; count > 0; count--) - *addr++ = le32_to_cpu(inl(port)); + *addr++ = inl(port); vx2_release_pseudo_dma(chip); } diff --git a/sound/pcmcia/vx/vxp_ops.c b/sound/pcmcia/vx/vxp_ops.c index 56aa1ba73ccc..49a883341eff 100644 --- a/sound/pcmcia/vx/vxp_ops.c +++ b/sound/pcmcia/vx/vxp_ops.c @@ -375,7 +375,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, length >>= 1; /* in 16bit words */ /* Transfer using pseudo-dma. */ for (; length > 0; length--) { - outw(cpu_to_le16(*addr), port); + outw(*addr, port); addr++; } addr = (unsigned short *)runtime->dma_area; @@ -385,7 +385,7 @@ static void vxp_dma_write(struct vx_core *chip, struct snd_pcm_runtime *runtime, count >>= 1; /* in 16bit words */ /* Transfer using pseudo-dma. */ for (; count > 0; count--) { - outw(cpu_to_le16(*addr), port); + outw(*addr, port); addr++; } vx_release_pseudo_dma(chip); @@ -417,7 +417,7 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, length >>= 1; /* in 16bit words */ /* Transfer using pseudo-dma. */ for (; length > 0; length--) - *addr++ = le16_to_cpu(inw(port)); + *addr++ = inw(port); addr = (unsigned short *)runtime->dma_area; pipe->hw_ptr = 0; } @@ -425,12 +425,12 @@ static void vxp_dma_read(struct vx_core *chip, struct snd_pcm_runtime *runtime, count >>= 1; /* in 16bit words */ /* Transfer using pseudo-dma. */ for (; count > 1; count--) - *addr++ = le16_to_cpu(inw(port)); + *addr++ = inw(port); /* Disable DMA */ pchip->regDIALOG &= ~VXP_DLG_DMAREAD_SEL_MASK; vx_outb(chip, DIALOG, pchip->regDIALOG); /* Read the last word (16 bits) */ - *addr = le16_to_cpu(inw(port)); + *addr = inw(port); /* Disable 16-bit accesses */ pchip->regDIALOG &= ~VXP_DLG_DMA16_SEL_MASK; vx_outb(chip, DIALOG, pchip->regDIALOG); diff --git a/sound/soc/codecs/audio-ext-clk.c b/sound/soc/codecs/audio-ext-clk.c index fda1158682d9..4004fa74c9ba 100644 --- a/sound/soc/codecs/audio-ext-clk.c +++ b/sound/soc/codecs/audio-ext-clk.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -229,31 +229,62 @@ static int audio_ext_set_lpass_mclk_v1(struct clk *clk, return ret; } -static int audio_ext_set_lpass_mclk_v2(enum clk_enablement enable) +static int audio_ext_set_lpass_mclk_v2(struct clk *clk, + enum clk_enablement enable) { struct afe_clk_set m_clk = lpass_default2; struct afe_clk_set ibit_clk = lpass_default2; - int ret = 0; + struct audio_ext_lpass_mclk *audio_lpass_mclk; + int ret = 0, val = 0; pr_debug("%s: Setting clock using v2, enable(%d)\n", __func__, enable); - /* Set both mclk and ibit clocks when using LPASS_CLK_VER_2 */ - m_clk.enable = enable; - ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &m_clk); - if (ret < 0) { - pr_err("%s: afe_set_lpass_clock_v2 failed for mclk_3 with ret %d\n", - __func__, ret); + audio_lpass_mclk = container_of(clk, struct audio_ext_lpass_mclk, c); + if (audio_lpass_mclk == NULL) { + pr_err("%s: audio_lpass_mclk is NULL\n", __func__); + ret = -EINVAL; goto done; } - ibit_clk.clk_id = Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT; - ibit_clk.clk_freq_in_hz = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ; - ibit_clk.enable = enable; - ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, &ibit_clk); - if (ret < 0) { - pr_err("%s: afe_set_lpass_clock_v2 failed for ibit with ret %d\n", - __func__, ret); - goto err_ibit_clk_set; + if (!audio_lpass_mclk->lpass_clock) { + /* Set both mclk and ibit clocks when using LPASS_CLK_VER_2 */ + m_clk.enable = enable; + ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, + &m_clk); + if (ret < 0) { + pr_err("%s: afe_set_lpass_clock_v2 failed for mclk_3\n" + "with ret %d\n", __func__, ret); + goto done; + } + + ibit_clk.clk_id = Q6AFE_LPASS_CLK_ID_PRI_MI2S_IBIT; + ibit_clk.clk_freq_in_hz = Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ; + ibit_clk.enable = enable; + ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, + &ibit_clk); + if (ret < 0) { + pr_err("%s: afe_set_lpass_clock_v2 failed for ibit\n" + "with ret %d\n", __func__, ret); + goto err_ibit_clk_set; + } + } else { + if (audio_lpass_mclk->lpass_csr_gpio_mux_spkrctl_vaddr && + enable) { + val = ioread32(audio_lpass_mclk-> + lpass_csr_gpio_mux_spkrctl_vaddr); + val = val | 0x00000002; + iowrite32(val, audio_lpass_mclk-> + lpass_csr_gpio_mux_spkrctl_vaddr); + } + + digital_cdc_core_clk.enable = enable; + ret = afe_set_lpass_clock_v2(AFE_PORT_ID_PRIMARY_MI2S_RX, + &digital_cdc_core_clk); + if (ret < 0) { + pr_err("%s: afe_set_digital_codec_core_clock failed\n" + " with ret %d\n", __func__, ret); + goto done; + } } ret = 0; @@ -299,7 +330,7 @@ static int audio_ext_lpass_mclk_prepare(struct clk *clk) lpass_clk_ver = afe_get_lpass_clk_ver(); if (lpass_clk_ver >= LPASS_CLK_VER_2) - ret = audio_ext_set_lpass_mclk_v2(CLK_ENABLE); + ret = audio_ext_set_lpass_mclk_v2(clk, CLK_ENABLE); else ret = audio_ext_set_lpass_mclk_v1(clk, CLK_ENABLE); @@ -336,7 +367,7 @@ static void audio_ext_lpass_mclk_unprepare(struct clk *clk) lpass_clk_ver = afe_get_lpass_clk_ver(); if (lpass_clk_ver >= LPASS_CLK_VER_2) - ret = audio_ext_set_lpass_mclk_v2(CLK_DISABLE); + ret = audio_ext_set_lpass_mclk_v2(clk, CLK_DISABLE); else ret = audio_ext_set_lpass_mclk_v1(clk, CLK_DISABLE); diff --git a/sound/soc/codecs/msm8x16-wcd.c b/sound/soc/codecs/msm8x16-wcd.c index 964372f0f328..0044f63fbcd1 100644 --- a/sound/soc/codecs/msm8x16-wcd.c +++ b/sound/soc/codecs/msm8x16-wcd.c @@ -49,7 +49,8 @@ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000) #define MSM8X16_WCD_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ SNDRV_PCM_FMTBIT_S24_LE |\ - SNDRV_PCM_FMTBIT_S24_3LE) + SNDRV_PCM_FMTBIT_S24_3LE |\ + SNDRV_PCM_FMTBIT_S32_LE) #define NUM_INTERPOLATORS 3 #define BITS_PER_REG 8 @@ -4755,13 +4756,24 @@ static int msm8x16_wcd_hw_params(struct snd_pcm_substream *substream, } switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: - snd_soc_update_bits(dai->codec, + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + snd_soc_update_bits(dai->codec, MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL, 0x20, 0x20); + } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + snd_soc_update_bits(dai->codec, + MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL, 0x20, 0x20); + } break; case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_3LE: - snd_soc_update_bits(dai->codec, + case SNDRV_PCM_FORMAT_S32_LE: + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + snd_soc_update_bits(dai->codec, MSM8X16_WCD_A_CDC_CLK_RX_I2S_CTL, 0x20, 0x00); + } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + snd_soc_update_bits(dai->codec, + MSM8X16_WCD_A_CDC_CLK_TX_I2S_CTL, 0x20, 0x00); + } break; default: dev_err(dai->codec->dev, "%s: wrong format selected\n", diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index bf6fc60d816e..aed0448707ed 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -886,6 +886,15 @@ static ssize_t wcd9xxx_print_name(struct switch_dev *sdev, char *buf) return -EINVAL; } +static const struct tasha_reg_mask_val tasha_high_impedance[] = { + {WCD9335_TLMM_I2S_TX_SD0_PINCFG, 0x1F, 0x0C}, + {WCD9335_TLMM_I2S_TX_SD1_PINCFG, 0x1F, 0x0C}, + {WCD9335_TLMM_I2S_TX_SCK_PINCFG, 0x1F, 0x0C}, + {WCD9335_TLMM_I2S_TX_WS_PINCFG, 0x1F, 0x0C}, + {WCD9335_TEST_DEBUG_PIN_CTL_OE_1, 0xE0, 0xE0}, + {WCD9335_TEST_DEBUG_PIN_CTL_OE_2, 0x01, 0x01}, +}; + /** * tasha_set_spkr_gain_offset - offset the speaker path * gain with the given offset value. @@ -989,6 +998,20 @@ static void tasha_cdc_sido_ccl_enable(struct tasha_priv *tasha, bool ccl_flag) } } +static void tasha_set_high_impedance_mode(struct snd_soc_codec *codec) +{ + const struct tasha_reg_mask_val *regs; + int i, size; + + dev_dbg(codec->dev, "%s: setting TX I2S in Hi-Z mode\n", __func__); + regs = tasha_high_impedance; + size = ARRAY_SIZE(tasha_high_impedance); + + for (i = 0; i < size; i++) + snd_soc_update_bits(codec, regs[i].reg, + regs[i].mask, regs[i].val); +} + static bool tasha_cdc_is_svs_enabled(struct tasha_priv *tasha) { if (TASHA_IS_2_0(tasha->wcd9xxx->version) && @@ -13991,6 +14014,8 @@ static int tasha_codec_probe(struct snd_soc_codec *codec) mutex_unlock(&codec->mutex); snd_soc_dapm_sync(dapm); + if (pdata->wcd9xxx_mic_tristate) + tasha_set_high_impedance_mode(codec); priv_headset_type = tasha; @@ -14008,6 +14033,7 @@ static int tasha_codec_probe(struct snd_soc_codec *codec) pr_err("%s: failed to register switch audiowizard_force_preset\n", __func__); } /* ASUS_BSP Paul --- */ + return ret; err_pdata: diff --git a/sound/soc/msm/apq8009-i2s-ext-codec.c b/sound/soc/msm/apq8009-i2s-ext-codec.c index 22abdac808d8..14734a366096 100644 --- a/sound/soc/msm/apq8009-i2s-ext-codec.c +++ b/sound/soc/msm/apq8009-i2s-ext-codec.c @@ -1,4 +1,4 @@ - /* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. + /* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -69,11 +70,48 @@ #define WSA8810_NAME_1 "wsa881x.20170211" #define WSA8810_NAME_2 "wsa881x.20170212" +#define TDM_SLOT_OFFSET_MAX 8 + enum btsco_rates { RATE_8KHZ_ID, RATE_16KHZ_ID, }; +enum { + PRIMARY_TDM_RX_0, + PRIMARY_TDM_TX_0, + SECONDARY_TDM_RX_0, + SECONDARY_TDM_TX_0, + TDM_MAX, +}; + + +/* TDM default channels */ +static int msm_pri_tdm_rx_0_ch = 8; +static int msm_pri_tdm_tx_0_ch = 8; + +/* TDM default bit format */ +static int msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE; + +/* TDM default sampling rate */ +static int msm_pri_tdm_rx_0_sample_rate = SAMPLING_RATE_48KHZ; +static int msm_pri_tdm_tx_0_sample_rate = SAMPLING_RATE_48KHZ; + +static char const *tdm_ch_text[] = {"One", "Two", "Three", "Four", + "Five", "Six", "Seven", "Eight"}; +static char const *tdm_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE", + "S32_LE"}; +static char const *tdm_sample_rate_text[] = {"KHZ_16", "KHZ_48"}; + +/* TDM default offset */ +static unsigned int tdm_slot_offset[TDM_MAX][TDM_SLOT_OFFSET_MAX] = { + /* PRI_TDM_RX */ + {0, 4, 8, 12, 16, 20, 24, 28}, + /* PRI_TDM_TX */ + {0, 4, 8, 12, 16, 20, 24, 28}, +}; + struct apq8009_asoc_mach_data { int mclk_freq; struct afe_digital_clk_cfg digital_cdc_clk; @@ -106,6 +144,7 @@ static int apq8009_auxpcm_rate = 8000; static atomic_t pri_mi2s_clk_ref; static atomic_t quat_mi2s_clk_ref; static atomic_t auxpcm_mi2s_clk_ref; +static int tdm_i2s_switch_enable = -EINVAL; static int apq8009_enable_extcodec_ext_clk(struct snd_soc_codec *codec, int enable, bool dapm); @@ -286,12 +325,210 @@ static struct snd_soc_dapm_route wcd9335_audio_paths[] = { {"MIC BIAS4", NULL, "MCLK"}, }; -static char const *rx_bit_format_text[] = {"S16_LE", "S24_3LE", "S24_LE"}; +static char const *rx_bit_format_text[] = {"S16_LE", "S24_3LE", "S24_LE", + "S32_LE"}; static const char *const mi2s_tx_ch_text[] = {"One", "Two", "Three", "Four"}; static char const *pri_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96", "KHZ_192", "KHZ_8", "KHZ_16", "KHZ_32"}; + +static int msm_pri_tdm_rx_0_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("msm_pri_tdm_rx_0_ch = %d", + msm_pri_tdm_rx_0_ch); + ucontrol->value.integer.value[0] = msm_pri_tdm_rx_0_ch - 1; + return 0; +} + +static int msm_pri_tdm_rx_0_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_pri_tdm_rx_0_ch = ucontrol->value.integer.value[0] + 1; + pr_debug("msm_pri_tdm_rx_0_ch = %d", + msm_pri_tdm_rx_0_ch); + return 0; +} + +static int msm_pri_tdm_tx_0_ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + pr_debug("msm_pri_tdm_tx_0_ch = %d", + msm_pri_tdm_tx_0_ch); + ucontrol->value.integer.value[0] = msm_pri_tdm_tx_0_ch - 1; + return 0; +} + +static int msm_pri_tdm_tx_0_ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + msm_pri_tdm_tx_0_ch = ucontrol->value.integer.value[0] + 1; + pr_debug("msm_pri_tdm_tx_0_ch = %d", + msm_pri_tdm_tx_0_ch); + return 0; +} + +static int msm_pri_tdm_rx_0_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_pri_tdm_rx_0_bit_format) { + case SNDRV_PCM_FORMAT_S32_LE: + ucontrol->value.integer.value[0] = 3; + break; + case SNDRV_PCM_FORMAT_S24_3LE: + ucontrol->value.integer.value[0] = 2; + break; + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("msm_pri_tdm_rx_0_bit_format = %ld", + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_pri_tdm_rx_0_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 3: + msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S32_LE; + break; + case 2: + msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S24_3LE; + break; + case 1: + msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + msm_pri_tdm_rx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("msm_pri_tdm_rx_0_bit_format = %d", + msm_pri_tdm_rx_0_bit_format); + return 0; +} + +static int msm_pri_tdm_tx_0_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_pri_tdm_tx_0_bit_format) { + case SNDRV_PCM_FORMAT_S32_LE: + ucontrol->value.integer.value[0] = 3; + break; + case SNDRV_PCM_FORMAT_S24_3LE: + ucontrol->value.integer.value[0] = 2; + break; + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + pr_debug("msm_pri_tdm_tx_0_bit_format = %ld", + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_pri_tdm_tx_0_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 3: + msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S32_LE; + break; + case 2: + msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S24_3LE; + break; + case 1: + msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S24_LE; + break; + case 0: + default: + msm_pri_tdm_tx_0_bit_format = SNDRV_PCM_FORMAT_S16_LE; + break; + } + pr_debug("msm_pri_tdm_tx_0_bit_format = %d", + msm_pri_tdm_tx_0_bit_format); + return 0; +} + +static int msm_pri_tdm_rx_0_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_pri_tdm_rx_0_sample_rate) { + case SAMPLING_RATE_16KHZ: + ucontrol->value.integer.value[0] = 0; + break; + case SAMPLING_RATE_48KHZ: + default: + ucontrol->value.integer.value[0] = 1; + break; + } + pr_debug("msm_pri_tdm_rx_0_sample_rate = %ld", + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_pri_tdm_rx_0_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 0: + msm_pri_tdm_rx_0_sample_rate = SAMPLING_RATE_16KHZ; + break; + case 1: + default: + msm_pri_tdm_rx_0_sample_rate = SAMPLING_RATE_48KHZ; + break; + } + pr_debug("msm_pri_tdm_rx_0_sample_rate = %d", + msm_pri_tdm_rx_0_sample_rate); + return 0; +} + +static int msm_pri_tdm_tx_0_sample_rate_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (msm_pri_tdm_tx_0_sample_rate) { + case SAMPLING_RATE_16KHZ: + ucontrol->value.integer.value[0] = 0; + break; + case SAMPLING_RATE_48KHZ: + default: + ucontrol->value.integer.value[0] = 1; + break; + } + pr_debug("msm_pri_tdm_tx_0_sample_rate = %ld", + ucontrol->value.integer.value[0]); + return 0; +} + +static int msm_pri_tdm_tx_0_sample_rate_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 0: + msm_pri_tdm_tx_0_sample_rate = SAMPLING_RATE_16KHZ; + break; + case 1: + default: + msm_pri_tdm_tx_0_sample_rate = SAMPLING_RATE_48KHZ; + break; + } + pr_debug("msm_pri_tdm_tx_0_sample_rate = %d", + msm_pri_tdm_tx_0_sample_rate); + return 0; +} + static int msm_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -397,6 +634,10 @@ static int mi2s_tx_bit_format_get(struct snd_kcontrol *kcontrol, { switch (mi2s_tx_bit_format) { + case SNDRV_PCM_FORMAT_S32_LE: + ucontrol->value.integer.value[0] = 3; + break; + case SNDRV_PCM_FORMAT_S24_LE: ucontrol->value.integer.value[0] = 2; break; @@ -422,6 +663,10 @@ static int mi2s_tx_bit_format_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { switch (ucontrol->value.integer.value[0]) { + case 3: + mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S32_LE; + tx_bits_per_sample = 32; + break; case 2: mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S24_LE; tx_bits_per_sample = 32; @@ -502,6 +747,203 @@ static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } + +static int msm_tdm_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + struct snd_interval *rate = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_RATE); + struct snd_interval *channels = hw_param_interval(params, + SNDRV_PCM_HW_PARAM_CHANNELS); + + switch (cpu_dai->id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + channels->min = channels->max = msm_pri_tdm_rx_0_ch; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_pri_tdm_rx_0_bit_format); + rate->min = rate->max = msm_pri_tdm_rx_0_sample_rate; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX: + channels->min = channels->max = msm_pri_tdm_tx_0_ch; + param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, + msm_pri_tdm_tx_0_bit_format); + rate->min = rate->max = msm_pri_tdm_tx_0_sample_rate; + break; + default: + pr_err("%s: dai id 0x%x not supported", __func__, + cpu_dai->id); + return -EINVAL; + } + + pr_debug("%s: dai id = 0x%x channels = %d rate = %d", __func__, + cpu_dai->id, channels->max, rate->max); + + return 0; +} + +static unsigned int tdm_param_set_slot_mask(u16 port_id, + int slot_width, int channels) +{ + unsigned int slot_mask = 0; + int upper, lower, i, j; + unsigned int *slot_offset; + + switch (port_id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + lower = PRIMARY_TDM_RX_0; + upper = PRIMARY_TDM_RX_0; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX: + lower = PRIMARY_TDM_TX_0; + upper = PRIMARY_TDM_TX_0; + break; + default: + return slot_mask; + } + + for (i = lower; i <= upper; i++) { + slot_offset = tdm_slot_offset[i]; + for (j = 0; j < channels; j++) { + if (slot_offset[j] != AFE_SLOT_MAPPING_OFFSET_INVALID) + /* + * set the mask of active slot according to + * the offset table for the group of devices + */ + slot_mask |= + (1 << ((slot_offset[j] * 8) / slot_width)); + else + break; + } + } + + return slot_mask; +} + +static int msm_tdm_snd_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret = 0; + int channels, slot_width, slots; + unsigned int slot_mask; + unsigned int *slot_offset; + int offset_channels = 0; + int i; + + pr_debug("%s: dai id = 0x%x\n", __func__, cpu_dai->id); + + channels = params_channels(params); + switch (channels) { + case 1: + case 2: + case 3: + case 4: + case 6: + case 8: + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S32_LE: + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_3LE: + case SNDRV_PCM_FORMAT_S16_LE: + /* + * up to 8 channel HW configuration should + * use 32 bit slot width for max support of + * stream bit width. (slot_width > bit_width) + */ + slot_width = 32; + break; + default: + pr_err("%s: invalid param format 0x%x\n", + __func__, params_format(params)); + return -EINVAL; + } + slots = 8; + slot_mask = tdm_param_set_slot_mask(cpu_dai->id, + slot_width, channels); + if (!slot_mask) { + pr_err("%s: invalid slot_mask 0x%x\n", + __func__, slot_mask); + return -EINVAL; + } + break; + default: + pr_err("%s: invalid param channels %d\n", + __func__, channels); + return -EINVAL; + } + + switch (cpu_dai->id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + slot_offset = tdm_slot_offset[PRIMARY_TDM_RX_0]; + break; + case AFE_PORT_ID_PRIMARY_TDM_TX: + slot_offset = tdm_slot_offset[PRIMARY_TDM_TX_0]; + break; + default: + pr_err("%s: dai id 0x%x not supported\n", + __func__, cpu_dai->id); + return -EINVAL; + } + + for (i = 0; i < channels; i++) { + if (slot_offset[i] != AFE_SLOT_MAPPING_OFFSET_INVALID) + offset_channels++; + else + break; + } + + if (offset_channels == 0) { + pr_err("%s: slot offset not supported, offset_channels %d\n", + __func__, offset_channels); + return -EINVAL; + } + + if (channels > offset_channels) { + pr_err("%s: channels %d exceed offset_channels %d\n", + __func__, channels, offset_channels); + return -EINVAL; + } + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0, slot_mask, + slots, slot_width); + if (ret < 0) { + pr_err("%s: failed to set tdm slot, err:%d\n", + __func__, ret); + goto end; + } + + ret = snd_soc_dai_set_channel_map(cpu_dai, + 0, NULL, channels, slot_offset); + if (ret < 0) { + pr_err("%s: failed to set channel map, err:%d\n", + __func__, ret); + goto end; + } + } else { + ret = snd_soc_dai_set_tdm_slot(cpu_dai, slot_mask, 0, + slots, slot_width); + if (ret < 0) { + pr_err("%s: failed to set tdm slot, err:%d\n", + __func__, ret); + goto end; + } + + ret = snd_soc_dai_set_channel_map(cpu_dai, + channels, slot_offset, 0, NULL); + if (ret < 0) { + pr_err("%s: failed to set channel map, err:%d\n", + __func__, ret); + goto end; + } + } + +end: + return ret; +} + static int msm_pri_mi2s_rx_ch_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -776,9 +1218,16 @@ static int msm_btsco_rate_put(struct snd_kcontrol *kcontrol, } static const struct soc_enum msm_snd_enum[] = { - SOC_ENUM_SINGLE_EXT(3, rx_bit_format_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_bit_format_text), + rx_bit_format_text), SOC_ENUM_SINGLE_EXT(4, mi2s_tx_ch_text), SOC_ENUM_SINGLE_EXT(6, pri_rx_sample_rate_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_ch_text), + tdm_ch_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_bit_format_text), + tdm_bit_format_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(tdm_sample_rate_text), + tdm_sample_rate_text), }; static const char *const btsco_rate_text[] = {"BTSCO_RATE_8KHZ", @@ -800,6 +1249,22 @@ static const struct snd_kcontrol_new msm_snd_controls[] = { msm_btsco_rate_get, msm_btsco_rate_put), SOC_ENUM_EXT("MI2S_RX SampleRate", msm_snd_enum[2], pri_rx_sample_rate_get, pri_rx_sample_rate_put), + SOC_ENUM_EXT("PRI_TDM_RX_0 Channels", msm_snd_enum[3], + msm_pri_tdm_rx_0_ch_get, msm_pri_tdm_rx_0_ch_put), + SOC_ENUM_EXT("PRI_TDM_TX_0 Channels", msm_snd_enum[3], + msm_pri_tdm_tx_0_ch_get, msm_pri_tdm_tx_0_ch_put), + SOC_ENUM_EXT("PRI_TDM_RX_0 Bit Format", msm_snd_enum[4], + msm_pri_tdm_rx_0_bit_format_get, + msm_pri_tdm_rx_0_bit_format_put), + SOC_ENUM_EXT("PRI_TDM_TX_0 Bit Format", msm_snd_enum[4], + msm_pri_tdm_tx_0_bit_format_get, + msm_pri_tdm_tx_0_bit_format_put), + SOC_ENUM_EXT("PRI_TDM_RX_0 SampleRate", msm_snd_enum[5], + msm_pri_tdm_rx_0_sample_rate_get, + msm_pri_tdm_rx_0_sample_rate_put), + SOC_ENUM_EXT("PRI_TDM_TX_0 SampleRate", msm_snd_enum[5], + msm_pri_tdm_tx_0_sample_rate_get, + msm_pri_tdm_tx_0_sample_rate_put), }; static int apq8009_mclk_event(struct snd_soc_dapm_widget *w, @@ -974,6 +1439,107 @@ static void msm_mi2s_snd_shutdown(struct snd_pcm_substream *substream) __func__, "pri_i2s"); } + +static int msm_tdm_startup(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_card *card = rtd->card; + struct apq8009_asoc_mach_data *pdata = + snd_soc_card_get_drvdata(card); + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret = 0, val = 0; + + pr_debug("substream = %s stream = %d", + substream->name, substream->stream); + pr_debug("dai id = 0x%x", cpu_dai->id); + + switch (cpu_dai->id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + case AFE_PORT_ID_PRIMARY_TDM_RX_1: + case AFE_PORT_ID_PRIMARY_TDM_RX_2: + case AFE_PORT_ID_PRIMARY_TDM_RX_3: + case AFE_PORT_ID_PRIMARY_TDM_RX_4: + case AFE_PORT_ID_PRIMARY_TDM_RX_5: + case AFE_PORT_ID_PRIMARY_TDM_RX_6: + case AFE_PORT_ID_PRIMARY_TDM_RX_7: + case AFE_PORT_ID_PRIMARY_TDM_TX: + case AFE_PORT_ID_PRIMARY_TDM_TX_1: + case AFE_PORT_ID_PRIMARY_TDM_TX_2: + case AFE_PORT_ID_PRIMARY_TDM_TX_3: + case AFE_PORT_ID_PRIMARY_TDM_TX_4: + case AFE_PORT_ID_PRIMARY_TDM_TX_5: + case AFE_PORT_ID_PRIMARY_TDM_TX_6: + case AFE_PORT_ID_PRIMARY_TDM_TX_7: + /* Configure mux for Primary TDM */ + if (pdata->vaddr_gpio_mux_pcm_ctl) { + val = ioread32(pdata->vaddr_gpio_mux_pcm_ctl); + val = val | 0x00000001; + iowrite32(val, pdata->vaddr_gpio_mux_pcm_ctl); + } else { + return -EINVAL; + } + if (pdata->vaddr_gpio_mux_mic_ctl) { + val = ioread32(pdata->vaddr_gpio_mux_mic_ctl); + /*0x1808000 Use this value for slave mode*/ + val = val | 0x02020002; /*this is for master mode*/ + iowrite32(val, pdata->vaddr_gpio_mux_mic_ctl); + } else { + return -EINVAL; + } + + ret = msm_gpioset_activate(CLIENT_WCD_EXT, "quat_i2s"); + if (ret < 0) + pr_err("%s: failed to activate primary TDM gpio set\n", + __func__); + /* Enable I2S switch to turn on TDM mics for SOM*/ + if (tdm_i2s_switch_enable >= 0) + gpio_direction_output(tdm_i2s_switch_enable, 1); + break; + default: + pr_err("dai id 0x%x not supported", cpu_dai->id); + break; + return -EINVAL; + } + return ret; +} + +static void msm_tdm_shutdown(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = rtd->cpu_dai; + int ret = 0; + + switch (cpu_dai->id) { + case AFE_PORT_ID_PRIMARY_TDM_RX: + case AFE_PORT_ID_PRIMARY_TDM_RX_1: + case AFE_PORT_ID_PRIMARY_TDM_RX_2: + case AFE_PORT_ID_PRIMARY_TDM_RX_3: + case AFE_PORT_ID_PRIMARY_TDM_RX_4: + case AFE_PORT_ID_PRIMARY_TDM_RX_5: + case AFE_PORT_ID_PRIMARY_TDM_RX_6: + case AFE_PORT_ID_PRIMARY_TDM_RX_7: + case AFE_PORT_ID_PRIMARY_TDM_TX: + case AFE_PORT_ID_PRIMARY_TDM_TX_1: + case AFE_PORT_ID_PRIMARY_TDM_TX_2: + case AFE_PORT_ID_PRIMARY_TDM_TX_3: + case AFE_PORT_ID_PRIMARY_TDM_TX_4: + case AFE_PORT_ID_PRIMARY_TDM_TX_5: + case AFE_PORT_ID_PRIMARY_TDM_TX_6: + ret = msm_gpioset_suspend(CLIENT_WCD_EXT, "quat_i2s"); + if (ret < 0) { + pr_err("%s: gpio set cannot be de-activated %s\n", + __func__, "pri_tdm"); + return; + } + + if (tdm_i2s_switch_enable >= 0) + gpio_direction_output(tdm_i2s_switch_enable, 0); + break; + default: + break; + } +} + static int msm_audrx_init_wcd(struct snd_soc_pcm_runtime *rtd) { @@ -1070,6 +1636,28 @@ static struct snd_soc_ops msm_pri_auxpcm_be_ops = { .startup = msm_prim_auxpcm_startup, }; +static struct snd_soc_dai_link msm_afe_rxtx_lb_be_dai_link[] = { + { + .name = LPASS_BE_AFE_LOOPBACK_TX, + .stream_name = "AFE Loopback Capture", + .cpu_dai_name = "msm-dai-q6-dev.24577", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_AFE_LOOPBACK_TX, + .ignore_pmdown_time = 1, + .ignore_suspend = 1, + }, +}; + +static struct snd_soc_ops msm_tdm_be_ops = { + .startup = msm_tdm_startup, + .hw_params = msm_tdm_snd_hw_params, + .shutdown = msm_tdm_shutdown, +}; + static struct snd_soc_dai_link apq8009_9326_dai[] = { /* Backend DAI Links */ { @@ -1523,6 +2111,7 @@ static struct snd_soc_dai_link apq8009_dai[] = { .platform_name = "msm-compress-dsp", .dynamic = 1, .dpcm_playback = 1, + .dpcm_capture = 1, .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST}, .codec_dai_name = "snd-soc-dummy-dai", @@ -1738,9 +2327,143 @@ static struct snd_soc_dai_link apq8009_dai[] = { }, }; +static struct snd_soc_dai_link msm_tdm_fe_dai[] = { + /* FE TDM DAI links */ + { + .name = "Primary TDM RX 0 Hostless", + .stream_name = "Primary TDM RX 0 Hostless", + .cpu_dai_name = "PRI_TDM_RX_0_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + { + .name = "Primary TDM TX 0 Hostless", + .stream_name = "Primary TDM TX 0 Hostless", + .cpu_dai_name = "PRI_TDM_TX_0_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + { + .name = "Secondary TDM RX 0 Hostless", + .stream_name = "Secondary TDM RX 0 Hostless", + .cpu_dai_name = "SEC_TDM_RX_0_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_playback = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, + { + .name = "Secondary TDM TX 0 Hostless", + .stream_name = "Secondary TDM TX 0 Hostless", + .cpu_dai_name = "SEC_TDM_TX_0_HOSTLESS", + .platform_name = "msm-pcm-hostless", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .no_host_mode = SND_SOC_DAI_LINK_NO_HOST, + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + }, +}; + +static struct snd_soc_dai_link msm_compr_fe_dai[] = { + /* FE TDM DAI links */ + {/* hw:x,43 */ + .name = "APQ8009 Compress3", + .stream_name = "Compress3", + .cpu_dai_name = "MultiMedia10", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA10, + }, + {/* hw:x,44 */ + .name = "APQ8009 Compress4", + .stream_name = "Compress4", + .cpu_dai_name = "MultiMedia11", + .platform_name = "msm-compress-dsp", + .dynamic = 1, + .dpcm_capture = 1, + .trigger = {SND_SOC_DPCM_TRIGGER_POST, + SND_SOC_DPCM_TRIGGER_POST}, + .codec_dai_name = "snd-soc-dummy-dai", + .codec_name = "snd-soc-dummy", + .ignore_suspend = 1, + .ignore_pmdown_time = 1, + .be_id = MSM_FRONTEND_DAI_MULTIMEDIA11, + }, +}; + +static struct snd_soc_dai_link msm_tdm_be_dai[] = { + /* TDM be dai links */ + { + .name = LPASS_BE_PRI_TDM_RX_0, + .stream_name = "Primary TDM0 Playback", + .cpu_dai_name = "msm-dai-q6-tdm.36864", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-rx", + .no_pcm = 1, + .dpcm_playback = 1, + .be_id = MSM_BACKEND_DAI_PRI_TDM_RX_0, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &msm_tdm_be_ops, + .ignore_suspend = 1, + }, + { + .name = LPASS_BE_PRI_TDM_TX_0, + .stream_name = "Primary TDM0 Capture", + .cpu_dai_name = "msm-dai-q6-tdm.36865", + .platform_name = "msm-pcm-routing", + .codec_name = "msm-stub-codec.1", + .codec_dai_name = "msm-stub-tx", + .no_pcm = 1, + .dpcm_capture = 1, + .be_id = MSM_BACKEND_DAI_PRI_TDM_TX_0, + .be_hw_params_fixup = msm_tdm_be_hw_params_fixup, + .ops = &msm_tdm_be_ops, + .ignore_suspend = 1, + }, +}; + static struct snd_soc_dai_link apq8009_9326_dai_links[ ARRAY_SIZE(apq8009_dai) + - ARRAY_SIZE(apq8009_9326_dai)]; + ARRAY_SIZE(msm_tdm_fe_dai) + + ARRAY_SIZE(msm_compr_fe_dai) + + ARRAY_SIZE(apq8009_9326_dai) + + ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link) + + ARRAY_SIZE(msm_tdm_be_dai)]; static struct snd_soc_card snd_soc_card_9326_apq8009; @@ -1760,7 +2483,7 @@ static int populate_ext_snd_card_dt_data(struct platform_device *pdev) struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) { struct snd_soc_card *card = &snd_soc_card_9326_apq8009; - int num_links, ret; + int ret, len1, len2, len3, len4; card->dev = dev; ret = snd_soc_of_parse_card_name(card, "qcom,model"); @@ -1771,16 +2494,39 @@ struct snd_soc_card *populate_snd_card_dailinks(struct device *dev) } pr_debug("%s: CARD is %s\n", __func__, card->name); - num_links = ARRAY_SIZE(apq8009_9326_dai_links); + len1 = ARRAY_SIZE(apq8009_dai); + len2 = len1 + ARRAY_SIZE(msm_tdm_fe_dai); + len3 = len2 + ARRAY_SIZE(msm_compr_fe_dai); + len4 = len3 + ARRAY_SIZE(apq8009_9326_dai); memcpy(apq8009_9326_dai_links, apq8009_dai, sizeof(apq8009_dai)); - memcpy(apq8009_9326_dai_links + ARRAY_SIZE(apq8009_dai), - apq8009_9326_dai, sizeof(apq8009_9326_dai)); + memcpy(apq8009_9326_dai_links + len1, msm_tdm_fe_dai, + sizeof(msm_tdm_fe_dai)); + memcpy(apq8009_9326_dai_links + len2, msm_compr_fe_dai, + sizeof(msm_compr_fe_dai)); + memcpy(apq8009_9326_dai_links + len3, apq8009_9326_dai, + sizeof(apq8009_9326_dai)); + + if (of_property_read_bool(dev->of_node, "qcom,afe-rxtx-lb")) { + dev_dbg(dev, "%s(): AFE RX to TX loopback supported\n", + __func__); + memcpy(apq8009_9326_dai_links + len4, + msm_afe_rxtx_lb_be_dai_link, + sizeof(msm_afe_rxtx_lb_be_dai_link)); + len4 += ARRAY_SIZE(msm_afe_rxtx_lb_be_dai_link); + } + if (of_property_read_bool(dev->of_node, "qcom,tdm-audio-intf")) { + dev_dbg(dev, "%s(): TDM support present\n", + __func__); + memcpy(apq8009_9326_dai_links + len4, msm_tdm_be_dai, + sizeof(msm_tdm_be_dai)); + len4 += ARRAY_SIZE(msm_tdm_be_dai); + } card->dai_link = apq8009_9326_dai_links; - card->num_links = num_links; + card->num_links = len4; card->dev = dev; return card; @@ -2140,6 +2886,22 @@ static int apq8009_asoc_machine_probe(struct platform_device *pdev) ret); goto err; } + + tdm_i2s_switch_enable = of_get_named_gpio(pdev->dev.of_node, + "qcom,tdm-i2s-switch-enable", 0); + if (tdm_i2s_switch_enable >= 0) { + dev_dbg(&pdev->dev, "%s: tdm switch gpio %d", __func__, + tdm_i2s_switch_enable); + ret = gpio_request(tdm_i2s_switch_enable, "TDM_RESET"); + if (ret) { + pr_err("%s: Failed to request gpio\n", __func__); + goto err; + } + } else + dev_err(&pdev->dev, "Looking up %s property in node %s failed\n", + "qcom,tdm-i2s-switch-enable", + pdev->dev.of_node->full_name); + return 0; err: if (pdata->vaddr_gpio_mux_spkr_ctl) diff --git a/sound/soc/msm/msm-dai-fe.c b/sound/soc/msm/msm-dai-fe.c index 7857813ca3b0..b8f666d0ce15 100644 --- a/sound/soc/msm/msm-dai-fe.c +++ b/sound/soc/msm/msm-dai-fe.c @@ -108,7 +108,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -140,7 +141,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -223,7 +225,9 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .rates = (SNDRV_PCM_RATE_8000_192000| SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S24_LE), + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -255,7 +259,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 0, .channels_max = 8, .rate_min = 8000, @@ -288,7 +293,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -320,7 +326,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -372,7 +379,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -2118,7 +2126,10 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { .aif_name = "MM_UL9", .rates = (SNDRV_PCM_RATE_8000_48000| SNDRV_PCM_RATE_KNOT), - .formats = SNDRV_PCM_FMTBIT_S16_LE, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -2513,7 +2524,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -2532,7 +2544,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, @@ -2551,7 +2564,8 @@ static struct snd_soc_dai_driver msm_fe_dais[] = { SNDRV_PCM_RATE_KNOT), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .channels_min = 1, .channels_max = 8, .rate_min = 8000, diff --git a/sound/soc/msm/msm8952-slimbus.c b/sound/soc/msm/msm8952-slimbus.c index 7fccff15cac3..775328a8635a 100644 --- a/sound/soc/msm/msm8952-slimbus.c +++ b/sound/soc/msm/msm8952-slimbus.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -1042,6 +1042,9 @@ static int slim0_tx_bit_format_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { switch (slim0_tx_bit_format) { + case SNDRV_PCM_FORMAT_S32_LE: + ucontrol->value.integer.value[0] = 3; + break; case SNDRV_PCM_FORMAT_S24_3LE: ucontrol->value.integer.value[0] = 2; break; @@ -1065,6 +1068,9 @@ static int slim0_tx_bit_format_put(struct snd_kcontrol *kcontrol, int rc = 0; switch (ucontrol->value.integer.value[0]) { + case 3: + slim0_tx_bit_format = SNDRV_PCM_FORMAT_S32_LE; + break; case 2: slim0_tx_bit_format = SNDRV_PCM_FORMAT_S24_3LE; break; @@ -1799,7 +1805,8 @@ static const char *const slim4_tx_ch_text[] = {"One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight"}; static const char *const vi_feed_ch_text[] = {"One", "Two"}; -static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"}; +static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE", + "S32_LE"}; static char const *slim0_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96", "KHZ_192", "KHZ_44P1", "KHZ_16"}; static char const *slim4_rx_sample_rate_text[] = {"KHZ_48", "KHZ_96", diff --git a/sound/soc/msm/msm8952.c b/sound/soc/msm/msm8952.c index 880677fc39a9..24fc90036b51 100644 --- a/sound/soc/msm/msm8952.c +++ b/sound/soc/msm/msm8952.c @@ -68,6 +68,9 @@ static int msm_vi_feed_tx_ch = 2; static int mi2s_rx_bit_format = SNDRV_PCM_FORMAT_S16_LE; static int mi2s_rx_bits_per_sample = 16; static int mi2s_rx_sample_rate = SAMPLING_RATE_48KHZ; +static int mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE; +static int mi2s_tx_bits_per_sample = 16; +static int mi2s_tx_sample_rate = SAMPLING_RATE_48KHZ; static atomic_t quat_mi2s_clk_ref; static atomic_t quin_mi2s_clk_ref; @@ -161,7 +164,8 @@ static struct afe_clk_set wsa_ana_clk = { 0, }; -static char const *rx_bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE"}; +static char const *bit_format_text[] = {"S16_LE", "S24_LE", "S24_3LE", + "S32_LE"}; static const char *const mi2s_ch_text[] = {"One", "Two"}; static const char *const loopback_mclk_text[] = {"DISABLE", "ENABLE"}; static const char *const btsco_rate_text[] = {"BTSCO_RATE_8KHZ", @@ -389,7 +393,7 @@ static int msm_tx_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, pr_debug("%s(), channel:%d\n", __func__, msm_ter_mi2s_tx_ch); param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_FORMAT_S16_LE); + mi2s_tx_bit_format); rate->min = rate->max = 48000; channels->min = channels->max = msm_ter_mi2s_tx_ch; @@ -480,7 +484,7 @@ static int msm_mi2s_snd_hw_params(struct snd_pcm_substream *substream, mi2s_rx_bit_format); else param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT, - SNDRV_PCM_FORMAT_S16_LE); + mi2s_tx_bit_format); return 0; } @@ -549,7 +553,7 @@ static bool is_mi2s_rx_port(int port_id) return ret; } -static uint32_t get_mi2s_rx_clk_val(int port_id) +static uint32_t get_mi2s_clk_val(int port_id) { uint32_t clk_val = 0; @@ -559,8 +563,10 @@ static uint32_t get_mi2s_rx_clk_val(int port_id) */ if (is_mi2s_rx_port(port_id)) clk_val = (mi2s_rx_sample_rate * mi2s_rx_bits_per_sample * 2); + else + clk_val = (mi2s_tx_sample_rate * mi2s_tx_bits_per_sample * 2); - pr_debug("%s: MI2S Rx bit clock value: 0x%0x\n", __func__, clk_val); + pr_debug("%s: MI2S bit clock value: 0x%0x\n", __func__, clk_val); return clk_val; } @@ -581,7 +587,7 @@ static int msm_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable) if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) { mi2s_rx_clk_v1.clk_val1 = - get_mi2s_rx_clk_val(port_id); + get_mi2s_clk_val(port_id); ret = afe_set_lpass_clock(port_id, &mi2s_rx_clk_v1); } else { @@ -589,14 +595,14 @@ static int msm_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable) mi2s_rx_clk.clk_id = msm8952_get_clk_id(port_id); mi2s_rx_clk.clk_freq_in_hz = - get_mi2s_rx_clk_val(port_id); + get_mi2s_clk_val(port_id); ret = afe_set_lpass_clock_v2(port_id, &mi2s_rx_clk); } } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { if (pdata->afe_clk_ver == AFE_CLK_VERSION_V1) { mi2s_tx_clk_v1.clk_val1 = - Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ; + get_mi2s_clk_val(port_id); ret = afe_set_lpass_clock(port_id, &mi2s_tx_clk_v1); } else { @@ -604,7 +610,7 @@ static int msm_mi2s_sclk_ctl(struct snd_pcm_substream *substream, bool enable) mi2s_tx_clk.clk_id = msm8952_get_clk_id(port_id); mi2s_tx_clk.clk_freq_in_hz = - Q6AFE_LPASS_IBIT_CLK_1_P536_MHZ; + get_mi2s_clk_val(port_id); ret = afe_set_lpass_clock_v2(port_id, &mi2s_tx_clk); } @@ -790,6 +796,61 @@ static int mi2s_rx_bit_format_put(struct snd_kcontrol *kcontrol, return 0; } +static int mi2s_tx_bit_format_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + switch (ucontrol->value.integer.value[0]) { + case 3: + mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S32_LE; + mi2s_tx_bits_per_sample = 32; + break; + case 2: + mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S24_3LE; + mi2s_tx_bits_per_sample = 32; + break; + case 1: + mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S24_LE; + mi2s_tx_bits_per_sample = 32; + break; + case 0: + default: + mi2s_tx_bit_format = SNDRV_PCM_FORMAT_S16_LE; + mi2s_tx_bits_per_sample = 16; + break; + } + return 0; +} + +static int mi2s_tx_bit_format_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + + switch (mi2s_tx_bit_format) { + case SNDRV_PCM_FORMAT_S32_LE: + ucontrol->value.integer.value[0] = 3; + break; + + case SNDRV_PCM_FORMAT_S24_3LE: + ucontrol->value.integer.value[0] = 2; + break; + + case SNDRV_PCM_FORMAT_S24_LE: + ucontrol->value.integer.value[0] = 1; + break; + + case SNDRV_PCM_FORMAT_S16_LE: + default: + ucontrol->value.integer.value[0] = 0; + break; + } + + pr_debug("%s: mi2s_tx_bit_format = %d, ucontrol value = %ld\n", + __func__, mi2s_tx_bit_format, + ucontrol->value.integer.value[0]); + + return 0; +} + static int loopback_mclk_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -988,8 +1049,8 @@ static int msm_vi_feed_tx_ch_put(struct snd_kcontrol *kcontrol, } static const struct soc_enum msm_snd_enum[] = { - SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(rx_bit_format_text), - rx_bit_format_text), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(bit_format_text), + bit_format_text), SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(mi2s_ch_text), mi2s_ch_text), SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(loopback_mclk_text), @@ -1007,6 +1068,8 @@ static const struct soc_enum msm_snd_enum[] = { static const struct snd_kcontrol_new msm_snd_controls[] = { SOC_ENUM_EXT("MI2S_RX Format", msm_snd_enum[0], mi2s_rx_bit_format_get, mi2s_rx_bit_format_put), + SOC_ENUM_EXT("MI2S_TX Format", msm_snd_enum[0], + mi2s_tx_bit_format_get, mi2s_tx_bit_format_put), SOC_ENUM_EXT("MI2S_TX Channels", msm_snd_enum[1], msm_ter_mi2s_tx_ch_get, msm_ter_mi2s_tx_ch_put), SOC_ENUM_EXT("MI2S_RX Channels", msm_snd_enum[1], diff --git a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c index 260927e8d434..388fed14ed81 100644 --- a/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -118,7 +119,6 @@ struct msm_compr_pdata { uint32_t volume[MSM_FRONTEND_DAI_MAX][2]; /* For both L & R */ struct msm_compr_audio_effects *audio_effects[MSM_FRONTEND_DAI_MAX]; bool use_dsp_gapless_mode; - bool use_legacy_api; /* indicates use older asm apis*/ struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX]; struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX]; bool is_in_use[MSM_FRONTEND_DAI_MAX]; @@ -842,6 +842,10 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream, } switch (prtd->codec_param.codec.format) { + case SNDRV_PCM_FORMAT_S32_LE: + bit_width = 32; + sample_word_size = 32; + break; case SNDRV_PCM_FORMAT_S24_LE: bit_width = 24; sample_word_size = 32; @@ -856,7 +860,10 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream, sample_word_size = 16; break; } - ret = q6asm_media_format_block_pcm_format_support_v3( + + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_7): + ret = q6asm_media_format_block_pcm_format_support_v3( prtd->audio_client, prtd->sample_rate, prtd->num_channels, @@ -864,6 +871,24 @@ static int msm_compr_send_media_format_block(struct snd_compr_stream *cstream, use_default_chmap, chmap, sample_word_size); + break; + case (Q6_SUBSYS_AVS2_8): + ret = q6asm_media_format_block_pcm_format_support_v4( + prtd->audio_client, + prtd->sample_rate, + prtd->num_channels, + bit_width, stream_id, + use_default_chmap, + chmap, + sample_word_size, + ASM_LITTLE_ENDIAN, + DEFAULT_QF); + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } if (ret < 0) pr_err("%s: CMD Format block failed\n", __func__); @@ -1158,10 +1183,25 @@ static int msm_compr_configure_dsp_for_playback } else { pr_debug("%s: stream_id %d bits_per_sample %d\n", __func__, ac->stream_id, bits_per_sample); - ret = q6asm_stream_open_write_v3(ac, + + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_7): + ret = q6asm_stream_open_write_v3(ac, + prtd->codec, bits_per_sample, + ac->stream_id, + prtd->gapless_state.use_dsp_gapless_mode); + break; + case (Q6_SUBSYS_AVS2_8): + ret = q6asm_stream_open_write_v4(ac, prtd->codec, bits_per_sample, ac->stream_id, prtd->gapless_state.use_dsp_gapless_mode); + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } if (ret < 0) { pr_err("%s:ASM open write err[%d] for compr type[%d]\n", __func__, ret, prtd->compr_passthr); @@ -2282,13 +2322,22 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) /* * Cache this time as last known time */ - if (pdata->use_legacy_api) + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_6): q6asm_get_session_time_legacy( prtd->audio_client, &prtd->marker_timestamp); - else + break; + case (Q6_SUBSYS_AVS2_7): + case (Q6_SUBSYS_AVS2_8): q6asm_get_session_time(prtd->audio_client, &prtd->marker_timestamp); + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } spin_lock_irqsave(&prtd->lock, flags); /* @@ -2386,10 +2435,25 @@ static int msm_compr_trigger(struct snd_compr_stream *cstream, int cmd) pr_debug("%s: open_write stream_id %d bits_per_sample %d", __func__, stream_id, bits_per_sample); - rc = q6asm_stream_open_write_v3(prtd->audio_client, + + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_7): + rc = q6asm_stream_open_write_v3(ac, + prtd->codec, bits_per_sample, + ac->stream_id, + prtd->gapless_state.use_dsp_gapless_mode); + break; + case (Q6_SUBSYS_AVS2_8): + rc = q6asm_stream_open_write_v4(ac, prtd->codec, bits_per_sample, - stream_id, + ac->stream_id, prtd->gapless_state.use_dsp_gapless_mode); + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } if (rc < 0) { pr_err("%s: Session out open failed for gapless\n", __func__); @@ -2468,13 +2532,22 @@ static int msm_compr_pointer(struct snd_compr_stream *cstream, stream. */ if (!first_buffer || gapless_transition) { - - if (pdata->use_legacy_api) - rc = q6asm_get_session_time_legacy( - prtd->audio_client, &prtd->marker_timestamp); - else - rc = q6asm_get_session_time( - prtd->audio_client, &prtd->marker_timestamp); + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_6): + q6asm_get_session_time_legacy( + prtd->audio_client, + &prtd->marker_timestamp); + break; + case (Q6_SUBSYS_AVS2_7): + case (Q6_SUBSYS_AVS2_8): + q6asm_get_session_time(prtd->audio_client, + &prtd->marker_timestamp); + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } if (rc < 0) { pr_err("%s: Get Session Time return =%lld\n", __func__, timestamp); @@ -3480,8 +3553,6 @@ static int msm_compr_probe(struct snd_soc_platform *platform) { struct msm_compr_pdata *pdata; int i; - int rc; - const char *qdsp_version; pr_debug("%s\n", __func__); pdata = (struct msm_compr_pdata *) @@ -3504,17 +3575,6 @@ static int msm_compr_probe(struct snd_soc_platform *platform) snd_soc_add_platform_controls(platform, msm_compr_gapless_controls, ARRAY_SIZE(msm_compr_gapless_controls)); - rc = of_property_read_string(platform->dev->of_node, - "qcom,adsp-version", &qdsp_version); - if (!rc) { - if (!strcmp(qdsp_version, "MDSP 1.2")) - pdata->use_legacy_api = true; - else - pdata->use_legacy_api = false; - } else - pdata->use_legacy_api = false; - - pr_debug("%s: use legacy api %d\n", __func__, pdata->use_legacy_api); /* * use_dsp_gapless_mode part of platform data(pdata) is updated from HAL * through a mixer control before compress driver is opened. The mixer @@ -3525,6 +3585,16 @@ static int msm_compr_probe(struct snd_soc_platform *platform) return 0; } +static int msm_compr_chmix_cfg_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 128; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xFFFFFFFF; + return 0; +} + static int msm_compr_volume_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { @@ -3843,6 +3913,113 @@ static int msm_compr_add_app_type_cfg_control(struct snd_soc_pcm_runtime *rtd) return 0; } + +static int msm_compr_chmix_cfg_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); + struct msm_compr_pdata *pdata = (struct msm_compr_pdata *) + snd_soc_component_get_drvdata(comp); + struct snd_compr_stream *cstream = NULL; + struct snd_soc_pcm_runtime *rtd = NULL; + u64 fe_id = kcontrol->private_value; + int ip_channel_cnt, op_channel_cnt; + int i, index = 0; + int ch_coeff[PCM_FORMAT_MAX_NUM_CHANNEL * PCM_FORMAT_MAX_NUM_CHANNEL]; + bool use_default_chmap = true; + char *chmap = NULL; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + return -EINVAL; + } + cstream = pdata->cstream[fe_id]; + if (!cstream) { + pr_err("%s: stream inactive\n", __func__); + return -EINVAL; + } + rtd = cstream->private_data; + if (!rtd) { + pr_err("%s: stream inactive\n", __func__); + return -EINVAL; + } + + use_default_chmap = !(pdata->ch_map[rtd->dai_link->be_id]->set_ch_map); + chmap = pdata->ch_map[rtd->dai_link->be_id]->channel_map; + + ip_channel_cnt = ucontrol->value.integer.value[index++]; + op_channel_cnt = ucontrol->value.integer.value[index++]; + /* + * wght coeff of first out channel corresponding to each in channel + * are sent followed by second out channel for each in channel etc. + */ + memset(ch_coeff, 0, sizeof(ch_coeff)); + for (i = 0; i < op_channel_cnt * ip_channel_cnt; i++) { + ch_coeff[i] = + ucontrol->value.integer.value[index++]; + } + + msm_pcm_routing_send_chmix_cfg(fe_id, ip_channel_cnt, op_channel_cnt, + ch_coeff, SESSION_TYPE_RX, use_default_chmap, chmap); + + return 0; +} + +static int msm_compr_chmix_cfg_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_compr_add_chmix_cfg_controls(struct snd_soc_pcm_runtime *rtd) +{ + const char *mixer_ctl_name = "Audio Stream"; + const char *deviceNo = "NN"; + const char *suffix = "Channel Mix Cfg"; + int ctl_len; + char *mixer_str = NULL; + struct snd_kcontrol_new chmix_cfg_controls[1] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "?", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = msm_compr_chmix_cfg_ctl_info, + .get = msm_compr_chmix_cfg_ctl_get, + .put = msm_compr_chmix_cfg_ctl_put, + .private_value = 0, + } + }; + + if (!rtd) { + pr_err("%s NULL rtd\n", __func__); + return -EINVAL; + } + + pr_debug("%s: added new compr FE with name %s, id %d, cpu dai %s, device no %d\n", + __func__, rtd->dai_link->name, rtd->dai_link->be_id, + rtd->dai_link->cpu_dai_name, rtd->pcm->device); + + ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1 + + strlen(suffix) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) + return -ENOMEM; + + snprintf(mixer_str, ctl_len, "%s %d %s", mixer_ctl_name, + rtd->pcm->device, suffix); + + chmix_cfg_controls[0].name = mixer_str; + chmix_cfg_controls[0].private_value = rtd->dai_link->be_id; + pr_debug("%s: Registering new mixer ctl %s", __func__, mixer_str); + snd_soc_add_platform_controls(rtd->platform, + chmix_cfg_controls, + ARRAY_SIZE(chmix_cfg_controls)); + kfree(mixer_str); + return 0; +} + static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = "Playback Channel Map"; @@ -3873,7 +4050,6 @@ static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd) ctl_len = strlen(mixer_ctl_name) + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); - if (!mixer_str) { pr_err("%s: failed to allocate mixer ctrl str of len %d\n", __func__, ctl_len); @@ -3932,6 +4108,9 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) if (rc) pr_err("%s: Could not add Compr Channel Map Control\n", __func__); + rc = msm_compr_add_chmix_cfg_controls(rtd); + if (rc) + pr_err("%s: add chmix cfg controls failed:%d\n", __func__, rc); return 0; } diff --git a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c index e5c226f9126b..1c40ba0fa3c1 100644 --- a/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-dai-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -190,17 +190,25 @@ struct msm_dai_q6_auxpcm_dai_data { struct msm_dai_q6_dai_data bdai_data; /* incoporate base DAI data */ }; +static union afe_port_group_config group_cfg_tx; +static union afe_port_group_config group_cfg_rx; + struct msm_dai_q6_tdm_dai_data { DECLARE_BITMAP(status_mask, STATUS_MAX); u32 rate; u32 channels; u32 bitwidth; u32 num_group_ports; + bool afe_ebit_unsupported; + bool sec_port_enable; struct afe_clk_set clk_set; /* hold LPASS clock config. */ union afe_port_group_config group_cfg; /* hold tdm group config */ struct afe_tdm_port_config port_cfg; /* hold tdm config */ }; +static bool afe_ebit_unsupported; +static bool tdm_sec_port_enable; + /* MI2S format field for AFE_PORT_CMD_I2S_CONFIG command * 0: linear PCM * 1: non-linear PCM @@ -2049,7 +2057,7 @@ static struct snd_soc_dai_driver msm_dai_q6_afe_lb_tx_dai[] = { .channels_min = 1, .channels_max = 8, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 48000, }, .id = AFE_LOOPBACK_TX, .probe = msm_dai_q6_dai_probe, @@ -3127,6 +3135,10 @@ static int msm_dai_q6_mi2s_hw_params(struct snd_pcm_substream *substream, dai_data->port_config.i2s.bit_width = 24; dai_data->bitwidth = 24; break; + case SNDRV_PCM_FORMAT_S32_LE: + dai_data->port_config.i2s.bit_width = 32; + dai_data->bitwidth = 32; + break; default: pr_err("%s: format %d\n", __func__, params_format(params)); @@ -3285,10 +3297,14 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { .stream_name = "Primary MI2S Capture", .aif_name = "PRI_MI2S_TX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &msm_dai_q6_mi2s_ops, .id = MSM_PRIM_MI2S, @@ -3310,10 +3326,14 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { .stream_name = "Secondary MI2S Capture", .aif_name = "SEC_MI2S_TX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &msm_dai_q6_mi2s_ops, .id = MSM_SEC_MI2S, @@ -3334,10 +3354,14 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { .stream_name = "Tertiary MI2S Capture", .aif_name = "TERT_MI2S_TX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &msm_dai_q6_mi2s_ops, .id = MSM_TERT_MI2S, @@ -3359,10 +3383,14 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { .stream_name = "Quaternary MI2S Capture", .aif_name = "QUAT_MI2S_TX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &msm_dai_q6_mi2s_ops, .id = MSM_QUAT_MI2S, @@ -3396,10 +3424,14 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { .stream_name = "Quinary MI2S Capture", .aif_name = "QUIN_MI2S_TX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &msm_dai_q6_mi2s_ops, .id = MSM_QUIN_MI2S, @@ -3411,10 +3443,14 @@ static struct snd_soc_dai_driver msm_dai_q6_mi2s_dai[] = { .stream_name = "Senary_mi2s Capture", .aif_name = "SENARY_TX", .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_8000 | - SNDRV_PCM_RATE_16000, - .formats = SNDRV_PCM_FMTBIT_S16_LE, + SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000, + .formats = (SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), .rate_min = 8000, - .rate_max = 48000, + .rate_max = 192000, }, .ops = &msm_dai_q6_mi2s_ops, .id = MSM_SENARY_MI2S, @@ -4151,6 +4187,16 @@ static int msm_dai_tdm_q6_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "%s: Clk Attribute from DT file %d\n", __func__, tdm_clk_set.clk_attri); + afe_ebit_unsupported = of_property_read_bool(pdev->dev.of_node, + "qcom,msm-cpudai-tdm-afe-ebit-unsupported"); + + dev_dbg(&pdev->dev, "afe_ebit_unsupported %d\n", afe_ebit_unsupported); + + tdm_sec_port_enable = of_property_read_bool(pdev->dev.of_node, + "qcom,msm-cpudai-tdm-sec-port-enable"); + + dev_dbg(&pdev->dev, "tdm_sec_port_enable %d\n", tdm_sec_port_enable); + /* other initializations within device group */ atomic_set(&tdm_group_ref[group_idx], 0); @@ -4926,6 +4972,9 @@ static int msm_dai_q6_tdm_set_clk( { int rc = 0; + pr_debug("dai_data->group_cfg.tdm_cfg.group_id = %d : %d\n", + dai_data->group_cfg.tdm_cfg.group_id, + dai_data->clk_set.clk_freq_in_hz); switch (dai_data->group_cfg.tdm_cfg.group_id) { case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX: case AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX: @@ -5097,11 +5146,15 @@ static int msm_dai_q6_dai_tdm_remove(struct snd_soc_dai *dai) dev_err(dai->dev, "fail to disable AFE group 0x%x\n", group_id); } - rc = msm_dai_q6_tdm_set_clk(tdm_dai_data, - dai->id, false); - if (IS_ERR_VALUE(rc)) { - dev_err(dai->dev, "%s: fail to disable AFE clk 0x%x\n", + if (!(tdm_dai_data->afe_ebit_unsupported && + !tdm_dai_data->clk_set.clk_freq_in_hz)) { + rc = msm_dai_q6_tdm_set_clk(tdm_dai_data, + dai->id, false); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, + "%s: fail to disable AFE clk 0x%x\n", __func__, dai->id); + } } } } @@ -5138,6 +5191,10 @@ static int msm_dai_q6_tdm_set_tdm_slot(struct snd_soc_dai *dai, case 16: cap_mask = 0xFFFF; break; + case 4: + cap_mask = 0xF; + break; + default: dev_err(dai->dev, "%s: invalid slots %d\n", __func__, slots); @@ -5180,6 +5237,11 @@ static int msm_dai_q6_tdm_set_tdm_slot(struct snd_soc_dai *dai, tdm_group->nslots_per_frame = slots; tdm_group->slot_width = slot_width; tdm_group->slot_mask = rx_mask & cap_mask; + dev_dbg(dai->dev, "%s:Rx:tdm_group->nslots_per_frame %d\n" + "tdm_group->slot_width %d\n" + "tdm_group->slot_mask %d\n", __func__, + tdm_group->nslots_per_frame, + tdm_group->slot_width, tdm_group->slot_mask); break; case AFE_PORT_ID_PRIMARY_TDM_TX: case AFE_PORT_ID_PRIMARY_TDM_TX_1: @@ -5216,6 +5278,10 @@ static int msm_dai_q6_tdm_set_tdm_slot(struct snd_soc_dai *dai, tdm_group->nslots_per_frame = slots; tdm_group->slot_width = slot_width; tdm_group->slot_mask = tx_mask & cap_mask; + dev_dbg(dai->dev, "%s:Tx:tdm_group->nslots_per_frame %d\n" + "tdm_group->slot_width %d,tdm_group->slot_mask %d\n" + "tx%d\n", __func__, tdm_group->nslots_per_frame, + tdm_group->slot_width, tdm_group->slot_mask, tx_mask); break; default: dev_err(dai->dev, "%s: invalid dai id 0x%x\n", @@ -5516,7 +5582,34 @@ static int msm_dai_q6_tdm_hw_params(struct snd_pcm_substream *substream, custom_tdm_header->header[6], custom_tdm_header->header[7]); } + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + group_cfg_tx.tdm_cfg.num_channels = + dai_data->group_cfg.tdm_cfg.num_channels; + group_cfg_tx.tdm_cfg.sample_rate = + dai_data->group_cfg.tdm_cfg.sample_rate; + group_cfg_tx.tdm_cfg.bit_width = + dai_data->group_cfg.tdm_cfg.bit_width; + group_cfg_tx.tdm_cfg.nslots_per_frame = + dai_data->group_cfg.tdm_cfg.nslots_per_frame; + group_cfg_tx.tdm_cfg.slot_width = + dai_data->group_cfg.tdm_cfg.slot_width; + group_cfg_tx.tdm_cfg.slot_mask = + dai_data->group_cfg.tdm_cfg.slot_mask; + } else { + group_cfg_rx.tdm_cfg.num_channels = + dai_data->group_cfg.tdm_cfg.num_channels; + group_cfg_rx.tdm_cfg.sample_rate = + dai_data->group_cfg.tdm_cfg.sample_rate; + group_cfg_rx.tdm_cfg.bit_width = + dai_data->group_cfg.tdm_cfg.bit_width; + group_cfg_rx.tdm_cfg.nslots_per_frame = + dai_data->group_cfg.tdm_cfg.nslots_per_frame; + group_cfg_rx.tdm_cfg.slot_width = + dai_data->group_cfg.tdm_cfg.slot_width; + group_cfg_rx.tdm_cfg.slot_mask = + dai_data->group_cfg.tdm_cfg.slot_mask; + } return 0; } @@ -5527,8 +5620,13 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream, struct msm_dai_q6_tdm_dai_data *dai_data = dev_get_drvdata(dai->dev); u16 group_id = dai_data->group_cfg.tdm_cfg.group_id; + u16 sec_group_id = 0; int group_idx = 0; + int sec_group_idx = 0; + u16 prim_port_id = 0; + u16 sec_port_id = 0; atomic_t *group_ref = NULL; + atomic_t *sec_group_ref = NULL; group_idx = msm_dai_q6_get_group_idx(dai->id); if (group_idx < 0) { @@ -5548,41 +5646,165 @@ static int msm_dai_q6_tdm_prepare(struct snd_pcm_substream *substream, /* TX and RX share the same clk. AFE clk is enabled per group to simplify the logic. DSP will monitor the clk count. */ - rc = msm_dai_q6_tdm_set_clk(dai_data, - dai->id, true); - if (IS_ERR_VALUE(rc)) { - dev_err(dai->dev, "%s: fail to enable AFE clk 0x%x\n", - __func__, dai->id); - goto rtn; + if (!(dai_data->afe_ebit_unsupported && + !dai_data->clk_set.clk_freq_in_hz)) { + rc = msm_dai_q6_tdm_set_clk(dai_data, + dai->id, true); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, + "%s:AFE CLK enable fail 0x%x\n", + __func__, dai->id); + goto rtn; + } } if (dai_data->num_group_ports > 1) { + dev_dbg(dai->dev, "%s:enable afe group\n", + __func__); rc = afe_port_group_enable(group_id, &dai_data->group_cfg, true); if (IS_ERR_VALUE(rc)) { - dev_err(dai->dev, "%s: fail to enable AFE group 0x%x\n", + dev_err(dai->dev, + "%s:failed to enable grp %x\n", __func__, group_id); goto rtn; } } } - - rc = afe_tdm_port_start(dai->id, &dai_data->port_cfg, + /* + * 8909 HW has a dependency where for Rx/Tx to work in TDM mode + * We need to start a Tx or Rx port in the same group. + * Hence for BG use TDM_TX when a RX session is requested and + * use TDM_RX port when a TX session is requested as these ports + * are unused as of now. + */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + prim_port_id = dai->id; + if (dai_data->sec_port_enable) { + sec_port_id = AFE_PORT_ID_PRIMARY_TDM_TX; + sec_group_ref = &tdm_group_ref[sec_group_idx]; + } + if ((dai_data->num_group_ports > 1) && + (dai_data->sec_port_enable)) { + sec_group_id = + AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX; + sec_group_idx = + msm_dai_q6_get_group_idx(sec_group_id); + if (sec_group_idx < 0) { + dev_err(dai->dev, "%s port id 0x%x\n" + "not supported\n", __func__, + sec_group_id); + goto rtn; + } + if (atomic_read(sec_group_ref) == 0) { + rc = afe_port_group_enable( + sec_group_id, + &group_cfg_tx, + true); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, + "%s:failed to\n" + "enable grp\n" + "%x\n", __func__, + group_id); + goto rtn; + } + } + } + } else { + prim_port_id = dai->id; + if (dai_data->sec_port_enable) { + sec_port_id = AFE_PORT_ID_PRIMARY_TDM_RX; + sec_group_ref = &tdm_group_ref[sec_group_idx]; + } + if ((dai_data->num_group_ports > 1) && + (dai_data->sec_port_enable)) { + sec_group_id = + AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX; + sec_group_idx = + msm_dai_q6_get_group_idx(sec_group_id); + if (sec_group_idx < 0) { + dev_err(dai->dev, "%s port id 0x%x\n" + " not supported\n", __func__, + sec_group_id); + goto rtn; + } + if (atomic_read(sec_group_ref) == 0) { + rc = afe_port_group_enable( + sec_group_id, + &group_cfg_rx, + true); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, + "%s:failed to\n" + "enable grp\n" + "%x\n", __func__, + group_id); + goto rtn; + } + } + } + } + dev_dbg(dai->dev, "\n%s:open prim port id %d TDM rate: %d\n" + "dai_data->port_cfg.tdm.slot_mask %x\n" + "dai_data->port_cfg.tdm.nslots_per_frame:%x\n", + __func__, prim_port_id, + dai_data->port_cfg.tdm.num_channels, + dai_data->port_cfg.tdm.slot_mask, + dai_data->port_cfg.tdm.nslots_per_frame); + + rc = afe_tdm_port_start(prim_port_id, &dai_data->port_cfg, dai_data->rate, dai_data->num_group_ports); + if (IS_ERR_VALUE(rc)) { if (atomic_read(group_ref) == 0) { afe_port_group_enable(group_id, NULL, false); - msm_dai_q6_tdm_set_clk(dai_data, - dai->id, false); + if (!(dai_data->afe_ebit_unsupported && + !dai_data->clk_set.clk_freq_in_hz)) + msm_dai_q6_tdm_set_clk(dai_data, + dai->id, false); } - dev_err(dai->dev, "%s: fail to open AFE port 0x%x\n", - __func__, dai->id); + dev_err(dai->dev, "%s: open AFE port 0x%x\n", + __func__, prim_port_id); } else { set_bit(STATUS_PORT_STARTED, dai_data->status_mask); atomic_inc(group_ref); } + dai_data->port_cfg.tdm.num_channels = 1; + dai_data->port_cfg.tdm.slot_mask = 1; + + dev_dbg(dai->dev, "\n%s:open sec port id %d TDM rate: %d\n" + "dai_data->port_cfg.tdm.slot_mask %x\n" + "dai_data->port_cfg.tdm.nslotsper_frame:%x\n", __func__, + sec_port_id, dai_data->port_cfg.tdm.num_channels, + dai_data->port_cfg.tdm.slot_mask, + dai_data->port_cfg.tdm.nslots_per_frame); + + if (sec_port_id != 0) { + rc = afe_tdm_port_start(sec_port_id, + &dai_data->port_cfg, + dai_data->rate, + dai_data->num_group_ports); + if (IS_ERR_VALUE(rc)) { + if (atomic_read(group_ref) == 0) { + afe_port_group_enable(group_id, + NULL, false); + if (!(dai_data->afe_ebit_unsupported && + !dai_data->clk_set.clk_freq_in_hz)) + msm_dai_q6_tdm_set_clk(dai_data, + dai->id, false); + } + dev_err(dai->dev, "%s: fail AFE port 0x%x\n", + __func__, sec_port_id); + } else { + set_bit(STATUS_PORT_STARTED, + dai_data->status_mask); + atomic_inc(sec_group_ref); + } + } + /* TODO: need to monitor PCM/MI2S/TDM HW status */ /* NOTE: AFE should error out if HW resource contention */ @@ -5600,8 +5822,13 @@ static void msm_dai_q6_tdm_shutdown(struct snd_pcm_substream *substream, struct msm_dai_q6_tdm_dai_data *dai_data = dev_get_drvdata(dai->dev); u16 group_id = dai_data->group_cfg.tdm_cfg.group_id; + u16 sec_group_id = 0; int group_idx = 0; + int sec_group_idx = 0; + u16 prim_port_id = 0; + u16 sec_port_id = 0; atomic_t *group_ref = NULL; + atomic_t *sec_group_ref = NULL; group_idx = msm_dai_q6_get_group_idx(dai->id); if (group_idx < 0) { @@ -5615,11 +5842,60 @@ static void msm_dai_q6_tdm_shutdown(struct snd_pcm_substream *substream, group_ref = &tdm_group_ref[group_idx]; if (test_bit(STATUS_PORT_STARTED, dai_data->status_mask)) { - rc = afe_close(dai->id); + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + prim_port_id = dai->id; + if (dai_data->sec_port_enable) { + sec_port_id = AFE_PORT_ID_PRIMARY_TDM_TX; + sec_group_ref = &tdm_group_ref[sec_group_idx]; + } + if ((dai_data->num_group_ports > 1) && + (dai_data->sec_port_enable)) { + sec_group_id = + AFE_GROUP_DEVICE_ID_PRIMARY_TDM_TX; + sec_group_idx = + msm_dai_q6_get_group_idx(sec_group_id); + if (sec_group_idx < 0) { + dev_err(dai->dev, "%s port id 0x%x\n" + "not supported\n", + __func__, sec_group_id); + return; + } + } + } else { + prim_port_id = dai->id; + if (dai_data->sec_port_enable) { + sec_port_id = AFE_PORT_ID_PRIMARY_TDM_RX; + sec_group_ref = &tdm_group_ref[sec_group_idx]; + } + if ((dai_data->num_group_ports > 1) && + (dai_data->sec_port_enable)) { + sec_group_id = + AFE_GROUP_DEVICE_ID_PRIMARY_TDM_RX; + sec_group_idx = + msm_dai_q6_get_group_idx(sec_group_id); + if (sec_group_idx < 0) { + dev_err(dai->dev, "%s port id 0x%x\n" + "not supported\n", + __func__, sec_group_id); + return; + } + } + } + rc = afe_close(prim_port_id); if (IS_ERR_VALUE(rc)) { dev_err(dai->dev, "%s: fail to close AFE port 0x%x\n", - __func__, dai->id); + __func__, prim_port_id); + } + + if (sec_port_id != 0) { + rc = afe_close(sec_port_id); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s: fail AFE port 0x%x\n", + __func__, sec_port_id); + } + atomic_dec(sec_group_ref); } + atomic_dec(group_ref); clear_bit(STATUS_PORT_STARTED, dai_data->status_mask); @@ -5628,17 +5904,32 @@ static void msm_dai_q6_tdm_shutdown(struct snd_pcm_substream *substream, rc = afe_port_group_enable(group_id, NULL, false); if (IS_ERR_VALUE(rc)) { - dev_err(dai->dev, "%s: fail to disable AFE group 0x%x\n", + dev_err(dai->dev, + "%s: failed to disable grp 0x%x\n", __func__, group_id); } - rc = msm_dai_q6_tdm_set_clk(dai_data, - dai->id, false); - if (IS_ERR_VALUE(rc)) { - dev_err(dai->dev, "%s: fail to disable AFE clk 0x%x\n", + if (!(dai_data->afe_ebit_unsupported && + !dai_data->clk_set.clk_freq_in_hz)) { + rc = msm_dai_q6_tdm_set_clk(dai_data, + dai->id, false); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, + "%s: fail to disable AFE clk 0x%x\n", __func__, dai->id); + } + } + } + if ((dai_data->num_group_ports > 1) && + (dai_data->sec_port_enable)) { + if (atomic_read(sec_group_ref) == 0) { + rc = afe_port_group_enable(sec_group_id, + NULL, false); + if (IS_ERR_VALUE(rc)) { + dev_err(dai->dev, "%s:failed to\n" + "enable grp %x\n", __func__, group_id); + } } } - /* TODO: need to monitor PCM/MI2S/TDM HW status */ /* NOTE: AFE should error out if HW resource contention */ @@ -7005,6 +7296,46 @@ static int msm_dai_q6_tdm_dev_probe(struct platform_device *pdev) dai_data->group_cfg.tdm_cfg = tdm_group_cfg; /* copy static num group ports per parent node */ dai_data->num_group_ports = num_tdm_group_ports[group_idx]; + dev_dbg(&pdev->dev, "TX group configuration tdm_dev_id 0x%x\n", + tdm_dev_id); + + dai_data->afe_ebit_unsupported = afe_ebit_unsupported; + dai_data->sec_port_enable = tdm_sec_port_enable; + + if (tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX || + tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_1 || + tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_2 || + tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_TX_3) { + memcpy(&group_cfg_tx.group_cfg, + &dai_data->group_cfg.group_cfg , + sizeof(dai_data->group_cfg.group_cfg)); + memcpy(&group_cfg_tx.group_enable, + &dai_data->group_cfg.group_enable, + sizeof(dai_data->group_cfg.group_enable)); + memcpy(&group_cfg_tx.tdm_cfg, + &dai_data->group_cfg.tdm_cfg, + sizeof(dai_data->group_cfg.tdm_cfg)); + dev_dbg(&pdev->dev, + "Copy TX group configuration Successfully tdm_id %d\n", + tdm_dev_id); + } + if (tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_RX || + tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_RX_1 || + tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_RX_2 || + tdm_dev_id == AFE_PORT_ID_PRIMARY_TDM_RX_3) { + memcpy(&group_cfg_rx.group_cfg, + &dai_data->group_cfg.group_cfg , + sizeof(dai_data->group_cfg.group_cfg)); + memcpy(&group_cfg_rx.group_enable, + &dai_data->group_cfg.group_enable, + sizeof(dai_data->group_cfg.group_enable)); + memcpy(&group_cfg_rx.tdm_cfg, + &dai_data->group_cfg.tdm_cfg, + sizeof(dai_data->group_cfg.tdm_cfg)); + dev_dbg(&pdev->dev, + "Copy RX group configuration Successfully tdm_id %d\n", + tdm_dev_id); + } dev_set_drvdata(&pdev->dev, dai_data); diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c index eefae71a27bf..e505f416ab2c 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -34,6 +34,7 @@ #include #include #include +#include #include "msm-pcm-q6-v2.h" #include "msm-pcm-routing-v2.h" @@ -68,10 +69,11 @@ static struct snd_pcm_hardware msm_pcm_hardware_capture = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), - .rates = SNDRV_PCM_RATE_8000_48000, + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .rates = SNDRV_PCM_RATE_8000_384000, .rate_min = 8000, - .rate_max = 48000, + .rate_max = 384000, .channels_min = 1, .channels_max = 4, .buffer_bytes_max = CAPTURE_MAX_NUM_PERIODS * @@ -91,10 +93,11 @@ static struct snd_pcm_hardware msm_pcm_hardware_playback = { SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME), .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S24_3LE), - .rates = SNDRV_PCM_RATE_8000_192000, + SNDRV_PCM_FMTBIT_S24_3LE | + SNDRV_PCM_FMTBIT_S32_LE), + .rates = SNDRV_PCM_RATE_8000_384000, .rate_min = 8000, - .rate_max = 192000, + .rate_max = 384000, .channels_min = 1, .channels_max = 8, .buffer_bytes_max = PLAYBACK_MAX_NUM_PERIODS * @@ -109,7 +112,7 @@ static struct snd_pcm_hardware msm_pcm_hardware_playback = { /* Conventional and unconventional sample rate supported */ static unsigned int supported_sample_rates[] = { 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, - 88200, 96000, 176400, 192000 + 88200, 96000, 176400, 192000, 384000 }; static struct snd_pcm_hw_constraint_list constraints_sample_rates = { @@ -290,7 +293,7 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) struct msm_audio *prtd = runtime->private_data; struct msm_plat_data *pdata; struct snd_pcm_hw_params *params; - int ret; + int ret = 0; uint16_t bits_per_sample; uint16_t sample_word_size; @@ -321,6 +324,10 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) pr_debug("%s: perf: %x\n", __func__, prtd->audio_client->perf_mode); switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S32_LE: + bits_per_sample = 32; + sample_word_size = 32; + break; case SNDRV_PCM_FORMAT_S24_LE: bits_per_sample = 24; sample_word_size = 32; @@ -336,9 +343,20 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) break; } - ret = q6asm_open_write_v3(prtd->audio_client, - FORMAT_LINEAR_PCM, bits_per_sample); - + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_7): + ret = q6asm_open_write_v3(prtd->audio_client, + FORMAT_LINEAR_PCM, bits_per_sample); + break; + case (Q6_SUBSYS_AVS2_8): + ret = q6asm_open_write_v4(prtd->audio_client, + FORMAT_LINEAR_PCM, bits_per_sample); + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } if (ret < 0) { pr_err("%s: q6asm_open_write_v2 failed\n", __func__); q6asm_audio_client_free(prtd->audio_client); @@ -361,11 +379,28 @@ static int msm_pcm_playback_prepare(struct snd_pcm_substream *substream) return ret; } - ret = q6asm_media_format_block_multi_ch_pcm_v3( + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_7): + ret = q6asm_media_format_block_multi_ch_pcm_v3( prtd->audio_client, runtime->rate, runtime->channels, !prtd->set_channel_map, prtd->channel_map, bits_per_sample, sample_word_size); + break; + case (Q6_SUBSYS_AVS2_8): + ret = q6asm_media_format_block_multi_ch_pcm_v4( + prtd->audio_client, runtime->rate, + runtime->channels, !prtd->set_channel_map, + prtd->channel_map, bits_per_sample, + sample_word_size, ASM_LITTLE_ENDIAN, + DEFAULT_QF); + + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } if (ret < 0) pr_info("%s: CMD Format block failed\n", __func__); @@ -410,6 +445,8 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) if ((params_format(params) == SNDRV_PCM_FORMAT_S24_LE) || (params_format(params) == SNDRV_PCM_FORMAT_S24_3LE)) bits_per_sample = 24; + else if (params_format(params) == SNDRV_PCM_FORMAT_S32_LE) + bits_per_sample = 32; /* ULL mode is not supported in capture path */ if (pdata->perf_mode_set == LEGACY_PCM_MODE) @@ -421,8 +458,23 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) __func__, params_channels(params), prtd->audio_client->perf_mode); - ret = q6asm_open_read_v3(prtd->audio_client, FORMAT_LINEAR_PCM, - bits_per_sample); + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_7): + ret = q6asm_open_read_v3(prtd->audio_client, + FORMAT_LINEAR_PCM, + bits_per_sample); + break; + case (Q6_SUBSYS_AVS2_8): + ret = q6asm_open_read_v4(prtd->audio_client, + FORMAT_LINEAR_PCM, + bits_per_sample); + + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } if (ret < 0) { pr_err("%s: q6asm_open_read failed\n", __func__); q6asm_audio_client_free(prtd->audio_client); @@ -467,6 +519,10 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) return 0; switch (runtime->format) { + case SNDRV_PCM_FORMAT_S32_LE: + bits_per_sample = 32; + sample_word_size = 32; + break; case SNDRV_PCM_FORMAT_S24_LE: bits_per_sample = 24; sample_word_size = 32; @@ -485,11 +541,32 @@ static int msm_pcm_capture_prepare(struct snd_pcm_substream *substream) pr_debug("%s: Samp_rate = %d Channel = %d bit width = %d, word size = %d\n", __func__, prtd->samp_rate, prtd->channel_mode, bits_per_sample, sample_word_size); - ret = q6asm_enc_cfg_blk_pcm_format_support_v3(prtd->audio_client, - prtd->samp_rate, - prtd->channel_mode, - bits_per_sample, - sample_word_size); + + switch (q6core_get_avs_version()) { + case (Q6_SUBSYS_AVS2_7): + ret = q6asm_enc_cfg_blk_pcm_format_support_v3( + prtd->audio_client, + prtd->samp_rate, + prtd->channel_mode, + bits_per_sample, + sample_word_size); + break; + case (Q6_SUBSYS_AVS2_8): + ret = q6asm_enc_cfg_blk_pcm_format_support_v4( + prtd->audio_client, + prtd->samp_rate, + prtd->channel_mode, + bits_per_sample, + sample_word_size, + ASM_LITTLE_ENDIAN, + DEFAULT_QF); + + break; + case (Q6_SUBSYS_INVALID): + default: + pr_err("%s: INVALID AVS IMAGE\n", __func__); + break; + } if (ret < 0) pr_debug("%s: cmd cfg pcm was block failed", __func__); @@ -1548,6 +1625,150 @@ static int msm_pcm_add_app_type_controls(struct snd_soc_pcm_runtime *rtd) return 0; } +static int msm_pcm_chmix_cfg_ctl_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 128; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xFFFFFFFF; + return 0; +} + +static int msm_pcm_chmix_cfg_ctl_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *usr_info = snd_kcontrol_chip(kcontrol); + struct snd_soc_platform *platform; + struct msm_plat_data *pdata; + struct snd_pcm_substream *substream; + struct msm_audio *prtd; + u64 fe_id = kcontrol->private_value; + int ip_channel_cnt, op_channel_cnt; + int i, index = 0, ret = 0; + int ch_coeff[PCM_FORMAT_MAX_NUM_CHANNEL * PCM_FORMAT_MAX_NUM_CHANNEL]; + bool use_default_chmap = true; + char *ch_map = NULL; + + pr_debug("%s: fe_id- %llu\n", __func__, fe_id); + if (fe_id >= MSM_FRONTEND_DAI_MAX) { + pr_err("%s: Received out of bounds fe_id %llu\n", + __func__, fe_id); + ret = -EINVAL; + goto done; + } + + if (!usr_info) { + pr_err("%s: usr_info is null\n", __func__); + ret = -EINVAL; + goto done; + } + platform = snd_soc_component_to_platform(usr_info); + if (!platform) { + pr_err("%s: platform is null\n", __func__); + ret = -EINVAL; + goto done; + } + pdata = dev_get_drvdata(platform->dev); + if (!pdata) { + pr_err("%s: pdata is null\n", __func__); + ret = -EINVAL; + goto done; + } + substream = pdata->pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; + + if (!substream) { + pr_err("%s substream not found\n", __func__); + return -ENODEV; + } + if (!substream->runtime) { + pr_err("%s substream runtime not found\n", __func__); + ret = -EINVAL; + goto done; + } + prtd = substream->runtime->private_data; + if (!prtd) { + pr_err("%s: stream inactive\n", __func__); + ret = -EINVAL; + goto done; + } + use_default_chmap = !prtd->set_channel_map; + ch_map = prtd->channel_map; + ip_channel_cnt = ucontrol->value.integer.value[index++]; + op_channel_cnt = ucontrol->value.integer.value[index++]; + /* + * wght coeff of first out channel corresponding to each in channel + * are sent followed by second out channel for each in channel etc. + */ + memset(ch_coeff, 0, sizeof(ch_coeff)); + for (i = 0; i < op_channel_cnt * ip_channel_cnt; i++) { + ch_coeff[i] = + ucontrol->value.integer.value[index++]; + } + + msm_pcm_routing_send_chmix_cfg(fe_id, ip_channel_cnt, op_channel_cnt, + ch_coeff, SESSION_TYPE_RX, use_default_chmap, ch_map); +done: + return ret; +} + +static int msm_pcm_chmix_cfg_ctl_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + return 0; +} + +static int msm_pcm_add_chmix_cfg_controls(struct snd_soc_pcm_runtime *rtd) +{ + const char *mixer_ctl_name = "Audio Stream"; + const char *deviceNo = "NN"; + const char *suffix = "Channel Mix Cfg"; + char *mixer_str = NULL; + int ctl_len = 0; + struct msm_plat_data *pdata; + struct snd_kcontrol_new chmix_cfg_controls[1] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "?", + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = msm_pcm_chmix_cfg_ctl_info, + .get = msm_pcm_chmix_cfg_ctl_get, + .put = msm_pcm_chmix_cfg_ctl_put, + .private_value = 0, + } + }; + + if (!rtd) { + pr_err("%s: NULL rtd\n", __func__); + return -EINVAL; + } + + ctl_len = strlen(mixer_ctl_name) + 1 + + strlen(deviceNo) + 1 + strlen(suffix) + 1; + mixer_str = kzalloc(ctl_len, GFP_KERNEL); + if (!mixer_str) + return -ENOMEM; + + snprintf(mixer_str, ctl_len, "%s %d %s", + mixer_ctl_name, rtd->pcm->device, suffix); + chmix_cfg_controls[0].name = mixer_str; + chmix_cfg_controls[0].private_value = rtd->dai_link->be_id; + pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); + pdata = dev_get_drvdata(rtd->platform->dev); + if (pdata) { + if (!pdata->pcm) + pdata->pcm = rtd->pcm; + snd_soc_add_platform_controls(rtd->platform, + chmix_cfg_controls, + ARRAY_SIZE(chmix_cfg_controls)); + } else { + pr_err("%s: NULL pdata\n", __func__); + return -EINVAL; + } + kfree(mixer_str); + return 0; +} + static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) { int ret = 0; @@ -1565,6 +1786,10 @@ static int msm_pcm_add_controls(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add pcm topology control %d\n", __func__, ret); } + + ret = msm_pcm_add_chmix_cfg_controls(rtd); + if (ret) + pr_err("%s: add chmix cfg controls failed:%d\n", __func__, ret); return ret; } diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h index 187133b1db75..b3a7e856a9c0 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-q6-v2.h @@ -1,7 +1,7 @@ /* * Copyright (C) 2008 Google, Inc. * Copyright (C) 2008 HTC Corporation - * Copyright (c) 2012-2017 The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2018 The Linux Foundation. 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 @@ -59,11 +59,11 @@ struct msm_audio_in_frame_info { #define PLAYBACK_MIN_NUM_PERIODS 2 #define PLAYBACK_MAX_NUM_PERIODS 8 -#define PLAYBACK_MAX_PERIOD_SIZE 61440 +#define PLAYBACK_MAX_PERIOD_SIZE 122880 #define PLAYBACK_MIN_PERIOD_SIZE 128 #define CAPTURE_MIN_NUM_PERIODS 2 #define CAPTURE_MAX_NUM_PERIODS 8 -#define CAPTURE_MAX_PERIOD_SIZE 61440 +#define CAPTURE_MAX_PERIOD_SIZE 122880 #define CAPTURE_MIN_PERIOD_SIZE 320 struct msm_audio { @@ -124,6 +124,7 @@ struct output_meta_data_st { struct msm_plat_data { int perf_mode; int perf_mode_set; + struct snd_pcm *pcm; }; #endif /*_MSM_PCM_H*/ diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c index f20c6f7a2a54..f5daf4cf1513 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.c @@ -104,13 +104,16 @@ enum { #define SLIMBUS_5_TX_TEXT "SLIMBUS_5_TX" #define TERT_MI2S_TX_TEXT "TERT_MI2S_TX" #define QUAT_MI2S_TX_TEXT "QUAT_MI2S_TX" +#define PRI_TDM_TX_3_TEXT "PRI_TDM_TX_3" +#define PRI_TDM_TX_2_TEXT "PRI_TDM_TX_2" #define ADM_LSM_TX_TEXT "ADM_LSM_TX" #define LSM_FUNCTION_TEXT "LSM Function" static const char * const lsm_port_text[] = { "None", SLIMBUS_0_TX_TEXT, SLIMBUS_1_TX_TEXT, SLIMBUS_2_TX_TEXT, SLIMBUS_3_TX_TEXT, SLIMBUS_4_TX_TEXT, SLIMBUS_5_TX_TEXT, - TERT_MI2S_TX_TEXT, QUAT_MI2S_TX_TEXT, ADM_LSM_TX_TEXT + TERT_MI2S_TX_TEXT, QUAT_MI2S_TX_TEXT, ADM_LSM_TX_TEXT, + PRI_TDM_TX_2_TEXT, PRI_TDM_TX_3_TEXT, }; struct msm_pcm_route_bdai_pp_params { @@ -133,6 +136,9 @@ static int msm_routing_get_bit_width(unsigned int format) int bit_width; switch (format) { + case SNDRV_PCM_FORMAT_S32_LE: + bit_width = 32; + break; case SNDRV_PCM_FORMAT_S24_LE: case SNDRV_PCM_FORMAT_S24_3LE: bit_width = 24; @@ -682,6 +688,78 @@ static bool is_mm_lsm_fe_id(int fe_id) return rc; } +/* + * msm_pcm_routing_send_chmix_cfg + * + * Receives fe_id, ip_channel_cnt, op_channel_cnt, channel weight, session_type + * use_default_chmap and channel map to map in channel mixer and send to + * adm programmable matrix. + * + * fe_id - Passed value, frontend id which is wanted + * ip_channel_cnt - Passed value, number of input channels + * op_channel_cnt - Passed value, number of output channels + * ch_wght_coeff - Passed reference, weights for each output channel + * session_type - Passed value, session_type for RX or TX + * use_default_chmap - true if default channel map to be used + * ch_map - input/output channel map for playback/capture session respectively + */ + +int msm_pcm_routing_send_chmix_cfg(int fe_id, int ip_channel_cnt, + int op_channel_cnt, int *ch_wght_coeff, + int session_type, bool use_default_chmap, + char *channel_map) +{ + int rc = 0, idx = 0, i, j; + int be_index = 0, port_id, index = 0; + unsigned int session_id = 0; + + pr_debug("%s: fe_id[%d] ip_ch[%d] op_ch[%d] sess_type [%d]\n", + __func__, fe_id, ip_channel_cnt, op_channel_cnt, session_type); + + if (!use_default_chmap && (channel_map == NULL)) { + pr_err("%s: No valid chan map and can't use default\n", + __func__); + return -EINVAL; + } + + if ((ch_wght_coeff == NULL) || (op_channel_cnt > ADM_MAX_CHANNELS) || + (ip_channel_cnt > ADM_MAX_CHANNELS)) { + pr_err("%s: Invalid channels or null coefficients\n", __func__); + return -EINVAL; + } + + for (be_index = 0; be_index < MSM_BACKEND_DAI_MAX; be_index++) { + port_id = msm_bedais[be_index].port_id; + if (!msm_bedais[be_index].active || + !test_bit(fe_id, &msm_bedais[be_index].fe_sessions)) + continue; + + session_id = fe_dai_map[fe_id][session_type].strm_id; + channel_mixer[fe_id].input_channels[0] = ip_channel_cnt; + channel_mixer[fe_id].output_channel = op_channel_cnt; + channel_mixer[fe_id].rule = 0; + + for (j = 0; j < op_channel_cnt; j++) { + for (i = 0; i < ip_channel_cnt; i++) + channel_mixer[fe_id].channel_weight[j][i] = + ch_wght_coeff[index++]; + } + for (idx = 0; idx < MAX_COPPS_PER_PORT; idx++) { + unsigned long copp = + session_copp_map[fe_id][session_type][be_index]; + if (!test_bit(idx, &copp)) + continue; + rc = adm_programable_channel_mixer(port_id, + idx, session_id, session_type, + channel_mixer + fe_id, 0, + use_default_chmap, channel_map); + if (rc < 0) + pr_err("%s: err setting channel mix config\n", + __func__); + } + } + return 0; +} void msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int app_type, int acdb_dev_id, int sample_rate, int session_type) @@ -1139,6 +1217,8 @@ static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode, int sess_type = 0; int i = 0, j = 0, be_id; int ret = 0; + bool use_default_chmap = true; + char *ch_map = NULL; if (fe_id >= MSM_FRONTEND_DAI_MM_SIZE) { pr_err("%s: invalid FE %d\n", __func__, fe_id); @@ -1181,7 +1261,8 @@ static int msm_pcm_routing_channel_mixer(int fe_id, bool perf_mode, ret = adm_programable_channel_mixer( msm_bedais[be_id].port_id, copp_idx, dspst_id, sess_type, - channel_mixer + fe_id, i); + channel_mixer + fe_id, i, + use_default_chmap, ch_map); } } @@ -2057,6 +2138,12 @@ static int msm_routing_lsm_port_put(struct snd_kcontrol *kcontrol, case 9: lsm_port = ADM_LSM_PORT_ID; break; + case 10: + lsm_port = AFE_PORT_ID_PRIMARY_TDM_TX_2; + break; + case 11: + lsm_port = AFE_PORT_ID_PRIMARY_TDM_TX_3; + break; default: pr_err("Default lsm port"); break; @@ -3233,6 +3320,7 @@ static const struct snd_kcontrol_new ext_ec_ref_mux_ul2 = SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL2 MUX Mux", msm_route_ec_ref_rx_enum[0], msm_routing_ec_ref_rx_get, msm_routing_ec_ref_rx_put); + static const struct snd_kcontrol_new ext_ec_ref_mux_ul3 = SOC_DAPM_ENUM_EXT("AUDIO_REF_EC_UL3 MUX Mux", msm_route_ec_ref_rx_enum[0], @@ -4033,15 +4121,6 @@ static const struct snd_kcontrol_new secondary_mi2s_rx_mixer_controls[] = { msm_routing_put_audio_mixer), }; -static const struct snd_kcontrol_new mi2s_hl_mixer_controls[] = { - SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX, - MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, msm_routing_get_port_mixer, - msm_routing_put_port_mixer), - SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX, - MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer, - msm_routing_put_port_mixer), -}; - static const struct snd_kcontrol_new primary_mi2s_rx_mixer_controls[] = { SOC_SINGLE_EXT("MultiMedia1", MSM_BACKEND_DAI_PRI_MI2S_RX , MSM_FRONTEND_DAI_MULTIMEDIA1, 1, 0, msm_routing_get_audio_mixer, @@ -7376,6 +7455,9 @@ static const struct snd_kcontrol_new tx_voip_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX_Voip", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3_Voip", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_VOIP, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), }; static const struct snd_kcontrol_new tx_voice_stub_mixer_controls[] = { @@ -7510,6 +7592,9 @@ static const struct snd_kcontrol_new tx_qchat_mixer_controls[] = { SOC_SINGLE_EXT("TERT_MI2S_TX_QCHAT", MSM_BACKEND_DAI_TERTIARY_MI2S_TX, MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer, msm_routing_put_voice_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3_QCHAT", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_QCHAT, 1, 0, msm_routing_get_voice_mixer, + msm_routing_put_voice_mixer), }; static const struct snd_kcontrol_new sbus_0_rx_port_mixer_controls[] = { @@ -8854,6 +8939,9 @@ static const struct snd_kcontrol_new sec_mi2s_rx_port_mixer_controls[] = { SOC_SINGLE_EXT("PRI_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX, MSM_BACKEND_DAI_PRI_MI2S_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), + SOC_SINGLE_EXT("INTERNAL_FM_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX, + MSM_BACKEND_DAI_INT_FM_TX, 1, 0, msm_routing_get_port_mixer, + msm_routing_put_port_mixer), SOC_SINGLE_EXT("TERT_MI2S_TX", MSM_BACKEND_DAI_SECONDARY_MI2S_RX, MSM_BACKEND_DAI_TERTIARY_MI2S_TX, 1, 0, msm_routing_get_port_mixer, msm_routing_put_port_mixer), @@ -8896,6 +8984,12 @@ static const struct snd_kcontrol_new lsm1_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_LSM1, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), }; static const struct snd_kcontrol_new lsm2_mixer_controls[] = { @@ -8920,6 +9014,12 @@ static const struct snd_kcontrol_new lsm2_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_LSM2, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), }; static const struct snd_kcontrol_new lsm3_mixer_controls[] = { @@ -8944,6 +9044,12 @@ static const struct snd_kcontrol_new lsm3_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_LSM3, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), }; static const struct snd_kcontrol_new lsm4_mixer_controls[] = { @@ -8968,6 +9074,12 @@ static const struct snd_kcontrol_new lsm4_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_LSM4, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), }; static const struct snd_kcontrol_new lsm5_mixer_controls[] = { @@ -8992,6 +9104,12 @@ static const struct snd_kcontrol_new lsm5_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_LSM5, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), }; static const struct snd_kcontrol_new lsm6_mixer_controls[] = { @@ -9016,6 +9134,12 @@ static const struct snd_kcontrol_new lsm6_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_LSM6, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), }; static const struct snd_kcontrol_new lsm7_mixer_controls[] = { @@ -9040,6 +9164,12 @@ static const struct snd_kcontrol_new lsm7_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_LSM7, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), }; static const struct snd_kcontrol_new lsm8_mixer_controls[] = { @@ -9064,6 +9194,12 @@ static const struct snd_kcontrol_new lsm8_mixer_controls[] = { SOC_SINGLE_EXT("QUAT_MI2S_TX", MSM_BACKEND_DAI_QUATERNARY_MI2S_TX, MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_2", MSM_BACKEND_DAI_PRI_TDM_TX_2, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), + SOC_SINGLE_EXT("PRI_TDM_TX_3", MSM_BACKEND_DAI_PRI_TDM_TX_3, + MSM_FRONTEND_DAI_LSM8, 1, 0, msm_routing_get_listen_mixer, + msm_routing_put_listen_mixer), }; static const struct snd_kcontrol_new slim_fm_switch_mixer_controls = @@ -9158,6 +9294,10 @@ static const struct snd_kcontrol_new lsm_controls[] = { msm_routing_lsm_func_get, msm_routing_lsm_func_put), SOC_ENUM_EXT(QUAT_MI2S_TX_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, msm_routing_lsm_func_get, msm_routing_lsm_func_put), + SOC_ENUM_EXT(PRI_TDM_TX_2_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, + msm_routing_lsm_func_get, msm_routing_lsm_func_put), + SOC_ENUM_EXT(PRI_TDM_TX_3_TEXT" "LSM_FUNCTION_TEXT, lsm_func_enum, + msm_routing_lsm_func_get, msm_routing_lsm_func_put), /* kcontrol of lsm_port */ SOC_ENUM_EXT("LSM1 Port", lsm_port_enum, msm_routing_lsm_port_get, @@ -9649,6 +9789,9 @@ static int msm_audio_sound_focus_derive_port_id(struct snd_kcontrol *kcontrol, } else if (!strcmp(kcontrol->id.name + strlen(prefix), "QUATERNARY_MI2S")) { *port_id = AFE_PORT_ID_QUATERNARY_MI2S_TX; + } else if (!strcmp(kcontrol->id.name + strlen(prefix), + "PRIMARY_TDM")) { + *port_id = AFE_PORT_ID_PRIMARY_TDM_TX; } else { pr_err("%s: mixer ctl name=%s, could not derive valid port id\n", __func__, kcontrol->id.name); @@ -9868,6 +10011,21 @@ static const struct snd_kcontrol_new msm_source_tracking_controls[] = { .info = msm_source_tracking_info, .get = msm_audio_source_tracking_get, }, + { + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Sound Focus Audio Tx PRIMARY_TDM", + .info = msm_sound_focus_info, + .get = msm_audio_sound_focus_get, + .put = msm_audio_sound_focus_put, + }, + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Source Tracking Audio Tx PRIMARY_TDM", + .info = msm_source_tracking_info, + .get = msm_audio_source_tracking_get, + }, }; static int spkr_prot_put_vi_lch_port(struct snd_kcontrol *kcontrol, @@ -10390,6 +10548,8 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_AIF_IN("SLIMBUS_2_TX", "Slimbus2 Capture", 0, 0, 0, 0), SND_SOC_DAPM_AIF_IN("QUIN_MI2S_TX", "Quinary MI2S Capture", 0, 0, 0, 0), + SND_SOC_DAPM_AIF_IN("SENARY_MI2S_TX", "Senary MI2S Capture", + 0, 0, 0, 0), SND_SOC_DAPM_AIF_OUT("INT_BT_SCO_RX", "Internal BT-SCO Playback", 0, 0, 0 , 0), SND_SOC_DAPM_AIF_IN("INT_BT_SCO_TX", "Internal BT-SCO Capture", @@ -10631,9 +10791,6 @@ static const struct snd_soc_dapm_widget msm_qdsp6_widgets[] = { SND_SOC_DAPM_MIXER("SEC_MI2S_RX_SD1 Audio Mixer", SND_SOC_NOPM, 0, 0, secondary_mi2s_rx2_mixer_controls, ARRAY_SIZE(secondary_mi2s_rx2_mixer_controls)), - SND_SOC_DAPM_MIXER("SEC_MI2S_RX Port Mixer", SND_SOC_NOPM, 0, 0, - mi2s_hl_mixer_controls, - ARRAY_SIZE(mi2s_hl_mixer_controls)), SND_SOC_DAPM_MIXER("PRI_MI2S_RX Audio Mixer", SND_SOC_NOPM, 0, 0, primary_mi2s_rx_mixer_controls, ARRAY_SIZE(primary_mi2s_rx_mixer_controls)), @@ -11256,9 +11413,6 @@ static const struct snd_soc_dapm_route intercon[] = { {"SEC_MI2S_RX_SD1 Audio Mixer", "MultiMedia6", "MM_DL6"}, {"SEC_MI2S_RX_SD1", NULL, "SEC_MI2S_RX_SD1 Audio Mixer"}, - {"SEC_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, - {"SEC_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, - {"PRI_MI2S_RX Audio Mixer", "MultiMedia1", "MM_DL1"}, {"PRI_MI2S_RX Audio Mixer", "MultiMedia2", "MM_DL2"}, {"PRI_MI2S_RX Audio Mixer", "MultiMedia3", "MM_DL3"}, @@ -11267,6 +11421,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"PRI_MI2S_RX Audio Mixer", "MultiMedia6", "MM_DL6"}, {"PRI_MI2S_RX Audio Mixer", "MultiMedia7", "MM_DL7"}, {"PRI_MI2S_RX Audio Mixer", "MultiMedia8", "MM_DL8"}, + {"PRI_MI2S_RX Audio Mixer", "MultiMedia9", "MM_DL9"}, {"PRI_MI2S_RX Audio Mixer", "MultiMedia10", "MM_DL10"}, {"PRI_MI2S_RX Audio Mixer", "MultiMedia11", "MM_DL11"}, {"PRI_MI2S_RX Audio Mixer", "MultiMedia12", "MM_DL12"}, @@ -12087,6 +12242,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"INTERNAL_BT_SCO_RX_Voice Mixer", "QCHAT", "QCHAT_DL"}, {"INTERNAL_BT_SCO_RX_Voice Mixer", "VoiceMMode1", "VOICEMMODE1_DL"}, {"INTERNAL_BT_SCO_RX_Voice Mixer", "VoiceMMode2", "VOICEMMODE2_DL"}, + {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"}, + {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"}, {"INT_BT_SCO_RX", NULL, "INTERNAL_BT_SCO_RX_Voice Mixer"}, {"AFE_PCM_RX_Voice Mixer", "CSVoice", "CS-VOICE_DL1"}, @@ -12408,6 +12565,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"LSM1 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, {"LSM1 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"LSM1 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM1 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"LSM1 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"LSM1_UL_HL", NULL, "LSM1 Mixer"}, {"LSM2 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, @@ -12417,6 +12576,9 @@ static const struct snd_soc_dapm_route intercon[] = { {"LSM2 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, {"LSM2 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"LSM2 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM2 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"LSM2 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, + {"LSM2_UL_HL", NULL, "LSM2 Mixer"}, @@ -12427,6 +12589,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"LSM3 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, {"LSM3 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"LSM3 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM3 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"LSM3 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"LSM3_UL_HL", NULL, "LSM3 Mixer"}, @@ -12437,6 +12601,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"LSM4 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, {"LSM4 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"LSM4 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM4 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"LSM4 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"LSM4_UL_HL", NULL, "LSM4 Mixer"}, {"LSM5 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, @@ -12446,6 +12612,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"LSM5 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, {"LSM5 Mixer", "TERT_MI2S_TX", "TERT_MI2S_TX"}, {"LSM5 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM5 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"LSM5 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"LSM5_UL_HL", NULL, "LSM5 Mixer"}, {"LSM6 Mixer", "SLIMBUS_0_TX", "SLIMBUS_0_TX"}, @@ -12454,6 +12622,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"LSM6 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, {"LSM6 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, {"LSM6 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM6 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"LSM6 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"LSM6_UL_HL", NULL, "LSM6 Mixer"}, @@ -12463,6 +12633,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"LSM7 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, {"LSM7 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, {"LSM7 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM7 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"LSM7 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"LSM7_UL_HL", NULL, "LSM7 Mixer"}, @@ -12472,6 +12644,8 @@ static const struct snd_soc_dapm_route intercon[] = { {"LSM8 Mixer", "SLIMBUS_4_TX", "SLIMBUS_4_TX"}, {"LSM8 Mixer", "SLIMBUS_5_TX", "SLIMBUS_5_TX"}, {"LSM8 Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, + {"LSM8 Mixer", "PRI_TDM_TX_2", "PRI_TDM_TX_2"}, + {"LSM8 Mixer", "PRI_TDM_TX_3", "PRI_TDM_TX_3"}, {"LSM8_UL_HL", NULL, "LSM8 Mixer"}, @@ -12485,6 +12659,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"QCHAT_Tx Mixer", "MI2S_TX_QCHAT", "MI2S_TX"}, {"QCHAT_Tx Mixer", "PRI_MI2S_TX_QCHAT", "PRI_MI2S_TX"}, {"QCHAT_Tx Mixer", "TERT_MI2S_TX_QCHAT", "TERT_MI2S_TX"}, + {"QCHAT_Tx Mixer", "PRI_TDM_TX_3_QCHAT", "PRI_TDM_TX_3"}, {"QCHAT_UL", NULL, "QCHAT_Tx Mixer"}, {"INT_FM_RX", NULL, "INTFM_DL_HL"}, @@ -12923,8 +13098,6 @@ static const struct snd_soc_dapm_route intercon[] = { {"SLIMBUS_1_RX Mixer", "Voice2 Stub", "VOICE2_STUB_DL"}, {"SLIMBUS_1_RX Mixer", "VoLTE Stub", "VOLTE_STUB_DL"}, {"SLIMBUS_1_RX", NULL, "SLIMBUS_1_RX Mixer"}, - {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"}, - {"INTERNAL_BT_SCO_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"}, {"AFE_PCM_RX_Voice Mixer", "Voice Stub", "VOICE_STUB_DL"}, {"AFE_PCM_RX_Voice Mixer", "Voice2 Stub", "VOICE2_STUB_DL"}, {"AFE_PCM_RX_Voice Mixer", "VoLTE Stub", "VOLTE_STUB_DL"}, @@ -12985,6 +13158,7 @@ static const struct snd_soc_dapm_route intercon[] = { {"SEC_MI2S_RX Port Mixer", "QUAT_MI2S_TX", "QUAT_MI2S_TX"}, {"SEC_MI2S_RX Port Mixer", "SLIM_0_TX", "SLIMBUS_0_TX"}, {"SEC_MI2S_RX Port Mixer", "AUX_PCM_UL_TX", "AUX_PCM_TX"}, + {"SEC_MI2S_RX Port Mixer", "INTERNAL_FM_TX", "INT_FM_TX"}, {"SEC_MI2S_RX", NULL, "SEC_MI2S_RX Port Mixer"}, {"TERT_MI2S_RX Port Mixer", "PRI_MI2S_TX", "PRI_MI2S_TX"}, diff --git a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h index a47377ab38d3..65cdf43c0f71 100644 --- a/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h +++ b/sound/soc/msm/qdsp6v2/msm-pcm-routing-v2.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -414,4 +414,8 @@ void msm_pcm_routing_reg_stream_app_type_cfg(int fedai_id, int app_type, int acdb_dev_id, int sample_rate, int session_type); int msm_pcm_routing_get_stream_app_type_cfg(int fedai_id, int session_type, int *app_type, int *acdb_dev_id, int *sample_rate); +int msm_pcm_routing_send_chmix_cfg(int fe_id, int ip_channel_cnt, + int op_channel_cnt, int *ch_wght_coeff, + int session_type, bool use_default_chmap, + char *channel_map); #endif /*_MSM_PCM_H*/ diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c index bb995d12f277..4bbd4057299c 100644 --- a/sound/soc/msm/qdsp6v2/q6adm.c +++ b/sound/soc/msm/qdsp6v2/q6adm.c @@ -780,18 +780,21 @@ static int adm_populate_channel_weight(u16 *ptr, * session_type - Passed value, session_type for RX or TX * ch_mixer - Passed value, ch_mixer for which channel mixer config is needed * channel_index - Passed value, channel_index for which channel is needed + * use_default_chmap - true if default channel map to be used + * ch_map - input/output channel map for playback/capture session respectively */ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, int session_type, struct msm_pcm_channel_mixer *ch_mixer, - int channel_index) + int channel_index, bool use_default_chmap, + char *ch_map) { struct adm_cmd_set_pspd_mtmx_strtr_params_v5 *adm_params = NULL; struct adm_param_data_v5 data_v5; int ret = 0, port_idx, sz = 0, param_size = 0; u16 *adm_pspd_params; u16 *ptr; - int index = 0; + int index = 0, i; pr_debug("%s: port_id = %d\n", __func__, port_id); port_id = afe_convert_virtual_to_portid(port_id); @@ -858,84 +861,93 @@ int adm_programable_channel_mixer(int port_id, int copp_idx, int session_id, adm_pspd_params[3] = ch_mixer->input_channels[channel_index]; index = 4; - if (ch_mixer->output_channel == 1) { - adm_pspd_params[index] = PCM_CHANNEL_FC; - } else if (ch_mixer->output_channel == 2) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - } else if (ch_mixer->output_channel == 3) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_FC; - } else if (ch_mixer->output_channel == 4) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LS; - adm_pspd_params[index + 3] = PCM_CHANNEL_RS; - } else if (ch_mixer->output_channel == 5) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_FC; - adm_pspd_params[index + 3] = PCM_CHANNEL_LS; - adm_pspd_params[index + 4] = PCM_CHANNEL_RS; - } else if (ch_mixer->output_channel == 6) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; - adm_pspd_params[index + 3] = PCM_CHANNEL_FC; - adm_pspd_params[index + 4] = PCM_CHANNEL_LS; - adm_pspd_params[index + 5] = PCM_CHANNEL_RS; - } else if (ch_mixer->output_channel == 8) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; - adm_pspd_params[index + 3] = PCM_CHANNEL_FC; - adm_pspd_params[index + 4] = PCM_CHANNEL_LS; - adm_pspd_params[index + 5] = PCM_CHANNEL_RS; - adm_pspd_params[index + 6] = PCM_CHANNEL_LB; - adm_pspd_params[index + 7] = PCM_CHANNEL_RB; - } - - index = index + ch_mixer->output_channel; - if (ch_mixer->input_channels[channel_index] == 1) { - adm_pspd_params[index] = PCM_CHANNEL_FC; - } else if (ch_mixer->input_channels[channel_index] == 2) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - } else if (ch_mixer->input_channels[channel_index] == 3) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_FC; - } else if (ch_mixer->input_channels[channel_index] == 4) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LS; - adm_pspd_params[index + 3] = PCM_CHANNEL_RS; - } else if (ch_mixer->input_channels[channel_index] == 5) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_FC; - adm_pspd_params[index + 3] = PCM_CHANNEL_LS; - adm_pspd_params[index + 4] = PCM_CHANNEL_RS; - } else if (ch_mixer->input_channels[channel_index] == 6) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; - adm_pspd_params[index + 3] = PCM_CHANNEL_FC; - adm_pspd_params[index + 4] = PCM_CHANNEL_LS; - adm_pspd_params[index + 5] = PCM_CHANNEL_RS; - } else if (ch_mixer->input_channels[channel_index] == 8) { - adm_pspd_params[index] = PCM_CHANNEL_FL; - adm_pspd_params[index + 1] = PCM_CHANNEL_FR; - adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; - adm_pspd_params[index + 3] = PCM_CHANNEL_FC; - adm_pspd_params[index + 4] = PCM_CHANNEL_LS; - adm_pspd_params[index + 5] = PCM_CHANNEL_RS; - adm_pspd_params[index + 6] = PCM_CHANNEL_LB; - adm_pspd_params[index + 7] = PCM_CHANNEL_RB; - } - - index = index + ch_mixer->input_channels[channel_index]; + if ((session_type == SESSION_TYPE_TX) && !use_default_chmap && ch_map) { + for (i = 0; i < ch_mixer->output_channel; i++) + adm_pspd_params[index++] = ch_map[i]; + } else { + if (ch_mixer->output_channel == 1) { + adm_pspd_params[index] = PCM_CHANNEL_FC; + } else if (ch_mixer->output_channel == 2) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + } else if (ch_mixer->output_channel == 3) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_FC; + } else if (ch_mixer->output_channel == 4) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_LS; + adm_pspd_params[index + 3] = PCM_CHANNEL_RS; + } else if (ch_mixer->output_channel == 5) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_FC; + adm_pspd_params[index + 3] = PCM_CHANNEL_LS; + adm_pspd_params[index + 4] = PCM_CHANNEL_RS; + } else if (ch_mixer->output_channel == 6) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; + adm_pspd_params[index + 3] = PCM_CHANNEL_FC; + adm_pspd_params[index + 4] = PCM_CHANNEL_LS; + adm_pspd_params[index + 5] = PCM_CHANNEL_RS; + } else if (ch_mixer->output_channel == 8) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; + adm_pspd_params[index + 3] = PCM_CHANNEL_FC; + adm_pspd_params[index + 4] = PCM_CHANNEL_LS; + adm_pspd_params[index + 5] = PCM_CHANNEL_RS; + adm_pspd_params[index + 6] = PCM_CHANNEL_LB; + adm_pspd_params[index + 7] = PCM_CHANNEL_RB; + } + index = index + ch_mixer->output_channel; + } + + if ((session_type == SESSION_TYPE_RX) && !use_default_chmap && ch_map) { + for (i = 0; i < ch_mixer->input_channels[channel_index]; i++) + adm_pspd_params[index++] = ch_map[i]; + } else { + if (ch_mixer->input_channels[channel_index] == 1) { + adm_pspd_params[index] = PCM_CHANNEL_FC; + } else if (ch_mixer->input_channels[channel_index] == 2) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + } else if (ch_mixer->input_channels[channel_index] == 3) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_FC; + } else if (ch_mixer->input_channels[channel_index] == 4) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_LS; + adm_pspd_params[index + 3] = PCM_CHANNEL_RS; + } else if (ch_mixer->input_channels[channel_index] == 5) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_FC; + adm_pspd_params[index + 3] = PCM_CHANNEL_LS; + adm_pspd_params[index + 4] = PCM_CHANNEL_RS; + } else if (ch_mixer->input_channels[channel_index] == 6) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; + adm_pspd_params[index + 3] = PCM_CHANNEL_FC; + adm_pspd_params[index + 4] = PCM_CHANNEL_LS; + adm_pspd_params[index + 5] = PCM_CHANNEL_RS; + } else if (ch_mixer->input_channels[channel_index] == 8) { + adm_pspd_params[index] = PCM_CHANNEL_FL; + adm_pspd_params[index + 1] = PCM_CHANNEL_FR; + adm_pspd_params[index + 2] = PCM_CHANNEL_LFE; + adm_pspd_params[index + 3] = PCM_CHANNEL_FC; + adm_pspd_params[index + 4] = PCM_CHANNEL_LS; + adm_pspd_params[index + 5] = PCM_CHANNEL_RS; + adm_pspd_params[index + 6] = PCM_CHANNEL_LB; + adm_pspd_params[index + 7] = PCM_CHANNEL_RB; + } + index = index + ch_mixer->input_channels[channel_index]; + } ret = adm_populate_channel_weight(&adm_pspd_params[index], ch_mixer, channel_index); if (ret) { diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c index b668c21afae5..efca7bc3ea42 100644 --- a/sound/soc/msm/qdsp6v2/q6asm.c +++ b/sound/soc/msm/qdsp6v2/q6asm.c @@ -135,6 +135,24 @@ static int out_cold_index; static char *out_buffer; static char *in_buffer; +static inline uint32_t q6asm_get_pcm_format_id(uint32_t media_format_block_ver) +{ + uint32_t pcm_format_id; + + switch (media_format_block_ver) { + case PCM_MEDIA_FORMAT_V4: + pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V4; + break; + case PCM_MEDIA_FORMAT_V3: + pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3; + break; + case PCM_MEDIA_FORMAT_V2: + default: + pcm_format_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; + break; + } + return pcm_format_id; +} static int audio_output_latency_dbgfs_open(struct inode *inode, struct file *file) @@ -2343,7 +2361,8 @@ static void q6asm_add_mmaphdr(struct audio_client *ac, struct apr_hdr *hdr, static int __q6asm_open_read(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, - bool use_v3_format, bool ts_mode) + uint32_t pcm_format_block_ver, + bool ts_mode) { int rc = 0x00; struct asm_stream_cmd_open_read_v3 open; @@ -2383,12 +2402,9 @@ static int __q6asm_open_read(struct audio_client *ac, switch (format) { case FORMAT_LINEAR_PCM: open.mode_flags |= 0x00; + open.enc_cfg_id = q6asm_get_pcm_format_id(pcm_format_block_ver); if (ts_mode) open.mode_flags |= ABSOLUTE_TIMESTAMP_ENABLE; - if (use_v3_format) - open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3; - else - open.enc_cfg_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; break; case FORMAT_MPEG4_AAC: open.mode_flags |= BUFFER_META_ENABLE; @@ -2459,14 +2475,16 @@ int q6asm_open_read(struct audio_client *ac, uint32_t format) { return __q6asm_open_read(ac, format, 16, - false /*use_v3_format*/, false/*ts_mode*/); + PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/, + false/*ts_mode*/); } int q6asm_open_read_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) { return __q6asm_open_read(ac, format, bits_per_sample, - false /*use_v3_format*/, false/*ts_mode*/); + PCM_MEDIA_FORMAT_V2 /*media fmt block ver*/, + false/*ts_mode*/); } /* @@ -2480,7 +2498,8 @@ int q6asm_open_read_v3(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) { return __q6asm_open_read(ac, format, bits_per_sample, - true /*use_v3_format*/, false/*ts_mode*/); + PCM_MEDIA_FORMAT_V3/*media fmt block ver*/, + false/*ts_mode*/); } EXPORT_SYMBOL(q6asm_open_read_v3); @@ -2495,7 +2514,8 @@ int q6asm_open_read_v4(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample) { return __q6asm_open_read(ac, format, bits_per_sample, - true /*use_v3_format*/, true/*ts_mode*/); + PCM_MEDIA_FORMAT_V4 /*media fmt block ver*/, + true/*ts_mode*/); } EXPORT_SYMBOL(q6asm_open_read_v4); @@ -2586,7 +2606,8 @@ int q6asm_open_write_compressed(struct audio_client *ac, uint32_t format, static int __q6asm_open_write(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, uint32_t stream_id, - bool is_gapless_mode, bool use_v3_format) + bool is_gapless_mode, + uint32_t pcm_format_block_ver) { int rc = 0x00; struct asm_stream_cmd_open_write_v3 open; @@ -2654,11 +2675,7 @@ static int __q6asm_open_write(struct audio_client *ac, uint32_t format, } switch (format) { case FORMAT_LINEAR_PCM: - if (use_v3_format) - open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V3; - else - open.dec_fmt_id = ASM_MEDIA_FMT_MULTI_CHANNEL_PCM_V2; - + open.dec_fmt_id = q6asm_get_pcm_format_id(pcm_format_block_ver); break; case FORMAT_MPEG4_AAC: open.dec_fmt_id = ASM_MEDIA_FMT_AAC_V2; @@ -2737,7 +2754,7 @@ int q6asm_open_write(struct audio_client *ac, uint32_t format) { return __q6asm_open_write(ac, format, 16, ac->stream_id, false /*gapless*/, - false /*use_v3_format*/); + PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/); } int q6asm_open_write_v2(struct audio_client *ac, uint32_t format, @@ -2745,7 +2762,7 @@ int q6asm_open_write_v2(struct audio_client *ac, uint32_t format, { return __q6asm_open_write(ac, format, bits_per_sample, ac->stream_id, false /*gapless*/, - false /*use_v3_format*/); + PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/); } /* @@ -2760,17 +2777,33 @@ int q6asm_open_write_v3(struct audio_client *ac, uint32_t format, { return __q6asm_open_write(ac, format, bits_per_sample, ac->stream_id, false /*gapless*/, - true /*use_v3_format*/); + PCM_MEDIA_FORMAT_V3 /*pcm_format_block_ver*/); } EXPORT_SYMBOL(q6asm_open_write_v3); +/* + * q6asm_open_write_v4 - Opens audio playback session + * + * @ac: Client session handle + * @format: decoder format + * @bits_per_sample: bit width of playback session + */ +int q6asm_open_write_v4(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample) +{ + return __q6asm_open_write(ac, format, bits_per_sample, + ac->stream_id, false /*gapless*/, + PCM_MEDIA_FORMAT_V4 /*pcm_format_block_ver*/); +} +EXPORT_SYMBOL(q6asm_open_write_v4); + int q6asm_stream_open_write_v2(struct audio_client *ac, uint32_t format, uint16_t bits_per_sample, int32_t stream_id, bool is_gapless_mode) { return __q6asm_open_write(ac, format, bits_per_sample, stream_id, is_gapless_mode, - false /*use_v3_format*/); + PCM_MEDIA_FORMAT_V2 /*pcm_format_block_ver*/); } /* @@ -2788,10 +2821,29 @@ int q6asm_stream_open_write_v3(struct audio_client *ac, uint32_t format, { return __q6asm_open_write(ac, format, bits_per_sample, stream_id, is_gapless_mode, - true /*use_v3_format*/); + PCM_MEDIA_FORMAT_V3 /*pcm_format_block_ver*/); } EXPORT_SYMBOL(q6asm_stream_open_write_v3); +/* + * q6asm_stream_open_write_v4 - Creates audio stream for playback + * + * @ac: Client session handle + * @format: asm playback format + * @bits_per_sample: bit width of requested stream + * @stream_id: stream id of stream to be associated with this session + * @is_gapless_mode: true if gapless mode needs to be enabled + */ +int q6asm_stream_open_write_v4(struct audio_client *ac, uint32_t format, + uint16_t bits_per_sample, int32_t stream_id, + bool is_gapless_mode) +{ + return __q6asm_open_write(ac, format, bits_per_sample, + stream_id, is_gapless_mode, + PCM_MEDIA_FORMAT_V4 /*pcm_format_block_ver*/); +} +EXPORT_SYMBOL(q6asm_stream_open_write_v4); + static int __q6asm_open_read_write(struct audio_client *ac, uint32_t rd_format, uint32_t wr_format, bool is_meta_data_mode, uint32_t bits_per_sample, @@ -3718,6 +3770,108 @@ int q6asm_set_encdec_chan_map(struct audio_client *ac, return rc; } +/* + * q6asm_enc_cfg_blk_pcm_v4 - sends encoder configuration parameters + * + * @ac: Client session handle + * @rate: sample rate + * @channels: number of channels + * @bits_per_sample: bit width of encoder session + * @use_default_chmap: true if default channel map to be used + * @use_back_flavor: to configure back left and right channel + * @channel_map: input channel map + * @sample_word_size: Size in bits of the word that holds a sample of a channel + * @endianness: endianness of the pcm data + * @mode: Mode to provide additional info about the pcm input data + */ +int q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, bool use_default_chmap, + bool use_back_flavor, u8 *channel_map, + uint16_t sample_word_size, uint16_t endianness, + uint16_t mode) +{ + struct asm_multi_channel_pcm_enc_cfg_v4 enc_cfg; + struct asm_enc_cfg_blk_param_v2 enc_fg_blk; + u8 *channel_mapping; + u32 frames_per_buf = 0; + int rc; + + if (!use_default_chmap && (channel_map == NULL)) { + pr_err("%s: No valid chan map and can't use default\n", + __func__); + rc = -EINVAL; + goto fail_cmd; + } + + pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, + ac->session, rate, channels, + bits_per_sample, sample_word_size); + + memset(&enc_cfg, 0, sizeof(enc_cfg)); + q6asm_add_hdr(ac, &enc_cfg.hdr, sizeof(enc_cfg), TRUE); + atomic_set(&ac->cmd_state, -1); + enc_cfg.hdr.opcode = ASM_STREAM_CMD_SET_ENCDEC_PARAM; + enc_cfg.encdec.param_id = ASM_PARAM_ID_ENCDEC_ENC_CFG_BLK_V2; + enc_cfg.encdec.param_size = sizeof(enc_cfg) - sizeof(enc_cfg.hdr) - + sizeof(enc_cfg.encdec); + enc_cfg.encblk.frames_per_buf = frames_per_buf; + enc_cfg.encblk.enc_cfg_blk_size = enc_cfg.encdec.param_size - + sizeof(enc_fg_blk); + enc_cfg.num_channels = channels; + enc_cfg.bits_per_sample = bits_per_sample; + enc_cfg.sample_rate = rate; + enc_cfg.is_signed = 1; + enc_cfg.sample_word_size = sample_word_size; + enc_cfg.endianness = endianness; + enc_cfg.mode = mode; + channel_mapping = enc_cfg.channel_mapping; + + memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL); + + if (use_default_chmap) { + pr_debug("%s: setting default channel map for %d channels", + __func__, channels); + if (q6asm_map_channels(channel_mapping, channels, + use_back_flavor)) { + pr_err("%s: map channels failed %d\n", + __func__, channels); + rc = -EINVAL; + goto fail_cmd; + } + } else { + pr_debug("%s: Using pre-defined channel map", __func__); + memcpy(channel_mapping, channel_map, + PCM_FORMAT_MAX_NUM_CHANNEL); + } + + rc = apr_send_pkt(ac->apr, (uint32_t *) &enc_cfg); + if (rc < 0) { + pr_err("%s: Command open failed %d\n", __func__, rc); + goto fail_cmd; + } + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout opcode[0x%x]\n", + __func__, enc_cfg.hdr.opcode); + rc = -ETIMEDOUT; + goto fail_cmd; + } + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state)); + goto fail_cmd; + } + return 0; +fail_cmd: + return rc; +} +EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_v4); + /* * q6asm_enc_cfg_blk_pcm_v3 - sends encoder configuration parameters * @@ -3894,6 +4048,18 @@ int q6asm_enc_cfg_blk_pcm_v2(struct audio_client *ac, return rc; } +static int __q6asm_enc_cfg_blk_pcm_v4(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + return q6asm_enc_cfg_blk_pcm_v4(ac, rate, channels, + bits_per_sample, true, false, NULL, + sample_word_size, endianness, mode); +} + static int __q6asm_enc_cfg_blk_pcm_v3(struct audio_client *ac, uint32_t rate, uint32_t channels, uint16_t bits_per_sample, @@ -3943,6 +4109,31 @@ int q6asm_enc_cfg_blk_pcm_format_support_v3(struct audio_client *ac, } EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v3); +/* + * q6asm_enc_cfg_blk_pcm_format_support_v4 - sends encoder configuration + * parameters + * + * @ac: Client session handle + * @rate: sample rate + * @channels: number of channels + * @bits_per_sample: bit width of encoder session + * @sample_word_size: Size in bits of the word that holds a sample of a channel + * @endianness: endianness of the pcm data + * @mode: Mode to provide additional info about the pcm input data + */ +int q6asm_enc_cfg_blk_pcm_format_support_v4(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + return __q6asm_enc_cfg_blk_pcm_v4(ac, rate, channels, + bits_per_sample, sample_word_size, + endianness, mode); +} +EXPORT_SYMBOL(q6asm_enc_cfg_blk_pcm_format_support_v4); + int q6asm_enc_cfg_blk_pcm_native(struct audio_client *ac, uint32_t rate, uint32_t channels) { @@ -4585,6 +4776,91 @@ static int __q6asm_media_format_block_pcm_v3(struct audio_client *ac, return rc; } +static int __q6asm_media_format_block_pcm_v4(struct audio_client *ac, + uint32_t rate, uint32_t channels, + uint16_t bits_per_sample, + int stream_id, + bool use_default_chmap, + char *channel_map, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + struct asm_multi_channel_pcm_fmt_blk_param_v4 fmt; + u8 *channel_mapping; + int rc; + + pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, + ac->session, rate, channels, + bits_per_sample, sample_word_size); + + memset(&fmt, 0, sizeof(fmt)); + q6asm_stream_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE, stream_id); + atomic_set(&ac->cmd_state, -1); + /* + * Updated the token field with stream/session for compressed playback + * Platform driver must know the the stream with which the command is + * associated + */ + if (ac->io_mode & COMPRESSED_STREAM_IO) + fmt.hdr.token = ((ac->session << 8) & 0xFFFF00) | + (stream_id & 0xFF); + + pr_debug("%s: token = 0x%x, stream_id %d, session 0x%x\n", + __func__, fmt.hdr.token, stream_id, ac->session); + + fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; + fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) - + sizeof(fmt.fmt_blk); + fmt.param.num_channels = channels; + fmt.param.bits_per_sample = bits_per_sample; + fmt.param.sample_rate = rate; + fmt.param.is_signed = 1; + fmt.param.sample_word_size = sample_word_size; + fmt.param.endianness = endianness; + fmt.param.mode = mode; + channel_mapping = fmt.param.channel_mapping; + + memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL); + + if (use_default_chmap) { + if (q6asm_map_channels(channel_mapping, channels, false)) { + pr_err("%s: map channels failed %d\n", + __func__, channels); + rc = -EINVAL; + goto fail_cmd; + } + } else { + memcpy(channel_mapping, channel_map, + PCM_FORMAT_MAX_NUM_CHANNEL); + } + + rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt); + if (rc < 0) { + pr_err("%s: Comamnd open failed %d\n", __func__, rc); + rc = -EINVAL; + goto fail_cmd; + } + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout. waited for format update\n", __func__); + rc = -ETIMEDOUT; + goto fail_cmd; + } + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state)); + goto fail_cmd; + } + return 0; +fail_cmd: + return rc; +} + int q6asm_media_format_block_pcm(struct audio_client *ac, uint32_t rate, uint32_t channels) { @@ -4652,6 +4928,47 @@ int q6asm_media_format_block_pcm_format_support_v3(struct audio_client *ac, } EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v3); +/* + * q6asm_media_format_block_pcm_format_support_v4- sends pcm decoder + * configuration parameters + * + * @ac: Client session handle + * @rate: sample rate + * @channels: number of channels + * @bits_per_sample: bit width of encoder session + * @stream_id: stream id of stream to be associated with this session + * @use_default_chmap: true if default channel map to be used + * @channel_map: input channel map + * @sample_word_size: Size in bits of the word that holds a sample of a channel + * @endianness: endianness of the pcm data + * @mode: Mode to provide additional info about the pcm input data + */ +int q6asm_media_format_block_pcm_format_support_v4(struct audio_client *ac, + uint32_t rate, + uint32_t channels, + uint16_t bits_per_sample, + int stream_id, + bool use_default_chmap, + char *channel_map, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + if (!use_default_chmap && (channel_map == NULL)) { + pr_err("%s: No valid chan map and can't use default\n", + __func__); + return -EINVAL; + } + return __q6asm_media_format_block_pcm_v4(ac, rate, + channels, bits_per_sample, stream_id, + use_default_chmap, channel_map, + sample_word_size, endianness, + mode); + +} +EXPORT_SYMBOL(q6asm_media_format_block_pcm_format_support_v4); + + static int __q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, uint32_t rate, uint32_t channels, bool use_default_chmap, char *channel_map, @@ -4785,6 +5102,78 @@ static int __q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac, return rc; } +static int __q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac, + uint32_t rate, + uint32_t channels, + bool use_default_chmap, + char *channel_map, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + struct asm_multi_channel_pcm_fmt_blk_param_v4 fmt; + u8 *channel_mapping; + int rc; + + pr_debug("%s: session[%d]rate[%d]ch[%d]bps[%d]wordsize[%d]\n", __func__, + ac->session, rate, channels, + bits_per_sample, sample_word_size); + + memset(&fmt, 0, sizeof(fmt)); + q6asm_add_hdr(ac, &fmt.hdr, sizeof(fmt), TRUE); + atomic_set(&ac->cmd_state, -1); + + fmt.hdr.opcode = ASM_DATA_CMD_MEDIA_FMT_UPDATE_V2; + fmt.fmt_blk.fmt_blk_size = sizeof(fmt) - sizeof(fmt.hdr) - + sizeof(fmt.fmt_blk); + fmt.param.num_channels = channels; + fmt.param.bits_per_sample = bits_per_sample; + fmt.param.sample_rate = rate; + fmt.param.is_signed = 1; + fmt.param.sample_word_size = sample_word_size; + fmt.param.endianness = endianness; + fmt.param.mode = mode; + channel_mapping = fmt.param.channel_mapping; + + memset(channel_mapping, 0, PCM_FORMAT_MAX_NUM_CHANNEL); + + if (use_default_chmap) { + if (q6asm_map_channels(channel_mapping, channels, false)) { + pr_err("%s: map channels failed %d\n", + __func__, channels); + rc = -EINVAL; + goto fail_cmd; + } + } else { + memcpy(channel_mapping, channel_map, + PCM_FORMAT_MAX_NUM_CHANNEL); + } + + rc = apr_send_pkt(ac->apr, (uint32_t *) &fmt); + if (rc < 0) { + pr_err("%s: Comamnd open failed %d\n", __func__, rc); + goto fail_cmd; + } + rc = wait_event_timeout(ac->cmd_wait, + (atomic_read(&ac->cmd_state) >= 0), 5*HZ); + if (!rc) { + pr_err("%s: timeout. waited for format update\n", __func__); + rc = -ETIMEDOUT; + goto fail_cmd; + } + if (atomic_read(&ac->cmd_state) > 0) { + pr_err("%s: DSP returned error[%s]\n", + __func__, adsp_err_get_err_str( + atomic_read(&ac->cmd_state))); + rc = adsp_err_get_lnx_err_code( + atomic_read(&ac->cmd_state)); + goto fail_cmd; + } + return 0; +fail_cmd: + return rc; +} int q6asm_media_format_block_multi_ch_pcm(struct audio_client *ac, uint32_t rate, uint32_t channels, @@ -4832,6 +5221,39 @@ int q6asm_media_format_block_multi_ch_pcm_v3(struct audio_client *ac, } EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v3); +/* + * q6asm_media_format_block_multi_ch_pcm_v4 - sends pcm decoder configuration + * parameters + * + * @ac: Client session handle + * @rate: sample rate + * @channels: number of channels + * @bits_per_sample: bit width of encoder session + * @use_default_chmap: true if default channel map to be used + * @channel_map: input channel map + * @sample_word_size: Size in bits of the word that holds a sample of a channel + * @endianness: endianness of the pcm data + * @mode: Mode to provide additional info about the pcm input data + */ +int q6asm_media_format_block_multi_ch_pcm_v4(struct audio_client *ac, + uint32_t rate, uint32_t channels, + bool use_default_chmap, + char *channel_map, + uint16_t bits_per_sample, + uint16_t sample_word_size, + uint16_t endianness, + uint16_t mode) +{ + return __q6asm_media_format_block_multi_ch_pcm_v4(ac, rate, channels, + use_default_chmap, + channel_map, + bits_per_sample, + sample_word_size, + endianness, + mode); +} +EXPORT_SYMBOL(q6asm_media_format_block_multi_ch_pcm_v4); + static int __q6asm_media_format_block_multi_aac(struct audio_client *ac, struct asm_aac_cfg *cfg, int stream_id) { diff --git a/sound/soc/msm/qdsp6v2/q6core.c b/sound/soc/msm/qdsp6v2/q6core.c index 3fbf251c310c..71a65c63ca5f 100644 --- a/sound/soc/msm/qdsp6v2/q6core.c +++ b/sound/soc/msm/qdsp6v2/q6core.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -57,7 +57,8 @@ struct q6core_str { u32 bus_bw_resp_received; enum cmd_flags { FLAG_NONE, - FLAG_CMDRSP_LICENSE_RESULT + FLAG_CMDRSP_LICENSE_RESULT, + FLAG_AVCS_GET_VERSIONS_RESULT, } cmd_resp_received_flag; u32 avcs_fwk_ver_resp_received; struct mutex cmd_lock; @@ -71,6 +72,7 @@ struct q6core_str { uint32_t mem_map_cal_handle; int32_t adsp_status; struct q6core_avcs_ver_info q6core_avcs_ver_info; + u32 q6_core_avs_version; }; static struct q6core_str q6core_lcl; @@ -180,7 +182,33 @@ static int32_t aprv2_core_fn_q(struct apr_client_data *data, void *priv) q6core_lcl.bus_bw_resp_received = 1; wake_up(&q6core_lcl.bus_bw_req_wait); break; - case AVCS_CMDRSP_GET_LICENSE_VALIDATION_RESULT: + case AVCS_GET_VERSIONS_RSP: + payload1 = data->payload; + pr_debug("%s: Received ADSP version response[3]0x%x\n", + __func__, payload1[3]); + q6core_lcl.cmd_resp_received_flag = + FLAG_AVCS_GET_VERSIONS_RESULT; + if (AVCS_CMDRSP_Q6_ID_2_6 == payload1[3]) { + q6core_lcl.q6_core_avs_version = Q6_SUBSYS_AVS2_6; + pr_debug("%s: Received ADSP version as 2.6\n", + __func__); + } else if (AVCS_CMDRSP_Q6_ID_2_7 == payload1[3]) { + q6core_lcl.q6_core_avs_version = Q6_SUBSYS_AVS2_7; + pr_debug("%s: Received ADSP version as 2.7\n", + __func__); + } else if (AVCS_CMDRSP_Q6_ID_2_8 == payload1[3]) { + q6core_lcl.q6_core_avs_version = Q6_SUBSYS_AVS2_8; + pr_info("%s: Received ADSP version as 2.8\n", + __func__); + } else { + pr_err("%s: ADSP version is neither 2.6 nor 2.7\n", + __func__); + q6core_lcl.q6_core_avs_version = Q6_SUBSYS_INVALID; + } + wake_up(&q6core_lcl.cmd_req_wait); + break; + + case AVCS_CMDRSP_GET_LICENSE_VALIDATION_RESULT: payload1 = data->payload; pr_debug("%s: cmd = LICENSE_VALIDATION_RESULT, result = 0x%x\n", __func__, payload1[0]); @@ -421,6 +449,65 @@ int32_t core_set_license(uint32_t key, uint32_t module_id) return rc; } +int core_get_adsp_ver(void) +{ + struct avcs_cmd_get_version_result get_aver_cmd; + int ret = 0; + + mutex_lock(&(q6core_lcl.cmd_lock)); + ocm_core_open(); + if (q6core_lcl.core_handle_q == NULL) { + pr_err("%s: apr registration for CORE failed\n", __func__); + ret = -ENODEV; + goto fail_cmd; + } + + get_aver_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD, + APR_HDR_LEN(APR_HDR_SIZE), APR_PKT_VER); + get_aver_cmd.hdr.pkt_size = sizeof(get_aver_cmd); + get_aver_cmd.hdr.src_port = 0; + get_aver_cmd.hdr.dest_port = 0; + get_aver_cmd.hdr.token = 0; + get_aver_cmd.hdr.opcode = AVCS_GET_VERSIONS; + + ret = apr_send_pkt(q6core_lcl.core_handle_q, + (uint32_t *) &get_aver_cmd); + if (ret < 0) { + pr_err("%s: Core get DSP version request failed, err %d\n", + __func__, ret); + ret = -EREMOTE; + goto fail_cmd; + } + + q6core_lcl.cmd_resp_received_flag &= ~(FLAG_AVCS_GET_VERSIONS_RESULT); + mutex_unlock(&(q6core_lcl.cmd_lock)); + ret = wait_event_timeout(q6core_lcl.cmd_req_wait, + (q6core_lcl.cmd_resp_received_flag == + FLAG_AVCS_GET_VERSIONS_RESULT), + msecs_to_jiffies(TIMEOUT_MS)); + mutex_lock(&(q6core_lcl.cmd_lock)); + if (!ret) { + pr_err("%s: wait_event timeout for AVCS_GET_VERSIONS_RESULT\n", + __func__); + ret = -ETIMEDOUT; + goto fail_cmd; + } + q6core_lcl.cmd_resp_received_flag &= ~(FLAG_AVCS_GET_VERSIONS_RESULT); + +fail_cmd: + if (ret < 0) + q6core_lcl.q6_core_avs_version = Q6_SUBSYS_INVALID; + mutex_unlock(&(q6core_lcl.cmd_lock)); + return ret; +} + +enum q6_subsys_image q6core_get_avs_version(void) +{ + if (q6core_lcl.q6_core_avs_version == 0) + core_get_adsp_ver(); + return q6core_lcl.q6_core_avs_version; +} + int32_t core_get_license_status(uint32_t module_id) { struct avcs_cmd_get_license_validation_result get_lvr_cmd; diff --git a/sound/soc/msm/qdsp6v2/rtac.c b/sound/soc/msm/qdsp6v2/rtac.c index 9b5e72f94d1b..11c46335993e 100644 --- a/sound/soc/msm/qdsp6v2/rtac.c +++ b/sound/soc/msm/qdsp6v2/rtac.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved. +/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -127,6 +127,11 @@ struct mutex rtac_voice_mutex; struct mutex rtac_voice_apr_mutex; struct mutex rtac_afe_apr_mutex; +static struct mutex rtac_asm_cal_mutex; +static struct mutex rtac_adm_cal_mutex; +static struct mutex rtac_afe_cal_mutex; +static struct mutex rtac_voice_cal_mutex; + int rtac_clear_mapping(uint32_t cal_type) { int result = 0; @@ -1693,42 +1698,62 @@ static long rtac_ioctl_shared(struct file *f, } case AUDIO_GET_RTAC_ADM_CAL: + mutex_lock(&rtac_adm_cal_mutex); result = send_adm_apr((void *)arg, ADM_CMD_GET_PP_PARAMS_V5); + mutex_unlock(&rtac_adm_cal_mutex); break; case AUDIO_SET_RTAC_ADM_CAL: + mutex_lock(&rtac_adm_cal_mutex); result = send_adm_apr((void *)arg, ADM_CMD_SET_PP_PARAMS_V5); + mutex_unlock(&rtac_adm_cal_mutex); break; case AUDIO_GET_RTAC_ASM_CAL: + mutex_lock(&rtac_asm_cal_mutex); result = send_rtac_asm_apr((void *)arg, ASM_STREAM_CMD_GET_PP_PARAMS_V2); + mutex_unlock(&rtac_asm_cal_mutex); break; case AUDIO_SET_RTAC_ASM_CAL: + mutex_lock(&rtac_asm_cal_mutex); result = send_rtac_asm_apr((void *)arg, ASM_STREAM_CMD_SET_PP_PARAMS_V2); + mutex_unlock(&rtac_asm_cal_mutex); break; case AUDIO_GET_RTAC_CVS_CAL: + mutex_lock(&rtac_voice_cal_mutex); result = send_voice_apr(RTAC_CVS, (void *)arg, VOICE_CMD_GET_PARAM); + mutex_unlock(&rtac_voice_cal_mutex); break; case AUDIO_SET_RTAC_CVS_CAL: + mutex_lock(&rtac_voice_cal_mutex); result = send_voice_apr(RTAC_CVS, (void *)arg, VOICE_CMD_SET_PARAM); + mutex_unlock(&rtac_voice_cal_mutex); break; case AUDIO_GET_RTAC_CVP_CAL: + mutex_lock(&rtac_voice_cal_mutex); result = send_voice_apr(RTAC_CVP, (void *)arg, VOICE_CMD_GET_PARAM); + mutex_unlock(&rtac_voice_cal_mutex); break; case AUDIO_SET_RTAC_CVP_CAL: + mutex_lock(&rtac_voice_cal_mutex); result = send_voice_apr(RTAC_CVP, (void *)arg, VOICE_CMD_SET_PARAM); + mutex_unlock(&rtac_voice_cal_mutex); break; case AUDIO_GET_RTAC_AFE_CAL: + mutex_lock(&rtac_afe_cal_mutex); result = send_rtac_afe_apr((void *)arg, AFE_PORT_CMD_GET_PARAM_V2); + mutex_unlock(&rtac_afe_cal_mutex); break; case AUDIO_SET_RTAC_AFE_CAL: + mutex_lock(&rtac_afe_cal_mutex); result = send_rtac_afe_apr((void *)arg, AFE_PORT_CMD_SET_PARAM_V2); + mutex_unlock(&rtac_afe_cal_mutex); break; default: pr_err("%s: Invalid IOCTL, command = %d!\n", @@ -1860,6 +1885,7 @@ static int __init rtac_init(void) init_waitqueue_head(&rtac_adm_apr_data.cmd_wait); mutex_init(&rtac_adm_mutex); mutex_init(&rtac_adm_apr_mutex); + mutex_init(&rtac_adm_cal_mutex); rtac_adm_buffer = kzalloc( rtac_cal[ADM_RTAC_CAL].map_data.map_size, GFP_KERNEL); @@ -1876,6 +1902,7 @@ static int __init rtac_init(void) init_waitqueue_head(&rtac_asm_apr_data[i].cmd_wait); } mutex_init(&rtac_asm_apr_mutex); + mutex_init(&rtac_asm_cal_mutex); rtac_asm_buffer = kzalloc( rtac_cal[ASM_RTAC_CAL].map_data.map_size, GFP_KERNEL); @@ -1891,6 +1918,7 @@ static int __init rtac_init(void) atomic_set(&rtac_afe_apr_data.cmd_state, 0); init_waitqueue_head(&rtac_afe_apr_data.cmd_wait); mutex_init(&rtac_afe_apr_mutex); + mutex_init(&rtac_afe_cal_mutex); rtac_afe_buffer = kzalloc( rtac_cal[AFE_RTAC_CAL].map_data.map_size, GFP_KERNEL); @@ -1911,6 +1939,7 @@ static int __init rtac_init(void) } mutex_init(&rtac_voice_mutex); mutex_init(&rtac_voice_apr_mutex); + mutex_init(&rtac_voice_cal_mutex); rtac_voice_buffer = kzalloc( rtac_cal[VOICE_RTAC_CAL].map_data.map_size, GFP_KERNEL); diff --git a/sound/soc/sirf/sirf-usp.c b/sound/soc/sirf/sirf-usp.c index 186dc7f33a55..cdb7416a91ff 100644 --- a/sound/soc/sirf/sirf-usp.c +++ b/sound/soc/sirf/sirf-usp.c @@ -367,10 +367,9 @@ static int sirf_usp_pcm_probe(struct platform_device *pdev) platform_set_drvdata(pdev, usp); mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap(&pdev->dev, mem_res->start, - resource_size(mem_res)); - if (base == NULL) - return -ENOMEM; + base = devm_ioremap_resource(&pdev->dev, mem_res); + if (IS_ERR(base)) + return PTR_ERR(base); usp->regmap = devm_regmap_init_mmio(&pdev->dev, base, &sirf_usp_regmap_config); if (IS_ERR(usp->regmap)) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e871ffb069ce..c09ee574e8a1 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1715,8 +1715,10 @@ int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) continue; if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)) - continue; + (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)) { + soc_pcm_hw_free(be_substream); + be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; + } dev_dbg(be->dev, "ASoC: close BE %s\n", dpcm->fe->dai_link->name); diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index e8822542b257..52af32177bf4 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c @@ -1263,7 +1263,7 @@ static void retire_capture_urb(struct snd_usb_substream *subs, if (bytes % (runtime->sample_bits >> 3) != 0) { int oldbytes = bytes; bytes = frames * stride; - dev_warn(&subs->dev->dev, + dev_warn_ratelimited(&subs->dev->dev, "Corrected urb data len. %d->%d\n", oldbytes, bytes); } diff --git a/tools/perf/arch/powerpc/util/skip-callchain-idx.c b/tools/perf/arch/powerpc/util/skip-callchain-idx.c index d73ef8bb08c7..8e24f39f9158 100644 --- a/tools/perf/arch/powerpc/util/skip-callchain-idx.c +++ b/tools/perf/arch/powerpc/util/skip-callchain-idx.c @@ -230,7 +230,7 @@ int arch_skip_callchain_idx(struct machine *machine, struct thread *thread, u64 ip; u64 skip_slot = -1; - if (chain->nr < 3) + if (!chain || chain->nr < 3) return skip_slot; ip = chain->ips[2]; diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c index 5b1b807265a1..f771e09eef33 100644 --- a/tools/power/x86/turbostat/turbostat.c +++ b/tools/power/x86/turbostat/turbostat.c @@ -605,9 +605,7 @@ void format_all_counters(struct thread_data *t, struct core_data *c, struct pkg_ if (!printed || !summary_only) print_header(); - if (topo.num_cpus > 1) - format_counters(&average.threads, &average.cores, - &average.packages); + format_counters(&average.threads, &average.cores, &average.packages); printed = 1; @@ -2011,7 +2009,9 @@ void check_cpuid() family = (fms >> 8) & 0xf; model = (fms >> 4) & 0xf; stepping = fms & 0xf; - if (family == 6 || family == 0xf) + if (family == 0xf) + family += (fms >> 20) & 0xff; + if (family >= 6) model += ((fms >> 16) & 0xf) << 4; if (verbose) diff --git a/tools/testing/selftests/ftrace/test.d/00basic/snapshot.tc b/tools/testing/selftests/ftrace/test.d/00basic/snapshot.tc new file mode 100644 index 000000000000..3b1f45e13a2e --- /dev/null +++ b/tools/testing/selftests/ftrace/test.d/00basic/snapshot.tc @@ -0,0 +1,28 @@ +#!/bin/sh +# description: Snapshot and tracing setting +# flags: instance + +[ ! -f snapshot ] && exit_unsupported + +echo "Set tracing off" +echo 0 > tracing_on + +echo "Allocate and take a snapshot" +echo 1 > snapshot + +# Since trace buffer is empty, snapshot is also empty, but allocated +grep -q "Snapshot is allocated" snapshot + +echo "Ensure keep tracing off" +test `cat tracing_on` -eq 0 + +echo "Set tracing on" +echo 1 > tracing_on + +echo "Take a snapshot again" +echo 1 > snapshot + +echo "Ensure keep tracing on" +test `cat tracing_on` -eq 1 + +exit 0 diff --git a/tools/testing/selftests/sync/config b/tools/testing/selftests/sync/config new file mode 100644 index 000000000000..1ab7e8130db2 --- /dev/null +++ b/tools/testing/selftests/sync/config @@ -0,0 +1,4 @@ +CONFIG_STAGING=y +CONFIG_ANDROID=y +CONFIG_SYNC=y +CONFIG_SW_SYNC=y diff --git a/tools/usb/ffs-test.c b/tools/usb/ffs-test.c index 88d5e71be044..47dfa0b0fcd7 100644 --- a/tools/usb/ffs-test.c +++ b/tools/usb/ffs-test.c @@ -44,12 +44,25 @@ /******************** Little Endian Handling ********************************/ -#define cpu_to_le16(x) htole16(x) -#define cpu_to_le32(x) htole32(x) +/* + * cpu_to_le16/32 are used when initializing structures, a context where a + * function call is not allowed. To solve this, we code cpu_to_le16/32 in a way + * that allows them to be used when initializing structures. + */ + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define cpu_to_le16(x) (x) +#define cpu_to_le32(x) (x) +#else +#define cpu_to_le16(x) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)) +#define cpu_to_le32(x) \ + ((((x) & 0xff000000u) >> 24) | (((x) & 0x00ff0000u) >> 8) | \ + (((x) & 0x0000ff00u) << 8) | (((x) & 0x000000ffu) << 24)) +#endif + #define le32_to_cpu(x) le32toh(x) #define le16_to_cpu(x) le16toh(x) - /******************** Messages and Errors ***********************************/ static const char argv0[] = "ffs-test"; diff --git a/tools/usb/usbip/src/usbip_detach.c b/tools/usb/usbip/src/usbip_detach.c index 05c6d15856eb..b4356ed875e5 100644 --- a/tools/usb/usbip/src/usbip_detach.c +++ b/tools/usb/usbip/src/usbip_detach.c @@ -43,7 +43,7 @@ void usbip_detach_usage(void) static int detach_port(char *port) { - int ret; + int ret = 0; uint8_t portnum; char path[PATH_MAX+1]; @@ -71,9 +71,12 @@ static int detach_port(char *port) } ret = usbip_vhci_detach_device(portnum); - if (ret < 0) - return -1; + if (ret < 0) { + ret = -1; + goto call_driver_close; + } +call_driver_close: usbip_vhci_driver_close(); return ret;